]> gerrit.simantics Code Review - simantics/3d.git/blob - vtk.rendering/src/vtk/rendering/vtkInteractorForwarder.java
Various fixes to vtk swt components
[simantics/3d.git] / vtk.rendering / src / vtk / rendering / vtkInteractorForwarder.java
1 package vtk.rendering;
2
3 import java.awt.GraphicsDevice;
4 import java.awt.GraphicsEnvironment;
5 import java.awt.event.InputEvent;
6 import java.awt.event.KeyEvent;
7 import java.awt.event.KeyListener;
8 import java.awt.event.MouseEvent;
9 import java.awt.event.MouseListener;
10 import java.awt.event.MouseMotionListener;
11 import java.awt.event.MouseWheelEvent;
12 import java.awt.event.MouseWheelListener;
13 import java.lang.reflect.Field;
14 import java.util.concurrent.Executors;
15 import java.util.concurrent.ScheduledExecutorService;
16 import java.util.concurrent.TimeUnit;
17
18 /**
19  * Helper class used to implement all Mouse/Key Java listener and convert them
20  * into the vtkInteractor proper event.
21  *
22  * @authors   Sebastien Jourdain - sebastien.jourdain@kitware.com, Kitware Inc 2012
23  *            Joachim Pouderoux - joachim.pouderoux@kitware.com, Kitware SAS 2012
24  * @copyright This work was supported by CEA/CESTA
25  *            Commissariat a l'Energie Atomique et aux Energies Alternatives,
26  *            15 avenue des Sablieres, CS 60001, 33116 Le Barp, France.
27  */
28 public class vtkInteractorForwarder implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener {
29   final public static int MOUSE_BUTTON_1 = 1;
30   final public static int MOUSE_BUTTON_2 = 2;
31   final public static int MOUSE_BUTTON_3 = 4;
32   final public static int MOUSE_MODIFIER_SHIFT = 1;
33   final public static int MOUSE_MODIFIER_CTRL = 2;
34   final public static int MOUSE_MODIFIER_ALT = 4;
35
36   private int lastX;
37   private int lastY;
38   private int ctrlPressed;
39   private int shiftPressed;
40   private vtkComponent<?> component;
41   private double updateRate, updateRateRelease;
42   private double scaleFactor = 1;
43   private ScheduledExecutorService scheduler;
44   private Runnable eventTick;
45   private vtkEventInterceptor eventInterceptor;
46
47   public vtkInteractorForwarder(vtkComponent<?> component) {
48     this.component = component;
49     this.lastX = this.lastY = this.ctrlPressed = 0;
50     this.updateRate = 5.0;
51     this.updateRateRelease = 0.01;
52     this.scaleFactor = vtkInteractorForwarder.getDisplayScale();
53
54     this.eventTick = new Runnable() {
55
56       public void run() {
57         vtkInteractorForwarder.this.component.getVTKLock().lock();
58         vtkInteractorForwarder.this.component.getRenderWindowInteractor().TimerEvent();
59         vtkInteractorForwarder.this.component.getVTKLock().unlock();
60       }
61     };
62
63     // Schedule time events
64     this.scheduler = Executors.newSingleThreadScheduledExecutor();
65   }
66
67   /**
68    * Provide a custom event interceptor
69    *
70    * @param eventInterceptor
71    */
72   public void setEventInterceptor(vtkEventInterceptor eventInterceptor) {
73     this.eventInterceptor = eventInterceptor;
74   }
75
76   /**
77    * @return the custom event interceptor if any otherwise return null
78    */
79   public vtkEventInterceptor getEventInterceptor() {
80     return eventInterceptor;
81   }
82
83   /**
84    * Method called by VTK to start a timer
85    */
86   public void StartTimer() {
87     this.scheduler.scheduleAtFixedRate(this.eventTick, 10, 10, TimeUnit.MILLISECONDS);
88   }
89
90   /**
91    * Method called by VTK to stop a timer
92    */
93   public void DestroyTimer() {
94     this.scheduler.shutdown();
95   }
96
97   /**
98    * Allow the user to change the update rate
99    *
100    * @param updateRate
101    * @param updateRateRelease
102    */
103   public void setUpdateRate(double updateRate, double updateRateRelease) {
104     this.updateRate = updateRate;
105     this.updateRateRelease = updateRateRelease;
106   }
107
108   /**
109    * @return the update rate that is currently used
110    */
111   public double getUpdateRate() {
112     return updateRate;
113   }
114
115   /**
116    * @return the update rate after release that is currently used
117    */
118   public double getUpdateRateRelease() {
119     return updateRateRelease;
120   }
121
122   public void mousePressed(MouseEvent e) {
123     if (component == null || component.getRenderer() == null) {
124       return;
125     }
126
127     // Allow user to override some behavior
128     if (this.eventInterceptor != null && this.eventInterceptor.mousePressed(e)) {
129       return;
130     }
131
132     // Update scale factor if needed
133     this.scaleFactor = 1;
134     if (e.getComponent().getGraphicsConfiguration() != null) {
135       this.scaleFactor = vtkInteractorForwarder.getGraphicDeviceScale(e.getComponent().getGraphicsConfiguration().getDevice());
136     }
137
138     try {
139       component.getVTKLock().lockInterruptibly();
140       component.getRenderWindow().SetDesiredUpdateRate(this.updateRate);
141       lastX = (int)(e.getX() * scaleFactor);
142       lastY = (int)(e.getY() * scaleFactor);
143       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
144       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
145       component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
146       switch (e.getButton()) {
147       case MouseEvent.BUTTON3:
148         component.getRenderWindowInteractor().RightButtonPressEvent();
149         break;
150       case MouseEvent.BUTTON2:
151         component.getRenderWindowInteractor().MiddleButtonPressEvent();
152         break;
153       case MouseEvent.BUTTON1:
154       default:
155         component.getRenderWindowInteractor().LeftButtonPressEvent();
156         break;
157       }
158     } catch (InterruptedException interupt) {
159       // Nothing to do
160     } finally {
161       component.getVTKLock().unlock();
162     }
163   }
164
165   public void mouseReleased(MouseEvent e) {
166     if (component == null || component.getRenderer() == null) {
167       return;
168     }
169
170     // Allow user to override some behavior
171     if (this.eventInterceptor != null && this.eventInterceptor.mouseReleased(e)) {
172       return;
173     }
174
175     try {
176       component.getVTKLock().lockInterruptibly();
177       component.getRenderWindow().SetDesiredUpdateRate(this.updateRateRelease);
178       lastX = (int)(e.getX() * scaleFactor);
179       lastY = (int)(e.getY() * scaleFactor);
180       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
181       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
182       component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
183       switch (e.getButton()) {
184       case MouseEvent.BUTTON3:
185         component.getRenderWindowInteractor().RightButtonReleaseEvent();
186         break;
187       case MouseEvent.BUTTON2:
188         component.getRenderWindowInteractor().MiddleButtonReleaseEvent();
189         break;
190       case MouseEvent.BUTTON1:
191       default:
192         component.getRenderWindowInteractor().LeftButtonReleaseEvent();
193         break;
194       }
195     } catch (InterruptedException interupt) {
196       // Nothing to do
197     } finally {
198       component.getVTKLock().unlock();
199     }
200   }
201
202   public void mouseMoved(MouseEvent e) {
203     if (component == null || component.getRenderer() == null) {
204       return;
205     }
206
207     // Allow user to override some behavior
208     if (this.eventInterceptor != null && this.eventInterceptor.mouseMoved(e)) {
209       return;
210     }
211
212     try {
213       component.getVTKLock().lockInterruptibly();
214       component.getRenderWindow().SetDesiredUpdateRate(this.updateRateRelease);
215       lastX = (int)(e.getX() * scaleFactor);
216       lastY = (int)(e.getY() * scaleFactor);
217       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
218       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
219       component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
220       component.getRenderWindowInteractor().MouseMoveEvent();
221     } catch (InterruptedException interupt) {
222       // Nothing to do
223     } finally {
224       component.getVTKLock().unlock();
225     }
226   }
227
228   public void mouseDragged(MouseEvent e) {
229     // Allow user to override some behavior
230     if (this.eventInterceptor != null && this.eventInterceptor.mouseDragged(e)) {
231       return;
232     }
233
234     this.mouseMoved(e);
235   }
236
237   public void mouseEntered(MouseEvent e) {
238     if (component == null || component.getRenderer() == null) {
239       return;
240     }
241
242     // Allow user to override some behavior
243     if (this.eventInterceptor != null && this.eventInterceptor.mouseEntered(e)) {
244       return;
245     }
246
247     try {
248       component.getVTKLock().lockInterruptibly();
249       component.getRenderWindow().SetDesiredUpdateRate(this.updateRateRelease);
250       lastX = (int)(e.getX() * scaleFactor);
251       lastY = (int)(e.getY() * scaleFactor);
252       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
253       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
254       component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
255       component.getRenderWindowInteractor().EnterEvent();
256     } catch (InterruptedException interupt) {
257       // Nothing to do
258     } finally {
259       component.getVTKLock().unlock();
260     }
261   }
262
263   public void mouseExited(MouseEvent e) {
264     if (component == null || component.getRenderer() == null) {
265       return;
266     }
267
268     // Allow user to override some behavior
269     if (this.eventInterceptor != null && this.eventInterceptor.mouseExited(e)) {
270       return;
271     }
272
273     try {
274       component.getVTKLock().lockInterruptibly();
275       component.getRenderWindow().SetDesiredUpdateRate(this.updateRateRelease);
276       lastX = (int)(e.getX() * scaleFactor);
277       lastY = (int)(e.getY() * scaleFactor);
278       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
279       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
280       component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
281       component.getRenderWindowInteractor().LeaveEvent();
282     } catch (InterruptedException interupt) {
283       // Nothing to do
284     } finally {
285       component.getVTKLock().unlock();
286     }
287   }
288
289   public void mouseClicked(MouseEvent e) {
290     // Allow user to override some behavior
291     if (this.eventInterceptor != null && this.eventInterceptor.mouseClicked(e)) {
292       return;
293     }
294   }
295
296   public void mouseWheelMoved(MouseWheelEvent e) {
297     if (component == null || component.getRenderer() == null) {
298       return;
299     }
300
301     // Allow user to override some behavior
302     if (this.eventInterceptor != null && this.eventInterceptor.mouseWheelMoved(e)) {
303       return;
304     }
305
306     try {
307       component.getVTKLock().lockInterruptibly();
308       component.getRenderWindow().SetDesiredUpdateRate(this.updateRateRelease);
309       lastX = (int)(e.getX() * scaleFactor);
310       lastY = (int)(e.getY() * scaleFactor);
311       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
312       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
313       if (e.getWheelRotation() > 0) {
314         component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
315         component.getRenderWindowInteractor().MouseWheelForwardEvent();
316       }
317       else if (e.getWheelRotation() < 0) {
318         component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
319         component.getRenderWindowInteractor().MouseWheelBackwardEvent();
320       }
321     } catch (InterruptedException interupt) {
322       // Nothing to do
323     } finally {
324       component.getVTKLock().unlock();
325     }
326   }
327
328   public void keyPressed(KeyEvent e) {
329     if (component == null || component.getRenderer() == null) {
330       return;
331     }
332
333     // Allow user to override some behavior
334     if (this.eventInterceptor != null && this.eventInterceptor.keyPressed(e)) {
335       return;
336     }
337
338     try {
339       component.getVTKLock().lockInterruptibly();
340       component.getRenderWindow().SetDesiredUpdateRate(this.updateRateRelease);
341       ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1 : 0;
342       shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1 : 0;
343       char keyChar = e.getKeyChar();
344       component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, keyChar, 0, String.valueOf(keyChar));
345       component.getRenderWindowInteractor().KeyPressEvent();
346       component.getRenderWindowInteractor().CharEvent();
347     } catch (InterruptedException interupt) {
348       // Nothing to do
349     } finally {
350       component.getVTKLock().unlock();
351     }
352   }
353
354   public void keyReleased(KeyEvent e) {
355     // Allow user to override some behavior
356     if (this.eventInterceptor != null && this.eventInterceptor.keyReleased(e)) {
357       return;
358     }
359   }
360
361   public void keyTyped(KeyEvent e) {
362     // Allow user to override some behavior
363     if (this.eventInterceptor != null && this.eventInterceptor.keyTyped(e)) {
364       return;
365     }
366   }
367
368   public static int getDisplayScale() {
369     GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
370     return getGraphicDeviceScale(graphicsDevice);
371   }
372
373   public static int getGraphicDeviceScale(GraphicsDevice device) {
374     try {
375       Field field = device.getClass().getDeclaredField("scale");
376       if (field != null) {
377           field.setAccessible(true);
378           Object scale = field.get(device);
379           if (scale instanceof Integer) {
380             return ((Integer) scale).intValue();
381           }
382           System.out.println("Invalid scale type: " + scale);
383       }
384     } catch (Exception e) {
385       // Don't care, at least we tried.
386     }
387     return 1;
388   }
389 }