123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <class name="Canvas">
- <relationships>
- <association name="parent" class="A" min="1" max="1" />
- <inheritance class="SCCDWidget" priority='0'/>
- <inheritance class="tk.Canvas" priority='1'/>
- <association name="elements" class="CanvasElement"/>
- <association name="connecting_lines" class="ConnectingLines"/>
- <association name="prompt" class="ChoicePrompt"/>
- </relationships>
- <constructor>
- <parameter name="parent" />
- <super class="SCCDWidget"/>
- <super class="tk.Canvas">
- <parameter expr="parent" />
- <parameter expr="**{'scrollregion': (0, 0, parent.winfo_screenwidth()*2, parent.winfo_screenheight() * 2)}"/>
- </super>
- <body>
- vbar = tk.Scrollbar(self, orient=tk.VERTICAL)
- vbar.config(command=self.yview)
- vbar.pack(side=tk.RIGHT, fill=tk.Y, pady=(0, 16))
- hbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
- hbar.config(command=self.xview)
- hbar.pack(side=tk.BOTTOM, fill=tk.X)
- self.config(background='white', yscrollcommand=vbar.set, xscrollcommand=hbar.set)
- self.focus_set()
- self.assoc_links = {}
- self.element_group = {}
- self.group_location = {}
- self.connecting_lines = {}
- self.lines = set()
- self.layers = []
- self.to_move = {}
- self.elems = []
- self.tmp_line = None
- self.currently_selected = None
- self.loading = [tk.PhotoImage(file="icons/loading.gif", format="gif -index %i" % i) for i in range(8)]
- </body>
- </constructor>
- <destructor>
- <body>
- self.destroy()
- </body>
- </destructor>
- <scxml initial="main">
- <state id="main">
- <transition target="../ready">
- <raise event="tk_widget" scope="narrow" target="'parent'">
- <parameter expr="self"/>
- </raise>
- </transition>
- </state>
- <parallel id="ready">
- <state id="process_events" initial="ready">
- <state id="ready">
- <transition event="select_for_creation" target=".">
- <parameter name="element_name"/>
- <script>
- self.currently_selected = element_name
- </script>
- </transition>
- <transition event="right-click" cond="self.currently_selected is not None and id(self) == ID and not control_pressed" target="../creating_element">
- <parameter name="ID"/>
- <script>
- self.create_location = (self.last_x, self.last_y)
- </script>
- </transition>
- <transition event="create_line" target="../creating_line">
- <parameter name="cs_element"/>
- <parameter name="as_element"/>
- <parameter name="coordinates"/>
- <script>
- self.creating_line = (cs_element, as_element, coordinates)
- </script>
- </transition>
- <transition event="define_group" target="../creating_group">
- <parameter name="element"/>
- <script>
- self.creating_id = element["id"]
- self.group_location[element['id']] = (element['x'], element['y'])
- </script>
- <raise event="create_instance" scope="cd">
- <parameter expr="'elements'"/>
- <parameter expr="'CanvasElement'"/>
- <parameter expr="self"/>
- <parameter expr="(element['x'], element['y'])"/>
- <parameter expr="element['id']"/>
- <parameter expr="element['__asid']"/>
- </raise>
- </transition>
- <transition event="define_contains" target=".">
- <parameter name="element"/>
- <script>
- self.element_group[element["__target"]] = element["__source"]
- </script>
- </transition>
- <transition event="draw_canvas" cond="element['type'] != 'ConnectingLine'" target=".">
- <parameter name="element"/>
- <raise event="draw_element" scope="narrow" target="self.assoc_links[self.element_group[element['id']]]">
- <parameter expr="element"/>
- </raise>
- </transition>
- <transition event="draw_canvas" cond="element['type'] == 'ConnectingLine'" target=".">
- <parameter name="element"/>
- <raise event="create_instance" scope="cd">
- <parameter expr="'connecting_lines'"/>
- <parameter expr="'ConnectingLine'"/>
- <parameter expr="self"/>
- <parameter expr="element"/>
- </raise>
- </transition>
- <transition event="instance_created" target=".">
- <parameter name="result"/>
- <raise event="start_instance" scope="cd">
- <parameter expr="result"/>
- </raise>
- </transition>
- <transition event="moved_group" target=".">
- <parameter name="group_element"/>
- <parameter name="new_location"/>
- <script>
- self.group_location[group_element] = new_location
- </script>
- <raise event="moved_element" scope="narrow" target="'connecting_lines'">
- <parameter expr="group_element"/>
- <parameter expr="new_location"/>
- </raise>
- </transition>
- <transition event="deleted_group" target=".">
- <parameter name="group_element"/>
- <script>
- del self.group_location[group_element]
- print("Remove group_location " + str(group_element))
- </script>
- <raise event="deleted_element" scope="narrow" target="'connecting_lines'">
- <parameter expr="group_element"/>
- </raise>
- </transition>
- </state>
- <state id="creating_line" initial="drawing">
- <onentry>
- <script>
- self.tmp_line = self.create_line(self.creating_line[2][0], self.creating_line[2][1], self.last_x, self.last_y)
- </script>
- </onentry>
- <state id="drawing">
- <transition event="motion" target=".">
- <script>
- x, y, _, _ = self.coords(self.tmp_line)
- # NOTE: make sure that you can not click on the temporary line itself
- if x > self.last_x:
- self.last_x += 2
- else:
- self.last_x -= 2
- if y > self.last_y:
- self.last_y += 2
- else:
- self.last_y -= 2
- self.coords(self.tmp_line, x, y, self.last_x, self.last_y)
- </script>
- </transition>
- <transition event="right-click" cond="ID == id(self) and not control_pressed" target="../../ready">
- <parameter name="ID"/>
- <script>
- self.delete(self.tmp_line)
- self.tmp_line = None
- </script>
- </transition>
- <transition event="create_line" target="../create_in_mv">
- <parameter name="cs_element"/>
- <parameter name="as_element"/>
- <script>
- origin_cs, origin_as, _ = self.creating_line
- self.creating_line = (origin_cs, origin_as, cs_element, as_element)
- </script>
- </transition>
- </state>
- <state id="create_in_mv" initial="query_type">
- <state id="query_type">
- <onentry>
- <raise event="mv_request" scope="broad">
- <parameter expr="'connections_between'"/>
- <parameter expr="[current_model, self.creating_line[1], self.creating_line[3]]"/>
- </raise>
- </onentry>
- <transition event="mv_response" target="../check_types">
- <parameter name="result"/>
- <script>
- self.allowed_types = result
- </script>
- </transition>
- </state>
- <state id="check_types">
- <transition cond="len(self.allowed_types) == 0" target="../../../ready"/>
- <transition cond="len(self.allowed_types) == 1" target="../create">
- <script>
- self.assoc_type = self.allowed_types.pop()
- </script>
- </transition>
- <transition cond="len(self.allowed_types) > 1" target="../request_user">
- <script>
- self.allowed_types = list(self.allowed_types)
- </script>
- </transition>
- </state>
- <state id="request_user" initial="check_next">
- <onentry>
- <script>
- self.new_allowed_types = {}
- </script>
- </onentry>
- <state id="check_next">
- <transition cond="len(self.allowed_types) > 0" target="../convert_to_name"/>
- <transition cond="len(self.allowed_types) == 0" target="../request">
- <script>
- self.allowed_types = self.new_allowed_types
- </script>
- </transition>
- </state>
- <state id="convert_to_name">
- <onentry>
- <raise event="mv_request" scope="broad">
- <parameter expr="'read_attrs'"/>
- <parameter expr="[current_metamodel, self.allowed_types[0]]"/>
- </raise>
- </onentry>
- <transition event="mv_response" target="../check_next">
- <parameter name="result"/>
- <script>
- if 'name' in result and result['name'] is not None:
- self.new_allowed_types[result['name']] = self.allowed_types[0]
- self.allowed_types.pop(0)
- </script>
- </transition>
- </state>
- <state id="request">
- <onentry>
- <raise event="create_instance" scope="cd">
- <parameter expr="'prompt'"/>
- <parameter expr="'ChoicePrompt'"/>
- <parameter expr="'Pick desired link type:'"/>
- <parameter expr="self.allowed_types.keys()"/>
- </raise>
- </onentry>
- <transition event="instance_created" target="../wait_for_response">
- <parameter name="assoc_name"/>
- <raise event="start_instance" scope="cd">
- <parameter expr="assoc_name"/>
- </raise>
- <script>
- self.assoc_type = None
- </script>
- </transition>
- </state>
- <state id="wait_for_response">
- <transition event="choice_result" target=".">
- <parameter name="result"/>
- <script>
- self.assoc_type = self.allowed_types[result]
- </script>
- </transition>
- <transition event="close_window" cond="self.assoc_type is not None" target="../../create">
- <raise event="delete_instance" scope="cd">
- <parameter expr="'prompt'"/>
- </raise>
- </transition>
- <transition event="close_window" cond="self.assoc_type is None" target="../../../../ready">
- <raise event="delete_instance" scope="cd">
- <parameter expr="'prompt'"/>
- </raise>
- <script>
- self.delete(self.tmp_line)
- self.tmp_line = None
- </script>
- </transition>
- </state>
- </state>
- <state id="create">
- <onentry>
- <raise event="mv_request" scope="broad">
- <parameter expr="'instantiate'"/>
- <parameter expr="[current_model, self.assoc_type, (self.creating_line[1], self.creating_line[3]), '']"/>
- </raise>
- </onentry>
- <transition event="mv_response" target="../../../waiting_for_clear">
- <parameter name="ID"/>
- <raise event="minimal_rerender_model" scope="narrow" target="'parent'"/>
- </transition>
- </state>
- </state>
- </state>
- <state id="creating_group">
- <transition event="instance_created" target="../wait_canvas_element_ready">
- <parameter name="assoc_name"/>
- <raise event="start_instance" scope="cd">
- <parameter expr="assoc_name"/>
- </raise>
- <script>
- self.assoc_links[self.creating_id] = assoc_name
- </script>
- </transition>
- </state>
- <state id="wait_canvas_element_ready">
- <transition event="moved_group" target=".">
- <parameter name="group_element"/>
- <parameter name="new_location"/>
- <script>
- self.group_location[group_element] = new_location
- </script>
- <raise event="moved_element" scope="narrow" target="'connecting_lines'">
- <parameter expr="group_element"/>
- <parameter expr="new_location"/>
- </raise>
- </transition>
- <transition event="canvas_element_ready" target="../ready">
- <raise event="group_ready" scope="narrow" target="'parent'"/>
- </transition>
- </state>
- <state id="creating_element">
- <onentry>
- <raise event="mv_request" scope="broad">
- <parameter expr="'instantiate'"/>
- <parameter expr="[current_model, self.currently_selected, None, '']"/>
- </raise>
- <script>
- self.elems.append([0, self.create_image(self.last_x, self.last_y, image=self.loading[0])])
- </script>
- </onentry>
- <transition event="mv_response" target="../waiting_for_clear">
- <parameter name="ID"/>
- <script>
- self.to_move[ID] = self.create_location
- </script>
- <raise event="minimal_rerender_model" scope="narrow" target="'parent'"/>
- </transition>
- </state>
- <state id="waiting_for_clear"/>
- <transition event="clear_canvas" target="ready">
- <raise event="delete_instance" scope="cd">
- <parameter expr="'elements'"/>
- </raise>
- <raise event="delete_instance" scope="cd">
- <parameter expr="'connecting_lines'"/>
- </raise>
- <script>
- for f in self.elems:
- self.delete(f[1])
- if self.tmp_line is not None:
- self.delete(self.tmp_line)
- self.tmp_line = None
- self.elems = []
- self.group_location = {}
- self.layers = []
- </script>
- </transition>
- </state>
- <state id="update_loading">
- <state id="updating">
- <transition after="self.sccd_yield() + 0.1" target=".">
- <script>
- for i in self.elems:
- self.itemconfigure(i[1], image=self.loading[i[0]])
- i[0] = (i[0] + 1) % 8
- </script>
- </transition>
- </state>
- </state>
- </parallel>
- </scxml>
- </class>
|