canvas.xml 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. <class name="Canvas">
  2. <relationships>
  3. <association name="parent" class="A" min="1" max="1" />
  4. <inheritance class="SCCDWidget" priority='0'/>
  5. <inheritance class="tk.Canvas" priority='1'/>
  6. <association name="elements" class="CanvasElement"/>
  7. <association name="connecting_lines" class="ConnectingLines"/>
  8. <association name="prompt" class="ChoicePrompt"/>
  9. </relationships>
  10. <constructor>
  11. <parameter name="parent" />
  12. <super class="SCCDWidget"/>
  13. <super class="tk.Canvas">
  14. <parameter expr="parent" />
  15. <parameter expr="**{'scrollregion': (0, 0, parent.winfo_screenwidth()*2, parent.winfo_screenheight() * 2)}"/>
  16. </super>
  17. <body>
  18. vbar = tk.Scrollbar(self, orient=tk.VERTICAL)
  19. vbar.config(command=self.yview)
  20. vbar.pack(side=tk.RIGHT, fill=tk.Y, pady=(0, 16))
  21. hbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
  22. hbar.config(command=self.xview)
  23. hbar.pack(side=tk.BOTTOM, fill=tk.X)
  24. self.config(background='white', yscrollcommand=vbar.set, xscrollcommand=hbar.set)
  25. self.focus_set()
  26. self.assoc_links = {}
  27. self.element_group = {}
  28. self.group_location = {}
  29. self.connecting_lines = {}
  30. self.lines = set()
  31. self.layers = []
  32. self.to_move = {}
  33. self.elems = []
  34. self.tmp_line = None
  35. self.currently_selected = None
  36. self.loading = [tk.PhotoImage(file="icons/loading.gif", format="gif -index %i" % i) for i in range(8)]
  37. </body>
  38. </constructor>
  39. <destructor>
  40. <body>
  41. self.destroy()
  42. </body>
  43. </destructor>
  44. <scxml initial="main">
  45. <state id="main">
  46. <transition target="../ready">
  47. <raise event="tk_widget" scope="narrow" target="'parent'">
  48. <parameter expr="self"/>
  49. </raise>
  50. </transition>
  51. </state>
  52. <parallel id="ready">
  53. <state id="process_events" initial="ready">
  54. <state id="ready">
  55. <transition event="select_for_creation" target=".">
  56. <parameter name="element_name"/>
  57. <script>
  58. self.currently_selected = element_name
  59. </script>
  60. </transition>
  61. <transition event="right-click" cond="self.currently_selected is not None and id(self) == ID and not control_pressed" target="../creating_element">
  62. <parameter name="ID"/>
  63. <script>
  64. self.create_location = (self.last_x, self.last_y)
  65. </script>
  66. </transition>
  67. <transition event="create_line" target="../creating_line">
  68. <parameter name="cs_element"/>
  69. <parameter name="as_element"/>
  70. <parameter name="coordinates"/>
  71. <script>
  72. self.creating_line = (cs_element, as_element, coordinates)
  73. </script>
  74. </transition>
  75. <transition event="define_group" target="../creating_group">
  76. <parameter name="element"/>
  77. <script>
  78. self.creating_id = element["id"]
  79. self.group_location[element['id']] = (element['x'], element['y'])
  80. </script>
  81. <raise event="create_instance" scope="cd">
  82. <parameter expr="'elements'"/>
  83. <parameter expr="'CanvasElement'"/>
  84. <parameter expr="self"/>
  85. <parameter expr="(element['x'], element['y'])"/>
  86. <parameter expr="element['id']"/>
  87. <parameter expr="element['__asid']"/>
  88. </raise>
  89. </transition>
  90. <transition event="define_contains" target=".">
  91. <parameter name="element"/>
  92. <script>
  93. self.element_group[element["__target"]] = element["__source"]
  94. </script>
  95. </transition>
  96. <transition event="draw_canvas" cond="element['type'] != 'ConnectingLine'" target=".">
  97. <parameter name="element"/>
  98. <raise event="draw_element" scope="narrow" target="self.assoc_links[self.element_group[element['id']]]">
  99. <parameter expr="element"/>
  100. </raise>
  101. </transition>
  102. <transition event="draw_canvas" cond="element['type'] == 'ConnectingLine'" target=".">
  103. <parameter name="element"/>
  104. <raise event="create_instance" scope="cd">
  105. <parameter expr="'connecting_lines'"/>
  106. <parameter expr="'ConnectingLine'"/>
  107. <parameter expr="self"/>
  108. <parameter expr="element"/>
  109. </raise>
  110. </transition>
  111. <transition event="instance_created" target=".">
  112. <parameter name="result"/>
  113. <raise event="start_instance" scope="cd">
  114. <parameter expr="result"/>
  115. </raise>
  116. </transition>
  117. <transition event="moved_group" target=".">
  118. <parameter name="group_element"/>
  119. <parameter name="new_location"/>
  120. <script>
  121. self.group_location[group_element] = new_location
  122. </script>
  123. <raise event="moved_element" scope="narrow" target="'connecting_lines'">
  124. <parameter expr="group_element"/>
  125. <parameter expr="new_location"/>
  126. </raise>
  127. </transition>
  128. <transition event="deleted_group" target=".">
  129. <parameter name="group_element"/>
  130. <script>
  131. try:
  132. del self.group_location[group_element]
  133. except KeyError:
  134. pass
  135. </script>
  136. <raise event="deleted_element" scope="narrow" target="'connecting_lines'">
  137. <parameter expr="group_element"/>
  138. </raise>
  139. </transition>
  140. </state>
  141. <state id="creating_line" initial="drawing">
  142. <onentry>
  143. <script>
  144. self.tmp_line = self.create_line(self.creating_line[2][0], self.creating_line[2][1], self.last_x, self.last_y)
  145. </script>
  146. </onentry>
  147. <onexit>
  148. <script>
  149. self.delete(self.tmp_line)
  150. self.tmp_line = None
  151. </script>
  152. </onexit>
  153. <state id="drawing">
  154. <transition event="motion" target=".">
  155. <script>
  156. x, y, _, _ = self.coords(self.tmp_line)
  157. # NOTE: make sure that you can not click on the temporary line itself
  158. if x > self.last_x:
  159. self.last_x += 2
  160. else:
  161. self.last_x -= 2
  162. if y > self.last_y:
  163. self.last_y += 2
  164. else:
  165. self.last_y -= 2
  166. self.coords(self.tmp_line, x, y, self.last_x, self.last_y)
  167. </script>
  168. </transition>
  169. <transition event="right-click" cond="ID == id(self) and not control_pressed" target="../../ready">
  170. <parameter name="ID"/>
  171. </transition>
  172. <transition event="create_line" target="../create_in_mv">
  173. <parameter name="cs_element"/>
  174. <parameter name="as_element"/>
  175. <script>
  176. origin_cs, origin_as, _ = self.creating_line
  177. self.creating_line = (origin_cs, origin_as, cs_element, as_element)
  178. </script>
  179. </transition>
  180. </state>
  181. <state id="create_in_mv" initial="query_type">
  182. <state id="query_type">
  183. <onentry>
  184. <raise event="mv_request" scope="broad">
  185. <parameter expr="'connections_between'"/>
  186. <parameter expr="[current_model, self.creating_line[1], self.creating_line[3]]"/>
  187. </raise>
  188. </onentry>
  189. <transition event="mv_response" target="../check_types">
  190. <parameter name="result"/>
  191. <script>
  192. self.allowed_types = result
  193. </script>
  194. </transition>
  195. <transition event="mv_exception" target="../../../ready">
  196. <parameter name="ID"/>
  197. <parameter name="exception_name"/>
  198. <parameter name="description"/>
  199. <raise event="errorlog_log" scope="broad">
  200. <parameter expr="'Could not query connections between elements: %s -- %s' % (exception_name, description)"/>
  201. </raise>
  202. </transition>
  203. </state>
  204. <state id="check_types">
  205. <transition cond="len(self.allowed_types) == 0" target="../../../ready">
  206. <raise event="errorlog_log" scope="broad">
  207. <parameter expr="'No allowed associations from %s to %s' % (self.creating_line[1], self.creating_line[3])"/>
  208. </raise>
  209. </transition>
  210. <transition cond="len(self.allowed_types) == 1" target="../create">
  211. <script>
  212. self.assoc_type = self.allowed_types.pop()
  213. </script>
  214. </transition>
  215. <transition cond="len(self.allowed_types) > 1" target="../request_user">
  216. <script>
  217. self.allowed_types = list(self.allowed_types)
  218. </script>
  219. </transition>
  220. </state>
  221. <state id="request_user" initial="check_next">
  222. <onentry>
  223. <script>
  224. self.new_allowed_types = {}
  225. </script>
  226. </onentry>
  227. <state id="check_next">
  228. <transition cond="len(self.allowed_types) > 0" target="../convert_to_name"/>
  229. <transition cond="len(self.allowed_types) == 0" target="../request">
  230. <script>
  231. self.allowed_types = self.new_allowed_types
  232. </script>
  233. </transition>
  234. </state>
  235. <state id="convert_to_name">
  236. <onentry>
  237. <raise event="mv_request" scope="broad">
  238. <parameter expr="'read_attrs'"/>
  239. <parameter expr="[current_metamodel, self.allowed_types[0]]"/>
  240. </raise>
  241. </onentry>
  242. <transition event="mv_response" target="../check_next">
  243. <parameter name="result"/>
  244. <script>
  245. if 'name' in result and result['name'] is not None:
  246. self.new_allowed_types[result['name']] = self.allowed_types[0]
  247. self.allowed_types.pop(0)
  248. </script>
  249. </transition>
  250. <transition event="mv_exception" target="../../../../ready">
  251. <parameter name="ID"/>
  252. <parameter name="exception_name"/>
  253. <parameter name="description"/>
  254. <raise event="errorlog_log" scope="broad">
  255. <parameter expr="'Could not read attributes: %s -- %s' % (exception_name, description)"/>
  256. </raise>
  257. </transition>
  258. </state>
  259. <state id="request">
  260. <onentry>
  261. <raise event="create_instance" scope="cd">
  262. <parameter expr="'prompt'"/>
  263. <parameter expr="'ChoicePrompt'"/>
  264. <parameter expr="'Pick desired link type:'"/>
  265. <parameter expr="self.allowed_types.keys()"/>
  266. </raise>
  267. </onentry>
  268. <transition event="instance_created" target="../wait_for_response">
  269. <parameter name="assoc_name"/>
  270. <raise event="start_instance" scope="cd">
  271. <parameter expr="assoc_name"/>
  272. </raise>
  273. <script>
  274. self.assoc_type = None
  275. </script>
  276. </transition>
  277. </state>
  278. <state id="wait_for_response">
  279. <transition event="choice_result" target=".">
  280. <parameter name="result"/>
  281. <script>
  282. self.assoc_type = self.allowed_types[result]
  283. </script>
  284. </transition>
  285. <transition event="close_window" cond="self.assoc_type is not None" target="../../create">
  286. <raise event="delete_instance" scope="cd">
  287. <parameter expr="'prompt'"/>
  288. </raise>
  289. </transition>
  290. <transition event="close_window" cond="self.assoc_type is None" target="../../../../ready">
  291. <raise event="delete_instance" scope="cd">
  292. <parameter expr="'prompt'"/>
  293. </raise>
  294. </transition>
  295. </state>
  296. </state>
  297. <state id="create">
  298. <onentry>
  299. <raise event="mv_request" scope="broad">
  300. <parameter expr="'instantiate'"/>
  301. <parameter expr="[current_model, self.assoc_type, (self.creating_line[1], self.creating_line[3]), '']"/>
  302. </raise>
  303. </onentry>
  304. <transition event="mv_response" target="../../../waiting_for_clear">
  305. <parameter name="ID"/>
  306. <raise event="minimal_rerender_model" scope="narrow" target="'parent'"/>
  307. </transition>
  308. <transition event="mv_exception" target="../../../ready">
  309. <parameter name="ID"/>
  310. <parameter name="exception_name"/>
  311. <parameter name="description"/>
  312. <raise event="errorlog_log" scope="broad">
  313. <parameter expr="'Could not instantiate element: %s -- %s' % (exception_name, description)"/>
  314. </raise>
  315. </transition>
  316. </state>
  317. </state>
  318. </state>
  319. <state id="creating_group">
  320. <transition event="instance_created" target="../wait_canvas_element_ready">
  321. <parameter name="assoc_name"/>
  322. <raise event="start_instance" scope="cd">
  323. <parameter expr="assoc_name"/>
  324. </raise>
  325. <script>
  326. self.assoc_links[self.creating_id] = assoc_name
  327. </script>
  328. </transition>
  329. </state>
  330. <state id="wait_canvas_element_ready">
  331. <transition event="moved_group" target=".">
  332. <parameter name="group_element"/>
  333. <parameter name="new_location"/>
  334. <script>
  335. self.group_location[group_element] = new_location
  336. </script>
  337. <raise event="moved_element" scope="narrow" target="'connecting_lines'">
  338. <parameter expr="group_element"/>
  339. <parameter expr="new_location"/>
  340. </raise>
  341. </transition>
  342. <transition event="canvas_element_ready" target="../ready">
  343. <raise event="group_ready" scope="narrow" target="'parent'"/>
  344. </transition>
  345. </state>
  346. <state id="creating_element">
  347. <onentry>
  348. <raise event="mv_request" scope="broad">
  349. <parameter expr="'instantiate'"/>
  350. <parameter expr="[current_model, self.currently_selected, None, '']"/>
  351. </raise>
  352. <script>
  353. self.elems.append([0, self.create_image(self.last_x, self.last_y, image=self.loading[0])])
  354. </script>
  355. </onentry>
  356. <transition event="mv_response" target="../waiting_for_clear">
  357. <parameter name="ID"/>
  358. <script>
  359. self.to_move[ID] = self.create_location
  360. </script>
  361. <raise event="minimal_rerender_model" scope="narrow" target="'parent'"/>
  362. </transition>
  363. <transition event="mv_exception" target="../ready">
  364. <parameter name="ID"/>
  365. <parameter name="exception_name"/>
  366. <parameter name="description"/>
  367. <raise event="errorlog_log" scope="broad">
  368. <parameter expr="'Could not instantiate element: %s -- %s' % (exception_name, description)"/>
  369. </raise>
  370. </transition>
  371. </state>
  372. <state id="waiting_for_clear"/>
  373. <transition event="clear_canvas" target="ready">
  374. <raise event="delete_instance" scope="cd">
  375. <parameter expr="'elements'"/>
  376. </raise>
  377. <raise event="delete_instance" scope="cd">
  378. <parameter expr="'connecting_lines'"/>
  379. </raise>
  380. <script>
  381. for f in self.elems:
  382. self.delete(f[1])
  383. if self.tmp_line is not None:
  384. self.delete(self.tmp_line)
  385. self.tmp_line = None
  386. self.elems = []
  387. self.group_location = {}
  388. self.layers = []
  389. </script>
  390. </transition>
  391. </state>
  392. <state id="update_loading">
  393. <state id="updating">
  394. <transition after="self.sccd_yield() + 0.1" target=".">
  395. <script>
  396. for i in self.elems:
  397. self.itemconfigure(i[1], image=self.loading[i[0]])
  398. i[0] = (i[0] + 1) % 8
  399. </script>
  400. </transition>
  401. </state>
  402. </state>
  403. </parallel>
  404. </scxml>
  405. </class>