1 /*****************************************************************************
2 * Virtual Mockup for Machine Vision
3 * Copyright (C) 2001-2003 Fabio R. de Miranda, João E. Kogler Jr.,
4 * Carlos S. Santos.
5 * Virtual Mockup for Machine Vision Project funded by SENAC-SP
6 *
7 * Permission is granted to redistribute and/or modify this
8 * software under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License (http://www.gnu.org/copyleft/lesser.html)
16 * for more details.
17 *
18 *****************************************************************************/
19
20 package camera3d.gui;
21
22 import camera3d.*;
23 import camera3d.event.SelectionChangedEvent;
24 import camera3d.manipulation.*;
25 import javax.swing.*;
26 import java.awt.event.*;
27 import java.util.*;
28 import java.util.ArrayList;
29 import javax.media.j3d.Canvas3D;
30
31 /***
32 *
33 * @author Fábio Roberto de Miranda, Carlos da Silva dos Santos
34 * @version 1.0
35 */
36 public class ViewportsEventHandler implements SelectionChangeListener {
37
38 /*** Indicates that the handler is in transforming state, when picking is disabled
39 * and the currently selected object can be manipulated. */
40 public static final int TRANSFORMING = 0;
41 /*** Indicates that the handler is in idle state, when picking is enabled
42 * and no manipulation of objects can be performed. */
43 public static final int IDLE = 1;
44
45 /*** Indicates whether a transformation is beeing performed. */
46 private int state;
47
48 /*** Indicates the kind of transformation (translation, rotation, scaling or none)
49 * to be applied to the currently selected object.
50 */
51 private TransformType type = TransformType.NONE;
52 //int type = ViewportContextMenu.NONE_TYPE;
53
54 /*** Indicates the mode (absolute or relative) of transformation to be applied to
55 * the currently selected object.*/
56 private TransformMode mode = TransformMode.ABSOLUTE;
57 //int mode = VcObject.ABSOLUTE_MODE;
58
59 /*** Indicates the scope (axis, plane) on which a transformation will take effect. */
60 private TransformScope scope = TransformScope.X;
61 //int axis = VcObject.X;
62
63 /*** Holds the initial X coordinate of a mouse drag event. */
64 private int beginX;
65 /*** Holds the initial Y coordinate of a mouse drag event. */
66 private int beginY;
67
68 /*** Manipulator used to perform a transformation on the currently selected
69 * object. */
70 private TransformationManipulator currentManipulator;
71 private TranslationManipulator transManipulator;
72 private RotationManipulator rotManipulator;
73 private ScalingManipulator scaleManipulator;
74
75 private InternalListener internalListener = new InternalListener();
76 private KeybListener keyboardListener = new KeybListener();
77
78 // Introduced 08/04/2003 to eliminate dependency on ViewportContextMenu
79 // informing ViewportsEventHandler of which Viewport had been entered.
80 /*** List of Viewports which send their events to ViewportsEventHandler. Necessary
81 * for retrieving current Viewport from MouseEntered event.*/
82 private List viewportList = new ArrayList();
83 private Viewport lastViewport;
84
85 private GUIControl guiControl;
86
87 /*** Reference to the object currently selected */
88 private VcObject selectedObject;
89
90 /*** Reference to the VcView object currently shown */
91 private VcView currentView=null;
92
93 private static ViewportsEventHandler handler;
94
95 private ViewportWindowManager manager;
96
97 private static final Viewport UNLIKELY_VIEWPORT = new Viewport();
98
99 /***
100 * Desperate singleton
101 */
102 public ViewportsEventHandler getViewportEventsHandler(GUIControl guiControl){
103 handler = new ViewportsEventHandler(guiControl);
104 return handler;
105 }
106
107 public ViewportsEventHandler(GUIControl guiControl) {
108 this();
109 this.guiControl = guiControl;
110 transManipulator = new TranslationManipulator();
111 rotManipulator = new RotationManipulator();
112 scaleManipulator = new ScalingManipulator();
113 }
114
115
116 public ViewportsEventHandler(){
117 this.state = ViewportsEventHandler.IDLE;
118 }
119
120 public void addViewportFrame(ViewportFrame vpFrame){
121 vpFrame.getViewport().getCanvas3D().addMouseListener(internalListener);
122 vpFrame.getViewport().getCanvas3D().addMouseMotionListener((MouseMotionListener)internalListener);
123 vpFrame.getViewport().getCanvas3D().addKeyListener(keyboardListener);
124 viewportList.add(vpFrame.getViewport());
125 }
126
127
128 /* Code pasted from Java's PopupDemo.java */
129 class InternalListener extends MouseAdapter implements MouseMotionListener {
130 public void mousePressed(MouseEvent e) {
131 /*
132 Warning: there is a bug with the way translation manipulation works,
133 as we don't check whether the mouse click actually "hits" the object.
134 That allows the user to click on the void and initiate a translation,
135 causing a sudden movement of the object from its position to the mouse
136 position.
137 */
138 // if the selectedObject is null or non-live we can't do
139 // anything with it
140 if(selectedObject==null|| !selectedObject.isLive()) return;
141 debugln("Mouse pressed");
142 int mod = e.getModifiers();
143 if ((mod&MouseEvent.BUTTON1_MASK)==MouseEvent.BUTTON1_MASK){
144 beginX = e.getX();
145 beginY = e.getY();
146 switch (state) {
147 case TRANSFORMING:
148 currentManipulator.setBeginPoint(beginX, beginY);
149 ///DANGER
150 selectedObject.setOngoingTransformation(true);
151 break;
152 }
153 }
154 }
155
156 public void mouseReleased(MouseEvent e) {
157 if(selectedObject==null|| !selectedObject.isLive()) return;
158 debugln("Mouse released");
159 switch (state) {
160 case TRANSFORMING:
161 //DANGER
162 selectedObject.setOngoingTransformation(false);
163 break;
164 }
165 }
166
167 public void mouseEntered(MouseEvent e){
168 //debugln("Mouse entered");
169 Canvas3D canvas = (Canvas3D)e.getSource();
170 setEnteredViewport(getViewportFromCanvas(canvas));
171 Object obj = canvas.getView().getViewPlatform().getUserData();
172 if(obj instanceof VcView){
173 currentView = (VcView) obj;
174 currentView.setNavigateEnable(true);
175 // does not allow manipulation of current view
176 if(currentView==selectedObject){
177 cancelAction();
178 }
179 debugln("___VPEHandler current view: " + currentView.getLabel());
180 }
181 }
182
183 public void mouseExited(MouseEvent e){
184 debugln("Mouse exited");
185 if(currentView!=null){
186 currentView.setNavigateEnable(false);
187 currentView = null;
188 }
189 }
190
191 // MouseMotionListener methods
192 public void mouseMoved(MouseEvent e){
193
194 if(selectedObject==null|| !selectedObject.isLive()) return;
195 //debugln("Mouse moved to "+e.getX()+","+e.getY());
196 int mod = e.getModifiers();
197 if ((mod&MouseEvent.BUTTON1_MASK)==MouseEvent.BUTTON1_MASK){
198 //debugln(" While Btn 1 pressed");
199 switch (state) {
200 case TRANSFORMING:
201 currentManipulator.setCurrentPoint(e.getX(), e.getY());
202 break;
203 }
204
205 }
206 }
207
208 public void mouseDragged(MouseEvent e){
209 if(selectedObject==null|| !selectedObject.isLive()) return;
210 //debugln("Mouse Dragged to "+e.getX()+","+e.getY());
211 int mod = e.getModifiers();
212 if ((mod&MouseEvent.BUTTON1_MASK)==MouseEvent.BUTTON1_MASK){
213 //debugln(" While Btn 1 pressed");
214 switch (state) {
215 case TRANSFORMING:
216 if (currentManipulator!=null){
217 currentManipulator.setCurrentPoint(e.getX(), e.getY());
218 }
219 break;
220 }
221 }
222
223 }
224
225 }
226
227 class KeybListener extends KeyAdapter{
228 public void keyPressed(KeyEvent k){
229 debugln("Key Pressed: "+KeyEvent.getKeyText(k.getKeyCode()));
230 if (k.getKeyCode() == KeyEvent.VK_ESCAPE){
231 cancelAction();
232 }
233 if (k.getKeyCode() == KeyEvent.VK_X){
234 setAxis(KeyEvent.VK_X);
235 }
236 if (k.getKeyCode() == KeyEvent.VK_Y){
237 setAxis(KeyEvent.VK_Y);
238 }
239 if (k.getKeyCode() == KeyEvent.VK_Z){
240 setAxis(KeyEvent.VK_Z);
241 }
242
243
244 }
245
246 public void keyReleased(KeyEvent k){
247 debugln("Key Released: "+KeyEvent.getKeyText(k.getKeyCode()));
248 }
249 }
250
251
252 private void cancelAction(){
253 state = ViewportsEventHandler.IDLE;
254 manager.setPickingInViewports(true);
255
256 if(selectedObject!=null)selectedObject.setOngoingTransformation(false);
257 if(currentManipulator!=null) currentManipulator.clearSelection();
258 manager.setCursorInViewports(TransformType.NONE);
259 // Warn frames that no action is selected anymore
260 manager.setTransformationTypeInContextMenus(TransformType.NONE, mode, scope,false);
261 }
262
263 private void setEnteredViewport(Viewport viewport){
264 this.lastViewport = viewport;
265 debugln("Entered view:"+viewport.getView().getLabel());
266 if (state == ViewportsEventHandler.TRANSFORMING){
267 //currentManipulator.setCurrentViewport(viewport);
268 currentManipulator.setCanvas3D(viewport.getCanvas3D());
269 }
270 }
271
272 private Viewport getViewportFromCanvas(Canvas3D canvas){
273 Viewport viewport = UNLIKELY_VIEWPORT;
274
275 for(Iterator iter = viewportList.iterator();iter.hasNext(); ){
276 Viewport vp = (Viewport)iter.next();
277 if(canvas==vp.getCanvas3D()){
278 viewport = vp;
279 break;
280 }
281 }
282 return viewport;
283 }
284
285 public void setSelectedManipulationAction(TransformType type){
286 /* If there is no object selected we will not allow setting action
287 type. It would be better to disable the corresponding option
288 in viewport context menu till one object gets selected. */
289 if(selectedObject==null){
290 cancelAction();
291 return;
292 }
293 this.type = type;
294 manager.setCursorInViewports(type);
295 this.state = TRANSFORMING;
296 boolean viewSelected = false;
297 if(type==TransformType.TRANSLATION){
298 currentManipulator = transManipulator;
299 transManipulator.setTranslatableObject((TranslatableObject)selectedObject);
300 }else if(type==TransformType.ROTATION){
301 currentManipulator = rotManipulator;
302 rotManipulator.setRotatableObject((RotatableObject)selectedObject);
303 }else if(type==TransformType.SCALING){
304 currentManipulator = scaleManipulator;
305 scaleManipulator.setScalableObject((ScalableObject)selectedObject);
306 // all scaling is performed relative to local axis
307 mode = TransformMode.RELATIVE;
308 if (selectedObject instanceof VcView){
309 setSelectedManipulationScope(TransformScope.XYZ);
310 viewSelected = true;
311 }
312 }
313 currentManipulator.setCanvas3D(lastViewport.getCanvas3D());
314
315 currentManipulator.setTransformationScope(scope);
316 currentManipulator.setTransformationMode(mode);
317 currentManipulator.setBeginPoint(beginX, beginY);
318
319 manager.setPickingInViewports(false);
320 manager.setTransformationTypeInContextMenus(type, mode, scope,viewSelected);
321 }
322
323 public void setSelectedManipulationScope(TransformScope scope){
324 /* If there is no object selected we will not allow setting action
325 type. It would be better to disable the corresponding option
326 in viewport context menu till one object gets selected. */
327 if(selectedObject==null){
328 cancelAction();
329 return;
330 }
331
332 debugln("VPEvtHandler select scope");
333 this.scope = scope;
334 switch (state){
335 case TRANSFORMING:
336 currentManipulator.setTransformationScope(scope);
337 debugln("VPEvtHandler: "+ scope.toString());
338 break;
339 case IDLE:
340 break;
341 }
342 boolean viewSelected = (selectedObject instanceof VcView);
343 manager.setTransformationTypeInContextMenus(type, mode, scope, viewSelected);
344 }
345
346 public void setSelectedManipulationMode(TransformMode mode){
347 /* If there is no object selected we will not allow setting action
348 mode. It would be better to disable the corresponding option
349 in viewport context menu till one object gets selected. */
350 if(selectedObject==null){
351 cancelAction();
352 return;
353 }
354
355 debugln("VPEvtHandler mode "+ mode.toString());
356 this.mode = mode;
357
358 switch (state){
359 case TRANSFORMING:
360 if(selectedObject!=null){
361 selectedObject.setOngoingTransformationMode(this.mode);
362 }
363 if (currentManipulator!=null){
364 currentManipulator.setTransformationMode(this.mode);
365 //debugln("Manipulator was not null");
366 }
367 break;
368 }
369 boolean viewSelected = (selectedObject instanceof VcView);
370 manager.setTransformationTypeInContextMenus(type, mode, scope,viewSelected);
371 }
372
373 /*** Needed to disable/enable picking of objects*/
374 public void setViewportWindowManager(ViewportWindowManager manager){
375 this.manager = manager;
376 }
377
378 void enablePicking(){
379 manager.setPickingInViewports(true);
380 }
381
382 void disablePicking(){
383 manager.setPickingInViewports(false);
384 }
385
386
387 void debugln(String s){
388 if (GUIControl.debugflag)
389 System.out.println(s);
390 }
391
392 // Triggers proper transformation
393 void beginTransformation(){
394 state = ViewportsEventHandler.TRANSFORMING;
395 }
396
397 /***
398 * Informs this object of changes made to the list of selected objects. Necessary
399 * to inform transformation manipulators of the object currently selected.
400 */
401 public void selectionChanged(SelectionChangedEvent event){
402 List added = event.getAddedObjects();
403 if(added.size() >= 1){
404 this.selectedObject = (VcObject)added.get(0);
405 } else {
406 debugln("Zero objects selected: cancelling action");
407 this.selectedObject = null;
408 cancelAction();
409 selectedObject = null;
410 }
411
412 // if the selected object is the current view we will not allow
413 // any manipulation
414 if(selectedObject==currentView){
415 cancelAction();
416 return;
417 }
418
419 switch (state) {
420 case TRANSFORMING:
421 if (currentManipulator==rotManipulator){
422 rotManipulator.setRotatableObject((RotatableObject)selectedObject);
423 }
424 if (currentManipulator==rotManipulator){
425 transManipulator.setTranslatableObject((TranslatableObject)selectedObject);
426 }
427 if (currentManipulator==rotManipulator){
428 scaleManipulator.setScalableObject((ScalableObject)selectedObject);
429 }
430 break;
431 }
432 if (selectedObject!=null){
433 selectedObject.setOngoingTransformationMode(mode);
434 if (selectedObject instanceof VcView){
435 if (type == TransformType.SCALING){
436 // Do something to forbid the use of NU scaling of VcViews
437 if (scope!=TransformScope.XYZ){
438 setSelectedManipulationScope(TransformScope.XYZ);
439 }
440 boolean viewSelected = (selectedObject instanceof VcView);
441 manager.setTransformationTypeInContextMenus(type, mode, scope,viewSelected);
442 }
443 }
444 }
445
446 }
447
448 void setAxis(int key){
449 switch(key){
450 case KeyEvent.VK_X:
451 setSelectedManipulationScope(TransformScope.X);
452 break;
453 case KeyEvent.VK_Y:
454 setSelectedManipulationScope(TransformScope.Y);
455 break;
456 case KeyEvent.VK_Z:
457 setSelectedManipulationScope(TransformScope.Z);
458 break;
459 }
460 /*
461 int ctx_type = type;
462
463 if ((type == VcObject.SCALING_TYPE)&&(selectedObject instanceof VcView)){
464 ctx_type = ViewportContextMenu.VIEW_SCALE_TYPE;
465 }
466 */
467 boolean viewSelected = (selectedObject instanceof VcView);
468 manager.setTransformationTypeInContextMenus(type, mode, scope,viewSelected);
469 }
470
471 }
This page was automatically generated by Maven