1 /* 2 * $RCSfile: MouseTranslate.java,v $ 3 * 4 * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * - Redistribution of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * - Redistribution in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * Neither the name of Sun Microsystems, Inc. or the names of 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * This software is provided "AS IS," without a warranty of any 23 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 24 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 26 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 27 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 28 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 29 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 30 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 31 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 32 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR 33 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGES. 35 * 36 * You acknowledge that this software is not designed, licensed or 37 * intended for use in the design, construction, operation or 38 * maintenance of any nuclear facility. 39 * 40 * $Revision: 1.1 $ 41 * $Date: 2009/04/08 06:31:15 $ 42 * $State: Exp $ 43 */ 44 45 package edu.uci.ics.jung.visualization3d.control; 46 47 import java.awt.*; 48 import java.awt.event.*; 49 import java.util.*; 50 import javax.media.j3d.*; 51 import javax.vecmath.*; 52 53 import com.sun.j3d.utils.behaviors.mouse.MouseBehavior; 54 import com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback; 55 56 /** 57 * MouseTranslate is a Java3D behavior object that lets users control the 58 * translation (X, Y) of an object via a mouse drag motion with the third 59 * mouse button (alt-click on PC). See MouseRotate for similar usage info. 60 */ 61 62 public class MouseTranslate extends MouseBehavior { 63 64 double x_factor = .02; 65 double y_factor = .02; 66 Vector3d translation = new Vector3d(); 67 68 private MouseBehaviorCallback callback = null; 69 70 /** 71 * Creates a mouse translate behavior given the transform group. 72 * @param transformGroup The transformGroup to operate on. 73 */ 74 public MouseTranslate(TransformGroup transformGroup) { 75 super(transformGroup); 76 } 77 78 /** 79 * Creates a default translate behavior. 80 */ 81 public MouseTranslate(){ 82 super(0); 83 } 84 85 /** 86 * Creates a translate behavior. 87 * Note that this behavior still needs a transform 88 * group to work on (use setTransformGroup(tg)) and 89 * the transform group must add this behavior. 90 * @param flags 91 */ 92 public MouseTranslate(int flags) { 93 super(flags); 94 } 95 96 /** 97 * Creates a translate behavior that uses AWT listeners and behavior 98 * posts rather than WakeupOnAWTEvent. The behavior is added to the 99 * specified Component. A null component can be passed to specify 100 * the behavior should use listeners. Components can then be added 101 * to the behavior with the addListener(Component c) method. 102 * @param c The Component to add the MouseListener 103 * and MouseMotionListener to. 104 * @since Java 3D 1.2.1 105 */ 106 public MouseTranslate(Component c) { 107 super(c, 0); 108 } 109 110 /** 111 * Creates a translate behavior that uses AWT listeners and behavior 112 * posts rather than WakeupOnAWTEvent. The behaviors is added to 113 * the specified Component and works on the given TransformGroup. 114 * A null component can be passed to specify the behavior should use 115 * listeners. Components can then be added to the behavior with the 116 * addListener(Component c) method. 117 * @param c The Component to add the MouseListener and 118 * MouseMotionListener to. 119 * @param transformGroup The TransformGroup to operate on. 120 * @since Java 3D 1.2.1 121 */ 122 public MouseTranslate(Component c, TransformGroup transformGroup) { 123 super(c, transformGroup); 124 } 125 126 /** 127 * Creates a translate behavior that uses AWT listeners and behavior 128 * posts rather than WakeupOnAWTEvent. The behavior is added to the 129 * specified Component. A null component can be passed to specify 130 * the behavior should use listeners. Components can then be added to 131 * the behavior with the addListener(Component c) method. 132 * Note that this behavior still needs a transform 133 * group to work on (use setTransformGroup(tg)) and the transform 134 * group must add this behavior. 135 * @param flags interesting flags (wakeup conditions). 136 * @since Java 3D 1.2.1 137 */ 138 public MouseTranslate(Component c, int flags) { 139 super(c, flags); 140 } 141 142 public void initialize() { 143 super.initialize(); 144 if ((flags & INVERT_INPUT) == INVERT_INPUT) { 145 invert = true; 146 x_factor *= -1; 147 y_factor *= -1; 148 } 149 } 150 151 /** 152 * Return the x-axis movement multipler. 153 **/ 154 public double getXFactor() { 155 return x_factor; 156 } 157 158 /** 159 * Return the y-axis movement multipler. 160 **/ 161 public double getYFactor() { 162 return y_factor; 163 } 164 165 /** 166 * Set the x-axis amd y-axis movement multipler with factor. 167 **/ 168 public void setFactor( double factor) { 169 x_factor = y_factor = factor; 170 } 171 172 /** 173 * Set the x-axis amd y-axis movement multipler with xFactor and yFactor 174 * respectively. 175 **/ 176 public void setFactor( double xFactor, double yFactor) { 177 x_factor = xFactor; 178 y_factor = yFactor; 179 } 180 181 public void processStimulus (Enumeration criteria) { 182 WakeupCriterion wakeup; 183 AWTEvent[] events; 184 MouseEvent evt; 185 // int id; 186 // int dx, dy; 187 188 while (criteria.hasMoreElements()) { 189 wakeup = (WakeupCriterion) criteria.nextElement(); 190 191 if (wakeup instanceof WakeupOnAWTEvent) { 192 events = ((WakeupOnAWTEvent)wakeup).getAWTEvent(); 193 if (events.length > 0) { 194 evt = (MouseEvent) events[events.length-1]; 195 doProcess(evt); 196 } 197 } 198 199 else if (wakeup instanceof WakeupOnBehaviorPost) { 200 while (true) { 201 // access to the queue must be synchronized 202 synchronized (mouseq) { 203 if (mouseq.isEmpty()) break; 204 evt = (MouseEvent)mouseq.remove(0); 205 // consolodate MOUSE_DRAG events 206 while ((evt.getID() == MouseEvent.MOUSE_DRAGGED) && 207 !mouseq.isEmpty() && 208 (((MouseEvent)mouseq.get(0)).getID() == 209 MouseEvent.MOUSE_DRAGGED)) { 210 evt = (MouseEvent)mouseq.remove(0); 211 } 212 } 213 doProcess(evt); 214 } 215 } 216 217 } 218 wakeupOn(mouseCriterion); 219 } 220 221 void doProcess(MouseEvent evt) { 222 int id; 223 int dx, dy; 224 225 processMouseEvent(evt); 226 227 if (((buttonPress)&&((flags & MANUAL_WAKEUP) == 0)) || 228 ((wakeUp)&&((flags & MANUAL_WAKEUP) != 0))){ 229 id = evt.getID(); 230 if ((id == MouseEvent.MOUSE_DRAGGED) && 231 !evt.isAltDown() && !evt.isMetaDown()) { 232 233 x = evt.getX(); 234 y = evt.getY(); 235 236 dx = x - x_last; 237 dy = y - y_last; 238 239 if ((!reset) && ((Math.abs(dy) < 50) && (Math.abs(dx) < 50))) { 240 //System.out.println("dx " + dx + " dy " + dy); 241 transformGroup.getTransform(currXform); 242 243 244 // System.err.println("currXform is \n"+currXform); 245 Transform3D origCurrentXform = new Transform3D(currXform); 246 247 Transform3D ltvw = new Transform3D(); 248 transformGroup.getLocalToVworld(ltvw); 249 // System.err.println("ltvw is \n"+ltvw); 250 Matrix3d mat = new Matrix3d(); 251 ltvw.getRotationScale(mat); 252 Transform3D rot = new Transform3D(); 253 rot.set(mat); 254 // x_factor = y_factor = 1/ltvw.getScale(); 255 256 // currXform.mulInverse(origCurrentXform); 257 // currXform.mul(rot); 258 259 260 // System.err.println("after mul. currXform is \n"+currXform); 261 // Transform3D scale = new Transform3D(); 262 // scale.setScale(ltvw.getScale()); 263 // scale.invert(); 264 // rot.mul(scale); 265 266 267 268 translation.x = dx*x_factor; 269 translation.y = -dy*y_factor; 270 271 272 // Vector3d translationOut = new Vector3d(); 273 // rot.transform(translation, translationOut); 274 275 transformX.set(translation); 276 277 if (invert) { 278 currXform.mul(currXform, transformX); 279 } else { 280 currXform.mul(transformX, currXform); 281 } 282 283 // currXform.mulInverse(rot); 284 // currXform.mul(origCurrentXform); 285 transformGroup.setTransform(currXform); 286 287 transformChanged( currXform ); 288 289 if (callback!=null) 290 callback.transformChanged( MouseBehaviorCallback.TRANSLATE, 291 currXform ); 292 293 } 294 else { 295 reset = false; 296 } 297 x_last = x; 298 y_last = y; 299 } 300 else if (id == MouseEvent.MOUSE_PRESSED) { 301 x_last = evt.getX(); 302 y_last = evt.getY(); 303 } 304 } 305 } 306 307 /** 308 * Users can overload this method which is called every time 309 * the Behavior updates the transform 310 * 311 * Default implementation does nothing 312 */ 313 public void transformChanged( Transform3D transform ) { 314 } 315 316 /** 317 * The transformChanged method in the callback class will 318 * be called every time the transform is updated 319 */ 320 public void setupCallback( MouseBehaviorCallback callback ) { 321 this.callback = callback; 322 } 323 } 324