diff -r 000000000000 -r b622defdfd98 Viewer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Viewer.py Wed Jan 31 16:31:39 2007 +0100 @@ -0,0 +1,1541 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor +#based on the plcopen standard. +# +#Copyright (C): Edouard TISSERANT and Laurent BESSARD +# +#See COPYING file for copyrights details. +# +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +# +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#Lesser General Public License for more details. +# +#You should have received a copy of the GNU Lesser General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from wxPython.wx import * +from wxPython.stc import * +from wxPython.grid import * +import wx + +from plcopen.structures import * +from graphics.GraphicCommons import * +from graphics.SFC_Objects import * +from graphics.FBD_Objects import * +from graphics.LD_Objects import * + +import re + +#------------------------------------------------------------------------------- +# Graphic elements Viewer base class +#------------------------------------------------------------------------------- + +# ID Constants for menu items +[wxID_FBDVIEWERCONTEXTUALMENUITEMS0, wxID_FBDVIEWERCONTEXTUALMENUITEMS1, + wxID_FBDVIEWERCONTEXTUALMENUITEMS2, wxID_FBDVIEWERCONTEXTUALMENUITEMS3, + wxID_FBDVIEWERCONTEXTUALMENUITEMS5, wxID_FBDVIEWERCONTEXTUALMENUITEMS6, + wxID_FBDVIEWERCONTEXTUALMENUITEMS8, wxID_FBDVIEWERCONTEXTUALMENUITEMS9, + wxID_FBDVIEWERCONTEXTUALMENUITEMS11, +] = [wx.NewId() for _init_coll_ContextualMenu_Items in range(9)] + + +""" +Class that implements a Viewer based on a wxScrolledWindow for drawing and +manipulating graphic elements +""" + +class Viewer(wx.ScrolledWindow): + + # Create Contextual Menu items + def _init_coll_ContextualMenu_Items(self, parent): + # Create menu items + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS0, + kind=wx.ITEM_RADIO, text=u'No Modifier') + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS1, + kind=wx.ITEM_RADIO, text=u'Negated') + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS2, + kind=wx.ITEM_RADIO, text=u'Rising Edge') + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS3, + kind=wx.ITEM_RADIO, text=u'Falling Edge') + parent.AppendSeparator() + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS5, + kind=wx.ITEM_NORMAL, text=u'Add Wire Segment') + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS6, + kind=wx.ITEM_NORMAL, text=u'Delete Wire Segment') + parent.AppendSeparator() + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS8, + kind=wx.ITEM_NORMAL, text=u'Add Divergence Branch') + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS9, + kind=wx.ITEM_NORMAL, text=u'Delete Divergence Branch') + parent.AppendSeparator() + parent.Append(help='', id=wxID_FBDVIEWERCONTEXTUALMENUITEMS11, + kind=wx.ITEM_NORMAL, text=u'Delete') + # Link menu event to corresponding called functions + self.Bind(wx.EVT_MENU, self.OnNoModifierMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS0) + self.Bind(wx.EVT_MENU, self.OnNegatedMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS1) + self.Bind(wx.EVT_MENU, self.OnRisingEdgeMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS2) + self.Bind(wx.EVT_MENU, self.OnFallingEdgeMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS3) + self.Bind(wx.EVT_MENU, self.OnAddSegmentMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS5) + self.Bind(wx.EVT_MENU, self.OnDeleteSegmentMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS6) + self.Bind(wx.EVT_MENU, self.OnAddBranchMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS8) + self.Bind(wx.EVT_MENU, self.OnDeleteBranchMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS9) + self.Bind(wx.EVT_MENU, self.OnDeleteMenu, + id=wxID_FBDVIEWERCONTEXTUALMENUITEMS11) + + # Create and initialize Contextual Menu + def _init_menus(self): + self.ContextualMenu = wx.Menu(title='') + + self._init_coll_ContextualMenu_Items(self.ContextualMenu) + + # Create a new Viewer + def __init__(self, parent, window, controler): + wx.ScrolledWindow.__init__(self, parent, style=wx.SUNKEN_BORDER) + self._init_menus() + # Adding a rubberband to Viewer + self.rubberBand = RubberBand(drawingSurface=self) + self.SetBackgroundColour(wxColour(255,255,255)) + self.ResetView() + self.Scaling = None + #self.Scaling = (8, 8) + self.DrawGrid = True + self.current_id = 0 + + # Initialize Viewer mode to Selection mode + self.Mode = MODE_SELECTION + + self.Parent = window + self.Controler = controler + + # Link Viewer event to corresponding methods + EVT_PAINT(self, self.OnPaint) + EVT_LEFT_DOWN(self, self.OnViewerLeftDown) + EVT_LEFT_UP(self, self.OnViewerLeftUp) + EVT_LEFT_DCLICK(self, self.OnViewerLeftDClick) + EVT_RIGHT_UP(self, self.OnViewerRightUp) + EVT_MOTION(self, self.OnViewerMotion) + EVT_CHAR(self, self.OnChar) + + # Returns a new id + def GetNewId(self): + self.current_id += 1 + return self.current_id + + # Destructor + def __del__(self): + self.ResetView() + +#------------------------------------------------------------------------------- +# Reset functions +#------------------------------------------------------------------------------- + + # Resets Viewer lists + def ResetView(self): + self.Blocks = [] + self.Wires = [] + self.Elements = [] + self.SelectedElement = None + + # Changes Viewer mode + def SetMode(self, mode): + self.Mode = mode + # Reset selection + if self.SelectedElement: + self.SelectedElement.SetSelected(False) + self.SelectedElement = None + self.Refresh() + +#------------------------------------------------------------------------------- +# Refresh functions +#------------------------------------------------------------------------------- + + # Refresh Viewer elements + def RefreshView(self): + self.current_id = 0 + # Start by reseting Viewer + self.ResetView() + instance = True + # List of ids of already loaded blocks + ids = [] + # Load Blocks until they are all loaded + while instance: + instance = self.Controler.GetCurrentElementEditingInstanceInfos(exclude=ids) + if instance: + self.loadInstance(instance, ids) + self.Refresh() + + # Load instance from given informations + def loadInstance(self, instance, ids): + ids.append(instance["id"]) + self.current_id = max(self.current_id, instance["id"]) + if instance["type"] == "input": + variable = FBD_Variable(self, INPUT, instance["name"], instance["value_type"], instance["id"]) + variable.SetPosition(instance["x"], instance["y"]) + variable.SetSize(instance["width"], instance["height"]) + self.Blocks.append(variable) + self.Elements.append(variable) + connectors = variable.GetConnectors() + connectors["output"].SetPosition(wxPoint(*instance["connector"]["position"])) + if instance["connector"]["negated"]: + connectors["output"].SetNegated(True) + if instance["connector"]["edge"]: + connectors["output"].SetEdge(instance["connector"]["edge"]) + elif instance["type"] == "output": + variable = FBD_Variable(self, OUTPUT, instance["name"], instance["value_type"], instance["id"]) + variable.SetPosition(instance["x"], instance["y"]) + variable.SetSize(instance["width"], instance["height"]) + self.Blocks.append(variable) + self.Elements.append(variable) + connectors = variable.GetConnectors() + connectors["input"].SetPosition(wxPoint(*instance["connector"]["position"])) + if instance["connector"]["negated"]: + connectors["input"].SetNegated(True) + if instance["connector"]["edge"]: + connectors["input"].SetEdge(instance["connector"]["edge"]) + self.CreateWires(connectors["input"], instance["connector"]["links"], ids) + elif instance["type"] == "inout": + variable = FBD_Variable(self, INOUT, instance["name"], instance["value_type"], instance["id"]) + variable.SetPosition(instance["x"], instance["y"]) + variable.SetSize(instance["width"], instance["height"]) + self.Blocks.append(variable) + self.Elements.append(variable) + connectors = variable.GetConnectors() + connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"])) + connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"])) + if instance["connectors"]["output"]["negated"]: + connectors["output"].SetNegated(True) + if instance["connectors"]["output"]["edge"]: + connectors["output"].SetEdge(instance["connectors"]["output"]["edge"]) + if instance["connectors"]["input"]["negated"]: + connectors["input"].SetNegated(True) + if instance["connectors"]["input"]["edge"]: + connectors["input"].SetEdge(instance["connectors"]["input"]["edge"]) + self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids) + elif instance["type"] == "continuation": + connection = FBD_Connector(self, CONTINUATION, instance["name"], instance["id"]) + connection.SetPosition(instance["x"], instance["y"]) + connection.SetSize(instance["width"], instance["height"]) + self.Blocks.append(connection) + self.Elements.append(connection) + connector = connection.GetConnector() + connector.SetPosition(wxPoint(*instance["connector"]["position"])) + elif instance["type"] == "connection": + connection = FBD_Connection(self, CONNECTOR, instance["name"], instance["id"]) + connection.SetPosition(instance["x"], instance["y"]) + connection.SetSize(instance["width"], instance["height"]) + self.Blocks.append(connection) + self.Elements.append(connection) + connector = connection.GetConnector() + connector.SetPosition(wxPoint(*instance["connector"]["position"])) + self.CreateWires(connector, instance["connector"]["links"], ids) + elif instance["type"] == "comment": + comment = Comment(self, instance["content"], instance["id"]) + comment.SetPosition(instance["x"], instance["y"]) + comment.SetSize(instance["width"], instance["height"]) + self.Elements.append(comment) + elif instance["type"] == "leftPowerRail": + leftpowerrail = LD_PowerRail(self, LEFTRAIL, instance["id"], [True for i in range(len(instance["connectors"]))]) + leftpowerrail.SetPosition(instance["x"], instance["y"]) + self.Blocks.append(leftpowerrail) + self.Elements.append(leftpowerrail) + connectors = leftpowerrail.GetConnectors() + for i, connector in enumerate(instance["connectors"]): + connectors[i].SetPosition(wxPoint(*connector["position"])) + elif instance["type"] == "rightPowerRail": + rightpowerrail = LD_PowerRail(self, RIGHTRAIL, instance["id"], [True for i in range(len(instance["connectors"]))]) + rightpowerrail.SetPosition(instance["x"], instance["y"]) + self.Blocks.append(rightpowerrail) + self.Elements.append(rightpowerrail) + connectors = rightpowerrail.GetConnectors() + for i, connector in enumerate(instance["connectors"]): + connectors[i].SetPosition(wxPoint(*connector["position"])) + self.CreateWires(connectors[i], connector["links"], ids) + elif instance["type"] == "contact": + if instance["negated"]: + negated = instance["negated"] + else: + negated = False + if instance["edge"]: + edge = instance["edge"] + else: + edge = "none" + if negated and edge == "none": + contact_type = CONTACT_REVERSE + elif not negated and edge == "rising": + contact_type = CONTACT_RISING + elif not negated and edge == "falling": + contact_type = CONTACT_FALLING + else: + contact_type = CONTACT_NORMAL + contact = LD_Contact(self, contact_type, instance["name"], instance["id"]) + contact.SetPosition(instance["x"], instance["y"]) + self.Blocks.append(contact) + self.Elements.append(contact) + connectors = contact.GetConnectors() + connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"])) + self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids) + connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"])) + elif instance["type"] == "coil": + if instance["negated"]: + negated = instance["negated"] + else: + negated = False + if instance["storage"]: + storage = instance["storage"] + else: + storage = "none" + if negated and storage == "none": + coil_type = COIL_REVERSE + elif not negated and storage == "set": + coil_type = COIL_SET + elif not negated and storage == "reset": + coil_type = COIL_RESET + else: + coil_type = COIL_NORMAL + coil = LD_Coil(self, coil_type, instance["name"], instance["id"]) + coil.SetPosition(instance["x"], instance["y"]) + self.Blocks.append(coil) + self.Elements.append(coil) + connectors = coil.GetConnectors() + connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"])) + self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids) + connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"])) + elif instance["type"] == "step": + if instance["initial"]: + initial = instance["initial"] + else: + initial = False + step = SFC_Step(self, instance["name"], initial, instance["id"]) + step.SetPosition(instance["x"], instance["y"]) + step.SetSize(instance["width"], instance["height"]) + self.Blocks.append(step) + self.Elements.append(step) + if "output" in instance["connectors"]: + step.AddOutput() + if "action" in instance["connectors"]: + step.AddAction() + connectors = step.GetConnectors() + if connectors["input"]: + connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"])) + self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids) + if connectors["output"]: + connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"])) + if connectors["action"]: + connectors["action"].SetPosition(wxPoint(*instance["connectors"]["action"]["position"])) + elif instance["type"] == "transition": + transition = SFC_Transition(self, instance["condition_type"], instance["condition"], instance["id"]) + transition.SetPosition(instance["x"], instance["y"]) + self.Blocks.append(transition) + self.Elements.append(transition) + connectors = transition.GetConnectors() + connectors["input"].SetPosition(wxPoint(*instance["connectors"]["input"]["position"])) + self.CreateWires(connectors["input"], instance["connectors"]["input"]["links"], ids) + connectors["output"].SetPosition(wxPoint(*instance["connectors"]["output"]["position"])) + elif instance["type"] in ["selectionDivergence", "selectionConvergence", "simultaneousDivergence", "simultaneousConvergence"]: + if instance["type"] == "selectionDivergence": + divergence = SFC_Divergence(self, SELECTION_DIVERGENCE, + len(instance["connectors"]["outputs"]), instance["id"]) + elif instance["type"] == "selectionConvergence": + divergence = SFC_Divergence(self, SELECTION_CONVERGENCE, + len(instance["connectors"]["inputs"]), instance["id"]) + elif instance["type"] == "simultaneousDivergence": + divergence = SFC_Divergence(self, SIMULTANEOUS_DIVERGENCE, + len(instance["connectors"]["outputs"]), instance["id"]) + else: + divergence = SFC_Divergence(self, SIMULTANEOUS_CONVERGENCE, + len(instance["connectors"]["inputs"]), instance["id"]) + divergence.SetPosition(instance["x"], instance["y"]) + divergence.SetSize(instance["width"], instance["height"]) + self.Blocks.append(divergence) + self.Elements.append(divergence) + connectors = divergence.GetConnectors() + for i, input_connector in enumerate(instance["connectors"]["inputs"]): + connector = connectors["inputs"][i] + connector.SetPosition(wxPoint(*input_connector["position"])) + self.CreateWires(connector, input_connector["links"], ids) + for i, output_connector in enumerate(instance["connectors"]["outputs"]): + connector = connectors["outputs"][i] + connector.SetPosition(wxPoint(*output_connector["position"])) + elif instance["type"] == "jump": + jump = SFC_Jump(self, instance["target"], instance["id"]) + jump.SetPosition(instance["x"], instance["y"]) + self.Blocks.append(jump) + self.Elements.append(jump) + connector = jump.GetConnector() + connector.SetPosition(wxPoint(*instance["connector"]["position"])) + self.CreateWires(connector, instance["connector"]["links"], ids) + elif instance["type"] == "actionBlock": + actionBlock = SFC_ActionBlock(self, instance["actions"], instance["id"]) + actionBlock.SetPosition(instance["x"], instance["y"]) + actionBlock.SetSize(instance["width"], instance["height"]) + self.Blocks.append(actionBlock) + self.Elements.append(actionBlock) + connector = actionBlock.GetConnector() + connector.SetPosition(wxPoint(*instance["connector"]["position"])) + self.CreateWires(connector, instance["connector"]["links"], ids) + else: + if instance["name"] != None: + block = FBD_Block(self, instance["type"], instance["name"], instance["id"], len(instance["connectors"]["inputs"])) + else: + block = FBD_Block(self, instance["type"], "", instance["id"], len(instance["connectors"]["inputs"])) + block.SetPosition(instance["x"], instance["y"]) + block.SetSize(instance["width"], instance["height"]) + self.Blocks.append(block) + self.Elements.append(block) + connectors = block.GetConnectors() + for i, input_connector in enumerate(instance["connectors"]["inputs"]): + connector = connectors["inputs"][i] + connector.SetPosition(wxPoint(*input_connector["position"])) + if input_connector["negated"]: + connector.SetNegated(True) + if input_connector["edge"]: + connector.SetEdge(input_connector["edge"]) + self.CreateWires(connector, input_connector["links"], ids) + for i, output_connector in enumerate(instance["connectors"]["outputs"]): + connector = connectors["outputs"][i] + if output_connector["negated"]: + connector.SetNegated(True) + if output_connector["edge"]: + connector.SetEdge(output_connector["edge"]) + connector.SetPosition(wxPoint(*output_connector["position"])) + + def CreateWires(self, start_connector, links, ids): + for link in links: + refLocalId = link["refLocalId"] + if refLocalId != None: + if refLocalId not in ids: + new_instance = self.Controler.GetCurrentElementEditingInstanceInfos(refLocalId) + if new_instance: + self.loadInstance(new_instance, ids) + connected = self.FindElementById(refLocalId) + if connected: + points = link["points"] + end_connector = connected.GetConnector(wxPoint(points[-1][0], points[-1][1])) + if end_connector: + wire = Wire(self) + wire.SetPoints(points) + start_connector.Connect((wire, 0), False) + end_connector.Connect((wire, -1), False) + wire.ConnectStartPoint(None, start_connector) + wire.ConnectEndPoint(None, end_connector) + self.Wires.append(wire) + self.Elements.append(wire) + +#------------------------------------------------------------------------------- +# Search Element functions +#------------------------------------------------------------------------------- + + def FindBlock(self, pos): + for block in self.Blocks: + if block.HitTest(pos) or block.TestHandle(pos) != (0, 0): + return block + return None + + def FindWire(self, pos): + for wire in self.Wires: + if wire.HitTest(pos) or wire.TestHandle(pos) != (0, 0): + return wire + return None + + def FindElement(self, pos, exclude_group = False): + if self.SelectedElement and not (exclude_group and isinstance(self.SelectedElement, Graphic_Group)): + if self.SelectedElement.HitTest(pos) or self.SelectedElement.TestHandle(pos) != (0, 0): + return self.SelectedElement + for element in self.Elements: + if element.HitTest(pos) or element.TestHandle(pos) != (0, 0): + return element + return None + + def FindBlockConnector(self, pos): + for block in self.Blocks: + result = block.TestConnector(pos) + if result: + return result + return None + + def FindElementById(self, id): + for element in self.Elements: + if element.GetId() == id: + return element + return None + + def SearchElements(self, bbox): + elements = [] + for element in self.Elements: + element_bbox = element.GetBoundingBox() + 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: + elements.append(element) + return elements + +#------------------------------------------------------------------------------- +# Popup menu functions +#------------------------------------------------------------------------------- + + def PopupBlockMenu(self, connector = None): + self.ContextualMenu.FindItemByPosition(0).Enable(connector != None) + self.ContextualMenu.FindItemByPosition(1).Enable(connector != None) + self.ContextualMenu.FindItemByPosition(2).Enable(connector != None) + self.ContextualMenu.FindItemByPosition(3).Enable(connector != None) + self.ContextualMenu.FindItemByPosition(5).Enable(False) + self.ContextualMenu.FindItemByPosition(6).Enable(False) + self.ContextualMenu.FindItemByPosition(8).Enable(False) + self.ContextualMenu.FindItemByPosition(9).Enable(False) + if connector: + if connector.IsNegated(): + self.ContextualMenu.FindItemByPosition(1).Check(True) + elif connector.GetEdge() == "rising": + self.ContextualMenu.FindItemByPosition(2).Check(True) + elif connector.GetEdge() == "falling": + self.ContextualMenu.FindItemByPosition(3).Check(True) + else: + self.ContextualMenu.FindItemByPosition(0).Check(True) + self.PopupMenu(self.ContextualMenu) + + def PopupVariableMenu(self, connector = None): + self.ContextualMenu.FindItemByPosition(0).Enable(connector != None) + self.ContextualMenu.FindItemByPosition(1).Enable(connector != None) + self.ContextualMenu.FindItemByPosition(2).Enable(False) + self.ContextualMenu.FindItemByPosition(3).Enable(False) + self.ContextualMenu.FindItemByPosition(5).Enable(False) + self.ContextualMenu.FindItemByPosition(6).Enable(False) + self.ContextualMenu.FindItemByPosition(8).Enable(False) + self.ContextualMenu.FindItemByPosition(9).Enable(False) + if connector: + if connector.IsNegated(): + self.ContextualMenu.FindItemByPosition(1).Check(True) + else: + self.ContextualMenu.FindItemByPosition(0).Check(True) + self.PopupMenu(self.ContextualMenu) + + def PopupWireMenu(self): + self.ContextualMenu.FindItemByPosition(0).Enable(False) + self.ContextualMenu.FindItemByPosition(1).Enable(False) + self.ContextualMenu.FindItemByPosition(2).Enable(False) + self.ContextualMenu.FindItemByPosition(3).Enable(False) + self.ContextualMenu.FindItemByPosition(5).Enable(True) + self.ContextualMenu.FindItemByPosition(6).Enable(True) + self.ContextualMenu.FindItemByPosition(8).Enable(False) + self.ContextualMenu.FindItemByPosition(9).Enable(False) + self.PopupMenu(self.ContextualMenu) + + def PopupDivergenceMenu(self, connector): + self.ContextualMenu.FindItemByPosition(0).Enable(False) + self.ContextualMenu.FindItemByPosition(1).Enable(False) + self.ContextualMenu.FindItemByPosition(2).Enable(False) + self.ContextualMenu.FindItemByPosition(3).Enable(False) + self.ContextualMenu.FindItemByPosition(5).Enable(False) + self.ContextualMenu.FindItemByPosition(6).Enable(False) + self.ContextualMenu.FindItemByPosition(8).Enable(True) + self.ContextualMenu.FindItemByPosition(9).Enable(connector) + self.PopupMenu(self.ContextualMenu) + + def PopupDefaultMenu(self): + self.ContextualMenu.FindItemByPosition(0).Enable(False) + self.ContextualMenu.FindItemByPosition(1).Enable(False) + self.ContextualMenu.FindItemByPosition(2).Enable(False) + self.ContextualMenu.FindItemByPosition(3).Enable(False) + self.ContextualMenu.FindItemByPosition(5).Enable(False) + self.ContextualMenu.FindItemByPosition(6).Enable(False) + self.ContextualMenu.FindItemByPosition(8).Enable(False) + self.ContextualMenu.FindItemByPosition(9).Enable(False) + self.PopupMenu(self.ContextualMenu) + + def EditCommentContent(self, comment): + dialog = wxTextEntryDialog(self.Parent, "Edit comment", "Please enter comment text", comment.GetContent(), wxOK|wxCANCEL|wxTE_MULTILINE) + if dialog.ShowModal() == wxID_OK: + value = dialog.GetValue() + comment.SetContent(value) + infos = {"content" : value} + infos["width"], infos["height"] = comment.GetSize() + self.Controler.SetCurrentElementEditingCommentInfos(comment.GetId(), infos) + self.Refresh() + dialog.Destroy() + +#------------------------------------------------------------------------------- +# Menu items functions +#------------------------------------------------------------------------------- + + def OnNoModifierMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Blocks: + self.SelectedElement.SetConnectorNegated(False) + event.Skip() + + def OnNegatedMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Blocks: + self.SelectedElement.SetConnectorNegated(True) + event.Skip() + + def OnRisingEdgeMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Blocks: + self.SelectedElement.SetConnectorEdge("rising") + event.Skip() + + def OnFallingEdgeMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Blocks: + self.SelectedElement.SetConnectorEdge("falling") + event.Skip() + + def OnAddSegmentMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Wires: + self.SelectedElement.AddSegment() + event.Skip() + + def OnDeleteSegmentMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Wires: + self.SelectedElement.DeleteSegment() + event.Skip() + + def OnAddBranchMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Blocks: + self.AddDivergenceBranch(self.SelectedElement) + event.Skip() + + def OnDeleteBranchMenu(self, event): + if self.SelectedElement and self.SelectedElement in self.Blocks: + self.RemoveDivergenceBranch(self.SelectedElement) + event.Skip() + + def OnDeleteMenu(self, event): + if self.SelectedElement: + self.SelectedElement.Delete() + self.SelectedElement = None + event.Skip() + +#------------------------------------------------------------------------------- +# Mouse event functions +#------------------------------------------------------------------------------- + + def OnViewerLeftDown(self, event): + event.Skip() + + def OnViewerLeftUp(self, event): + event.Skip() + + def OnViewerRightUp(self, event): + event.Skip() + + def OnViewerLeftDClick(self, event): + event.Skip() + + def OnViewerMotion(self, event): + event.Skip() + +#------------------------------------------------------------------------------- +# Keyboard event functions +#------------------------------------------------------------------------------- + + def OnChar(self, event): + event.Skip() + +#------------------------------------------------------------------------------- +# Model update functions +#------------------------------------------------------------------------------- + + def RefreshBlockModel(self, block): + blockid = block.GetId() + infos = {} + infos["type"] = block.GetType() + infos["name"] = block.GetName() + infos["x"], infos["y"] = block.GetPosition() + infos["width"], infos["height"] = block.GetSize() + infos["connectors"] = block.GetConnectors() + self.Controler.SetCurrentElementEditingBlockInfos(blockid, infos) + + def RefreshVariableModel(self, variable): + variableid = variable.GetId() + infos = {} + infos["name"] = variable.GetName() + infos["x"], infos["y"] = variable.GetPosition() + infos["width"], infos["height"] = variable.GetSize() + infos["connectors"] = variable.GetConnectors() + self.Controler.SetCurrentElementEditingVariableInfos(variableid, infos) + + def RefreshConnectionModel(self, connection): + connectionid = connection.GetId() + infos = {} + infos["name"] = connection.GetName() + infos["x"], infos["y"] = connection.GetPosition() + infos["width"], infos["height"] = connection.GetSize() + infos["connector"] = connection.GetConnector() + self.Controler.SetCurrentElementEditingConnectionInfos(connectionid, infos) + + def RefreshCommentModel(self, comment): + commentid = comment.GetId() + infos = {} + infos["content"] = comment.GetContent() + infos["x"], infos["y"] = comment.GetPosition() + infos["width"], infos["height"] = comment.GetSize() + self.Controler.SetCurrentElementEditingCommentInfos(commentid, infos) + + def RefreshPowerRailModel(self, powerrail): + powerrailid = powerrail.GetId() + infos = {} + infos["x"], infos["y"] = powerrail.GetPosition() + infos["width"], infos["height"] = powerrail.GetSize() + infos["connectors"] = powerrail.GetConnectors() + self.Controler.SetCurrentElementEditingPowerRailInfos(powerrailid, infos) + + def RefreshContactModel(self, contact): + contactid = contact.GetId() + infos = {} + infos["name"] = contact.GetName() + infos["type"] = contact.GetType() + infos["x"], infos["y"] = contact.GetPosition() + infos["width"], infos["height"] = contact.GetSize() + infos["connectors"] = contact.GetConnectors() + self.Controler.SetCurrentElementEditingContactInfos(contactid, infos) + + def RefreshCoilModel(self, coil): + coilid = coil.GetId() + infos = {} + infos["name"] = coil.GetName() + infos["type"] = coil.GetType() + infos["x"], infos["y"] = coil.GetPosition() + infos["width"], infos["height"] = coil.GetSize() + infos["connectors"] = coil.GetConnectors() + self.Controler.SetCurrentElementEditingCoilInfos(coilid, infos) + + def RefreshStepModel(self, step): + stepid = step.GetId() + infos = {} + infos["name"] = step.GetName() + infos["initial"] = step.GetInitial() + infos["x"], infos["y"] = step.GetPosition() + infos["width"], infos["height"] = step.GetSize() + infos["connectors"] = step.GetConnectors() + self.Controler.SetCurrentElementEditingStepInfos(stepid, infos) + + def RefreshTransitionModel(self, transition): + transitionid = transition.GetId() + infos = {} + infos["type"] = transition.GetType() + infos["condition"] = transition.GetCondition() + infos["x"], infos["y"] = transition.GetPosition() + infos["width"], infos["height"] = transition.GetSize() + infos["connectors"] = transition.GetConnectors() + self.Controler.SetCurrentElementEditingTransitionInfos(transitionid, infos) + + def RefreshDivergenceModel(self, divergence): + divergenceid = divergence.GetId() + infos = {} + infos["x"], infos["y"] = divergence.GetPosition() + infos["width"], infos["height"] = divergence.GetSize() + infos["connectors"] = divergence.GetConnectors() + self.Controler.SetCurrentElementEditingDivergenceInfos(divergenceid, infos) + + def RefreshJumpModel(self, jump): + jumpid = jump.GetId() + infos = {} + infos["target"] = jump.GetTarget() + infos["x"], infos["y"] = jump.GetPosition() + infos["width"], infos["height"] = jump.GetSize() + infos["connector"] = jump.GetConnector() + self.Controler.SetCurrentElementEditingJumpInfos(jumpid, infos) + + def RefreshActionBlockModel(self, actionblock): + actionblockid = actionblock.GetId() + infos = {} + infos["actions"] = actionblock.GetActions() + infos["x"], infos["y"] = actionblock.GetPosition() + infos["width"], infos["height"] = actionblock.GetSize() + infos["connector"] = actionblock.GetConnector() + self.Controler.SetCurrentElementEditingActionBlockInfos(actionblockid, infos) + +#------------------------------------------------------------------------------- +# Editing functions +#------------------------------------------------------------------------------- + + def Cut(self): + pass + + def Copy(self): + pass + + def Paste(self): + pass + +#------------------------------------------------------------------------------- +# Drawing functions +#------------------------------------------------------------------------------- + + def OnPaint(self, event): + dc = wxClientDC(self) + dc.Clear() + dc.SetPen(wxPen(wxColour(230, 230, 230))) + if self.Scaling and self.DrawGrid: + width, height = dc.GetSize() + for i in xrange(1, width / self.Scaling[0] + 1): + dc.DrawLine(i * self.Scaling[0], 0, i * self.Scaling[0], height) + for i in xrange(1, height / self.Scaling[1] + 1): + dc.DrawLine(0, i * self.Scaling[1], width, i * self.Scaling[1]) + for wire in self.Wires: + if wire != self.SelectedElement: + wire.Draw(dc) + for element in self.Elements: + if element not in self.Wires and element != self.SelectedElement: + element.Draw(dc) + if self.SelectedElement: + self.SelectedElement.Draw(dc) + event.Skip() + + +#------------------------------------------------------------------------------- +# Textual programs Viewer class +#------------------------------------------------------------------------------- + + +NEWLINE = "\n" +NUMBERS = [str(i) for i in xrange(10)] +LETTERS = ['_'] +for i in xrange(26): + LETTERS.append(chr(ord('a') + i)) + LETTERS.append(chr(ord('A') + i)) + +[wxSTC_PLC_WORD, wxSTC_PLC_COMMENT, wxSTC_PLC_NUMBER, wxSTC_PLC_VARIABLE, + wxSTC_PLC_FUNCTION, wxSTC_PLC_JUMP] = range(6) +[SPACE, WORD, NUMBER, COMMENT] = range(4) + +[wxID_TEXTVIEWER, +] = [wx.NewId() for _init_ctrls in range(1)] + +if wx.Platform == '__WXMSW__': + faces = { 'times': 'Times New Roman', + 'mono' : 'Courier New', + 'helv' : 'Arial', + 'other': 'Comic Sans MS', + 'size' : 10, + } +else: + faces = { 'times': 'Times', + 'mono' : 'Courier', + 'helv' : 'Helvetica', + 'other': 'new century schoolbook', + 'size' : 12, + } +re_texts = {} +re_texts["letter"] = "[A-Za-z]" +re_texts["digit"] = "[0-9]" +re_texts["identifier"] = "((?:%(letter)s|(?:_(?:%(letter)s|%(digit)s)))(?:_?(?:%(letter)s|%(digit)s))*)"%re_texts +IDENTIFIER_MODEL = re.compile(re_texts["identifier"]) +LABEL_MODEL = re.compile("[ \t\n]%(identifier)s:[ \t\n]"%re_texts) + +class TextViewer(wxStyledTextCtrl): + + def __init__(self, parent, window, controler): + wxStyledTextCtrl.__init__(self, parent, wxID_TEXTVIEWER, style=0) + + self.CmdKeyAssign(ord('+'), wxSTC_SCMOD_CTRL, wxSTC_CMD_ZOOMIN) + self.CmdKeyAssign(ord('-'), wxSTC_SCMOD_CTRL, wxSTC_CMD_ZOOMOUT) + + self.SetViewWhiteSpace(False) + + self.SetLexer(wxSTC_LEX_CONTAINER) + + # Global default styles for all languages + self.StyleSetSpec(wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces) + self.StyleClearAll() # Reset all to be like the default + + self.StyleSetSpec(wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,size:%(size)d" % faces) + self.SetSelBackground(1, "#E0E0E0") + + # Highlighting styles + self.StyleSetSpec(wxSTC_PLC_WORD, "fore:#00007F,bold,size:%(size)d" % faces) + self.StyleSetSpec(wxSTC_PLC_VARIABLE, "fore:#7F0000,size:%(size)d" % faces) + self.StyleSetSpec(wxSTC_PLC_FUNCTION, "fore:#7F7F00,size:%(size)d" % faces) + self.StyleSetSpec(wxSTC_PLC_COMMENT, "fore:#7F7F7F,size:%(size)d" % faces) + self.StyleSetSpec(wxSTC_PLC_NUMBER, "fore:#007F7F,size:%(size)d" % faces) + self.StyleSetSpec(wxSTC_PLC_JUMP, "fore:#007F00,size:%(size)d" % faces) + + # Indicators styles + self.IndicatorSetStyle(0, wxSTC_INDIC_SQUIGGLE) + self.IndicatorSetForeground(0, wxRED) + + # Line numbers in the margin + self.SetMarginType(1, wxSTC_MARGIN_NUMBER) + self.SetMarginWidth(1, 50) + + # Indentation size + self.SetTabWidth(2) + + self.Keywords = [] + self.Variables = [] + self.Functions = [] + self.Jumps = [] + self.TextChanged = False + + self.Controler = controler + + EVT_KEY_DOWN(self, self.OnKeyDown) + EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded) + + def SetKeywords(self, keywords): + self.Keywords = [keyword.upper() for keyword in keywords] + self.Colourise(0, -1) + + def SetVariables(self, variables): + self.Variables = [variable.upper() for variable in variables] + self.Colourise(0, -1) + + def SetFunctions(self, blocktypes): + self.Functions = [] + for category in blocktypes: + for blocktype in category["list"]: + if blocktype["name"] not in self.Keywords and blocktype["name"] not in self.Variables: + self.Functions.append(blocktype["name"].upper()) + self.Colourise(0, -1) + + def RefreshJumpList(self): + self.Jumps = [jump.upper() for jump in LABEL_MODEL.findall(self.GetText())] + self.Colourise(0, -1) + + def RefreshView(self): + self.SetText(self.Controler.GetCurrentElementEditingText()) + self.RefreshJumpList() + + def OnStyleNeeded(self, event): + self.TextChanged = True + line = self.LineFromPosition(self.GetEndStyled()) + if line == 0: + start_pos = 0 + else: + start_pos = self.GetLineEndPosition(line - 1) + 1 + end_pos = event.GetPosition() + self.StartStyling(start_pos, 0xff) + + i = start_pos + state = SPACE + line = "" + word = "" + while i < end_pos: + char = chr(self.GetCharAt(i)).upper() + line += char + if char == NEWLINE: + if state == COMMENT: + self.SetStyling(i - start_pos + 1, wxSTC_PLC_COMMENT) + elif state == NUMBER: + self.SetStyling(i - start_pos, wxSTC_PLC_NUMBER) + elif state == WORD: + if word in self.Keywords: + self.SetStyling(i - start_pos, wxSTC_PLC_WORD) + elif word in self.Variables: + self.SetStyling(i - start_pos, wxSTC_PLC_VARIABLE) + elif word in self.Functions: + self.SetStyling(i - start_pos, wxSTC_PLC_FUNCTION) + elif word in self.Jumps: + self.SetStyling(i - start_pos, wxSTC_PLC_JUMP) + else: + self.SetStyling(i - start_pos, 31) + if self.GetCurrentPos() < start_pos or self.GetCurrentPos() > i: + self.StartStyling(start_pos, wxSTC_INDICS_MASK) + self.SetStyling(i - start_pos, wxSTC_INDIC0_MASK) + self.StartStyling(i, 0xff) + else: + self.SetStyling(i - start_pos, 31) + start_pos = i + state = SPACE + line = "" + elif line.endswith("(*") and state != COMMENT: + self.SetStyling(i - start_pos - 1, 31) + start_pos = i + state = COMMENT + elif state == COMMENT: + if line.endswith("*)"): + self.SetStyling(i - start_pos + 2, wxSTC_PLC_COMMENT) + start_pos = i + 1 + state = SPACE + elif char in LETTERS: + if state == NUMBER: + word = "#" + state = WORD + elif state == SPACE: + self.SetStyling(i - start_pos, 31) + word = char + start_pos = i + state = WORD + else: + word += char + elif char in NUMBERS or char == '.' and state != WORD: + if state == SPACE: + self.SetStyling(i - start_pos, 31) + start_pos = i + state = NUMBER + if state == WORD and char != '.': + word += char + else: + if state == WORD: + if word in self.Keywords: + self.SetStyling(i - start_pos, wxSTC_PLC_WORD) + elif word in self.Variables: + self.SetStyling(i - start_pos, wxSTC_PLC_VARIABLE) + elif word in self.Functions: + self.SetStyling(i - start_pos, wxSTC_PLC_FUNCTION) + elif word in self.Jumps: + self.SetStyling(i - start_pos, wxSTC_PLC_JUMP) + else: + self.SetStyling(i - start_pos, 31) + if self.GetCurrentPos() < start_pos or self.GetCurrentPos() > i: + self.StartStyling(start_pos, wxSTC_INDICS_MASK) + self.SetStyling(i - start_pos, wxSTC_INDIC0_MASK) + self.StartStyling(i, 0xff) + word = "" + start_pos = i + state = SPACE + elif state == NUMBER: + self.SetStyling(i - start_pos, wxSTC_PLC_NUMBER) + start_pos = i + state = SPACE + i += 1 + if state == COMMENT: + self.SetStyling(i - start_pos + 2, wxSTC_PLC_COMMENT) + elif state == NUMBER: + self.SetStyling(i - start_pos, wxSTC_PLC_NUMBER) + elif state == WORD: + if word in self.Keywords: + self.SetStyling(i - start_pos, wxSTC_PLC_WORD) + elif word in self.Variables: + self.SetStyling(i - start_pos, wxSTC_PLC_VARIABLE) + elif word in self.Functions: + self.SetStyling(i - start_pos, wxSTC_PLC_FUNCTION) + elif word in self.Jumps: + self.SetStyling(i - start_pos, wxSTC_PLC_JUMP) + else: + self.SetStyling(i - start_pos, 31) + else: + self.SetStyling(i - start_pos, 31) + event.Skip() + + def Cut(self): + self.CmdKeyExecute(wxSTC_CMD_CUT) + + def Copy(self): + self.CmdKeyExecute(wxSTC_CMD_COPY) + + def Paste(self): + self.CmdKeyExecute(wxSTC_CMD_PASTE) + + def RefreshModel(self): + if self.TextChanged: + self.RefreshJumpList() + self.Controler.SetCurrentElementEditingText(self.GetText()) + + def OnKeyDown(self, event): + if self.CallTipActive(): + self.CallTipCancel() + key = event.KeyCode() + + if key == WXK_SPACE and event.ControlDown(): + pos = self.GetCurrentPos() + + # Tips + if event.ShiftDown(): + self.CallTipSetBackground("yellow") + self.CallTipShow(pos, 'Here will be some help.') + + # Code completion + else: + kw = [key for key in self.Keywords] + + kw.sort() # Python sorts are case sensitive + self.AutoCompSetIgnoreCase(False) # so this needs to match + + self.AutoCompShow(0, " ".join(kw)) + else: + self.TextChanged = False + wxCallAfter(self.RefreshModel) + event.Skip() + + +#------------------------------------------------------------------------------- +# Resource Editor class +#------------------------------------------------------------------------------- + +class ResourceTable(wxPyGridTableBase): + + """ + A custom wxGrid Table using user supplied data + """ + def __init__(self, parent, data, colnames): + # The base class must be initialized *first* + wxPyGridTableBase.__init__(self) + self.data = data + self.colnames = colnames + self.Parent = parent + + self.ColAlignements = [] + self.ColSizes = [] + # XXX + # we need to store the row length and collength to + # see if the table has changed size + self._rows = self.GetNumberRows() + self._cols = self.GetNumberCols() + + def GetColAlignements(self): + return self.ColAlignements + + def SetColAlignements(self, list): + self.ColAlignements = list + + def GetColSizes(self): + return self.ColSizes + + def SetColSizes(self, list): + self.ColSizes = list + + def GetNumberCols(self): + return len(self.colnames) + + def GetNumberRows(self): + return len(self.data) + + def GetColLabelValue(self, col): + if col < len(self.colnames): + return self.colnames[col] + + def GetRowLabelValues(self, row): + return row + + def GetValue(self, row, col): + if row < self.GetNumberRows(): + name = str(self.data[row].get(self.GetColLabelValue(col), "")) + return name + + def GetValueByName(self, row, colname): + return self.data[row].get(colname) + + def SetValue(self, row, col, value): + if col < len(self.colnames): + self.data[row][self.GetColLabelValue(col)] = value + + def SetValueByName(self, row, colname, value): + if colname in self.colnames: + self.data[row][colname] = value + + def ResetView(self, grid): + """ + (wxGrid) -> Reset the grid view. Call this to + update the grid if rows and columns have been added or deleted + """ + grid.BeginBatch() + for current, new, delmsg, addmsg in [ + (self._rows, self.GetNumberRows(), wxGRIDTABLE_NOTIFY_ROWS_DELETED, wxGRIDTABLE_NOTIFY_ROWS_APPENDED), + (self._cols, self.GetNumberCols(), wxGRIDTABLE_NOTIFY_COLS_DELETED, wxGRIDTABLE_NOTIFY_COLS_APPENDED), + ]: + if new < current: + msg = wxGridTableMessage(self,delmsg,new,current-new) + grid.ProcessTableMessage(msg) + elif new > current: + msg = wxGridTableMessage(self,addmsg,new-current) + grid.ProcessTableMessage(msg) + self.UpdateValues(grid) + grid.EndBatch() + + self._rows = self.GetNumberRows() + self._cols = self.GetNumberCols() + # update the column rendering scheme + self._updateColAttrs(grid) + + # update the scrollbars and the displayed part of the grid + grid.AdjustScrollbars() + grid.ForceRefresh() + + def UpdateValues(self, grid): + """Update all displayed values""" + # This sends an event to the grid table to update all of the values + msg = wxGridTableMessage(self, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES) + grid.ProcessTableMessage(msg) + + def _updateColAttrs(self, grid): + """ + wxGrid -> update the column attributes to add the + appropriate renderer given the column name. + + Otherwise default to the default renderer. + """ + + for col in range(self.GetNumberCols()): + attr = wxGridCellAttr() + attr.SetAlignment(self.ColAlignements[col], wxALIGN_CENTRE) + grid.SetColAttr(col, attr) + grid.SetColSize(col, self.ColSizes[col]) + + for row in range(self.GetNumberRows()): + for col in range(self.GetNumberCols()): + editor = None + renderer = None + colname = self.GetColLabelValue(col) + grid.SetReadOnly(row, col, False) + if colname in ["Name","Interval"]: + editor = wxGridCellTextEditor() + renderer = wxGridCellStringRenderer() + if colname == "Interval" and self.GetValueByName(row, "Single") != "": + grid.SetReadOnly(row, col, True) + elif colname == "Single": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.VariableList) + if self.GetValueByName(row, "Interval") != "": + grid.SetReadOnly(row, col, True) + elif colname == "Type": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.TypeList) + elif colname == "Priority": + editor = wxGridCellNumberEditor() + editor.SetParameters("0,65535") + elif colname == "Task": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.TaskList) + + grid.SetCellEditor(row, col, editor) + grid.SetCellRenderer(row, col, renderer) + + grid.SetCellBackgroundColour(row, col, wxWHITE) + + def SetData(self, data): + self.data = data + + def GetData(self): + return self.data + + def GetCurrentIndex(self): + return self.CurrentIndex + + def SetCurrentIndex(self, index): + self.CurrentIndex = index + + def AppendRow(self, row_content): + self.data.append(row_content) + + def RemoveRow(self, row_index): + self.data.pop(row_index) + + def MoveRow(self, row_index, move, grid): + new_index = max(0, min(row_index + move, len(self.data) - 1)) + if new_index != row_index: + self.data.insert(new_index, self.data.pop(row_index)) + grid.SetGridCursor(new_index, grid.GetGridCursorCol()) + + def Empty(self): + self.data = [] + self.editors = [] + +[wxID_RESOURCEEDITOR, wxID_RESOURCEEDITORSTATICTEXT1, + wxID_RESOURCEEDITORSTATICTEXT2, wxID_RESOURCEEDITORINSTANCESGRID, + wxID_RESOURCEEDITORTASKSGRID, wxID_RESOURCEEDITORADDINSTANCEBUTTON, + wxID_RESOURCEEDITORDELETEINSTANCEBUTTON, wxID_RESOURCEEDITORUPINSTANCEBUTTON, + wxID_RESOURCEEDITORDOWNINSTANCEBUTTON, wxID_RESOURCEEDITORADDTASKBUTTON, + wxID_RESOURCEEDITORDELETETASKBUTTON, wxID_RESOURCEEDITORUPTASKBUTTON, + wxID_RESOURCEEDITORDOWNTASKBUTTON, +] = [wx.NewId() for _init_ctrls in range(13)] + +class ResourceEditor(wx.Panel): + + def _init_coll_InstancesSizer_Growables(self, parent): + # generated method, don't edit + + parent.AddGrowableCol(0) + parent.AddGrowableRow(1) + + def _init_coll_InstancesSizer_Items(self, parent): + # generated method, don't edit + + parent.AddSizer(self.InstancesButtonsSizer, 0, border=0, flag=wxGROW) + parent.AddWindow(self.InstancesGrid, 0, border=0, flag=wxGROW) + + def _init_coll_InstancesButtonsSizer_Growables(self, parent): + # generated method, don't edit + + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + + def _init_coll_InstancesButtonsSizer_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.staticText2, 0, border=0, flag=wxALIGN_BOTTOM) + parent.AddWindow(self.AddInstanceButton, 0, border=0, flag=0) + parent.AddWindow(self.DeleteInstanceButton, 0, border=0, flag=0) + parent.AddWindow(self.UpInstanceButton, 0, border=0, flag=0) + parent.AddWindow(self.DownInstanceButton, 0, border=0, flag=0) + + def _init_coll_TasksSizer_Growables(self, parent): + # generated method, don't edit + + parent.AddGrowableCol(0) + parent.AddGrowableRow(1) + + def _init_coll_TasksSizer_Items(self, parent): + # generated method, don't edit + + parent.AddSizer(self.TasksButtonsSizer, 0, border=0, flag=wxGROW) + parent.AddWindow(self.TasksGrid, 0, border=0, flag=wxGROW) + + def _init_coll_TasksButtonsSizer_Growables(self, parent): + # generated method, don't edit + + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + + def _init_coll_TasksButtonsSizer_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.staticText1, 0, border=0, flag=wxALIGN_BOTTOM) + parent.AddWindow(self.AddTaskButton, 0, border=0, flag=0) + parent.AddWindow(self.DeleteTaskButton, 0, border=0, flag=0) + parent.AddWindow(self.UpTaskButton, 0, border=0, flag=0) + parent.AddWindow(self.DownTaskButton, 0, border=0, flag=0) + + def _init_coll_MainGridSizer_Items(self, parent): + # generated method, don't edit + + parent.AddSizer(self.TasksSizer, 0, border=0, flag=wxGROW) + parent.AddSizer(self.InstancesSizer, 0, border=0, flag=wxGROW) + + def _init_coll_MainGridSizer_Growables(self, parent): + # generated method, don't edit + + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + parent.AddGrowableRow(1) + + def _init_sizers(self): + # generated method, don't edit + self.MainGridSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) + + self.InstancesSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) + + self.InstancesButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) + + self.TasksSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) + + self.TasksButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) + + self._init_coll_MainGridSizer_Growables(self.MainGridSizer) + self._init_coll_MainGridSizer_Items(self.MainGridSizer) + self._init_coll_InstancesSizer_Growables(self.InstancesSizer) + self._init_coll_InstancesSizer_Items(self.InstancesSizer) + self._init_coll_InstancesButtonsSizer_Growables(self.InstancesButtonsSizer) + self._init_coll_InstancesButtonsSizer_Items(self.InstancesButtonsSizer) + self._init_coll_TasksSizer_Growables(self.TasksSizer) + self._init_coll_TasksSizer_Items(self.TasksSizer) + self._init_coll_TasksButtonsSizer_Growables(self.TasksButtonsSizer) + self._init_coll_TasksButtonsSizer_Items(self.TasksButtonsSizer) + + self.SetSizer(self.MainGridSizer) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Panel.__init__(self, id=wxID_RESOURCEEDITOR, name='', parent=prnt, + pos=wx.Point(0, 0), size=wx.Size(-1, -1), + style=wx.SUNKEN_BORDER) + + self.staticText1 = wx.StaticText(id=wxID_RESOURCEEDITORSTATICTEXT1, + label=u'Tasks:', name='staticText2', parent=self, pos=wx.Point(0, + 0), size=wx.Size(60, 17), style=wxALIGN_CENTER) + + self.TasksGrid = wx.grid.Grid(id=wxID_RESOURCEEDITORTASKSGRID, + name='TasksGrid', parent=self, pos=wx.Point(0, 0), + size=wx.Size(-1, -1), style=wxVSCROLL) + self.TasksGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, + 'Sans')) + self.TasksGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, + False, 'Sans')) + EVT_GRID_CELL_CHANGE(self.TasksGrid, self.OnTasksGridCellChange) + + self.AddTaskButton = wx.Button(id=wxID_RESOURCEEDITORADDTASKBUTTON, label='Add Task', + name='AddTaskButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(102, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORADDTASKBUTTON, self.OnAddTaskButton) + + self.DeleteTaskButton = wx.Button(id=wxID_RESOURCEEDITORDELETETASKBUTTON, label='Delete Task', + name='DeleteTaskButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(102, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORDELETETASKBUTTON, self.OnDeleteTaskButton) + + self.UpTaskButton = wx.Button(id=wxID_RESOURCEEDITORUPTASKBUTTON, label='^', + name='UpTaskButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORUPTASKBUTTON, self.OnUpTaskButton) + + self.DownTaskButton = wx.Button(id=wxID_RESOURCEEDITORDOWNTASKBUTTON, label='v', + name='DownTaskButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORDOWNTASKBUTTON, self.OnDownTaskButton) + + self.staticText2 = wx.StaticText(id=wxID_RESOURCEEDITORSTATICTEXT2, + label=u'Instances:', name='staticText1', parent=self, + pos=wx.Point(0, 0), size=wx.Size(85, 17), style=wxALIGN_CENTER) + + self.InstancesGrid = wx.grid.Grid(id=wxID_RESOURCEEDITORINSTANCESGRID, + name='InstancesGrid', parent=self, pos=wx.Point(0, 0), + size=wx.Size(-1, -1), style=wxVSCROLL) + self.InstancesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, + 'Sans')) + self.InstancesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, + False, 'Sans')) + EVT_GRID_CELL_CHANGE(self.InstancesGrid, self.OnInstancesGridCellChange) + + self.AddInstanceButton = wx.Button(id=wxID_RESOURCEEDITORADDINSTANCEBUTTON, label='Add Instance', + name='AddInstanceButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(122, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORADDINSTANCEBUTTON, self.OnAddInstanceButton) + + self.DeleteInstanceButton = wx.Button(id=wxID_RESOURCEEDITORDELETEINSTANCEBUTTON, label='Delete Instance', + name='DeleteInstanceButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(122, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORDELETEINSTANCEBUTTON, self.OnDeleteInstanceButton) + + self.UpInstanceButton = wx.Button(id=wxID_RESOURCEEDITORUPINSTANCEBUTTON, label='^', + name='UpInstanceButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORUPINSTANCEBUTTON, self.OnUpInstanceButton) + + self.DownInstanceButton = wx.Button(id=wxID_RESOURCEEDITORDOWNINSTANCEBUTTON, label='v', + name='DownInstanceButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + EVT_BUTTON(self, wxID_RESOURCEEDITORDOWNINSTANCEBUTTON, self.OnDownInstanceButton) + + self._init_sizers() + + def __init__(self, parent, window, controler): + self._init_ctrls(parent) + + self.Parent = window + self.Controler = controler + + self.TasksDefaultValue = {"Name" : "", "Single" : "", "Interval" : "", "Priority" : 0} + self.TasksTable = ResourceTable(self, [], ["Name", "Single", "Interval", "Priority"]) + self.TasksTable.SetColAlignements([wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_RIGHT, wxALIGN_RIGHT]) + self.TasksTable.SetColSizes([200, 100, 100, 100]) + self.TasksGrid.SetTable(self.TasksTable) + self.TasksGrid.SetRowLabelSize(0) + self.TasksTable.ResetView(self.TasksGrid) + + self.InstancesDefaultValue = {"Name" : "", "Type" : "", "Task" : ""} + self.InstancesTable = ResourceTable(self, [], ["Name", "Type", "Task"]) + self.InstancesTable.SetColAlignements([wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT]) + self.InstancesTable.SetColSizes([200, 150, 150]) + self.InstancesGrid.SetTable(self.InstancesTable) + self.InstancesGrid.SetRowLabelSize(0) + self.InstancesTable.ResetView(self.InstancesGrid) + + def RefreshTypeList(self): + self.TypeList = "" + blocktypes = self.Controler.GetBlockResource() + for blocktype in blocktypes: + self.TypeList += ",%s"%blocktype + + def RefreshTaskList(self): + self.TaskList = "" + for row in xrange(self.TasksTable.GetNumberRows()): + self.TaskList += ",%s"%self.TasksTable.GetValueByName(row, "Name") + + def RefreshVariableList(self): + self.VariableList = "" + for variable in self.Controler.GetCurrentResourceEditingVariables(): + self.VariableList += ",%s"%variable + + def RefreshModel(self): + self.Controler.SetCurrentResourceEditingInfos(self.TasksTable.GetData(), self.InstancesTable.GetData()) + + def RefreshView(self): + tasks, instances = self.Controler.GetCurrentResourceEditingInfos() + self.TasksTable.SetData(tasks) + self.InstancesTable.SetData(instances) + self.RefreshTypeList() + self.RefreshTaskList() + self.RefreshVariableList() + self.InstancesTable.ResetView(self.InstancesGrid) + self.TasksTable.ResetView(self.TasksGrid) + + def OnAddTaskButton(self, event): + self.TasksTable.AppendRow(self.TasksDefaultValue.copy()) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnDeleteTaskButton(self, event): + row = self.TasksGrid.GetGridCursorRow() + self.TasksTable.RemoveRow(row) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnUpTaskButton(self, event): + row = self.TasksGrid.GetGridCursorRow() + self.TasksTable.MoveRow(row, -1, self.TasksGrid) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnDownTaskButton(self, event): + row = self.TasksGrid.GetGridCursorRow() + self.TasksTable.MoveRow(row, 1, self.TasksGrid) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnAddInstanceButton(self, event): + self.InstancesTable.AppendRow(self.InstancesDefaultValue.copy()) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnDeleteInstanceButton(self, event): + row = self.InstancesGrid.GetGridCursorRow() + self.InstancesTable.RemoveRow(row) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnUpInstanceButton(self, event): + row = self.InstancesGrid.GetGridCursorRow() + self.InstancesTable.MoveRow(row, -1, self.InstancesGrid) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnDownInstanceButton(self, event): + row = self.InstancesGrid.GetGridCursorRow() + self.InstancesTable.MoveRow(row, 1, self.InstancesGrid) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnTasksGridCellChange(self, event): + row, col = event.GetRow(), event.GetCol() + if self.TasksTable.GetColLabelValue(event.GetCol()) == "Name": + tasklist = self.TaskList.split(",") + for i in xrange(self.TasksTable.GetNumberRows()): + task = self.TasksTable.GetValueByName(i, "Name") + if task in tasklist: + tasklist.remove(task) + tasklist.remove("") + if len(tasklist) > 0: + old_name = tasklist[0] + new_name = self.TasksTable.GetValue(row, col) + for i in xrange(self.InstancesTable.GetNumberRows()): + if self.InstancesTable.GetValueByName(i, "Task") == old_name: + self.InstancesTable.SetValueByName(i, "Task", new_name) + self.RefreshModel() + self.RefreshView() + event.Skip() + + def OnInstancesGridCellChange(self, event): + self.RefreshModel() + self.RefreshView() + event.Skip()