behavioursc_canvas.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*******************************************************************************
  2. AToMPM - A Tool for Multi-Paradigm Modelling
  3. Copyright (c) 2011 Raphael Mannadiar (raphael.mannadiar@mail.mcgill.ca)
  4. This file is part of AToMPM.
  5. AToMPM is free software: you can redistribute it and/or modify it under the
  6. terms of the GNU Lesser General Public License as published by the Free Software
  7. Foundation, either version 3 of the License, or (at your option) any later
  8. version.
  9. AToMPM is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11. PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with AToMPM. If not, see <http://www.gnu.org/licenses/>.
  14. *******************************************************************************/
  15. __canvasBehaviourStatechart = {
  16. '__STATE_IDLE' : 0,
  17. '__STATE_CANVAS_SELECTING' : 1,
  18. '__STATE_SOMETHING_SELECTED' : 2,
  19. '__STATE_DRAGGING_SELECTION' : 3,
  20. '__STATE_DRAWING_EDGE' : 4,
  21. '__STATE_EDITING_CONNECTION_PATHS' : 5,
  22. '__STATE_DRAGGING_CONNECTION_PATH_CTRL_POINT': 6,
  23. '__currentState' : undefined,
  24. '__entryActions':{
  25. 1:
  26. function(event)
  27. {
  28. GUIUtils.disableDock();
  29. __initCanvasSelectionOverlay(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  30. },
  31. 3:
  32. function(event)
  33. {
  34. GUIUtils.disableDock();
  35. GeometryUtils.initSelectionTransformationPreviewOverlay(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  36. },
  37. 4:
  38. function(event)
  39. {
  40. GUIUtils.disableDock();
  41. ConnectionUtils.initConnectionPath(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY),event.target);
  42. },
  43. 6:
  44. function(event)
  45. {
  46. GUIUtils.disableDock();
  47. }
  48. },
  49. '__exitActions' :{
  50. 1:
  51. function(event)
  52. {
  53. GUIUtils.enableDock();
  54. },
  55. 3:
  56. function(event)
  57. {
  58. GUIUtils.enableDock();
  59. },
  60. 4:
  61. function(event)
  62. {
  63. GUIUtils.enableDock();
  64. },
  65. 6:
  66. function(event)
  67. {
  68. GUIUtils.enableDock();
  69. }
  70. },
  71. /* transition to specified state */
  72. '__T' :
  73. function(s,event)
  74. {
  75. if( this.__currentState in this.__exitActions )
  76. this.__exitActions[this.__currentState](event);
  77. this.__currentState = s;
  78. if( s in this.__entryActions )
  79. this.__entryActions[s](event);
  80. },
  81. /* initialise the statechart */
  82. 'init':
  83. function()
  84. {
  85. this.__currentState = this.__STATE_IDLE;
  86. },
  87. /* handle an event... only discarded events are allowed to propagate to parent
  88. HTML element
  89. name: internal name of the event
  90. event: the javascript event */
  91. 'handleUserEvent':
  92. function(name,event)
  93. {
  94. if( this.__currentState == this.__STATE_IDLE )
  95. {
  96. if( name == __EVENT_RIGHT_RELEASE_CANVAS )
  97. DataUtils.create(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  98. else if( name == __EVENT_LEFT_PRESS_CANVAS )
  99. this.__T(this.__STATE_CANVAS_SELECTING,event);
  100. else if( name == __EVENT_MIDDLE_RELEASE_ICON )
  101. {
  102. __select( event.target );
  103. WindowManagement.openDialog(_ENTITY_EDITOR);
  104. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  105. }
  106. else if( name == __EVENT_SHIFT_MIDDLE_RELEASE_ICON )
  107. WindowManagement.openDialog(__SVG_TEXT_EDITOR, event.target);
  108. else if( name == __EVENT_LEFT_RELEASE_ICON )
  109. {
  110. __select( event.target );
  111. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  112. }
  113. else if( name == __EVENT_SHIFT_LEFT_RELEASE_ICON )
  114. {
  115. __select( event.target, true );
  116. WindowManagement.openDialog(_ENTITY_EDITOR);
  117. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  118. }
  119. else if( name == __EVENT_CODED_SELECTION )
  120. {
  121. __select(event);
  122. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  123. }
  124. else if( name == __EVENT_RIGHT_PRESS_ICON )
  125. this.__T(this.__STATE_DRAWING_EDGE,event);
  126. else if( name == __EVENT_SHIFT_WHEEL_ICON )
  127. {
  128. if( event.wheelDelta > 0 )
  129. __iconToFront(event.target);
  130. else
  131. __iconToBack(event.target);
  132. }
  133. else
  134. return;
  135. if( event && event.stopPropagation )
  136. {
  137. event.stopPropagation();
  138. event.preventDefault();
  139. }
  140. }
  141. else if( this.__currentState == this.__STATE_CANVAS_SELECTING )
  142. {
  143. if( name == __EVENT_MOUSE_MOVE ){
  144. __updateCanvasSelectionOverlay(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  145. }
  146. else if( name == __EVENT_LEFT_RELEASE_CANVAS ||
  147. name == __EVENT_LEFT_RELEASE_ICON )
  148. {
  149. if( ! __selectSelection() )
  150. this.__T(this.__STATE_IDLE,event);
  151. else
  152. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  153. }
  154. else
  155. return;
  156. if( event && event.stopPropagation )
  157. {
  158. event.stopPropagation();
  159. event.preventDefault();
  160. }
  161. }
  162. else if( this.__currentState == this.__STATE_SOMETHING_SELECTED )
  163. {
  164. if( name == __EVENT_KEYUP_DEL )
  165. {
  166. DataUtils.del();
  167. __select();
  168. this.__T(this.__STATE_IDLE,event);
  169. }
  170. else if( name == __EVENT_KEYUP_ESC ||
  171. name == __EVENT_LEFT_PRESS_CANVAS ||
  172. name == __EVENT_LEFT_PRESS_ICON ||
  173. name == __EVENT_CODED_CANVAS_EDIT ||
  174. name == __EVENT_MIDDLE_RELEASE_CANVAS ||
  175. name == __EVENT_MIDDLE_RELEASE_ICON ||
  176. name == __EVENT_SHIFT_MIDDLE_RELEASE_ICON ||
  177. name == __EVENT_RIGHT_RELEASE_CANVAS ||
  178. name == __EVENT_RIGHT_RELEASE_ICON )
  179. {
  180. __select();
  181. this.__T(this.__STATE_IDLE,event);
  182. }
  183. else if( name == __EVENT_LEFT_PRESS_SELECTION )
  184. {
  185. if( ! GeometryUtils.areTransformationsAllowed() )
  186. console.warn('the selection dragging mode can only be activated if '+
  187. 'all of the ends of selected edges are also selected, '+
  188. 'and if the geometry controls are inactive')
  189. else
  190. this.__T(this.__STATE_DRAGGING_SELECTION,event);
  191. }
  192. else if( name == __EVENT_KEYUP_CTRL )
  193. {
  194. if( ! GeometryUtils.areTransformationsAllowed() )
  195. console.warn('the geometry controls can only be activated if all '+
  196. 'of the ends of selected edges are also selected, and'+
  197. 'if the geometry controls aren\'t already active')
  198. else
  199. GeometryUtils.showGeometryControlsOverlay();
  200. }
  201. else if( name == __EVENT_KEYUP_ALT )
  202. {
  203. GeometryUtils.hideGeometryControlsOverlay();
  204. GeometryUtils.hideTransformationPreviewOverlay();
  205. }
  206. else if( name == __EVENT_KEYUP_SHIFT &&
  207. __selectionContainsType(__EDGETYPE) )
  208. {
  209. ConnectionUtils.showConnectionPathEditingOverlay();
  210. __select();
  211. this.__T(this.__STATE_EDITING_CONNECTION_PATHS);
  212. }
  213. else if( name == __EVENT_KEYUP_INS ||
  214. name == __EVENT_KEYUP_COMMAND )
  215. {
  216. WindowManagement.openDialog(_ENTITY_EDITOR);
  217. }
  218. else if( name == __EVENT_CODED_SELECTION )
  219. {
  220. __select(event);
  221. }
  222. else if( name == __EVENT_KEYUP_TAB )
  223. {
  224. if( ! GeometryUtils.areTransformationsAllowed() )
  225. console.warn('selection snapping is only enabled if all of '+
  226. 'the ends of selected edges are also selected, '+
  227. 'and if the geometry controls are inactive');
  228. else
  229. GeometryUtils.snapSelectionToGrid();
  230. }
  231. else
  232. return;
  233. if( event && event.stopPropagation )
  234. {
  235. event.stopPropagation();
  236. event.preventDefault();
  237. }
  238. }
  239. else if( this.__currentState == this.__STATE_DRAGGING_SELECTION )
  240. {
  241. if( name == __EVENT_MOUSE_MOVE )
  242. GeometryUtils.previewSelectionTranslation(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  243. else if( name == __EVENT_KEYUP_ESC )
  244. {
  245. GeometryUtils.hideTransformationPreviewOverlay();
  246. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  247. }
  248. else if( name == __EVENT_LEFT_RELEASE_CANVAS ||
  249. name == __EVENT_LEFT_RELEASE_SELECTION )
  250. {
  251. GeometryUtils.transformSelection(__SELECTION_DRAG);
  252. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  253. }
  254. else if( name == __EVENT_LEFT_RELEASE_ICON )
  255. {
  256. DataUtils.getInsertConnectionType(
  257. event.target,
  258. undefined,
  259. function(connectionType)
  260. {
  261. if( connectionType )
  262. GeometryUtils.transformSelection(
  263. __SELECTION_DRAG,
  264. {'dropTarget':event.target,
  265. 'connectionType':connectionType});
  266. else
  267. {
  268. console.warn('no containment relationship was created');
  269. GeometryUtils.transformSelection(__SELECTION_DRAG);
  270. }
  271. });
  272. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  273. }
  274. else
  275. return;
  276. if( event && event.stopPropagation )
  277. {
  278. event.stopPropagation();
  279. event.preventDefault();
  280. }
  281. }
  282. else if( this.__currentState == this.__STATE_DRAWING_EDGE )
  283. {
  284. if( name == __EVENT_MOUSE_MOVE ){
  285. ConnectionUtils.updateConnectionSegment(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  286. }
  287. else if( name == __EVENT_KEYUP_ESC ||
  288. name == __EVENT_RIGHT_RELEASE_CANVAS )
  289. {
  290. ConnectionUtils.hideConnectionPath();
  291. this.__T(this.__STATE_IDLE,event);
  292. }
  293. else if( name == __EVENT_LEFT_RELEASE_CANVAS ||
  294. name == __EVENT_LEFT_RELEASE_ICON ||
  295. name == __EVENT_KEYUP_CTRL )
  296. ConnectionUtils.addConnectionSegment();
  297. else if( name == __EVENT_MIDDLE_RELEASE_CANVAS ||
  298. name == __EVENT_MIDDLE_RELEASE_ICON ||
  299. name == __EVENT_KEYUP_ALT )
  300. ConnectionUtils.deleteConnectionSegment();
  301. else if( name == __EVENT_KEYUP_TAB )
  302. ConnectionUtils.snapConnectionSegment();
  303. else if( name == __EVENT_RIGHT_RELEASE_ICON )
  304. {
  305. if( ConnectionUtils.getConnectionPath().getTotalLength() <= 5 )
  306. console.warn('to avoid accidental path creations, paths must '+
  307. 'measure at least 5px');
  308. else
  309. DataUtils.connect(event.target);
  310. this.__T(this.__STATE_IDLE,event);
  311. }
  312. else
  313. return;
  314. if( event && event.stopPropagation )
  315. {
  316. event.stopPropagation();
  317. event.preventDefault();
  318. }
  319. }
  320. else if( this.__currentState == this.__STATE_EDITING_CONNECTION_PATHS )
  321. {
  322. if( name == __EVENT_KEYUP_ESC ||
  323. name == __EVENT_LEFT_RELEASE_CANVAS ||
  324. name == __EVENT_LEFT_RELEASE_ICON ||
  325. name == __EVENT_CODED_CANVAS_EDIT )
  326. {
  327. ConnectionUtils.hideConnectionPathEditingOverlay();
  328. this.__T(this.__STATE_IDLE,event);
  329. }
  330. else if( name == __EVENT_LEFT_PRESS_CTRL_POINT )
  331. {
  332. ConnectionUtils.initControlPointTranslation(event.target);
  333. this.__T(this.__STATE_DRAGGING_CONNECTION_PATH_CTRL_POINT,event);
  334. }
  335. else if( name == __EVENT_MIDDLE_RELEASE_CTRL_POINT )
  336. ConnectionUtils.deleteControlPoint(event.target);
  337. else if( name == __EVENT_RIGHT_RELEASE_CTRL_POINT )
  338. ConnectionUtils.addControlPoint(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY),event.target);
  339. else if( name == __EVENT_KEYUP_TAB )
  340. ConnectionUtils.snapControlPoint();
  341. else if( name == __EVENT_CODED_SELECTION )
  342. {
  343. ConnectionUtils.hideConnectionPathEditingOverlay();
  344. __select(event);
  345. this.__T(this.__STATE_SOMETHING_SELECTED,event);
  346. }
  347. else
  348. return;
  349. if( event && event.stopPropagation )
  350. {
  351. event.stopPropagation();
  352. event.preventDefault();
  353. }
  354. }
  355. else if( this.__currentState == this.__STATE_DRAGGING_CONNECTION_PATH_CTRL_POINT )
  356. {
  357. if( name == __EVENT_MOUSE_MOVE )
  358. ConnectionUtils.previewControlPointTranslation(GUIUtils.convertToCanvasX(event.pageX), GUIUtils.convertToCanvasY(event.pageY));
  359. else if( name == __EVENT_LEFT_RELEASE_CTRL_POINT )
  360. {
  361. ConnectionUtils.updateConnectionPath();
  362. this.__T(this.__STATE_EDITING_CONNECTION_PATHS,event);
  363. }
  364. else
  365. return;
  366. if( event && event.stopPropagation )
  367. {
  368. event.stopPropagation();
  369. event.preventDefault();
  370. }
  371. }
  372. }
  373. }