SFCViewer.py
changeset 0 b622defdfd98
child 1 e9d01d824086
equal deleted inserted replaced
-1:000000000000 0:b622defdfd98
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard.
       
     6 #
       
     7 #Copyright (C): Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU Lesser General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #Lesser General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU Lesser General Public
       
    22 #License along with this library; if not, write to the Free Software
       
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    24 
       
    25 from wxPython.wx import *
       
    26 from wxPython.grid import *
       
    27 import wx
       
    28 from types import *
       
    29 
       
    30 from plcopen.structures import *
       
    31 from graphics.GraphicCommons import *
       
    32 from graphics.SFC_Objects import *
       
    33 from Viewer import *
       
    34 
       
    35 class SFC_Viewer(Viewer):
       
    36     
       
    37     def __init__(self, parent, window, controler):
       
    38         Viewer.__init__(self, parent, window, controler)
       
    39     
       
    40     def ConnectConnectors(self, start, end):
       
    41         startpoint = [start.GetPosition(False), start.GetDirection()]
       
    42         endpoint = [end.GetPosition(False), end.GetDirection()]
       
    43         wire = Wire(self, startpoint, endpoint)
       
    44         self.Wires.append(wire)
       
    45         self.Elements.append(wire)
       
    46         start.Connect((wire, 0), False)
       
    47         end.Connect((wire, -1), False)
       
    48         wire.ConnectStartPoint(None, start)
       
    49         wire.ConnectEndPoint(None, end)
       
    50         return wire
       
    51     
       
    52     def CreateTransition(self, connector, next = None):
       
    53         previous = connector.GetParentBlock()
       
    54         id = self.GetNewId()
       
    55         transition = SFC_Transition(self, "reference", "", id)
       
    56         pos = connector.GetPosition(False)
       
    57         transition.SetPosition(pos.x, pos.y + SFC_WIRE_MIN_SIZE)
       
    58         transition_connectors = transition.GetConnectors()
       
    59         wire = self.ConnectConnectors(transition_connectors["input"], connector)
       
    60         if isinstance(previous, SFC_Divergence):
       
    61             previous.RefreshConnectedPosition(connector)
       
    62         else:
       
    63             previous.RefreshOutputPosition()
       
    64         wire.SetPoints([wxPoint(pos.x, pos.y + GetWireSize(previous)), wxPoint(pos.x, pos.y)])
       
    65         self.Blocks.append(transition)
       
    66         self.Elements.append(transition)
       
    67         self.Controler.AddCurrentElementEditingTransition(id)
       
    68         self.RefreshTransitionModel(transition)
       
    69         if next:
       
    70             wire = self.ConnectConnectors(next, transition_connectors["output"])
       
    71             pos = transition_connectors["output"].GetPosition(False)
       
    72             next_block = next.GetParentBlock()
       
    73             next_pos = next.GetPosition(False)
       
    74             transition.RefreshOutputPosition((0, pos.y + SFC_WIRE_MIN_SIZE - next_pos.y))
       
    75             wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
       
    76             if isinstance(next_block, SFC_Divergence):
       
    77                 next_block.RefreshPosition()
       
    78             next_block.RefreshModel()
       
    79         return transition
       
    80     
       
    81     def RemoveTransition(self, transition):
       
    82         connectors = transition.GetConnectors()
       
    83         input_wires = connectors["input"].GetWires()
       
    84         if len(input_wires) != 1:
       
    85             return
       
    86         input_wire = input_wires[0][0]
       
    87         previous = input_wire.EndConnected
       
    88         input_wire.Clean()
       
    89         self.Wires.remove(input_wire)
       
    90         self.Elements.remove(input_wire)
       
    91         output_wires = connectors["output"].GetWires()
       
    92         if len(output_wires) != 1:
       
    93             return
       
    94         output_wire = output_wires[0][0]
       
    95         next = output_wire.StartConnected
       
    96         output_wire.Clean()
       
    97         self.Wires.remove(output_wire)
       
    98         self.Elements.remove(output_wire)
       
    99         transition.Clean()
       
   100         self.Blocks.remove(transition)
       
   101         self.Elements.remove(transition)
       
   102         self.Controler.RemoveCurrentElementEditingInstance(transition.GetId())
       
   103         wire = self.ConnectConnectors(next, previous)
       
   104         return wire
       
   105     
       
   106     def CreateStep(self, name, connector, next = None):
       
   107         previous = connector.GetParentBlock()
       
   108         id = self.GetNewId()
       
   109         step = SFC_Step(self, name, False, id)
       
   110         if next:
       
   111             step.AddOutput()
       
   112         min_width, min_height = step.GetMinSize()
       
   113         pos = connector.GetPosition(False)
       
   114         step.SetPosition(pos.x, pos.y + SFC_WIRE_MIN_SIZE)
       
   115         step.SetSize(min_width, min_height)
       
   116         step_connectors = step.GetConnectors()
       
   117         wire = self.ConnectConnectors(step_connectors["input"], connector)
       
   118         if isinstance(previous, SFC_Divergence):
       
   119             previous.RefreshConnectedPosition(connector)
       
   120         else:
       
   121             previous.RefreshOutputPosition()
       
   122         wire.SetPoints([wxPoint(pos.x, pos.y + GetWireSize(previous)), wxPoint(pos.x, pos.y)])
       
   123         self.Blocks.append(step)
       
   124         self.Elements.append(step)
       
   125         self.Controler.AddCurrentElementEditingStep(id)
       
   126         self.RefreshStepModel(step)
       
   127         if next:
       
   128             wire = self.ConnectConnectors(next, step_connectors["output"])
       
   129             pos = step_connectors["output"].GetPosition(False)
       
   130             next_block = next.GetParentBlock()
       
   131             next_pos = next.GetPosition(False)
       
   132             step.RefreshOutputPosition((0, pos.y + SFC_WIRE_MIN_SIZE - next_pos.y))
       
   133             wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
       
   134             if isinstance(next_block, SFC_Divergence):
       
   135                 next_block.RefreshPosition()
       
   136             next_block.RefreshModel()
       
   137         return step
       
   138 
       
   139     def RemoveStep(self, step):
       
   140         connectors = step.GetConnectors()
       
   141         if connectors["input"]:
       
   142             input_wires = connectors["input"].GetWires()
       
   143             if len(input_wires) != 1:
       
   144                 return
       
   145             input_wire = input_wires[0][0]
       
   146             previous = input_wire.EndConnected
       
   147             input_wire.Clean()
       
   148             self.Wires.remove(input_wire)
       
   149             self.Elements.remove(input_wire)
       
   150         else:
       
   151             previous = None
       
   152         if connectors["output"]:
       
   153             output_wires = connectors["output"].GetWires()
       
   154             if len(output_wires) != 1:
       
   155                 return
       
   156             output_wire = output_wires[0][0]
       
   157             next = output_wire.StartConnected
       
   158             output_wire.Clean()
       
   159             self.Wires.remove(output_wire)
       
   160             self.Elements.remove(output_wire)
       
   161         else:
       
   162             next = None
       
   163         action = step.GetActionConnector()
       
   164         if action:
       
   165             self.DeleteActionBlock(action.GetParentBlock())
       
   166         step.Clean()
       
   167         self.Blocks.remove(step)
       
   168         self.Elements.remove(step)
       
   169         self.Controler.RemoveCurrentElementEditingInstance(step.GetId())
       
   170         if next and previous:
       
   171             wire = self.ConnectConnectors(next, previous)
       
   172             return wire
       
   173         else:
       
   174             return None
       
   175 
       
   176 #-------------------------------------------------------------------------------
       
   177 #                          Mouse event functions
       
   178 #-------------------------------------------------------------------------------
       
   179 
       
   180     def OnViewerLeftDown(self, event):
       
   181         if self.Mode == MODE_SELECTION:
       
   182             pos = event.GetPosition()
       
   183             if event.ControlDown():
       
   184                 element = self.FindElement(pos, True)
       
   185                 if element and element not in self.Wires:
       
   186                     if isinstance(self.SelectedElement, Graphic_Group):
       
   187                         self.SelectedElement.SelectElement(element)
       
   188                     else:
       
   189                         group = Graphic_Group(self)
       
   190                         self.SelectedElement.SetSelected(False)
       
   191                         group.SelectElement(self.SelectedElement)
       
   192                         group.SelectElement(element)
       
   193                         self.SelectedElement = group
       
   194                     elements = self.SelectedElement.GetElements()
       
   195                     if len(elements) == 0:
       
   196                         self.SelectedElement = element
       
   197                     elif len(elements) == 1:
       
   198                         self.SelectedElement = elements[0]
       
   199             else:
       
   200                 element = self.FindElement(pos)
       
   201                 if self.SelectedElement and self.SelectedElement != element:
       
   202                     if self.SelectedElement in self.Wires:
       
   203                         self.SelectedElement.SetSelectedSegment(None)
       
   204                     else:
       
   205                         self.SelectedElement.SetSelected(False)
       
   206                     self.SelectedElement = None
       
   207                     self.Refresh()
       
   208                 if element:
       
   209                     self.SelectedElement = element
       
   210                     self.SelectedElement.OnLeftDown(event, self.Scaling)
       
   211                     self.Refresh()
       
   212                 else:
       
   213                     self.rubberBand.Reset()
       
   214                     self.rubberBand.OnLeftDown(event, self.Scaling)
       
   215         elif self.Mode == MODE_COMMENT:
       
   216             self.rubberBand.Reset()
       
   217             self.rubberBand.OnLeftDown(event, self.Scaling)
       
   218         elif self.Mode == MODE_WIRE:
       
   219             pos = GetScaledEventPosition(event, self.Scaling)
       
   220             wire = Wire(self, [wxPoint(pos.x, pos.y), SOUTH], [wxPoint(pos.x, pos.y), NORTH])
       
   221             wire.oldPos = pos
       
   222             wire.Handle = (HANDLE_POINT, 0)
       
   223             wire.ProcessDragging(0, 0)
       
   224             wire.Handle = (HANDLE_POINT, 1)
       
   225             self.Wires.append(wire)
       
   226             self.Elements.append(wire)
       
   227             if self.SelectedElement:
       
   228                 self.SelectedElement.SetSelected(False)
       
   229             self.SelectedElement = wire
       
   230             self.Refresh()
       
   231         event.Skip()
       
   232 
       
   233     def OnViewerLeftUp(self, event):
       
   234         if self.rubberBand.IsShown():
       
   235             if self.Mode == MODE_SELECTION:
       
   236                 elements = self.SearchElements(self.rubberBand.GetCurrentExtent())
       
   237                 self.rubberBand.OnLeftUp(event, self.Scaling)
       
   238                 if len(elements) > 0:
       
   239                     self.SelectedElement = Graphic_Group(self)
       
   240                     self.SelectedElement.SetElements(elements)
       
   241                     self.SelectedElement.SetSelected(True)
       
   242                     self.Refresh()
       
   243             elif self.Mode == MODE_COMMENT:
       
   244                 bbox = self.rubberBand.GetCurrentExtent()
       
   245                 self.rubberBand.OnLeftUp(event, self.Scaling)
       
   246                 wxCallAfter(self.AddComment, bbox)
       
   247         elif self.Mode == MODE_INITIAL_STEP:
       
   248             wxCallAfter(self.AddInitialStep, GetScaledEventPosition(event, self.Scaling))
       
   249         elif self.Mode == MODE_SELECTION and self.SelectedElement:
       
   250             if self.SelectedElement in self.Wires:
       
   251                 self.SelectedElement.SetSelectedSegment(0)
       
   252             else:
       
   253                 self.SelectedElement.OnLeftUp(event, self.Scaling)
       
   254             wxCallAfter(self.SetCursor, wxNullCursor)
       
   255             self.ReleaseMouse()
       
   256             self.Refresh()
       
   257         elif self.Mode == MODE_WIRE and self.SelectedElement:
       
   258             self.SelectedElement.ResetPoints()
       
   259             self.SelectedElement.OnMotion(event, self.Scaling)
       
   260             self.SelectedElement.GeneratePoints()
       
   261             self.SelectedElement.RefreshModel()
       
   262             self.SelectedElement.SetSelected(True)
       
   263             self.Refresh()
       
   264         event.Skip()
       
   265     
       
   266     def OnViewerRightUp(self, event):
       
   267         pos = event.GetPosition()
       
   268         element = self.FindElement(pos)
       
   269         if element:
       
   270             if self.SelectedElement and self.SelectedElement != element:
       
   271                 self.SelectedElement.SetSelected(False)
       
   272             self.SelectedElement = element
       
   273             if self.SelectedElement in self.Wires:
       
   274                 self.SelectedElement.SetSelectedSegment(0)
       
   275             else:
       
   276                 self.SelectedElement.SetSelected(True)
       
   277                 self.SelectedElement.OnRightUp(event, self.Scaling)
       
   278             wxCallAfter(self.SetCursor, wxNullCursor)
       
   279             self.ReleaseMouse()
       
   280             self.Refresh()
       
   281         event.Skip()
       
   282     
       
   283     def OnViewerLeftDClick(self, event):
       
   284         if self.Mode == MODE_SELECTION and self.SelectedElement:
       
   285             self.SelectedElement.OnLeftDClick(event, self.Scaling)
       
   286             self.Refresh()
       
   287         event.Skip()
       
   288     
       
   289     def OnViewerMotion(self, event):
       
   290         if self.rubberBand.IsShown():
       
   291             self.rubberBand.OnMotion(event, self.Scaling)
       
   292         elif self.Mode == MODE_SELECTION and self.SelectedElement:
       
   293             if self.SelectedElement not in self.Wires:
       
   294                 self.SelectedElement.OnMotion(event, self.Scaling)
       
   295             self.Refresh()
       
   296         elif self.Mode == MODE_WIRE and self.SelectedElement:
       
   297             self.SelectedElement.ResetPoints()
       
   298             self.SelectedElement.OnMotion(event, self.Scaling)
       
   299             self.SelectedElement.GeneratePoints()
       
   300             self.Refresh()
       
   301         event.Skip()
       
   302 
       
   303 #-------------------------------------------------------------------------------
       
   304 #                          Keyboard event functions
       
   305 #-------------------------------------------------------------------------------
       
   306 
       
   307     def OnChar(self, event):
       
   308         keycode = event.GetKeyCode()
       
   309         if self.Scaling:
       
   310             scaling = self.Scaling
       
   311         else:
       
   312             scaling = (8, 8)
       
   313         if keycode == WXK_DELETE and self.SelectedElement:
       
   314             self.SelectedElement.Delete()
       
   315             self.SelectedElement = None
       
   316         elif keycode == WXK_LEFT and self.SelectedElement:
       
   317             self.SelectedElement.Move(-scaling[0], 0)
       
   318         elif keycode == WXK_RIGHT and self.SelectedElement:
       
   319             self.SelectedElement.Move(scaling[0], 0)
       
   320         elif keycode == WXK_UP and self.SelectedElement:
       
   321             self.SelectedElement.Move(0, -scaling[1])
       
   322         elif keycode == WXK_DOWN and self.SelectedElement:
       
   323             self.SelectedElement.Move(0, scaling[1])
       
   324         self.Refresh()
       
   325         event.Skip()
       
   326         
       
   327 #-------------------------------------------------------------------------------
       
   328 #                          Adding element functions
       
   329 #-------------------------------------------------------------------------------
       
   330 
       
   331     def AddInitialStep(self, pos):
       
   332         dialog = wxTextEntryDialog(self.Parent, "Add a new initial step", "Please enter step name", "", wxOK|wxCANCEL)
       
   333         if dialog.ShowModal() == wxID_OK:
       
   334             id = self.GetNewId()
       
   335             name = dialog.GetValue()
       
   336             step = SFC_Step(self, name, True, id)
       
   337             min_width, min_height = step.GetMinSize()
       
   338             step.SetPosition(pos.x, pos.y)
       
   339             width, height = step.GetSize()
       
   340             step.SetSize(max(min_width, width), max(min_height, height))
       
   341             self.Blocks.append(step)
       
   342             self.Elements.append(step)
       
   343             self.Controler.AddCurrentElementEditingStep(id)
       
   344             self.RefreshStepModel(step)
       
   345             self.Parent.RefreshProjectTree()
       
   346             self.Refresh()
       
   347         dialog.Destroy()
       
   348 
       
   349     def AddStep(self):
       
   350         if self.SelectedElement in self.Wires or isinstance(self.SelectedElement, SFC_Step):
       
   351             dialog = wxTextEntryDialog(self.Parent, "Add a new step", "Please enter step name", "", wxOK|wxCANCEL)
       
   352             if dialog.ShowModal() == wxID_OK:
       
   353                 name = dialog.GetValue()
       
   354                 if self.SelectedElement in self.Wires:
       
   355                     self.SelectedElement.SetSelectedSegment(None)
       
   356                     previous = self.SelectedElement.EndConnected
       
   357                     next = self.SelectedElement.StartConnected
       
   358                     self.SelectedElement.Clean()
       
   359                     self.Wires.remove(self.SelectedElement)
       
   360                     self.Elements.remove(self.SelectedElement)
       
   361                 else:
       
   362                     connectors = self.SelectedElement.GetConnectors()
       
   363                     if connectors["output"]:
       
   364                         previous = connectors["output"]
       
   365                         wires = previous.GetWires()
       
   366                         if len(wires) != 1:
       
   367                             return
       
   368                         wire = wires[0][0]
       
   369                         next = wire.StartConnected
       
   370                         wire.Clean()
       
   371                         self.Wires.remove(wire)
       
   372                         self.Elements.remove(wire)
       
   373                     else:
       
   374                         self.SelectedElement.AddOutput()
       
   375                         connectors = self.SelectedElement.GetConnectors()
       
   376                         self.RefreshStepModel(self.SelectedElement)
       
   377                         previous = connectors["output"]
       
   378                         next = None
       
   379                 previous_block = previous.GetParentBlock()
       
   380                 if isinstance(previous_block, SFC_Step) or isinstance(previous_block, SFC_Divergence) and previous_block.GetType() in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]:
       
   381                     transition = self.CreateTransition(previous)
       
   382                     transition_connectors = transition.GetConnectors()
       
   383                     step = self.CreateStep(name, transition_connectors["output"], next)
       
   384                 else:
       
   385                     step = self.CreateStep(name, previous)
       
   386                     step.AddOutput()
       
   387                     step.RefreshModel()
       
   388                     step_connectors = step.GetConnectors()
       
   389                     transition = self.CreateTransition(step_connectors["output"], next)
       
   390                 if self.SelectedElement in self.Wires:
       
   391                     self.SelectedElement = wire
       
   392                     self.SelectedElement.SetSelectedSegment(0)
       
   393                 else:
       
   394                     self.SelectedElement.SetSelected(False)
       
   395                     self.SelectedElement = step
       
   396                     self.SelectedElement.SetSelected(True)
       
   397                 self.Parent.RefreshProjectTree()
       
   398                 self.Refresh()
       
   399             dialog.Destroy()
       
   400     
       
   401     def AddStepAction(self):
       
   402         if isinstance(self.SelectedElement, SFC_Step):
       
   403             connectors = self.SelectedElement.GetConnectors()
       
   404             if not connectors["action"]:
       
   405                 dialog = ActionBlockDialog(self.Parent)
       
   406                 dialog.SetQualifierList(self.Controler.GetQualifierTypes())
       
   407                 dialog.SetActionList(self.Controler.GetCurrentElementEditingActions())
       
   408                 dialog.SetVariableList(self.Controler.GetCurrentElementEditingInterfaceVars())
       
   409                 if dialog.ShowModal() == wxID_OK:
       
   410                     actions = dialog.GetValues()
       
   411                     self.SelectedElement.AddAction()
       
   412                     self.RefreshStepModel(self.SelectedElement)
       
   413                     connectors = self.SelectedElement.GetConnectors()
       
   414                     pos = connectors["action"].GetPosition(False)
       
   415                     id = self.GetNewId()
       
   416                     actionblock = SFC_ActionBlock(self, [], id)
       
   417                     actionblock.SetPosition(pos.x + SFC_WIRE_MIN_SIZE, pos.y - SFC_STEP_DEFAULT_SIZE[1] / 2)
       
   418                     actionblock_connector = actionblock.GetConnector()
       
   419                     wire = self.ConnectConnectors(actionblock_connector, connectors["action"])
       
   420                     wire.SetPoints([wxPoint(pos.x + SFC_WIRE_MIN_SIZE, pos.y), wxPoint(pos.x, pos.y)])
       
   421                     actionblock.SetActions(actions)
       
   422                     self.Blocks.append(actionblock)
       
   423                     self.Elements.append(actionblock)
       
   424                     self.Controler.AddCurrentElementEditingActionBlock(id)
       
   425                     self.RefreshActionBlockModel(actionblock)
       
   426                     self.Refresh()
       
   427                 dialog.Destroy()
       
   428     
       
   429     def AddDivergence(self):
       
   430         if self.SelectedElement in self.Wires or isinstance(self.SelectedElement, Graphic_Group) or isinstance(self.SelectedElement, SFC_Step):        
       
   431             dialog = DivergenceCreateDialog(self.Parent)
       
   432             if dialog.ShowModal() == wxID_OK:
       
   433                 value = dialog.GetValues()
       
   434                 if value["type"] == SELECTION_DIVERGENCE:
       
   435                     if self.SelectedElement in self.Wires and isinstance(self.SelectedElement.EndConnected.GetParentBlock(), SFC_Step):
       
   436                         self.SelectedElement.SetSelectedSegment(None)
       
   437                         previous = self.SelectedElement.EndConnected
       
   438                         next = self.SelectedElement.StartConnected
       
   439                         self.SelectedElement.Clean()
       
   440                         self.Wires.remove(self.SelectedElement)
       
   441                         self.Elements.remove(self.SelectedElement)
       
   442                         self.SelectedElement = None
       
   443                     elif isinstance(self.SelectedElement, SFC_Step):
       
   444                         connectors = self.SelectedElement.GetConnectors()
       
   445                         if connectors["output"]:
       
   446                             previous = connectors["output"]
       
   447                             wires = previous.GetWires()
       
   448                             if len(wires) != 1:
       
   449                                 return
       
   450                             wire = wires[0][0]
       
   451                             next = wire.StartConnected
       
   452                             wire.Clean()
       
   453                             self.Wires.remove(wire)
       
   454                             self.Elements.remove(wire)
       
   455                         else:
       
   456                             self.SelectedElement.AddOutput()
       
   457                             connectors = self.SelectedElement.GetConnectors()
       
   458                             self.RefreshStepModel(self.SelectedElement)
       
   459                             previous = connectors["output"]
       
   460                             next = None
       
   461                     else:
       
   462                         return
       
   463                     id = self.GetNewId()
       
   464                     divergence = SFC_Divergence(self, SELECTION_DIVERGENCE, value["number"], id)
       
   465                     pos = previous.GetPosition(False)
       
   466                     previous_block = previous.GetParentBlock()
       
   467                     wire_size = GetWireSize(previous_block)
       
   468                     divergence.SetPosition(pos.x, pos.y + wire_size)
       
   469                     divergence_connectors = divergence.GetConnectors()
       
   470                     wire = self.ConnectConnectors(divergence_connectors["inputs"][0], previous)
       
   471                     previous_block.RefreshOutputPosition()
       
   472                     wire.SetPoints([wxPoint(pos.x, pos.y + wire_size), wxPoint(pos.x, pos.y)])
       
   473                     self.Blocks.append(divergence)
       
   474                     self.Elements.append(divergence)
       
   475                     self.Controler.AddCurrentElementEditingDivergence(id, value["type"])
       
   476                     self.RefreshDivergenceModel(divergence)
       
   477                     for index, connector in enumerate(divergence_connectors["outputs"]):
       
   478                         if next:
       
   479                             wire = self.ConnectConnectors(next, connector)
       
   480                             pos = connector.GetPosition(False)
       
   481                             next_pos = next.GetPosition(False)
       
   482                             next_block = next.GetParentBlock()
       
   483                             divergence.RefreshOutputPosition((0, pos.y + SFC_WIRE_MIN_SIZE - next_pos.y))
       
   484                             divergence.RefreshConnectedPosition(connector)
       
   485                             wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
       
   486                             next_block.RefreshModel()
       
   487                             next = None
       
   488                         else:
       
   489                             transition = self.CreateTransition(connector)
       
   490                             transition_connectors = transition.GetConnectors()
       
   491                             step = self.CreateStep("Step", transition_connectors["output"])
       
   492                 elif value["type"] == SIMULTANEOUS_DIVERGENCE:
       
   493                     if self.SelectedElement in self.Wires and isinstance(self.SelectedElement.EndConnected.GetParentBlock(), SFC_Transition):
       
   494                         self.SelectedElement.SetSelectedSegment(None)
       
   495                         previous = self.SelectedElement.EndConnected
       
   496                         next = self.SelectedElement.StartConnected
       
   497                         self.SelectedElement.Clean()
       
   498                         self.Wires.remove(self.SelectedElement)
       
   499                         self.Elements.remove(self.SelectedElement)
       
   500                         self.SelectedElement = None
       
   501                     elif isinstance(self.SelectedElement, SFC_Step):
       
   502                         connectors = self.SelectedElement.GetConnectors()
       
   503                         if connectors["output"]:
       
   504                             previous = connectors["output"]
       
   505                             wires = previous.GetWires()
       
   506                             if len(wires) != 1:
       
   507                                 return
       
   508                             wire = wires[0][0]
       
   509                             next = wire.StartConnected
       
   510                             wire.Clean()
       
   511                             self.Wires.remove(wire)
       
   512                             self.Elements.remove(wire)
       
   513                         else:
       
   514                             self.SelectedElement.AddOutput()
       
   515                             connectors = self.SelectedElement.GetConnectors()
       
   516                             self.RefreshStepModel(self.SelectedElement)
       
   517                             previous = connectors["output"]
       
   518                             next = None
       
   519                         transition = self.CreateTransition(previous)
       
   520                         transition_connectors = transition.GetConnectors()
       
   521                         previous = transition_connectors["output"]
       
   522                     else:
       
   523                         return
       
   524                     id = self.GetNewId()
       
   525                     divergence = SFC_Divergence(self, SIMULTANEOUS_DIVERGENCE, value["number"], id)
       
   526                     pos = previous.GetPosition(False)
       
   527                     previous_block = previous.GetParentBlock()
       
   528                     wire_size = GetWireSize(previous_block)
       
   529                     divergence.SetPosition(pos.x, pos.y + wire_size)
       
   530                     divergence_connectors = divergence.GetConnectors()
       
   531                     wire = self.ConnectConnectors(divergence_connectors["inputs"][0], previous)
       
   532                     previous_block.RefreshOutputPosition()
       
   533                     wire.SetPoints([wxPoint(pos.x, pos.y + wire_size), wxPoint(pos.x, pos.y)])
       
   534                     self.Blocks.append(divergence)
       
   535                     self.Elements.append(divergence)
       
   536                     self.Controler.AddCurrentElementEditingDivergence(id, value["type"])
       
   537                     self.RefreshDivergenceModel(divergence)
       
   538                     for index, connector in enumerate(divergence_connectors["outputs"]):
       
   539                         if next:
       
   540                             wire = self.ConnectConnectors(next, connector)
       
   541                             pos = connector.GetPosition(False)
       
   542                             next_pos = next.GetPosition(False)
       
   543                             next_block = next.GetParentBlock()
       
   544                             divergence.RefreshOutputPosition((0, pos.y + SFC_WIRE_MIN_SIZE - next_pos.y))
       
   545                             divergence.RefreshConnectedPosition(connector)
       
   546                             wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
       
   547                             next_block.RefreshModel()
       
   548                             next = None
       
   549                         else:
       
   550                             step = self.CreateStep("Step", connector)
       
   551                 elif isinstance(self.SelectedElement, Graphic_Group) and len(self.SelectedElement.GetElements()) > 1:
       
   552                     next = None
       
   553                     for element in self.SelectedElement.GetElements():
       
   554                         connectors = element.GetConnectors()
       
   555                         if not isinstance(element, SFC_Step) or connectors["output"] and next:
       
   556                             return
       
   557                         elif connectors["output"] and not next:
       
   558                             wires = connectors["output"].GetWires()
       
   559                             if len(wires) != 1:
       
   560                                 return
       
   561                             if value["type"] == SELECTION_CONVERGENCE:
       
   562                                 transition = wires[0][0].StartConnected.GetParentBlock()
       
   563                                 transition_connectors = transition.GetConnectors()
       
   564                                 wires = transition_connectors["output"].GetWires()
       
   565                                 if len(wires) != 1:
       
   566                                     return
       
   567                             wire = wires[0][0]
       
   568                             next = wire.StartConnected
       
   569                             wire.Clean()
       
   570                             self.Wires.remove(wire)
       
   571                             self.Elements.remove(wire)
       
   572                     inputs = []
       
   573                     for input in self.SelectedElement.GetElements():
       
   574                         input_connectors = input.GetConnectors()
       
   575                         if not input_connectors["output"]:
       
   576                             input.AddOutput()
       
   577                             input.RefreshModel()
       
   578                             input_connectors = input.GetConnectors()
       
   579                             if value["type"] == SELECTION_CONVERGENCE:
       
   580                                 transition = self.CreateTransition(input_connectors["output"])
       
   581                                 transition_connectors = transition.GetConnectors()
       
   582                                 inputs.append(transition_connectors["output"])
       
   583                             else:
       
   584                                 inputs.append(input_connectors["output"])
       
   585                         elif value["type"] == SELECTION_CONVERGENCE:
       
   586                             wires = input_connectors["output"].GetWires()
       
   587                             transition = wires[0][0].StartConnected.GetParentBlock()
       
   588                             transition_connectors = transition.GetConnectors()
       
   589                             inputs.append(transition_connectors["output"])
       
   590                         else:
       
   591                             inputs.append(input_connectors["output"])
       
   592                     id = self.GetNewId()
       
   593                     divergence = SFC_Divergence(self, value["type"], len(inputs), id)
       
   594                     pos = inputs[0].GetPosition(False)
       
   595                     divergence.SetPosition(pos.x, pos.y + SFC_WIRE_MIN_SIZE)
       
   596                     divergence_connectors = divergence.GetConnectors()
       
   597                     for i, input in enumerate(inputs):
       
   598                         pos = input.GetPosition(False)
       
   599                         wire = self.ConnectConnectors(divergence_connectors["inputs"][i], input)
       
   600                         wire_size = GetWireSize(input)
       
   601                         wire.SetPoints([wxPoint(pos.x, pos.y + wire_size), wxPoint(pos.x, pos.y)])
       
   602                         input_block = input.GetParentBlock()
       
   603                         input_block.RefreshOutputPosition()
       
   604                     divergence.RefreshPosition()
       
   605                     pos = divergence_connectors["outputs"][0].GetRelPosition()
       
   606                     divergence.MoveConnector(divergence_connectors["outputs"][0], - pos.x)
       
   607                     self.Blocks.append(divergence)
       
   608                     self.Elements.append(divergence)
       
   609                     self.Controler.AddCurrentElementEditingDivergence(id, value["type"])
       
   610                     self.RefreshDivergenceModel(divergence)
       
   611                     if next:
       
   612                         wire = self.ConnectConnectors(next, divergence_connectors["outputs"][0])
       
   613                         pos = divergence_connectors["outputs"][0].GetPosition(False)
       
   614                         next_pos = next.GetPosition(False)
       
   615                         next_block = next.GetParentBlock()
       
   616                         divergence.RefreshOutputPosition((0, pos.y + SFC_WIRE_MIN_SIZE - next_pos.y))
       
   617                         divergence.RefreshConnectedPosition(divergence_connectors["outputs"][0])
       
   618                         wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
       
   619                         next_block.RefreshModel()
       
   620                     else:
       
   621                         if value["type"] == SELECTION_CONVERGENCE:
       
   622                             previous = divergence_connectors["outputs"][0]
       
   623                         else:
       
   624                             transition = self.CreateTransition(divergence_connectors["outputs"][0])
       
   625                             transition_connectors = transition.GetConnectors()
       
   626                             previous = transition_connectors["output"]
       
   627                         self.CreateStep("Step", previous)
       
   628                 self.Refresh()
       
   629             dialog.Destroy()
       
   630     
       
   631     def AddDivergenceBranch(self, divergence):
       
   632         if isinstance(divergence, SFC_Divergence):
       
   633             type = divergence.GetType()
       
   634             if type in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
       
   635                 divergence.AddBranch()
       
   636                 divergence_connectors = divergence.GetConnectors()
       
   637                 if type == SELECTION_DIVERGENCE:
       
   638                     transition = self.CreateTransition(divergence_connectors["outputs"][-1])
       
   639                     transition_connectors = transition.GetConnectors()
       
   640                     previous = transition_connectors["output"]
       
   641                 else:
       
   642                     previous = divergence_connectors["outputs"][-1]
       
   643                 step = self.CreateStep("Step", previous)
       
   644                 self.Refresh()
       
   645     
       
   646     def AddJump(self):
       
   647         if isinstance(self.SelectedElement, SFC_Step) and not self.SelectedElement.Output:
       
   648             choices = []
       
   649             for block in self.Blocks:
       
   650                 if isinstance(block, SFC_Step):
       
   651                     choices.append(block.GetName())
       
   652             dialog = wxSingleChoiceDialog(self.Parent, "Add a new jump", "Please choose a target", choices, wxOK|wxCANCEL)
       
   653             if dialog.ShowModal() == wxID_OK:
       
   654                 value = dialog.GetStringSelection()
       
   655                 self.SelectedElement.AddOutput()
       
   656                 self.RefreshStepModel(self.SelectedElement)
       
   657                 step_connectors = self.SelectedElement.GetConnectors()
       
   658                 transition = self.CreateTransition(step_connectors["output"])
       
   659                 transition_connectors = transition.GetConnectors()
       
   660                 id = self.GetNewId()
       
   661                 jump = SFC_Jump(self, value, id)
       
   662                 pos = transition_connectors["output"].GetPosition(False)
       
   663                 jump.SetPosition(pos.x, pos.y + SFC_WIRE_MIN_SIZE)
       
   664                 self.Blocks.append(jump)
       
   665                 self.Elements.append(jump)
       
   666                 self.Controler.AddCurrentElementEditingJump(id)
       
   667                 jump_connector = jump.GetConnector()
       
   668                 wire = self.ConnectConnectors(jump_connector, transition_connectors["output"])
       
   669                 transition.RefreshOutputPosition()
       
   670                 wire.SetPoints([wxPoint(pos.x, pos.y + SFC_WIRE_MIN_SIZE), wxPoint(pos.x, pos.y)])
       
   671                 self.RefreshJumpModel(jump)
       
   672                 self.Refresh()
       
   673             dialog.Destroy()
       
   674     
       
   675     def AddComment(self, bbox):
       
   676         dialog = wxTextEntryDialog(self.Parent, "Add a new comment", "Please enter comment text", "", wxOK|wxCANCEL|wxTE_MULTILINE)
       
   677         if dialog.ShowModal() == wxID_OK:
       
   678             value = dialog.GetValue()
       
   679             id = self.GetNewId()
       
   680             comment = Comment(self, value, id)
       
   681             comment.SetPosition(bbox.x, bbox.y)
       
   682             min_width, min_height = comment.GetMinSize()
       
   683             comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height))
       
   684             self.Elements.append(comment)
       
   685             self.Controler.AddCurrentElementEditingComment(id)
       
   686             self.RefreshCommentModel(comment)
       
   687             self.Refresh()
       
   688         dialog.Destroy()
       
   689 
       
   690     def EditStepContent(self, step):
       
   691         dialog = wxTextEntryDialog(self.Parent, "Edit step name", "Please enter step name", step.GetName(), wxOK|wxCANCEL)
       
   692         if dialog.ShowModal() == wxID_OK:
       
   693             value = dialog.GetValue()
       
   694             step.SetName(value)
       
   695             min_size = step.GetMinSize()
       
   696             size = step.GetSize()
       
   697             step.UpdateSize(max(min_size[0], size[0]), max(min_size[1], size[1]))
       
   698             step.RefreshModel()
       
   699             self.Refresh()
       
   700         dialog.Destroy()
       
   701 
       
   702     def EditTransitionContent(self, transition):
       
   703         dialog = TransitionContentDialog(self.Parent)
       
   704         dialog.SetTransitions(self.Controler.GetCurrentElementEditingTransitions())
       
   705         dialog.SetValues({"type":transition.GetType(),"value":transition.GetCondition()})
       
   706         if dialog.ShowModal() == wxID_OK:
       
   707             values = dialog.GetValues()
       
   708             transition.SetType(values["type"])
       
   709             transition.SetCondition(values["value"])
       
   710             transition.RefreshModel()
       
   711             self.Refresh()
       
   712         dialog.Destroy()
       
   713 
       
   714     def EditJumpContent(self, jump):
       
   715         choices = []
       
   716         for block in self.Blocks:
       
   717             if isinstance(block, SFC_Step):
       
   718                 choices.append(block.GetName())
       
   719         dialog = wxSingleChoiceDialog(self.Parent, "Edit jump target", "Please choose a target", choices, wxOK|wxCANCEL)
       
   720         dialog.SetSelection(choices.index(jump.GetTarget()))
       
   721         if dialog.ShowModal() == wxID_OK:
       
   722             value = dialog.GetStringSelection()
       
   723             jump.SetTarget(value)
       
   724             jump.RefreshModel()
       
   725             self.Refresh()
       
   726         dialog.Destroy()
       
   727 
       
   728     def EditActionBlockContent(self, actionblock):
       
   729         dialog = ActionBlockDialog(self.Parent)
       
   730         dialog.SetQualifierList(self.Controler.GetQualifierTypes())
       
   731         dialog.SetActionList(self.Controler.GetCurrentElementEditingActions())
       
   732         dialog.SetVariableList(self.Controler.GetCurrentElementEditingInterfaceVars())
       
   733         dialog.SetValues(actionblock.GetActions())
       
   734         if dialog.ShowModal() == wxID_OK:
       
   735             actions = dialog.GetValues()
       
   736             actionblock.SetActions(actions)
       
   737             actionblock.RefreshModel()
       
   738             self.Refresh()
       
   739         dialog.Destroy()
       
   740         
       
   741 
       
   742 #-------------------------------------------------------------------------------
       
   743 #                          Delete element functions
       
   744 #-------------------------------------------------------------------------------
       
   745 
       
   746     def DeleteStep(self, step):
       
   747         step_connectors = step.GetConnectors()
       
   748         if not step.GetInitial() or not step_connectors["output"]:
       
   749             previous = step.GetPreviousConnector()
       
   750             if previous:
       
   751                 previous_block = previous.GetParentBlock()
       
   752             else:
       
   753                 previous_block = None
       
   754             next = step.GetNextConnector()
       
   755             if next:
       
   756                 next_block = next.GetParentBlock()
       
   757             else:
       
   758                 next_block = None
       
   759             if isinstance(next_block, SFC_Transition):
       
   760                 self.RemoveTransition(next_block)
       
   761                 next = step.GetNextConnector()
       
   762                 if next:
       
   763                     next_block = next.GetParentBlock()
       
   764                 else:
       
   765                     next_block = None
       
   766             elif isinstance(previous_block, SFC_Transition):
       
   767                 self.RemoveTransition(previous_block)
       
   768                 previous = step.GetPreviousConnector()
       
   769                 if previous:
       
   770                     previous_block = previous.GetParentBlock()
       
   771                 else:
       
   772                     previous_block = None
       
   773             wire = self.RemoveStep(step)
       
   774             self.SelectedElement = None
       
   775             if next_block:
       
   776                 if isinstance(next_block, SFC_Divergence) and next_block.GetType() == SIMULTANEOUS_CONVERGENCE and isinstance(previous_block, SFC_Divergence) and previous_block.GetType() == SIMULTANEOUS_DIVERGENCE:
       
   777                     wire.Clean()
       
   778                     self.Wires.remove(wire)
       
   779                     self.Elements.remove(wire)
       
   780                     next_block.RemoveBranch(next)
       
   781                     if next_block.GetBranchNumber() < 2:
       
   782                         self.DeleteDivergence(next_block)
       
   783                     else:
       
   784                         next_block.RefreshModel()
       
   785                     previous_block.RemoveBranch(previous)
       
   786                     if previous_block.GetBranchNumber() < 2:
       
   787                         self.DeleteDivergence(previous_block)
       
   788                     else:
       
   789                         previous_block.RefreshModel()
       
   790                 else:
       
   791                     pos = previous.GetPosition(False)
       
   792                     next_pos = next.GetPosition(False)
       
   793                     wire_size = GetWireSize(previous_block)
       
   794                     previous_block.RefreshOutputPosition((0, pos.y + wire_size - next_pos.y))
       
   795                     wire.SetPoints([wxPoint(pos.x, pos.y + wire_size), wxPoint(pos.x, pos.y)])
       
   796                     if isinstance(next_block, SFC_Divergence):
       
   797                         next_block.RefreshPosition()
       
   798                     next_block.RefreshModel()
       
   799             else:
       
   800                 if isinstance(previous_block, SFC_Step):
       
   801                     previous_block.RemoveOutput()
       
   802                     self.RefreshStepModel(previous_block)
       
   803                 elif isinstance(previous_block, SFC_Divergence):
       
   804                     if previous_block.GetType() in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
       
   805                         self.DeleteDivergence(previous_block)
       
   806                     else:
       
   807                         previous_block.RemoveBranch(previous)
       
   808                         if previous_block.GetBranchNumber() < 2:
       
   809                             self.DeleteDivergence(previous_block)
       
   810                         else:
       
   811                             self.RefreshDivergenceModel(previous_block)
       
   812         
       
   813     def DeleteTransition(self, transition):
       
   814         previous = transition.GetPreviousConnector()
       
   815         previous_block = previous.GetParentBlock()
       
   816         next = transition.GetNextConnector()
       
   817         next_block = next.GetParentBlock()
       
   818         if isinstance(previous_block, SFC_Divergence) and previous_block.GetType() == SELECTION_DIVERGENCE and isinstance(next_block, SFC_Divergence) and next_block.GetType() == SELECTION_CONVERGENCE:
       
   819             wires = previous.GetWires()
       
   820             if len(wires) != 1:
       
   821                 return
       
   822             wire = wires[0][0]
       
   823             wire.Clean()
       
   824             self.Wires.remove(wire)
       
   825             self.Elements.remove(wire)
       
   826             wires = next.GetWires()
       
   827             if len(wires) != 1:
       
   828                 return
       
   829             wire = wires[0][0]
       
   830             wire.Clean()
       
   831             self.Wires.remove(wire)
       
   832             self.Elements.remove(wire)
       
   833             transition.Clean()
       
   834             self.Blocks.remove(transition)
       
   835             self.Elements.remove(transition)
       
   836             self.Controler.RemoveCurrentElementEditingInstance(transition.GetId())
       
   837             previous_block.RemoveBranch(previous)
       
   838             if previous_block.GetBranchNumber() < 2:
       
   839                 self.DeleteDivergence(previous_block)
       
   840             else:
       
   841                 self.RefreshDivergenceModel(previous_block)
       
   842             next_block.RemoveBranch(next)
       
   843             if next_block.GetBranchNumber() < 2:
       
   844                 self.DeleteDivergence(next_block)
       
   845             else:
       
   846                 self.RefreshDivergenceModel(next_block)
       
   847         self.Parent.RefreshProjectTree()
       
   848 
       
   849     def DeleteDivergence(self, divergence):
       
   850         connectors = divergence.GetConnectors()
       
   851         type = divergence.GetType()
       
   852         if type in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
       
   853             wires = connectors["outputs"][0].GetWires()
       
   854             if len(wires) > 1:
       
   855                 return
       
   856             elif len(wires) == 1:
       
   857                 next = wires[0][0].StartConnected
       
   858                 next_block = next.GetParentBlock()
       
   859                 wire = wires[0][0]
       
   860                 wire.Clean()
       
   861                 self.Wires.remove(wire)
       
   862                 self.Elements.remove(wire)
       
   863             else:
       
   864                 next = None
       
   865                 next_block = None
       
   866             for index, connector in enumerate(connectors["inputs"]):
       
   867                 if next and index == 0:
       
   868                     wires = connector.GetWires()
       
   869                     wire = wires[0][0]
       
   870                     previous = wires[0][0].EndConnected
       
   871                     wire.Clean()
       
   872                     self.Wires.remove(wire)
       
   873                     self.Elements.remove(wire)
       
   874                 else:
       
   875                     if type == SELECTION_CONVERGENCE:
       
   876                         wires = connector.GetWires()
       
   877                         previous_block = wires[0][0].EndConnected.GetParentBlock()
       
   878                         self.RemoveTransition(previous_block)
       
   879                     wires = connector.GetWires()
       
   880                     wire = wires[0][0]
       
   881                     previous_connector = wire.EndConnected
       
   882                     previous_block = previous_connector.GetParentBlock()
       
   883                     wire.Clean()
       
   884                     self.Wires.remove(wire)
       
   885                     self.Elements.remove(wire)
       
   886                     if isinstance(previous_block, SFC_Step):
       
   887                         previous_block.RemoveOutput()
       
   888                         self.RefreshStepModel(previous_block)
       
   889                     elif isinstance(previous_block, SFC_Divergence):
       
   890                         if previous_block.GetType() in [SELECTION_DIVERGENCE, SIMULTANEOUS_DIVERGENCE]:
       
   891                             previous_block.RemoveBranch(previous_connector)
       
   892                             if previous_block.GetBranchNumber() < 2:
       
   893                                 self.DeleteDivergence(previous_block)
       
   894                             else:
       
   895                                 self.RefreshDivergenceModel(previous_block)
       
   896                         else:
       
   897                             self.DeleteDivergence(previous_block)
       
   898             divergence.Clean()
       
   899             self.Blocks.remove(divergence)
       
   900             self.Elements.remove(divergence)
       
   901             self.Controler.RemoveCurrentElementEditingInstance(divergence.GetId())
       
   902             if next:
       
   903                 wire = self.ConnectConnectors(next, previous)
       
   904                 previous_block = previous.GetParentBlock()
       
   905                 pos = previous.GetPosition(False)
       
   906                 next_pos = next.GetPosition(False)
       
   907                 wire_size = GetWireSize(previous_block)
       
   908                 previous_block.RefreshOutputPosition((0, previous_pos.y + wire_size - next_pos.y))
       
   909                 wire.SetPoints([wxPoint(previous_pos.x, previous_pos.y + wire_size), 
       
   910                     wxPoint(previous_pos.x, previous_pos.y)])
       
   911                 if isinstance(next_block, SFC_Divergence):
       
   912                     next_block.RefreshPosition()
       
   913                 next_block.RefreshModel()
       
   914         elif divergence.GetBranchNumber() == 1:
       
   915             wires = connectors["inputs"][0].GetWires()
       
   916             if len(wires) != 1:
       
   917                 return
       
   918             wire = wires[0][0]
       
   919             previous = wire.EndConnected
       
   920             previous_block = previous.GetParentBlock()
       
   921             wire.Clean()
       
   922             self.Wires.remove(wire)
       
   923             self.Elements.remove(wire)
       
   924             wires = connectors["outputs"][0].GetWires()
       
   925             if len(wires) != 1:
       
   926                 return
       
   927             wire = wires[0][0]
       
   928             next = wire.StartConnected
       
   929             next_block = next.GetParentBlock()
       
   930             wire.Clean()
       
   931             self.Wires.remove(wire)
       
   932             self.Elements.remove(wire)
       
   933             divergence.Clean()
       
   934             self.Blocks.remove(divergence)
       
   935             self.Elements.remove(divergence)
       
   936             self.Controler.RemoveCurrentElementEditingInstance(divergence.GetId())
       
   937             wire = self.ConnectConnectors(next, previous)
       
   938             previous_pos = previous.GetPosition(False)
       
   939             next_pos = next.GetPosition(False)
       
   940             wire_size = GetWireSize(previous_block)
       
   941             previous_block.RefreshOutputPosition((previous_pos.x - next_pos.x, previous_pos.y + wire_size - next_pos.y))
       
   942             wire.SetPoints([wxPoint(previous_pos.x, previous_pos.y + wire_size), 
       
   943                 wxPoint(previous_pos.x, previous_pos.y)])
       
   944             if isinstance(next_block, SFC_Divergence):
       
   945                 next_block.RefreshPosition()
       
   946             next_block.RefreshModel()
       
   947         self.Parent.RefreshProjectTree()
       
   948 
       
   949     def DeleteJump(self, jump):
       
   950         previous = jump.GetPreviousConnector()
       
   951         previous_block = previous.GetParentBlock()
       
   952         if isinstance(previous_block, SFC_Transition):
       
   953             self.RemoveTransition(previous_block)
       
   954             previous = jump.GetPreviousConnector()
       
   955             if previous:
       
   956                 previous_block = previous.GetParentBlock()
       
   957             else:
       
   958                 previous_block = None
       
   959         wires = previous.GetWires()
       
   960         if len(wires) != 1:
       
   961             return
       
   962         wire = wires[0][0]
       
   963         wire.Clean()
       
   964         self.Wires.remove(wire)
       
   965         self.Elements.remove(wire)
       
   966         jump.Clean()
       
   967         self.Blocks.remove(jump)
       
   968         self.Elements.remove(jump)
       
   969         self.Controler.RemoveCurrentElementEditingInstance(jump.GetId())
       
   970         if isinstance(previous_block, SFC_Step):
       
   971             previous_block.RemoveOutput()
       
   972             self.RefreshStepModel(previous_block)
       
   973         elif isinstance(previous_block, SFC_Divergence):
       
   974             if previous_block.GetType() in [SELECTION_CONVERGENCE, SIMULTANEOUS_CONVERGENCE]:
       
   975                 self.DeleteDivergence(previous_block)
       
   976             else:
       
   977                 previous_block.RemoveBranch(previous)
       
   978                 if previous_block.GetBranchNumber() < 2:
       
   979                     self.DeleteDivergence(previous_block)
       
   980                 else:
       
   981                     previous_block.RefreshModel()
       
   982         self.Parent.RefreshProjectTree()
       
   983 
       
   984     def DeleteActionBlock(self, actionblock):
       
   985         connector = actionblock.GetConnector()
       
   986         wires = connector.GetWires()
       
   987         if len(wires) != 1:
       
   988             return
       
   989         wire = wires[0][0]
       
   990         step = wire.EndConnected.GetParentBlock()
       
   991         wire.Clean()
       
   992         self.Wires.remove(wire)
       
   993         self.Elements.remove(wire)
       
   994         actionblock.Clean()
       
   995         self.Blocks.remove(actionblock)
       
   996         self.Elements.remove(actionblock)
       
   997         self.Controler.RemoveCurrentElementEditingInstance(actionblock.GetId())
       
   998         step.RemoveAction()
       
   999         self.RefreshStepModel(step)
       
  1000         step.RefreshOutputPosition()
       
  1001         step.RefreshOutputModel(True)
       
  1002         self.Parent.RefreshProjectTree()
       
  1003 
       
  1004     def DeleteComment(self, comment):
       
  1005         self.Elements.remove(self.SelectedElement)
       
  1006         self.Controler.RemoveCurrentElementEditingInstance(comment.GetId())
       
  1007         
       
  1008     def DeleteWire(self, wire):
       
  1009         pass
       
  1010 
       
  1011 
       
  1012 #-------------------------------------------------------------------------------
       
  1013 #                          Edit Transition Content Dialog
       
  1014 #-------------------------------------------------------------------------------
       
  1015 
       
  1016 [wxID_TRANSITIONCONTENTDIALOG, wxID_TRANSITIONCONTENTDIALOGMAINPANEL, 
       
  1017  wxID_TRANSITIONCONTENTDIALOGREFERENCE, wxID_TRANSITIONCONTENTDIALOGINLINE, 
       
  1018  wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, 
       
  1019 ] = [wx.NewId() for _init_ctrls in range(6)]
       
  1020 
       
  1021 class TransitionContentDialog(wx.Dialog):
       
  1022     def _init_coll_flexGridSizer1_Items(self, parent):
       
  1023         # generated method, don't edit
       
  1024 
       
  1025         parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
       
  1026 
       
  1027     def _init_sizers(self):
       
  1028         # generated method, don't edit
       
  1029         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
       
  1030 
       
  1031         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
       
  1032 
       
  1033         self.SetSizer(self.flexGridSizer1)
       
  1034 
       
  1035     def _init_ctrls(self, prnt):
       
  1036         # generated method, don't edit
       
  1037         wx.Dialog.__init__(self, id=wxID_TRANSITIONCONTENTDIALOG,
       
  1038               name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223),
       
  1039               size=wx.Size(300, 200), style=wx.DEFAULT_DIALOG_STYLE,
       
  1040               title='Edit transition')
       
  1041         self.SetClientSize(wx.Size(300, 200))
       
  1042 
       
  1043         self.MainPanel = wx.Panel(id=wxID_TRANSITIONCONTENTDIALOGMAINPANEL,
       
  1044               name='MainPanel', parent=self, pos=wx.Point(0, 0),
       
  1045               size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL)
       
  1046         self.MainPanel.SetAutoLayout(True)
       
  1047 
       
  1048         self.radioButton1 = wx.RadioButton(id=wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1,
       
  1049               label='Reference', name='radioButton1', parent=self.MainPanel,
       
  1050               pos=wx.Point(24, 24), size=wx.Size(114, 24), style=0)
       
  1051         EVT_RADIOBUTTON(self, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, self.OnTypeChanged)
       
  1052         self.radioButton1.SetValue(True)
       
  1053 
       
  1054         self.Reference = wx.Choice(id=wxID_TRANSITIONCONTENTDIALOGREFERENCE,
       
  1055               name='Reference', parent=self.MainPanel, pos=wx.Point(48, 48), 
       
  1056               size=wx.Size(200, 24), style=0)
       
  1057 
       
  1058         self.radioButton2 = wx.RadioButton(id=wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2,
       
  1059               label='Inline', name='radioButton2', parent=self.MainPanel,
       
  1060               pos=wx.Point(24, 72), size=wx.Size(114, 24), style=0)
       
  1061         EVT_RADIOBUTTON(self, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, self.OnTypeChanged)
       
  1062         self.radioButton2.SetValue(False)
       
  1063 
       
  1064         self.Inline = wx.TextCtrl(id=wxID_TRANSITIONCONTENTDIALOGINLINE,
       
  1065               name='Inline', parent=self.MainPanel, pos=wx.Point(48, 96),
       
  1066               size=wx.Size(200, 24), style=0)
       
  1067 
       
  1068         self._init_sizers()
       
  1069 
       
  1070     def __init__(self, parent):
       
  1071         self._init_ctrls(parent)
       
  1072         self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
       
  1073         self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
       
  1074         
       
  1075         EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK)
       
  1076     
       
  1077     def OnOK(self, event):
       
  1078         error = []
       
  1079         if self.radioButton1.GetValue() and self.Reference.GetStringSelection() == "":
       
  1080             error.append("Reference")
       
  1081         if self.radioButton2.GetValue() and self.Inline.GetValue() == "":
       
  1082             error.append("Inline")
       
  1083         if len(error) > 0:
       
  1084             text = ""
       
  1085             for i, item in enumerate(error):
       
  1086                 if i == 0:
       
  1087                     text += item
       
  1088                 elif i == len(error) - 1:
       
  1089                     text += " and %s"%item
       
  1090                 else:
       
  1091                     text += ", %s"%item 
       
  1092             message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR)
       
  1093             message.ShowModal()
       
  1094             message.Destroy()
       
  1095         else:
       
  1096             self.EndModal(wxID_OK)
       
  1097 
       
  1098     def OnTypeChanged(self, event):
       
  1099         if self.radioButton1.GetValue():
       
  1100             self.Reference.Enable(True)
       
  1101             self.Inline.Enable(False)
       
  1102         else:
       
  1103             self.Reference.Enable(False)
       
  1104             self.Inline.Enable(True)
       
  1105         event.Skip()
       
  1106 
       
  1107     def SetTransitions(self, transitions):
       
  1108         for transition in transitions:
       
  1109             self.Reference.Append(transition)
       
  1110 
       
  1111     def SetValues(self, values):
       
  1112         if values["type"] == "reference":
       
  1113             self.radioButton1.SetValue(True)
       
  1114             self.radioButton2.SetValue(False)
       
  1115             self.Reference.Enable(True)
       
  1116             self.Inline.Enable(False)
       
  1117             self.Reference.SetStringSelection(values["value"])
       
  1118         elif values["type"] == "inline":
       
  1119             self.radioButton1.SetValue(False)
       
  1120             self.radioButton2.SetValue(True)
       
  1121             self.Reference.Enable(False)
       
  1122             self.Inline.Enable(True)
       
  1123             self.Inline.SetValue(values["value"])
       
  1124                 
       
  1125     def GetValues(self):
       
  1126         values = {}
       
  1127         if self.radioButton1.GetValue():
       
  1128             values["type"] = "reference"
       
  1129             values["value"] = self.Reference.GetStringSelection()
       
  1130         else:
       
  1131             values["type"] = "inline"
       
  1132             values["value"] = self.Inline.GetValue()
       
  1133         return values
       
  1134 
       
  1135 #-------------------------------------------------------------------------------
       
  1136 #                         Create New Divergence Dialog
       
  1137 #-------------------------------------------------------------------------------
       
  1138 
       
  1139 [wxID_DIVERGENCECREATEDIALOG, wxID_DIVERGENCECREATEDIALOGMAINPANEL, 
       
  1140  wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2,
       
  1141  wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, 
       
  1142  wxID_DIVERGENCECREATEDIALOGSEQUENCES, wxID_DIVERGENCECREATEDIALOGPREVIEW, 
       
  1143  wxID_DIVERGENCECREATEDIALOGSTATICTEXT1, wxID_DIVERGENCECREATEDIALOGSTATICTEXT2, 
       
  1144  wxID_DIVERGENCECREATEDIALOGSTATICTEXT3,  
       
  1145 ] = [wx.NewId() for _init_ctrls in range(11)]
       
  1146 
       
  1147 class DivergenceCreateDialog(wx.Dialog):
       
  1148     def _init_coll_flexGridSizer1_Items(self, parent):
       
  1149         # generated method, don't edit
       
  1150 
       
  1151         parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
       
  1152 
       
  1153     def _init_sizers(self):
       
  1154         # generated method, don't edit
       
  1155         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
       
  1156 
       
  1157         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
       
  1158 
       
  1159         self.SetSizer(self.flexGridSizer1)
       
  1160 
       
  1161     def _init_ctrls(self, prnt):
       
  1162         # generated method, don't edit
       
  1163         wx.Dialog.__init__(self, id=wxID_DIVERGENCECREATEDIALOG,
       
  1164               name='DivergencePropertiesDialog', parent=prnt, pos=wx.Point(376, 223),
       
  1165               size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE,
       
  1166               title='Create a new divergence or convergence')
       
  1167         self.SetClientSize(wx.Size(500, 260))
       
  1168 
       
  1169         self.MainPanel = wx.Panel(id=wxID_DIVERGENCECREATEDIALOGMAINPANEL,
       
  1170               name='MainPanel', parent=self, pos=wx.Point(0, 0),
       
  1171               size=wx.Size(600, 220), style=wx.TAB_TRAVERSAL)
       
  1172         self.MainPanel.SetAutoLayout(True)
       
  1173 
       
  1174         self.staticText1 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT1,
       
  1175               label='Type:', name='staticText1', parent=self.MainPanel,
       
  1176               pos=wx.Point(24, 24), size=wx.Size(200, 17), style=0)
       
  1177 
       
  1178         self.radioButton1 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1,
       
  1179               label='Selection Divergence', name='radioButton1', parent=self.MainPanel,
       
  1180               pos=wx.Point(24, 48), size=wx.Size(200, 24), style=0)
       
  1181         EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, self.OnTypeChanged)
       
  1182         self.radioButton1.SetValue(True)
       
  1183 
       
  1184         self.radioButton2 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2,
       
  1185               label='Selection Convergence', name='radioButton2', parent=self.MainPanel, 
       
  1186               pos=wx.Point(24, 72), size=wx.Size(200, 24), style=0)
       
  1187         EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, self.OnTypeChanged)
       
  1188         self.radioButton2.SetValue(False)
       
  1189 
       
  1190         self.radioButton3 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3,
       
  1191               label='Simultaneous Divergence', name='radioButton3', parent=self.MainPanel,
       
  1192               pos=wx.Point(24, 96), size=wx.Size(200, 24), style=0)
       
  1193         EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, self.OnTypeChanged)
       
  1194         self.radioButton3.SetValue(False)
       
  1195 
       
  1196         self.radioButton4 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4,
       
  1197               label='Simultaneous Convergence', name='radioButton4', parent=self.MainPanel, 
       
  1198               pos=wx.Point(24, 120), size=wx.Size(200, 24), style=0)
       
  1199         EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, self.OnTypeChanged)
       
  1200         self.radioButton4.SetValue(False)
       
  1201 
       
  1202         self.staticText2 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT2,
       
  1203               label='Number of sequences:', name='staticText2', parent=self.MainPanel,
       
  1204               pos=wx.Point(24, 150), size=wx.Size(200, 17), style=0)
       
  1205 
       
  1206         self.Sequences = wx.SpinCtrl(id=wxID_DIVERGENCECREATEDIALOGSEQUENCES,
       
  1207               name='Sequences', parent=self.MainPanel, pos=wx.Point(24, 174),
       
  1208               size=wx.Size(200, 24), style=0, min=2, max=20)
       
  1209         EVT_SPINCTRL(self, wxID_DIVERGENCECREATEDIALOGSEQUENCES, self.OnSequencesChanged)
       
  1210 
       
  1211         self.staticText3 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT3,
       
  1212               label='Preview:', name='staticText3', parent=self.MainPanel,
       
  1213               pos=wx.Point(250, 24), size=wx.Size(100, 17), style=0)
       
  1214 
       
  1215         self.Preview = wx.Panel(id=wxID_DIVERGENCECREATEDIALOGPREVIEW,
       
  1216               name='Preview', parent=self.MainPanel, pos=wx.Point(250, 48),
       
  1217               size=wx.Size(225, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
       
  1218         self.Preview.SetBackgroundColour(wxColour(255,255,255))
       
  1219 
       
  1220         self._init_sizers()
       
  1221 
       
  1222     def __init__(self, parent):
       
  1223         self._init_ctrls(parent)
       
  1224         self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
       
  1225         self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
       
  1226         
       
  1227         self.Divergence = None
       
  1228         
       
  1229         EVT_PAINT(self, self.OnPaint)
       
  1230 
       
  1231     def GetValues(self):
       
  1232         values = {}
       
  1233         if self.radioButton1.GetValue():
       
  1234             values["type"] = SELECTION_DIVERGENCE
       
  1235         elif self.radioButton2.GetValue():
       
  1236             values["type"] = SELECTION_CONVERGENCE
       
  1237         elif self.radioButton3.GetValue():
       
  1238             values["type"] = SIMULTANEOUS_DIVERGENCE
       
  1239         else:
       
  1240             values["type"] = SIMULTANEOUS_CONVERGENCE
       
  1241         values["number"] = self.Sequences.GetValue()
       
  1242         return values
       
  1243 
       
  1244     def OnTypeChanged(self, event):
       
  1245         self.RefreshPreview()
       
  1246         event.Skip()
       
  1247 
       
  1248     def OnSequencesChanged(self, event):
       
  1249         self.RefreshPreview()
       
  1250         event.Skip()
       
  1251         
       
  1252     def RefreshPreview(self):
       
  1253         dc = wxClientDC(self.Preview)
       
  1254         dc.Clear()
       
  1255         if self.radioButton1.GetValue():
       
  1256             self.Divergence = SFC_Divergence(self.Preview, SELECTION_DIVERGENCE, self.Sequences.GetValue())
       
  1257         elif self.radioButton2.GetValue():
       
  1258             self.Divergence = SFC_Divergence(self.Preview, SELECTION_CONVERGENCE, self.Sequences.GetValue())
       
  1259         elif self.radioButton3.GetValue():
       
  1260             self.Divergence = SFC_Divergence(self.Preview, SIMULTANEOUS_DIVERGENCE, self.Sequences.GetValue())
       
  1261         else:
       
  1262             self.Divergence = SFC_Divergence(self.Preview, SIMULTANEOUS_CONVERGENCE, self.Sequences.GetValue())
       
  1263         width, height = self.Divergence.GetSize()
       
  1264         clientsize = self.Preview.GetClientSize()
       
  1265         x = (clientsize.width - width) / 2
       
  1266         y = (clientsize.height - height) / 2
       
  1267         self.Divergence.SetPosition(x, y)
       
  1268         self.Divergence.Draw(dc)
       
  1269 
       
  1270     def OnPaint(self, event):
       
  1271         self.RefreshPreview()
       
  1272 
       
  1273 
       
  1274 #-------------------------------------------------------------------------------
       
  1275 #                            Action Block Dialog
       
  1276 #-------------------------------------------------------------------------------
       
  1277 
       
  1278 class ActionTable(wxPyGridTableBase):
       
  1279     
       
  1280     """
       
  1281     A custom wxGrid Table using user supplied data
       
  1282     """
       
  1283     def __init__(self, parent, data, colnames):
       
  1284         # The base class must be initialized *first*
       
  1285         wxPyGridTableBase.__init__(self)
       
  1286         self.data = data
       
  1287         self.colnames = colnames
       
  1288         self.Parent = parent
       
  1289         # XXX
       
  1290         # we need to store the row length and collength to
       
  1291         # see if the table has changed size
       
  1292         self._rows = self.GetNumberRows()
       
  1293         self._cols = self.GetNumberCols()
       
  1294     
       
  1295     def GetNumberCols(self):
       
  1296         return len(self.colnames)
       
  1297         
       
  1298     def GetNumberRows(self):
       
  1299         return len(self.data)
       
  1300 
       
  1301     def GetColLabelValue(self, col):
       
  1302         if col < len(self.colnames):
       
  1303             return self.colnames[col]
       
  1304 
       
  1305     def GetRowLabelValues(self, row):
       
  1306         return row
       
  1307 
       
  1308     def GetValue(self, row, col):
       
  1309         if row < self.GetNumberRows():
       
  1310             name = str(self.data[row].get(self.GetColLabelValue(col), ""))
       
  1311             return name
       
  1312     
       
  1313     def GetValueByName(self, row, colname):
       
  1314         return self.data[row].get(colname)
       
  1315 
       
  1316     def SetValue(self, row, col, value):
       
  1317         if col < len(self.colnames):
       
  1318             self.data[row][self.GetColLabelValue(col)] = value
       
  1319         
       
  1320     def ResetView(self, grid):
       
  1321         """
       
  1322         (wxGrid) -> Reset the grid view.   Call this to
       
  1323         update the grid if rows and columns have been added or deleted
       
  1324         """
       
  1325         grid.BeginBatch()
       
  1326         for current, new, delmsg, addmsg in [
       
  1327             (self._rows, self.GetNumberRows(), wxGRIDTABLE_NOTIFY_ROWS_DELETED, wxGRIDTABLE_NOTIFY_ROWS_APPENDED),
       
  1328             (self._cols, self.GetNumberCols(), wxGRIDTABLE_NOTIFY_COLS_DELETED, wxGRIDTABLE_NOTIFY_COLS_APPENDED),
       
  1329         ]:
       
  1330             if new < current:
       
  1331                 msg = wxGridTableMessage(self,delmsg,new,current-new)
       
  1332                 grid.ProcessTableMessage(msg)
       
  1333             elif new > current:
       
  1334                 msg = wxGridTableMessage(self,addmsg,new-current)
       
  1335                 grid.ProcessTableMessage(msg)
       
  1336                 self.UpdateValues(grid)
       
  1337         grid.EndBatch()
       
  1338 
       
  1339         self._rows = self.GetNumberRows()
       
  1340         self._cols = self.GetNumberCols()
       
  1341         # update the column rendering scheme
       
  1342         self._updateColAttrs(grid)
       
  1343 
       
  1344         # update the scrollbars and the displayed part of the grid
       
  1345         grid.AdjustScrollbars()
       
  1346         grid.ForceRefresh()
       
  1347 
       
  1348     def UpdateValues(self, grid):
       
  1349         """Update all displayed values"""
       
  1350         # This sends an event to the grid table to update all of the values
       
  1351         msg = wxGridTableMessage(self, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES)
       
  1352         grid.ProcessTableMessage(msg)
       
  1353 
       
  1354     def _updateColAttrs(self, grid):
       
  1355         """
       
  1356         wxGrid -> update the column attributes to add the
       
  1357         appropriate renderer given the column name.
       
  1358 
       
  1359         Otherwise default to the default renderer.
       
  1360         """
       
  1361         
       
  1362         for col in range(self.GetNumberCols()):
       
  1363             attr = wxGridCellAttr()
       
  1364             attr.SetAlignment(self.Parent.ColAlignements[col], wxALIGN_CENTRE)
       
  1365             grid.SetColAttr(col, attr)
       
  1366             grid.SetColSize(col, self.Parent.ColSizes[col])
       
  1367         
       
  1368         typelist = None
       
  1369         accesslist = None
       
  1370         for row in range(self.GetNumberRows()):
       
  1371             for col in range(self.GetNumberCols()):
       
  1372                 editor = None
       
  1373                 renderer = None
       
  1374                 readonly = False
       
  1375                 colname = self.GetColLabelValue(col)
       
  1376                 if colname == "Qualifier":
       
  1377                     editor = wxGridCellChoiceEditor()
       
  1378                     editor.SetParameters(self.Parent.QualifierList)
       
  1379                 if colname == "Duration":
       
  1380                     editor = wxGridCellTextEditor()
       
  1381                     renderer = wxGridCellStringRenderer()
       
  1382                     if self.Parent.DurationList[self.data[row]["Qualifier"]]:
       
  1383                         readonly = False
       
  1384                     else:
       
  1385                         readonly = True
       
  1386                         self.data[row]["Duration"] = ""
       
  1387                 elif colname == "Type":
       
  1388                     editor = wxGridCellChoiceEditor()
       
  1389                     editor.SetParameters(self.Parent.TypeList)
       
  1390                 elif colname == "Value":
       
  1391                     type = self.data[row]["Type"]
       
  1392                     if type == "Action":
       
  1393                         editor = wxGridCellChoiceEditor()
       
  1394                         editor.SetParameters(self.Parent.ActionList)
       
  1395                     elif type == "Variable":
       
  1396                         editor = wxGridCellChoiceEditor()
       
  1397                         editor.SetParameters(self.Parent.VariableList)
       
  1398                     elif type == "Inline":
       
  1399                         editor = wxGridCellTextEditor()
       
  1400                         renderer = wxGridCellStringRenderer()
       
  1401                 elif colname == "Indicator":
       
  1402                     editor = wxGridCellChoiceEditor()
       
  1403                     editor.SetParameters(self.Parent.VariableList)
       
  1404                     
       
  1405                 grid.SetCellEditor(row, col, editor)
       
  1406                 grid.SetCellRenderer(row, col, renderer)
       
  1407                 grid.SetReadOnly(row, col, readonly)
       
  1408                 
       
  1409                 grid.SetCellBackgroundColour(row, col, wxWHITE)
       
  1410     
       
  1411     def SetData(self, data):
       
  1412         self.data = data
       
  1413     
       
  1414     def GetData(self):
       
  1415         return self.data
       
  1416     
       
  1417     def GetCurrentIndex(self):
       
  1418         return self.CurrentIndex
       
  1419     
       
  1420     def SetCurrentIndex(self, index):
       
  1421         self.CurrentIndex = index
       
  1422     
       
  1423     def AppendRow(self, row_content):
       
  1424         self.data.append(row_content)
       
  1425 
       
  1426     def RemoveRow(self, row_index):
       
  1427         self.data.pop(row_index)
       
  1428         
       
  1429     def MoveRow(self, row_index, move, grid):
       
  1430         new_index = max(0, min(row_index + move, len(self.data) - 1))
       
  1431         if new_index != row_index:
       
  1432             self.data.insert(new_index, self.data.pop(row_index))
       
  1433             grid.SetGridCursor(new_index, grid.GetGridCursorCol())
       
  1434 
       
  1435     def Empty(self):
       
  1436         self.data = []
       
  1437         self.editors = []
       
  1438 
       
  1439 [wxID_ACTIONBLOCKDIALOG, wxID_ACTIONBLOCKDIALOGMAINPANEL, 
       
  1440  wxID_ACTIONBLOCKDIALOGVARIABLESGRID, wxID_ACTIONBLOCKDIALOGSTATICTEXT1, 
       
  1441  wxID_ACTIONBLOCKDIALOGADDBUTTON,wxID_ACTIONBLOCKDIALOGDELETEBUTTON, 
       
  1442  wxID_ACTIONBLOCKDIALOGUPBUTTON, wxID_ACTIONBLOCKDIALOGDOWNBUTTON, 
       
  1443 ] = [wx.NewId() for _init_ctrls in range(8)]
       
  1444 
       
  1445 class ActionBlockDialog(wx.Dialog):
       
  1446     def _init_coll_flexGridSizer1_Items(self, parent):
       
  1447         # generated method, don't edit
       
  1448 
       
  1449         parent.AddWindow(self.MainPanel, 0, border=0, flag=0)
       
  1450 
       
  1451     def _init_sizers(self):
       
  1452         # generated method, don't edit
       
  1453         self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
       
  1454 
       
  1455         self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
       
  1456 
       
  1457         self.SetSizer(self.flexGridSizer1)
       
  1458 
       
  1459     def _init_ctrls(self, prnt):
       
  1460         # generated method, don't edit
       
  1461         wx.Dialog.__init__(self, id=wxID_ACTIONBLOCKDIALOG,
       
  1462               name='ActionBlockDialog', parent=prnt, pos=wx.Point(376, 223),
       
  1463               size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE,
       
  1464               title='Edit action block properties')
       
  1465         self.SetClientSize(wx.Size(500, 300))
       
  1466 
       
  1467         self.MainPanel = wx.Panel(id=wxID_ACTIONBLOCKDIALOGMAINPANEL,
       
  1468               name='MainPanel', parent=self, pos=wx.Point(0, 0),
       
  1469               size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
       
  1470         self.MainPanel.SetAutoLayout(True)
       
  1471 
       
  1472         self.staticText1 = wx.StaticText(id=wxID_ACTIONBLOCKDIALOGSTATICTEXT1,
       
  1473               label='Actions:', name='staticText1', parent=self.MainPanel,
       
  1474               pos=wx.Point(24, 24), size=wx.Size(95, 17), style=0)
       
  1475 
       
  1476         self.ActionsGrid = wx.grid.Grid(id=wxID_ACTIONBLOCKDIALOGVARIABLESGRID,
       
  1477               name='ActionsGrid', parent=self.MainPanel, pos=wx.Point(24, 44), 
       
  1478               size=wx.Size(450, 150), style=wxVSCROLL)
       
  1479         self.ActionsGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
       
  1480               'Sans'))
       
  1481         self.ActionsGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
       
  1482               False, 'Sans'))
       
  1483         self.ActionsGrid.DisableDragGridSize()
       
  1484         self.ActionsGrid.EnableScrolling(False, True)
       
  1485         EVT_GRID_CELL_CHANGE(self.ActionsGrid, self.OnActionsGridCellChange)
       
  1486 
       
  1487         self.AddButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGADDBUTTON, label='Add',
       
  1488               name='AddButton', parent=self.MainPanel, pos=wx.Point(245, 204),
       
  1489               size=wx.Size(72, 32), style=0)
       
  1490         EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGADDBUTTON, self.OnAddButton)
       
  1491 
       
  1492         self.DeleteButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGDELETEBUTTON, label='Delete',
       
  1493               name='DeleteButton', parent=self.MainPanel, pos=wx.Point(325, 204),
       
  1494               size=wx.Size(72, 32), style=0)
       
  1495         EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGDELETEBUTTON, self.OnDeleteButton)
       
  1496 
       
  1497         self.UpButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGUPBUTTON, label='^',
       
  1498               name='UpButton', parent=self.MainPanel, pos=wx.Point(405, 204),
       
  1499               size=wx.Size(32, 32), style=0)
       
  1500         EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGUPBUTTON, self.OnUpButton)
       
  1501 
       
  1502         self.DownButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGDOWNBUTTON, label='v',
       
  1503               name='DownButton', parent=self.MainPanel, pos=wx.Point(445, 204),
       
  1504               size=wx.Size(32, 32), style=0)
       
  1505         EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGDOWNBUTTON, self.OnDownButton)
       
  1506 
       
  1507         self._init_sizers()
       
  1508 
       
  1509     def __init__(self, parent):
       
  1510         self._init_ctrls(parent)
       
  1511         self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL)
       
  1512         self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT)
       
  1513         
       
  1514         self.DefaultValue = {"Qualifier" : "N", "Duration" : "", "Type" : "Action", "Value" : "", "Indicator" : ""}
       
  1515         self.Table = ActionTable(self, [], ["Qualifier","Duration","Type","Value","Indicator"])
       
  1516         self.TypeList = "Action,Variable,Inline"
       
  1517         self.ColSizes = [60, 90, 80, 110, 80]
       
  1518         self.ColAlignements = [wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT]
       
  1519         
       
  1520         self.ActionsGrid.SetTable(self.Table)
       
  1521         self.ActionsGrid.SetRowLabelSize(0)
       
  1522         
       
  1523         self.Table.ResetView(self.ActionsGrid)
       
  1524 
       
  1525     def OnAddButton(self, event):
       
  1526         self.Table.AppendRow(self.DefaultValue.copy())
       
  1527         self.Table.ResetView(self.ActionsGrid)
       
  1528         event.Skip()
       
  1529 
       
  1530     def OnDeleteButton(self, event):
       
  1531         row = self.ActionsGrid.GetGridCursorRow()
       
  1532         self.Table.RemoveRow(row)
       
  1533         self.Table.ResetView(self.ActionsGrid)
       
  1534         event.Skip()
       
  1535 
       
  1536     def OnUpButton(self, event):
       
  1537         row = self.ActionsGrid.GetGridCursorRow()
       
  1538         self.Table.MoveRow(row, -1, self.ActionsGrid)
       
  1539         self.Table.ResetView(self.ActionsGrid)
       
  1540         event.Skip()
       
  1541 
       
  1542     def OnDownButton(self, event):
       
  1543         row = self.ActionsGrid.GetGridCursorRow()
       
  1544         self.Table.MoveRow(row, 1, self.ActionsGrid)
       
  1545         self.Table.ResetView(self.ActionsGrid)
       
  1546         event.Skip()
       
  1547 
       
  1548     def OnActionsGridCellChange(self, event):
       
  1549         self.Table.ResetView(self.ActionsGrid)
       
  1550         event.Skip()
       
  1551 
       
  1552     def SetQualifierList(self, list):
       
  1553         self.QualifierList = ""
       
  1554         sep = ""
       
  1555         for qualifier in list.keys():
       
  1556             self.QualifierList += "%s%s"%(sep, qualifier)
       
  1557             sep = ","
       
  1558         self.DurationList = list
       
  1559 
       
  1560     def SetVariableList(self, list):
       
  1561         self.VariableList = ""
       
  1562         sep = ""
       
  1563         for variable in list:
       
  1564             self.VariableList += "%s%s"%(sep, variable["Name"])
       
  1565             sep = ","
       
  1566 
       
  1567     def SetActionList(self, list):
       
  1568         self.ActionList = ""
       
  1569         sep = ""
       
  1570         for action in list:
       
  1571             self.ActionList += "%s%s"%(sep, action)
       
  1572             sep = ","
       
  1573 
       
  1574     def SetValues(self, actions):
       
  1575         for action in actions:
       
  1576             row = {"Qualifier" : action["qualifier"], "Value" : action["value"],
       
  1577                 "Indicator" : action["indicator"]}
       
  1578             if action["type"] == "reference":
       
  1579                 if action["value"] in self.ActionList:
       
  1580                     row["Type"] = "Action"
       
  1581                 elif action["value"] in self.VariableList:
       
  1582                     row["Type"] = "Variable"
       
  1583                 else:
       
  1584                     row["Type"] = "Inline"
       
  1585             else:
       
  1586                 row["Type"] = "Inline"
       
  1587             if "duration" in action:
       
  1588                 row["Duration"] = action["duration"]
       
  1589             self.Table.AppendRow(row)
       
  1590         self.Table.ResetView(self.ActionsGrid)
       
  1591     
       
  1592     def GetValues(self):
       
  1593         values = []
       
  1594         for data in self.Table.GetData():
       
  1595             action = {"qualifier" : data["Qualifier"], "value" : data["Value"],
       
  1596                 "indicator" : data["Indicator"]}
       
  1597             if data["Type"] in ["Action", "Variable"]:
       
  1598                 action["type"] = "reference"
       
  1599             else:
       
  1600                 action["type"] = "inline"
       
  1601             if data["Duration"] != "":
       
  1602                 action["duration"] = data["Duration"]
       
  1603             values.append(action)
       
  1604         return values