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;
19 * Helper class used to implement all Mouse/Key Java listener and convert them
20 * into the vtkInteractor proper event.
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.
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;
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;
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();
54 this.eventTick = new Runnable() {
57 vtkInteractorForwarder.this.component.getVTKLock().lock();
58 vtkInteractorForwarder.this.component.getRenderWindowInteractor().TimerEvent();
59 vtkInteractorForwarder.this.component.getVTKLock().unlock();
63 // Schedule time events
64 this.scheduler = Executors.newSingleThreadScheduledExecutor();
68 * Provide a custom event interceptor
70 * @param eventInterceptor
72 public void setEventInterceptor(vtkEventInterceptor eventInterceptor) {
73 this.eventInterceptor = eventInterceptor;
77 * @return the custom event interceptor if any otherwise return null
79 public vtkEventInterceptor getEventInterceptor() {
80 return eventInterceptor;
84 * Method called by VTK to start a timer
86 public void StartTimer() {
87 this.scheduler.scheduleAtFixedRate(this.eventTick, 10, 10, TimeUnit.MILLISECONDS);
91 * Method called by VTK to stop a timer
93 public void DestroyTimer() {
94 this.scheduler.shutdown();
98 * Allow the user to change the update rate
101 * @param updateRateRelease
103 public void setUpdateRate(double updateRate, double updateRateRelease) {
104 this.updateRate = updateRate;
105 this.updateRateRelease = updateRateRelease;
109 * @return the update rate that is currently used
111 public double getUpdateRate() {
116 * @return the update rate after release that is currently used
118 public double getUpdateRateRelease() {
119 return updateRateRelease;
122 public void mousePressed(MouseEvent e) {
123 if (component == null || component.getRenderer() == null) {
127 // Allow user to override some behavior
128 if (this.eventInterceptor != null && this.eventInterceptor.mousePressed(e)) {
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());
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();
150 case MouseEvent.BUTTON2:
151 component.getRenderWindowInteractor().MiddleButtonPressEvent();
153 case MouseEvent.BUTTON1:
155 component.getRenderWindowInteractor().LeftButtonPressEvent();
158 } catch (InterruptedException interupt) {
161 component.getVTKLock().unlock();
165 public void mouseReleased(MouseEvent e) {
166 if (component == null || component.getRenderer() == null) {
170 // Allow user to override some behavior
171 if (this.eventInterceptor != null && this.eventInterceptor.mouseReleased(e)) {
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();
187 case MouseEvent.BUTTON2:
188 component.getRenderWindowInteractor().MiddleButtonReleaseEvent();
190 case MouseEvent.BUTTON1:
192 component.getRenderWindowInteractor().LeftButtonReleaseEvent();
195 } catch (InterruptedException interupt) {
198 component.getVTKLock().unlock();
202 public void mouseMoved(MouseEvent e) {
203 if (component == null || component.getRenderer() == null) {
207 // Allow user to override some behavior
208 if (this.eventInterceptor != null && this.eventInterceptor.mouseMoved(e)) {
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) {
224 component.getVTKLock().unlock();
228 public void mouseDragged(MouseEvent e) {
229 // Allow user to override some behavior
230 if (this.eventInterceptor != null && this.eventInterceptor.mouseDragged(e)) {
237 public void mouseEntered(MouseEvent e) {
238 if (component == null || component.getRenderer() == null) {
242 // Allow user to override some behavior
243 if (this.eventInterceptor != null && this.eventInterceptor.mouseEntered(e)) {
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) {
259 component.getVTKLock().unlock();
263 public void mouseExited(MouseEvent e) {
264 if (component == null || component.getRenderer() == null) {
268 // Allow user to override some behavior
269 if (this.eventInterceptor != null && this.eventInterceptor.mouseExited(e)) {
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) {
285 component.getVTKLock().unlock();
289 public void mouseClicked(MouseEvent e) {
290 // Allow user to override some behavior
291 if (this.eventInterceptor != null && this.eventInterceptor.mouseClicked(e)) {
296 public void mouseWheelMoved(MouseWheelEvent e) {
297 if (component == null || component.getRenderer() == null) {
301 // Allow user to override some behavior
302 if (this.eventInterceptor != null && this.eventInterceptor.mouseWheelMoved(e)) {
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();
317 else if (e.getWheelRotation() < 0) {
318 component.getRenderWindowInteractor().SetEventInformationFlipY(lastX, lastY, ctrlPressed, shiftPressed, '0', 0, "0");
319 component.getRenderWindowInteractor().MouseWheelBackwardEvent();
321 } catch (InterruptedException interupt) {
324 component.getVTKLock().unlock();
328 public void keyPressed(KeyEvent e) {
329 if (component == null || component.getRenderer() == null) {
333 // Allow user to override some behavior
334 if (this.eventInterceptor != null && this.eventInterceptor.keyPressed(e)) {
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) {
350 component.getVTKLock().unlock();
354 public void keyReleased(KeyEvent e) {
355 // Allow user to override some behavior
356 if (this.eventInterceptor != null && this.eventInterceptor.keyReleased(e)) {
361 public void keyTyped(KeyEvent e) {
362 // Allow user to override some behavior
363 if (this.eventInterceptor != null && this.eventInterceptor.keyTyped(e)) {
368 public static int getDisplayScale() {
369 GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
370 return getGraphicDeviceScale(graphicsDevice);
373 public static int getGraphicDeviceScale(GraphicsDevice device) {
375 Field field = device.getClass().getDeclaredField("scale");
377 field.setAccessible(true);
378 Object scale = field.get(device);
379 if (scale instanceof Integer) {
380 return ((Integer) scale).intValue();
382 System.out.println("Invalid scale type: " + scale);
384 } catch (Exception e) {
385 // Don't care, at least we tried.