<?xml version="1.0" ?>
<diagram author="Simon Van Mierlo" name="Particle Interaction">
    <description>
        Visualization of Particle Interaction Simulation
    </description>
    <top>
        import Tkinter as tk
        from tkinter_widget import TkinterWidget
    </top>
    <inport name="input"/>
    <inport name="output"/>
    <class name="MainApp" default="true">
        <relationships>
            <association name="fields" class="Field" />
        </relationships>
        <constructor>
            <parameter name="root" />
            <parameter name="resolution" />
            <body>
                self.nr_of_fields = 0
                self.root = root
                self.resolution = resolution
            </body>
        </constructor>
        <scxml initial="main">
            <parallel id="main">
                <state id="main_behaviour" initial="initializing">
                    <state id="initializing">
                        <onentry>
                            <raise event="create_field" scope="local" />
                        </onentry>
                        <transition target="../running" />
                    </state>
                    <state id="running">
                        <transition event="field_created" target=".">
                            <script>
                                self.nr_of_fields += 1
                            </script>
                        </transition>
                        <transition event="field_deleted" target="." cond="self.nr_of_fields > 1">
                            <script>
                                self.nr_of_fields -= 1
                            </script>
                        </transition>
                        <transition event="field_deleted" target="." cond="self.nr_of_fields == 1">
                            <raise event="stop" scope="local" />
                        </transition>
                    </state>
                </state>
                <state id="creating_behaviour" initial="waiting">
                    <state id="waiting">
                        <transition event="create_field" target="../creating">
                            <raise event="create_instance" scope="cd">
                                <parameter expr="'fields'" />
                                <parameter expr="'Field'" />
                                <parameter expr="self.resolution" />
                            </raise>
                        </transition>
                    </state>
                    <state id="creating">
                        <transition event="instance_created" target="../waiting">
                            <parameter name="association_name" />
                            <raise event="start_instance" scope="cd">
                                <parameter expr="association_name" />
                            </raise>
                            <raise event="set_association_name" scope="narrow" target="association_name">
                                <parameter expr="association_name" />
                            </raise>
                            <raise event="field_created" scope="local" />
                        </transition>
                    </state>
                </state>
                <state id="deleting_behaviour" initial="waiting">
                    <state id="waiting">
                        <transition event="delete_field" target="../deleting">
                            <parameter name="association_name" />
                            <raise event="delete_instance" scope="cd">
                                <parameter expr="association_name" />
                            </raise>
                        </transition>
                    </state>
                    <state id="deleting">
                        <transition event="instance_deleted" target="../waiting">
                            <raise event="field_deleted" scope="local" />
                        </transition>
                    </state>
                </state>
                <transition event="stop" target="../stopped" />
            </parallel>
            <state id="stopped">
                <onentry>
                    <script>
                        self.root.quit()
                    </script>
                </onentry>
            </state>
        </scxml>
    </class>
    <class name="Field">
        <relationships>
            <association name="parent" class="MainApp" min="1" max="1" />
            <association name="particles" class="Particle" />
            <inheritance class="tk.Toplevel" priority="1" />
            <inheritance class="TkinterWidget" priority="0" />
        </relationships>
        <constructor>
            <parameter name="resolution" type="tuple" />
            <super class="tk.Toplevel" />
            <super class="TkinterWidget">
                <parameter expr="True" />
            </super>
            <body>
                <![CDATA[                
                self.geometry('{}x{}'.format(resolution[0], resolution[1]))                
                CANVAS_SIZE_TUPLE = (0, 0, self.winfo_screenwidth(), self.winfo_screenheight())
                self.canvas = tk.Canvas(self, relief=tk.RIDGE, scrollregion=CANVAS_SIZE_TUPLE)
                self.canvas.focus_force()
                self.canvas.pack(expand = True, fill=tk.BOTH)
                self.text = self.canvas.create_text(5, 5, anchor='nw', text="TIME: %s" % 0.0)
                self.title('Particle Interaction')
                
                self.particles = {}
                self.creates = []
                self.moves = []
                self.color_changes = []
                self.deletes = []
                self.new_particle_id = None
                
                self.set_bindable_and_tagorid(self.canvas)
                
                self.positions = {}
                self.curr_positions = {}
                ]]>
            </body>
        </constructor>
        <destructor>
            <body>
                self.destroy()
            </body>
        </destructor>
        <scxml initial="main">
            <parallel id="main">
                <state id="main_behaviour" initial="initializing">
                    <state id="initializing">
                        <transition event="set_association_name" target="../running">
                            <parameter name="association_name" />
                            <script>
                                self.association_name = association_name
                            </script>
                        </transition>
                    </state>
                    <state id="running">
                        <transition event="window-close" port="input" target="." cond="tagorid == id(self)">
                            <parameter name="tagorid" type="int" default="None" />
                            <raise event="stop" scope="local" />
                        </transition>
                    </state>
                </state>
                <state id="creating_behaviour" initial="idle">
                    <state id="idle">
                        <transition target="../creating_particle" event="create_particle">
                            <parameter name="new_particle_info" />
                            <raise event="create_instance" scope="cd">
                                <parameter expr='"particles"' />
                                <parameter expr='"Particle"' />
                                <parameter expr="self.canvas" />
                                <parameter expr="new_particle_info[0]" />
                                <parameter expr="new_particle_info[1][0]" />
                                <parameter expr="new_particle_info[1][1]" />
                                <parameter expr="new_particle_info[2]" />
                            </raise>
                            <script>
                                self.new_particle_id = new_particle_info[0]
                            </script>
                        </transition>
                    </state>
                    <state id="creating_particle">
                        <transition event="instance_created" target="../idle">
                            <parameter name="association_name" type="string"/>
                            <raise event="start_instance" scope="cd">
                                <parameter expr="association_name" />
                            </raise>
                            <raise event="set_association_name" scope="narrow" target="association_name">
                                <parameter expr="association_name" />
                            </raise>
                            <script>
                                self.particles[self.new_particle_id] = association_name
                            </script>
                        </transition>
                    </state>
                </state>
                <state id="listening_behaviour" initial="listening">
                    <state id="listening">
                        <transition target="." port="input" event="update_time">
                            <parameter name="new_time" />
                            <script>
                                self.canvas.itemconfig(self.text, text=new_time)
                            </script>
                        </transition>
                        <transition target="." port="input" event="create_particle">
                            <parameter name="params" />
                            <raise event="create_particle">
                                <parameter expr="params" />
                            </raise>
                        </transition>
                        <transition target="." port="input" event="delete_particle">
                            <parameter name="particle_id" />
                            <raise event="delete_instance" scope="cd">
                                <parameter expr="self.particles[particle_id]" />
                            </raise>
                            <script>
                                del self.particles[particle_id]
                            </script>
                        </transition>
                        <transition target="." port="input" event="delete">
                            <parameter name="clicked_id" type="int" />
                            <raise event="delete_selected" port="output" />
                        </transition>
                    </state>
                </state>
                <transition event="stop" target="../stopped">
                    <raise event="delete_instance" scope="cd">
                        <parameter expr="'particles'" />
                    </raise>
                </transition>
            </parallel>
            <state id="stopped">
                <onentry>
                    <raise event="delete_field" scope="narrow" target="'parent'">
                        <parameter expr="self.association_name" />
                    </raise>
                </onentry>
            </state>
        </scxml>
    </class>
    <class name="Particle">
        <relationships>
            <association name="parent" class="Field" min="1" max="1" />
            <inheritance class="TkinterWidget" priority="0" />
        </relationships>
        <constructor>
            <parameter name="canvas" />
            <parameter name="particle_id" />
            <parameter name="x" />
            <parameter name="y" />
            <parameter name="r" />
            <super class="TkinterWidget">
                <parameter expr="True" />
            </super>
            <body>
                self.canvas = canvas
                self.x = x
                self.y = y
                self.r = r
                self.circle_id = self.canvas.create_oval(x - r, y - r, x + r, y + r, fill="red")
                self.middle_id = self.canvas.create_oval(x - 4, y - 4, x + 4, y + 4, fill="orange")
                self.set_bindable_and_tagorid(self.canvas, [self.circle_id, self.middle_id])
                self.particle_id = particle_id
            </body>
        </constructor>
        <destructor>
            <body>
                self.canvas.delete(self.circle_id)
                self.canvas.delete(self.middle_id)
            </body>
        </destructor>
        <scxml initial="initializing">
            <state id="initializing">
                <transition target="../running" event="set_association_name">
                    <parameter name="association_name" type="str" />
                    <script>
                        self.association_name = association_name
                    </script>
                </transition>
            </state>
            <state id="running">
                <transition target="." port="input" event="move_particle" cond="params[0] == self.particle_id">
                    <parameter name="params" />
                    <script>
                        x, y = params[1]
                        curr_pos = self.canvas.coords(self.circle_id)
                        self.canvas.move(self.circle_id, x - self.r - curr_pos[0], y - self.r - curr_pos[1])
                        curr_pos_middle = self.canvas.coords(self.middle_id)
                        self.canvas.move(self.middle_id, x - 4 - curr_pos_middle[0], y - 4 - curr_pos_middle[1])
                    </script>
                </transition>
                <transition target="." port="input" event="color_particle" cond="params[0] == self.particle_id">
                    <parameter name="params" />
                    <script>
                        self.canvas.itemconfig(self.circle_id, fill=params[1])
                    </script>
                </transition>
                <transition target="." port="input" event="left-click" cond="clicked_id == id(self)">
                    <parameter name="clicked_id" type="int" />
                    <raise event="particle_clicked" port="output">
                        <parameter expr="self.particle_id" />
                    </raise>
                </transition>
            </state>
            <state id="deleted" />
        </scxml>
    </class>
</diagram>