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