1 /*
   2  *
   3  * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  *   - Redistributions of source code must retain the above copyright
  10  *     notice, this list of conditions and the following disclaimer.
  11  *
  12  *   - Redistributions in binary form must reproduce the above copyright
  13  *     notice, this list of conditions and the following disclaimer in the
  14  *     documentation and/or other materials provided with the distribution.
  15  *
  16  *   - Neither the name of Oracle nor the names of its
  17  *     contributors may be used to endorse or promote products derived
  18  *     from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 package java2d.demos.Transforms;
  33 
  34 
  35 import static java.awt.Color.BLACK;
  36 import static java.awt.Color.ORANGE;
  37 import static java.awt.Color.WHITE;
  38 import java.awt.Component;
  39 import java.awt.Dimension;
  40 import java.awt.Font;
  41 import java.awt.Graphics2D;
  42 import java.awt.Image;
  43 import java.awt.event.ActionEvent;
  44 import java.awt.event.ActionListener;
  45 import java.awt.font.FontRenderContext;
  46 import java.awt.font.TextLayout;
  47 import java2d.AnimatingControlsSurface;
  48 import java2d.CustomControls;
  49 import javax.swing.AbstractButton;
  50 import javax.swing.JToggleButton;
  51 import javax.swing.JToolBar;
  52 
  53 
  54 /**
  55  * Scaling or Shearing or Rotating an image & rectangle.
  56  */
  57 @SuppressWarnings("serial")
  58 public class SelectTx extends AnimatingControlsSurface {
  59 
  60     protected static final int RIGHT = 0;
  61     private static final int LEFT = 1;
  62     private static final int XMIDDLE = 2;
  63     private static final int DOWN = 3;
  64     private static final int UP = 4;
  65     private static final int YMIDDLE = 5;
  66     private static final int XupYup = 6;
  67     private static final int XdownYdown = 7;
  68     private static final String[] title = { "Scale", "Shear", "Rotate" };
  69     protected static final int SCALE = 0;
  70     protected static final int SHEAR = 1;
  71     protected static final int ROTATE = 2;
  72     private Image original;
  73     private int iw, ih;
  74     protected int transformType = SHEAR;
  75     protected double sx, sy;
  76     protected double angdeg;
  77     protected int direction = RIGHT;
  78     protected int transformToggle;
  79 
  80     @SuppressWarnings("LeakingThisInConstructor")
  81     public SelectTx() {
  82         setBackground(WHITE);
  83         original = getImage("painting.png");
  84         iw = original.getWidth(this);
  85         ih = original.getHeight(this);
  86         setControls(new Component[] { new DemoControls(this) });
  87     }
  88 
  89     @Override
  90     public void reset(int w, int h) {
  91 
  92         iw = w > 3 ? w / 3 : 1;
  93         ih = h > 3 ? h / 3 : 1;
  94 
  95         if (transformType == SCALE) {
  96             direction = RIGHT;
  97             sx = sy = 1.0;
  98         } else if (transformType == SHEAR) {
  99             direction = RIGHT;
 100             sx = sy = 0;
 101         } else {
 102             angdeg = 0;
 103         }
 104     }
 105 
 106     @Override
 107     public void step(int w, int h) {
 108         int rw = iw + 10;
 109         int rh = ih + 10;
 110 
 111         if (transformType == SCALE && direction == RIGHT) {
 112             sx += .05;
 113             if (w * .5 - iw * .5 + rw * sx + 10 > w) {
 114                 direction = DOWN;
 115             }
 116         } else if (transformType == SCALE && direction == DOWN) {
 117             sy += .05;
 118             if (h * .5 - ih * .5 + rh * sy + 20 > h) {
 119                 direction = LEFT;
 120             }
 121         } else if (transformType == SCALE && direction == LEFT) {
 122             sx -= .05;
 123             if (rw * sx - 10 <= -(w * .5 - iw * .5)) {
 124                 direction = UP;
 125             }
 126         } else if (transformType == SCALE && direction == UP) {
 127             sy -= .05;
 128             if (rh * sy - 20 <= -(h * .5 - ih * .5)) {
 129                 direction = RIGHT;
 130                 transformToggle = SHEAR;
 131             }
 132         }
 133 
 134         if (transformType == SHEAR && direction == RIGHT) {
 135             sx += .05;
 136             if (rw + 2 * rh * sx + 20 > w) {
 137                 direction = LEFT;
 138                 sx -= .1;
 139             }
 140         } else if (transformType == SHEAR && direction == LEFT) {
 141             sx -= .05;
 142             if (rw - 2 * rh * sx + 20 > w) {
 143                 direction = XMIDDLE;
 144             }
 145         } else if (transformType == SHEAR && direction == XMIDDLE) {
 146             sx += .05;
 147             if (sx > 0) {
 148                 direction = DOWN;
 149                 sx = 0;
 150             }
 151         } else if (transformType == SHEAR && direction == DOWN) {
 152             sy -= .05;
 153             if (rh - 2 * rw * sy + 20 > h) {
 154                 direction = UP;
 155                 sy += .1;
 156             }
 157         } else if (transformType == SHEAR && direction == UP) {
 158             sy += .05;
 159             if (rh + 2 * rw * sy + 20 > h) {
 160                 direction = YMIDDLE;
 161             }
 162         } else if (transformType == SHEAR && direction == YMIDDLE) {
 163             sy -= .05;
 164             if (sy < 0) {
 165                 direction = XupYup;
 166                 sy = 0;
 167             }
 168         } else if (transformType == SHEAR && direction == XupYup) {
 169             sx += .05;
 170             sy += .05;
 171             if (rw + 2 * rh * sx + 30 > w || rh + 2 * rw * sy + 30 > h) {
 172                 direction = XdownYdown;
 173             }
 174         } else if (transformType == SHEAR && direction == XdownYdown) {
 175             sy -= .05;
 176             sx -= .05;
 177             if (sy < 0) {
 178                 direction = RIGHT;
 179                 sx = sy = 0.0;
 180                 transformToggle = ROTATE;
 181             }
 182         }
 183 
 184         if (transformType == ROTATE) {
 185             angdeg += 5;
 186             if (angdeg == 360) {
 187                 angdeg = 0;
 188                 transformToggle = SCALE;
 189             }
 190         }
 191     }
 192 
 193     @Override
 194     public void render(int w, int h, Graphics2D g2) {
 195 
 196         Font font = g2.getFont();
 197         FontRenderContext frc = g2.getFontRenderContext();
 198         TextLayout tl = new TextLayout(title[transformType], font, frc);
 199         g2.setColor(BLACK);
 200         tl.draw(g2, (float) (w / 2 - tl.getBounds().getWidth() / 2),
 201                 (tl.getAscent() + tl.getDescent()));
 202 
 203         if (transformType == ROTATE) {
 204             String s = Double.toString(angdeg);
 205             g2.drawString("angdeg=" + s, 2, h - 4);
 206         } else {
 207             String s = Double.toString(sx);
 208             s = (s.length() < 5) ? s : s.substring(0, 5);
 209             TextLayout tlsx = new TextLayout("sx=" + s, font, frc);
 210             tlsx.draw(g2, 2, h - 4);
 211 
 212             s = Double.toString(sy);
 213             s = (s.length() < 5) ? s : s.substring(0, 5);
 214             g2.drawString("sy=" + s, (int) (tlsx.getBounds().getWidth() + 4), h
 215                     - 4);
 216         }
 217 
 218         if (transformType == SCALE) {
 219             g2.translate(w / 2 - iw / 2, h / 2 - ih / 2);
 220             g2.scale(sx, sy);
 221         } else if (transformType == SHEAR) {
 222             g2.translate(w / 2 - iw / 2, h / 2 - ih / 2);
 223             g2.shear(sx, sy);
 224         } else {
 225             g2.rotate(Math.toRadians(angdeg), w / 2, h / 2);
 226             g2.translate(w / 2 - iw / 2, h / 2 - ih / 2);
 227         }
 228 
 229         g2.setColor(ORANGE);
 230         g2.fillRect(0, 0, iw + 10, ih + 10);
 231         g2.drawImage(original, 5, 5, iw, ih, ORANGE, this);
 232 
 233     }
 234 
 235     public static void main(String argv[]) {
 236         createDemoFrame(new SelectTx());
 237     }
 238 
 239 
 240     static final class DemoControls extends CustomControls implements
 241             ActionListener {
 242 
 243         SelectTx demo;
 244         JToolBar toolbar;
 245 
 246         public DemoControls(SelectTx demo) {
 247             super(demo.name);
 248             this.demo = demo;
 249             add(toolbar = new JToolBar());
 250             toolbar.setFloatable(false);
 251             addTool("Scale", false);
 252             addTool("Shear", true);
 253             addTool("Rotate", false);
 254         }
 255 
 256         public void addTool(String str, boolean state) {
 257             JToggleButton b =
 258                     (JToggleButton) toolbar.add(new JToggleButton(str));
 259             b.setFocusPainted(false);
 260             b.setSelected(state);
 261             b.addActionListener(this);
 262             int width = b.getPreferredSize().width;
 263             Dimension prefSize = new Dimension(width, 21);
 264             b.setPreferredSize(prefSize);
 265             b.setMaximumSize(prefSize);
 266             b.setMinimumSize(prefSize);
 267         }
 268 
 269         @Override
 270         public void actionPerformed(ActionEvent e) {
 271             for (int i = 0; i < toolbar.getComponentCount(); i++) {
 272                 JToggleButton b = (JToggleButton) toolbar.getComponentAtIndex(i);
 273                 b.setSelected(false);
 274             }
 275             JToggleButton b = (JToggleButton) e.getSource();
 276             b.setSelected(true);
 277             if (b.getText().equals("Scale")) {
 278                 demo.transformType = SelectTx.SCALE;
 279                 demo.direction = SelectTx.RIGHT;
 280                 demo.sx = demo.sy = 1;
 281             } else if (b.getText().equals("Shear")) {
 282                 demo.transformType = SelectTx.SHEAR;
 283                 demo.direction = SelectTx.RIGHT;
 284                 demo.sx = demo.sy = 0;
 285             } else if (b.getText().equals("Rotate")) {
 286                 demo.transformType = SelectTx.ROTATE;
 287                 demo.angdeg = 0;
 288             }
 289         }
 290 
 291         @Override
 292         public Dimension getPreferredSize() {
 293             return new Dimension(200, 39);
 294         }
 295 
 296         @Override
 297         @SuppressWarnings("SleepWhileHoldingLock")
 298         public void run() {
 299             Thread me = Thread.currentThread();
 300             demo.transformToggle = demo.transformType;
 301             while (thread == me) {
 302                 try {
 303                     Thread.sleep(222);
 304                 } catch (InterruptedException e) {
 305                     return;
 306                 }
 307                 if (demo.transformToggle != demo.transformType) {
 308                     ((AbstractButton) toolbar.getComponentAtIndex(
 309                             demo.transformToggle)).doClick();
 310                 }
 311             }
 312             thread = null;
 313         }
 314     } // End DemoControls class
 315 } // End SelectTx class
 316