Viewer.py
changeset 0 b622defdfd98
child 2 93bc4c2cf376
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.stc import * 
       
    27 from wxPython.grid import *
       
    28 import wx
       
    29 
       
    30 from plcopen.structures import *
       
    31 from graphics.GraphicCommons import *
       
    32 from graphics.SFC_Objects import *
       
    33 from graphics.FBD_Objects import *
       
    34 from graphics.LD_Objects import *
       
    35 
       
    36 import re
       
    37 
       
    38 #-------------------------------------------------------------------------------
       
    39 #                       Graphic elements Viewer base class
       
    40 #-------------------------------------------------------------------------------
       
    41 
       
    42 # ID Constants for menu items
       
    43 [wxID_FBDVIEWERCONTEXTUALMENUITEMS0, wxID_FBDVIEWERCONTEXTUALMENUITEMS1,
       
    44  wxID_FBDVIEWERCONTEXTUALMENUITEMS2, wxID_FBDVIEWERCONTEXTUALMENUITEMS3,
       
    45  wxID_FBDVIEWERCONTEXTUALMENUITEMS5, wxID_FBDVIEWERCONTEXTUALMENUITEMS6,
       
    46  wxID_FBDVIEWERCONTEXTUALMENUITEMS8, wxID_FBDVIEWERCONTEXTUALMENUITEMS9,
       
    47  wxID_FBDVIEWERCONTEXTUALMENUITEMS11,
       
    48 ] = [wx.NewId() for _init_coll_ContextualMenu_Items in range(9)]
       
    49 
       
    50 
       
    51 """
       
    52 Class that implements a Viewer based on a wxScrolledWindow for drawing and 
       
    53 manipulating graphic elements
       
    54 """
       
    55 
       
    56 class Viewer(wx.ScrolledWindow):
       
    57     
       
    58     # Create Contextual Menu items
       
    59     def _init_coll_ContextualMenu_Items(self, parent):
       
    60         # Create menu items
       
    61         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS0,
       
    62               kind=wx.ITEM_RADIO, text=u'No Modifier')
       
    63         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS1,
       
    64               kind=wx.ITEM_RADIO, text=u'Negated')
       
    65         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS2,
       
    66               kind=wx.ITEM_RADIO, text=u'Rising Edge')
       
    67         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS3,
       
    68               kind=wx.ITEM_RADIO, text=u'Falling Edge')
       
    69         parent.AppendSeparator()
       
    70         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS5,
       
    71               kind=wx.ITEM_NORMAL, text=u'Add Wire Segment')
       
    72         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS6,
       
    73               kind=wx.ITEM_NORMAL, text=u'Delete Wire Segment')
       
    74         parent.AppendSeparator()
       
    75         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS8,
       
    76               kind=wx.ITEM_NORMAL, text=u'Add Divergence Branch')
       
    77         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS9,
       
    78               kind=wx.ITEM_NORMAL, text=u'Delete Divergence Branch')
       
    79         parent.AppendSeparator()
       
    80         parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS11,
       
    81               kind=wx.ITEM_NORMAL, text=u'Delete')
       
    82         # Link menu event to corresponding called functions
       
    83         self.Bind(wx.EVT_MENU, self.OnNoModifierMenu,
       
    84               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS0)
       
    85         self.Bind(wx.EVT_MENU, self.OnNegatedMenu,
       
    86               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS1)
       
    87         self.Bind(wx.EVT_MENU, self.OnRisingEdgeMenu,
       
    88               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS2)
       
    89         self.Bind(wx.EVT_MENU, self.OnFallingEdgeMenu,
       
    90               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS3)
       
    91         self.Bind(wx.EVT_MENU, self.OnAddSegmentMenu,
       
    92               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS5)
       
    93         self.Bind(wx.EVT_MENU, self.OnDeleteSegmentMenu,
       
    94               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS6)
       
    95         self.Bind(wx.EVT_MENU, self.OnAddBranchMenu,
       
    96               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS8)
       
    97         self.Bind(wx.EVT_MENU, self.OnDeleteBranchMenu,
       
    98               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS9)
       
    99         self.Bind(wx.EVT_MENU, self.OnDeleteMenu,
       
   100               id=wxID_FBDVIEWERCONTEXTUALMENUITEMS11)
       
   101     
       
   102     # Create and initialize Contextual Menu
       
   103     def _init_menus(self):
       
   104         self.ContextualMenu = wx.Menu(title='')
       
   105         
       
   106         self._init_coll_ContextualMenu_Items(self.ContextualMenu)
       
   107     
       
   108     # Create a new Viewer
       
   109     def __init__(self, parent, window, controler):
       
   110         wx.ScrolledWindow.__init__(self, parent, style=wx.SUNKEN_BORDER)
       
   111         self._init_menus()
       
   112         # Adding a rubberband to Viewer
       
   113         self.rubberBand = RubberBand(drawingSurface=self)
       
   114         self.SetBackgroundColour(wxColour(255,255,255))
       
   115         self.ResetView()
       
   116         self.Scaling = None
       
   117         #self.Scaling = (8, 8)
       
   118         self.DrawGrid = True
       
   119         self.current_id = 0    
       
   120         
       
   121         # Initialize Viewer mode to Selection mode
       
   122         self.Mode = MODE_SELECTION
       
   123         
       
   124         self.Parent = window
       
   125         self.Controler = controler
       
   126         
       
   127         # Link Viewer event to corresponding methods
       
   128         EVT_PAINT(self, self.OnPaint)
       
   129         EVT_LEFT_DOWN(self, self.OnViewerLeftDown)
       
   130         EVT_LEFT_UP(self, self.OnViewerLeftUp)
       
   131         EVT_LEFT_DCLICK(self, self.OnViewerLeftDClick)
       
   132         EVT_RIGHT_UP(self, self.OnViewerRightUp)
       
   133         EVT_MOTION(self, self.OnViewerMotion)
       
   134         EVT_CHAR(self, self.OnChar)
       
   135     
       
   136     # Returns a new id
       
   137     def GetNewId(self):
       
   138         self.current_id += 1
       
   139         return self.current_id
       
   140     
       
   141     # Destructor
       
   142     def __del__(self):
       
   143         self.ResetView()
       
   144 
       
   145 #-------------------------------------------------------------------------------
       
   146 #                              Reset functions
       
   147 #-------------------------------------------------------------------------------
       
   148 
       
   149     # Resets Viewer lists
       
   150     def ResetView(self):
       
   151         self.Blocks = []
       
   152         self.Wires = []
       
   153         self.Elements = []
       
   154         self.SelectedElement = None
       
   155     
       
   156     # Changes Viewer mode
       
   157     def SetMode(self, mode):
       
   158         self.Mode = mode
       
   159         # Reset selection
       
   160         if self.SelectedElement:
       
   161             self.SelectedElement.SetSelected(False)
       
   162             self.SelectedElement = None
       
   163             self.Refresh()
       
   164 
       
   165 #-------------------------------------------------------------------------------
       
   166 #                          Refresh functions
       
   167 #-------------------------------------------------------------------------------
       
   168 
       
   169     # Refresh Viewer elements
       
   170     def RefreshView(self):
       
   171         self.current_id = 0
       
   172         # Start by reseting Viewer
       
   173         self.ResetView()
       
   174         instance = True
       
   175         # List of ids of already loaded blocks
       
   176         ids = []
       
   177         # Load Blocks until they are all loaded
       
   178         while instance:
       
   179             instance = self.Controler.GetCurrentElementEditingInstanceInfos(exclude=ids)
       
   180             if instance:
       
   181                 self.loadInstance(instance, ids)
       
   182         self.Refresh()
       
   183     
       
   184     # Load instance from given informations
       
   185     def loadInstance(self, instance, ids):
       
   186         ids.append(instance["id"])
       
   187         self.current_id = max(self.current_id, instance["id"]) 
       
   188         if instance["type"] == "input":
       
   189             variable = FBD_Variable(self, INPUT, instance["name"], instance["value_type"], instance["id"])
       
   190             variable.SetPosition(instance["x"], instance["y"])
       
   191             variable.SetSize(instance["width"], instance["height"])
       
   192             self.Blocks.append(variable)
       
   193             self.Elements.append(variable)
       
   194             connectors = variable.GetConnectors()
       
   195             connectors["output"].SetPosition(wxPoint(*instance["connector"]["position"]))
       
   196             if instance["connector"]["negated"]:
       
   197                 connectors["output"].SetNegated(True)
       
   198             if instance["connector"]["edge"]:
       
   199                 connectors["output"].SetEdge(instance["connector"]["edge"])
       
   200         elif instance["type"] == "output":
       
   201             variable = FBD_Variable(self, OUTPUT, instance["name"], instance["value_type"], instance["id"])
       
   202             variable.SetPosition(instance["x"], instance["y"])
       
   203             variable.SetSize(instance["width"], instance["height"])
       
   204             self.Blocks.append(variable)
       
   205             self.Elements.append(variable)
       
   206             connectors = variable.GetConnectors()
       
   207             connectors["input"].SetPosition(wxPoint(*instance["connector"]["position"]))
       
   208             if instance["connector"]["negated"]:
       
   209                 connectors["input"].SetNegated(True)
       
   210             if instance["connector"]["edge"]:
       
   211                 connectors["input"].SetEdge(instance["connector"]["edge"])
       
   212             self.CreateWires(connectors["input"], instance["connector"]["links"], ids)
       
   213         elif instance["type"] == "inout":
       
   214             variable = FBD_Variable(self, INOUT, instance["name"], instance["value_type"], instance["id"])
       
   215             variable.SetPosition(instance["x"], instance["y"])
       
   216             variable.SetSize(instance["width"], instance["height"])
       
   217             self.Blocks.append(variable)
       
   218             self.Elements.append(variable)
       
   219             connectors = variable.GetConnectors()
       
   220             connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"]))
       
   221             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
       
   222             if instance["connectors"]["output"]["negated"]:
       
   223                 connectors["output"].SetNegated(True)
       
   224             if instance["connectors"]["output"]["edge"]:
       
   225                 connectors["output"].SetEdge(instance["connectors"]["output"]["edge"])
       
   226             if instance["connectors"]["input"]["negated"]:
       
   227                 connectors["input"].SetNegated(True)
       
   228             if instance["connectors"]["input"]["edge"]:
       
   229                 connectors["input"].SetEdge(instance["connectors"]["input"]["edge"])
       
   230             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
       
   231         elif instance["type"] == "continuation":
       
   232             connection = FBD_Connector(self, CONTINUATION, instance["name"], instance["id"])
       
   233             connection.SetPosition(instance["x"], instance["y"])
       
   234             connection.SetSize(instance["width"], instance["height"])
       
   235             self.Blocks.append(connection)
       
   236             self.Elements.append(connection)
       
   237             connector = connection.GetConnector()
       
   238             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
       
   239         elif instance["type"] == "connection":
       
   240             connection = FBD_Connection(self, CONNECTOR, instance["name"], instance["id"])
       
   241             connection.SetPosition(instance["x"], instance["y"])
       
   242             connection.SetSize(instance["width"], instance["height"])
       
   243             self.Blocks.append(connection)
       
   244             self.Elements.append(connection)
       
   245             connector = connection.GetConnector()
       
   246             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
       
   247             self.CreateWires(connector, instance["connector"]["links"], ids)
       
   248         elif instance["type"] == "comment":
       
   249             comment = Comment(self, instance["content"], instance["id"])
       
   250             comment.SetPosition(instance["x"], instance["y"])
       
   251             comment.SetSize(instance["width"], instance["height"])
       
   252             self.Elements.append(comment)
       
   253         elif instance["type"] == "leftPowerRail":
       
   254             leftpowerrail = LD_PowerRail(self, LEFTRAIL, instance["id"], [True for i in range(len(instance["connectors"]))])
       
   255             leftpowerrail.SetPosition(instance["x"], instance["y"])
       
   256             self.Blocks.append(leftpowerrail)
       
   257             self.Elements.append(leftpowerrail)
       
   258             connectors = leftpowerrail.GetConnectors()
       
   259             for i, connector in enumerate(instance["connectors"]):
       
   260                 connectors[i].SetPosition(wxPoint(*connector["position"]))
       
   261         elif instance["type"] == "rightPowerRail":
       
   262             rightpowerrail = LD_PowerRail(self, RIGHTRAIL, instance["id"], [True for i in range(len(instance["connectors"]))])
       
   263             rightpowerrail.SetPosition(instance["x"], instance["y"])
       
   264             self.Blocks.append(rightpowerrail)
       
   265             self.Elements.append(rightpowerrail)
       
   266             connectors = rightpowerrail.GetConnectors()
       
   267             for i, connector in enumerate(instance["connectors"]):
       
   268                 connectors[i].SetPosition(wxPoint(*connector["position"]))
       
   269                 self.CreateWires(connectors[i], connector["links"], ids)
       
   270         elif instance["type"] == "contact":
       
   271             if instance["negated"]:
       
   272                 negated = instance["negated"]
       
   273             else:
       
   274                 negated = False
       
   275             if instance["edge"]:
       
   276                 edge = instance["edge"]
       
   277             else:
       
   278                 edge = "none"
       
   279             if negated and edge == "none":
       
   280                 contact_type = CONTACT_REVERSE
       
   281             elif not negated and edge == "rising":
       
   282                 contact_type = CONTACT_RISING
       
   283             elif not negated and edge == "falling":
       
   284                 contact_type = CONTACT_FALLING
       
   285             else:
       
   286                 contact_type = CONTACT_NORMAL
       
   287             contact = LD_Contact(self, contact_type, instance["name"], instance["id"])
       
   288             contact.SetPosition(instance["x"], instance["y"])
       
   289             self.Blocks.append(contact)
       
   290             self.Elements.append(contact)
       
   291             connectors = contact.GetConnectors()
       
   292             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
       
   293             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
       
   294             connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"]))
       
   295         elif instance["type"] == "coil":
       
   296             if instance["negated"]:
       
   297                 negated = instance["negated"]
       
   298             else:
       
   299                 negated = False
       
   300             if instance["storage"]:
       
   301                 storage = instance["storage"]
       
   302             else:
       
   303                 storage = "none"
       
   304             if negated and storage == "none":
       
   305                 coil_type = COIL_REVERSE
       
   306             elif not negated and storage == "set":
       
   307                 coil_type = COIL_SET
       
   308             elif not negated and storage == "reset":
       
   309                 coil_type = COIL_RESET
       
   310             else:
       
   311                 coil_type = COIL_NORMAL
       
   312             coil = LD_Coil(self, coil_type, instance["name"], instance["id"])
       
   313             coil.SetPosition(instance["x"], instance["y"])
       
   314             self.Blocks.append(coil)
       
   315             self.Elements.append(coil)
       
   316             connectors = coil.GetConnectors()
       
   317             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
       
   318             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
       
   319             connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"]))
       
   320         elif instance["type"] == "step":
       
   321             if instance["initial"]:
       
   322                 initial = instance["initial"]
       
   323             else:
       
   324                 initial = False
       
   325             step = SFC_Step(self, instance["name"], initial, instance["id"])
       
   326             step.SetPosition(instance["x"], instance["y"])
       
   327             step.SetSize(instance["width"], instance["height"])
       
   328             self.Blocks.append(step)
       
   329             self.Elements.append(step)
       
   330             if "output" in instance["connectors"]:
       
   331                 step.AddOutput()
       
   332             if "action" in instance["connectors"]:
       
   333                 step.AddAction()
       
   334             connectors = step.GetConnectors()
       
   335             if connectors["input"]:
       
   336                 connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
       
   337                 self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
       
   338             if connectors["output"]:
       
   339                 connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"]))
       
   340             if connectors["action"]:
       
   341                 connectors["action"].SetPosition(wxPoint(*instance["connectors"]["action"]["position"]))
       
   342         elif instance["type"] == "transition":
       
   343             transition = SFC_Transition(self, instance["condition_type"], instance["condition"], instance["id"])
       
   344             transition.SetPosition(instance["x"], instance["y"])
       
   345             self.Blocks.append(transition)
       
   346             self.Elements.append(transition)
       
   347             connectors = transition.GetConnectors()
       
   348             connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"]))
       
   349             self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids)
       
   350             connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"]))
       
   351         elif instance["type"] in ["selectionDivergence", "selectionConvergence", "simultaneousDivergence", "simultaneousConvergence"]:
       
   352             if instance["type"] == "selectionDivergence":
       
   353                 divergence = SFC_Divergence(self, SELECTION_DIVERGENCE, 
       
   354                     len(instance["connectors"]["outputs"]), instance["id"])
       
   355             elif instance["type"] == "selectionConvergence":
       
   356                 divergence = SFC_Divergence(self, SELECTION_CONVERGENCE, 
       
   357                     len(instance["connectors"]["inputs"]), instance["id"])
       
   358             elif instance["type"] == "simultaneousDivergence":
       
   359                 divergence = SFC_Divergence(self, SIMULTANEOUS_DIVERGENCE, 
       
   360                     len(instance["connectors"]["outputs"]), instance["id"])
       
   361             else:
       
   362                 divergence = SFC_Divergence(self, SIMULTANEOUS_CONVERGENCE, 
       
   363                     len(instance["connectors"]["inputs"]), instance["id"])
       
   364             divergence.SetPosition(instance["x"], instance["y"])
       
   365             divergence.SetSize(instance["width"], instance["height"])
       
   366             self.Blocks.append(divergence)
       
   367             self.Elements.append(divergence)
       
   368             connectors = divergence.GetConnectors()
       
   369             for i, input_connector in enumerate(instance["connectors"]["inputs"]):
       
   370                 connector = connectors["inputs"][i]
       
   371                 connector.SetPosition(wxPoint(*input_connector["position"]))
       
   372                 self.CreateWires(connector, input_connector["links"], ids)
       
   373             for i, output_connector in enumerate(instance["connectors"]["outputs"]):
       
   374                 connector = connectors["outputs"][i]
       
   375                 connector.SetPosition(wxPoint(*output_connector["position"]))
       
   376         elif instance["type"] == "jump":
       
   377             jump = SFC_Jump(self, instance["target"], instance["id"])
       
   378             jump.SetPosition(instance["x"], instance["y"])
       
   379             self.Blocks.append(jump)
       
   380             self.Elements.append(jump)
       
   381             connector = jump.GetConnector()
       
   382             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
       
   383             self.CreateWires(connector, instance["connector"]["links"], ids)
       
   384         elif instance["type"] == "actionBlock":
       
   385             actionBlock = SFC_ActionBlock(self, instance["actions"], instance["id"])
       
   386             actionBlock.SetPosition(instance["x"], instance["y"])
       
   387             actionBlock.SetSize(instance["width"], instance["height"])
       
   388             self.Blocks.append(actionBlock)
       
   389             self.Elements.append(actionBlock)
       
   390             connector = actionBlock.GetConnector()
       
   391             connector.SetPosition(wxPoint(*instance["connector"]["position"]))
       
   392             self.CreateWires(connector, instance["connector"]["links"], ids)
       
   393         else:
       
   394             if instance["name"] != None:
       
   395                 block = FBD_Block(self, instance["type"], instance["name"], instance["id"], len(instance["connectors"]["inputs"]))
       
   396             else:
       
   397                 block = FBD_Block(self, instance["type"], "", instance["id"], len(instance["connectors"]["inputs"]))
       
   398             block.SetPosition(instance["x"], instance["y"])
       
   399             block.SetSize(instance["width"], instance["height"])
       
   400             self.Blocks.append(block)
       
   401             self.Elements.append(block)
       
   402             connectors = block.GetConnectors()
       
   403             for i, input_connector in enumerate(instance["connectors"]["inputs"]):
       
   404                 connector = connectors["inputs"][i]
       
   405                 connector.SetPosition(wxPoint(*input_connector["position"]))
       
   406                 if input_connector["negated"]:
       
   407                     connector.SetNegated(True)
       
   408                 if input_connector["edge"]:
       
   409                     connector.SetEdge(input_connector["edge"])
       
   410                 self.CreateWires(connector, input_connector["links"], ids)
       
   411             for i, output_connector in enumerate(instance["connectors"]["outputs"]):
       
   412                 connector = connectors["outputs"][i]
       
   413                 if output_connector["negated"]:
       
   414                     connector.SetNegated(True)
       
   415                 if output_connector["edge"]:
       
   416                     connector.SetEdge(output_connector["edge"])
       
   417                 connector.SetPosition(wxPoint(*output_connector["position"]))
       
   418     
       
   419     def CreateWires(self, start_connector, links, ids):
       
   420         for link in links:
       
   421             refLocalId = link["refLocalId"]
       
   422             if refLocalId != None:
       
   423                 if refLocalId not in ids:
       
   424                     new_instance = self.Controler.GetCurrentElementEditingInstanceInfos(refLocalId)
       
   425                     if new_instance:
       
   426                         self.loadInstance(new_instance, ids)
       
   427                 connected = self.FindElementById(refLocalId)
       
   428                 if connected:
       
   429                     points = link["points"]
       
   430                     end_connector = connected.GetConnector(wxPoint(points[-1][0], points[-1][1]))
       
   431                     if end_connector:
       
   432                         wire = Wire(self)
       
   433                         wire.SetPoints(points)
       
   434                         start_connector.Connect((wire, 0), False)
       
   435                         end_connector.Connect((wire, -1), False)
       
   436                         wire.ConnectStartPoint(None, start_connector)
       
   437                         wire.ConnectEndPoint(None, end_connector)
       
   438                         self.Wires.append(wire)
       
   439                         self.Elements.append(wire)
       
   440 
       
   441 #-------------------------------------------------------------------------------
       
   442 #                          Search Element functions
       
   443 #-------------------------------------------------------------------------------
       
   444 
       
   445     def FindBlock(self, pos):
       
   446         for block in self.Blocks:
       
   447             if block.HitTest(pos) or block.TestHandle(pos) != (0, 0):
       
   448                 return block
       
   449         return None
       
   450     
       
   451     def FindWire(self, pos):
       
   452         for wire in self.Wires:
       
   453             if wire.HitTest(pos) or wire.TestHandle(pos) != (0, 0):
       
   454                 return wire
       
   455         return None
       
   456     
       
   457     def FindElement(self, pos, exclude_group = False):
       
   458         if self.SelectedElement and not (exclude_group and isinstance(self.SelectedElement, Graphic_Group)):
       
   459             if self.SelectedElement.HitTest(pos) or self.SelectedElement.TestHandle(pos) != (0, 0):
       
   460                 return self.SelectedElement
       
   461         for element in self.Elements:
       
   462             if element.HitTest(pos) or element.TestHandle(pos) != (0, 0):
       
   463                 return element
       
   464         return None
       
   465     
       
   466     def FindBlockConnector(self, pos):
       
   467         for block in self.Blocks:
       
   468             result = block.TestConnector(pos)
       
   469             if result:
       
   470                 return result
       
   471         return None
       
   472     
       
   473     def FindElementById(self, id):
       
   474         for element in self.Elements:
       
   475             if element.GetId() == id:
       
   476                 return element
       
   477         return None
       
   478     
       
   479     def SearchElements(self, bbox):
       
   480         elements = []
       
   481         for element in self.Elements:
       
   482             element_bbox = element.GetBoundingBox()
       
   483             if element_bbox.x >= bbox.x and element_bbox.y >= bbox.y and element_bbox.x + element_bbox.width <= bbox.x + bbox.width and element_bbox.y + element_bbox.height <= bbox.y + bbox.height:
       
   484                 elements.append(element)
       
   485         return elements
       
   486 
       
   487 #-------------------------------------------------------------------------------
       
   488 #                           Popup menu functions
       
   489 #-------------------------------------------------------------------------------
       
   490 
       
   491     def PopupBlockMenu(self, connector = None):
       
   492         self.ContextualMenu.FindItemByPosition(0).Enable(connector != None)
       
   493         self.ContextualMenu.FindItemByPosition(1).Enable(connector != None)
       
   494         self.ContextualMenu.FindItemByPosition(2).Enable(connector != None)
       
   495         self.ContextualMenu.FindItemByPosition(3).Enable(connector != None)
       
   496         self.ContextualMenu.FindItemByPosition(5).Enable(False)
       
   497         self.ContextualMenu.FindItemByPosition(6).Enable(False)
       
   498         self.ContextualMenu.FindItemByPosition(8).Enable(False)
       
   499         self.ContextualMenu.FindItemByPosition(9).Enable(False)
       
   500         if connector:
       
   501             if connector.IsNegated():
       
   502                 self.ContextualMenu.FindItemByPosition(1).Check(True)
       
   503             elif connector.GetEdge() == "rising":
       
   504                 self.ContextualMenu.FindItemByPosition(2).Check(True)
       
   505             elif connector.GetEdge() == "falling":
       
   506                 self.ContextualMenu.FindItemByPosition(3).Check(True)
       
   507             else:
       
   508                 self.ContextualMenu.FindItemByPosition(0).Check(True)
       
   509         self.PopupMenu(self.ContextualMenu)
       
   510     
       
   511     def PopupVariableMenu(self, connector = None):
       
   512         self.ContextualMenu.FindItemByPosition(0).Enable(connector != None)
       
   513         self.ContextualMenu.FindItemByPosition(1).Enable(connector != None)
       
   514         self.ContextualMenu.FindItemByPosition(2).Enable(False)
       
   515         self.ContextualMenu.FindItemByPosition(3).Enable(False)
       
   516         self.ContextualMenu.FindItemByPosition(5).Enable(False)
       
   517         self.ContextualMenu.FindItemByPosition(6).Enable(False)
       
   518         self.ContextualMenu.FindItemByPosition(8).Enable(False)
       
   519         self.ContextualMenu.FindItemByPosition(9).Enable(False)
       
   520         if connector:
       
   521             if connector.IsNegated():
       
   522                 self.ContextualMenu.FindItemByPosition(1).Check(True)
       
   523             else:
       
   524                 self.ContextualMenu.FindItemByPosition(0).Check(True)
       
   525         self.PopupMenu(self.ContextualMenu)
       
   526 
       
   527     def PopupWireMenu(self):
       
   528         self.ContextualMenu.FindItemByPosition(0).Enable(False)
       
   529         self.ContextualMenu.FindItemByPosition(1).Enable(False)
       
   530         self.ContextualMenu.FindItemByPosition(2).Enable(False)
       
   531         self.ContextualMenu.FindItemByPosition(3).Enable(False)
       
   532         self.ContextualMenu.FindItemByPosition(5).Enable(True)
       
   533         self.ContextualMenu.FindItemByPosition(6).Enable(True)
       
   534         self.ContextualMenu.FindItemByPosition(8).Enable(False)
       
   535         self.ContextualMenu.FindItemByPosition(9).Enable(False)
       
   536         self.PopupMenu(self.ContextualMenu)
       
   537     
       
   538     def PopupDivergenceMenu(self, connector):
       
   539         self.ContextualMenu.FindItemByPosition(0).Enable(False)
       
   540         self.ContextualMenu.FindItemByPosition(1).Enable(False)
       
   541         self.ContextualMenu.FindItemByPosition(2).Enable(False)
       
   542         self.ContextualMenu.FindItemByPosition(3).Enable(False)
       
   543         self.ContextualMenu.FindItemByPosition(5).Enable(False)
       
   544         self.ContextualMenu.FindItemByPosition(6).Enable(False)
       
   545         self.ContextualMenu.FindItemByPosition(8).Enable(True)
       
   546         self.ContextualMenu.FindItemByPosition(9).Enable(connector)
       
   547         self.PopupMenu(self.ContextualMenu)
       
   548     
       
   549     def PopupDefaultMenu(self):
       
   550         self.ContextualMenu.FindItemByPosition(0).Enable(False)
       
   551         self.ContextualMenu.FindItemByPosition(1).Enable(False)
       
   552         self.ContextualMenu.FindItemByPosition(2).Enable(False)
       
   553         self.ContextualMenu.FindItemByPosition(3).Enable(False)
       
   554         self.ContextualMenu.FindItemByPosition(5).Enable(False)
       
   555         self.ContextualMenu.FindItemByPosition(6).Enable(False)
       
   556         self.ContextualMenu.FindItemByPosition(8).Enable(False)
       
   557         self.ContextualMenu.FindItemByPosition(9).Enable(False)
       
   558         self.PopupMenu(self.ContextualMenu)
       
   559 
       
   560     def EditCommentContent(self, comment):
       
   561         dialog = wxTextEntryDialog(self.Parent, "Edit comment", "Please enter comment text", comment.GetContent(), wxOK|wxCANCEL|wxTE_MULTILINE)
       
   562         if dialog.ShowModal() == wxID_OK:
       
   563             value = dialog.GetValue()
       
   564             comment.SetContent(value)
       
   565             infos = {"content" : value}
       
   566             infos["width"], infos["height"] = comment.GetSize()
       
   567             self.Controler.SetCurrentElementEditingCommentInfos(comment.GetId(), infos)
       
   568             self.Refresh()
       
   569         dialog.Destroy()
       
   570 
       
   571 #-------------------------------------------------------------------------------
       
   572 #                            Menu items functions
       
   573 #-------------------------------------------------------------------------------
       
   574 
       
   575     def OnNoModifierMenu(self, event):
       
   576         if self.SelectedElement and self.SelectedElement in self.Blocks:
       
   577             self.SelectedElement.SetConnectorNegated(False)
       
   578         event.Skip()
       
   579     
       
   580     def OnNegatedMenu(self, event):
       
   581         if self.SelectedElement and self.SelectedElement in self.Blocks:
       
   582             self.SelectedElement.SetConnectorNegated(True)
       
   583         event.Skip()
       
   584 
       
   585     def OnRisingEdgeMenu(self, event):
       
   586         if self.SelectedElement and self.SelectedElement in self.Blocks:
       
   587             self.SelectedElement.SetConnectorEdge("rising")
       
   588         event.Skip()
       
   589 
       
   590     def OnFallingEdgeMenu(self, event):
       
   591         if self.SelectedElement and self.SelectedElement in self.Blocks:
       
   592             self.SelectedElement.SetConnectorEdge("falling")
       
   593         event.Skip()
       
   594 
       
   595     def OnAddSegmentMenu(self, event):
       
   596         if self.SelectedElement and self.SelectedElement in self.Wires:
       
   597             self.SelectedElement.AddSegment()
       
   598         event.Skip()
       
   599 
       
   600     def OnDeleteSegmentMenu(self, event):
       
   601         if self.SelectedElement and self.SelectedElement in self.Wires:
       
   602             self.SelectedElement.DeleteSegment()
       
   603         event.Skip()
       
   604 
       
   605     def OnAddBranchMenu(self, event):
       
   606         if self.SelectedElement and self.SelectedElement in self.Blocks:
       
   607             self.AddDivergenceBranch(self.SelectedElement)
       
   608         event.Skip()
       
   609 
       
   610     def OnDeleteBranchMenu(self, event):
       
   611         if self.SelectedElement and self.SelectedElement in self.Blocks:
       
   612             self.RemoveDivergenceBranch(self.SelectedElement)
       
   613         event.Skip()
       
   614 
       
   615     def OnDeleteMenu(self, event):
       
   616         if self.SelectedElement:
       
   617             self.SelectedElement.Delete()
       
   618             self.SelectedElement = None
       
   619         event.Skip()
       
   620 
       
   621 #-------------------------------------------------------------------------------
       
   622 #                          Mouse event functions
       
   623 #-------------------------------------------------------------------------------
       
   624 
       
   625     def OnViewerLeftDown(self, event):
       
   626         event.Skip()
       
   627 
       
   628     def OnViewerLeftUp(self, event):
       
   629         event.Skip()
       
   630     
       
   631     def OnViewerRightUp(self, event):
       
   632         event.Skip()
       
   633     
       
   634     def OnViewerLeftDClick(self, event):
       
   635         event.Skip()
       
   636     
       
   637     def OnViewerMotion(self, event):
       
   638         event.Skip()
       
   639 
       
   640 #-------------------------------------------------------------------------------
       
   641 #                          Keyboard event functions
       
   642 #-------------------------------------------------------------------------------
       
   643 
       
   644     def OnChar(self, event):
       
   645         event.Skip()
       
   646 
       
   647 #-------------------------------------------------------------------------------
       
   648 #                          Model update functions
       
   649 #-------------------------------------------------------------------------------
       
   650 
       
   651     def RefreshBlockModel(self, block):
       
   652         blockid = block.GetId()
       
   653         infos = {}
       
   654         infos["type"] = block.GetType()
       
   655         infos["name"] = block.GetName()
       
   656         infos["x"], infos["y"] = block.GetPosition()
       
   657         infos["width"], infos["height"] = block.GetSize()
       
   658         infos["connectors"] = block.GetConnectors()
       
   659         self.Controler.SetCurrentElementEditingBlockInfos(blockid, infos)
       
   660     
       
   661     def RefreshVariableModel(self, variable):
       
   662         variableid = variable.GetId()
       
   663         infos = {}
       
   664         infos["name"] = variable.GetName()
       
   665         infos["x"], infos["y"] = variable.GetPosition()
       
   666         infos["width"], infos["height"] = variable.GetSize()
       
   667         infos["connectors"] = variable.GetConnectors()
       
   668         self.Controler.SetCurrentElementEditingVariableInfos(variableid, infos)
       
   669 
       
   670     def RefreshConnectionModel(self, connection):
       
   671         connectionid = connection.GetId()
       
   672         infos = {}
       
   673         infos["name"] = connection.GetName()
       
   674         infos["x"], infos["y"] = connection.GetPosition()
       
   675         infos["width"], infos["height"] = connection.GetSize()
       
   676         infos["connector"] = connection.GetConnector()
       
   677         self.Controler.SetCurrentElementEditingConnectionInfos(connectionid, infos)
       
   678 
       
   679     def RefreshCommentModel(self, comment):
       
   680         commentid = comment.GetId()
       
   681         infos = {}
       
   682         infos["content"] = comment.GetContent()
       
   683         infos["x"], infos["y"] = comment.GetPosition()
       
   684         infos["width"], infos["height"] = comment.GetSize()
       
   685         self.Controler.SetCurrentElementEditingCommentInfos(commentid, infos)
       
   686 
       
   687     def RefreshPowerRailModel(self, powerrail):
       
   688         powerrailid = powerrail.GetId()
       
   689         infos = {}
       
   690         infos["x"], infos["y"] = powerrail.GetPosition()
       
   691         infos["width"], infos["height"] = powerrail.GetSize()
       
   692         infos["connectors"] = powerrail.GetConnectors()
       
   693         self.Controler.SetCurrentElementEditingPowerRailInfos(powerrailid, infos)
       
   694 
       
   695     def RefreshContactModel(self, contact):
       
   696         contactid = contact.GetId()
       
   697         infos = {}
       
   698         infos["name"] = contact.GetName()
       
   699         infos["type"] = contact.GetType()
       
   700         infos["x"], infos["y"] = contact.GetPosition()
       
   701         infos["width"], infos["height"] = contact.GetSize()
       
   702         infos["connectors"] = contact.GetConnectors()
       
   703         self.Controler.SetCurrentElementEditingContactInfos(contactid, infos)
       
   704 
       
   705     def RefreshCoilModel(self, coil):
       
   706         coilid = coil.GetId()
       
   707         infos = {}
       
   708         infos["name"] = coil.GetName()
       
   709         infos["type"] = coil.GetType()
       
   710         infos["x"], infos["y"] = coil.GetPosition()
       
   711         infos["width"], infos["height"] = coil.GetSize()
       
   712         infos["connectors"] = coil.GetConnectors()
       
   713         self.Controler.SetCurrentElementEditingCoilInfos(coilid, infos)
       
   714 
       
   715     def RefreshStepModel(self, step):
       
   716         stepid = step.GetId()
       
   717         infos = {}
       
   718         infos["name"] = step.GetName()
       
   719         infos["initial"] = step.GetInitial()
       
   720         infos["x"], infos["y"] = step.GetPosition()
       
   721         infos["width"], infos["height"] = step.GetSize()
       
   722         infos["connectors"] = step.GetConnectors()
       
   723         self.Controler.SetCurrentElementEditingStepInfos(stepid, infos)
       
   724 
       
   725     def RefreshTransitionModel(self, transition):
       
   726         transitionid = transition.GetId()
       
   727         infos = {}
       
   728         infos["type"] = transition.GetType()
       
   729         infos["condition"] = transition.GetCondition()
       
   730         infos["x"], infos["y"] = transition.GetPosition()
       
   731         infos["width"], infos["height"] = transition.GetSize()
       
   732         infos["connectors"] = transition.GetConnectors()
       
   733         self.Controler.SetCurrentElementEditingTransitionInfos(transitionid, infos)
       
   734 
       
   735     def RefreshDivergenceModel(self, divergence):
       
   736         divergenceid = divergence.GetId()
       
   737         infos = {}
       
   738         infos["x"], infos["y"] = divergence.GetPosition()
       
   739         infos["width"], infos["height"] = divergence.GetSize()
       
   740         infos["connectors"] = divergence.GetConnectors()
       
   741         self.Controler.SetCurrentElementEditingDivergenceInfos(divergenceid, infos)
       
   742 
       
   743     def RefreshJumpModel(self, jump):
       
   744         jumpid = jump.GetId()
       
   745         infos = {}
       
   746         infos["target"] = jump.GetTarget()
       
   747         infos["x"], infos["y"] = jump.GetPosition()
       
   748         infos["width"], infos["height"] = jump.GetSize()
       
   749         infos["connector"] = jump.GetConnector()
       
   750         self.Controler.SetCurrentElementEditingJumpInfos(jumpid, infos)
       
   751 
       
   752     def RefreshActionBlockModel(self, actionblock):
       
   753         actionblockid = actionblock.GetId()
       
   754         infos = {}
       
   755         infos["actions"] = actionblock.GetActions()
       
   756         infos["x"], infos["y"] = actionblock.GetPosition()
       
   757         infos["width"], infos["height"] = actionblock.GetSize()
       
   758         infos["connector"] = actionblock.GetConnector()
       
   759         self.Controler.SetCurrentElementEditingActionBlockInfos(actionblockid, infos)
       
   760 
       
   761 #-------------------------------------------------------------------------------
       
   762 #                            Editing functions
       
   763 #-------------------------------------------------------------------------------
       
   764     
       
   765     def Cut(self):
       
   766         pass
       
   767         
       
   768     def Copy(self):
       
   769         pass
       
   770     
       
   771     def Paste(self):
       
   772         pass
       
   773 
       
   774 #-------------------------------------------------------------------------------
       
   775 #                            Drawing functions
       
   776 #-------------------------------------------------------------------------------
       
   777 
       
   778     def OnPaint(self, event):
       
   779         dc = wxClientDC(self)
       
   780         dc.Clear()
       
   781         dc.SetPen(wxPen(wxColour(230, 230, 230)))
       
   782         if self.Scaling and self.DrawGrid:
       
   783             width, height = dc.GetSize()
       
   784             for i in xrange(1, width / self.Scaling[0] + 1):
       
   785                 dc.DrawLine(i * self.Scaling[0], 0, i * self.Scaling[0], height)
       
   786             for i in xrange(1, height / self.Scaling[1] + 1):
       
   787                 dc.DrawLine(0, i * self.Scaling[1], width, i * self.Scaling[1])
       
   788         for wire in self.Wires:
       
   789             if wire != self.SelectedElement:
       
   790                 wire.Draw(dc)
       
   791         for element in self.Elements:
       
   792             if element not in self.Wires and element != self.SelectedElement:
       
   793                 element.Draw(dc)
       
   794         if self.SelectedElement:
       
   795             self.SelectedElement.Draw(dc)
       
   796         event.Skip()
       
   797 
       
   798 
       
   799 #-------------------------------------------------------------------------------
       
   800 #                         Textual programs Viewer class
       
   801 #-------------------------------------------------------------------------------
       
   802 
       
   803 
       
   804 NEWLINE = "\n"
       
   805 NUMBERS = [str(i) for i in xrange(10)]
       
   806 LETTERS = ['_']
       
   807 for i in xrange(26):
       
   808     LETTERS.append(chr(ord('a') + i))
       
   809     LETTERS.append(chr(ord('A') + i))
       
   810 
       
   811 [wxSTC_PLC_WORD, wxSTC_PLC_COMMENT, wxSTC_PLC_NUMBER, wxSTC_PLC_VARIABLE, 
       
   812  wxSTC_PLC_FUNCTION, wxSTC_PLC_JUMP] = range(6)
       
   813 [SPACE, WORD, NUMBER, COMMENT] = range(4)
       
   814 
       
   815 [wxID_TEXTVIEWER,
       
   816 ] = [wx.NewId() for _init_ctrls in range(1)]
       
   817 
       
   818 if wx.Platform == '__WXMSW__':
       
   819     faces = { 'times': 'Times New Roman',
       
   820               'mono' : 'Courier New',
       
   821               'helv' : 'Arial',
       
   822               'other': 'Comic Sans MS',
       
   823               'size' : 10,
       
   824              }
       
   825 else:
       
   826     faces = { 'times': 'Times',
       
   827               'mono' : 'Courier',
       
   828               'helv' : 'Helvetica',
       
   829               'other': 'new century schoolbook',
       
   830               'size' : 12,
       
   831              }
       
   832 re_texts = {}
       
   833 re_texts["letter"] = "[A-Za-z]"
       
   834 re_texts["digit"] = "[0-9]"
       
   835 re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts
       
   836 IDENTIFIER_MODEL = re.compile(re_texts["identifier"])
       
   837 LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts)
       
   838 
       
   839 class TextViewer(wxStyledTextCtrl):
       
   840     
       
   841     def __init__(self, parent, window, controler):
       
   842         wxStyledTextCtrl.__init__(self, parent, wxID_TEXTVIEWER, style=0)
       
   843         
       
   844         self.CmdKeyAssign(ord('+'), wxSTC_SCMOD_CTRL, wxSTC_CMD_ZOOMIN)
       
   845         self.CmdKeyAssign(ord('-'), wxSTC_SCMOD_CTRL, wxSTC_CMD_ZOOMOUT)
       
   846         
       
   847         self.SetViewWhiteSpace(False)
       
   848         
       
   849         self.SetLexer(wxSTC_LEX_CONTAINER)
       
   850         
       
   851         # Global default styles for all languages
       
   852         self.StyleSetSpec(wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
       
   853         self.StyleClearAll()  # Reset all to be like the default
       
   854         
       
   855         self.StyleSetSpec(wxSTC_STYLE_LINENUMBER,  "back:#C0C0C0,size:%(size)d" % faces)
       
   856         self.SetSelBackground(1, "#E0E0E0")
       
   857         
       
   858         # Highlighting styles
       
   859         self.StyleSetSpec(wxSTC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
       
   860         self.StyleSetSpec(wxSTC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces)
       
   861         self.StyleSetSpec(wxSTC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces)
       
   862         self.StyleSetSpec(wxSTC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces)
       
   863         self.StyleSetSpec(wxSTC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
       
   864         self.StyleSetSpec(wxSTC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces)
       
   865         
       
   866         # Indicators styles
       
   867         self.IndicatorSetStyle(0, wxSTC_INDIC_SQUIGGLE)
       
   868         self.IndicatorSetForeground(0, wxRED)
       
   869         
       
   870         # Line numbers in the margin
       
   871         self.SetMarginType(1, wxSTC_MARGIN_NUMBER)
       
   872         self.SetMarginWidth(1, 50)
       
   873         
       
   874         # Indentation size
       
   875         self.SetTabWidth(2)
       
   876         
       
   877         self.Keywords = []
       
   878         self.Variables = []
       
   879         self.Functions = []
       
   880         self.Jumps = []
       
   881         self.TextChanged = False
       
   882         
       
   883         self.Controler = controler
       
   884 
       
   885         EVT_KEY_DOWN(self, self.OnKeyDown)
       
   886         EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded)
       
   887     
       
   888     def SetKeywords(self, keywords):
       
   889         self.Keywords = [keyword.upper() for keyword in keywords]
       
   890         self.Colourise(0, -1)
       
   891     
       
   892     def SetVariables(self, variables):
       
   893         self.Variables = [variable.upper() for variable in variables]
       
   894         self.Colourise(0, -1)
       
   895     
       
   896     def SetFunctions(self, blocktypes):
       
   897         self.Functions = []
       
   898         for category in blocktypes:
       
   899             for blocktype in category["list"]:
       
   900                 if blocktype["name"] not in self.Keywords and blocktype["name"] not in self.Variables:
       
   901                     self.Functions.append(blocktype["name"].upper())
       
   902         self.Colourise(0, -1)
       
   903     
       
   904     def RefreshJumpList(self):
       
   905         self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())]
       
   906         self.Colourise(0, -1)
       
   907     
       
   908     def RefreshView(self):
       
   909         self.SetText(self.Controler.GetCurrentElementEditingText())
       
   910         self.RefreshJumpList()
       
   911     
       
   912     def OnStyleNeeded(self, event):
       
   913         self.TextChanged = True
       
   914         line = self.LineFromPosition(self.GetEndStyled())
       
   915         if line == 0:
       
   916             start_pos = 0
       
   917         else:
       
   918             start_pos = self.GetLineEndPosition(line - 1) + 1
       
   919         end_pos = event.GetPosition()
       
   920         self.StartStyling(start_pos, 0xff)
       
   921         
       
   922         i = start_pos
       
   923         state = SPACE
       
   924         line = ""
       
   925         word = ""
       
   926         while i < end_pos:
       
   927             char = chr(self.GetCharAt(i)).upper()
       
   928             line += char
       
   929             if char == NEWLINE:
       
   930                 if state == COMMENT:
       
   931                     self.SetStyling(i - start_pos + 1, wxSTC_PLC_COMMENT)
       
   932                 elif state == NUMBER:
       
   933                     self.SetStyling(i - start_pos, wxSTC_PLC_NUMBER)
       
   934                 elif state == WORD:
       
   935                     if word in self.Keywords:
       
   936                         self.SetStyling(i - start_pos, wxSTC_PLC_WORD)
       
   937                     elif word in self.Variables:
       
   938                         self.SetStyling(i - start_pos, wxSTC_PLC_VARIABLE)
       
   939                     elif word in self.Functions:
       
   940                         self.SetStyling(i - start_pos, wxSTC_PLC_FUNCTION)
       
   941                     elif word in self.Jumps:
       
   942                         self.SetStyling(i - start_pos, wxSTC_PLC_JUMP)
       
   943                     else:
       
   944                         self.SetStyling(i - start_pos, 31)
       
   945                         if self.GetCurrentPos() < start_pos or self.GetCurrentPos() > i:
       
   946                             self.StartStyling(start_pos, wxSTC_INDICS_MASK)
       
   947                             self.SetStyling(i - start_pos, wxSTC_INDIC0_MASK)
       
   948                             self.StartStyling(i, 0xff)    
       
   949                 else:
       
   950                     self.SetStyling(i - start_pos, 31)
       
   951                 start_pos = i
       
   952                 state = SPACE
       
   953                 line = ""
       
   954             elif line.endswith("(*") and state != COMMENT:
       
   955                 self.SetStyling(i - start_pos - 1, 31)
       
   956                 start_pos = i
       
   957                 state = COMMENT
       
   958             elif state == COMMENT:
       
   959                 if line.endswith("*)"):
       
   960                     self.SetStyling(i - start_pos + 2, wxSTC_PLC_COMMENT)
       
   961                     start_pos = i + 1
       
   962                     state = SPACE
       
   963             elif char in LETTERS:
       
   964                 if state == NUMBER:
       
   965                     word = "#"
       
   966                     state = WORD
       
   967                 elif state == SPACE:
       
   968                     self.SetStyling(i - start_pos, 31)
       
   969                     word = char
       
   970                     start_pos = i
       
   971                     state = WORD
       
   972                 else:
       
   973                     word += char
       
   974             elif char in NUMBERS or char == '.' and state != WORD:
       
   975                 if state == SPACE:
       
   976                     self.SetStyling(i - start_pos, 31)
       
   977                     start_pos = i
       
   978                     state = NUMBER
       
   979                 if state == WORD and char != '.':
       
   980                     word += char
       
   981             else:
       
   982                 if state == WORD:
       
   983                     if word in self.Keywords:
       
   984                         self.SetStyling(i - start_pos, wxSTC_PLC_WORD)
       
   985                     elif word in self.Variables:
       
   986                         self.SetStyling(i - start_pos, wxSTC_PLC_VARIABLE)
       
   987                     elif word in self.Functions:
       
   988                         self.SetStyling(i - start_pos, wxSTC_PLC_FUNCTION)
       
   989                     elif word in self.Jumps:
       
   990                         self.SetStyling(i - start_pos, wxSTC_PLC_JUMP)
       
   991                     else:
       
   992                         self.SetStyling(i - start_pos, 31)
       
   993                         if self.GetCurrentPos() < start_pos or self.GetCurrentPos() > i:
       
   994                             self.StartStyling(start_pos, wxSTC_INDICS_MASK)
       
   995                             self.SetStyling(i - start_pos, wxSTC_INDIC0_MASK)
       
   996                             self.StartStyling(i, 0xff)
       
   997                     word = ""
       
   998                     start_pos = i
       
   999                     state = SPACE
       
  1000                 elif state == NUMBER:
       
  1001                     self.SetStyling(i - start_pos, wxSTC_PLC_NUMBER)
       
  1002                     start_pos = i
       
  1003                     state = SPACE
       
  1004             i += 1
       
  1005         if state == COMMENT:
       
  1006             self.SetStyling(i - start_pos + 2, wxSTC_PLC_COMMENT)
       
  1007         elif state == NUMBER:
       
  1008             self.SetStyling(i - start_pos, wxSTC_PLC_NUMBER)
       
  1009         elif state == WORD:
       
  1010             if word in self.Keywords:
       
  1011                 self.SetStyling(i - start_pos, wxSTC_PLC_WORD)
       
  1012             elif word in self.Variables:
       
  1013                 self.SetStyling(i - start_pos, wxSTC_PLC_VARIABLE)
       
  1014             elif word in self.Functions:
       
  1015                 self.SetStyling(i - start_pos, wxSTC_PLC_FUNCTION)
       
  1016             elif word in self.Jumps:
       
  1017                 self.SetStyling(i - start_pos, wxSTC_PLC_JUMP)
       
  1018             else:
       
  1019                 self.SetStyling(i - start_pos, 31)
       
  1020         else:
       
  1021             self.SetStyling(i - start_pos, 31)
       
  1022         event.Skip()
       
  1023     
       
  1024     def Cut(self):
       
  1025         self.CmdKeyExecute(wxSTC_CMD_CUT)
       
  1026         
       
  1027     def Copy(self):
       
  1028         self.CmdKeyExecute(wxSTC_CMD_COPY)
       
  1029     
       
  1030     def Paste(self):
       
  1031         self.CmdKeyExecute(wxSTC_CMD_PASTE)
       
  1032     
       
  1033     def RefreshModel(self):
       
  1034         if self.TextChanged:
       
  1035             self.RefreshJumpList()
       
  1036             self.Controler.SetCurrentElementEditingText(self.GetText())
       
  1037     
       
  1038     def OnKeyDown(self, event):
       
  1039         if self.CallTipActive():
       
  1040             self.CallTipCancel()
       
  1041         key = event.KeyCode()
       
  1042 
       
  1043         if key == WXK_SPACE and event.ControlDown():
       
  1044             pos = self.GetCurrentPos()
       
  1045 
       
  1046             # Tips
       
  1047             if event.ShiftDown():
       
  1048                 self.CallTipSetBackground("yellow")
       
  1049                 self.CallTipShow(pos, 'Here will be some help.')
       
  1050             
       
  1051             # Code completion
       
  1052             else:
       
  1053                 kw = [key for key in self.Keywords]
       
  1054                 
       
  1055                 kw.sort()  # Python sorts are case sensitive
       
  1056                 self.AutoCompSetIgnoreCase(False)  # so this needs to match
       
  1057 
       
  1058                 self.AutoCompShow(0, " ".join(kw))
       
  1059         else:
       
  1060             self.TextChanged = False
       
  1061             wxCallAfter(self.RefreshModel)
       
  1062             event.Skip()
       
  1063 
       
  1064 
       
  1065 #-------------------------------------------------------------------------------
       
  1066 #                            Resource Editor class
       
  1067 #-------------------------------------------------------------------------------
       
  1068 
       
  1069 class ResourceTable(wxPyGridTableBase):
       
  1070     
       
  1071     """
       
  1072     A custom wxGrid Table using user supplied data
       
  1073     """
       
  1074     def __init__(self, parent, data, colnames):
       
  1075         # The base class must be initialized *first*
       
  1076         wxPyGridTableBase.__init__(self)
       
  1077         self.data = data
       
  1078         self.colnames = colnames
       
  1079         self.Parent = parent
       
  1080         
       
  1081         self.ColAlignements = []
       
  1082         self.ColSizes = []
       
  1083         # XXX
       
  1084         # we need to store the row length and collength to
       
  1085         # see if the table has changed size
       
  1086         self._rows = self.GetNumberRows()
       
  1087         self._cols = self.GetNumberCols()
       
  1088     
       
  1089     def GetColAlignements(self):
       
  1090         return self.ColAlignements
       
  1091     
       
  1092     def SetColAlignements(self, list):
       
  1093         self.ColAlignements = list
       
  1094 
       
  1095     def GetColSizes(self):
       
  1096         return self.ColSizes
       
  1097     
       
  1098     def SetColSizes(self, list):
       
  1099         self.ColSizes = list
       
  1100 
       
  1101     def GetNumberCols(self):
       
  1102         return len(self.colnames)
       
  1103         
       
  1104     def GetNumberRows(self):
       
  1105         return len(self.data)
       
  1106 
       
  1107     def GetColLabelValue(self, col):
       
  1108         if col < len(self.colnames):
       
  1109             return self.colnames[col]
       
  1110 
       
  1111     def GetRowLabelValues(self, row):
       
  1112         return row
       
  1113 
       
  1114     def GetValue(self, row, col):
       
  1115         if row < self.GetNumberRows():
       
  1116             name = str(self.data[row].get(self.GetColLabelValue(col), ""))
       
  1117             return name
       
  1118     
       
  1119     def GetValueByName(self, row, colname):
       
  1120         return self.data[row].get(colname)
       
  1121 
       
  1122     def SetValue(self, row, col, value):
       
  1123         if col < len(self.colnames):
       
  1124             self.data[row][self.GetColLabelValue(col)] = value
       
  1125     
       
  1126     def SetValueByName(self, row, colname, value):
       
  1127         if colname in self.colnames:
       
  1128             self.data[row][colname] = value
       
  1129     
       
  1130     def ResetView(self, grid):
       
  1131         """
       
  1132         (wxGrid) -> Reset the grid view.   Call this to
       
  1133         update the grid if rows and columns have been added or deleted
       
  1134         """
       
  1135         grid.BeginBatch()
       
  1136         for current, new, delmsg, addmsg in [
       
  1137             (self._rows, self.GetNumberRows(), wxGRIDTABLE_NOTIFY_ROWS_DELETED, wxGRIDTABLE_NOTIFY_ROWS_APPENDED),
       
  1138             (self._cols, self.GetNumberCols(), wxGRIDTABLE_NOTIFY_COLS_DELETED, wxGRIDTABLE_NOTIFY_COLS_APPENDED),
       
  1139         ]:
       
  1140             if new < current:
       
  1141                 msg = wxGridTableMessage(self,delmsg,new,current-new)
       
  1142                 grid.ProcessTableMessage(msg)
       
  1143             elif new > current:
       
  1144                 msg = wxGridTableMessage(self,addmsg,new-current)
       
  1145                 grid.ProcessTableMessage(msg)
       
  1146                 self.UpdateValues(grid)
       
  1147         grid.EndBatch()
       
  1148 
       
  1149         self._rows = self.GetNumberRows()
       
  1150         self._cols = self.GetNumberCols()
       
  1151         # update the column rendering scheme
       
  1152         self._updateColAttrs(grid)
       
  1153 
       
  1154         # update the scrollbars and the displayed part of the grid
       
  1155         grid.AdjustScrollbars()
       
  1156         grid.ForceRefresh()
       
  1157 
       
  1158     def UpdateValues(self, grid):
       
  1159         """Update all displayed values"""
       
  1160         # This sends an event to the grid table to update all of the values
       
  1161         msg = wxGridTableMessage(self, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES)
       
  1162         grid.ProcessTableMessage(msg)
       
  1163 
       
  1164     def _updateColAttrs(self, grid):
       
  1165         """
       
  1166         wxGrid -> update the column attributes to add the
       
  1167         appropriate renderer given the column name.
       
  1168 
       
  1169         Otherwise default to the default renderer.
       
  1170         """
       
  1171         
       
  1172         for col in range(self.GetNumberCols()):
       
  1173             attr = wxGridCellAttr()
       
  1174             attr.SetAlignment(self.ColAlignements[col], wxALIGN_CENTRE)
       
  1175             grid.SetColAttr(col, attr)
       
  1176             grid.SetColSize(col, self.ColSizes[col])
       
  1177         
       
  1178         for row in range(self.GetNumberRows()):
       
  1179             for col in range(self.GetNumberCols()):
       
  1180                 editor = None
       
  1181                 renderer = None
       
  1182                 colname = self.GetColLabelValue(col)
       
  1183                 grid.SetReadOnly(row, col, False)
       
  1184                 if colname in ["Name","Interval"]:
       
  1185                     editor = wxGridCellTextEditor()
       
  1186                     renderer = wxGridCellStringRenderer()
       
  1187                     if colname == "Interval" and self.GetValueByName(row, "Single") != "":
       
  1188                         grid.SetReadOnly(row, col, True)
       
  1189                 elif colname == "Single":
       
  1190                     editor = wxGridCellChoiceEditor()
       
  1191                     editor.SetParameters(self.Parent.VariableList)
       
  1192                     if self.GetValueByName(row, "Interval") != "":
       
  1193                         grid.SetReadOnly(row, col, True)
       
  1194                 elif colname == "Type":
       
  1195                     editor = wxGridCellChoiceEditor()
       
  1196                     editor.SetParameters(self.Parent.TypeList)
       
  1197                 elif colname == "Priority":
       
  1198                     editor = wxGridCellNumberEditor()
       
  1199                     editor.SetParameters("0,65535")
       
  1200                 elif colname == "Task":
       
  1201                     editor = wxGridCellChoiceEditor()
       
  1202                     editor.SetParameters(self.Parent.TaskList)
       
  1203                     
       
  1204                 grid.SetCellEditor(row, col, editor)
       
  1205                 grid.SetCellRenderer(row, col, renderer)
       
  1206                 
       
  1207                 grid.SetCellBackgroundColour(row, col, wxWHITE)
       
  1208     
       
  1209     def SetData(self, data):
       
  1210         self.data = data
       
  1211     
       
  1212     def GetData(self):
       
  1213         return self.data
       
  1214     
       
  1215     def GetCurrentIndex(self):
       
  1216         return self.CurrentIndex
       
  1217     
       
  1218     def SetCurrentIndex(self, index):
       
  1219         self.CurrentIndex = index
       
  1220     
       
  1221     def AppendRow(self, row_content):
       
  1222         self.data.append(row_content)
       
  1223 
       
  1224     def RemoveRow(self, row_index):
       
  1225         self.data.pop(row_index)
       
  1226         
       
  1227     def MoveRow(self, row_index, move, grid):
       
  1228         new_index = max(0, min(row_index + move, len(self.data) - 1))
       
  1229         if new_index != row_index:
       
  1230             self.data.insert(new_index, self.data.pop(row_index))
       
  1231             grid.SetGridCursor(new_index, grid.GetGridCursorCol())
       
  1232 
       
  1233     def Empty(self):
       
  1234         self.data = []
       
  1235         self.editors = []
       
  1236 
       
  1237 [wxID_RESOURCEEDITOR, wxID_RESOURCEEDITORSTATICTEXT1,
       
  1238  wxID_RESOURCEEDITORSTATICTEXT2, wxID_RESOURCEEDITORINSTANCESGRID,
       
  1239  wxID_RESOURCEEDITORTASKSGRID, wxID_RESOURCEEDITORADDINSTANCEBUTTON,
       
  1240  wxID_RESOURCEEDITORDELETEINSTANCEBUTTON, wxID_RESOURCEEDITORUPINSTANCEBUTTON,
       
  1241  wxID_RESOURCEEDITORDOWNINSTANCEBUTTON, wxID_RESOURCEEDITORADDTASKBUTTON,
       
  1242  wxID_RESOURCEEDITORDELETETASKBUTTON, wxID_RESOURCEEDITORUPTASKBUTTON,
       
  1243  wxID_RESOURCEEDITORDOWNTASKBUTTON,
       
  1244 ] = [wx.NewId() for _init_ctrls in range(13)]
       
  1245 
       
  1246 class ResourceEditor(wx.Panel):
       
  1247     
       
  1248     def _init_coll_InstancesSizer_Growables(self, parent):
       
  1249         # generated method, don't edit
       
  1250 
       
  1251         parent.AddGrowableCol(0)
       
  1252         parent.AddGrowableRow(1)
       
  1253 
       
  1254     def _init_coll_InstancesSizer_Items(self, parent):
       
  1255         # generated method, don't edit
       
  1256 
       
  1257         parent.AddSizer(self.InstancesButtonsSizer, 0, border=0, flag=wxGROW)
       
  1258         parent.AddWindow(self.InstancesGrid, 0, border=0, flag=wxGROW)
       
  1259 
       
  1260     def _init_coll_InstancesButtonsSizer_Growables(self, parent):
       
  1261         # generated method, don't edit
       
  1262 
       
  1263         parent.AddGrowableCol(0)
       
  1264         parent.AddGrowableRow(0)
       
  1265 
       
  1266     def _init_coll_InstancesButtonsSizer_Items(self, parent):
       
  1267         # generated method, don't edit
       
  1268 
       
  1269         parent.AddWindow(self.staticText2, 0, border=0, flag=wxALIGN_BOTTOM)
       
  1270         parent.AddWindow(self.AddInstanceButton, 0, border=0, flag=0)
       
  1271         parent.AddWindow(self.DeleteInstanceButton, 0, border=0, flag=0)
       
  1272         parent.AddWindow(self.UpInstanceButton, 0, border=0, flag=0)
       
  1273         parent.AddWindow(self.DownInstanceButton, 0, border=0, flag=0)
       
  1274 
       
  1275     def _init_coll_TasksSizer_Growables(self, parent):
       
  1276         # generated method, don't edit
       
  1277 
       
  1278         parent.AddGrowableCol(0)
       
  1279         parent.AddGrowableRow(1)
       
  1280 
       
  1281     def _init_coll_TasksSizer_Items(self, parent):
       
  1282         # generated method, don't edit
       
  1283 
       
  1284         parent.AddSizer(self.TasksButtonsSizer, 0, border=0, flag=wxGROW)
       
  1285         parent.AddWindow(self.TasksGrid, 0, border=0, flag=wxGROW)
       
  1286 
       
  1287     def _init_coll_TasksButtonsSizer_Growables(self, parent):
       
  1288         # generated method, don't edit
       
  1289 
       
  1290         parent.AddGrowableCol(0)
       
  1291         parent.AddGrowableRow(0)
       
  1292 
       
  1293     def _init_coll_TasksButtonsSizer_Items(self, parent):
       
  1294         # generated method, don't edit
       
  1295 
       
  1296         parent.AddWindow(self.staticText1, 0, border=0, flag=wxALIGN_BOTTOM)
       
  1297         parent.AddWindow(self.AddTaskButton, 0, border=0, flag=0)
       
  1298         parent.AddWindow(self.DeleteTaskButton, 0, border=0, flag=0)
       
  1299         parent.AddWindow(self.UpTaskButton, 0, border=0, flag=0)
       
  1300         parent.AddWindow(self.DownTaskButton, 0, border=0, flag=0)
       
  1301 
       
  1302     def _init_coll_MainGridSizer_Items(self, parent):
       
  1303         # generated method, don't edit
       
  1304 
       
  1305         parent.AddSizer(self.TasksSizer, 0, border=0, flag=wxGROW)
       
  1306         parent.AddSizer(self.InstancesSizer, 0, border=0, flag=wxGROW)
       
  1307 
       
  1308     def _init_coll_MainGridSizer_Growables(self, parent):
       
  1309         # generated method, don't edit
       
  1310 
       
  1311         parent.AddGrowableCol(0)
       
  1312         parent.AddGrowableRow(0)
       
  1313         parent.AddGrowableRow(1)
       
  1314 
       
  1315     def _init_sizers(self):
       
  1316         # generated method, don't edit
       
  1317         self.MainGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
  1318 
       
  1319         self.InstancesSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
  1320 
       
  1321         self.InstancesButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
       
  1322 
       
  1323         self.TasksSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
  1324 
       
  1325         self.TasksButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
       
  1326 
       
  1327         self._init_coll_MainGridSizer_Growables(self.MainGridSizer)
       
  1328         self._init_coll_MainGridSizer_Items(self.MainGridSizer)
       
  1329         self._init_coll_InstancesSizer_Growables(self.InstancesSizer)
       
  1330         self._init_coll_InstancesSizer_Items(self.InstancesSizer)
       
  1331         self._init_coll_InstancesButtonsSizer_Growables(self.InstancesButtonsSizer)
       
  1332         self._init_coll_InstancesButtonsSizer_Items(self.InstancesButtonsSizer)
       
  1333         self._init_coll_TasksSizer_Growables(self.TasksSizer)
       
  1334         self._init_coll_TasksSizer_Items(self.TasksSizer)
       
  1335         self._init_coll_TasksButtonsSizer_Growables(self.TasksButtonsSizer)
       
  1336         self._init_coll_TasksButtonsSizer_Items(self.TasksButtonsSizer)
       
  1337 
       
  1338         self.SetSizer(self.MainGridSizer)
       
  1339 
       
  1340     def _init_ctrls(self, prnt):
       
  1341         # generated method, don't edit
       
  1342         wx.Panel.__init__(self, id=wxID_RESOURCEEDITOR, name='', parent=prnt,
       
  1343               pos=wx.Point(0, 0), size=wx.Size(-1, -1),
       
  1344               style=wx.SUNKEN_BORDER)
       
  1345         
       
  1346         self.staticText1 = wx.StaticText(id=wxID_RESOURCEEDITORSTATICTEXT1,
       
  1347               label=u'Tasks:', name='staticText2', parent=self, pos=wx.Point(0,
       
  1348               0), size=wx.Size(60, 17), style=wxALIGN_CENTER)
       
  1349 
       
  1350         self.TasksGrid = wx.grid.Grid(id=wxID_RESOURCEEDITORTASKSGRID,
       
  1351               name='TasksGrid', parent=self, pos=wx.Point(0, 0), 
       
  1352               size=wx.Size(-1, -1), style=wxVSCROLL)
       
  1353         self.TasksGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
       
  1354               'Sans'))
       
  1355         self.TasksGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
       
  1356               False, 'Sans'))
       
  1357         EVT_GRID_CELL_CHANGE(self.TasksGrid, self.OnTasksGridCellChange)
       
  1358 
       
  1359         self.AddTaskButton = wx.Button(id=wxID_RESOURCEEDITORADDTASKBUTTON, label='Add Task',
       
  1360               name='AddTaskButton', parent=self, pos=wx.Point(0, 0),
       
  1361               size=wx.Size(102, 32), style=0)
       
  1362         EVT_BUTTON(self, wxID_RESOURCEEDITORADDTASKBUTTON, self.OnAddTaskButton)
       
  1363 
       
  1364         self.DeleteTaskButton = wx.Button(id=wxID_RESOURCEEDITORDELETETASKBUTTON, label='Delete Task',
       
  1365               name='DeleteTaskButton', parent=self, pos=wx.Point(0, 0),
       
  1366               size=wx.Size(102, 32), style=0)
       
  1367         EVT_BUTTON(self, wxID_RESOURCEEDITORDELETETASKBUTTON, self.OnDeleteTaskButton)
       
  1368 
       
  1369         self.UpTaskButton = wx.Button(id=wxID_RESOURCEEDITORUPTASKBUTTON, label='^',
       
  1370               name='UpTaskButton', parent=self, pos=wx.Point(0, 0),
       
  1371               size=wx.Size(32, 32), style=0)
       
  1372         EVT_BUTTON(self, wxID_RESOURCEEDITORUPTASKBUTTON, self.OnUpTaskButton)
       
  1373 
       
  1374         self.DownTaskButton = wx.Button(id=wxID_RESOURCEEDITORDOWNTASKBUTTON, label='v',
       
  1375               name='DownTaskButton', parent=self, pos=wx.Point(0, 0),
       
  1376               size=wx.Size(32, 32), style=0)
       
  1377         EVT_BUTTON(self, wxID_RESOURCEEDITORDOWNTASKBUTTON, self.OnDownTaskButton)
       
  1378 
       
  1379         self.staticText2 = wx.StaticText(id=wxID_RESOURCEEDITORSTATICTEXT2,
       
  1380               label=u'Instances:', name='staticText1', parent=self,
       
  1381               pos=wx.Point(0, 0), size=wx.Size(85, 17), style=wxALIGN_CENTER)
       
  1382 
       
  1383         self.InstancesGrid = wx.grid.Grid(id=wxID_RESOURCEEDITORINSTANCESGRID,
       
  1384               name='InstancesGrid', parent=self, pos=wx.Point(0, 0), 
       
  1385               size=wx.Size(-1, -1), style=wxVSCROLL)
       
  1386         self.InstancesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False,
       
  1387               'Sans'))
       
  1388         self.InstancesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL,
       
  1389               False, 'Sans'))
       
  1390         EVT_GRID_CELL_CHANGE(self.InstancesGrid, self.OnInstancesGridCellChange)
       
  1391 
       
  1392         self.AddInstanceButton = wx.Button(id=wxID_RESOURCEEDITORADDINSTANCEBUTTON, label='Add Instance',
       
  1393               name='AddInstanceButton', parent=self, pos=wx.Point(0, 0),
       
  1394               size=wx.Size(122, 32), style=0)
       
  1395         EVT_BUTTON(self, wxID_RESOURCEEDITORADDINSTANCEBUTTON, self.OnAddInstanceButton)
       
  1396 
       
  1397         self.DeleteInstanceButton = wx.Button(id=wxID_RESOURCEEDITORDELETEINSTANCEBUTTON, label='Delete Instance',
       
  1398               name='DeleteInstanceButton', parent=self, pos=wx.Point(0, 0),
       
  1399               size=wx.Size(122, 32), style=0)
       
  1400         EVT_BUTTON(self, wxID_RESOURCEEDITORDELETEINSTANCEBUTTON, self.OnDeleteInstanceButton)
       
  1401 
       
  1402         self.UpInstanceButton = wx.Button(id=wxID_RESOURCEEDITORUPINSTANCEBUTTON, label='^',
       
  1403               name='UpInstanceButton', parent=self, pos=wx.Point(0, 0),
       
  1404               size=wx.Size(32, 32), style=0)
       
  1405         EVT_BUTTON(self, wxID_RESOURCEEDITORUPINSTANCEBUTTON, self.OnUpInstanceButton)
       
  1406 
       
  1407         self.DownInstanceButton = wx.Button(id=wxID_RESOURCEEDITORDOWNINSTANCEBUTTON, label='v',
       
  1408               name='DownInstanceButton', parent=self, pos=wx.Point(0, 0),
       
  1409               size=wx.Size(32, 32), style=0)
       
  1410         EVT_BUTTON(self, wxID_RESOURCEEDITORDOWNINSTANCEBUTTON, self.OnDownInstanceButton)
       
  1411 
       
  1412         self._init_sizers()
       
  1413 
       
  1414     def __init__(self, parent, window, controler):
       
  1415         self._init_ctrls(parent)
       
  1416         
       
  1417         self.Parent = window
       
  1418         self.Controler = controler
       
  1419         
       
  1420         self.TasksDefaultValue = {"Name" : "", "Single" : "", "Interval" : "", "Priority" : 0}
       
  1421         self.TasksTable = ResourceTable(self, [], ["Name", "Single", "Interval", "Priority"])
       
  1422         self.TasksTable.SetColAlignements([wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_RIGHT, wxALIGN_RIGHT])
       
  1423         self.TasksTable.SetColSizes([200, 100, 100, 100])
       
  1424         self.TasksGrid.SetTable(self.TasksTable)
       
  1425         self.TasksGrid.SetRowLabelSize(0)
       
  1426         self.TasksTable.ResetView(self.TasksGrid)
       
  1427 
       
  1428         self.InstancesDefaultValue = {"Name" : "", "Type" : "", "Task" : ""}
       
  1429         self.InstancesTable = ResourceTable(self, [], ["Name", "Type", "Task"])
       
  1430         self.InstancesTable.SetColAlignements([wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT])
       
  1431         self.InstancesTable.SetColSizes([200, 150, 150])
       
  1432         self.InstancesGrid.SetTable(self.InstancesTable)
       
  1433         self.InstancesGrid.SetRowLabelSize(0)
       
  1434         self.InstancesTable.ResetView(self.InstancesGrid)
       
  1435 
       
  1436     def RefreshTypeList(self):
       
  1437         self.TypeList = ""
       
  1438         blocktypes = self.Controler.GetBlockResource()
       
  1439         for blocktype in blocktypes:
       
  1440             self.TypeList += ",%s"%blocktype
       
  1441 
       
  1442     def RefreshTaskList(self):
       
  1443         self.TaskList = ""
       
  1444         for row in xrange(self.TasksTable.GetNumberRows()):
       
  1445             self.TaskList += ",%s"%self.TasksTable.GetValueByName(row, "Name")
       
  1446 
       
  1447     def RefreshVariableList(self):
       
  1448         self.VariableList = ""
       
  1449         for variable in self.Controler.GetCurrentResourceEditingVariables():
       
  1450             self.VariableList += ",%s"%variable
       
  1451         
       
  1452     def RefreshModel(self):
       
  1453         self.Controler.SetCurrentResourceEditingInfos(self.TasksTable.GetData(), self.InstancesTable.GetData())
       
  1454 
       
  1455     def RefreshView(self):
       
  1456         tasks, instances = self.Controler.GetCurrentResourceEditingInfos()
       
  1457         self.TasksTable.SetData(tasks)
       
  1458         self.InstancesTable.SetData(instances)
       
  1459         self.RefreshTypeList()
       
  1460         self.RefreshTaskList()
       
  1461         self.RefreshVariableList()
       
  1462         self.InstancesTable.ResetView(self.InstancesGrid)
       
  1463         self.TasksTable.ResetView(self.TasksGrid)
       
  1464 
       
  1465     def OnAddTaskButton(self, event):
       
  1466         self.TasksTable.AppendRow(self.TasksDefaultValue.copy())
       
  1467         self.RefreshModel()
       
  1468         self.RefreshView()
       
  1469         event.Skip()
       
  1470 
       
  1471     def OnDeleteTaskButton(self, event):
       
  1472         row = self.TasksGrid.GetGridCursorRow()
       
  1473         self.TasksTable.RemoveRow(row)
       
  1474         self.RefreshModel()
       
  1475         self.RefreshView()
       
  1476         event.Skip()
       
  1477 
       
  1478     def OnUpTaskButton(self, event):
       
  1479         row = self.TasksGrid.GetGridCursorRow()
       
  1480         self.TasksTable.MoveRow(row, -1, self.TasksGrid)
       
  1481         self.RefreshModel()
       
  1482         self.RefreshView()
       
  1483         event.Skip()
       
  1484 
       
  1485     def OnDownTaskButton(self, event):
       
  1486         row = self.TasksGrid.GetGridCursorRow()
       
  1487         self.TasksTable.MoveRow(row, 1, self.TasksGrid)
       
  1488         self.RefreshModel()
       
  1489         self.RefreshView()
       
  1490         event.Skip()
       
  1491 
       
  1492     def OnAddInstanceButton(self, event):
       
  1493         self.InstancesTable.AppendRow(self.InstancesDefaultValue.copy())
       
  1494         self.RefreshModel()
       
  1495         self.RefreshView()
       
  1496         event.Skip()
       
  1497 
       
  1498     def OnDeleteInstanceButton(self, event):
       
  1499         row = self.InstancesGrid.GetGridCursorRow()
       
  1500         self.InstancesTable.RemoveRow(row)
       
  1501         self.RefreshModel()
       
  1502         self.RefreshView()
       
  1503         event.Skip()
       
  1504 
       
  1505     def OnUpInstanceButton(self, event):
       
  1506         row = self.InstancesGrid.GetGridCursorRow()
       
  1507         self.InstancesTable.MoveRow(row, -1, self.InstancesGrid)
       
  1508         self.RefreshModel()
       
  1509         self.RefreshView()
       
  1510         event.Skip()
       
  1511 
       
  1512     def OnDownInstanceButton(self, event):
       
  1513         row = self.InstancesGrid.GetGridCursorRow()
       
  1514         self.InstancesTable.MoveRow(row, 1, self.InstancesGrid)
       
  1515         self.RefreshModel()
       
  1516         self.RefreshView()
       
  1517         event.Skip()
       
  1518 
       
  1519     def OnTasksGridCellChange(self, event):
       
  1520         row, col = event.GetRow(), event.GetCol()
       
  1521         if self.TasksTable.GetColLabelValue(event.GetCol()) == "Name":
       
  1522             tasklist = self.TaskList.split(",")
       
  1523             for i in xrange(self.TasksTable.GetNumberRows()):
       
  1524                 task = self.TasksTable.GetValueByName(i, "Name")
       
  1525                 if task in tasklist:
       
  1526                     tasklist.remove(task)
       
  1527             tasklist.remove("")
       
  1528             if len(tasklist) > 0:
       
  1529                 old_name = tasklist[0]
       
  1530                 new_name = self.TasksTable.GetValue(row, col)
       
  1531                 for i in xrange(self.InstancesTable.GetNumberRows()):
       
  1532                     if self.InstancesTable.GetValueByName(i, "Task") == old_name:
       
  1533                         self.InstancesTable.SetValueByName(i, "Task", new_name)
       
  1534         self.RefreshModel()
       
  1535         self.RefreshView()
       
  1536         event.Skip()
       
  1537 
       
  1538     def OnInstancesGridCellChange(self, event):
       
  1539         self.RefreshModel()
       
  1540         self.RefreshView()
       
  1541         event.Skip()