"""
Generated by Statechart compiler by Glenn De Jonghe and Joeri Exelmans

Date:   Tue Jan 26 10:23:07 2016

Model author: Simon Van Mierlo
Model name:   Particle Interaction
Model description:
Visualization of Particle Interaction Simulation
"""

from python_runtime.statecharts_core import *
import Tkinter as tk
from tkinter_widget import TkinterWidget

# package "Particle Interaction"

class MainApp(RuntimeClassBase):
	def __init__(self, controller, root, resolution):
		RuntimeClassBase.__init__(self, controller)
		
		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
		
		# Call user defined constructor
		MainApp.user_defined_constructor(self, root, resolution)
	
	def user_defined_constructor(self, root, resolution):
		self.nr_of_fields = 0
		self.root = root
		self.resolution = resolution
	
	def user_defined_destructor(self):
		pass
	
	def initializeStatechart(self):
		self.current_state[self.Root] = []
		self.current_state[self.Root_main] = []
		self.current_state[self.Root_main_main_behaviour] = []
		self.current_state[self.Root_main_creating_behaviour] = []
		self.current_state[self.Root_main_deleting_behaviour] = []
		
		# Enter default state
		self.enterDefault_Root_main()
	
	# Unique IDs for all statechart nodes
	Root = 0
	Root_main = 1
	Root_main_main_behaviour = 2
	Root_main_creating_behaviour = 3
	Root_main_deleting_behaviour = 4
	Root_main_main_behaviour_initializing = 5
	Root_main_main_behaviour_running = 6
	Root_main_creating_behaviour_waiting = 7
	Root_main_creating_behaviour_creating = 8
	Root_main_deleting_behaviour_waiting = 9
	Root_main_deleting_behaviour_deleting = 10
	Root_stopped = 11
	
	# Statechart enter/exit action method(s)
	
	def enter_Root_main(self):
		self.current_state[self.Root].append(self.Root_main)
	
	def exit_Root_main(self):
		self.exit_Root_main_main_behaviour()
		self.exit_Root_main_creating_behaviour()
		self.exit_Root_main_deleting_behaviour()
		self.current_state[self.Root] = []
	
	def enter_Root_main_main_behaviour(self):
		self.current_state[self.Root_main].append(self.Root_main_main_behaviour)
	
	def exit_Root_main_main_behaviour(self):
		if self.Root_main_main_behaviour_initializing in self.current_state[self.Root_main_main_behaviour]:
			self.exit_Root_main_main_behaviour_initializing()
		if self.Root_main_main_behaviour_running in self.current_state[self.Root_main_main_behaviour]:
			self.exit_Root_main_main_behaviour_running()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_creating_behaviour(self):
		self.current_state[self.Root_main].append(self.Root_main_creating_behaviour)
	
	def exit_Root_main_creating_behaviour(self):
		if self.Root_main_creating_behaviour_waiting in self.current_state[self.Root_main_creating_behaviour]:
			self.exit_Root_main_creating_behaviour_waiting()
		if self.Root_main_creating_behaviour_creating in self.current_state[self.Root_main_creating_behaviour]:
			self.exit_Root_main_creating_behaviour_creating()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_deleting_behaviour(self):
		self.current_state[self.Root_main].append(self.Root_main_deleting_behaviour)
	
	def exit_Root_main_deleting_behaviour(self):
		if self.Root_main_deleting_behaviour_waiting in self.current_state[self.Root_main_deleting_behaviour]:
			self.exit_Root_main_deleting_behaviour_waiting()
		if self.Root_main_deleting_behaviour_deleting in self.current_state[self.Root_main_deleting_behaviour]:
			self.exit_Root_main_deleting_behaviour_deleting()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_main_behaviour_initializing(self):
		self.raiseInternalEvent(Event("create_field", None, []))
		self.current_state[self.Root_main_main_behaviour].append(self.Root_main_main_behaviour_initializing)
	
	def exit_Root_main_main_behaviour_initializing(self):
		self.current_state[self.Root_main_main_behaviour] = []
	
	def enter_Root_main_main_behaviour_running(self):
		self.current_state[self.Root_main_main_behaviour].append(self.Root_main_main_behaviour_running)
	
	def exit_Root_main_main_behaviour_running(self):
		self.current_state[self.Root_main_main_behaviour] = []
	
	def enter_Root_main_creating_behaviour_waiting(self):
		self.current_state[self.Root_main_creating_behaviour].append(self.Root_main_creating_behaviour_waiting)
	
	def exit_Root_main_creating_behaviour_waiting(self):
		self.current_state[self.Root_main_creating_behaviour] = []
	
	def enter_Root_main_creating_behaviour_creating(self):
		self.current_state[self.Root_main_creating_behaviour].append(self.Root_main_creating_behaviour_creating)
	
	def exit_Root_main_creating_behaviour_creating(self):
		self.current_state[self.Root_main_creating_behaviour] = []
	
	def enter_Root_main_deleting_behaviour_waiting(self):
		self.current_state[self.Root_main_deleting_behaviour].append(self.Root_main_deleting_behaviour_waiting)
	
	def exit_Root_main_deleting_behaviour_waiting(self):
		self.current_state[self.Root_main_deleting_behaviour] = []
	
	def enter_Root_main_deleting_behaviour_deleting(self):
		self.current_state[self.Root_main_deleting_behaviour].append(self.Root_main_deleting_behaviour_deleting)
	
	def exit_Root_main_deleting_behaviour_deleting(self):
		self.current_state[self.Root_main_deleting_behaviour] = []
	
	def enter_Root_stopped(self):
		self.root.quit()
		self.current_state[self.Root].append(self.Root_stopped)
	
	def exit_Root_stopped(self):
		self.current_state[self.Root] = []
	
	# Statechart enter/exit default method(s)
	
	def enterDefault_Root_main(self):
		self.enter_Root_main()
		self.enterDefault_Root_main_main_behaviour()
		self.enterDefault_Root_main_creating_behaviour()
		self.enterDefault_Root_main_deleting_behaviour()
	
	def enterDefault_Root_main_main_behaviour(self):
		self.enter_Root_main_main_behaviour()
		self.enter_Root_main_main_behaviour_initializing()
	
	def enterDefault_Root_main_creating_behaviour(self):
		self.enter_Root_main_creating_behaviour()
		self.enter_Root_main_creating_behaviour_waiting()
	
	def enterDefault_Root_main_deleting_behaviour(self):
		self.enter_Root_main_deleting_behaviour()
		self.enter_Root_main_deleting_behaviour_waiting()
	
	# Statechart transitions
	
	def generateCandidatesChildren_Root(self):
		if self.current_state[self.Root][0] == self.Root_main:
			return self.generateCandidates_Root_main()
		elif self.current_state[self.Root][0] == self.Root_stopped:
			return self.generateCandidates_Root_stopped()
		return False
	
	def generateCandidates_Root(self):
		if not self.combo_step.isArenaChanged(self.Root):
			return self.generateCandidatesChildren_Root()
		else:
			return True
	
	def generateCandidatesChildren_Root_main(self):
		branch_done = False
		branch_done = (self.generateCandidates_Root_main_main_behaviour() or branch_done)
		branch_done = (self.generateCandidates_Root_main_creating_behaviour() or branch_done)
		branch_done = (self.generateCandidates_Root_main_deleting_behaviour() or branch_done)
		return branch_done
	
	def generateCandidatesCurrent_Root_main(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "stop":
				self.small_step.addCandidate(self.transition_Root_main_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main(self):
		if not self.combo_step.isArenaChanged(self.Root_main):
			branch_done = False
			if self.semantics.priority == StatechartSemantics.SourceParent:
				branch_done = self.generateCandidatesCurrent_Root_main()
				if not branch_done:
					branch_done = self.generateCandidatesChildren_Root_main()
			elif self.semantics.priority == StatechartSemantics.SourceChild:
				branch_done = self.generateCandidatesChildren_Root_main()
				if not branch_done:
					branch_done = self.generateCandidatesCurrent_Root_main()
			return branch_done
		else:
			return True
	
	def transition_Root_main_1(self, parameters):
		self.exit_Root_main()
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_stopped()
	
	def generateCandidatesChildren_Root_main_main_behaviour(self):
		if self.current_state[self.Root_main_main_behaviour][0] == self.Root_main_main_behaviour_initializing:
			return self.generateCandidates_Root_main_main_behaviour_initializing()
		elif self.current_state[self.Root_main_main_behaviour][0] == self.Root_main_main_behaviour_running:
			return self.generateCandidates_Root_main_main_behaviour_running()
		return False
	
	def generateCandidates_Root_main_main_behaviour(self):
		if not self.combo_step.isArenaChanged(self.Root_main_main_behaviour):
			return self.generateCandidatesChildren_Root_main_main_behaviour()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_main_behaviour_initializing(self):
		enabled_events = self.getEnabledEvents()
		self.small_step.addCandidate(self.transition_Root_main_main_behaviour_initializing_1, [])
		return True
		return False
	
	def generateCandidates_Root_main_main_behaviour_initializing(self):
		if not self.combo_step.isArenaChanged(self.Root_main_main_behaviour_initializing):
			return self.generateCandidatesCurrent_Root_main_main_behaviour_initializing()
		else:
			return True
	
	def transition_Root_main_main_behaviour_initializing_1(self, parameters):
		self.exit_Root_main_main_behaviour_initializing()
		self.combo_step.setArenaChanged(self.Root_main_main_behaviour)
		self.enter_Root_main_main_behaviour_running()
	
	def generateCandidatesCurrent_Root_main_main_behaviour_running(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "field_created":
				self.small_step.addCandidate(self.transition_Root_main_main_behaviour_running_1, e.parameters)
				return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "field_deleted":
				parameters = e.parameters
				if self.nr_of_fields > 1:
					self.small_step.addCandidate(self.transition_Root_main_main_behaviour_running_2, e.parameters)
					return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "field_deleted":
				parameters = e.parameters
				if self.nr_of_fields == 1:
					self.small_step.addCandidate(self.transition_Root_main_main_behaviour_running_3, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_main_main_behaviour_running(self):
		if not self.combo_step.isArenaChanged(self.Root_main_main_behaviour_running):
			return self.generateCandidatesCurrent_Root_main_main_behaviour_running()
		else:
			return True
	
	def transition_Root_main_main_behaviour_running_1(self, parameters):
		self.exit_Root_main_main_behaviour_running()
		self.nr_of_fields += 1
		self.combo_step.setArenaChanged(self.Root_main_main_behaviour)
		self.enter_Root_main_main_behaviour_running()
	
	def transition_Root_main_main_behaviour_running_2(self, parameters):
		self.exit_Root_main_main_behaviour_running()
		self.nr_of_fields -= 1
		self.combo_step.setArenaChanged(self.Root_main_main_behaviour)
		self.enter_Root_main_main_behaviour_running()
	
	def transition_Root_main_main_behaviour_running_3(self, parameters):
		self.exit_Root_main_main_behaviour_running()
		self.raiseInternalEvent(Event("stop", None, []))
		self.combo_step.setArenaChanged(self.Root_main_main_behaviour)
		self.enter_Root_main_main_behaviour_running()
	
	def generateCandidatesChildren_Root_main_creating_behaviour(self):
		if self.current_state[self.Root_main_creating_behaviour][0] == self.Root_main_creating_behaviour_waiting:
			return self.generateCandidates_Root_main_creating_behaviour_waiting()
		elif self.current_state[self.Root_main_creating_behaviour][0] == self.Root_main_creating_behaviour_creating:
			return self.generateCandidates_Root_main_creating_behaviour_creating()
		return False
	
	def generateCandidates_Root_main_creating_behaviour(self):
		if not self.combo_step.isArenaChanged(self.Root_main_creating_behaviour):
			return self.generateCandidatesChildren_Root_main_creating_behaviour()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_creating_behaviour_waiting(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "create_field":
				self.small_step.addCandidate(self.transition_Root_main_creating_behaviour_waiting_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_creating_behaviour_waiting(self):
		if not self.combo_step.isArenaChanged(self.Root_main_creating_behaviour_waiting):
			return self.generateCandidatesCurrent_Root_main_creating_behaviour_waiting()
		else:
			return True
	
	def transition_Root_main_creating_behaviour_waiting_1(self, parameters):
		self.exit_Root_main_creating_behaviour_waiting()
		self.big_step.outputEventOM(Event("create_instance", None, [self, 'fields', 'Field', self.resolution]))
		self.combo_step.setArenaChanged(self.Root_main_creating_behaviour)
		self.enter_Root_main_creating_behaviour_creating()
	
	def generateCandidatesCurrent_Root_main_creating_behaviour_creating(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "instance_created":
				self.small_step.addCandidate(self.transition_Root_main_creating_behaviour_creating_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_creating_behaviour_creating(self):
		if not self.combo_step.isArenaChanged(self.Root_main_creating_behaviour_creating):
			return self.generateCandidatesCurrent_Root_main_creating_behaviour_creating()
		else:
			return True
	
	def transition_Root_main_creating_behaviour_creating_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_main_creating_behaviour_creating()
		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.raiseInternalEvent(Event("field_created", None, []))
		self.combo_step.setArenaChanged(self.Root_main_creating_behaviour)
		self.enter_Root_main_creating_behaviour_waiting()
	
	def generateCandidatesChildren_Root_main_deleting_behaviour(self):
		if self.current_state[self.Root_main_deleting_behaviour][0] == self.Root_main_deleting_behaviour_waiting:
			return self.generateCandidates_Root_main_deleting_behaviour_waiting()
		elif self.current_state[self.Root_main_deleting_behaviour][0] == self.Root_main_deleting_behaviour_deleting:
			return self.generateCandidates_Root_main_deleting_behaviour_deleting()
		return False
	
	def generateCandidates_Root_main_deleting_behaviour(self):
		if not self.combo_step.isArenaChanged(self.Root_main_deleting_behaviour):
			return self.generateCandidatesChildren_Root_main_deleting_behaviour()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_deleting_behaviour_waiting(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "delete_field":
				self.small_step.addCandidate(self.transition_Root_main_deleting_behaviour_waiting_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_deleting_behaviour_waiting(self):
		if not self.combo_step.isArenaChanged(self.Root_main_deleting_behaviour_waiting):
			return self.generateCandidatesCurrent_Root_main_deleting_behaviour_waiting()
		else:
			return True
	
	def transition_Root_main_deleting_behaviour_waiting_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_main_deleting_behaviour_waiting()
		self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
		self.combo_step.setArenaChanged(self.Root_main_deleting_behaviour)
		self.enter_Root_main_deleting_behaviour_deleting()
	
	def generateCandidatesCurrent_Root_main_deleting_behaviour_deleting(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "instance_deleted":
				self.small_step.addCandidate(self.transition_Root_main_deleting_behaviour_deleting_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_deleting_behaviour_deleting(self):
		if not self.combo_step.isArenaChanged(self.Root_main_deleting_behaviour_deleting):
			return self.generateCandidatesCurrent_Root_main_deleting_behaviour_deleting()
		else:
			return True
	
	def transition_Root_main_deleting_behaviour_deleting_1(self, parameters):
		self.exit_Root_main_deleting_behaviour_deleting()
		self.raiseInternalEvent(Event("field_deleted", None, []))
		self.combo_step.setArenaChanged(self.Root_main_deleting_behaviour)
		self.enter_Root_main_deleting_behaviour_waiting()
	
	def generateCandidates_Root_stopped(self):
		return False
	
	# Generate transition candidates for current small step
	def generateCandidates(self):
		self.generateCandidates_Root()

class Field(RuntimeClassBase, tk.Toplevel, TkinterWidget):
	def __init__(self, controller, resolution):
		RuntimeClassBase.__init__(self, controller)
		
		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
		
		# Call user defined constructor
		Field.user_defined_constructor(self, resolution)
	
	def user_defined_constructor(self, resolution):
		tk.Toplevel.__init__(self)
		TkinterWidget.__init__(self, True)
		self.geometry('{}x{}'.format(resolution[0], resolution[1]))                
		CANVAS_SIZE_TUPLE = (0, 0, self.winfo_screenwidth(), self.winfo_screenheight())
		self.canvas = tk.Canvas(self, relief=tk.RIDGE, scrollregion=CANVAS_SIZE_TUPLE)
		self.canvas.focus_force()
		self.canvas.pack(expand = True, fill=tk.BOTH)
		self.text = self.canvas.create_text(5, 5, anchor='nw', text="TIME: %s" % 0.0)
		self.title('Particle Interaction')
		
		self.particles = {}
		self.creates = []
		self.moves = []
		self.color_changes = []
		self.deletes = []
		self.new_particle_id = None
		
		self.set_bindable_and_tagorid(self.canvas)
		
		self.positions = {}
		self.curr_positions = {}
	
	def user_defined_destructor(self):
		self.destroy()
		# Call super class destructors
		if hasattr(tk.Toplevel, "__del__"):
			tk.Toplevel.__del__(self)
		if hasattr(TkinterWidget, "__del__"):
			TkinterWidget.__del__(self)
	
	def initializeStatechart(self):
		self.current_state[self.Root] = []
		self.current_state[self.Root_main] = []
		self.current_state[self.Root_main_main_behaviour] = []
		self.current_state[self.Root_main_creating_behaviour] = []
		self.current_state[self.Root_main_listening_behaviour] = []
		
		# Enter default state
		self.enterDefault_Root_main()
	
	# Unique IDs for all statechart nodes
	Root = 0
	Root_main = 1
	Root_main_main_behaviour = 2
	Root_main_creating_behaviour = 3
	Root_main_listening_behaviour = 4
	Root_main_main_behaviour_initializing = 5
	Root_main_main_behaviour_running = 6
	Root_main_creating_behaviour_idle = 7
	Root_main_creating_behaviour_creating_particle = 8
	Root_main_listening_behaviour_listening = 9
	Root_stopped = 10
	
	# Statechart enter/exit action method(s)
	
	def enter_Root_main(self):
		self.current_state[self.Root].append(self.Root_main)
	
	def exit_Root_main(self):
		self.exit_Root_main_main_behaviour()
		self.exit_Root_main_creating_behaviour()
		self.exit_Root_main_listening_behaviour()
		self.current_state[self.Root] = []
	
	def enter_Root_main_main_behaviour(self):
		self.current_state[self.Root_main].append(self.Root_main_main_behaviour)
	
	def exit_Root_main_main_behaviour(self):
		if self.Root_main_main_behaviour_initializing in self.current_state[self.Root_main_main_behaviour]:
			self.exit_Root_main_main_behaviour_initializing()
		if self.Root_main_main_behaviour_running in self.current_state[self.Root_main_main_behaviour]:
			self.exit_Root_main_main_behaviour_running()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_creating_behaviour(self):
		self.current_state[self.Root_main].append(self.Root_main_creating_behaviour)
	
	def exit_Root_main_creating_behaviour(self):
		if self.Root_main_creating_behaviour_idle in self.current_state[self.Root_main_creating_behaviour]:
			self.exit_Root_main_creating_behaviour_idle()
		if self.Root_main_creating_behaviour_creating_particle in self.current_state[self.Root_main_creating_behaviour]:
			self.exit_Root_main_creating_behaviour_creating_particle()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_listening_behaviour(self):
		self.current_state[self.Root_main].append(self.Root_main_listening_behaviour)
	
	def exit_Root_main_listening_behaviour(self):
		if self.Root_main_listening_behaviour_listening in self.current_state[self.Root_main_listening_behaviour]:
			self.exit_Root_main_listening_behaviour_listening()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_main_behaviour_initializing(self):
		self.current_state[self.Root_main_main_behaviour].append(self.Root_main_main_behaviour_initializing)
	
	def exit_Root_main_main_behaviour_initializing(self):
		self.current_state[self.Root_main_main_behaviour] = []
	
	def enter_Root_main_main_behaviour_running(self):
		self.current_state[self.Root_main_main_behaviour].append(self.Root_main_main_behaviour_running)
	
	def exit_Root_main_main_behaviour_running(self):
		self.current_state[self.Root_main_main_behaviour] = []
	
	def enter_Root_main_creating_behaviour_idle(self):
		self.current_state[self.Root_main_creating_behaviour].append(self.Root_main_creating_behaviour_idle)
	
	def exit_Root_main_creating_behaviour_idle(self):
		self.current_state[self.Root_main_creating_behaviour] = []
	
	def enter_Root_main_creating_behaviour_creating_particle(self):
		self.current_state[self.Root_main_creating_behaviour].append(self.Root_main_creating_behaviour_creating_particle)
	
	def exit_Root_main_creating_behaviour_creating_particle(self):
		self.current_state[self.Root_main_creating_behaviour] = []
	
	def enter_Root_main_listening_behaviour_listening(self):
		self.current_state[self.Root_main_listening_behaviour].append(self.Root_main_listening_behaviour_listening)
	
	def exit_Root_main_listening_behaviour_listening(self):
		self.current_state[self.Root_main_listening_behaviour] = []
	
	def enter_Root_stopped(self):
		self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_field", None, [self.association_name])]))
		self.current_state[self.Root].append(self.Root_stopped)
	
	def exit_Root_stopped(self):
		self.current_state[self.Root] = []
	
	# Statechart enter/exit default method(s)
	
	def enterDefault_Root_main(self):
		self.enter_Root_main()
		self.enterDefault_Root_main_main_behaviour()
		self.enterDefault_Root_main_creating_behaviour()
		self.enterDefault_Root_main_listening_behaviour()
	
	def enterDefault_Root_main_main_behaviour(self):
		self.enter_Root_main_main_behaviour()
		self.enter_Root_main_main_behaviour_initializing()
	
	def enterDefault_Root_main_creating_behaviour(self):
		self.enter_Root_main_creating_behaviour()
		self.enter_Root_main_creating_behaviour_idle()
	
	def enterDefault_Root_main_listening_behaviour(self):
		self.enter_Root_main_listening_behaviour()
		self.enter_Root_main_listening_behaviour_listening()
	
	# Statechart transitions
	
	def generateCandidatesChildren_Root(self):
		if self.current_state[self.Root][0] == self.Root_main:
			return self.generateCandidates_Root_main()
		elif self.current_state[self.Root][0] == self.Root_stopped:
			return self.generateCandidates_Root_stopped()
		return False
	
	def generateCandidates_Root(self):
		if not self.combo_step.isArenaChanged(self.Root):
			return self.generateCandidatesChildren_Root()
		else:
			return True
	
	def generateCandidatesChildren_Root_main(self):
		branch_done = False
		branch_done = (self.generateCandidates_Root_main_main_behaviour() or branch_done)
		branch_done = (self.generateCandidates_Root_main_creating_behaviour() or branch_done)
		branch_done = (self.generateCandidates_Root_main_listening_behaviour() or branch_done)
		return branch_done
	
	def generateCandidatesCurrent_Root_main(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "stop":
				self.small_step.addCandidate(self.transition_Root_main_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main(self):
		if not self.combo_step.isArenaChanged(self.Root_main):
			branch_done = False
			if self.semantics.priority == StatechartSemantics.SourceParent:
				branch_done = self.generateCandidatesCurrent_Root_main()
				if not branch_done:
					branch_done = self.generateCandidatesChildren_Root_main()
			elif self.semantics.priority == StatechartSemantics.SourceChild:
				branch_done = self.generateCandidatesChildren_Root_main()
				if not branch_done:
					branch_done = self.generateCandidatesCurrent_Root_main()
			return branch_done
		else:
			return True
	
	def transition_Root_main_1(self, parameters):
		self.exit_Root_main()
		self.big_step.outputEventOM(Event("delete_instance", None, [self, 'particles']))
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_stopped()
	
	def generateCandidatesChildren_Root_main_main_behaviour(self):
		if self.current_state[self.Root_main_main_behaviour][0] == self.Root_main_main_behaviour_initializing:
			return self.generateCandidates_Root_main_main_behaviour_initializing()
		elif self.current_state[self.Root_main_main_behaviour][0] == self.Root_main_main_behaviour_running:
			return self.generateCandidates_Root_main_main_behaviour_running()
		return False
	
	def generateCandidates_Root_main_main_behaviour(self):
		if not self.combo_step.isArenaChanged(self.Root_main_main_behaviour):
			return self.generateCandidatesChildren_Root_main_main_behaviour()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_main_behaviour_initializing(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "set_association_name":
				self.small_step.addCandidate(self.transition_Root_main_main_behaviour_initializing_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_main_behaviour_initializing(self):
		if not self.combo_step.isArenaChanged(self.Root_main_main_behaviour_initializing):
			return self.generateCandidatesCurrent_Root_main_main_behaviour_initializing()
		else:
			return True
	
	def transition_Root_main_main_behaviour_initializing_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_main_main_behaviour_initializing()
		self.association_name = association_name
		self.combo_step.setArenaChanged(self.Root_main_main_behaviour)
		self.enter_Root_main_main_behaviour_running()
	
	def generateCandidatesCurrent_Root_main_main_behaviour_running(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "window-close") and (e.port == "input"):
				parameters = e.parameters
				tagorid = parameters[0]
				if tagorid == id(self):
					self.small_step.addCandidate(self.transition_Root_main_main_behaviour_running_1, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_main_main_behaviour_running(self):
		if not self.combo_step.isArenaChanged(self.Root_main_main_behaviour_running):
			return self.generateCandidatesCurrent_Root_main_main_behaviour_running()
		else:
			return True
	
	def transition_Root_main_main_behaviour_running_1(self, parameters):
		tagorid = parameters[0]
		self.exit_Root_main_main_behaviour_running()
		self.raiseInternalEvent(Event("stop", None, []))
		self.combo_step.setArenaChanged(self.Root_main_main_behaviour)
		self.enter_Root_main_main_behaviour_running()
	
	def generateCandidatesChildren_Root_main_creating_behaviour(self):
		if self.current_state[self.Root_main_creating_behaviour][0] == self.Root_main_creating_behaviour_idle:
			return self.generateCandidates_Root_main_creating_behaviour_idle()
		elif self.current_state[self.Root_main_creating_behaviour][0] == self.Root_main_creating_behaviour_creating_particle:
			return self.generateCandidates_Root_main_creating_behaviour_creating_particle()
		return False
	
	def generateCandidates_Root_main_creating_behaviour(self):
		if not self.combo_step.isArenaChanged(self.Root_main_creating_behaviour):
			return self.generateCandidatesChildren_Root_main_creating_behaviour()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_creating_behaviour_idle(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "create_particle":
				self.small_step.addCandidate(self.transition_Root_main_creating_behaviour_idle_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_creating_behaviour_idle(self):
		if not self.combo_step.isArenaChanged(self.Root_main_creating_behaviour_idle):
			return self.generateCandidatesCurrent_Root_main_creating_behaviour_idle()
		else:
			return True
	
	def transition_Root_main_creating_behaviour_idle_1(self, parameters):
		new_particle_info = parameters[0]
		self.exit_Root_main_creating_behaviour_idle()
		self.big_step.outputEventOM(Event("create_instance", None, [self, "particles", "Particle", self.canvas, new_particle_info[0], new_particle_info[1][0], new_particle_info[1][1], new_particle_info[2]]))
		self.new_particle_id = new_particle_info[0]
		self.combo_step.setArenaChanged(self.Root_main_creating_behaviour)
		self.enter_Root_main_creating_behaviour_creating_particle()
	
	def generateCandidatesCurrent_Root_main_creating_behaviour_creating_particle(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "instance_created":
				self.small_step.addCandidate(self.transition_Root_main_creating_behaviour_creating_particle_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_creating_behaviour_creating_particle(self):
		if not self.combo_step.isArenaChanged(self.Root_main_creating_behaviour_creating_particle):
			return self.generateCandidatesCurrent_Root_main_creating_behaviour_creating_particle()
		else:
			return True
	
	def transition_Root_main_creating_behaviour_creating_particle_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_main_creating_behaviour_creating_particle()
		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.particles[self.new_particle_id] = association_name
		self.combo_step.setArenaChanged(self.Root_main_creating_behaviour)
		self.enter_Root_main_creating_behaviour_idle()
	
	def generateCandidatesChildren_Root_main_listening_behaviour(self):
		if self.current_state[self.Root_main_listening_behaviour][0] == self.Root_main_listening_behaviour_listening:
			return self.generateCandidates_Root_main_listening_behaviour_listening()
		return False
	
	def generateCandidates_Root_main_listening_behaviour(self):
		if not self.combo_step.isArenaChanged(self.Root_main_listening_behaviour):
			return self.generateCandidatesChildren_Root_main_listening_behaviour()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_listening_behaviour_listening(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "update_time") and (e.port == "input"):
				self.small_step.addCandidate(self.transition_Root_main_listening_behaviour_listening_1, e.parameters)
				return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "create_particle") and (e.port == "input"):
				self.small_step.addCandidate(self.transition_Root_main_listening_behaviour_listening_2, e.parameters)
				return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "delete_particle") and (e.port == "input"):
				self.small_step.addCandidate(self.transition_Root_main_listening_behaviour_listening_3, e.parameters)
				return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "delete") and (e.port == "input"):
				self.small_step.addCandidate(self.transition_Root_main_listening_behaviour_listening_4, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_listening_behaviour_listening(self):
		if not self.combo_step.isArenaChanged(self.Root_main_listening_behaviour_listening):
			return self.generateCandidatesCurrent_Root_main_listening_behaviour_listening()
		else:
			return True
	
	def transition_Root_main_listening_behaviour_listening_1(self, parameters):
		new_time = parameters[0]
		self.exit_Root_main_listening_behaviour_listening()
		self.canvas.itemconfig(self.text, text=new_time)
		self.combo_step.setArenaChanged(self.Root_main_listening_behaviour)
		self.enter_Root_main_listening_behaviour_listening()
	
	def transition_Root_main_listening_behaviour_listening_2(self, parameters):
		params = parameters[0]
		self.exit_Root_main_listening_behaviour_listening()
		self.raiseInternalEvent(Event("create_particle", None, [params]))
		self.combo_step.setArenaChanged(self.Root_main_listening_behaviour)
		self.enter_Root_main_listening_behaviour_listening()
	
	def transition_Root_main_listening_behaviour_listening_3(self, parameters):
		particle_id = parameters[0]
		self.exit_Root_main_listening_behaviour_listening()
		self.big_step.outputEventOM(Event("delete_instance", None, [self, self.particles[particle_id]]))
		del self.particles[particle_id]
		self.combo_step.setArenaChanged(self.Root_main_listening_behaviour)
		self.enter_Root_main_listening_behaviour_listening()
	
	def transition_Root_main_listening_behaviour_listening_4(self, parameters):
		clicked_id = parameters[0]
		self.exit_Root_main_listening_behaviour_listening()
		self.big_step.outputEvent(Event("delete_selected", "output", []))
		self.combo_step.setArenaChanged(self.Root_main_listening_behaviour)
		self.enter_Root_main_listening_behaviour_listening()
	
	def generateCandidates_Root_stopped(self):
		return False
	
	# Generate transition candidates for current small step
	def generateCandidates(self):
		self.generateCandidates_Root()

class Particle(RuntimeClassBase, TkinterWidget):
	def __init__(self, controller, canvas, particle_id, x, y, r):
		RuntimeClassBase.__init__(self, controller)
		
		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
		
		# Call user defined constructor
		Particle.user_defined_constructor(self, canvas, particle_id, x, y, r)
	
	def user_defined_constructor(self, canvas, particle_id, x, y, r):
		TkinterWidget.__init__(self, True)
		self.canvas = canvas
		self.x = x
		self.y = y
		self.r = r
		self.circle_id = self.canvas.create_oval(x - r, y - r, x + r, y + r, fill="red")
		self.middle_id = self.canvas.create_oval(x - 4, y - 4, x + 4, y + 4, fill="orange")
		self.set_bindable_and_tagorid(self.canvas, [self.circle_id, self.middle_id])
		self.particle_id = particle_id
	
	def user_defined_destructor(self):
		self.canvas.delete(self.circle_id)
		self.canvas.delete(self.middle_id)
		# Call super class destructors
		if hasattr(TkinterWidget, "__del__"):
			TkinterWidget.__del__(self)
	
	def initializeStatechart(self):
		self.current_state[self.Root] = []
		
		# Enter default state
		self.enter_Root_initializing()
	
	# Unique IDs for all statechart nodes
	Root = 0
	Root_initializing = 1
	Root_running = 2
	Root_deleted = 3
	
	# Statechart enter/exit action method(s)
	
	def enter_Root_initializing(self):
		self.current_state[self.Root].append(self.Root_initializing)
	
	def exit_Root_initializing(self):
		self.current_state[self.Root] = []
	
	def enter_Root_running(self):
		self.current_state[self.Root].append(self.Root_running)
	
	def exit_Root_running(self):
		self.current_state[self.Root] = []
	
	def enter_Root_deleted(self):
		self.current_state[self.Root].append(self.Root_deleted)
	
	def exit_Root_deleted(self):
		self.current_state[self.Root] = []
	
	# Statechart transitions
	
	def generateCandidatesChildren_Root(self):
		if self.current_state[self.Root][0] == self.Root_initializing:
			return self.generateCandidates_Root_initializing()
		elif self.current_state[self.Root][0] == self.Root_running:
			return self.generateCandidates_Root_running()
		elif self.current_state[self.Root][0] == self.Root_deleted:
			return self.generateCandidates_Root_deleted()
		return False
	
	def generateCandidates_Root(self):
		if not self.combo_step.isArenaChanged(self.Root):
			return self.generateCandidatesChildren_Root()
		else:
			return True
	
	def generateCandidatesCurrent_Root_initializing(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "set_association_name":
				self.small_step.addCandidate(self.transition_Root_initializing_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_initializing(self):
		if not self.combo_step.isArenaChanged(self.Root_initializing):
			return self.generateCandidatesCurrent_Root_initializing()
		else:
			return True
	
	def transition_Root_initializing_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_initializing()
		self.association_name = association_name
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_running()
	
	def generateCandidatesCurrent_Root_running(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "move_particle") and (e.port == "input"):
				parameters = e.parameters
				params = parameters[0]
				if params[0] == self.particle_id:
					self.small_step.addCandidate(self.transition_Root_running_1, e.parameters)
					return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "color_particle") and (e.port == "input"):
				parameters = e.parameters
				params = parameters[0]
				if params[0] == self.particle_id:
					self.small_step.addCandidate(self.transition_Root_running_2, e.parameters)
					return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "left-click") and (e.port == "input"):
				parameters = e.parameters
				clicked_id = parameters[0]
				if clicked_id == id(self):
					self.small_step.addCandidate(self.transition_Root_running_3, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_running(self):
		if not self.combo_step.isArenaChanged(self.Root_running):
			return self.generateCandidatesCurrent_Root_running()
		else:
			return True
	
	def transition_Root_running_1(self, parameters):
		params = parameters[0]
		self.exit_Root_running()
		x, y = params[1]
		curr_pos = self.canvas.coords(self.circle_id)
		self.canvas.move(self.circle_id, x - self.r - curr_pos[0], y - self.r - curr_pos[1])
		curr_pos_middle = self.canvas.coords(self.middle_id)
		self.canvas.move(self.middle_id, x - 4 - curr_pos_middle[0], y - 4 - curr_pos_middle[1])
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_running()
	
	def transition_Root_running_2(self, parameters):
		params = parameters[0]
		self.exit_Root_running()
		self.canvas.itemconfig(self.circle_id, fill=params[1])
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_running()
	
	def transition_Root_running_3(self, parameters):
		clicked_id = parameters[0]
		self.exit_Root_running()
		self.big_step.outputEvent(Event("particle_clicked", "output", [self.particle_id]))
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_running()
	
	def generateCandidates_Root_deleted(self):
		return False
	
	# Generate transition candidates for current small step
	def generateCandidates(self):
		self.generateCandidates_Root()

class ObjectManager(ObjectManagerBase):
	def __init__(self, controller):
		ObjectManagerBase.__init__(self, controller)
	
	def instantiate(self, class_name, construct_params):
		if class_name == "MainApp":
			instance = MainApp(self.controller, construct_params[0], construct_params[1])
			instance.associations = {}
			instance.associations["fields"] = Association("Field", 0, -1)
		elif class_name == "Field":
			instance = Field(self.controller, construct_params[0])
			instance.associations = {}
			instance.associations["parent"] = Association("MainApp", 1, 1)
			instance.associations["particles"] = Association("Particle", 0, -1)
		elif class_name == "Particle":
			instance = Particle(self.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3], construct_params[4])
			instance.associations = {}
			instance.associations["parent"] = Association("Field", 1, 1)
		return instance

class Controller(EventLoopControllerBase):
	def __init__(self, root, resolution, event_loop_callbacks, finished_callback = None):
		if finished_callback == None: finished_callback = None
		EventLoopControllerBase.__init__(self, ObjectManager(self), event_loop_callbacks, finished_callback)
		self.addInputPort("input")
		self.addInputPort("output")
		self.object_manager.createInstance("MainApp", [root, resolution])