SVEventHandler.java 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // Copyright 2007 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); You may not
  4. // use this file except in compliance with the License. You may obtain a copy of
  5. // the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
  6. // applicable law or agreed to in writing, software distributed under the
  7. // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
  8. // OF ANY KIND, either express or implied. See the License for the specific
  9. // language governing permissions and limitations under the License.
  10. package com.google.scrollview.events;
  11. import com.google.scrollview.ScrollView;
  12. import com.google.scrollview.events.SVEvent;
  13. import com.google.scrollview.events.SVEventType;
  14. import com.google.scrollview.ui.SVWindow;
  15. import org.piccolo2d.PCamera;
  16. import org.piccolo2d.PNode;
  17. import org.piccolo2d.event.PBasicInputEventHandler;
  18. import org.piccolo2d.event.PInputEvent;
  19. import org.piccolo2d.nodes.PPath;
  20. import java.awt.Color;
  21. import java.awt.event.ActionEvent;
  22. import java.awt.event.ActionListener;
  23. import java.awt.event.KeyEvent;
  24. import java.awt.event.KeyListener;
  25. import java.awt.event.WindowEvent;
  26. import java.awt.event.WindowListener;
  27. import java.awt.Window;
  28. import javax.swing.Timer;
  29. /**
  30. * The ScrollViewEventHandler takes care of any events which might happen on the
  31. * canvas and converts them to an according SVEvent, which is (using the
  32. * processEvent method) then added to a message queue. All events from the
  33. * message queue get sent gradually.
  34. *
  35. * @author wanke@google.com
  36. */
  37. public class SVEventHandler extends PBasicInputEventHandler implements
  38. ActionListener, KeyListener, WindowListener {
  39. /** Necessary to wait for a defined period of time (for SVET_HOVER). */
  40. public Timer timer;
  41. /** The window which the event corresponds to. */
  42. private SVWindow svWindow;
  43. /** These are used to determine a selection size (for SVET_SELECTION). */
  44. private int lastX = 0;
  45. private int lastY = 0;
  46. /**
  47. * These are used in case we want to transmit our position, but do not get it
  48. * because it was no MouseEvent, in particular SVET_HOVER and SVET_INPUT.
  49. */
  50. private int lastXMove = 0;
  51. private int lastYMove = 0;
  52. /** For Drawing a rubber-band rectangle for selection. */
  53. private int startX = 0;
  54. private int startY = 0;
  55. private float rubberBandTransparency = 0.5f;
  56. private PNode selection = null;
  57. /** The string entered since the last enter. Since the client
  58. * end eats all newlines, we can't use the newline
  59. * character, so use ! for now, as it cannot be entered
  60. * directly anyway and therefore can never show up for real. */
  61. private String keyStr = "!";
  62. /** Setup the timer. */
  63. public SVEventHandler(SVWindow wdw) {
  64. timer = new Timer(1000, this);
  65. svWindow = wdw;
  66. }
  67. /**
  68. * Store the newest x,y values, add the message to the queue and restart the
  69. * timer.
  70. */
  71. private void processEvent(SVEvent e) {
  72. lastXMove = e.x;
  73. lastYMove = e.y;
  74. ScrollView.addMessage(e);
  75. timer.restart();
  76. }
  77. /** Show the associated popup menu at (x,y) (relative position of the window). */
  78. private void showPopup(PInputEvent e) {
  79. double x = e.getCanvasPosition().getX();
  80. double y = e.getCanvasPosition().getY();
  81. if (svWindow.svPuMenu != null) {
  82. svWindow.svPuMenu.show(svWindow, (int) x, (int) y);
  83. }
  84. }
  85. /** The mouse is clicked - create an SVET_CLICK event. */
  86. @Override
  87. public void mouseClicked(PInputEvent e) {
  88. if (e.isPopupTrigger()) {
  89. showPopup(e);
  90. } else {
  91. processEvent(new SVEvent(SVEventType.SVET_CLICK, svWindow, (int) e
  92. .getPosition().getX(), (int) e.getPosition().getY(), 0, 0, null));
  93. }
  94. }
  95. /**
  96. * The mouse key is pressed (and keeps getting pressed).
  97. * Depending on the OS, show a popup menu (if the button pressed is associated
  98. * with popup menus, like the RMB under windows&linux) or otherwise save the
  99. * position (in case it is a selection).
  100. */
  101. @Override
  102. public void mousePressed(PInputEvent e) {
  103. if (e.isPopupTrigger()) {
  104. showPopup(e);
  105. } else {
  106. lastX = (int) e.getPosition().getX();
  107. lastY = (int) e.getPosition().getY();
  108. timer.restart();
  109. }
  110. }
  111. /** The mouse is getting dragged - create an SVET_MOUSE event. */
  112. @Override
  113. public void mouseDragged(PInputEvent e) {
  114. processEvent(new SVEvent(SVEventType.SVET_MOUSE, svWindow, (int) e
  115. .getPosition().getX(), (int) e.getPosition().getY(), (int) e
  116. .getPosition().getX()
  117. - lastX, (int) e.getPosition().getY() - lastY, null));
  118. // Paint a selection rectangle.
  119. if (selection == null) {
  120. startX = (int) e.getPosition().getX();
  121. startY = (int) e.getPosition().getY();
  122. selection = PPath.createRectangle(startX, startY, 1, 1);
  123. selection.setTransparency(rubberBandTransparency);
  124. svWindow.canvas.getLayer().addChild(selection);
  125. } else {
  126. int right = Math.max(startX, (int) e.getPosition().getX());
  127. int left = Math.min(startX, (int) e.getPosition().getX());
  128. int bottom = Math.max(startY, (int) e.getPosition().getY());
  129. int top = Math.min(startY, (int) e.getPosition().getY());
  130. svWindow.canvas.getLayer().removeChild(selection);
  131. selection = PPath.createRectangle(left, top, right - left, bottom - top);
  132. selection.setPaint(Color.YELLOW);
  133. selection.setTransparency(rubberBandTransparency);
  134. svWindow.canvas.getLayer().addChild(selection);
  135. }
  136. }
  137. /**
  138. * The mouse was released.
  139. * Depending on the OS, show a popup menu (if the button pressed is associated
  140. * with popup menus, like the RMB under windows&linux) or otherwise create an
  141. * SVET_SELECTION event.
  142. */
  143. @Override
  144. public void mouseReleased(PInputEvent e) {
  145. if (e.isPopupTrigger()) {
  146. showPopup(e);
  147. } else {
  148. processEvent(new SVEvent(SVEventType.SVET_SELECTION, svWindow, (int) e
  149. .getPosition().getX(), (int) e.getPosition().getY(), (int) e
  150. .getPosition().getX()
  151. - lastX, (int) e.getPosition().getY() - lastY, null));
  152. }
  153. if (selection != null) {
  154. svWindow.canvas.getLayer().removeChild(selection);
  155. selection = null;
  156. }
  157. }
  158. /**
  159. * The mouse wheel is used to zoom in and out of the viewport and center on
  160. * the (x,y) position the mouse is currently on.
  161. */
  162. @Override
  163. public void mouseWheelRotated(PInputEvent e) {
  164. PCamera lc = svWindow.canvas.getCamera();
  165. double sf = SVWindow.SCALING_FACTOR;
  166. if (e.getWheelRotation() < 0) {
  167. sf = 1 / sf;
  168. }
  169. lc.scaleViewAboutPoint(lc.getScale() / sf, e.getPosition().getX(), e
  170. .getPosition().getY());
  171. }
  172. /**
  173. * The mouse was moved - create an SVET_MOTION event. NOTE: This obviously
  174. * creates a lot of traffic and, depending on the type of application, could
  175. * quite possibly be disabled.
  176. */
  177. @Override
  178. public void mouseMoved(PInputEvent e) {
  179. processEvent(new SVEvent(SVEventType.SVET_MOTION, svWindow, (int) e
  180. .getPosition().getX(), (int) e.getPosition().getY(), 0, 0, null));
  181. }
  182. /**
  183. * The mouse entered the window.
  184. * Start the timer, which will then emit SVET_HOVER events every X ms. */
  185. @Override
  186. public void mouseEntered(PInputEvent e) {
  187. timer.restart();
  188. }
  189. /**
  190. * The mouse exited the window
  191. * Stop the timer, so no more SVET_HOVER events will emit. */
  192. @Override
  193. public void mouseExited(PInputEvent e) {
  194. timer.stop();
  195. }
  196. /**
  197. * The only associated object with this is the timer, so we use it to send a
  198. * SVET_HOVER event.
  199. */
  200. public void actionPerformed(ActionEvent e) {
  201. processEvent(new SVEvent(SVEventType.SVET_HOVER, svWindow, lastXMove,
  202. lastYMove, 0, 0, null));
  203. }
  204. /**
  205. * A key was pressed - create an SVET_INPUT event.
  206. *
  207. * NOTE: Might be useful to specify hotkeys.
  208. *
  209. * Implementation note: The keyListener provided by Piccolo seems to be
  210. * broken, so we use the AWT listener directly.
  211. * There are never any keyTyped events received either so we are
  212. * stuck with physical keys, which is very ugly.
  213. */
  214. public void keyPressed(KeyEvent e) {
  215. char keyCh = e.getKeyChar();
  216. if (keyCh == '\r' || keyCh == '\n' || keyCh == '\0' || keyCh == '?') {
  217. processEvent(new SVEvent(SVEventType.SVET_INPUT, svWindow, lastXMove,
  218. lastYMove, 0, 0, keyStr));
  219. // Send newline characters as '!' as '!' can never be a keypressed
  220. // and the client eats all newline characters.
  221. keyStr = "!";
  222. } else {
  223. processEvent(new SVEvent(SVEventType.SVET_INPUT, svWindow, lastXMove,
  224. lastYMove, 0, 0, String.valueOf(keyCh)));
  225. keyStr += keyCh;
  226. }
  227. }
  228. /**
  229. * A window is closed (by the 'x') - create an SVET_DESTROY event. If it was
  230. * the last open Window, also send an SVET_EXIT event (but do not exit unless
  231. * the client says so).
  232. */
  233. public void windowClosing(WindowEvent e) {
  234. processEvent(new SVEvent(SVEventType.SVET_DESTROY, svWindow, lastXMove,
  235. lastYMove, 0, 0, null));
  236. Window w = e.getWindow();
  237. if (w != null) {
  238. w.dispose();
  239. }
  240. SVWindow.nrWindows--;
  241. if (SVWindow.nrWindows == 0) {
  242. processEvent(new SVEvent(SVEventType.SVET_EXIT, svWindow, lastXMove,
  243. lastYMove, 0, 0, null));
  244. }
  245. }
  246. /** These are all events we do not care about and throw away. */
  247. public void keyReleased(KeyEvent e) {
  248. }
  249. public void keyTyped(KeyEvent e) {
  250. }
  251. public void windowActivated(WindowEvent e) {
  252. }
  253. public void windowClosed(WindowEvent e) {
  254. }
  255. public void windowDeactivated(WindowEvent e) {
  256. }
  257. public void windowDeiconified(WindowEvent e) {
  258. }
  259. public void windowIconified(WindowEvent e) {
  260. }
  261. public void windowOpened(WindowEvent e) {
  262. }
  263. }