canvas_element.xml 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <class name="CanvasElement">
  2. <relationships>
  3. <association name="parent" class="A" min="1" max="1" />
  4. <inheritance class="SCCDWidget" priority='0'/>
  5. <association name="elements" class="CanvasElement"/>
  6. <association name="prompt" class="PromptWindow"/>
  7. </relationships>
  8. <constructor>
  9. <parameter name="parent"/>
  10. <parameter name="coordinates"/>
  11. <parameter name="cs_element"/>
  12. <parameter name="as_element"/>
  13. <super class="SCCDWidget">
  14. <parameter expr="True"/>
  15. </super>
  16. <body>
  17. self.containing_canvas = parent
  18. self.coordinates = coordinates
  19. self.elements = {}
  20. self.tmp = {}
  21. self.cs_element = cs_element
  22. self.as_element = as_element
  23. self.diff_results = {}
  24. </body>
  25. </constructor>
  26. <destructor>
  27. <body>
  28. for f in self.elements:
  29. self.containing_canvas.delete(f)
  30. </body>
  31. </destructor>
  32. <scxml initial="main">
  33. <state id="main">
  34. <transition event="draw_element" target=".">
  35. <parameter name="element"/>
  36. <script>
  37. elem_x = self.coordinates[0] + element["x"]
  38. elem_y = self.coordinates[1] + element["y"]
  39. if element["type"] == "Rectangle":
  40. result = self.containing_canvas.create_rectangle(elem_x, elem_y, elem_x + element["width"], elem_y + element["height"], fill=element["fillColour"], outline=element["lineColour"])
  41. elif element["type"] == "Text":
  42. result = self.containing_canvas.create_text(elem_x, elem_y, fill=element["lineColour"], text=element["text"], anchor=tk.NW)
  43. elif element["type"] == "Line":
  44. result = self.containing_canvas.create_line(elem_x, elem_y, self.coordinates[0] + element["targetX"], self.coordinates[1] + element["targetY"], fill=element["lineColour"], width=element["lineWidth"], arrow=tk.LAST if element["arrow"] else tk.NONE)
  45. else:
  46. print("Undefined render format: " + str(element))
  47. result = None
  48. if result is not None:
  49. self.elements[result] = element["id"]
  50. self.set_bindable_and_tagorid(self.containing_canvas, result)
  51. </script>
  52. </transition>
  53. <transition event="left-click" cond="id(self) == ID" target="../dragging">
  54. <parameter name="ID"/>
  55. <script>
  56. self.original_coords = self.last_x, self.last_y
  57. self.prev_x = self.last_x
  58. self.prev_y = self.last_y
  59. </script>
  60. </transition>
  61. <transition event="middle-click" cond="id(self) == ID" target="../update_attrs">
  62. <parameter name="ID"/>
  63. </transition>
  64. </state>
  65. <state id="dragging">
  66. <transition event="motion" cond="id(self) == ID" target=".">
  67. <parameter name="ID"/>
  68. <script>
  69. delta_x = self.prev_x - self.last_x
  70. delta_y = self.prev_y - self.last_y
  71. for f in self.elements:
  72. old_coords = self.containing_canvas.coords(f)
  73. new_x = old_coords[0] - delta_x
  74. new_y = old_coords[1] - delta_y
  75. if len(old_coords) == 2:
  76. self.containing_canvas.coords(f, (new_x, new_y))
  77. elif len(old_coords) == 4:
  78. height = old_coords[3] - old_coords[1]
  79. width = old_coords[2] - old_coords[0]
  80. self.containing_canvas.coords(f, (new_x, new_y, new_x + width, new_y + height))
  81. self.prev_x = self.last_x
  82. self.prev_y = self.last_y
  83. delta_x = self.original_coords[0] - self.last_x
  84. delta_y = self.original_coords[1] - self.last_y
  85. </script>
  86. <raise event="moved_group" scope="narrow" target="'parent'">
  87. <parameter expr="self.cs_element"/>
  88. <parameter expr="(self.coordinates[0] - delta_x, self.coordinates[1] - delta_y)"/>
  89. </raise>
  90. </transition>
  91. <transition event="left-release" cond="id(self) == ID" target="../update_mv">
  92. <parameter name="ID"/>
  93. <script>
  94. delta_x = self.original_coords[0] - self.last_x
  95. delta_y = self.original_coords[1] - self.last_y
  96. self.coordinates = self.coordinates[0] - delta_x, self.coordinates[1] - delta_y
  97. </script>
  98. </transition>
  99. </state>
  100. <state id="update_attrs" initial="query">
  101. <state id="query">
  102. <onentry>
  103. <raise event="mv_request" scope="broad">
  104. <parameter expr="'read_attrs'"/>
  105. <parameter expr="[current_model, self.as_element]"/>
  106. </raise>
  107. </onentry>
  108. <transition event="mv_response" target="../prompt">
  109. <parameter name="result"/>
  110. <script>
  111. self.prev_results = result
  112. </script>
  113. </transition>
  114. </state>
  115. <state id="prompt">
  116. <onentry>
  117. <raise event="create_instance" scope="cd">
  118. <parameter expr="'prompt'"/>
  119. <parameter expr="'PromptWindow'"/>
  120. <parameter expr="self.prev_results"/>
  121. <parameter expr="{}"/>
  122. </raise>
  123. </onentry>
  124. <transition event="instance_created" target="../wait_for_results">
  125. <parameter name="name"/>
  126. <raise event="start_instance" scope="cd">
  127. <parameter expr="name"/>
  128. </raise>
  129. </transition>
  130. </state>
  131. <state id="wait_for_results">
  132. <transition event="prompt_results" target=".">
  133. <parameter name="results"/>
  134. <script>
  135. for k in results:
  136. if results[k] != self.prev_results[k]:
  137. self.diff_results[k] = json.loads(results[k])
  138. self.remaining_responses = len(self.diff_results)
  139. </script>
  140. </transition>
  141. <transition event="close_window" target="../process_results">
  142. <raise event="delete_instance" scope="cd">
  143. <parameter expr="'prompt'"/>
  144. </raise>
  145. </transition>
  146. </state>
  147. <state id="process_results">
  148. <transition cond="len(self.diff_results) > 0" target=".">
  149. <script>
  150. k, v = self.diff_results.popitem()
  151. </script>
  152. <raise event="mv_request" scope="broad">
  153. <parameter expr="'attr_assign'"/>
  154. <parameter expr="[current_model, self.as_element, k, v]"/>
  155. </raise>
  156. </transition>
  157. <transition cond="self.remaining_responses == 0" target="../mark_dirty"/>
  158. <transition event="mv_response" target=".">
  159. <script>
  160. self.remaining_responses -= 1
  161. </script>
  162. </transition>
  163. </state>
  164. <state id="mark_dirty">
  165. <onentry>
  166. <raise event="mv_request" scope="broad">
  167. <parameter expr="'attr_assign'"/>
  168. <parameter expr="[current_rendered_model, self.cs_element, 'dirty', True]"/>
  169. </raise>
  170. </onentry>
  171. <transition event="mv_response" target="../../main">
  172. <raise event="rerender_model" scope="narrow" target="'parent/parent'"/>
  173. </transition>
  174. </state>
  175. </state>
  176. <state id="update_mv" initial="x">
  177. <state id="x">
  178. <onentry>
  179. <raise event="mv_request" scope="broad">
  180. <parameter expr="'attr_assign'"/>
  181. <parameter expr="[current_rendered_model, self.cs_element, 'x', self.coordinates[0]]"/>
  182. </raise>
  183. </onentry>
  184. <transition event="mv_response" target="../y"/>
  185. </state>
  186. <state id="y">
  187. <onentry>
  188. <raise event="mv_request" scope="broad">
  189. <parameter expr="'attr_assign'"/>
  190. <parameter expr="[current_rendered_model, self.cs_element, 'y', self.coordinates[1]]"/>
  191. </raise>
  192. </onentry>
  193. <transition event="mv_response" target="../../main"/>
  194. </state>
  195. </state>
  196. </scxml>
  197. </class>