Sam Pieters před 1 rokem
rodič
revize
17274898ab

+ 2 - 2
README.md

@@ -97,5 +97,5 @@ python3 runner.py
 ### Timer
 ### Timer
 
 
 ## TODO
 ## TODO
-1) Is there no < or > in the condition transition
-
+1) How to do in_ui??
+2) Problem with getInstances --> with dissacociate it thinks that it still exists

+ 0 - 1
examples/BouncingBalls/sccd.xml

@@ -350,7 +350,6 @@
                 <state id="creating_circle">
                 <state id="creating_circle">
                     <onentry>
                     <onentry>
                         <raise port="ui" event="create_circle">
                         <raise port="ui" event="create_circle">
-                            canvas_id, x, y, r, style, res_port
                             <parameter expr="self.canvas_id"/><!-- canvas_id -->
                             <parameter expr="self.canvas_id"/><!-- canvas_id -->
                             <parameter expr="self.pos['x']"/><!-- x -->
                             <parameter expr="self.pos['x']"/><!-- x -->
                             <parameter expr="self.pos['y']"/><!-- y -->
                             <parameter expr="self.pos['y']"/><!-- y -->

+ 9 - 1
examples/ElevatorBalls/PyDEVS/runner.py

@@ -15,7 +15,15 @@ class OutputListener:
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
 	model = target.Controller(name="controller")
 	model = target.Controller(name="controller")
-	refs = {"ui": model.in_ui, "field_ui": model.atomic0.field_ui, "floor_ui": model.atomic1.floor_ui, "elevator_ui": model.atomic2.elevator_ui, "ball_ui": model.atomic3.ball_ui}
+	refs = {
+		"ui": model.in_ui,  
+		"field_ui": model.atomic0.field_ui, 
+		"floor_ui": model.atomic1.floor_ui, 
+		"control_ui": model.atomic2.control_ui,
+		"button_ui": model.atomic3.button_ui,
+		"elevator_ui": model.atomic4.elevator_ui, 
+		"ball_ui": model.atomic5.ball_ui
+		}
 
 
 	tkroot = tk.Tk()
 	tkroot = tk.Tk()
 	tkroot.withdraw()
 	tkroot.withdraw()

+ 374 - 80
examples/ElevatorBalls/PyDEVS/target.py

@@ -14,7 +14,7 @@ import time
 CANVAS_DIMS = (800, 550)
 CANVAS_DIMS = (800, 550)
 FLOOR_LENGTH = 350
 FLOOR_LENGTH = 350
 FLOOR_SPACE = 50
 FLOOR_SPACE = 50
-FLOORS = 4
+FLOORS = 3
 
 
 # package "Elevator Balls"
 # package "Elevator Balls"
 
 
@@ -23,6 +23,7 @@ class MainAppInstance(RuntimeClassBase):
         RuntimeClassBase.__init__(self, atomdevs)
         RuntimeClassBase.__init__(self, atomdevs)
         self.associations = {}
         self.associations = {}
         self.associations["floor"] = Association("Floor", 2, -1)
         self.associations["floor"] = Association("Floor", 2, -1)
+        self.associations["controls"] = Association("ElevatorControls", 1, 1)
         self.associations["elevator"] = Association("Elevator", 1, 1)
         self.associations["elevator"] = Association("Elevator", 1, 1)
         
         
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
         self.semantics.big_step_maximality = StatechartSemantics.TakeMany
@@ -76,20 +77,28 @@ class MainAppInstance(RuntimeClassBase):
         # state /wait
         # state /wait
         self.states["/wait"] = State(4, "/wait", self)
         self.states["/wait"] = State(4, "/wait", self)
         
         
+        # state /create_controls
+        self.states["/create_controls"] = State(5, "/create_controls", self)
+        
+        # state /creating_controls
+        self.states["/creating_controls"] = State(6, "/creating_controls", self)
+        
         # state /create_elevator
         # state /create_elevator
-        self.states["/create_elevator"] = State(5, "/create_elevator", self)
+        self.states["/create_elevator"] = State(7, "/create_elevator", self)
         
         
         # state /creating
         # state /creating
-        self.states["/creating"] = State(6, "/creating", self)
+        self.states["/creating"] = State(8, "/creating", self)
         
         
         # state /waiting
         # state /waiting
-        self.states["/waiting"] = State(7, "/waiting", self)
+        self.states["/waiting"] = State(9, "/waiting", self)
         
         
         # add children
         # add children
         self.states[""].addChild(self.states["/creating_window"])
         self.states[""].addChild(self.states["/creating_window"])
         self.states[""].addChild(self.states["/creating_canvas"])
         self.states[""].addChild(self.states["/creating_canvas"])
         self.states[""].addChild(self.states["/create_floors"])
         self.states[""].addChild(self.states["/create_floors"])
         self.states[""].addChild(self.states["/wait"])
         self.states[""].addChild(self.states["/wait"])
+        self.states[""].addChild(self.states["/create_controls"])
+        self.states[""].addChild(self.states["/creating_controls"])
         self.states[""].addChild(self.states["/create_elevator"])
         self.states[""].addChild(self.states["/create_elevator"])
         self.states[""].addChild(self.states["/creating"])
         self.states[""].addChild(self.states["/creating"])
         self.states[""].addChild(self.states["/waiting"])
         self.states[""].addChild(self.states["/waiting"])
@@ -109,7 +118,7 @@ class MainAppInstance(RuntimeClassBase):
         self.states["/creating_canvas"].addTransition(_creating_canvas_0)
         self.states["/creating_canvas"].addTransition(_creating_canvas_0)
         
         
         # transition /create_floors
         # transition /create_floors
-        _create_floors_0 = Transition(self, self.states["/create_floors"], [self.states["/create_elevator"]])
+        _create_floors_0 = Transition(self, self.states["/create_floors"], [self.states["/create_controls"]])
         _create_floors_0.setTrigger(None)
         _create_floors_0.setTrigger(None)
         _create_floors_0.setGuard(self._create_floors_0_guard)
         _create_floors_0.setGuard(self._create_floors_0_guard)
         self.states["/create_floors"].addTransition(_create_floors_0)
         self.states["/create_floors"].addTransition(_create_floors_0)
@@ -128,6 +137,18 @@ class MainAppInstance(RuntimeClassBase):
         _wait_1.setTrigger(Event("instance_started", None))
         _wait_1.setTrigger(Event("instance_started", None))
         self.states["/wait"].addTransition(_wait_1)
         self.states["/wait"].addTransition(_wait_1)
         
         
+        # transition /create_controls
+        _create_controls_0 = Transition(self, self.states["/create_controls"], [self.states["/creating_controls"]])
+        _create_controls_0.setAction(self._create_controls_0_exec)
+        _create_controls_0.setTrigger(None)
+        self.states["/create_controls"].addTransition(_create_controls_0)
+        
+        # transition /creating_controls
+        _creating_controls_0 = Transition(self, self.states["/creating_controls"], [self.states["/create_elevator"]])
+        _creating_controls_0.setAction(self._creating_controls_0_exec)
+        _creating_controls_0.setTrigger(Event("instance_created", None))
+        self.states["/creating_controls"].addTransition(_creating_controls_0)
+        
         # transition /create_elevator
         # transition /create_elevator
         _create_elevator_0 = Transition(self, self.states["/create_elevator"], [self.states["/creating"]])
         _create_elevator_0 = Transition(self, self.states["/create_elevator"], [self.states["/creating"]])
         _create_elevator_0.setAction(self._create_elevator_0_exec)
         _create_elevator_0.setAction(self._create_elevator_0_exec)
@@ -170,6 +191,13 @@ class MainAppInstance(RuntimeClassBase):
         association_name = parameters[0]
         association_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
     
     
+    def _create_controls_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "controls", "ElevatorControls", self.canvas_id]))
+    
+    def _creating_controls_0_exec(self, parameters):
+        association_name = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
+    
     def _create_elevator_0_exec(self, parameters):
     def _create_elevator_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("create_instance", None, [self, "elevator", "Elevator", self.canvas_id]))
         self.big_step.outputEventOM(Event("create_instance", None, [self, "elevator", "Elevator", self.canvas_id]))
     
     
@@ -189,6 +217,7 @@ class MainApp(ObjectManagerBase):
         self.input = self.addInPort("input")
         self.input = self.addInPort("input")
         self.output = self.addOutPort("ui")
         self.output = self.addOutPort("ui")
         self.outputs["floor"] = self.addOutPort("floor")
         self.outputs["floor"] = self.addOutPort("floor")
+        self.outputs["controls"] = self.addOutPort("controls")
         self.outputs["elevator"] = self.addOutPort("elevator")
         self.outputs["elevator"] = self.addOutPort("elevator")
         self.field_ui = self.addInPort("field_ui")
         self.field_ui = self.addInPort("field_ui")
         self.instances[self.next_instance] = MainAppInstance(self)
         self.instances[self.next_instance] = MainAppInstance(self)
@@ -281,10 +310,6 @@ class FloorInstance(RuntimeClassBase):
         _running_create_random_ball_0.setAction(self._running_create_random_ball_0_exec)
         _running_create_random_ball_0.setAction(self._running_create_random_ball_0_exec)
         _running_create_random_ball_0.setTrigger(Event("_0after"))
         _running_create_random_ball_0.setTrigger(Event("_0after"))
         self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_0)
         self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_0)
-        _running_create_random_ball_1 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
-        _running_create_random_ball_1.setAction(self._running_create_random_ball_1_exec)
-        _running_create_random_ball_1.setTrigger(Event("delete_ball", None))
-        self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_1)
         
         
         # transition /running/wait
         # transition /running/wait
         _running_wait_0 = Transition(self, self.states["/running/wait"], [self.states["/running/create_random_ball"]])
         _running_wait_0 = Transition(self, self.states["/running/wait"], [self.states["/running/create_random_ball"]])
@@ -304,10 +329,6 @@ class FloorInstance(RuntimeClassBase):
     def _running_create_random_ball_0_exec(self, parameters):
     def _running_create_random_ball_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, 10, self.pos['y']]))
         self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, 10, self.pos['y']]))
     
     
-    def _running_create_random_ball_1_exec(self, parameters):
-        association_name = parameters[0]
-        self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
-    
     def _running_wait_0_exec(self, parameters):
     def _running_wait_0_exec(self, parameters):
         association_name = parameters[0]
         association_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
@@ -331,6 +352,271 @@ class Floor(ObjectManagerBase):
         new_instance = FloorInstance(self, parameters[2], parameters[3])
         new_instance = FloorInstance(self, parameters[2], parameters[3])
         return new_instance
         return new_instance
 
 
+class ElevatorControlsInstance(RuntimeClassBase):
+    def __init__(self, atomdevs, canvas_id):
+        RuntimeClassBase.__init__(self, atomdevs)
+        self.associations = {}
+        self.associations["button"] = Association("ElevatorButton", 0, -1)
+        self.associations["balls"] = Association("Ball", 0, -1)
+        self.associations["parent"] = Association("Elevator", 1, 1)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        ElevatorControlsInstance.user_defined_constructor(self, canvas_id)
+        port_name = Ports.addInputPort("<narrow_cast>", self)
+        atomdevs.addInPort(port_name)
+        port_name = Ports.addInputPort("control_ui", self)
+        atomdevs.addInPort(port_name)
+        atomdevs.port_mappings[port_name] = atomdevs.next_instance
+        self.inports["control_ui"] = port_name
+    
+    def user_defined_constructor(self, canvas_id):
+        self.canvas_id = canvas_id;
+        self.button_num = FLOORS;
+        self.dim = {'x': 120, 'y': (50 + (FLOORS * 30))}
+        self.pos = {'x': CANVAS_DIMS[0] - ((self.dim['x'] / 2) + 10), 'y': (self.dim['y'] / 2) + 10}
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, "", self)
+        
+        # state /creating
+        self.states["/creating"] = State(1, "/creating", self)
+        
+        # state /creating/create_rect
+        self.states["/creating/create_rect"] = State(2, "/creating/create_rect", self)
+        self.states["/creating/create_rect"].setEnter(self._creating_create_rect_enter)
+        
+        # state /creating/create_buttons
+        self.states["/creating/create_buttons"] = State(3, "/creating/create_buttons", self)
+        
+        # state /creating/create_buttons/create_a_button
+        self.states["/creating/create_buttons/create_a_button"] = State(4, "/creating/create_buttons/create_a_button", self)
+        self.states["/creating/create_buttons/create_a_button"].setEnter(self._creating_create_buttons_create_a_button_enter)
+        
+        # state /creating/create_buttons/start_a_button
+        self.states["/creating/create_buttons/start_a_button"] = State(5, "/creating/create_buttons/start_a_button", self)
+        
+        # state /creating/create_buttons/check_next
+        self.states["/creating/create_buttons/check_next"] = State(6, "/creating/create_buttons/check_next", self)
+        
+        # state /running
+        self.states["/running"] = State(7, "/running", self)
+        
+        # add children
+        self.states[""].addChild(self.states["/creating"])
+        self.states[""].addChild(self.states["/running"])
+        self.states["/creating"].addChild(self.states["/creating/create_rect"])
+        self.states["/creating"].addChild(self.states["/creating/create_buttons"])
+        self.states["/creating/create_buttons"].addChild(self.states["/creating/create_buttons/create_a_button"])
+        self.states["/creating/create_buttons"].addChild(self.states["/creating/create_buttons/start_a_button"])
+        self.states["/creating/create_buttons"].addChild(self.states["/creating/create_buttons/check_next"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/creating"]
+        self.states["/creating"].default_state = self.states["/creating/create_rect"]
+        self.states["/creating/create_buttons"].default_state = self.states["/creating/create_buttons/create_a_button"]
+        
+        # transition /creating/create_rect
+        _creating_create_rect_0 = Transition(self, self.states["/creating/create_rect"], [self.states["/creating/create_buttons"]])
+        _creating_create_rect_0.setTrigger(None)
+        self.states["/creating/create_rect"].addTransition(_creating_create_rect_0)
+        
+        # transition /creating/create_buttons/create_a_button
+        _creating_create_buttons_create_a_button_0 = Transition(self, self.states["/creating/create_buttons/create_a_button"], [self.states["/creating/create_buttons/start_a_button"]])
+        _creating_create_buttons_create_a_button_0.setAction(self._creating_create_buttons_create_a_button_0_exec)
+        _creating_create_buttons_create_a_button_0.setTrigger(Event("instance_created", None))
+        self.states["/creating/create_buttons/create_a_button"].addTransition(_creating_create_buttons_create_a_button_0)
+        
+        # transition /creating/create_buttons/start_a_button
+        _creating_create_buttons_start_a_button_0 = Transition(self, self.states["/creating/create_buttons/start_a_button"], [self.states["/creating/create_buttons/check_next"]])
+        _creating_create_buttons_start_a_button_0.setTrigger(Event("instance_started", None))
+        self.states["/creating/create_buttons/start_a_button"].addTransition(_creating_create_buttons_start_a_button_0)
+        
+        # transition /creating/create_buttons/check_next
+        _creating_create_buttons_check_next_0 = Transition(self, self.states["/creating/create_buttons/check_next"], [self.states["/creating/create_buttons/create_a_button"]])
+        _creating_create_buttons_check_next_0.setAction(self._creating_create_buttons_check_next_0_exec)
+        _creating_create_buttons_check_next_0.setTrigger(None)
+        _creating_create_buttons_check_next_0.setGuard(self._creating_create_buttons_check_next_0_guard)
+        self.states["/creating/create_buttons/check_next"].addTransition(_creating_create_buttons_check_next_0)
+        _creating_create_buttons_check_next_1 = Transition(self, self.states["/creating/create_buttons/check_next"], [self.states["/running"]])
+        _creating_create_buttons_check_next_1.setTrigger(None)
+        _creating_create_buttons_check_next_1.setGuard(self._creating_create_buttons_check_next_1_guard)
+        self.states["/creating/create_buttons/check_next"].addTransition(_creating_create_buttons_check_next_1)
+        
+        # transition /running
+        _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_0.setAction(self._running_0_exec)
+        _running_0.setTrigger(Event("button_pressed", None))
+        self.states["/running"].addTransition(_running_0)
+    
+    def _creating_create_rect_enter(self):
+        self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'grey', 'outline': 'black'}, self.inports['control_ui']]))
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], 20, 'Elevator Controls', self.inports['control_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [self.canvas_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['control_ui']]))
+    
+    def _creating_create_buttons_create_a_button_enter(self):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "button", "ElevatorButton", self.canvas_id, self.button_num]))
+    
+    def _creating_create_buttons_create_a_button_0_exec(self, parameters):
+        association_name = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
+    
+    def _creating_create_buttons_check_next_0_exec(self, parameters):
+        self.button_num -= 1
+    
+    def _creating_create_buttons_check_next_0_guard(self, parameters):
+        return self.button_num != 0
+    
+    def _creating_create_buttons_check_next_1_guard(self, parameters):
+        return self.button_num == 0
+    
+    def _running_0_exec(self, parameters):
+        floor = parameters[0]
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("move_elevator", None, [0])]))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/creating"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ElevatorControls(ObjectManagerBase):
+    def __init__(self, name):
+        ObjectManagerBase.__init__(self, name)
+        self.input = self.addInPort("input")
+        self.output = self.addOutPort("ui")
+        self.outputs["button"] = self.addOutPort("button")
+        self.outputs["balls"] = self.addOutPort("balls")
+        self.outputs["parent"] = self.addOutPort("parent")
+        self.control_ui = self.addInPort("control_ui")
+    
+    def constructObject(self, parameters):
+        new_instance = ElevatorControlsInstance(self, parameters[2])
+        return new_instance
+
+class ElevatorButtonInstance(RuntimeClassBase):
+    def __init__(self, atomdevs, canvas_id, number):
+        RuntimeClassBase.__init__(self, atomdevs)
+        self.associations = {}
+        self.associations["parent"] = Association("ElevatorControls", 1, 1)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        ElevatorButtonInstance.user_defined_constructor(self, canvas_id, number)
+        port_name = Ports.addInputPort("<narrow_cast>", self)
+        atomdevs.addInPort(port_name)
+        port_name = Ports.addInputPort("button_ui", self)
+        atomdevs.addInPort(port_name)
+        atomdevs.port_mappings[port_name] = atomdevs.next_instance
+        self.inports["button_ui"] = port_name
+    
+    def user_defined_constructor(self, canvas_id, number):
+        self.canvas_id = canvas_id;
+        self.button_id = None;
+        
+        self.dim = {'x': 120, 'y': (50 + (FLOORS * 30))}
+        self.pos = {'x': CANVAS_DIMS[0] - ((self.dim['x'] / 2) + 10), 'y': (self.dim['y'] / 2) + 10}
+        self.r = 10
+        self.number = number;
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, "", self)
+        
+        # state /creating
+        self.states["/creating"] = State(1, "/creating", self)
+        self.states["/creating"].setEnter(self._creating_enter)
+        
+        # state /running
+        self.states["/running"] = State(2, "/running", self)
+        
+        # add children
+        self.states[""].addChild(self.states["/creating"])
+        self.states[""].addChild(self.states["/running"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/creating"]
+        
+        # transition /creating
+        _creating_0 = Transition(self, self.states["/creating"], [self.states["/running"]])
+        _creating_0.setAction(self._creating_0_exec)
+        _creating_0.setTrigger(Event("circle_created", None))
+        self.states["/creating"].addTransition(_creating_0)
+        
+        # transition /running
+        _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_0.setAction(self._running_0_exec)
+        _running_0.setTrigger(Event("button_click", self.getInPortName("button_ui")))
+        _running_0.setGuard(self._running_0_guard)
+        self.states["/running"].addTransition(_running_0)
+    
+    def _creating_enter(self):
+        self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, CANVAS_DIMS[0] - 70, 45 + (30 * (FLOORS - self.number)) , 10, {'fill':'black', 'outline': 'black'}, self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, CANVAS_DIMS[0] - 70, 45 + (30 * (FLOORS - self.number)) , str(self.number), self.inports['button_ui']]))
+    
+    def _creating_0_exec(self, parameters):
+        canvas_id = parameters[0]
+        circle_id = parameters[1]
+        self.button_id = circle_id
+        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'button_click', self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['button_ui']]))
+    
+    def _running_0_exec(self, parameters):
+        x = parameters[0]
+        y = parameters[1]
+        button = parameters[2]
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("button_pressed", None, [self.number])]))
+        self.big_step.outputEvent(Event("set_element_color", self.getOutPortName("ui"), [self.canvas_id, self.button_id, '#ff0']))
+    
+    def _running_0_guard(self, parameters):
+        x = parameters[0]
+        y = parameters[1]
+        button = parameters[2]
+        return button == ui.MOUSE_BUTTONS.LEFT
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/creating"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ElevatorButton(ObjectManagerBase):
+    def __init__(self, name):
+        ObjectManagerBase.__init__(self, name)
+        self.input = self.addInPort("input")
+        self.output = self.addOutPort("ui")
+        self.outputs["parent"] = self.addOutPort("parent")
+        self.button_ui = self.addInPort("button_ui")
+    
+    def constructObject(self, parameters):
+        new_instance = ElevatorButtonInstance(self, parameters[2], parameters[3])
+        return new_instance
+
 class ElevatorInstance(RuntimeClassBase):
 class ElevatorInstance(RuntimeClassBase):
     def __init__(self, atomdevs, canvas_id):
     def __init__(self, atomdevs, canvas_id):
         RuntimeClassBase.__init__(self, atomdevs)
         RuntimeClassBase.__init__(self, atomdevs)
@@ -363,19 +649,14 @@ class ElevatorInstance(RuntimeClassBase):
     
     
     def user_defined_constructor(self, canvas_id):
     def user_defined_constructor(self, canvas_id):
         self.canvas_id = canvas_id;
         self.canvas_id = canvas_id;
-        self.button_ids = {
-            'up': None,
-            'down': None,
-            'open': None
-        };
-        self.open_button = None;
+        
         self.is_open = False;
         self.is_open = False;
         
         
         elevator_height = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
         elevator_height = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
         
         
         self.dim = {'x': elevator_height, 'y': elevator_height};
         self.dim = {'x': elevator_height, 'y': elevator_height};
-        self.vel = {'x': 0, 'y': -2};
-        self.pos = {'x': FLOOR_LENGTH + (elevator_height / 2), 'y': 75};
+        self.vel = -2;
+        self.pos = {'x': FLOOR_LENGTH + (elevator_height / 2), 'y': (CANVAS_DIMS[1] - (elevator_height / 2))};
         self.smooth = 0.6; # value between 0 and 1
         self.smooth = 0.6; # value between 0 and 1
     
     
     def user_defined_destructor(self):
     def user_defined_destructor(self):
@@ -400,17 +681,26 @@ class ElevatorInstance(RuntimeClassBase):
         
         
         # state /root/running
         # state /root/running
         self.states["/root/running"] = State(4, "/root/running", self)
         self.states["/root/running"] = State(4, "/root/running", self)
-        self.states["/root/running"].setEnter(self._root_running_enter)
-        self.states["/root/running"].setExit(self._root_running_exit)
+        
+        # state /root/running/waiting
+        self.states["/root/running/waiting"] = State(5, "/root/running/waiting", self)
+        
+        # state /root/running/move
+        self.states["/root/running/move"] = State(6, "/root/running/move", self)
+        self.states["/root/running/move"].setEnter(self._root_running_move_enter)
+        self.states["/root/running/move"].setExit(self._root_running_move_exit)
         
         
         # add children
         # add children
         self.states[""].addChild(self.states["/root"])
         self.states[""].addChild(self.states["/root"])
         self.states["/root"].addChild(self.states["/root/waiting"])
         self.states["/root"].addChild(self.states["/root/waiting"])
         self.states["/root"].addChild(self.states["/root/creating_elevator"])
         self.states["/root"].addChild(self.states["/root/creating_elevator"])
         self.states["/root"].addChild(self.states["/root/running"])
         self.states["/root"].addChild(self.states["/root/running"])
+        self.states["/root/running"].addChild(self.states["/root/running/waiting"])
+        self.states["/root/running"].addChild(self.states["/root/running/move"])
         self.states[""].fixTree()
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/root"]
         self.states[""].default_state = self.states["/root"]
         self.states["/root"].default_state = self.states["/root/waiting"]
         self.states["/root"].default_state = self.states["/root/waiting"]
+        self.states["/root/running"].default_state = self.states["/root/running/waiting"]
         
         
         # transition /root/waiting
         # transition /root/waiting
         _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/creating_elevator"]])
         _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/creating_elevator"]])
@@ -424,27 +714,28 @@ class ElevatorInstance(RuntimeClassBase):
         _root_creating_elevator_0.setTrigger(Event("rectangle_created", None))
         _root_creating_elevator_0.setTrigger(Event("rectangle_created", None))
         self.states["/root/creating_elevator"].addTransition(_root_creating_elevator_0)
         self.states["/root/creating_elevator"].addTransition(_root_creating_elevator_0)
         
         
-        # transition /root/running
-        _root_running_0 = Transition(self, self.states["/root/running"], [self.states["/root/running"]])
-        _root_running_0.setAction(self._root_running_0_exec)
-        _root_running_0.setTrigger(Event("_0after"))
-        self.states["/root/running"].addTransition(_root_running_0)
-        _root_running_1 = Transition(self, self.states["/root/running"], [self.states["/root/running"]])
-        _root_running_1.setAction(self._root_running_1_exec)
-        _root_running_1.setTrigger(Event("right_click", self.getInPortName("elevator_ui")))
-        self.states["/root/running"].addTransition(_root_running_1)
-        _root_running_2 = Transition(self, self.states["/root/running"], [self.states["/root/running"]])
-        _root_running_2.setAction(self._root_running_2_exec)
-        _root_running_2.setTrigger(Event("instance_created", None))
-        self.states["/root/running"].addTransition(_root_running_2)
+        # transition /root/running/waiting
+        _root_running_waiting_0 = Transition(self, self.states["/root/running/waiting"], [self.states["/root/running/move"]])
+        _root_running_waiting_0.setTrigger(Event("move_elevator", None))
+        self.states["/root/running/waiting"].addTransition(_root_running_waiting_0)
+        
+        # transition /root/running/move
+        _root_running_move_0 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/move"]])
+        _root_running_move_0.setAction(self._root_running_move_0_exec)
+        _root_running_move_0.setTrigger(Event("_0after"))
+        self.states["/root/running/move"].addTransition(_root_running_move_0)
+        _root_running_move_1 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/waiting"]])
+        _root_running_move_1.setTrigger(None)
+        _root_running_move_1.setGuard(self._root_running_move_1_guard)
+        self.states["/root/running/move"].addTransition(_root_running_move_1)
     
     
     def _root_creating_elevator_enter(self):
     def _root_creating_elevator_enter(self):
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['elevator_ui']]))
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['elevator_ui']]))
     
     
-    def _root_running_enter(self):
+    def _root_running_move_enter(self):
         self.addTimer(0, 0.02)
         self.addTimer(0, 0.02)
     
     
-    def _root_running_exit(self):
+    def _root_running_move_exit(self):
         self.removeTimer(0)
         self.removeTimer(0)
     
     
     def _root_waiting_0_exec(self, parameters):
     def _root_waiting_0_exec(self, parameters):
@@ -459,27 +750,13 @@ class ElevatorInstance(RuntimeClassBase):
         canvas_id = parameters[0]
         canvas_id = parameters[0]
         rect_id = parameters[1]
         rect_id = parameters[1]
         self.elevator_id = rect_id
         self.elevator_id = rect_id
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RIGHT_CLICK, 'right_click', self.inports['elevator_ui']]))
     
     
-    def _root_running_0_exec(self, parameters):
-        # Invert velocity when colliding with canvas border:
-        if self.pos['y']-(self.dim['y']/2) <= 0 or self.pos['y']+(self.dim['y']/2) >= CANVAS_DIMS[1]:
-            self.vel['y'] = -self.vel['y'];
-        self.big_step.outputEvent(Event("move_element", self.getOutPortName("ui"), [self.canvas_id, self.elevator_id, self.vel['x'], self.vel['y']]))
-        self.pos['x'] += self.vel['x']
-        self.pos['y'] += self.vel['y']
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'balls', Event("update_bounds", None, [self.pos, self.dim, self.vel])]))
-    
-    def _root_running_1_exec(self, parameters):
-        x = parameters[0]
-        y = parameters[1]
-        button = parameters[2]
-        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, -1, x, y]))
+    def _root_running_move_0_exec(self, parameters):
+        self.big_step.outputEvent(Event("set_element_pos", self.getOutPortName("ui"), [self.canvas_id, self.elevator_id, self.pos['x'], self.pos['y']]))
+        self.pos['y'] += self.vel
     
     
-    def _root_running_2_exec(self, parameters):
-        association_name = parameters[0]
-        self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name])]))
+    def _root_running_move_1_guard(self, parameters):
+        return (self.pos['y'] - (self.dim['y']/2)) < 0
     
     
     def initializeStatechart(self):
     def initializeStatechart(self):
         # enter default state
         # enter default state
@@ -566,8 +843,11 @@ class BallInstance(RuntimeClassBase):
         # state /main_behaviour/selected
         # state /main_behaviour/selected
         self.states["/main_behaviour/selected"] = State(6, "/main_behaviour/selected", self)
         self.states["/main_behaviour/selected"] = State(6, "/main_behaviour/selected", self)
         
         
+        # state /main_behaviour/ball_delete
+        self.states["/main_behaviour/ball_delete"] = State(7, "/main_behaviour/ball_delete", self)
+        
         # state /deleted
         # state /deleted
-        self.states["/deleted"] = State(7, "/deleted", self)
+        self.states["/deleted"] = State(8, "/deleted", self)
         
         
         # add children
         # add children
         self.states[""].addChild(self.states["/main_behaviour"])
         self.states[""].addChild(self.states["/main_behaviour"])
@@ -577,6 +857,7 @@ class BallInstance(RuntimeClassBase):
         self.states["/main_behaviour"].addChild(self.states["/main_behaviour/bouncing"])
         self.states["/main_behaviour"].addChild(self.states["/main_behaviour/bouncing"])
         self.states["/main_behaviour"].addChild(self.states["/main_behaviour/dragging"])
         self.states["/main_behaviour"].addChild(self.states["/main_behaviour/dragging"])
         self.states["/main_behaviour"].addChild(self.states["/main_behaviour/selected"])
         self.states["/main_behaviour"].addChild(self.states["/main_behaviour/selected"])
+        self.states["/main_behaviour"].addChild(self.states["/main_behaviour/ball_delete"])
         self.states[""].fixTree()
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/main_behaviour"]
         self.states[""].default_state = self.states["/main_behaviour"]
         self.states["/main_behaviour"].default_state = self.states["/main_behaviour/initializing"]
         self.states["/main_behaviour"].default_state = self.states["/main_behaviour/initializing"]
@@ -598,8 +879,7 @@ class BallInstance(RuntimeClassBase):
         _main_behaviour_bouncing_0.setAction(self._main_behaviour_bouncing_0_exec)
         _main_behaviour_bouncing_0.setAction(self._main_behaviour_bouncing_0_exec)
         _main_behaviour_bouncing_0.setTrigger(Event("_0after"))
         _main_behaviour_bouncing_0.setTrigger(Event("_0after"))
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_0)
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_0)
-        _main_behaviour_bouncing_1 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/bouncing"]])
-        _main_behaviour_bouncing_1.setAction(self._main_behaviour_bouncing_1_exec)
+        _main_behaviour_bouncing_1 = Transition(self, self.states["/main_behaviour/bouncing"], [self.states["/main_behaviour/ball_delete"]])
         _main_behaviour_bouncing_1.setTrigger(None)
         _main_behaviour_bouncing_1.setTrigger(None)
         _main_behaviour_bouncing_1.setGuard(self._main_behaviour_bouncing_1_guard)
         _main_behaviour_bouncing_1.setGuard(self._main_behaviour_bouncing_1_guard)
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_1)
         self.states["/main_behaviour/bouncing"].addTransition(_main_behaviour_bouncing_1)
@@ -629,10 +909,12 @@ class BallInstance(RuntimeClassBase):
         _main_behaviour_selected_0.setTrigger(Event("mouse_press", self.getInPortName("ball_ui")))
         _main_behaviour_selected_0.setTrigger(Event("mouse_press", self.getInPortName("ball_ui")))
         _main_behaviour_selected_0.setGuard(self._main_behaviour_selected_0_guard)
         _main_behaviour_selected_0.setGuard(self._main_behaviour_selected_0_guard)
         self.states["/main_behaviour/selected"].addTransition(_main_behaviour_selected_0)
         self.states["/main_behaviour/selected"].addTransition(_main_behaviour_selected_0)
-        _main_behaviour_selected_1 = Transition(self, self.states["/main_behaviour/selected"], [self.states["/deleted"]])
-        _main_behaviour_selected_1.setAction(self._main_behaviour_selected_1_exec)
-        _main_behaviour_selected_1.setTrigger(Event("delete_self", None))
-        self.states["/main_behaviour/selected"].addTransition(_main_behaviour_selected_1)
+        
+        # transition /main_behaviour/ball_delete
+        _main_behaviour_ball_delete_0 = Transition(self, self.states["/main_behaviour/ball_delete"], [self.states["/deleted"]])
+        _main_behaviour_ball_delete_0.setAction(self._main_behaviour_ball_delete_0_exec)
+        _main_behaviour_ball_delete_0.setTrigger(Event("delete_self", None))
+        self.states["/main_behaviour/ball_delete"].addTransition(_main_behaviour_ball_delete_0)
     
     
     def _main_behaviour_creating_circle_enter(self):
     def _main_behaviour_creating_circle_enter(self):
         self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.r, {'fill':'#000'}, self.inports['ball_ui']]))
         self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.r, {'fill':'#000'}, self.inports['ball_ui']]))
@@ -694,11 +976,8 @@ class BallInstance(RuntimeClassBase):
         self.pos['x'] += self.vel['x']
         self.pos['x'] += self.vel['x']
         self.pos['y'] += self.vel['y']
         self.pos['y'] += self.vel['y']
     
     
-    def _main_behaviour_bouncing_1_exec(self, parameters):
-        self.big_step.outputEvent(Event("destroy_element", self.getOutPortName("ui"), [self.canvas_id, self.circle_id]))
-    
     def _main_behaviour_bouncing_1_guard(self, parameters):
     def _main_behaviour_bouncing_1_guard(self, parameters):
-        return self.pos['x'] - self.r < 6
+        return self.pos['x'] - self.r < 2
     
     
     def _main_behaviour_bouncing_2_exec(self, parameters):
     def _main_behaviour_bouncing_2_exec(self, parameters):
         x = parameters[0]
         x = parameters[0]
@@ -756,9 +1035,9 @@ class BallInstance(RuntimeClassBase):
         button = parameters[2]
         button = parameters[2]
         return button == ui.MOUSE_BUTTONS.LEFT
         return button == ui.MOUSE_BUTTONS.LEFT
     
     
-    def _main_behaviour_selected_1_exec(self, parameters):
+    def _main_behaviour_ball_delete_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_ball", None, [self.association_name])]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_ball", None, [self.association_name])]))
-        self.big_step.outputEvent(Event("destroy_element", self.getOutPortName("ui"), [self.canvas_id, self.element_id]))
+        self.big_step.outputEvent(Event("destroy_element", self.getOutPortName("ui"), [self.canvas_id, self.circle_id]))
     
     
     def initializeStatechart(self):
     def initializeStatechart(self):
         # enter default state
         # enter default state
@@ -788,6 +1067,8 @@ class ObjectManager(TheObjectManager):
         self.input = self.addInPort("input")
         self.input = self.addInPort("input")
         self.output["MainApp"] = self.addOutPort()
         self.output["MainApp"] = self.addOutPort()
         self.output["Floor"] = self.addOutPort()
         self.output["Floor"] = self.addOutPort()
+        self.output["ElevatorControls"] = self.addOutPort()
+        self.output["ElevatorButton"] = self.addOutPort()
         self.output["Elevator"] = self.addOutPort()
         self.output["Elevator"] = self.addOutPort()
         self.output["Ball"] = self.addOutPort()
         self.output["Ball"] = self.addOutPort()
 
 
@@ -801,24 +1082,37 @@ class Controller(CoupledDEVS):
         self.objectmanager = self.addSubModel(ObjectManager("ObjectManager"))
         self.objectmanager = self.addSubModel(ObjectManager("ObjectManager"))
         self.atomic0 = self.addSubModel(MainApp("MainApp"))
         self.atomic0 = self.addSubModel(MainApp("MainApp"))
         self.atomic1 = self.addSubModel(Floor("Floor"))
         self.atomic1 = self.addSubModel(Floor("Floor"))
-        self.atomic2 = self.addSubModel(Elevator("Elevator"))
-        self.atomic3 = self.addSubModel(Ball("Ball"))
+        self.atomic2 = self.addSubModel(ElevatorControls("ElevatorControls"))
+        self.atomic3 = self.addSubModel(ElevatorButton("ElevatorButton"))
+        self.atomic4 = self.addSubModel(Elevator("Elevator"))
+        self.atomic5 = self.addSubModel(Ball("Ball"))
         self.connectPorts(self.atomic0.obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.atomic0.obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["MainApp"], self.atomic0.obj_manager_in)
         self.connectPorts(self.objectmanager.output["MainApp"], self.atomic0.obj_manager_in)
         self.connectPorts(self.atomic0.outputs["floor"], self.atomic1.input)
         self.connectPorts(self.atomic0.outputs["floor"], self.atomic1.input)
-        self.connectPorts(self.atomic0.outputs["elevator"], self.atomic2.input)
+        self.connectPorts(self.atomic0.outputs["controls"], self.atomic2.input)
+        self.connectPorts(self.atomic0.outputs["elevator"], self.atomic4.input)
         self.connectPorts(self.atomic1.obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.atomic1.obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.objectmanager.output["Floor"], self.atomic1.obj_manager_in)
         self.connectPorts(self.objectmanager.output["Floor"], self.atomic1.obj_manager_in)
-        self.connectPorts(self.atomic1.outputs["balls"], self.atomic3.input)
+        self.connectPorts(self.atomic1.outputs["balls"], self.atomic5.input)
         self.connectPorts(self.atomic1.outputs["parent"], self.atomic0.input)
         self.connectPorts(self.atomic1.outputs["parent"], self.atomic0.input)
         self.connectPorts(self.atomic2.obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.atomic2.obj_manager_out, self.objectmanager.input)
-        self.connectPorts(self.objectmanager.output["Elevator"], self.atomic2.obj_manager_in)
-        self.connectPorts(self.atomic2.outputs["balls"], self.atomic3.input)
-        self.connectPorts(self.atomic2.outputs["parent"], self.atomic0.input)
+        self.connectPorts(self.objectmanager.output["ElevatorControls"], self.atomic2.obj_manager_in)
+        self.connectPorts(self.atomic2.outputs["button"], self.atomic3.input)
+        self.connectPorts(self.atomic2.outputs["balls"], self.atomic5.input)
+        self.connectPorts(self.atomic2.outputs["parent"], self.atomic4.input)
         self.connectPorts(self.atomic3.obj_manager_out, self.objectmanager.input)
         self.connectPorts(self.atomic3.obj_manager_out, self.objectmanager.input)
-        self.connectPorts(self.objectmanager.output["Ball"], self.atomic3.obj_manager_in)
-        self.connectPorts(self.atomic3.outputs["parent"], self.atomic0.input)
+        self.connectPorts(self.objectmanager.output["ElevatorButton"], self.atomic3.obj_manager_in)
+        self.connectPorts(self.atomic3.outputs["parent"], self.atomic2.input)
+        self.connectPorts(self.atomic4.obj_manager_out, self.objectmanager.input)
+        self.connectPorts(self.objectmanager.output["Elevator"], self.atomic4.obj_manager_in)
+        self.connectPorts(self.atomic4.outputs["balls"], self.atomic5.input)
+        self.connectPorts(self.atomic4.outputs["parent"], self.atomic0.input)
+        self.connectPorts(self.atomic5.obj_manager_out, self.objectmanager.input)
+        self.connectPorts(self.objectmanager.output["Ball"], self.atomic5.obj_manager_in)
+        self.connectPorts(self.atomic5.outputs["parent"], self.atomic0.input)
         self.connectPorts(self.atomic0.output, self.out_ui)
         self.connectPorts(self.atomic0.output, self.out_ui)
         self.connectPorts(self.atomic1.output, self.out_ui)
         self.connectPorts(self.atomic1.output, self.out_ui)
         self.connectPorts(self.atomic2.output, self.out_ui)
         self.connectPorts(self.atomic2.output, self.out_ui)
-        self.connectPorts(self.atomic3.output, self.out_ui)
+        self.connectPorts(self.atomic3.output, self.out_ui)
+        self.connectPorts(self.atomic4.output, self.out_ui)
+        self.connectPorts(self.atomic5.output, self.out_ui)

+ 102 - 63
examples/ElevatorBalls/Python/target.py

@@ -81,8 +81,8 @@ class MainApp(RuntimeClassBase):
         # state /creating
         # state /creating
         self.states["/creating"] = State(8, "/creating", self)
         self.states["/creating"] = State(8, "/creating", self)
         
         
-        # state /waiting
-        self.states["/waiting"] = State(9, "/waiting", self)
+        # state /running
+        self.states["/running"] = State(9, "/running", self)
         
         
         # add children
         # add children
         self.states[""].addChild(self.states["/creating_window"])
         self.states[""].addChild(self.states["/creating_window"])
@@ -93,7 +93,7 @@ class MainApp(RuntimeClassBase):
         self.states[""].addChild(self.states["/creating_controls"])
         self.states[""].addChild(self.states["/creating_controls"])
         self.states[""].addChild(self.states["/create_elevator"])
         self.states[""].addChild(self.states["/create_elevator"])
         self.states[""].addChild(self.states["/creating"])
         self.states[""].addChild(self.states["/creating"])
-        self.states[""].addChild(self.states["/waiting"])
+        self.states[""].addChild(self.states["/running"])
         self.states[""].fixTree()
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/creating_window"]
         self.states[""].default_state = self.states["/creating_window"]
         
         
@@ -148,10 +148,24 @@ class MainApp(RuntimeClassBase):
         self.states["/create_elevator"].addTransition(_create_elevator_0)
         self.states["/create_elevator"].addTransition(_create_elevator_0)
         
         
         # transition /creating
         # transition /creating
-        _creating_0 = Transition(self, self.states["/creating"], [self.states["/waiting"]])
+        _creating_0 = Transition(self, self.states["/creating"], [self.states["/running"]])
         _creating_0.setAction(self._creating_0_exec)
         _creating_0.setAction(self._creating_0_exec)
         _creating_0.setTrigger(Event("instance_created", None))
         _creating_0.setTrigger(Event("instance_created", None))
         self.states["/creating"].addTransition(_creating_0)
         self.states["/creating"].addTransition(_creating_0)
+        
+        # transition /running
+        _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_0.setAction(self._running_0_exec)
+        _running_0.setTrigger(Event("create_ball", None))
+        self.states["/running"].addTransition(_running_0)
+        _running_1 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_1.setAction(self._running_1_exec)
+        _running_1.setTrigger(Event("instance_created", None))
+        self.states["/running"].addTransition(_running_1)
+        _running_2 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_2.setAction(self._running_2_exec)
+        _running_2.setTrigger(Event("update_bounds", None))
+        self.states["/running"].addTransition(_running_2)
     
     
     def _creating_window_enter(self):
     def _creating_window_enter(self):
         self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [CANVAS_DIMS[0], CANVAS_DIMS[1], "Bouncing Balls Elevator", self.inports['field_ui']]))
         self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [CANVAS_DIMS[0], CANVAS_DIMS[1], "Bouncing Balls Elevator", self.inports['field_ui']]))
@@ -198,6 +212,23 @@ class MainApp(RuntimeClassBase):
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name, self.canvas_id, self.window_id])]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name, self.canvas_id, self.window_id])]))
     
     
+    def _running_0_exec(self, parameters):
+        floor_num = parameters[0]
+        x = parameters[1]
+        y = parameters[2]
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "ball", "Ball", self.canvas_id, floor_num, x, y]))
+    
+    def _running_1_exec(self, parameters):
+        association_name = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name])]))
+    
+    def _running_2_exec(self, parameters):
+        pos = parameters[0]
+        dim = parameters[1]
+        vel = parameters[2]
+        self.big_step.outputEventOM(Event("broad_cast", None, [self, Event("update_bounds", None, [pos, dim, vel])]))
+    
     def initializeStatechart(self):
     def initializeStatechart(self):
         # enter default state
         # enter default state
         self.default_targets = self.states["/creating_window"].getEffectiveTargetStates()
         self.default_targets = self.states["/creating_window"].getEffectiveTargetStates()
@@ -233,7 +264,12 @@ class Floor(RuntimeClassBase):
         y_dim = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
         y_dim = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
         
         
         self.dim = {'x': FLOOR_LENGTH, 'y': y_dim};
         self.dim = {'x': FLOOR_LENGTH, 'y': y_dim};
-        self.pos = {'x': FLOOR_LENGTH / 2, 'y': (y_dim /2) + (self.floor_num * (y_dim + FLOOR_SPACE))};
+        
+        
+        # start position from the bottom instead of from the top
+        # self.pos = {'x': FLOOR_LENGTH / 2, 'y': (y_dim /2) + (self.floor_num * (y_dim + FLOOR_SPACE))};
+        
+        self.pos = {'x': FLOOR_LENGTH / 2, 'y': CANVAS_DIMS[1] - (y_dim /2) - ( self.floor_num * (y_dim + FLOOR_SPACE)  )};
     
     
     def user_defined_destructor(self):
     def user_defined_destructor(self):
         pass
         pass
@@ -257,14 +293,10 @@ class Floor(RuntimeClassBase):
         self.states["/running/create_random_ball"].setEnter(self._running_create_random_ball_enter)
         self.states["/running/create_random_ball"].setEnter(self._running_create_random_ball_enter)
         self.states["/running/create_random_ball"].setExit(self._running_create_random_ball_exit)
         self.states["/running/create_random_ball"].setExit(self._running_create_random_ball_exit)
         
         
-        # state /running/wait
-        self.states["/running/wait"] = State(4, "/running/wait", self)
-        
         # add children
         # add children
         self.states[""].addChild(self.states["/creating_floor"])
         self.states[""].addChild(self.states["/creating_floor"])
         self.states[""].addChild(self.states["/running"])
         self.states[""].addChild(self.states["/running"])
         self.states["/running"].addChild(self.states["/running/create_random_ball"])
         self.states["/running"].addChild(self.states["/running/create_random_ball"])
-        self.states["/running"].addChild(self.states["/running/wait"])
         self.states[""].fixTree()
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/creating_floor"]
         self.states[""].default_state = self.states["/creating_floor"]
         self.states["/running"].default_state = self.states["/running/create_random_ball"]
         self.states["/running"].default_state = self.states["/running/create_random_ball"]
@@ -275,16 +307,10 @@ class Floor(RuntimeClassBase):
         self.states["/creating_floor"].addTransition(_creating_floor_0)
         self.states["/creating_floor"].addTransition(_creating_floor_0)
         
         
         # transition /running/create_random_ball
         # transition /running/create_random_ball
-        _running_create_random_ball_0 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/wait"]])
+        _running_create_random_ball_0 = Transition(self, self.states["/running/create_random_ball"], [self.states["/running/create_random_ball"]])
         _running_create_random_ball_0.setAction(self._running_create_random_ball_0_exec)
         _running_create_random_ball_0.setAction(self._running_create_random_ball_0_exec)
         _running_create_random_ball_0.setTrigger(Event("_0after"))
         _running_create_random_ball_0.setTrigger(Event("_0after"))
         self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_0)
         self.states["/running/create_random_ball"].addTransition(_running_create_random_ball_0)
-        
-        # transition /running/wait
-        _running_wait_0 = Transition(self, self.states["/running/wait"], [self.states["/running/create_random_ball"]])
-        _running_wait_0.setAction(self._running_wait_0_exec)
-        _running_wait_0.setTrigger(Event("instance_created", None))
-        self.states["/running/wait"].addTransition(_running_wait_0)
     
     
     def _creating_floor_enter(self):
     def _creating_floor_enter(self):
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['floor_ui']]))
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['floor_ui']]))
@@ -296,12 +322,7 @@ class Floor(RuntimeClassBase):
         self.removeTimer(0)
         self.removeTimer(0)
     
     
     def _running_create_random_ball_0_exec(self, parameters):
     def _running_create_random_ball_0_exec(self, parameters):
-        self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas_id, self.floor_num, 10, self.pos['y']]))
-    
-    def _running_wait_0_exec(self, parameters):
-        association_name = parameters[0]
-        self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("create_ball", None, [self.floor_num, 10, self.pos['y']])]))
     
     
     def initializeStatechart(self):
     def initializeStatechart(self):
         # enter default state
         # enter default state
@@ -328,8 +349,8 @@ class ElevatorControls(RuntimeClassBase):
     
     
     def user_defined_constructor(self, canvas_id):
     def user_defined_constructor(self, canvas_id):
         self.canvas_id = canvas_id;
         self.canvas_id = canvas_id;
-        self.button_num = FLOORS;
-        self.dim = {'x': 120, 'y': (50 + (FLOORS * 30))}
+        self.button_num = (FLOORS - 1);
+        self.dim = {'x': 120, 'y': (50 + ((FLOORS - 1) * 30))}
         self.pos = {'x': CANVAS_DIMS[0] - ((self.dim['x'] / 2) + 10), 'y': (self.dim['y'] / 2) + 10}
         self.pos = {'x': CANVAS_DIMS[0] - ((self.dim['x'] / 2) + 10), 'y': (self.dim['y'] / 2) + 10}
     
     
     def user_defined_destructor(self):
     def user_defined_destructor(self):
@@ -414,7 +435,6 @@ class ElevatorControls(RuntimeClassBase):
     def _creating_create_rect_enter(self):
     def _creating_create_rect_enter(self):
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'grey', 'outline': 'black'}, self.inports['control_ui']]))
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'grey', 'outline': 'black'}, self.inports['control_ui']]))
         self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], 20, 'Elevator Controls', self.inports['control_ui']]))
         self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], 20, 'Elevator Controls', self.inports['control_ui']]))
-        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [self.canvas_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['control_ui']]))
     
     
     def _creating_create_buttons_create_a_button_enter(self):
     def _creating_create_buttons_create_a_button_enter(self):
         self.big_step.outputEventOM(Event("create_instance", None, [self, "button", "ElevatorButton", self.canvas_id, self.button_num]))
         self.big_step.outputEventOM(Event("create_instance", None, [self, "button", "ElevatorButton", self.canvas_id, self.button_num]))
@@ -500,26 +520,25 @@ class ElevatorButton(RuntimeClassBase):
         # transition /running
         # transition /running
         _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
         _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
         _running_0.setAction(self._running_0_exec)
         _running_0.setAction(self._running_0_exec)
-        _running_0.setTrigger(Event("button_click", self.getInPortName("button_ui")))
+        _running_0.setTrigger(Event("clicked", self.getInPortName("button_ui")))
         _running_0.setGuard(self._running_0_guard)
         _running_0.setGuard(self._running_0_guard)
         self.states["/running"].addTransition(_running_0)
         self.states["/running"].addTransition(_running_0)
     
     
     def _creating_enter(self):
     def _creating_enter(self):
-        self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, CANVAS_DIMS[0] - 70, 45 + (30 * (FLOORS - self.number)) , 10, {'fill':'black', 'outline': 'black'}, self.inports['button_ui']]))
-        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, CANVAS_DIMS[0] - 70, 45 + (30 * (FLOORS - self.number)) , str(self.number), self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("create_circle", self.getOutPortName("ui"), [self.canvas_id, CANVAS_DIMS[0] - 70, 45 + (30 * (FLOORS - 1 - self.number)) , 10, {'fill':'black', 'outline': 'black'}, self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("create_text", self.getOutPortName("ui"), [self.canvas_id, CANVAS_DIMS[0] - 70, 45 + (30 * (FLOORS - 1 - self.number)) , str(self.number), self.inports['button_ui']]))
     
     
     def _creating_0_exec(self, parameters):
     def _creating_0_exec(self, parameters):
         canvas_id = parameters[0]
         canvas_id = parameters[0]
         circle_id = parameters[1]
         circle_id = parameters[1]
         self.button_id = circle_id
         self.button_id = circle_id
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'button_click', self.inports['button_ui']]))
+        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'clicked', self.inports['button_ui']]))
         self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['button_ui']]))
         self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['button_ui']]))
     
     
     def _running_0_exec(self, parameters):
     def _running_0_exec(self, parameters):
         x = parameters[0]
         x = parameters[0]
         y = parameters[1]
         y = parameters[1]
         button = parameters[2]
         button = parameters[2]
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("button_pressed", None, [self.number])]))
         self.big_step.outputEvent(Event("set_element_color", self.getOutPortName("ui"), [self.canvas_id, self.button_id, '#ff0']))
         self.big_step.outputEvent(Event("set_element_color", self.getOutPortName("ui"), [self.canvas_id, self.button_id, '#ff0']))
     
     
     def _running_0_guard(self, parameters):
     def _running_0_guard(self, parameters):
@@ -591,8 +610,10 @@ class Elevator(RuntimeClassBase):
         # state /root/running
         # state /root/running
         self.states["/root/running"] = State(4, "/root/running", self)
         self.states["/root/running"] = State(4, "/root/running", self)
         
         
-        # state /root/running/waiting
-        self.states["/root/running/waiting"] = State(5, "/root/running/waiting", self)
+        # state /root/running/idle
+        self.states["/root/running/idle"] = State(5, "/root/running/idle", self)
+        self.states["/root/running/idle"].setEnter(self._root_running_idle_enter)
+        self.states["/root/running/idle"].setExit(self._root_running_idle_exit)
         
         
         # state /root/running/move
         # state /root/running/move
         self.states["/root/running/move"] = State(6, "/root/running/move", self)
         self.states["/root/running/move"] = State(6, "/root/running/move", self)
@@ -604,12 +625,12 @@ class Elevator(RuntimeClassBase):
         self.states["/root"].addChild(self.states["/root/waiting"])
         self.states["/root"].addChild(self.states["/root/waiting"])
         self.states["/root"].addChild(self.states["/root/creating_elevator"])
         self.states["/root"].addChild(self.states["/root/creating_elevator"])
         self.states["/root"].addChild(self.states["/root/running"])
         self.states["/root"].addChild(self.states["/root/running"])
-        self.states["/root/running"].addChild(self.states["/root/running/waiting"])
+        self.states["/root/running"].addChild(self.states["/root/running/idle"])
         self.states["/root/running"].addChild(self.states["/root/running/move"])
         self.states["/root/running"].addChild(self.states["/root/running/move"])
         self.states[""].fixTree()
         self.states[""].fixTree()
         self.states[""].default_state = self.states["/root"]
         self.states[""].default_state = self.states["/root"]
         self.states["/root"].default_state = self.states["/root/waiting"]
         self.states["/root"].default_state = self.states["/root/waiting"]
-        self.states["/root/running"].default_state = self.states["/root/running/waiting"]
+        self.states["/root/running"].default_state = self.states["/root/running/idle"]
         
         
         # transition /root/waiting
         # transition /root/waiting
         _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/creating_elevator"]])
         _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/creating_elevator"]])
@@ -623,17 +644,17 @@ class Elevator(RuntimeClassBase):
         _root_creating_elevator_0.setTrigger(Event("rectangle_created", None))
         _root_creating_elevator_0.setTrigger(Event("rectangle_created", None))
         self.states["/root/creating_elevator"].addTransition(_root_creating_elevator_0)
         self.states["/root/creating_elevator"].addTransition(_root_creating_elevator_0)
         
         
-        # transition /root/running/waiting
-        _root_running_waiting_0 = Transition(self, self.states["/root/running/waiting"], [self.states["/root/running/move"]])
-        _root_running_waiting_0.setTrigger(Event("move_elevator", None))
-        self.states["/root/running/waiting"].addTransition(_root_running_waiting_0)
+        # transition /root/running/idle
+        _root_running_idle_0 = Transition(self, self.states["/root/running/idle"], [self.states["/root/running/move"]])
+        _root_running_idle_0.setTrigger(Event("_0after"))
+        self.states["/root/running/idle"].addTransition(_root_running_idle_0)
         
         
         # transition /root/running/move
         # transition /root/running/move
         _root_running_move_0 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/move"]])
         _root_running_move_0 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/move"]])
         _root_running_move_0.setAction(self._root_running_move_0_exec)
         _root_running_move_0.setAction(self._root_running_move_0_exec)
-        _root_running_move_0.setTrigger(Event("_0after"))
+        _root_running_move_0.setTrigger(Event("_1after"))
         self.states["/root/running/move"].addTransition(_root_running_move_0)
         self.states["/root/running/move"].addTransition(_root_running_move_0)
-        _root_running_move_1 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/waiting"]])
+        _root_running_move_1 = Transition(self, self.states["/root/running/move"], [self.states["/root/running/idle"]])
         _root_running_move_1.setTrigger(None)
         _root_running_move_1.setTrigger(None)
         _root_running_move_1.setGuard(self._root_running_move_1_guard)
         _root_running_move_1.setGuard(self._root_running_move_1_guard)
         self.states["/root/running/move"].addTransition(_root_running_move_1)
         self.states["/root/running/move"].addTransition(_root_running_move_1)
@@ -641,11 +662,18 @@ class Elevator(RuntimeClassBase):
     def _root_creating_elevator_enter(self):
     def _root_creating_elevator_enter(self):
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['elevator_ui']]))
         self.big_step.outputEvent(Event("create_rectangle", self.getOutPortName("ui"), [self.canvas_id, self.pos['x'], self.pos['y'], self.dim['x'], self.dim['y'], {'fill':'white', 'outline': 'black'}, self.inports['elevator_ui']]))
     
     
+    def _root_running_idle_enter(self):
+        self.addTimer(0, 5)
+    
+    def _root_running_idle_exit(self):
+        self.removeTimer(0)
+    
     def _root_running_move_enter(self):
     def _root_running_move_enter(self):
-        self.addTimer(0, 0.02)
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("update_bounds", None, [self.pos, self.dim, self.vel])]))
+        self.addTimer(1, 0.02)
     
     
     def _root_running_move_exit(self):
     def _root_running_move_exit(self):
-        self.removeTimer(0)
+        self.removeTimer(1)
     
     
     def _root_waiting_0_exec(self, parameters):
     def _root_waiting_0_exec(self, parameters):
         association_name = parameters[0]
         association_name = parameters[0]
@@ -696,7 +724,15 @@ class Ball(RuntimeClassBase):
     
     
     def user_defined_constructor(self, canvas_id, floor_num, x, y):
     def user_defined_constructor(self, canvas_id, floor_num, x, y):
         self.canvas_id = canvas_id;
         self.canvas_id = canvas_id;
+        
+        
         self.floor_num = floor_num;
         self.floor_num = floor_num;
+        
+        self.elevator_floor = 0;
+        self.elevator_open = True;
+        self.rect_pos = None;
+        self.rect_dim = None;
+        
         self.r = 5.0;
         self.r = 5.0;
         self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
         self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
         self.pos = {'x': x, 'y': y};
         self.pos = {'x': x, 'y': y};
@@ -823,41 +859,44 @@ class Ball(RuntimeClassBase):
         canvas_id = parameters[0]
         canvas_id = parameters[0]
         circle_id = parameters[1]
         circle_id = parameters[1]
         self.circle_id = circle_id
         self.circle_id = circle_id
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_PRESS, 'mouse_press', self.inports['ball_ui']]))
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['ball_ui']]))
-        self.big_step.outputEvent(Event("bind_canvas_event", self.getOutPortName("ui"), [self.canvas_id, circle_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release', self.inports['ball_ui']]))
     
     
     def _main_behaviour_bouncing_0_exec(self, parameters):
     def _main_behaviour_bouncing_0_exec(self, parameters):
         if self.floor_num == -1:
         if self.floor_num == -1:
             if self.pos['x'] - self.r < self.rect_pos['x'] - (self.rect_dim['x'] / 2):
             if self.pos['x'] - self.r < self.rect_pos['x'] - (self.rect_dim['x'] / 2):
-                self.pos['x'] = self.rect_pos['x'] - (self.rect_dim['x'] / 2) + self.r  # Correct position
-                self.vel['x'] = -self.vel['x'] + self.rect_vel['x']
+                if self.elevator_open:
+                    self.floor_num = self.elevator_floor
+                else:
+                    self.pos['x'] = self.rect_pos['x'] - (self.rect_dim['x'] / 2) + self.r
+                    self.vel['x'] = -self.vel['x']
             elif self.pos['x'] + self.r > self.rect_pos['x'] + (self.rect_dim['x'] / 2):
             elif self.pos['x'] + self.r > self.rect_pos['x'] + (self.rect_dim['x'] / 2):
-                self.pos['x'] = self.rect_pos['x'] + (self.rect_dim['x'] / 2) - self.r  # Correct position
-                self.vel['x'] = -self.vel['x'] + self.rect_vel['x']
+                self.pos['x'] = self.rect_pos['x'] + (self.rect_dim['x'] / 2) - self.r
+                self.vel['x'] = -self.vel['x']
         
         
             # Check collision with the top and bottom borders
             # Check collision with the top and bottom borders
             if self.pos['y'] - self.r < self.rect_pos['y'] - (self.rect_dim['y'] / 2):
             if self.pos['y'] - self.r < self.rect_pos['y'] - (self.rect_dim['y'] / 2):
-                self.pos['y'] = self.rect_pos['y'] - (self.rect_dim['y'] / 2) + self.r  # Correct position
-                self.vel['y'] = -self.vel['y'] + self.rect_vel['y']
+                self.pos['y'] = self.rect_pos['y'] - (self.rect_dim['y'] / 2) + self.r
+                self.vel['y'] = -self.vel['y'] + self.rect_vel
             elif self.pos['y'] + self.r > self.rect_pos['y'] + (self.rect_dim['y'] / 2):
             elif self.pos['y'] + self.r > self.rect_pos['y'] + (self.rect_dim['y'] / 2):
-                self.pos['y'] = self.rect_pos['y'] + (self.rect_dim['y'] / 2) - self.r  # Correct position
-                self.vel['y'] = -self.vel['y'] + self.rect_vel['y']
+                self.pos['y'] = self.rect_pos['y'] + (self.rect_dim['y'] / 2) - self.r
+                self.vel['y'] = -self.vel['y'] + self.rect_vel
         else:
         else:
             floor_height = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
             floor_height = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
             floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
             floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
-            floor_pos = {'x': FLOOR_LENGTH / 2, 'y': (floor_height /2) + (self.floor_num * (floor_height + FLOOR_SPACE))};
+            floor_pos = {'x': FLOOR_LENGTH / 2, 'y': CANVAS_DIMS[1] - (floor_height /2) - ( self.floor_num * (floor_height + FLOOR_SPACE)  )};
         
         
             if self.pos['x'] - self.r < floor_pos['x'] - (floor_dim['x'] / 2):
             if self.pos['x'] - self.r < floor_pos['x'] - (floor_dim['x'] / 2):
-                self.pos['x'] = floor_pos['x'] - (floor_dim['x'] / 2) + self.r  # Correct position
+                self.pos['x'] = floor_pos['x'] - (floor_dim['x'] / 2) + self.r
                 self.vel['x'] = -self.vel['x']
                 self.vel['x'] = -self.vel['x']
             elif self.pos['x'] + self.r > floor_pos['x'] + (floor_dim['x'] / 2):
             elif self.pos['x'] + self.r > floor_pos['x'] + (floor_dim['x'] / 2):
-                self.pos['x'] = floor_pos['x'] + (floor_dim['x'] / 2) - self.r  # Correct position
-                self.vel['x'] = -self.vel['x']
+                if self.elevator_open and (self.elevator_floor == self.floor_num):
+                    self.floor_num = -1
+                else:
+                    self.pos['x'] = floor_pos['x'] + (floor_dim['x'] / 2) - self.r
+                    self.vel['x'] = -self.vel['x']
         
         
             # Check collision with the top and bottom borders
             # Check collision with the top and bottom borders
             if self.pos['y'] - self.r < floor_pos['y'] - (floor_dim['y'] / 2):
             if self.pos['y'] - self.r < floor_pos['y'] - (floor_dim['y'] / 2):
-                self.pos['y'] = floor_pos['y'] - (floor_dim['y'] / 2) + self.r  # Correct position
+                self.pos['y'] = floor_pos['y'] - (floor_dim['y'] / 2) + self.r
                 self.vel['y'] = -self.vel['y']
                 self.vel['y'] = -self.vel['y']
             elif self.pos['y'] + self.r > floor_pos['y'] + (floor_dim['y'] / 2):
             elif self.pos['y'] + self.r > floor_pos['y'] + (floor_dim['y'] / 2):
                 self.pos['y'] = floor_pos['y'] + (floor_dim['y'] / 2) - self.r  # Correct position
                 self.pos['y'] = floor_pos['y'] + (floor_dim['y'] / 2) - self.r  # Correct position
@@ -888,6 +927,7 @@ class Ball(RuntimeClassBase):
         self.rect_pos = pos
         self.rect_pos = pos
         self.rect_dim = dim
         self.rect_dim = dim
         self.rect_vel = vel
         self.rect_vel = vel
+        self.elevator_open = False
     
     
     def _main_behaviour_dragging_0_exec(self, parameters):
     def _main_behaviour_dragging_0_exec(self, parameters):
         x = parameters[0]
         x = parameters[0]
@@ -917,7 +957,7 @@ class Ball(RuntimeClassBase):
         x = parameters[0]
         x = parameters[0]
         y = parameters[1]
         y = parameters[1]
         button = parameters[2]
         button = parameters[2]
-        self.mouse_pos = {'x':x, 'y':y};
+        self.mouse_pos = {'x': x, 'y': y};
     
     
     def _main_behaviour_selected_0_guard(self, parameters):
     def _main_behaviour_selected_0_guard(self, parameters):
         x = parameters[0]
         x = parameters[0]
@@ -926,7 +966,7 @@ class Ball(RuntimeClassBase):
         return button == ui.MOUSE_BUTTONS.LEFT
         return button == ui.MOUSE_BUTTONS.LEFT
     
     
     def _main_behaviour_ball_delete_0_exec(self, parameters):
     def _main_behaviour_ball_delete_0_exec(self, parameters):
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_ball", None, [self.association_name])]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'floor', Event("delete_ball", None, [self.association_name])]))
         self.big_step.outputEvent(Event("destroy_element", self.getOutPortName("ui"), [self.canvas_id, self.circle_id]))
         self.big_step.outputEvent(Event("destroy_element", self.getOutPortName("ui"), [self.canvas_id, self.circle_id]))
     
     
     def initializeStatechart(self):
     def initializeStatechart(self):
@@ -945,16 +985,15 @@ class ObjectManager(ObjectManagerBase):
             instance.associations["floor"] = Association("Floor", 2, -1)
             instance.associations["floor"] = Association("Floor", 2, -1)
             instance.associations["controls"] = Association("ElevatorControls", 1, 1)
             instance.associations["controls"] = Association("ElevatorControls", 1, 1)
             instance.associations["elevator"] = Association("Elevator", 1, 1)
             instance.associations["elevator"] = Association("Elevator", 1, 1)
+            instance.associations["ball"] = Association("Ball", 0, -1)
         elif class_name == "Floor":
         elif class_name == "Floor":
             instance = Floor(self.controller, construct_params[0], construct_params[1])
             instance = Floor(self.controller, construct_params[0], construct_params[1])
             instance.associations = {}
             instance.associations = {}
-            instance.associations["balls"] = Association("Ball", 0, -1)
             instance.associations["parent"] = Association("MainApp", 1, 1)
             instance.associations["parent"] = Association("MainApp", 1, 1)
         elif class_name == "ElevatorControls":
         elif class_name == "ElevatorControls":
             instance = ElevatorControls(self.controller, construct_params[0])
             instance = ElevatorControls(self.controller, construct_params[0])
             instance.associations = {}
             instance.associations = {}
             instance.associations["button"] = Association("ElevatorButton", 0, -1)
             instance.associations["button"] = Association("ElevatorButton", 0, -1)
-            instance.associations["balls"] = Association("Ball", 0, -1)
             instance.associations["parent"] = Association("Elevator", 1, 1)
             instance.associations["parent"] = Association("Elevator", 1, 1)
         elif class_name == "ElevatorButton":
         elif class_name == "ElevatorButton":
             instance = ElevatorButton(self.controller, construct_params[0], construct_params[1])
             instance = ElevatorButton(self.controller, construct_params[0], construct_params[1])
@@ -963,7 +1002,7 @@ class ObjectManager(ObjectManagerBase):
         elif class_name == "Elevator":
         elif class_name == "Elevator":
             instance = Elevator(self.controller, construct_params[0])
             instance = Elevator(self.controller, construct_params[0])
             instance.associations = {}
             instance.associations = {}
-            instance.associations["balls"] = Association("Ball", 0, -1)
+            instance.associations["floors"] = Association("Floors", 1, 1)
             instance.associations["parent"] = Association("MainApp", 1, 1)
             instance.associations["parent"] = Association("MainApp", 1, 1)
         elif class_name == "Ball":
         elif class_name == "Ball":
             instance = Ball(self.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3])
             instance = Ball(self.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3])

+ 93 - 82
examples/ElevatorBalls/sccd.xml

@@ -17,6 +17,7 @@
             <association name="floor" class="Floor" min="2"/>
             <association name="floor" class="Floor" min="2"/>
             <association name="controls" class="ElevatorControls" min="1" max="1"/>
             <association name="controls" class="ElevatorControls" min="1" max="1"/>
             <association name="elevator" class="Elevator" min="1" max="1"/>
             <association name="elevator" class="Elevator" min="1" max="1"/>
+            <association name="ball" class="Ball" />
         </relationships>
         </relationships>
         <attribute name="window_id" />
         <attribute name="window_id" />
         <attribute name="canvas_id" />
         <attribute name="canvas_id" />
@@ -126,7 +127,7 @@
                 </transition>
                 </transition>
             </state>
             </state>
             <state id="creating">
             <state id="creating">
-                <transition event="instance_created" target="../waiting">
+                <transition event="instance_created" target="../running">
                     <parameter name="association_name" type="string"/>
                     <parameter name="association_name" type="string"/>
                     <raise scope="cd" event="start_instance">
                     <raise scope="cd" event="start_instance">
                         <parameter expr="association_name" />
                         <parameter expr="association_name" />
@@ -138,7 +139,39 @@
                     </raise>
                     </raise>
                 </transition>
                 </transition>
             </state>
             </state>
-            <state id="waiting">
+            <state id="running">
+                <transition event="create_ball" target=".">
+                    <parameter name="floor_num" type="int"/>
+                    <parameter name="x" type="int"/>
+                    <parameter name="y" type="int"/>
+                    <raise scope="cd" event="create_instance">
+                        <parameter expr='"ball"' />
+                        <parameter expr='"Ball"' />
+                        <parameter expr="self.canvas_id" />
+                        <parameter expr="floor_num" />
+                        <parameter expr="x" />
+                        <parameter expr="y" />
+                    </raise>
+                </transition>
+                <transition event='instance_created' target='.'>
+                    <parameter name="association_name" type="string"/>
+                    <raise scope="cd" event="start_instance">
+                        <parameter expr="association_name" />
+                    </raise>
+                    <raise scope="narrow" event="set_association_name" target="association_name">
+                        <parameter expr="association_name" />
+                    </raise>
+                </transition>
+                <transition event='update_bounds' target='.'>
+                    <parameter name="pos" type="dict"/>
+                    <parameter name="dim" type="dict"/>
+                    <parameter name="vel" type="int"/>
+                    <raise scope="broad" event="update_bounds">
+                        <parameter expr="pos" />
+                        <parameter expr="dim" />
+                        <parameter expr="vel" />
+                    </raise>
+                </transition>
             </state>
             </state>
         </scxml>
         </scxml>
     </class>
     </class>
@@ -150,7 +183,6 @@
         <atrribute name="pos" />
         <atrribute name="pos" />
         <inport name="floor_ui"/>
         <inport name="floor_ui"/>
         <relationships>
         <relationships>
-            <association name="balls" class="Ball" />
             <association name="parent" class="MainApp" min="1" max="1" />
             <association name="parent" class="MainApp" min="1" max="1" />
         </relationships>
         </relationships>
         <constructor>
         <constructor>
@@ -164,7 +196,12 @@
                 y_dim = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
                 y_dim = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
 
 
                 self.dim = {'x': FLOOR_LENGTH, 'y': y_dim};
                 self.dim = {'x': FLOOR_LENGTH, 'y': y_dim};
-                self.pos = {'x': FLOOR_LENGTH / 2, 'y': (y_dim /2) + (self.floor_num * (y_dim + FLOOR_SPACE))};
+
+
+                # start position from the bottom instead of from the top
+                # self.pos = {'x': FLOOR_LENGTH / 2, 'y': (y_dim /2) + (self.floor_num * (y_dim + FLOOR_SPACE))};
+
+                self.pos = {'x': FLOOR_LENGTH / 2, 'y': CANVAS_DIMS[1] - (y_dim /2) - ( self.floor_num * (y_dim + FLOOR_SPACE)  )};
                 ]]>
                 ]]>
             </body>
             </body>
         </constructor>
         </constructor>
@@ -186,28 +223,14 @@
             </state>
             </state>
             <state id="running" initial="create_random_ball">
             <state id="running" initial="create_random_ball">
                 <state id="create_random_ball" >
                 <state id="create_random_ball" >
-                    <transition after="random.randint(2, 10)" target="../wait">
-                        <raise scope="cd" event="create_instance">
-                            <parameter expr='"balls"' />
-                            <parameter expr='"Ball"' />
-                            <parameter expr="self.canvas_id" />
+                    <transition after="random.randint(2, 10)" target=".">
+                        <raise scope="narrow" event="create_ball" target="'parent'">
                             <parameter expr="self.floor_num" />
                             <parameter expr="self.floor_num" />
                             <parameter expr="10" />
                             <parameter expr="10" />
                             <parameter expr="self.pos['y']" />
                             <parameter expr="self.pos['y']" />
                         </raise>
                         </raise>
                     </transition>
                     </transition>
                 </state>
                 </state>
-                <state id="wait">
-                    <transition event="instance_created" target="../create_random_ball">
-                        <parameter name="association_name" type="string"/>
-                        <raise scope="cd" event="start_instance">
-                            <parameter expr="association_name" />
-                        </raise>
-                        <raise scope="narrow" event="set_association_name" target="association_name">
-                            <parameter expr="association_name" />
-                        </raise>
-                    </transition>
-                </state>
             </state>
             </state>
         </scxml>
         </scxml>
     </class>
     </class>
@@ -216,15 +239,14 @@
         <inport name="control_ui"/>
         <inport name="control_ui"/>
         <relationships>
         <relationships>
             <association name="button" class="ElevatorButton" />
             <association name="button" class="ElevatorButton" />
-            <association name="balls" class="Ball" />
             <association name="parent" class="Elevator" min="1" max="1" />
             <association name="parent" class="Elevator" min="1" max="1" />
         </relationships>
         </relationships>
         <constructor>
         <constructor>
             <parameter name="canvas_id" />
             <parameter name="canvas_id" />
             <body>
             <body>
                 self.canvas_id = canvas_id;
                 self.canvas_id = canvas_id;
-                self.button_num = FLOORS;
-                self.dim = {'x': 120, 'y': (50 + (FLOORS * 30))}
+                self.button_num = (FLOORS - 1);
+                self.dim = {'x': 120, 'y': (50 + ((FLOORS - 1) * 30))}
                 self.pos = {'x': CANVAS_DIMS[0] - ((self.dim['x'] / 2) + 10), 'y': (self.dim['y'] / 2) + 10}
                 self.pos = {'x': CANVAS_DIMS[0] - ((self.dim['x'] / 2) + 10), 'y': (self.dim['y'] / 2) + 10}
             </body>
             </body>
         </constructor>
         </constructor>
@@ -248,12 +270,6 @@
                             <parameter expr="'Elevator Controls'"/>
                             <parameter expr="'Elevator Controls'"/>
                             <parameter expr="self.inports['control_ui']"/><!-- inport for response -->
                             <parameter expr="self.inports['control_ui']"/><!-- inport for response -->
                         </raise>
                         </raise>
-                        <raise port="ui" event="bind_event">
-                            <parameter expr="self.canvas_id"/>                   <!-- widget_id -->
-                            <parameter expr="ui.EVENTS.MOUSE_MOVE"/>        <!-- tk_event -->
-                            <parameter expr="'mouse_move'"/>                <!-- sccd_event_name -->
-                            <parameter expr="self.inports['control_ui']"/>    <!-- inport for response -->
-                        </raise>
                     </onentry>
                     </onentry>
                     <transition target="../create_buttons" />
                     <transition target="../create_buttons" />
                 </state>
                 </state>
@@ -322,7 +338,7 @@
                     <raise port="ui" event="create_circle">
                     <raise port="ui" event="create_circle">
                         <parameter expr="self.canvas_id" />
                         <parameter expr="self.canvas_id" />
                         <parameter expr="CANVAS_DIMS[0] - 70"/>
                         <parameter expr="CANVAS_DIMS[0] - 70"/>
-                        <parameter expr="45 + (30 * (FLOORS - self.number)) "/>
+                        <parameter expr="45 + (30 * (FLOORS - 1 - self.number)) "/>
                         <parameter expr="10" />
                         <parameter expr="10" />
                         <parameter expr="{'fill':'black', 'outline': 'black'}"/><!-- style -->
                         <parameter expr="{'fill':'black', 'outline': 'black'}"/><!-- style -->
                         <parameter expr="self.inports['button_ui']"/><!-- inport for response -->
                         <parameter expr="self.inports['button_ui']"/><!-- inport for response -->
@@ -330,7 +346,7 @@
                     <raise port="ui" event="create_text">
                     <raise port="ui" event="create_text">
                         <parameter expr="self.canvas_id" />
                         <parameter expr="self.canvas_id" />
                         <parameter expr="CANVAS_DIMS[0] - 70"/>
                         <parameter expr="CANVAS_DIMS[0] - 70"/>
-                        <parameter expr="45 + (30 * (FLOORS - self.number)) "/>
+                        <parameter expr="45 + (30 * (FLOORS - 1 - self.number)) "/>
                         <parameter expr="str(self.number)"/>
                         <parameter expr="str(self.number)"/>
                         <parameter expr="self.inports['button_ui']"/><!-- inport for response -->
                         <parameter expr="self.inports['button_ui']"/><!-- inport for response -->
                     </raise>
                     </raise>
@@ -342,10 +358,10 @@
                         self.button_id = circle_id
                         self.button_id = circle_id
                     </script>
                     </script>
                     <raise port="ui" event="bind_canvas_event">
                     <raise port="ui" event="bind_canvas_event">
-                        <parameter expr="canvas_id"/>
+                        <parameter expr="self.canvas_id"/>
                         <parameter expr="circle_id"/><!-- widget_id -->
                         <parameter expr="circle_id"/><!-- widget_id -->
                         <parameter expr="ui.EVENTS.MOUSE_PRESS"/><!-- tk_event -->
                         <parameter expr="ui.EVENTS.MOUSE_PRESS"/><!-- tk_event -->
-                        <parameter expr="'button_click'"/><!-- sccd_event_name -->
+                        <parameter expr="'clicked'"/><!-- sccd_event_name -->
                         <parameter expr="self.inports['button_ui']"/><!-- inport for response -->
                         <parameter expr="self.inports['button_ui']"/><!-- inport for response -->
                     </raise>
                     </raise>
                     <raise port="ui" event="bind_canvas_event">
                     <raise port="ui" event="bind_canvas_event">
@@ -358,13 +374,10 @@
                 </transition>
                 </transition>
             </state>
             </state>
             <state id="running">
             <state id="running">
-                <transition port='button_ui' event="button_click" target='.' cond="button == ui.MOUSE_BUTTONS.LEFT">
+                <transition port='button_ui' event="clicked" target='.' cond="button == ui.MOUSE_BUTTONS.LEFT">
                     <parameter name="x" />
                     <parameter name="x" />
                     <parameter name="y" />
                     <parameter name="y" />
                     <parameter name="button" />
                     <parameter name="button" />
-                    <raise event="button_pressed" scope="narrow" target="'parent'">
-                        <parameter expr="self.number" />
-                    </raise>
                     <raise port="ui" event="set_element_color">
                     <raise port="ui" event="set_element_color">
                         <parameter expr="self.canvas_id"/>
                         <parameter expr="self.canvas_id"/>
                         <parameter expr="self.button_id"/>
                         <parameter expr="self.button_id"/>
@@ -382,7 +395,7 @@
         <atrribute name="pos" />
         <atrribute name="pos" />
         <inport name="elevator_ui"/>
         <inport name="elevator_ui"/>
         <relationships>
         <relationships>
-            <association name="balls" class="Ball" />
+            <association name="floors" class="Floors" min="1" max="1" />
             <association name="parent" class="MainApp" min="1" max="1" />
             <association name="parent" class="MainApp" min="1" max="1" />
         </relationships>
         </relationships>
         <constructor>
         <constructor>
@@ -436,13 +449,19 @@
                         </script>
                         </script>
                     </transition>
                     </transition>
                 </state>
                 </state>
-                <state id="running" initial="waiting">
-                    <state id="waiting">
-                        <transition event="move_elevator" target="../move">
-                            <parameter name="position" type="int"/>
+                <state id="running" initial="idle">
+                    <state id="idle">
+                        <transition after="5" target="../move">
                         </transition>
                         </transition>
                     </state>
                     </state>
                     <state id="move">
                     <state id="move">
+                        <onentry>
+                            <raise scope="narrow" event="update_bounds" target="'parent'">
+                                <parameter expr="self.pos" />
+                                <parameter expr="self.dim" />
+                                <parameter expr="self.vel" />
+                            </raise>
+                        </onentry>
                         <transition after="0.02" target=".">
                         <transition after="0.02" target=".">
                             <raise port="ui" event="set_element_pos">
                             <raise port="ui" event="set_element_pos">
                                 <parameter expr="self.canvas_id"/>
                                 <parameter expr="self.canvas_id"/>
@@ -454,7 +473,7 @@
                                 self.pos['y'] += self.vel
                                 self.pos['y'] += self.vel
                             </script>
                             </script>
                         </transition>
                         </transition>
-                        <transition target="../waiting" cond="(self.pos['y'] - (self.dim['y']/2)) &lt; 0">
+                        <transition target="../idle" cond="(self.pos['y'] - (self.dim['y']/2)) &lt; 0">
                         </transition>
                         </transition>
                     </state>
                     </state>
                 </state>
                 </state>
@@ -478,7 +497,15 @@
             <body>
             <body>
                 <![CDATA[
                 <![CDATA[
                 self.canvas_id = canvas_id;
                 self.canvas_id = canvas_id;
+
+
                 self.floor_num = floor_num;
                 self.floor_num = floor_num;
+
+                self.elevator_floor = 0;
+                self.elevator_open = True;
+                self.rect_pos = None;
+                self.rect_dim = None;
+
                 self.r = 5.0;
                 self.r = 5.0;
                 self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
                 self.vel = {'x': random.uniform(-5.0, 5.0), 'y': random.uniform(-5.0, 5.0)};
                 self.pos = {'x': x, 'y': y};
                 self.pos = {'x': x, 'y': y};
@@ -501,7 +528,6 @@
                 <state id="creating_circle">
                 <state id="creating_circle">
                     <onentry>
                     <onentry>
                         <raise port="ui" event="create_circle">
                         <raise port="ui" event="create_circle">
-                            canvas_id, x, y, r, style, res_port
                             <parameter expr="self.canvas_id"/><!-- canvas_id -->
                             <parameter expr="self.canvas_id"/><!-- canvas_id -->
                             <parameter expr="self.pos['x']"/><!-- x -->
                             <parameter expr="self.pos['x']"/><!-- x -->
                             <parameter expr="self.pos['y']"/><!-- y -->
                             <parameter expr="self.pos['y']"/><!-- y -->
@@ -516,27 +542,6 @@
                         <script>
                         <script>
                             self.circle_id = circle_id
                             self.circle_id = circle_id
                         </script>
                         </script>
-                        <raise port="ui" event="bind_canvas_event">
-                            <parameter expr="self.canvas_id"/>
-                            <parameter expr="circle_id"/>
-                            <parameter expr="ui.EVENTS.MOUSE_PRESS"/>
-                            <parameter expr="'mouse_press'"/>
-                            <parameter expr="self.inports['ball_ui']"/>
-                        </raise>
-                        <raise port="ui" event="bind_canvas_event">
-                            <parameter expr="self.canvas_id"/>
-                            <parameter expr="circle_id"/>
-                            <parameter expr="ui.EVENTS.MOUSE_MOVE"/>
-                            <parameter expr="'mouse_move'"/>
-                            <parameter expr="self.inports['ball_ui']"/>
-                        </raise>
-                        <raise port="ui" event="bind_canvas_event">
-                            <parameter expr="self.canvas_id"/>
-                            <parameter expr="circle_id"/>
-                            <parameter expr="ui.EVENTS.MOUSE_RELEASE"/>
-                            <parameter expr="'mouse_release'"/>
-                            <parameter expr="self.inports['ball_ui']"/>
-                        </raise>
                     </transition>
                     </transition>
                 </state>
                 </state>
                 <state id="bouncing">
                 <state id="bouncing">
@@ -545,34 +550,40 @@
                             <![CDATA[
                             <![CDATA[
                             if self.floor_num == -1:
                             if self.floor_num == -1:
                                 if self.pos['x'] - self.r < self.rect_pos['x'] - (self.rect_dim['x'] / 2):
                                 if self.pos['x'] - self.r < self.rect_pos['x'] - (self.rect_dim['x'] / 2):
-                                    self.pos['x'] = self.rect_pos['x'] - (self.rect_dim['x'] / 2) + self.r  # Correct position
-                                    self.vel['x'] = -self.vel['x'] + self.rect_vel['x']
+                                    if self.elevator_open:
+                                        self.floor_num = self.elevator_floor
+                                    else:
+                                        self.pos['x'] = self.rect_pos['x'] - (self.rect_dim['x'] / 2) + self.r
+                                        self.vel['x'] = -self.vel['x']
                                 elif self.pos['x'] + self.r > self.rect_pos['x'] + (self.rect_dim['x'] / 2):
                                 elif self.pos['x'] + self.r > self.rect_pos['x'] + (self.rect_dim['x'] / 2):
-                                    self.pos['x'] = self.rect_pos['x'] + (self.rect_dim['x'] / 2) - self.r  # Correct position
-                                    self.vel['x'] = -self.vel['x'] + self.rect_vel['x']
+                                    self.pos['x'] = self.rect_pos['x'] + (self.rect_dim['x'] / 2) - self.r
+                                    self.vel['x'] = -self.vel['x']
 
 
                                 # Check collision with the top and bottom borders
                                 # Check collision with the top and bottom borders
                                 if self.pos['y'] - self.r < self.rect_pos['y'] - (self.rect_dim['y'] / 2):
                                 if self.pos['y'] - self.r < self.rect_pos['y'] - (self.rect_dim['y'] / 2):
-                                    self.pos['y'] = self.rect_pos['y'] - (self.rect_dim['y'] / 2) + self.r  # Correct position
-                                    self.vel['y'] = -self.vel['y'] + self.rect_vel['y']
+                                    self.pos['y'] = self.rect_pos['y'] - (self.rect_dim['y'] / 2) + self.r
+                                    self.vel['y'] = -self.vel['y'] + self.rect_vel
                                 elif self.pos['y'] + self.r > self.rect_pos['y'] + (self.rect_dim['y'] / 2):
                                 elif self.pos['y'] + self.r > self.rect_pos['y'] + (self.rect_dim['y'] / 2):
-                                    self.pos['y'] = self.rect_pos['y'] + (self.rect_dim['y'] / 2) - self.r  # Correct position
-                                    self.vel['y'] = -self.vel['y'] + self.rect_vel['y']
+                                    self.pos['y'] = self.rect_pos['y'] + (self.rect_dim['y'] / 2) - self.r
+                                    self.vel['y'] = -self.vel['y'] + self.rect_vel
                             else:
                             else:
                                 floor_height = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
                                 floor_height = (CANVAS_DIMS[1] - ((FLOORS - 1) * FLOOR_SPACE)) / FLOORS
                                 floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
                                 floor_dim = {'x': FLOOR_LENGTH, 'y': floor_height};
-                                floor_pos = {'x': FLOOR_LENGTH / 2, 'y': (floor_height /2) + (self.floor_num * (floor_height + FLOOR_SPACE))};
+                                floor_pos = {'x': FLOOR_LENGTH / 2, 'y': CANVAS_DIMS[1] - (floor_height /2) - ( self.floor_num * (floor_height + FLOOR_SPACE)  )};
 
 
                                 if self.pos['x'] - self.r < floor_pos['x'] - (floor_dim['x'] / 2):
                                 if self.pos['x'] - self.r < floor_pos['x'] - (floor_dim['x'] / 2):
-                                    self.pos['x'] = floor_pos['x'] - (floor_dim['x'] / 2) + self.r  # Correct position
+                                    self.pos['x'] = floor_pos['x'] - (floor_dim['x'] / 2) + self.r
                                     self.vel['x'] = -self.vel['x']
                                     self.vel['x'] = -self.vel['x']
                                 elif self.pos['x'] + self.r > floor_pos['x'] + (floor_dim['x'] / 2):
                                 elif self.pos['x'] + self.r > floor_pos['x'] + (floor_dim['x'] / 2):
-                                    self.pos['x'] = floor_pos['x'] + (floor_dim['x'] / 2) - self.r  # Correct position
-                                    self.vel['x'] = -self.vel['x']
+                                    if self.elevator_open and (self.elevator_floor == self.floor_num):
+                                        self.floor_num = -1
+                                    else:
+                                        self.pos['x'] = floor_pos['x'] + (floor_dim['x'] / 2) - self.r
+                                        self.vel['x'] = -self.vel['x']
 
 
                                 # Check collision with the top and bottom borders
                                 # Check collision with the top and bottom borders
                                 if self.pos['y'] - self.r < floor_pos['y'] - (floor_dim['y'] / 2):
                                 if self.pos['y'] - self.r < floor_pos['y'] - (floor_dim['y'] / 2):
-                                    self.pos['y'] = floor_pos['y'] - (floor_dim['y'] / 2) + self.r  # Correct position
+                                    self.pos['y'] = floor_pos['y'] - (floor_dim['y'] / 2) + self.r
                                     self.vel['y'] = -self.vel['y']
                                     self.vel['y'] = -self.vel['y']
                                 elif self.pos['y'] + self.r > floor_pos['y'] + (floor_dim['y'] / 2):
                                 elif self.pos['y'] + self.r > floor_pos['y'] + (floor_dim['y'] / 2):
                                     self.pos['y'] = floor_pos['y'] + (floor_dim['y'] / 2) - self.r  # Correct position
                                     self.pos['y'] = floor_pos['y'] + (floor_dim['y'] / 2) - self.r  # Correct position
@@ -605,11 +616,12 @@
                     <transition event="update_bounds" target=".">
                     <transition event="update_bounds" target=".">
                         <parameter name="pos" type="dict" />
                         <parameter name="pos" type="dict" />
                         <parameter name="dim" type="dict" />
                         <parameter name="dim" type="dict" />
-                        <parameter name="vel" type="dict" />
+                        <parameter name="vel" type="int" />
                         <script>
                         <script>
                             self.rect_pos = pos
                             self.rect_pos = pos
                             self.rect_dim = dim
                             self.rect_dim = dim
                             self.rect_vel = vel
                             self.rect_vel = vel
+                            self.elevator_open = False
                         </script>
                         </script>
                     </transition>
                     </transition>
                 </state>
                 </state>
@@ -659,14 +671,14 @@
                         <parameter name="button" />
                         <parameter name="button" />
                         <script>
                         <script>
                             <![CDATA[
                             <![CDATA[
-                            self.mouse_pos = {'x':x, 'y':y};
+                            self.mouse_pos = {'x': x, 'y': y};
                             ]]>
                             ]]>
                         </script>
                         </script>
                     </transition>
                     </transition>
                 </state>
                 </state>
                 <state id="ball_delete">
                 <state id="ball_delete">
                     <transition event="delete_self" target='../../deleted'>                    
                     <transition event="delete_self" target='../../deleted'>                    
-                        <raise event="delete_ball" scope="narrow" target="'parent'">
+                        <raise event="delete_ball" scope="narrow" target="'floor'">
                             <parameter expr='self.association_name' />
                             <parameter expr='self.association_name' />
                         </raise>
                         </raise>
                         <raise port="ui" event="destroy_element">
                         <raise port="ui" event="destroy_element">
@@ -679,5 +691,4 @@
             <state id='deleted' />
             <state id='deleted' />
         </scxml>
         </scxml>
     </class>
     </class>
-
 </diagram>
 </diagram>

+ 1 - 1
sccd/runtime/DEVS_loop.py

@@ -8,7 +8,7 @@ def get_port(text):
 		result = match.group(1)
 		result = match.group(1)
 		return result
 		return result
 	else:
 	else:
-		return None
+		return text
 
 
 
 
 class DEVSSimulator(Simulator):
 class DEVSSimulator(Simulator):

+ 0 - 12
tests/BrokenTest/runner.py

@@ -1,12 +0,0 @@
-import target as target
-import threading
-from sccd.runtime.statecharts_core import Event
-
-controller = target.Controller(False)
-def raw_inputter():
-    while 1:
-        controller.addInput(Event(raw_input(), "input", []))
-thread = threading.Thread(target=raw_inputter)
-thread.daemon = True
-thread.start()
-controller.start()

+ 0 - 65
tests/BrokenTest/sccd.xml

@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<diagram author="Yentl Van Tendeloo+Simon Van Mierlo" name="broken">
-    <description>
-        Broken!
-        Sam: The file was called external input
-    </description>
-    
-    <inport name="input" />
-
-    <class name="A" default="true">
-        <relationships>
-            <association name="child" class="B" min="0" max="1"/>
-        </relationships>
-
-        <scxml initial="x">
-            <state id="x">
-                <onentry>
-                    <raise scope="cd" event="create_instance">
-                        <parameter expr="'child'"/>
-                        <parameter expr="'B'"/>
-                    </raise>
-                </onentry>
-
-                <transition event="instance_created" target="../ready">
-                    <parameter name="instancename"/>
-                    <script>
-                        self.instancename = instancename
-                    </script>
-                    <raise scope="cd" event="start_instance">
-                        <parameter expr="self.instancename"/>
-                    </raise>
-                </transition>
-            </state>
-            <state id="ready">
-                <transition after="0.001" target=".">
-                    <script>
-                        for _ in range(100000):
-                            pass
-                    </script>
-                </transition>
-                <transition event="close" target="../done">
-                    <raise scope="cd" event="delete_instance">
-                        <parameter expr="self.instancename"/>
-                    </raise>
-                </transition>
-            </state>
-            <state id="done"/>
-        </scxml>
-    </class>
-
-    <class name="B">
-        <relationships>
-            <association name="parent" class="A" min="1" max="1"/>
-        </relationships>
-
-        <scxml initial="z">
-            <state id="z">
-                <transition event="stop" port="input" target=".">
-                    <raise event="close" target="'parent[0]'" />
-                </transition>
-            </state>
-        </scxml>
-    </class>
-
-</diagram>

+ 1 - 1
tests/Test1/PyDEVS/target.py

@@ -4,7 +4,7 @@ Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van M
 Model author: Sam Pieters
 Model author: Sam Pieters
 Model name:   EndingTest
 Model name:   EndingTest
 Model description:
 Model description:
-Test 1: Check if the program ends on time.
+Test 1: Check if the model ends on time.
 """
 """
 
 
 from sccd.runtime.DEVS_statecharts_core import *
 from sccd.runtime.DEVS_statecharts_core import *

+ 12 - 5
tests/Test1/Python/runner.py

@@ -1,9 +1,16 @@
-import tests.Test1.Python.target as target
+import target as target
+from sccd.runtime.statecharts_core import Event
+import threading
+
+class OutputListener:
+	def add(self, event):
+		if event.port == "ui":
+			print(event.name, ", received on:", event.parameters[0], "seconds, parameters:", event.parameters[1:])
+				
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
 	controller = target.Controller()
 	controller = target.Controller()
 	controller.keep_running = False
 	controller.keep_running = False
-	controller.setVerbose(None)
-	controller.start()
-
-	
+	controller.addMyOwnOutputListener(OutputListener())
+	controller.setVerbose("check.txt")
+	controller.start()

+ 1 - 1
tests/Test1/Python/target.py

@@ -4,7 +4,7 @@ Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van M
 Model author: Sam Pieters
 Model author: Sam Pieters
 Model name:   EndingTest
 Model name:   EndingTest
 Model description:
 Model description:
-Test 1: Check if the program ends on time.
+Test 1: Check if the model ends on time.
 """
 """
 
 
 from sccd.runtime.statecharts_core import *
 from sccd.runtime.statecharts_core import *

+ 2 - 2
tests/Test3/PyDEVS/target.py

@@ -2,14 +2,14 @@
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration) and Sam Pieters (DEVS)
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration) and Sam Pieters (DEVS)
 
 
 Model author: Sam Pieters
 Model author: Sam Pieters
-Model name:   Output Test
+Model name:   Multiple Output Test
 Model description:
 Model description:
 Test 3: Check if the model outputs multiple events with an interval on the right time.
 Test 3: Check if the model outputs multiple events with an interval on the right time.
 """
 """
 
 
 from sccd.runtime.DEVS_statecharts_core import *
 from sccd.runtime.DEVS_statecharts_core import *
 
 
-# package "Output Test"
+# package "Multiple Output Test"
 
 
 class MainAppInstance(RuntimeClassBase):
 class MainAppInstance(RuntimeClassBase):
     def __init__(self, atomdevs):
     def __init__(self, atomdevs):

+ 2 - 2
tests/Test3/Python/target.py

@@ -2,14 +2,14 @@
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
 
 Model author: Sam Pieters
 Model author: Sam Pieters
-Model name:   Output Test
+Model name:   Multiple Output Test
 Model description:
 Model description:
 Test 3: Check if the model outputs multiple events with an interval on the right time.
 Test 3: Check if the model outputs multiple events with an interval on the right time.
 """
 """
 
 
 from sccd.runtime.statecharts_core import *
 from sccd.runtime.statecharts_core import *
 
 
-# package "Output Test"
+# package "Multiple Output Test"
 
 
 class MainApp(RuntimeClassBase):
 class MainApp(RuntimeClassBase):
     def __init__(self, controller):
     def __init__(self, controller):

+ 10 - 7
tests/Test4/sccd.xml

@@ -1,22 +1,25 @@
 <?xml version="1.1" ?>
 <?xml version="1.1" ?>
-<diagram author="Sam Pieters" name="Input Test">
+<diagram author="Sam Pieters" name="Global Input Test">
     <description>
     <description>
-        Test 4: Check if the model receives input on the right rime and sends and output event after 0.5 seconds.
+        Test 4: Check if the model receives input on the right time.
     </description>
     </description>
     <inport name="ui"/>
     <inport name="ui"/>
     <outport name="ui"/>
     <outport name="ui"/>
     <class name="MainApp" default="true">
     <class name="MainApp" default="true">
         <scxml initial="state1">
         <scxml initial="state1">
             <state id="state1">
             <state id="state1">
-                <transition event="input_test_event" target="../state2" />
-            </state>
-            <state id="state2">
                 <onentry>
                 <onentry>
-                    <raise port="ui" event="test_event">
-                        <parameter expr="str(self.amount)" />
+                    <raise port="ui" event="output_event">
                         <parameter expr="str('%.2f' % (self.getSimulatedTime() / 1000.0))" />
                         <parameter expr="str('%.2f' % (self.getSimulatedTime() / 1000.0))" />
                     </raise>
                     </raise>
                 </onentry>
                 </onentry>
+                <transition event="input_event" target="../state2">
+                    <raise port="ui" event="received">
+                        <parameter expr="str('%.2f' % (self.getSimulatedTime() / 1000.0))" />
+                    </raise>
+                </transition>
+            </state>
+            <state id="state2">
             </state>
             </state>
         </scxml>
         </scxml>
     </class>
     </class>