<?xml version="1.0" ?>
<diagram author="Simon Van Mierlo" name="ParticleInteraction">
    <description>
        Visualization of Particle Interaction Simulation
    </description>
    <inport name="ui" />
    <inport name="input" />
    <class name="MainApp" default="true">
        <relationships>
            <association name="fields" class="Field" />
        </relationships>
        <method name="MainApp">
            <parameter name="resolution" type="list" />
            <body>
            <![CDATA[
                this.nr_of_fields = 0
                this.resolution = resolution
                ui.bind_event(ui.window, ui.EVENTS.WINDOW_CLOSE, this.controller, 'window_close');
            ]]>
            </body>
        </method>
        <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>
                                this.nr_of_fields += 1
                            </script>
                        </transition>
                        <transition event="field_deleted" target="." cond="this.nr_of_fields > 1">
                            <script>
                                console.log('not stopped')
                            </script>
                            <script>
                                this.nr_of_fields -= 1
                            </script>
                        </transition>
                        <transition event="field_deleted" target="." cond="this.nr_of_fields == 1">
                            <script>
                                console.log('stopped')
                            </script>
                            <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="this.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>
                        <![CDATA[
                            ui.close_window(ui.window);
                        ]]>
                    </script>
                </onentry>
            </state>
        </scxml>
    </class>
    <class name="Field">
        <relationships>
            <association name="parent" class="MainApp" min="1" max="1" />
            <association name="particles" class="Particle" />
        </relationships>
        <method name="Field">
            <parameter name="resolution" type="list" />
            <body>
                <![CDATA[                
                this.field_window = ui.new_window(resolution[0] * 1.28, resolution[1] * 1.28);
                this.canvas = ui.append_canvas(this.field_window, resolution[0], resolution[1], {'background':'#eee'});
                this.text = this.canvas.add_text(5, 10, '0.0', {})
                ui.bind_event(this.field_window, ui.EVENTS.WINDOW_CLOSE, this.controller, 'window_close');
                ui.bind_event(this.field_window, ui.EVENTS.KEY_PRESS, this.controller, 'key_press');
                
                this.particles = {}
                this.creates = []
                this.moves = []
                this.color_changes = []
                this.deletes = []
                this.new_particle_id = undefined
                
                this.positions = {}
                this.curr_positions = {}
                ]]>
            </body>
        </method>
        <method name="~Field">
            <body>
            <![CDATA[
                ui.close_window(this.field_window);
            ]]>
            </body>
        </method>
        <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>
                                <![CDATA[
                                this.association_name = association_name
                                ]]>
                            </script>
                        </transition>
                    </state>
                    <state id="running">
                        <transition event="window_close" port="ui" target="." cond="window == this.field_window || window == ui.window">
                            <parameter name="window" type="Window"/>
                            <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="this.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>
                                <![CDATA[
                                this.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>
                                <![CDATA[
                                this.particles[this.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>
                                <![CDATA[
                                this.text.set_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="this.particles[particle_id]" />
                            </raise>
                            <script>
                                <![CDATA[
                                delete this.particles[particle_id]
                                ]]>
                            </script>
                        </transition>
                        <transition port="ui" target="." event="key_press" cond="key == ui.KEYCODES.DELETE &amp;&amp; active_window == this.field_window">
                            <parameter name="key" type="Key"/>
                            <parameter name="active_window" type="Window"/>
                            <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="this.association_name" />
                    </raise>
                </onentry>
            </state>
        </scxml>
    </class>
    <class name="Particle">
        <relationships>
            <association name="parent" class="Field" min="1" max="1" />
        </relationships>
		<inport name="particle_ui"/>
        <method name="Particle">
            <parameter name="canvas" />
            <parameter name="particle_id" />
            <parameter name="x" />
            <parameter name="y" />
            <parameter name="r" />
            <body>
                <![CDATA[
                this.canvas = canvas
                this.x = x
                this.y = y
                this.r = r
                this.circle_id = this.canvas.add_circle(x, y, r, {fill:"red"})
                this.middle_id = this.canvas.add_circle(x, y, 4, {fill:"orange"})
                this.particle_id = particle_id
                ui.bind_event(this.circle_id, ui.EVENTS.MOUSE_PRESS, this.controller, 'mouse_click', this.inports['particle_ui']);
                ]]>
            </body>
        </method>
        <method name="~Particle">
            <body>
                this.canvas.remove_element(this.circle_id)
                this.canvas.remove_element(this.middle_id)
            </body>
        </method>
        <scxml initial="initializing">
            <state id="initializing">
                <transition target="../running" event="set_association_name">
                    <parameter name="association_name" type="str" />
                    <script>
                        this.association_name = association_name
                    </script>
                </transition>
            </state>
            <state id="running">
                <transition target="." port="input" event="move_particle" cond="params[0] == this.particle_id">
                    <parameter name="params" />
                    <script>
                        var x = params[1][0]
                        var y = params[1][1]
                        this.circle_id.set_position(x, y)
                        this.middle_id.set_position(x, y)
                    </script>
                </transition>
                <transition target="." port="input" event="color_particle" cond="params[0] == this.particle_id">
                    <parameter name="params" />
                    <script>
                        this.circle_id.set_color(params[1])
                    </script>
                </transition>
                <transition target="." port="particle_ui" event="mouse_click" cond="button == ui.MOUSE_BUTTONS.LEFT">
                    <parameter name="x" type="int"/>
                    <parameter name="y" type="int"/>
                    <parameter  name="button" type="Button"/>
                    <raise event="particle_clicked" port="output">
                        <parameter expr="this.particle_id" />
                    </raise>
                </transition>
            </state>
            <state id="deleted" />
        </scxml>
    </class>
</diagram>