# HG changeset patch # User lbessard # Date 1183972214 -7200 # Node ID dae55dd9ee14e5e2d6f444bffaa5d0edfb321f44 # Parent 36d378bd852e8f08ca12e575aeb4daf2cb3e0f8a Current developping version diff -r 36d378bd852e -r dae55dd9ee14 Dialogs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Dialogs.py Mon Jul 09 11:10:14 2007 +0200 @@ -0,0 +1,1526 @@ +#!/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 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 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.grid import * +import wx + +from graphics.FBD_Objects import * +from graphics.LD_Objects import * +from graphics.SFC_Objects import * + +#------------------------------------------------------------------------------- +# Create New Block Dialog +#------------------------------------------------------------------------------- + +[wxID_BLOCKPROPERTIESDIALOG, wxID_BLOCKPROPERTIESDIALOGMAINPANEL, + wxID_BLOCKPROPERTIESDIALOGNAME, wxID_BLOCKPROPERTIESDIALOGTYPETREE, + wxID_BLOCKPROPERTIESDIALOGTYPEDESC, wxID_BLOCKPROPERTIESDIALOGINPUTS, + wxID_BLOCKPROPERTIESDIALOGPREVIEW, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, + wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT3, + wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, +] = [wx.NewId() for _init_ctrls in range(11)] + +[CATEGORY, BLOCK] = range(2) + +class BlockPropertiesDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_BLOCKPROPERTIESDIALOG, + name='BlockPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(600, 360), style=wx.DEFAULT_DIALOG_STYLE, + title='Block Properties') + self.SetClientSize(wx.Size(600, 360)) + + self.MainPanel = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(600, 320), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticbox1 = wx.StaticBox(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, + label='Type:', name='staticBox1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(245, 280), style=0) + + self.staticText2 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, + label='Name:', name='staticText2', parent=self.MainPanel, + pos=wx.Point(274, 24), size=wx.Size(70, 17), style=0) + + self.staticText3 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, + label='Inputs:', name='staticText4', parent=self.MainPanel, + pos=wx.Point(424, 24), size=wx.Size(70, 17), style=0) + + self.staticText4 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, + label='Preview:', name='staticText4', parent=self.MainPanel, + pos=wx.Point(274, 80), size=wx.Size(100, 17), style=0) + + self.TypeTree = wx.TreeCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPETREE, + name='TypeTree', parent=self.MainPanel, pos=wx.Point(34, 44), + size=wx.Size(225, 180), style=wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER) + EVT_TREE_SEL_CHANGED(self, wxID_BLOCKPROPERTIESDIALOGTYPETREE, self.OnTypeTreeItemSelected) + + self.TypeDesc = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPEDESC, + name='TypeDesc', parent=self.MainPanel, pos=wx.Point(34, 230), + size=wx.Size(225, 65), style=wx.TE_READONLY|wx.TE_MULTILINE) + + self.Name = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGNAME, value='', + name='Name', parent=self.MainPanel, pos=wx.Point(274, 48), + size=wx.Size(145, 24), style=0) + EVT_TEXT(self, wxID_BLOCKPROPERTIESDIALOGNAME, self.OnNameChanged) + + self.Inputs = wx.SpinCtrl(id=wxID_BLOCKPROPERTIESDIALOGINPUTS, + name='Inputs', parent=self.MainPanel, pos=wx.Point(424, 48), + size=wx.Size(145, 24), style=wxSP_ARROW_KEYS, min=2, max=20) + EVT_SPINCTRL(self, wxID_BLOCKPROPERTIESDIALOGINPUTS, self.OnInputsChanged) + + self.Preview = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGPREVIEW, + name='Preview', parent=self.MainPanel, pos=wx.Point(274, 104), + size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) + self.Preview.SetBackgroundColour(wxColour(255,255,255)) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + self.Name.SetValue("") + self.Name.Enable(False) + self.Inputs.Enable(False) + self.Block = None + self.MinBlockSize = None + + EVT_PAINT(self, self.OnPaint) + EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK) + + def FindTreeItem(self, root, name): + if root.IsOk(): + if self.TypeTree.GetItemText(root) == name: + return root + else: + item, root_cookie = self.TypeTree.GetFirstChild(root) + while item.IsOk(): + result = self.FindTreeItem(item, name) + if result: + return result + item, root_cookie = self.TypeTree.GetNextChild(root, root_cookie) + return None + + def OnOK(self, event): + error = [] + selected = self.TypeTree.GetSelection() + if not selected.IsOk() or self.TypeTree.GetItemParent(selected) == self.TypeTree.GetRootItem() or selected == self.TypeTree.GetRootItem(): + message = wxMessageDialog(self, "Form isn't complete. Valid block type must be selected!", "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + elif self.Name.IsEnabled() and self.Name.GetValue() == "": + message = wxMessageDialog(self, "Form isn't complete. Name must be filled!", "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + else: + self.EndModal(wxID_OK) + + def SetBlockList(self, blocktypes): + root = self.TypeTree.AddRoot("") + self.TypeTree.SetPyData(root, CATEGORY) + for category in blocktypes: + category_item = self.TypeTree.AppendItem(root, category["name"]) + self.TypeTree.SetPyData(category_item, CATEGORY) + for blocktype in category["list"]: + blocktype_item = self.TypeTree.AppendItem(category_item, blocktype["name"]) + self.TypeTree.SetPyData(blocktype_item, BLOCK) + + def SetMinBlockSize(self, size): + self.MinBlockSize = size + + def SetValues(self, values): + for name, value in values.items(): + if name == "type": + item = self.FindTreeItem(self.TypeTree.GetRootItem(), value) + if item: + self.TypeTree.SelectItem(item) + elif name == "name": + self.Name.SetValue(value) + elif name == "extension": + self.Inputs.SetValue(value) + self.RefreshPreview() + + def GetValues(self): + values = {} + values["type"] = self.TypeTree.GetItemText(self.TypeTree.GetSelection()) + if self.Name.GetValue() != "": + values["name"] = self.Name.GetValue() + values["width"], values["height"] = self.Block.GetSize() + values["extension"] = self.Inputs.GetValue() + return values + + def OnTypeTreeItemSelected(self, event): + self.Name.SetValue("") + selected = event.GetItem() + if self.TypeTree.GetPyData(selected) != CATEGORY: + blocktype = GetBlockType(self.TypeTree.GetItemText(selected)) + if blocktype: + self.Inputs.SetValue(len(blocktype["inputs"])) + self.Inputs.Enable(blocktype["extensible"]) + self.Name.Enable(blocktype["type"] != "function") + self.TypeDesc.SetValue(blocktype["comment"]) + wxCallAfter(self.RefreshPreview) + else: + self.Name.Enable(False) + self.Inputs.Enable(False) + self.Inputs.SetValue(2) + self.TypeDesc.SetValue("") + wxCallAfter(self.ErasePreview) + else: + self.Name.Enable(False) + self.Inputs.Enable(False) + self.Inputs.SetValue(2) + self.TypeDesc.SetValue("") + wxCallAfter(self.ErasePreview) + event.Skip() + + def OnNameChanged(self, event): + if self.Name.IsEnabled(): + self.RefreshPreview() + event.Skip() + + def OnInputsChanged(self, event): + if self.Inputs.IsEnabled(): + self.RefreshPreview() + event.Skip() + + def ErasePreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + self.Block = None + + def RefreshPreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + item = self.TypeTree.GetSelection() + if self.TypeTree.GetPyData(item) == CATEGORY: + self.Block = None + else: + blocktype = self.TypeTree.GetItemText(item) + if blocktype: + self.Block = FBD_Block(self.Preview, blocktype, self.Name.GetValue(), extension = self.Inputs.GetValue()) + width, height = self.MinBlockSize + min_width, min_height = self.Block.GetMinSize() + width, height = max(min_width, width), max(min_height, height) + self.Block.SetSize(width, height) + clientsize = self.Preview.GetClientSize() + x = (clientsize.width - width) / 2 + y = (clientsize.height - height) / 2 + self.Block.SetPosition(x, y) + self.Block.Draw(dc) + else: + self.Block = None + + def OnPaint(self, event): + if self.Block: + self.RefreshPreview() + + +#------------------------------------------------------------------------------- +# Create New Variable Dialog +#------------------------------------------------------------------------------- + +[wxID_VARIABLEPROPERTIESDIALOG, wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, + wxID_VARIABLEPROPERTIESDIALOGNAME, wxID_VARIABLEPROPERTIESDIALOGCLASS, + wxID_VARIABLEPROPERTIESDIALOGPREVIEW, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, + wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, +] = [wx.NewId() for _init_ctrls in range(8)] + +class VariablePropertiesDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_VARIABLEPROPERTIESDIALOG, + name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(400, 320), style=wx.DEFAULT_DIALOG_STYLE, + title='Variable Properties') + self.SetClientSize(wx.Size(400, 320)) + + self.MainPanel = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(400, 280), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticText1 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, + label='Class:', name='staticText1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) + + self.staticText2 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, + label='Name:', name='staticText2', parent=self.MainPanel, + pos=wx.Point(204, 24), size=wx.Size(70, 17), style=0) + + self.staticText3 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, + label='Preview:', name='staticText3', parent=self.MainPanel, + pos=wx.Point(24, 78), size=wx.Size(100, 17), style=0) + + self.Class = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGCLASS, + name='Class', parent=self.MainPanel, pos=wx.Point(24, 48), + size=wx.Size(145, 24), style=0) + EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGCLASS, self.OnClassChanged) + + self.Name = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGNAME, + name='Name', parent=self.MainPanel, pos=wx.Point(204, 48), + size=wx.Size(145, 24), style=0) + EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGNAME, self.OnNameChanged) + + self.Preview = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGPREVIEW, + name='Preview', parent=self.MainPanel, pos=wx.Point(24, 104), + size=wx.Size(350, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) + self.Preview.SetBackgroundColour(wxColour(255,255,255)) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + self.Variable = None + self.VarList = [] + self.MinVariableSize = None + self.RefreshNameList() + + for choice in ["Input", "Output", "InOut"]: + self.Class.Append(choice) + self.Class.SetStringSelection("Input") + + EVT_PAINT(self, self.OnPaint) + + def RefreshNameList(self): + selected = self.Name.GetStringSelection() + self.Name.Clear() + for name, var_type, value_type in self.VarList: + if var_type in ["Local","Temp"]: + self.Name.Append(name) + elif var_type == "Input" and self.Class.GetStringSelection() == "Input": + self.Name.Append(name) + elif var_type == "Output" and self.Class.GetStringSelection() == "Output": + self.Name.Append(name) + elif var_type == "InOut" and self.Class.GetStringSelection() == "InOut": + self.Name.Append(name) + if self.Name.FindString(selected) != wxNOT_FOUND: + self.Name.SetStringSelection(selected) + self.Name.Enable(self.Name.GetCount() > 0) + + def SetMinVariableSize(self, size): + self.MinVariableSize = size + + def SetVariables(self, vars): + self.VarList = vars + self.RefreshNameList() + + def SetValues(self, values): + for name, value in values.items(): + if name == "type": + if value == INPUT: + self.Class.SetStringSelection("Input") + if value == OUTPUT: + self.Class.SetStringSelection("Output") + if value == INOUT: + self.Class.SetStringSelection("InOut") + elif name == "name": + self.Name.SetStringSelection(value) + self.RefreshPreview() + + def GetValues(self): + values = {} + classtype = self.Class.GetStringSelection() + if classtype == "Input": + values["type"] = INPUT + elif classtype == "Output": + values["type"] = OUTPUT + elif classtype == "InOut": + values["type"] = INOUT + values["name"] = self.Name.GetStringSelection() + values["value_type"] = "" + for var_name, var_type, value_type in self.VarList: + if var_name == values["name"]: + values["value_type"] = value_type + values["width"], values["height"] = self.Variable.GetSize() + return values + + def OnClassChanged(self, event): + self.RefreshNameList() + self.RefreshPreview() + event.Skip() + + def OnNameChanged(self, event): + self.RefreshPreview() + event.Skip() + + def RefreshPreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + name = self.Name.GetStringSelection() + type = "" + for var_name, var_type, value_type in self.VarList: + if var_name == name: + type = value_type + classtype = self.Class.GetStringSelection() + if classtype == "Input": + self.Variable = FBD_Variable(self.Preview, INPUT, name, type) + elif classtype == "Output": + self.Variable = FBD_Variable(self.Preview, OUTPUT, name, type) + elif classtype == "InOut": + self.Variable = FBD_Variable(self.Preview, INOUT, name, type) + width, height = self.MinVariableSize + min_width, min_height = self.Variable.GetMinSize() + width, height = max(min_width, width), max(min_height, height) + self.Variable.SetSize(width, height) + clientsize = self.Preview.GetClientSize() + x = (clientsize.width - width) / 2 + y = (clientsize.height - height) / 2 + self.Variable.SetPosition(x, y) + self.Variable.Draw(dc) + + def OnPaint(self, event): + self.RefreshPreview() + +#------------------------------------------------------------------------------- +# Create New Connection Dialog +#------------------------------------------------------------------------------- + +[wxID_CONNECTIONPROPERTIESDIALOG, wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, + wxID_CONNECTIONPROPERTIESDIALOGNAME, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, + wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, + wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, + wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, +] = [wx.NewId() for _init_ctrls in range(9)] + +class ConnectionPropertiesDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_CONNECTIONPROPERTIESDIALOG, + name='ConnectionPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(350, 220), style=wx.DEFAULT_DIALOG_STYLE, + title='Connection Properties') + self.SetClientSize(wx.Size(350, 220)) + + self.MainPanel = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(340, 360), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticText1 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, + label='Type:', name='staticText1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) + + self.staticText2 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, + label='Name:', name='staticText2', parent=self.MainPanel, + pos=wx.Point(24, 104), size=wx.Size(70, 17), style=0) + + self.staticText3 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, + label='Preview:', name='staticText3', parent=self.MainPanel, + pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) + + self.radioButton1 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, + label='Connector', name='radioButton1', parent=self.MainPanel, + pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) + EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, self.OnTypeChanged) + self.radioButton1.SetValue(True) + + self.radioButton2 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, + label='Continuation', name='radioButton2', parent=self.MainPanel, + pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) + EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, self.OnTypeChanged) + self.radioButton2.SetValue(False) + + self.Name = wx.TextCtrl(id=wxID_CONNECTIONPROPERTIESDIALOGNAME, + name='Name', parent=self.MainPanel, pos=wx.Point(24, 130), + size=wx.Size(145, 24), style=0) + EVT_TEXT(self, wxID_CONNECTIONPROPERTIESDIALOGNAME, self.OnNameChanged) + + self.Preview = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, + name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), + size=wx.Size(150, 100), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) + self.Preview.SetBackgroundColour(wxColour(255,255,255)) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + self.Connection = None + self.MinConnectionSize = None + + EVT_PAINT(self, self.OnPaint) + + def SetMinConnectionSize(self, size): + self.MinConnectionSize = size + + def GetValues(self): + values = {} + if self.radioButton1.GetValue(): + values["type"] = CONNECTOR + else: + values["type"] = CONTINUATION + values["name"] = self.Name.GetValue() + values["width"], values["height"] = self.Connection.GetSize() + return values + + def OnTypeChanged(self, event): + self.RefreshPreview() + event.Skip() + + def OnNameChanged(self, event): + self.RefreshPreview() + event.Skip() + + def RefreshPreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + if self.radioButton1.GetValue(): + self.Connection = FBD_Connector(self.Preview, CONNECTOR, self.Name.GetValue()) + else: + self.Connection = FBD_Connector(self.Preview, CONTINUATION, self.Name.GetValue()) + width, height = self.MinConnectionSize + min_width, min_height = self.Connection.GetMinSize() + width, height = max(min_width, width), max(min_height, height) + self.Connection.SetSize(width, height) + clientsize = self.Preview.GetClientSize() + x = (clientsize.width - width) / 2 + y = (clientsize.height - height) / 2 + self.Connection.SetPosition(x, y) + self.Connection.Draw(dc) + + def OnPaint(self, event): + self.RefreshPreview() + + +#------------------------------------------------------------------------------- +# Edit Ladder Element Properties Dialog +#------------------------------------------------------------------------------- + + +[wxID_LDELEMENTDIALOG, wxID_LDELEMENTDIALOGMAINPANEL, + wxID_LDELEMENTDIALOGNAME, wxID_LDELEMENTDIALOGRADIOBUTTON1, + wxID_LDELEMENTDIALOGRADIOBUTTON2, wxID_LDELEMENTDIALOGRADIOBUTTON3, + wxID_LDELEMENTDIALOGRADIOBUTTON4, wxID_LDELEMENTDIALOGPREVIEW, + wxID_LDELEMENTDIALOGSTATICTEXT1, wxID_LDELEMENTDIALOGSTATICTEXT2, + wxID_LDELEMENTDIALOGSTATICTEXT3, +] = [wx.NewId() for _init_ctrls in range(11)] + +class LDElementDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt, title, labels): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_LDELEMENTDIALOG, + name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(350, 260), style=wx.DEFAULT_DIALOG_STYLE, + title=title) + self.SetClientSize(wx.Size(350, 260)) + + self.MainPanel = wx.Panel(id=wxID_LDELEMENTDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(340, 200), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticText1 = wx.StaticText(id=wxID_LDELEMENTDIALOGSTATICTEXT1, + label='Modifier:', name='staticText1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) + + self.staticText2 = wx.StaticText(id=wxID_LDELEMENTDIALOGSTATICTEXT2, + label='Name:', name='staticText2', parent=self.MainPanel, + pos=wx.Point(24, 150), size=wx.Size(70, 17), style=0) + + self.staticText3 = wx.StaticText(id=wxID_LDELEMENTDIALOGSTATICTEXT3, + label='Preview:', name='staticText3', parent=self.MainPanel, + pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) + + self.radioButton1 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON1, + label=labels[0], name='radioButton1', parent=self.MainPanel, + pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) + EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON1, self.OnTypeChanged) + self.radioButton1.SetValue(True) + + self.radioButton2 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON2, + label=labels[1], name='radioButton2', parent=self.MainPanel, + pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) + EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON2, self.OnTypeChanged) + + self.radioButton3 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON3, + label=labels[2], name='radioButton3', parent=self.MainPanel, + pos=wx.Point(24, 96), size=wx.Size(114, 24), style=0) + EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON3, self.OnTypeChanged) + + self.radioButton4 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON4, + label=labels[3], name='radioButton4', parent=self.MainPanel, + pos=wx.Point(24, 120), size=wx.Size(128, 24), style=0) + EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON4, self.OnTypeChanged) + + self.Name = wx.Choice(id=wxID_LDELEMENTDIALOGNAME, + name='Name', parent=self.MainPanel, pos=wx.Point(24, 174), + size=wx.Size(145, 24), style=0) + EVT_CHOICE(self, wxID_LDELEMENTDIALOGNAME, self.OnNameChanged) + + self.Preview = wx.Panel(id=wxID_LDELEMENTDIALOGPREVIEW, + name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), + size=wx.Size(150, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) + self.Preview.SetBackgroundColour(wxColour(255,255,255)) + + self._init_sizers() + + def __init__(self, parent, type): + self.Type = type + if type == "contact": + self._init_ctrls(parent, "Edit Contact Values", ['Normal','Negate','Rising Edge','Falling Edge']) + self.Element = LD_Contact(self.Preview, CONTACT_NORMAL, "") + elif type == "coil": + self._init_ctrls(parent, "Edit Coil Values", ['Normal','Negate','Set','Reset']) + self.Element = LD_Coil(self.Preview, COIL_NORMAL, "") + self.Element.SetPosition((150 - LD_ELEMENT_SIZE[0]) / 2, (150 - LD_ELEMENT_SIZE[1]) / 2) + + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + + EVT_PAINT(self, self.OnPaint) + + def SetElementSize(self, width, height): + min_width, min_height = self.Element.GetMinSize() + width, height = max(min_width, width), max(min_height, height) + self.Element.SetSize(width, height) + self.Element.SetPosition((150 - width) / 2, (150 - height) / 2) + + def SetVariables(self, vars): + self.Name.Clear() + for name in vars: + self.Name.Append(name) + self.Name.Enable(self.Name.GetCount() > 0) + + def SetValues(self, values): + for name, value in values.items(): + if name == "name": + self.Element.SetName(value) + self.Name.SetStringSelection(value) + elif name == "type": + self.Element.SetType(value) + if self.Type == "contact": + if value == CONTACT_NORMAL: + self.radioButton1.SetValue(True) + elif value == CONTACT_REVERSE: + self.radioButton2.SetValue(True) + elif value == CONTACT_RISING: + self.radioButton3.SetValue(True) + elif value == CONTACT_FALLING: + self.radioButton4.SetValue(True) + elif self.Type == "coil": + if value == COIL_NORMAL: + self.radioButton1.SetValue(True) + elif value == COIL_REVERSE: + self.radioButton2.SetValue(True) + elif value == COIL_SET: + self.radioButton3.SetValue(True) + elif value == COIL_RESET: + self.radioButton4.SetValue(True) + + def GetValues(self): + values = {} + values["name"] = self.Element.GetName() + values["type"] = self.Element.GetType() + values["width"], values["height"] = self.Element.GetSize() + return values + + def OnTypeChanged(self, event): + if self.Type == "contact": + if self.radioButton1.GetValue(): + self.Element.SetType(CONTACT_NORMAL) + elif self.radioButton2.GetValue(): + self.Element.SetType(CONTACT_REVERSE) + elif self.radioButton3.GetValue(): + self.Element.SetType(CONTACT_RISING) + elif self.radioButton4.GetValue(): + self.Element.SetType(CONTACT_FALLING) + elif self.Type == "coil": + if self.radioButton1.GetValue(): + self.Element.SetType(COIL_NORMAL) + elif self.radioButton2.GetValue(): + self.Element.SetType(COIL_REVERSE) + elif self.radioButton3.GetValue(): + self.Element.SetType(COIL_SET) + elif self.radioButton4.GetValue(): + self.Element.SetType(COIL_RESET) + self.RefreshPreview() + event.Skip() + + def OnNameChanged(self, event): + self.Element.SetName(self.Name.GetStringSelection()) + self.RefreshPreview() + event.Skip() + + def RefreshPreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + self.Element.Draw(dc) + + def OnPaint(self, event): + self.RefreshPreview() + event.Skip() + + +#------------------------------------------------------------------------------- +# Edit Ladder Power Rail Properties Dialog +#------------------------------------------------------------------------------- + + +[wxID_LDPOWERRAILDIALOG, wxID_LDPOWERRAILDIALOGMAINPANEL, + wxID_LDPOWERRAILDIALOGTYPE, wxID_LDPOWERRAILDIALOGRADIOBUTTON1, + wxID_LDPOWERRAILDIALOGRADIOBUTTON2, wxID_LDPOWERRAILDIALOGPREVIEW, + wxID_LDPOWERRAILDIALOGSTATICTEXT1, wxID_LDPOWERRAILDIALOGSTATICTEXT2, + wxID_LDPOWERRAILDIALOGSTATICTEXT3, wxID_LDPOWERRAILDIALOGPINNUMBER, +] = [wx.NewId() for _init_ctrls in range(10)] + +class LDPowerRailDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_LDPOWERRAILDIALOG, + name='PowerRailDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(350, 260), style=wx.DEFAULT_DIALOG_STYLE, + title='Power Rail Properties') + self.SetClientSize(wx.Size(350, 260)) + + self.MainPanel = wx.Panel(id=wxID_LDPOWERRAILDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(340, 200), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticText1 = wx.StaticText(id=wxID_LDPOWERRAILDIALOGSTATICTEXT1, + label='Type:', name='staticText1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) + + self.staticText2 = wx.StaticText(id=wxID_LDPOWERRAILDIALOGSTATICTEXT2, + label='Pin number:', name='staticText2', parent=self.MainPanel, + pos=wx.Point(24, 100), size=wx.Size(70, 17), style=0) + + self.staticText3 = wx.StaticText(id=wxID_LDPOWERRAILDIALOGSTATICTEXT3, + label='Preview:', name='staticText3', parent=self.MainPanel, + pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) + + self.radioButton1 = wx.RadioButton(id=wxID_LDPOWERRAILDIALOGRADIOBUTTON1, + label='Left PowerRail', name='radioButton1', parent=self.MainPanel, + pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) + EVT_RADIOBUTTON(self, wxID_LDPOWERRAILDIALOGRADIOBUTTON1, self.OnTypeChanged) + self.radioButton1.SetValue(True) + + self.radioButton2 = wx.RadioButton(id=wxID_LDPOWERRAILDIALOGRADIOBUTTON2, + label='Right PowerRail', name='radioButton2', parent=self.MainPanel, + pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) + EVT_RADIOBUTTON(self, wxID_LDPOWERRAILDIALOGRADIOBUTTON2, self.OnTypeChanged) + + self.PinNumber = wx.SpinCtrl(id=wxID_LDPOWERRAILDIALOGPINNUMBER, + name='PinNumber', parent=self.MainPanel, pos=wx.Point(24, 124), + size=wx.Size(145, 24), style=wxSP_ARROW_KEYS, min=1, max=20) + EVT_SPINCTRL(self, wxID_LDPOWERRAILDIALOGPINNUMBER, self.OnPinNumberChanged) + + self.Preview = wx.Panel(id=wxID_LDPOWERRAILDIALOGPREVIEW, + name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), + size=wx.Size(150, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) + self.Preview.SetBackgroundColour(wxColour(255,255,255)) + + self._init_sizers() + + def __init__(self, parent, type = LEFTRAIL, number = 1): + self._init_ctrls(parent) + self.Type = type + if type == LEFTRAIL: + self.radioButton1.SetValue(True) + elif type == RIGHTRAIL: + self.radioButton2.SetValue(True) + self.PinNumber.SetValue(number) + + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + + self.PowerRailMinSize = (0, 0) + self.PowerRail = None + + EVT_PAINT(self, self.OnPaint) + + def SetMinSize(self, size): + self.PowerRailMinSize = size + self.RefreshPreview() + + def GetValues(self): + values = {} + values["type"] = self.Type + values["number"] = self.PinNumber.GetValue() + values["width"], values["height"] = self.PowerRail.GetSize() + return values + + def OnTypeChanged(self, event): + if self.radioButton1.GetValue(): + self.Type = LEFTRAIL + elif self.radioButton2.GetValue(): + self.Type = RIGHTRAIL + self.RefreshPreview() + event.Skip() + + def OnPinNumberChanged(self, event): + self.RefreshPreview() + event.Skip() + + def RefreshPreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + self.PowerRail = LD_PowerRail(self.Preview, self.Type, connectors = [True for i in xrange(self.PinNumber.GetValue())]) + min_width, min_height = self.PowerRail.GetMinSize() + width, height = max(min_width, self.PowerRailMinSize[0]), max(min_height, self.PowerRailMinSize[1]) + self.PowerRail.SetSize(width, height) + self.PowerRail.RefreshConnectors() + self.PowerRail.SetPosition((150 - width) / 2, (150 - height) / 2) + self.PowerRail.Draw(dc) + + def OnPaint(self, event): + self.RefreshPreview() + event.Skip() + + +#------------------------------------------------------------------------------- +# Edit Transition Content Dialog +#------------------------------------------------------------------------------- + +[wxID_TRANSITIONCONTENTDIALOG, wxID_TRANSITIONCONTENTDIALOGMAINPANEL, + wxID_TRANSITIONCONTENTDIALOGREFERENCE, wxID_TRANSITIONCONTENTDIALOGINLINE, + wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, +] = [wx.NewId() for _init_ctrls in range(6)] + +class TransitionContentDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_TRANSITIONCONTENTDIALOG, + name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(300, 200), style=wx.DEFAULT_DIALOG_STYLE, + title='Edit transition') + self.SetClientSize(wx.Size(300, 200)) + + self.MainPanel = wx.Panel(id=wxID_TRANSITIONCONTENTDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.radioButton1 = wx.RadioButton(id=wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, + label='Reference', name='radioButton1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(114, 24), style=0) + EVT_RADIOBUTTON(self, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, self.OnTypeChanged) + self.radioButton1.SetValue(True) + + self.Reference = wx.Choice(id=wxID_TRANSITIONCONTENTDIALOGREFERENCE, + name='Reference', parent=self.MainPanel, pos=wx.Point(48, 48), + size=wx.Size(200, 24), style=0) + + self.radioButton2 = wx.RadioButton(id=wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, + label='Inline', name='radioButton2', parent=self.MainPanel, + pos=wx.Point(24, 72), size=wx.Size(114, 24), style=0) + EVT_RADIOBUTTON(self, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, self.OnTypeChanged) + self.radioButton2.SetValue(False) + + self.Inline = wx.TextCtrl(id=wxID_TRANSITIONCONTENTDIALOGINLINE, + name='Inline', parent=self.MainPanel, pos=wx.Point(48, 96), + size=wx.Size(200, 24), style=0) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + + EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK) + + def OnOK(self, event): + error = [] + if self.radioButton1.GetValue() and self.Reference.GetStringSelection() == "": + error.append("Reference") + if self.radioButton2.GetValue() and self.Inline.GetValue() == "": + error.append("Inline") + if len(error) > 0: + text = "" + for i, item in enumerate(error): + if i == 0: + text += item + elif i == len(error) - 1: + text += " and %s"%item + else: + text += ", %s"%item + message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + else: + self.EndModal(wxID_OK) + + def OnTypeChanged(self, event): + if self.radioButton1.GetValue(): + self.Reference.Enable(True) + self.Inline.Enable(False) + else: + self.Reference.Enable(False) + self.Inline.Enable(True) + event.Skip() + + def SetTransitions(self, transitions): + for transition in transitions: + self.Reference.Append(transition) + + def SetValues(self, values): + if values["type"] == "reference": + self.radioButton1.SetValue(True) + self.radioButton2.SetValue(False) + self.Reference.Enable(True) + self.Inline.Enable(False) + self.Reference.SetStringSelection(values["value"]) + elif values["type"] == "inline": + self.radioButton1.SetValue(False) + self.radioButton2.SetValue(True) + self.Reference.Enable(False) + self.Inline.Enable(True) + self.Inline.SetValue(values["value"]) + + def GetValues(self): + values = {} + if self.radioButton1.GetValue(): + values["type"] = "reference" + values["value"] = self.Reference.GetStringSelection() + else: + values["type"] = "inline" + values["value"] = self.Inline.GetValue() + return values + +#------------------------------------------------------------------------------- +# Create New Divergence Dialog +#------------------------------------------------------------------------------- + +[wxID_DIVERGENCECREATEDIALOG, wxID_DIVERGENCECREATEDIALOGMAINPANEL, + wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, + wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, + wxID_DIVERGENCECREATEDIALOGSEQUENCES, wxID_DIVERGENCECREATEDIALOGPREVIEW, + wxID_DIVERGENCECREATEDIALOGSTATICTEXT1, wxID_DIVERGENCECREATEDIALOGSTATICTEXT2, + wxID_DIVERGENCECREATEDIALOGSTATICTEXT3, +] = [wx.NewId() for _init_ctrls in range(11)] + +class DivergenceCreateDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_DIVERGENCECREATEDIALOG, + name='DivergencePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE, + title='Create a new divergence or convergence') + self.SetClientSize(wx.Size(500, 260)) + + self.MainPanel = wx.Panel(id=wxID_DIVERGENCECREATEDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(600, 220), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticText1 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT1, + label='Type:', name='staticText1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(200, 17), style=0) + + self.radioButton1 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, + label='Selection Divergence', name='radioButton1', parent=self.MainPanel, + pos=wx.Point(24, 48), size=wx.Size(200, 24), style=0) + EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, self.OnTypeChanged) + self.radioButton1.SetValue(True) + + self.radioButton2 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, + label='Selection Convergence', name='radioButton2', parent=self.MainPanel, + pos=wx.Point(24, 72), size=wx.Size(200, 24), style=0) + EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, self.OnTypeChanged) + self.radioButton2.SetValue(False) + + self.radioButton3 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, + label='Simultaneous Divergence', name='radioButton3', parent=self.MainPanel, + pos=wx.Point(24, 96), size=wx.Size(200, 24), style=0) + EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, self.OnTypeChanged) + self.radioButton3.SetValue(False) + + self.radioButton4 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, + label='Simultaneous Convergence', name='radioButton4', parent=self.MainPanel, + pos=wx.Point(24, 120), size=wx.Size(200, 24), style=0) + EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, self.OnTypeChanged) + self.radioButton4.SetValue(False) + + self.staticText2 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT2, + label='Number of sequences:', name='staticText2', parent=self.MainPanel, + pos=wx.Point(24, 150), size=wx.Size(200, 17), style=0) + + self.Sequences = wx.SpinCtrl(id=wxID_DIVERGENCECREATEDIALOGSEQUENCES, + name='Sequences', parent=self.MainPanel, pos=wx.Point(24, 174), + size=wx.Size(200, 24), style=0, min=2, max=20) + EVT_SPINCTRL(self, wxID_DIVERGENCECREATEDIALOGSEQUENCES, self.OnSequencesChanged) + + self.staticText3 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT3, + label='Preview:', name='staticText3', parent=self.MainPanel, + pos=wx.Point(250, 24), size=wx.Size(100, 17), style=0) + + self.Preview = wx.Panel(id=wxID_DIVERGENCECREATEDIALOGPREVIEW, + name='Preview', parent=self.MainPanel, pos=wx.Point(250, 48), + size=wx.Size(225, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) + self.Preview.SetBackgroundColour(wxColour(255,255,255)) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + + self.Divergence = None + self.MinSize = (0, 0) + + EVT_PAINT(self, self.OnPaint) + + def GetValues(self): + values = {} + if self.radioButton1.GetValue(): + values["type"] = SELECTION_DIVERGENCE + elif self.radioButton2.GetValue(): + values["type"] = SELECTION_CONVERGENCE + elif self.radioButton3.GetValue(): + values["type"] = SIMULTANEOUS_DIVERGENCE + else: + values["type"] = SIMULTANEOUS_CONVERGENCE + values["number"] = self.Sequences.GetValue() + return values + + def SetMinSize(self, size): + self.MinSize = size + + def OnTypeChanged(self, event): + self.RefreshPreview() + event.Skip() + + def OnSequencesChanged(self, event): + self.RefreshPreview() + event.Skip() + + def RefreshPreview(self): + dc = wxClientDC(self.Preview) + dc.Clear() + if self.radioButton1.GetValue(): + self.Divergence = SFC_Divergence(self.Preview, SELECTION_DIVERGENCE, self.Sequences.GetValue()) + elif self.radioButton2.GetValue(): + self.Divergence = SFC_Divergence(self.Preview, SELECTION_CONVERGENCE, self.Sequences.GetValue()) + elif self.radioButton3.GetValue(): + self.Divergence = SFC_Divergence(self.Preview, SIMULTANEOUS_DIVERGENCE, self.Sequences.GetValue()) + else: + self.Divergence = SFC_Divergence(self.Preview, SIMULTANEOUS_CONVERGENCE, self.Sequences.GetValue()) + width, height = self.Divergence.GetSize() + min_width, min_height = max(width, self.MinSize[0]), max(height, self.MinSize[1]) + self.Divergence.SetSize(min_width, min_height) + clientsize = self.Preview.GetClientSize() + x = (clientsize.width - min_width) / 2 + y = (clientsize.height - min_height) / 2 + self.Divergence.SetPosition(x, y) + self.Divergence.Draw(dc) + + def OnPaint(self, event): + self.RefreshPreview() + + +#------------------------------------------------------------------------------- +# Action Block Dialog +#------------------------------------------------------------------------------- + +class ActionTable(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 + # 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 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 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.Parent.ColAlignements[col], wxALIGN_CENTRE) + grid.SetColAttr(col, attr) + grid.SetColSize(col, self.Parent.ColSizes[col]) + + typelist = None + accesslist = None + for row in range(self.GetNumberRows()): + for col in range(self.GetNumberCols()): + editor = None + renderer = None + readonly = False + colname = self.GetColLabelValue(col) + if colname == "Qualifier": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.QualifierList) + if colname == "Duration": + editor = wxGridCellTextEditor() + renderer = wxGridCellStringRenderer() + if self.Parent.DurationList[self.data[row]["Qualifier"]]: + readonly = False + else: + readonly = True + self.data[row]["Duration"] = "" + elif colname == "Type": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.TypeList) + elif colname == "Value": + type = self.data[row]["Type"] + if type == "Action": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.ActionList) + elif type == "Variable": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.VariableList) + elif type == "Inline": + editor = wxGridCellTextEditor() + renderer = wxGridCellStringRenderer() + elif colname == "Indicator": + editor = wxGridCellChoiceEditor() + editor.SetParameters(self.Parent.VariableList) + + grid.SetCellEditor(row, col, editor) + grid.SetCellRenderer(row, col, renderer) + grid.SetReadOnly(row, col, readonly) + + 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_ACTIONBLOCKDIALOG, wxID_ACTIONBLOCKDIALOGMAINPANEL, + wxID_ACTIONBLOCKDIALOGVARIABLESGRID, wxID_ACTIONBLOCKDIALOGSTATICTEXT1, + wxID_ACTIONBLOCKDIALOGADDBUTTON,wxID_ACTIONBLOCKDIALOGDELETEBUTTON, + wxID_ACTIONBLOCKDIALOGUPBUTTON, wxID_ACTIONBLOCKDIALOGDOWNBUTTON, +] = [wx.NewId() for _init_ctrls in range(8)] + +class ActionBlockDialog(wx.Dialog): + def _init_coll_flexGridSizer1_Items(self, parent): + # generated method, don't edit + + parent.AddWindow(self.MainPanel, 0, border=0, flag=0) + + def _init_sizers(self): + # generated method, don't edit + self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) + + self.SetSizer(self.flexGridSizer1) + + def _init_ctrls(self, prnt): + # generated method, don't edit + wx.Dialog.__init__(self, id=wxID_ACTIONBLOCKDIALOG, + name='ActionBlockDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE, + title='Edit action block properties') + self.SetClientSize(wx.Size(500, 300)) + + self.MainPanel = wx.Panel(id=wxID_ACTIONBLOCKDIALOGMAINPANEL, + name='MainPanel', parent=self, pos=wx.Point(0, 0), + size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL) + self.MainPanel.SetAutoLayout(True) + + self.staticText1 = wx.StaticText(id=wxID_ACTIONBLOCKDIALOGSTATICTEXT1, + label='Actions:', name='staticText1', parent=self.MainPanel, + pos=wx.Point(24, 24), size=wx.Size(95, 17), style=0) + + self.ActionsGrid = wx.grid.Grid(id=wxID_ACTIONBLOCKDIALOGVARIABLESGRID, + name='ActionsGrid', parent=self.MainPanel, pos=wx.Point(24, 44), + size=wx.Size(450, 150), style=wxVSCROLL) + self.ActionsGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, + 'Sans')) + self.ActionsGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, + False, 'Sans')) + self.ActionsGrid.DisableDragGridSize() + self.ActionsGrid.EnableScrolling(False, True) + EVT_GRID_CELL_CHANGE(self.ActionsGrid, self.OnActionsGridCellChange) + + self.AddButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGADDBUTTON, label='Add', + name='AddButton', parent=self.MainPanel, pos=wx.Point(245, 204), + size=wx.Size(72, 32), style=0) + EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGADDBUTTON, self.OnAddButton) + + self.DeleteButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGDELETEBUTTON, label='Delete', + name='DeleteButton', parent=self.MainPanel, pos=wx.Point(325, 204), + size=wx.Size(72, 32), style=0) + EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGDELETEBUTTON, self.OnDeleteButton) + + self.UpButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGUPBUTTON, label='^', + name='UpButton', parent=self.MainPanel, pos=wx.Point(405, 204), + size=wx.Size(32, 32), style=0) + EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGUPBUTTON, self.OnUpButton) + + self.DownButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGDOWNBUTTON, label='v', + name='DownButton', parent=self.MainPanel, pos=wx.Point(445, 204), + size=wx.Size(32, 32), style=0) + EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGDOWNBUTTON, self.OnDownButton) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) + self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) + + self.DefaultValue = {"Qualifier" : "N", "Duration" : "", "Type" : "Action", "Value" : "", "Indicator" : ""} + self.Table = ActionTable(self, [], ["Qualifier","Duration","Type","Value","Indicator"]) + self.TypeList = "Action,Variable,Inline" + self.ColSizes = [60, 90, 80, 110, 80] + self.ColAlignements = [wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT] + + self.ActionsGrid.SetTable(self.Table) + self.ActionsGrid.SetRowLabelSize(0) + + self.Table.ResetView(self.ActionsGrid) + + def OnAddButton(self, event): + self.Table.AppendRow(self.DefaultValue.copy()) + self.Table.ResetView(self.ActionsGrid) + event.Skip() + + def OnDeleteButton(self, event): + row = self.ActionsGrid.GetGridCursorRow() + self.Table.RemoveRow(row) + self.Table.ResetView(self.ActionsGrid) + event.Skip() + + def OnUpButton(self, event): + row = self.ActionsGrid.GetGridCursorRow() + self.Table.MoveRow(row, -1, self.ActionsGrid) + self.Table.ResetView(self.ActionsGrid) + event.Skip() + + def OnDownButton(self, event): + row = self.ActionsGrid.GetGridCursorRow() + self.Table.MoveRow(row, 1, self.ActionsGrid) + self.Table.ResetView(self.ActionsGrid) + event.Skip() + + def OnActionsGridCellChange(self, event): + self.Table.ResetView(self.ActionsGrid) + event.Skip() + + def SetQualifierList(self, list): + self.QualifierList = "" + sep = "" + for qualifier in list.keys(): + self.QualifierList += "%s%s"%(sep, qualifier) + sep = "," + self.DurationList = list + + def SetVariableList(self, list): + self.VariableList = "" + sep = "" + for variable in list: + self.VariableList += "%s%s"%(sep, variable["Name"]) + sep = "," + + def SetActionList(self, list): + self.ActionList = "" + sep = "" + for action in list: + self.ActionList += "%s%s"%(sep, action) + sep = "," + + def SetValues(self, actions): + for action in actions: + row = {"Qualifier" : action["qualifier"], "Value" : action["value"]} + if action["type"] == "reference": + if action["value"] in self.ActionList: + row["Type"] = "Action" + elif action["value"] in self.VariableList: + row["Type"] = "Variable" + else: + row["Type"] = "Inline" + else: + row["Type"] = "Inline" + if "duration" in action: + row["Duration"] = action["duration"] + else: + row["Duration"] = "" + if "indicator" in action: + row["Indicator"] = action["indicator"] + else: + row["Indicator"] = "" + self.Table.AppendRow(row) + self.Table.ResetView(self.ActionsGrid) + + def GetValues(self): + values = [] + for data in self.Table.GetData(): + print data + action = {"qualifier" : data["Qualifier"], "value" : data["Value"]} + if data["Type"] in ["Action", "Variable"]: + action["type"] = "reference" + else: + action["type"] = "inline" + if data["Duration"] != "": + action["duration"] = data["Duration"] + if data["Indicator"] != "": + action["indicator"] = data["Indicator"] + values.append(action) + return values + + +#------------------------------------------------------------------------------- +# Edit Step Name Dialog +#------------------------------------------------------------------------------- + +class StepNameDialog(wxTextEntryDialog): + + def __init__(self, parent, message, caption = "Please enter text", defaultValue = "", + style = wxOK|wxCANCEL|wxCENTRE, pos = wxDefaultPosition): + wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) + + self.PouNames = [] + self.Variables = [] + self.StepNames = [] + + EVT_BUTTON(self, self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId(), self.OnOK) + + def OnOK(self, event): + step_name = self.GetSizer().GetItem(1).GetWindow().GetValue() + if step_name == "": + message = wxMessageDialog(self, "You must type a name!", "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + elif not TestIdentifier(step_name): + message = wxMessageDialog(self, "\"%s\" is not a valid identifier!"%step_name, "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + elif step_name.upper() in IEC_KEYWORDS: + message = wxMessageDialog(self, "\"%s\" is a keyword. It can't be used!"%step_name, "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + elif step_name.upper() in self.PouNames: + message = wxMessageDialog(self, "A pou with \"%s\" as name exists!"%step_name, "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + elif step_name.upper() in self.Variables: + message = wxMessageDialog(self, "A variable with \"%s\" as name exists!"%step_name, "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + elif step_name.upper() in self.StepNames: + message = wxMessageDialog(self, "\"%s\" step already exists!"%step_name, "Error", wxOK|wxICON_ERROR) + message.ShowModal() + message.Destroy() + else: + self.EndModal(wxID_OK) + + def SetPouNames(self, pou_names): + self.PouNames = [pou_name.upper() for pou_name in pou_names] + + def SetVariables(self, variables): + self.Variables = [var["Name"].upper() for var in variables] + + def SetStepNames(self, step_names): + self.StepNames = [step_name.upper() for step_name in step_names] + diff -r 36d378bd852e -r dae55dd9ee14 FBDViewer.py --- a/FBDViewer.py Sat Jul 07 11:35:17 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,905 +0,0 @@ -#!/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 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 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 * -import wx - -from plcopen.structures import * -from graphics.GraphicCommons import * -from graphics.FBD_Objects import * -from Viewer import * - -class FBD_Viewer(Viewer): - - def __init__(self, parent, window, controler): - Viewer.__init__(self, parent, window, controler) - -#------------------------------------------------------------------------------- -# Mouse event functions -#------------------------------------------------------------------------------- - - def OnViewerLeftDown(self, event): - if self.Mode == MODE_SELECTION: - pos = event.GetPosition() - if event.ControlDown() and self.SelectedElement: - element = self.FindElement(pos, True) - if element: - if isinstance(self.SelectedElement, Graphic_Group): - self.SelectedElement.SetSelected(False) - self.SelectedElement.SelectElement(element) - elif self.SelectedElement: - group = Graphic_Group(self) - group.SelectElement(self.SelectedElement) - group.SelectElement(element) - self.SelectedElement = group - elements = self.SelectedElement.GetElements() - if len(elements) == 0: - self.SelectedElement = element - elif len(elements) == 1: - self.SelectedElement = elements[0] - self.SelectedElement.SetSelected(True) - else: - element = self.FindElement(pos) - if self.SelectedElement and self.SelectedElement != element: - self.SelectedElement.SetSelected(False) - self.SelectedElement = None - self.Refresh() - if element: - self.SelectedElement = element - self.SelectedElement.OnLeftDown(event, self.Scaling) - self.Refresh() - else: - self.rubberBand.Reset() - self.rubberBand.OnLeftDown(event, self.Scaling) - elif self.Mode in [MODE_BLOCK,MODE_VARIABLE,MODE_CONNECTION,MODE_COMMENT]: - self.rubberBand.Reset() - self.rubberBand.OnLeftDown(event, self.Scaling) - elif self.Mode == MODE_WIRE: - pos = GetScaledEventPosition(event, self.Scaling) - connector = self.FindBlockConnector(pos) - if connector: - if (connector.GetDirection() == EAST): - wire = Wire(self, [wxPoint(pos.x, pos.y), EAST], [wxPoint(pos.x, pos.y), WEST]) - else: - wire = Wire(self, [wxPoint(pos.x, pos.y), WEST], [wxPoint(pos.x, pos.y), EAST]) - wire.oldPos = pos - wire.Handle = (HANDLE_POINT, 0) - wire.ProcessDragging(0, 0) - wire.Handle = (HANDLE_POINT, 1) - self.Wires.append(wire) - self.Elements.append(wire) - if self.SelectedElement: - self.SelectedElement.SetSelected(False) - self.SelectedElement = wire - elif self.SelectedElement: - self.SelectedElement.SetSelected(False) - self.SelectedElement = None - self.Refresh() - event.Skip() - - def OnViewerLeftUp(self, event): - if self.rubberBand.IsShown(): - if self.Mode == MODE_SELECTION: - elements = self.SearchElements(self.rubberBand.GetCurrentExtent()) - self.rubberBand.OnLeftUp(event, self.Scaling) - if len(elements) > 0: - self.SelectedElement = Graphic_Group(self) - self.SelectedElement.SetElements(elements) - self.SelectedElement.SetSelected(True) - self.Refresh() - elif self.Mode == MODE_BLOCK: - bbox = self.rubberBand.GetCurrentExtent() - self.rubberBand.OnLeftUp(event, self.Scaling) - wxCallAfter(self.AddNewBlock, bbox) - elif self.Mode == MODE_VARIABLE: - bbox = self.rubberBand.GetCurrentExtent() - self.rubberBand.OnLeftUp(event, self.Scaling) - wxCallAfter(self.AddNewVariable, bbox) - elif self.Mode == MODE_CONNECTION: - bbox = self.rubberBand.GetCurrentExtent() - self.rubberBand.OnLeftUp(event, self.Scaling) - wxCallAfter(self.AddNewConnection, bbox) - elif self.Mode == MODE_COMMENT: - bbox = self.rubberBand.GetCurrentExtent() - self.rubberBand.OnLeftUp(event, self.Scaling) - wxCallAfter(self.AddNewComment, bbox) - elif self.Mode == MODE_SELECTION and self.SelectedElement: - self.SelectedElement.OnLeftUp(event, self.Scaling) - wxCallAfter(self.SetCursor, wxNullCursor) - self.ReleaseMouse() - self.Refresh() - elif self.Mode == MODE_WIRE and self.SelectedElement: - pos = GetScaledEventPosition(event, self.Scaling) - connector = self.FindBlockConnector(pos, False) - if connector and connector != self.SelectedElement.StartConnected: - self.SelectedElement.ResetPoints() - self.SelectedElement.OnMotion(event, self.Scaling) - self.SelectedElement.GeneratePoints() - self.SelectedElement.RefreshModel() - self.SelectedElement.SetSelected(True) - else: - self.SelectedElement.Delete() - self.SelectedElement = None - self.Refresh() - if not self.SavedMode: - wxCallAfter(self.Parent.ResetCurrentMode) - event.Skip() - - def OnViewerRightUp(self, event): - pos = event.GetPosition() - element = self.FindElement(pos) - if element: - if self.SelectedElement and self.SelectedElement != element: - self.SelectedElement.SetSelected(False) - self.SelectedElement = element - self.SelectedElement.SetSelected(True) - self.SelectedElement.OnRightUp(event, self.Scaling) - wxCallAfter(self.SetCursor, wxNullCursor) - self.ReleaseMouse() - self.Refresh() - event.Skip() - - def OnViewerLeftDClick(self, event): - if self.Mode == MODE_SELECTION and self.SelectedElement: - self.SelectedElement.OnLeftDClick(event, self.Scaling) - self.Refresh() - event.Skip() - - def OnViewerMotion(self, event): - if self.rubberBand.IsShown(): - self.rubberBand.OnMotion(event, self.Scaling) - elif self.Mode == MODE_SELECTION and self.SelectedElement: - self.SelectedElement.OnMotion(event, self.Scaling) - self.Refresh() - elif self.Mode == MODE_WIRE and self.SelectedElement: - pos = GetScaledEventPosition(event, self.Scaling) - connector = self.FindBlockConnector(pos, False) - if not connector or self.SelectedElement.EndConnected == None: - self.SelectedElement.ResetPoints() - self.SelectedElement.OnMotion(event, self.Scaling) - self.SelectedElement.GeneratePoints() - self.Refresh() - event.Skip() - -#------------------------------------------------------------------------------- -# Keyboard event functions -#------------------------------------------------------------------------------- - - def OnChar(self, event): - keycode = event.GetKeyCode() - if self.Scaling: - scaling = self.Scaling - else: - scaling = (8, 8) - if keycode == WXK_DELETE and self.SelectedElement: - self.SelectedElement.Clean() - self.SelectedElement.Delete() - self.SelectedElement = None - elif keycode == WXK_LEFT and self.SelectedElement: - self.SelectedElement.Move(-scaling[0], 0) - elif keycode == WXK_RIGHT and self.SelectedElement: - self.SelectedElement.Move(scaling[0], 0) - elif keycode == WXK_UP and self.SelectedElement: - self.SelectedElement.Move(0, -scaling[1]) - elif keycode == WXK_DOWN and self.SelectedElement: - self.SelectedElement.Move(0, scaling[1]) - self.Refresh() - event.Skip() - -#------------------------------------------------------------------------------- -# Adding element functions -#------------------------------------------------------------------------------- - - def AddNewBlock(self, bbox): - dialog = BlockPropertiesDialog(self.Parent) - dialog.SetBlockList(self.Controler.GetBlockTypes()) - dialog.SetMinBlockSize((bbox.width, bbox.height)) - if dialog.ShowModal() == wxID_OK: - id = self.GetNewId() - values = dialog.GetValues() - if "name" in values: - block = FBD_Block(self, values["type"], values["name"], id, values["extension"]) - else: - block = FBD_Block(self, values["type"], "", id, values["extension"]) - block.SetPosition(bbox.x, bbox.y) - block.SetSize(values["width"], values["height"]) - self.Blocks.append(block) - self.Elements.append(block) - self.Controler.AddCurrentElementEditingBlock(id) - self.RefreshBlockModel(block) - self.Refresh() - dialog.Destroy() - - def AddNewVariable(self, bbox): - dialog = VariablePropertiesDialog(self.Parent) - dialog.SetMinVariableSize((bbox.width, bbox.height)) - varlist = [] - vars = self.Controler.GetCurrentElementEditingInterfaceVars() - if vars: - for var in vars: - varlist.append((var["Name"], var["Class"], var["Type"])) - returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() - if returntype: - varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) - dialog.SetVariables(varlist) - if dialog.ShowModal() == wxID_OK: - id = self.GetNewId() - values = dialog.GetValues() - variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id) - variable.SetPosition(bbox.x, bbox.y) - variable.SetSize(values["width"], values["height"]) - self.Blocks.append(variable) - self.Elements.append(variable) - self.Controler.AddCurrentElementEditingVariable(id, values["type"]) - self.RefreshVariableModel(variable) - self.Refresh() - dialog.Destroy() - - def AddNewConnection(self, bbox): - dialog = ConnectionPropertiesDialog(self.Parent) - dialog.SetMinConnectionSize((bbox.width, bbox.height)) - if dialog.ShowModal() == wxID_OK: - id = self.GetNewId() - values = dialog.GetValues() - connection = FBD_Connection(self, values["type"], values["name"], id) - connection.SetPosition(bbox.x, bbox.y) - connection.SetSize(values["width"], values["height"]) - self.Blocks.append(connection) - self.Elements.append(connection) - self.Controler.AddCurrentElementEditingConnection(id, values["type"]) - self.RefreshConnectionModel(connection) - self.Refresh() - dialog.Destroy() - - def AddNewComment(self, bbox): - dialog = wxTextEntryDialog(self.Parent, "Add a new comment", "Please enter comment text", "", wxOK|wxCANCEL|wxTE_MULTILINE) - if dialog.ShowModal() == wxID_OK: - value = dialog.GetValue() - id = self.GetNewId() - comment = Comment(self, value, id) - comment.SetPosition(bbox.x, bbox.y) - min_width, min_height = comment.GetMinSize() - comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height)) - self.Elements.append(comment) - self.Controler.AddCurrentElementEditingComment(id) - self.RefreshCommentModel(comment) - self.Refresh() - dialog.Destroy() - -#------------------------------------------------------------------------------- -# Delete element functions -#------------------------------------------------------------------------------- - - def DeleteBlock(self, block): - wires = [] - for output in block.GetConnectors()["outputs"]: - wires.extend([wire[0] for wire in output.GetWires()]) - block.Clean() - self.Blocks.remove(block) - self.Elements.remove(block) - self.Controler.RemoveCurrentElementEditingInstance(block.GetId()) - for wire in wires: - wire.RefreshModel() - - def DeleteVariable(self, variable): - wires = [] - if variable.GetType() == INPUT: - connector = variable.GetConnector() - wires.extend([wire[0] for wire in connector.GetWires()]) - variable.Clean() - self.Blocks.remove(variable) - self.Elements.remove(variable) - self.Controler.RemoveCurrentElementEditingInstance(variable.GetId()) - for wire in wires: - wire.RefreshModel() - - def DeleteConnection(self, connection): - wires = [] - if connection.GetType() == CONTINUATION: - connector = connection.GetConnector() - wires.extend([wire[0] for wire in connector.GetWires()]) - connection.Clean() - self.Blocks.remove(connection) - self.Elements.remove(connection) - self.Controler.RemoveCurrentElementEditingInstance(connection.GetId()) - for wire in wires: - wire.RefreshModel() - - def DeleteComment(self, comment): - self.Elements.remove(comment) - self.Controler.RemoveCurrentElementEditingInstance(comment.GetId()) - - def DeleteWire(self, wire): - connected = wire.GetConnected() - wire.Clean() - self.Wires.remove(wire) - self.Elements.remove(wire) - for connector in connected: - connector.RefreshParentBlock() - -#------------------------------------------------------------------------------- -# Edit element content functions -#------------------------------------------------------------------------------- - - def EditBlockContent(self, block): - dialog = BlockPropertiesDialog(self.Parent) - dialog.SetBlockList(self.Controler.GetBlockTypes()) - dialog.SetMinBlockSize(block.GetSize()) - values = {"name" : block.GetName(), "type" : block.GetType()} - values["extension"] = block.GetExtension() - dialog.SetValues(values) - if dialog.ShowModal() == wxID_OK: - values = dialog.GetValues() - if "name" in values: - block.SetName(values["name"]) - block.SetExtension(values["extension"]) - block.SetSize(values["width"], values["height"]) - block.SetType(values["type"]) - self.RefreshBlockModel(block) - self.Refresh() - dialog.Destroy() - - def EditVariableContent(self, variable): - dialog = VariablePropertiesDialog(self.Parent) - dialog.SetMinVariableSize(variable.GetSize()) - varlist = [] - vars = self.Controler.GetCurrentElementEditingInterfaceVars() - if vars: - for var in vars: - varlist.append((var["Name"], var["Class"], var["Type"])) - returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() - if returntype: - varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) - dialog.SetVariables(varlist) - values = {"name" : variable.GetName(), "type" : variable.GetType()} - dialog.SetValues(values) - if dialog.ShowModal() == wxID_OK: - old_type = variable.GetType() - values = dialog.GetValues() - variable.SetName(values["name"]) - variable.SetType(values["type"], values["value_type"]) - variable.SetSize(values["width"], values["height"]) - if old_type != values["type"]: - id = variable.GetId() - self.Controler.RemoveCurrentElementEditingInstance(id) - self.Controler.AddCurrentElementEditingVariable(id, values["type"]) - self.RefreshVariableModel(variable) - self.Refresh() - dialog.Destroy() - -#------------------------------------------------------------------------------- -# Create New Block Dialog -#------------------------------------------------------------------------------- - -[wxID_BLOCKPROPERTIESDIALOG, wxID_BLOCKPROPERTIESDIALOGMAINPANEL, - wxID_BLOCKPROPERTIESDIALOGNAME, wxID_BLOCKPROPERTIESDIALOGTYPETREE, - wxID_BLOCKPROPERTIESDIALOGTYPEDESC, wxID_BLOCKPROPERTIESDIALOGINPUTS, - wxID_BLOCKPROPERTIESDIALOGPREVIEW, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, - wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, wxID_BLOCKPROPERTIESDIALOGSTATICTEXT3, - wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, -] = [wx.NewId() for _init_ctrls in range(11)] - -[CATEGORY, BLOCK] = range(2) - -class BlockPropertiesDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_BLOCKPROPERTIESDIALOG, - name='BlockPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(600, 360), style=wx.DEFAULT_DIALOG_STYLE, - title='Block Properties') - self.SetClientSize(wx.Size(600, 360)) - - self.MainPanel = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(600, 320), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.staticbox1 = wx.StaticBox(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT1, - label='Type:', name='staticBox1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(245, 280), style=0) - - self.staticText2 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, - label='Name:', name='staticText2', parent=self.MainPanel, - pos=wx.Point(274, 24), size=wx.Size(70, 17), style=0) - - self.staticText3 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT2, - label='Inputs:', name='staticText4', parent=self.MainPanel, - pos=wx.Point(424, 24), size=wx.Size(70, 17), style=0) - - self.staticText4 = wx.StaticText(id=wxID_BLOCKPROPERTIESDIALOGSTATICTEXT4, - label='Preview:', name='staticText4', parent=self.MainPanel, - pos=wx.Point(274, 80), size=wx.Size(100, 17), style=0) - - self.TypeTree = wx.TreeCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPETREE, - name='TypeTree', parent=self.MainPanel, pos=wx.Point(34, 44), - size=wx.Size(225, 180), style=wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER) - EVT_TREE_SEL_CHANGED(self, wxID_BLOCKPROPERTIESDIALOGTYPETREE, self.OnTypeTreeItemSelected) - - self.TypeDesc = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGTYPEDESC, - name='TypeDesc', parent=self.MainPanel, pos=wx.Point(34, 230), - size=wx.Size(225, 65), style=wx.TE_READONLY|wx.TE_MULTILINE) - - self.Name = wx.TextCtrl(id=wxID_BLOCKPROPERTIESDIALOGNAME, value='', - name='Name', parent=self.MainPanel, pos=wx.Point(274, 48), - size=wx.Size(145, 24), style=0) - EVT_TEXT(self, wxID_BLOCKPROPERTIESDIALOGNAME, self.OnNameChanged) - - self.Inputs = wx.SpinCtrl(id=wxID_BLOCKPROPERTIESDIALOGINPUTS, - name='Inputs', parent=self.MainPanel, pos=wx.Point(424, 48), - size=wx.Size(145, 24), style=0, min=2, max=20) - EVT_SPINCTRL(self, wxID_BLOCKPROPERTIESDIALOGINPUTS, self.OnInputsChanged) - - self.Preview = wx.Panel(id=wxID_BLOCKPROPERTIESDIALOGPREVIEW, - name='Preview', parent=self.MainPanel, pos=wx.Point(274, 104), - size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.Preview.SetBackgroundColour(wxColour(255,255,255)) - - self._init_sizers() - - def __init__(self, parent): - self._init_ctrls(parent) - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - self.Name.SetValue("") - self.Name.Enable(False) - self.Inputs.Enable(False) - self.Block = None - self.MinBlockSize = None - - EVT_PAINT(self, self.OnPaint) - EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK) - - def FindTreeItem(self, root, name): - if root.IsOk(): - if self.TypeTree.GetItemText(root) == name: - return root - else: - item, root_cookie = self.TypeTree.GetFirstChild(root) - while item.IsOk(): - result = self.FindTreeItem(item, name) - if result: - return result - item, root_cookie = self.TypeTree.GetNextChild(root, root_cookie) - return None - - def OnOK(self, event): - error = [] - selected = self.TypeTree.GetSelection() - if not selected.IsOk() or self.TypeTree.GetItemParent(selected) == self.TypeTree.GetRootItem() or selected == self.TypeTree.GetRootItem(): - message = wxMessageDialog(self, "Form isn't complete. Valid block type must be selected!", "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - elif self.Name.IsEnabled() and self.Name.GetValue() == "": - message = wxMessageDialog(self, "Form isn't complete. Name must be filled!", "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - else: - self.EndModal(wxID_OK) - - def SetBlockList(self, blocktypes): - root = self.TypeTree.AddRoot("") - self.TypeTree.SetPyData(root, CATEGORY) - for category in blocktypes: - category_item = self.TypeTree.AppendItem(root, category["name"]) - self.TypeTree.SetPyData(category_item, CATEGORY) - for blocktype in category["list"]: - blocktype_item = self.TypeTree.AppendItem(category_item, blocktype["name"]) - self.TypeTree.SetPyData(blocktype_item, BLOCK) - - def SetMinBlockSize(self, size): - self.MinBlockSize = size - - def SetValues(self, values): - for name, value in values.items(): - if name == "type": - item = self.FindTreeItem(self.TypeTree.GetRootItem(), value) - if item: - self.TypeTree.SelectItem(item) - elif name == "name": - self.Name.SetValue(value) - elif name == "extension": - self.Inputs.SetValue(value) - self.RefreshPreview() - - def GetValues(self): - values = {} - values["type"] = self.TypeTree.GetItemText(self.TypeTree.GetSelection()) - if self.Name.GetValue() != "": - values["name"] = self.Name.GetValue() - values["width"], values["height"] = self.Block.GetSize() - values["extension"] = self.Inputs.GetValue() - return values - - def OnTypeTreeItemSelected(self, event): - self.Name.SetValue("") - selected = event.GetItem() - if self.TypeTree.GetPyData(selected) != CATEGORY: - blocktype = GetBlockType(self.TypeTree.GetItemText(selected)) - if blocktype: - self.Inputs.SetValue(len(blocktype["inputs"])) - self.Inputs.Enable(blocktype["extensible"]) - self.Name.Enable(blocktype["type"] != "function") - self.TypeDesc.SetValue(blocktype["comment"]) - wxCallAfter(self.RefreshPreview) - else: - self.Name.Enable(False) - self.Inputs.Enable(False) - self.Inputs.SetValue(2) - self.TypeDesc.SetValue("") - wxCallAfter(self.ErasePreview) - else: - self.Name.Enable(False) - self.Inputs.Enable(False) - self.Inputs.SetValue(2) - self.TypeDesc.SetValue("") - wxCallAfter(self.ErasePreview) - event.Skip() - - def OnNameChanged(self, event): - if self.Name.IsEnabled(): - self.RefreshPreview() - event.Skip() - - def OnInputsChanged(self, event): - if self.Inputs.IsEnabled(): - self.RefreshPreview() - event.Skip() - - def ErasePreview(self): - dc = wxClientDC(self.Preview) - dc.Clear() - self.Block = None - - def RefreshPreview(self): - dc = wxClientDC(self.Preview) - dc.Clear() - item = self.TypeTree.GetSelection() - if self.TypeTree.GetPyData(item) == CATEGORY: - self.Block = None - else: - blocktype = self.TypeTree.GetItemText(item) - if blocktype: - self.Block = FBD_Block(self.Preview, blocktype, self.Name.GetValue(), extension = self.Inputs.GetValue()) - width, height = self.MinBlockSize - min_width, min_height = self.Block.GetMinSize() - width, height = max(min_width, width), max(min_height, height) - self.Block.SetSize(width, height) - clientsize = self.Preview.GetClientSize() - x = (clientsize.width - width) / 2 - y = (clientsize.height - height) / 2 - self.Block.SetPosition(x, y) - self.Block.Draw(dc) - else: - self.Block = None - - def OnPaint(self, event): - if self.Block: - self.RefreshPreview() - - -#------------------------------------------------------------------------------- -# Create New Variable Dialog -#------------------------------------------------------------------------------- - -[wxID_VARIABLEPROPERTIESDIALOG, wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, - wxID_VARIABLEPROPERTIESDIALOGNAME, wxID_VARIABLEPROPERTIESDIALOGCLASS, - wxID_VARIABLEPROPERTIESDIALOGPREVIEW, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, - wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, -] = [wx.NewId() for _init_ctrls in range(8)] - -class VariablePropertiesDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_VARIABLEPROPERTIESDIALOG, - name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(400, 320), style=wx.DEFAULT_DIALOG_STYLE, - title='Variable Properties') - self.SetClientSize(wx.Size(400, 320)) - - self.MainPanel = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(400, 280), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.staticText1 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT1, - label='Class:', name='staticText1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) - - self.staticText2 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT2, - label='Name:', name='staticText2', parent=self.MainPanel, - pos=wx.Point(204, 24), size=wx.Size(70, 17), style=0) - - self.staticText3 = wx.StaticText(id=wxID_VARIABLEPROPERTIESDIALOGSTATICTEXT3, - label='Preview:', name='staticText3', parent=self.MainPanel, - pos=wx.Point(24, 78), size=wx.Size(100, 17), style=0) - - self.Class = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGCLASS, - name='Class', parent=self.MainPanel, pos=wx.Point(24, 48), - size=wx.Size(145, 24), style=0) - EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGCLASS, self.OnClassChanged) - - self.Name = wx.Choice(id=wxID_VARIABLEPROPERTIESDIALOGNAME, - name='Name', parent=self.MainPanel, pos=wx.Point(204, 48), - size=wx.Size(145, 24), style=0) - EVT_CHOICE(self, wxID_VARIABLEPROPERTIESDIALOGNAME, self.OnNameChanged) - - self.Preview = wx.Panel(id=wxID_VARIABLEPROPERTIESDIALOGPREVIEW, - name='Preview', parent=self.MainPanel, pos=wx.Point(24, 104), - size=wx.Size(350, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.Preview.SetBackgroundColour(wxColour(255,255,255)) - - self._init_sizers() - - def __init__(self, parent): - self._init_ctrls(parent) - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - self.Variable = None - self.VarList = [] - self.MinVariableSize = None - self.RefreshNameList() - - for choice in ["Input", "Output", "InOut"]: - self.Class.Append(choice) - self.Class.SetStringSelection("Input") - - EVT_PAINT(self, self.OnPaint) - - def RefreshNameList(self): - selected = self.Name.GetStringSelection() - self.Name.Clear() - for name, var_type, value_type in self.VarList: - if var_type in ["Local","Temp","Output","InOut"]: - self.Name.Append(name) - elif var_type == "Input" and self.Class.GetStringSelection() == "Input": - self.Name.Append(name) - if self.Name.FindString(selected) != wxNOT_FOUND: - self.Name.SetStringSelection(selected) - self.Name.Enable(self.Name.GetCount() > 0) - - def SetMinVariableSize(self, size): - self.MinVariableSize = size - - def SetVariables(self, vars): - self.VarList = vars - self.RefreshNameList() - - def SetValues(self, values): - for name, value in values.items(): - if name == "type": - if value == INPUT: - self.Class.SetStringSelection("Input") - if value == OUTPUT: - self.Class.SetStringSelection("Output") - if value == INOUT: - self.Class.SetStringSelection("InOut") - elif name == "name": - self.Name.SetStringSelection(value) - self.RefreshPreview() - - def GetValues(self): - values = {} - classtype = self.Class.GetStringSelection() - if classtype == "Input": - values["type"] = INPUT - elif classtype == "Output": - values["type"] = OUTPUT - elif classtype == "InOut": - values["type"] = INOUT - values["name"] = self.Name.GetStringSelection() - values["value_type"] = "" - for var_name, var_type, value_type in self.VarList: - if var_name == values["name"]: - values["value_type"] = value_type - values["width"], values["height"] = self.Variable.GetSize() - return values - - def OnClassChanged(self, event): - self.RefreshNameList() - self.RefreshPreview() - event.Skip() - - def OnNameChanged(self, event): - self.RefreshPreview() - event.Skip() - - def RefreshPreview(self): - dc = wxClientDC(self.Preview) - dc.Clear() - name = self.Name.GetStringSelection() - type = "" - for var_name, var_type, value_type in self.VarList: - if var_name == name: - type = value_type - classtype = self.Class.GetStringSelection() - if classtype == "Input": - self.Variable = FBD_Variable(self.Preview, INPUT, name, type) - elif classtype == "Output": - self.Variable = FBD_Variable(self.Preview, OUTPUT, name, type) - elif classtype == "InOut": - self.Variable = FBD_Variable(self.Preview, INOUT, name, type) - width, height = self.MinVariableSize - min_width, min_height = self.Variable.GetMinSize() - width, height = max(min_width, width), max(min_height, height) - self.Variable.SetSize(width, height) - clientsize = self.Preview.GetClientSize() - x = (clientsize.width - width) / 2 - y = (clientsize.height - height) / 2 - self.Variable.SetPosition(x, y) - self.Variable.Draw(dc) - - def OnPaint(self, event): - self.RefreshPreview() - -#------------------------------------------------------------------------------- -# Create New Connection Dialog -#------------------------------------------------------------------------------- - -[wxID_CONNECTIONPROPERTIESDIALOG, wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, - wxID_CONNECTIONPROPERTIESDIALOGNAME, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, - wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, - wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, - wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, -] = [wx.NewId() for _init_ctrls in range(9)] - -class ConnectionPropertiesDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_CONNECTIONPROPERTIESDIALOG, - name='ConnectionPropertiesDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(350, 220), style=wx.DEFAULT_DIALOG_STYLE, - title='Connection Properties') - self.SetClientSize(wx.Size(350, 220)) - - self.MainPanel = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(340, 360), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.staticText1 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT1, - label='Type:', name='staticText1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) - - self.staticText2 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT2, - label='Name:', name='staticText2', parent=self.MainPanel, - pos=wx.Point(24, 104), size=wx.Size(70, 17), style=0) - - self.staticText3 = wx.StaticText(id=wxID_CONNECTIONPROPERTIESDIALOGSTATICTEXT3, - label='Preview:', name='staticText3', parent=self.MainPanel, - pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) - - self.radioButton1 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, - label='Connector', name='radioButton1', parent=self.MainPanel, - pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) - EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON1, self.OnTypeChanged) - self.radioButton1.SetValue(True) - - self.radioButton2 = wx.RadioButton(id=wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, - label='Continuation', name='radioButton2', parent=self.MainPanel, - pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) - EVT_RADIOBUTTON(self, wxID_CONNECTIONPROPERTIESDIALOGRADIOBUTTON2, self.OnTypeChanged) - self.radioButton2.SetValue(False) - - self.Name = wx.TextCtrl(id=wxID_CONNECTIONPROPERTIESDIALOGNAME, - name='Name', parent=self.MainPanel, pos=wx.Point(24, 130), - size=wx.Size(145, 24), style=0) - EVT_TEXT(self, wxID_CONNECTIONPROPERTIESDIALOGNAME, self.OnNameChanged) - - self.Preview = wx.Panel(id=wxID_CONNECTIONPROPERTIESDIALOGPREVIEW, - name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), - size=wx.Size(150, 100), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.Preview.SetBackgroundColour(wxColour(255,255,255)) - - self._init_sizers() - - def __init__(self, parent): - self._init_ctrls(parent) - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - self.Connection = None - self.MinConnectionSize = None - - EVT_PAINT(self, self.OnPaint) - - def SetMinConnectionSize(self, size): - self.MinConnectionSize = size - - def GetValues(self): - values = {} - if self.radioButton1.GetValue(): - values["type"] = CONNECTOR - else: - values["type"] = CONTINUATION - values["name"] = self.Name.GetValue() - values["width"], values["height"] = self.Connection.GetSize() - return values - - def OnTypeChanged(self, event): - self.RefreshPreview() - event.Skip() - - def OnNameChanged(self, event): - self.RefreshPreview() - event.Skip() - - def RefreshPreview(self): - dc = wxClientDC(self.Preview) - dc.Clear() - if self.radioButton1.GetValue(): - self.Connection = FBD_Connector(self.Preview, CONNECTOR, self.Name.GetValue()) - else: - self.Connection = FBD_Connector(self.Preview, CONTINUATION, self.Name.GetValue()) - width, height = self.MinConnectionSize - min_width, min_height = self.Connection.GetMinSize() - width, height = max(min_width, width), max(min_height, height) - self.Connection.SetSize(width, height) - clientsize = self.Preview.GetClientSize() - x = (clientsize.width - width) / 2 - y = (clientsize.height - height) / 2 - self.Connection.SetPosition(x, y) - self.Connection.Draw(dc) - - def OnPaint(self, event): - self.RefreshPreview() - diff -r 36d378bd852e -r dae55dd9ee14 Images/coil.png Binary file Images/coil.png has changed diff -r 36d378bd852e -r dae55dd9ee14 Images/coil.svg --- a/Images/coil.svg Sat Jul 07 11:35:17 2007 +0200 +++ b/Images/coil.svg Mon Jul 09 11:10:14 2007 +0200 @@ -12,13 +12,14 @@ height="25" id="svg2" sodipodi:version="0.32" - inkscape:version="0.44" + inkscape:version="0.45.1" version="1.0" - inkscape:export-filename="/mnt/nfs/Pim/workspace_laurent/PLCOpenEditor/Images/coil.png" + inkscape:export-filename="/taf/Pim/workspace_laurent/plcopeneditor/Images/coil.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" - sodipodi:docbase="/mnt/nfs/Pim/workspace_laurent/PLCOpenEditor/Images" - sodipodi:docname="coil.svg"> + sodipodi:docbase="/taf/Pim/workspace_laurent/plcopeneditor/Images" + sodipodi:docname="coil.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> VAR + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff -r 36d378bd852e -r dae55dd9ee14 Images/rung.png Binary file Images/rung.png has changed diff -r 36d378bd852e -r dae55dd9ee14 Images/rung.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Images/rung.svg Mon Jul 09 11:10:14 2007 +0200 @@ -0,0 +1,111 @@ + + + + + + + + + image/svg+xml + + + + + + + VAR + + + + + diff -r 36d378bd852e -r dae55dd9ee14 LDViewer.py --- a/LDViewer.py Sat Jul 07 11:35:17 2007 +0200 +++ b/LDViewer.py Mon Jul 09 11:10:14 2007 +0200 @@ -30,6 +30,7 @@ from graphics.GraphicCommons import * from graphics.FBD_Objects import * from Viewer import * +from Dialogs import * def ExtractNextBlocks(block, block_list): current_list = [block] @@ -53,10 +54,11 @@ next_list.append(next) current_list = next_list -def CalcBranchSize(elements, stop): +def CalcBranchSize(elements, stops): branch_size = 0 - stop_list = [stop] - ExtractNextBlocks(stop, stop_list) + stop_list = stops + for stop in stops: + ExtractNextBlocks(stop, stop_list) element_tree = {} for element in elements: if element not in element_tree: @@ -64,13 +66,34 @@ GenerateTree(element, element_tree, stop_list) elif element_tree[element]: element_tree[element]["parents"].append("start") + remove_stops = {"start":[], "stop":[]} for element, values in element_tree.items(): - if values and values["children"] == ["stop"]: + if "stop" in values["children"]: + removed = [] + for child in values["children"]: + if child != "stop": +## if child in elements: +## RemoveElement(child, element_tree) +## removed.append(child) + if "start" in element_tree[child]["parents"]: + if element not in remove_stops["stop"]: + remove_stops["stop"].append(element) + if child not in remove_stops["start"]: + remove_stops["start"].append(child) + for child in removed: + values["children"].remove(child) + for element in remove_stops["start"]: + element_tree[element]["parents"].remove("start") + for element in remove_stops["stop"]: + element_tree[element]["children"].remove("stop") + for element, values in element_tree.items(): + if values and "stop" in values["children"]: CalcWeight(element, element_tree) if values["weight"]: branch_size += values["weight"] else: return 1 + #print branch_size return branch_size def RemoveElement(remove, element_tree): @@ -78,7 +101,8 @@ for child in element_tree[remove]["children"]: if child != "stop": RemoveElement(child, element_tree) - element_tree[remove] = None + element_tree.pop(remove) +## element_tree[remove] = None def GenerateTree(element, element_tree, stop_list): if element in element_tree: @@ -95,11 +119,12 @@ for wire, handle in connector.GetWires(): next = wire.EndConnected.GetParentBlock() if isinstance(next, LD_PowerRail) and next.GetType() == LEFTRAIL or next in stop_list: - for remove in element_tree[element]["children"]: - RemoveElement(remove, element_tree) - element_tree[element]["children"] = ["stop"] - elif element_tree[element]["children"] == ["stop"]: - element_tree[next] = None +## for remove in element_tree[element]["children"]: +## RemoveElement(remove, element_tree) +## element_tree[element]["children"] = ["stop"] + element_tree[element]["children"].append("stop") +## elif element_tree[element]["children"] == ["stop"]: +## element_tree[next] = None elif next not in element_tree or element_tree[next]: element_tree[element]["children"].append(next) if next in element_tree: @@ -227,6 +252,9 @@ return None def FindElement(self, pos): + if self.GetDrawingMode() == FREEDRAWING_MODE: + return Viewer.FindElement(self, pos) + elements = [] for element in self.Elements: if element.HitTest(pos) or element.TestHandle(pos) != (0, 0): @@ -243,6 +271,9 @@ return None def SearchElements(self, bbox): + if self.GetDrawingMode() == FREEDRAWING_MODE: + return Viewer.SearchElements(self, bbox) + elements = [] for element in self.Blocks: element_bbox = element.GetBoundingBox() @@ -255,8 +286,11 @@ #------------------------------------------------------------------------------- def OnViewerLeftDown(self, event): - if self.Mode == MODE_SELECTION: - pos = event.GetPosition() + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerLeftDown(self, event) + elif self.Mode == MODE_SELECTION: + dc = self.GetLogicalDC() + pos = event.GetLogicalPosition(dc) element = self.FindElement(pos) if self.SelectedElement: if self.SelectedElement in self.Elements: @@ -283,94 +317,106 @@ self.Refresh() if element: self.SelectedElement = element - self.SelectedElement.OnLeftDown(event, self.Scaling) + self.SelectedElement.OnLeftDown(event, dc, self.Scaling) self.Refresh() else: self.rubberBand.Reset() - self.rubberBand.OnLeftDown(event, self.Scaling) + self.rubberBand.OnLeftDown(event, dc, self.Scaling) event.Skip() def OnViewerLeftUp(self, event): - if self.rubberBand.IsShown(): + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerLeftUp(self, event) + elif self.rubberBand.IsShown(): if self.Mode == MODE_SELECTION: elements = self.SearchElements(self.rubberBand.GetCurrentExtent()) - self.rubberBand.OnLeftUp(event, self.Scaling) + self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) if len(elements) > 0: self.SelectedElement = Graphic_Group(self) self.SelectedElement.SetElements(elements) self.SelectedElement.SetSelected(True) self.Refresh() elif self.Mode == MODE_SELECTION and self.SelectedElement: + dc = self.GetLogicalDC() if self.SelectedElement in self.Elements: if self.SelectedElement in self.Wires: - result = self.SelectedElement.TestSegment(event.GetPosition(), True) + result = self.SelectedElement.TestSegment(event.GetLogicalPosition(dc), True) if result and result[1] in [EAST, WEST]: self.SelectedElement.SetSelectedSegment(result[0]) else: - self.SelectedElement.OnLeftUp(event, self.Scaling) + self.SelectedElement.OnLeftUp(event, dc, self.Scaling) else: for element in self.SelectedElement.GetElements(): if element in self.Wires: - result = element.TestSegment(event.GetPosition(), True) + result = element.TestSegment(event.GetLogicalPosition(dc), True) if result and result[1] in [EAST, WEST]: element.SetSelectedSegment(result[0]) else: - element.OnLeftUp(event, self.Scaling) + element.OnLeftUp(event, dc, self.Scaling) wxCallAfter(self.SetCursor, wxNullCursor) self.ReleaseMouse() self.Refresh() event.Skip() def OnViewerRightUp(self, event): - pos = event.GetPosition() - element = self.FindElement(pos) - if element: - if self.SelectedElement and self.SelectedElement != element: - self.SelectedElement.SetSelected(False) - self.SelectedElement = element - if self.SelectedElement in self.Wires: - self.SelectedElement.SetSelectedSegment(0) - else: - self.SelectedElement.SetSelected(True) - self.SelectedElement.OnRightUp(event, self.Scaling) - wxCallAfter(self.SetCursor, wxNullCursor) - self.ReleaseMouse() + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerRightUp(self, event) + else: + dc = self.GetLogicalDC() + pos = event.GetLogicalPosition(dc) + element = self.FindElement(pos) + if element: + if self.SelectedElement and self.SelectedElement != element: + self.SelectedElement.SetSelected(False) + self.SelectedElement = element + if self.SelectedElement in self.Wires: + self.SelectedElement.SetSelectedSegment(0) + else: + self.SelectedElement.SetSelected(True) + self.SelectedElement.OnRightUp(event, dc, self.Scaling) + wxCallAfter(self.SetCursor, wxNullCursor) + self.ReleaseMouse() + self.Refresh() + event.Skip() + + def OnViewerLeftDClick(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerLeftDClick(self, event) + elif self.Mode == MODE_SELECTION and self.SelectedElement: + self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling) self.Refresh() event.Skip() - def OnViewerLeftDClick(self, event): - if self.Mode == MODE_SELECTION and self.SelectedElement: - self.SelectedElement.OnLeftDClick(event, self.Scaling) + def OnViewerMotion(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerMotion(self, event) + event.Skip() + +#------------------------------------------------------------------------------- +# Keyboard event functions +#------------------------------------------------------------------------------- + + def OnChar(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnChar(self, event) + else: + keycode = event.GetKeyCode() + if keycode == WXK_DELETE and self.SelectedElement: + if self.SelectedElement in self.Blocks: + self.SelectedElement.Delete() + elif self.SelectedElement in self.Wires: + self.DeleteWire(self.SelectedElement) + elif self.SelectedElement not in self.Elements: + all_wires = True + for element in self.SelectedElement.GetElements(): + all_wires &= element in self.Wires + if all_wires: + self.DeleteWire(self.SelectedElement) + else: + self.SelectedElement.Delete() self.Refresh() event.Skip() - def OnViewerMotion(self, event): - if self.rubberBand.IsShown(): - self.rubberBand.OnMotion(event, self.Scaling) - event.Skip() - -#------------------------------------------------------------------------------- -# Keyboard event functions -#------------------------------------------------------------------------------- - - def OnChar(self, event): - keycode = event.GetKeyCode() - if keycode == WXK_DELETE and self.SelectedElement: - if self.SelectedElement in self.Blocks: - self.SelectedElement.Delete() - elif self.SelectedElement in self.Wires: - self.DeleteWire(self.SelectedElement) - elif self.SelectedElement not in self.Elements: - all_wires = True - for element in self.SelectedElement.GetElements(): - all_wires &= element in self.Wires - if all_wires: - self.DeleteWire(self.SelectedElement) - else: - self.SelectedElement.Delete() - self.Refresh() - event.Skip() - #------------------------------------------------------------------------------- # Adding element functions #------------------------------------------------------------------------------- @@ -669,6 +715,7 @@ for element in right_elements: right_powerrail &= isinstance(element.GetParentBlock(), LD_PowerRail) if not left_powerrail or not right_powerrail: + wires = [] if left_powerrail: powerrail = left_elements[0].GetParentBlock() index = 0 @@ -679,15 +726,14 @@ powerrail.InsertConnector(index + 1) powerrail.RefreshModel() connectors = powerrail.GetConnectors() + right_elements.reverse() for i, right_element in enumerate(right_elements): new_wire = Wire(self) + wires.append(new_wire) right_element.InsertConnect(right_index[i] + 1, (new_wire, 0), False) connectors[index + 1].Connect((new_wire, -1), False) new_wire.ConnectStartPoint(None, right_element) new_wire.ConnectEndPoint(None, connectors[index + 1]) - self.Wires.append(new_wire) - self.Elements.append(new_wire) - rung.SelectElement(new_wire) right_elements.reverse() elif right_powerrail: dialog = LDElementDialog(self.Parent, "coil") @@ -731,23 +777,20 @@ wire.ConnectEndPoint(None, coil_connectors["output"]) self.Wires.append(wire) self.Elements.append(wire) - rung.SelectElement(wire) + rung.SelectElement(wire) + left_elements.reverse() for i, left_element in enumerate(left_elements): # Create Wire between LeftPowerRail and Coil new_wire = Wire(self) + wires.append(new_wire) coil_connectors["input"].Connect((new_wire, 0), False) left_element.InsertConnect(left_index[i] + 1, (new_wire, -1), False) new_wire.ConnectStartPoint(None, coil_connectors["input"]) new_wire.ConnectEndPoint(None, left_element) - self.Wires.append(new_wire) - self.Elements.append(new_wire) - rung.SelectElement(new_wire) - left_elements.reverse() self.RefreshPosition(coil) else: left_elements.reverse() right_elements.reverse() - wires = [] for i, left_element in enumerate(left_elements): for j, right_element in enumerate(right_elements): exist = False @@ -760,12 +803,12 @@ left_element.InsertConnect(left_index[i] + 1, (new_wire, -1), False) new_wire.ConnectStartPoint(None, right_element) new_wire.ConnectEndPoint(None, left_element) - wires.reverse() - for wire in wires: - self.Wires.append(wire) - self.Elements.append(wire) - rung.SelectElement(wire) - right_elements.reverse() + wires.reverse() + for wire in wires: + self.Wires.append(wire) + self.Elements.append(wire) + rung.SelectElement(wire) + right_elements.reverse() for block in blocks: self.RefreshPosition(block) for right_element in right_elements: @@ -784,7 +827,6 @@ message.ShowModal() message.Destroy() - def AddBlock(self): message = wxMessageDialog(self, "This option isn't available yet!", "Warning", wxOK|wxICON_EXCLAMATION) message.ShowModal() @@ -795,69 +837,72 @@ #------------------------------------------------------------------------------- def DeleteContact(self, contact): - rungindex = self.FindRung(contact) - rung = self.Rungs[rungindex] - old_bbox = rung.GetBoundingBox() - connectors = contact.GetConnectors() - input_wires = [wire for wire, handle in connectors["input"].GetWires()] - output_wires = [wire for wire, handle in connectors["output"].GetWires()] - left_elements = [(wire.EndConnected, wire.EndConnected.GetWireIndex(wire)) for wire in input_wires] - right_elements = [(wire.StartConnected, wire.StartConnected.GetWireIndex(wire)) for wire in output_wires] - for wire in input_wires: - wire.Clean() - rung.SelectElement(wire) - self.Wires.remove(wire) - self.Elements.remove(wire) - for wire in output_wires: - wire.Clean() - rung.SelectElement(wire) - self.Wires.remove(wire) - self.Elements.remove(wire) - rung.SelectElement(contact) - contact.Clean() - left_elements.reverse() - right_elements.reverse() - powerrail = len(left_elements) == 1 and isinstance(left_elements[0][0].GetParentBlock(), LD_PowerRail) - for left_element, left_index in left_elements: + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.DeleteContact(self, contact) + else: + rungindex = self.FindRung(contact) + rung = self.Rungs[rungindex] + old_bbox = rung.GetBoundingBox() + connectors = contact.GetConnectors() + input_wires = [wire for wire, handle in connectors["input"].GetWires()] + output_wires = [wire for wire, handle in connectors["output"].GetWires()] + left_elements = [(wire.EndConnected, wire.EndConnected.GetWireIndex(wire)) for wire in input_wires] + right_elements = [(wire.StartConnected, wire.StartConnected.GetWireIndex(wire)) for wire in output_wires] + for wire in input_wires: + wire.Clean() + rung.SelectElement(wire) + self.Wires.remove(wire) + self.Elements.remove(wire) + for wire in output_wires: + wire.Clean() + rung.SelectElement(wire) + self.Wires.remove(wire) + self.Elements.remove(wire) + rung.SelectElement(contact) + contact.Clean() + left_elements.reverse() + right_elements.reverse() + powerrail = len(left_elements) == 1 and isinstance(left_elements[0][0].GetParentBlock(), LD_PowerRail) + for left_element, left_index in left_elements: + for right_element, right_index in right_elements: + wire_removed = [] + for wire, handle in right_element.GetWires(): + if wire.EndConnected == left_element: + wire_removed.append(wire) + elif isinstance(wire.EndConnected.GetParentBlock(), LD_PowerRail) and powerrail: + left_powerrail = wire.EndConnected.GetParentBlock() + index = left_powerrail.GetConnectorIndex(wire.EndConnected) + left_powerrail.DeleteConnector(index) + wire_removed.append(wire) + for wire in wire_removed: + wire.Clean() + self.Wires.remove(wire) + self.Elements.remove(wire) + rung.SelectElement(wire) + wires = [] + for left_element, left_index in left_elements: + for right_element, right_index in right_elements: + wire = Wire(self) + wires.append(wire) + right_element.InsertConnect(right_index, (wire, 0), False) + left_element.InsertConnect(left_index, (wire, -1), False) + wire.ConnectStartPoint(None, right_element) + wire.ConnectEndPoint(None, left_element) + wires.reverse() + for wire in wires: + self.Wires.append(wire) + self.Elements.append(wire) + rung.SelectElement(wire) + right_elements.reverse() for right_element, right_index in right_elements: - wire_removed = [] - for wire, handle in right_element.GetWires(): - if wire.EndConnected == left_element: - wire_removed.append(wire) - elif isinstance(wire.EndConnected.GetParentBlock(), LD_PowerRail) and powerrail: - left_powerrail = wire.EndConnected.GetParentBlock() - index = left_powerrail.GetConnectorIndex(wire.EndConnected) - left_powerrail.DeleteConnector(index) - wire_removed.append(wire) - for wire in wire_removed: - wire.Clean() - self.Wires.remove(wire) - self.Elements.remove(wire) - rung.SelectElement(wire) - wires = [] - for left_element, left_index in left_elements: - for right_element, right_index in right_elements: - wire = Wire(self) - wires.append(wire) - right_element.InsertConnect(right_index, (wire, 0), False) - left_element.InsertConnect(left_index, (wire, -1), False) - wire.ConnectStartPoint(None, right_element) - wire.ConnectEndPoint(None, left_element) - wires.reverse() - for wire in wires: - self.Wires.append(wire) - self.Elements.append(wire) - rung.SelectElement(wire) - right_elements.reverse() - for right_element, right_index in right_elements: - self.RefreshPosition(right_element.GetParentBlock()) - self.Blocks.remove(contact) - self.Elements.remove(contact) - self.Controler.RemoveCurrentElementEditingInstance(contact.GetId()) - rung.RefreshBoundingBox() - new_bbox = rung.GetBoundingBox() - self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1) - self.SelectedElement = None + self.RefreshPosition(right_element.GetParentBlock()) + self.Blocks.remove(contact) + self.Elements.remove(contact) + self.Controler.RemoveCurrentElementEditingInstance(contact.GetId()) + rung.RefreshBoundingBox() + new_bbox = rung.GetBoundingBox() + self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1) + self.SelectedElement = None def RecursiveDeletion(self, element, rung): connectors = element.GetConnectors() @@ -881,109 +926,115 @@ self.RefreshPosition(block) def DeleteCoil(self, coil): - rungindex = self.FindRung(coil) - rung = self.Rungs[rungindex] - old_bbox = rung.GetBoundingBox() - nbcoils = 0 - for element in rung.GetElements(): - if isinstance(element, LD_Coil): - nbcoils += 1 - if nbcoils > 1: - connectors = coil.GetConnectors() - output_wires = [wire for wire, handle in connectors["output"].GetWires()] - right_elements = [wire.StartConnected for wire in output_wires] - for wire in output_wires: - wire.Clean() - self.Wires.remove(wire) - self.Elements.remove(wire) - rung.SelectElement(wire) - for right_element in right_elements: - right_block = right_element.GetParentBlock() - if isinstance(right_block, LD_PowerRail): - if len(right_element.GetWires()) == 0: - index = right_block.GetConnectorIndex(right_element) - right_block.DeleteConnector(index) - powerrail_connectors = right_block.GetConnectors() - for connector in powerrail_connectors: - for wire, handle in connector.GetWires(): - block = wire.EndConnected.GetParentBlock() - endpoint = wire.EndConnected.GetPosition(False) - startpoint = connector.GetPosition(False) - block.Move(0, startpoint.y - endpoint.y) - self.RefreshPosition(block) - self.RecursiveDeletion(coil, rung) + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.DeleteContact(self, coil) else: - for element in rung.GetElements(): - if element in self.Wires: - element.Clean() - self.Wires.remove(element) - self.Elements.remove(element) - for element in rung.GetElements(): - if element in self.Blocks: - self.Controler.RemoveCurrentElementEditingInstance(element.GetId()) - self.Blocks.remove(element) - self.Elements.remove(element) - self.Controler.RemoveCurrentElementEditingInstance(self.Comments[rungindex].GetId()) - self.Elements.remove(self.Comments[rungindex]) - self.Comments.pop(rungindex) - self.Rungs.pop(rungindex) - if rungindex < len(self.Rungs): - next_bbox = self.Rungs[rungindex].GetBoundingBox() - self.RefreshRungs(old_bbox.y - next_bbox.y, rungindex) - self.SelectedElement = None - - def DeleteWire(self, wire): - wires = [] - left_elements = [] - right_elements = [] - if wire in self.Wires: - wires = [wire] - elif wire not in self.Elements: - for element in wire.GetElements(): - if element in self.Wires: - wires.append(element) - else: - wires = [] - break - if len(wires) > 0: - rungindex = self.FindRung(wires[0]) + rungindex = self.FindRung(coil) rung = self.Rungs[rungindex] old_bbox = rung.GetBoundingBox() - for wire in wires: - connections = wire.GetSelectedSegmentConnections() - left_block = wire.EndConnected.GetParentBlock() - if wire.EndConnected not in left_elements: - left_elements.append(wire.EndConnected) - if wire.StartConnected not in right_elements: - right_elements.append(wire.StartConnected) - if connections == (False, False) or connections == (False, True) and isinstance(left_block, LD_PowerRail): + nbcoils = 0 + for element in rung.GetElements(): + if isinstance(element, LD_Coil): + nbcoils += 1 + if nbcoils > 1: + connectors = coil.GetConnectors() + output_wires = [wire for wire, handle in connectors["output"].GetWires()] + right_elements = [wire.StartConnected for wire in output_wires] + for wire in output_wires: wire.Clean() self.Wires.remove(wire) self.Elements.remove(wire) rung.SelectElement(wire) - for left_element in left_elements: - left_block = left_element.GetParentBlock() - if isinstance(left_block, LD_PowerRail): - if len(left_element.GetWires()) == 0: - index = left_block.GetConnectorIndex(left_element) - left_block.DeleteConnector(index) - else: - connectors = left_block.GetConnectors() - output_connectors = [] - if "outputs" in connectors: - output_connectors = connectors["outputs"] - if "output" in connectors: - output_connectors = [connectors["output"]] - for connector in output_connectors: - for wire, handle in connector.GetWires(): - self.RefreshPosition(wire.StartConnected.GetParentBlock()) - for right_element in right_elements: - self.RefreshPosition(right_element.GetParentBlock()) - rung.RefreshBoundingBox() - new_bbox = rung.GetBoundingBox() - self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1) + for right_element in right_elements: + right_block = right_element.GetParentBlock() + if isinstance(right_block, LD_PowerRail): + if len(right_element.GetWires()) == 0: + index = right_block.GetConnectorIndex(right_element) + right_block.DeleteConnector(index) + powerrail_connectors = right_block.GetConnectors() + for connector in powerrail_connectors: + for wire, handle in connector.GetWires(): + block = wire.EndConnected.GetParentBlock() + endpoint = wire.EndConnected.GetPosition(False) + startpoint = connector.GetPosition(False) + block.Move(0, startpoint.y - endpoint.y) + self.RefreshPosition(block) + self.RecursiveDeletion(coil, rung) + else: + for element in rung.GetElements(): + if element in self.Wires: + element.Clean() + self.Wires.remove(element) + self.Elements.remove(element) + for element in rung.GetElements(): + if element in self.Blocks: + self.Controler.RemoveCurrentElementEditingInstance(element.GetId()) + self.Blocks.remove(element) + self.Elements.remove(element) + self.Controler.RemoveCurrentElementEditingInstance(self.Comments[rungindex].GetId()) + self.Elements.remove(self.Comments[rungindex]) + self.Comments.pop(rungindex) + self.Rungs.pop(rungindex) + if rungindex < len(self.Rungs): + next_bbox = self.Rungs[rungindex].GetBoundingBox() + self.RefreshRungs(old_bbox.y - next_bbox.y, rungindex) self.SelectedElement = None + def DeleteWire(self, wire): + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.DeleteWire(self, wire) + else: + wires = [] + left_elements = [] + right_elements = [] + if wire in self.Wires: + wires = [wire] + elif wire not in self.Elements: + for element in wire.GetElements(): + if element in self.Wires: + wires.append(element) + else: + wires = [] + break + if len(wires) > 0: + rungindex = self.FindRung(wires[0]) + rung = self.Rungs[rungindex] + old_bbox = rung.GetBoundingBox() + for wire in wires: + connections = wire.GetSelectedSegmentConnections() + left_block = wire.EndConnected.GetParentBlock() + if wire.EndConnected not in left_elements: + left_elements.append(wire.EndConnected) + if wire.StartConnected not in right_elements: + right_elements.append(wire.StartConnected) + if connections == (False, False) or connections == (False, True) and isinstance(left_block, LD_PowerRail): + wire.Clean() + self.Wires.remove(wire) + self.Elements.remove(wire) + rung.SelectElement(wire) + for left_element in left_elements: + left_block = left_element.GetParentBlock() + if isinstance(left_block, LD_PowerRail): + if len(left_element.GetWires()) == 0: + index = left_block.GetConnectorIndex(left_element) + left_block.DeleteConnector(index) + else: + connectors = left_block.GetConnectors() + output_connectors = [] + if "outputs" in connectors: + output_connectors = connectors["outputs"] + if "output" in connectors: + output_connectors = [connectors["output"]] + for connector in output_connectors: + for wire, handle in connector.GetWires(): + self.RefreshPosition(wire.StartConnected.GetParentBlock()) + for right_element in right_elements: + self.RefreshPosition(right_element.GetParentBlock()) + rung.RefreshBoundingBox() + new_bbox = rung.GetBoundingBox() + self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1) + self.SelectedElement = None + #------------------------------------------------------------------------------- # Refresh element position functions #------------------------------------------------------------------------------- @@ -1030,6 +1081,10 @@ movex = minx + interval - position[0] element.Move(movex, 0) position = element.GetPosition() + blocks = [] + for i, connector in enumerate(input_connectors): + for j, (wire, handle) in enumerate(connector.GetWires()): + blocks.append(wire.EndConnected.GetParentBlock()) for i, connector in enumerate(input_connectors): startpoint = connector.GetPosition(False) previous_blocks = [] @@ -1050,7 +1105,7 @@ start_offset = endpoint.y - startpoint.y offset = start_offset else: - offset = start_offset + LD_LINE_SIZE * CalcBranchSize(previous_blocks, block) + offset = start_offset + LD_LINE_SIZE * CalcBranchSize(previous_blocks, blocks) if block in block_list: wires = wire.EndConnected.GetWires() endmiddlepoint = wires[0][0].StartConnected.GetPosition(False)[0] - LD_WIRE_SIZE @@ -1087,6 +1142,7 @@ points = [startpoint, endpoint] wire.SetPoints(points) previous_blocks.append(block) + blocks.remove(block) ExtractNextBlocks(block, block_list) element.RefreshModel(False) if recursive: @@ -1147,175 +1203,3 @@ self.Refresh() dialog.Destroy() -#------------------------------------------------------------------------------- -# Edit Ladder Element Properties Dialog -#------------------------------------------------------------------------------- - -[wxID_LDELEMENTDIALOG, wxID_LDELEMENTDIALOGMAINPANEL, - wxID_LDELEMENTDIALOGNAME, wxID_LDELEMENTDIALOGRADIOBUTTON1, - wxID_LDELEMENTDIALOGRADIOBUTTON2, wxID_LDELEMENTDIALOGRADIOBUTTON3, - wxID_LDELEMENTDIALOGRADIOBUTTON4, wxID_LDELEMENTDIALOGPREVIEW, - wxID_LDELEMENTDIALOGSTATICTEXT1, wxID_LDELEMENTDIALOGSTATICTEXT2, - wxID_LDELEMENTDIALOGSTATICTEXT3, -] = [wx.NewId() for _init_ctrls in range(11)] - -class LDElementDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt, title, labels): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_LDELEMENTDIALOG, - name='VariablePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(350, 260), style=wx.DEFAULT_DIALOG_STYLE, - title=title) - self.SetClientSize(wx.Size(350, 260)) - - self.MainPanel = wx.Panel(id=wxID_LDELEMENTDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(340, 200), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.staticText1 = wx.StaticText(id=wxID_LDELEMENTDIALOGSTATICTEXT1, - label='Modifier:', name='staticText1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(70, 17), style=0) - - self.staticText2 = wx.StaticText(id=wxID_LDELEMENTDIALOGSTATICTEXT2, - label='Name:', name='staticText2', parent=self.MainPanel, - pos=wx.Point(24, 150), size=wx.Size(70, 17), style=0) - - self.staticText3 = wx.StaticText(id=wxID_LDELEMENTDIALOGSTATICTEXT3, - label='Preview:', name='staticText3', parent=self.MainPanel, - pos=wx.Point(174, 24), size=wx.Size(100, 17), style=0) - - self.radioButton1 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON1, - label=labels[0], name='radioButton1', parent=self.MainPanel, - pos=wx.Point(24, 48), size=wx.Size(114, 24), style=0) - EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON1, self.OnTypeChanged) - self.radioButton1.SetValue(True) - - self.radioButton2 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON2, - label=labels[1], name='radioButton2', parent=self.MainPanel, - pos=wx.Point(24, 72), size=wx.Size(128, 24), style=0) - EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON2, self.OnTypeChanged) - - self.radioButton3 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON3, - label=labels[2], name='radioButton3', parent=self.MainPanel, - pos=wx.Point(24, 96), size=wx.Size(114, 24), style=0) - EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON3, self.OnTypeChanged) - - self.radioButton4 = wx.RadioButton(id=wxID_LDELEMENTDIALOGRADIOBUTTON4, - label=labels[3], name='radioButton4', parent=self.MainPanel, - pos=wx.Point(24, 120), size=wx.Size(128, 24), style=0) - EVT_RADIOBUTTON(self, wxID_LDELEMENTDIALOGRADIOBUTTON4, self.OnTypeChanged) - - self.Name = wx.Choice(id=wxID_LDELEMENTDIALOGNAME, - name='Name', parent=self.MainPanel, pos=wx.Point(24, 174), - size=wx.Size(145, 24), style=0) - EVT_CHOICE(self, wxID_LDELEMENTDIALOGNAME, self.OnNameChanged) - - self.Preview = wx.Panel(id=wxID_LDELEMENTDIALOGPREVIEW, - name='Preview', parent=self.MainPanel, pos=wx.Point(174, 48), - size=wx.Size(150, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.Preview.SetBackgroundColour(wxColour(255,255,255)) - - self._init_sizers() - - def __init__(self, parent, type): - self.Type = type - if type == "contact": - self._init_ctrls(parent, "Edit Contact Values", ['Normal','Negate','Rising Edge','Falling Edge']) - self.Element = LD_Contact(self.Preview, CONTACT_NORMAL, "") - elif type == "coil": - self._init_ctrls(parent, "Edit Coil Values", ['Normal','Negate','Set','Reset']) - self.Element = LD_Coil(self.Preview, COIL_NORMAL, "") - self.Element.SetPosition((150 - LD_ELEMENT_SIZE[0]) / 2, (150 - LD_ELEMENT_SIZE[1]) / 2) - - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - - EVT_PAINT(self, self.OnPaint) - - def SetVariables(self, vars): - self.Name.Clear() - for name in vars: - self.Name.Append(name) - self.Name.Enable(self.Name.GetCount() > 0) - - def SetValues(self, values): - for name, value in values.items(): - if name == "name": - self.Element.SetName(value) - self.Name.SetStringSelection(value) - elif name == "type": - self.Element.SetType(value) - if self.Type == "contact": - if value == CONTACT_NORMAL: - self.radioButton1.SetValue(True) - elif value == CONTACT_REVERSE: - self.radioButton2.SetValue(True) - elif value == CONTACT_RISING: - self.radioButton3.SetValue(True) - elif value == CONTACT_FALLING: - self.radioButton4.SetValue(True) - elif self.Type == "coil": - if value == COIL_NORMAL: - self.radioButton1.SetValue(True) - elif value == COIL_REVERSE: - self.radioButton2.SetValue(True) - elif value == COIL_SET: - self.radioButton3.SetValue(True) - elif value == COIL_RESET: - self.radioButton4.SetValue(True) - - def GetValues(self): - values = {} - values["name"] = self.Element.GetName() - values["type"] = self.Element.GetType() - return values - - def OnTypeChanged(self, event): - if self.Type == "contact": - if self.radioButton1.GetValue(): - self.Element.SetType(CONTACT_NORMAL) - elif self.radioButton2.GetValue(): - self.Element.SetType(CONTACT_REVERSE) - elif self.radioButton3.GetValue(): - self.Element.SetType(CONTACT_RISING) - elif self.radioButton4.GetValue(): - self.Element.SetType(CONTACT_FALLING) - elif self.Type == "coil": - if self.radioButton1.GetValue(): - self.Element.SetType(COIL_NORMAL) - elif self.radioButton2.GetValue(): - self.Element.SetType(COIL_REVERSE) - elif self.radioButton3.GetValue(): - self.Element.SetType(COIL_SET) - elif self.radioButton4.GetValue(): - self.Element.SetType(COIL_RESET) - self.RefreshPreview() - event.Skip() - - def OnNameChanged(self, event): - self.Element.SetName(self.Name.GetStringSelection()) - self.RefreshPreview() - event.Skip() - - def RefreshPreview(self): - dc = wxClientDC(self.Preview) - dc.Clear() - self.Element.Draw(dc) - - def OnPaint(self, event): - self.RefreshPreview() - event.Skip() diff -r 36d378bd852e -r dae55dd9ee14 PLCControler.py --- a/PLCControler.py Sat Jul 07 11:35:17 2007 +0200 +++ b/PLCControler.py Mon Jul 09 11:10:14 2007 +0200 @@ -23,6 +23,7 @@ #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from minixsv import pyxsval +from xml.dom import minidom import cPickle import os,sys,re from datetime import * @@ -158,6 +159,7 @@ # Reset PLCControler internal variables def Reset(self): + self.VerifyXML = False self.Project = None self.ProjectBuffer = None self.FilePath = "" @@ -185,7 +187,7 @@ self.Project = plcopen.project() self.Project.setName(name) # Initialize the project buffer - self.ProjectBuffer = UndoBuffer(self.Copy(self.Project)) + #self.ProjectBuffer = UndoBuffer(self.Copy(self.Project)) # Change project name def SetProjectName(self, name): @@ -1054,7 +1056,7 @@ connections = variable.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} connector["links"].append(dic) infos["connectors"]["inputs"].append(connector) for variable in instance.outputVariables.getVariable(): @@ -1083,7 +1085,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connector"]["links"].append(dic) elif isinstance(instance, plcopen.inOutVariable): infos["name"] = instance.getExpression() @@ -1100,7 +1102,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connectors"]["input"]["links"].append(dic) elif isinstance(instance, plcopen.continuation): infos["name"] = instance.getName() @@ -1118,7 +1120,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connector"]["links"].append(dic) elif isinstance(instance, plcopen.comment): infos["type"] = "comment" @@ -1138,7 +1140,7 @@ connector["position"] = connection.getRelPosition() connector["links"] = [] for link in connection.getConnections(): - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} connector["links"].append(dic) infos["connectors"].append(connector) elif isinstance(instance, plcopen.contact): @@ -1152,7 +1154,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connectors"]["input"]["links"].append(dic) infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition() elif isinstance(instance, plcopen.coil): @@ -1166,7 +1168,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connectors"]["input"]["links"].append(dic) infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition() elif isinstance(instance, plcopen.step): @@ -1181,7 +1183,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connectors"]["input"]["links"].append(dic) if instance.connectionPointOut: infos["connectors"]["output"] = {"position" : instance.connectionPointOut.getRelPosition()} @@ -1198,7 +1200,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connectors"]["input"]["links"].append(dic) infos["connectors"]["output"]["position"] = instance.connectionPointOut.getRelPosition() elif isinstance(instance, (plcopen.selectionDivergence, plcopen.simultaneousDivergence)): @@ -1213,7 +1215,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} connector["links"].append(dic) infos["connectors"]["inputs"].append(connector) for sequence in instance.getConnectionPointOut(): @@ -1233,7 +1235,7 @@ connections = sequence.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} connector["links"].append(dic) infos["connectors"]["inputs"].append(connector) connector = {} @@ -1248,7 +1250,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connector"]["links"].append(dic) elif isinstance(instance, plcopen.actionBlock): infos["type"] = "actionBlock" @@ -1259,7 +1261,7 @@ connections = instance.connectionPointIn.getConnections() if connections: for link in connections: - dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints()} + dic = {"refLocalId":link.getRefLocalId(),"points":link.getPoints(),"formalParameter":link.getFormalParameter()} infos["connector"]["links"].append(dic) return infos return False @@ -1278,13 +1280,18 @@ for wire, handle in wires: points = wire.GetPoints(handle != 0) if handle == 0: - refLocalId = wire.GetConnectedId(-1) + result = wire.GetConnectedInfos(-1) else: - refLocalId = wire.GetConnectedId(0) - if refLocalId != None: + result = wire.GetConnectedInfos(0) + if result != None: + refLocalId, formalParameter = result connection.addConnection() connection.setConnectionId(idx, refLocalId) connection.setConnectionPoints(idx, points) + if formalParameter != "": + connection.setConnectionParameter(idx, formalParameter) + else: + connection.setConnectionParameter(idx, None) idx += 1 def AddCurrentElementEditingBlock(self, id): @@ -1847,14 +1854,20 @@ return tasks_data, instances_data def OpenXMLFile(self, filepath): - if sys: - sys.stdout = HolePseudoFile() - tree = pyxsval.parseAndValidate(filepath, os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd")) - if sys: - sys.stdout = sys.__stdout__ + if self.VerifyXML: + if sys: + sys.stdout = HolePseudoFile() + result = pyxsval.parseAndValidate(filepath, os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd")) + if sys: + sys.stdout = sys.__stdout__ + tree = result.getTree() + else: + xmlfile = open(filepath, 'r') + tree = minidom.parse(xmlfile) + xmlfile.close() self.Project = plcopen.project() - self.Project.loadXMLTree(tree.getTree().childNodes[0]) + self.Project.loadXMLTree(tree.childNodes[0]) self.UndoBuffer = UndoBuffer(self.Copy(self.Project), True) self.SetFilePath(filepath) self.ElementsOpened = [] @@ -1873,11 +1886,12 @@ "xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd http://www.plcopen.org/xml/tc6.xsd"} text += self.Project.generateXMLText("project", 0, extras) - if sys: - sys.stdout = HolePseudoFile() - pyxsval.parseAndValidateString(text, open(os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd"),"r").read()) - if sys: - sys.stdout = sys.__stdout__ + if self.VerifyXML: + if sys: + sys.stdout = HolePseudoFile() + pyxsval.parseAndValidateString(text, open(os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd"),"r").read()) + if sys: + sys.stdout = sys.__stdout__ if filepath: xmlfile = open(filepath,"w") @@ -1885,7 +1899,7 @@ xmlfile = open(self.FilePath,"w") xmlfile.write(text) xmlfile.close() - self.UndoBuffer.CurrentSaved() + #self.ProjectBuffer.CurrentSaved() if filepath: self.SetFilePath(filepath) return True @@ -1901,20 +1915,20 @@ return cPickle.loads(cPickle.dumps(model)) def BufferProject(self): - self.UndoBuffer.Buffering(self.Copy(self)) + self.ProjectBuffer.Buffering(self.Copy(self)) def ProjectIsSaved(self): - return self.UndoBuffer.IsCurrentSaved() + return self.ProjectBuffer.IsCurrentSaved() def LoadPrevious(self): - self.Project = self.Copy(self.UndoBuffer.Previous()) + self.Project = self.Copy(self.ProjectBuffer.Previous()) self.RefreshElementsOpened() def LoadNext(self): - self.Project = self.Copy(self.UndoBuffer.Next()) + self.Project = self.Copy(self.ProjectBuffer.Next()) self.RefreshElementsOpened() def GetBufferState(self): - first = self.UndoBuffer.IsFirst() - last = self.UndoBuffer.IsLast() + first = self.ProjectBuffer.IsFirst() + last = self.ProjectBuffer.IsLast() return not first, not last diff -r 36d378bd852e -r dae55dd9ee14 PLCOpenEditor.py --- a/PLCOpenEditor.py Sat Jul 07 11:35:17 2007 +0200 +++ b/PLCOpenEditor.py Mon Jul 09 11:10:14 2007 +0200 @@ -29,9 +29,10 @@ import wx from SFCViewer import * -from FBDViewer import * from LDViewer import * from Viewer import * +from TextViewer import * +from RessourceEditor import * from PLCControler import * from plcopen import OpenPDFDoc from plcopen.structures import * @@ -74,25 +75,6 @@ wxID_PLCOPENEDITORFBDTOOLBAR, wxID_PLCOPENEDITORLDTOOLBAR, ] = [wx.NewId() for _init_ctrls in range(10)] -[wxID_PLCOPENEDITORTOOLBARITEMS0, -] = [wx.NewId() for _init_coll_DefaultToolBar_Items in range(1)] - -SFC_ITEMS = [wxID_PLCOPENEDITORSFCTOOLBARITEMS1, - wxID_PLCOPENEDITORSFCTOOLBARITEMS2, wxID_PLCOPENEDITORSFCTOOLBARITEMS3, - wxID_PLCOPENEDITORSFCTOOLBARITEMS4, wxID_PLCOPENEDITORSFCTOOLBARITEMS5, - wxID_PLCOPENEDITORSFCTOOLBARITEMS6, -] = [wx.NewId() for _init_coll_SFCToolBar_Items in range(6)] - -FBD_ITEMS = [wxID_PLCOPENEDITORFBDTOOLBARITEMS1, - wxID_PLCOPENEDITORFBDTOOLBARITEMS2, wxID_PLCOPENEDITORFBDTOOLBARITEMS3, - wxID_PLCOPENEDITORFBDTOOLBARITEMS4, wxID_PLCOPENEDITORFBDTOOLBARITEMS5, -] = [wx.NewId() for _init_coll_FBDToolBar_Items in range(5)] - -LD_ITEMS = [wxID_PLCOPENEDITORLDTOOLBARITEMS1, - wxID_PLCOPENEDITORLDTOOLBARITEMS2, wxID_PLCOPENEDITORLDTOOLBARITEMS3, - wxID_PLCOPENEDITORLDTOOLBARITEMS4, -] = [wx.NewId() for _init_coll_LDToolBar_Items in range(4)] - [wxID_PLCOPENEDITORFILEMENUITEMS0, wxID_PLCOPENEDITORFILEMENUITEMS1, wxID_PLCOPENEDITORFILEMENUITEMS2, wxID_PLCOPENEDITORFILEMENUITEMS3, wxID_PLCOPENEDITORFILEMENUITEMS5, wxID_PLCOPENEDITORFILEMENUITEMS6, @@ -125,6 +107,56 @@ [wxID_PLCOPENEDITORCONFIGMENUITEMS0, wxID_PLCOPENEDITORCONFIGMENUITEMS1, ] = [wx.NewId() for _init_coll_ConfigMenu_Items in range(2)] + +#------------------------------------------------------------------------------- +# ToolBars definitions +#------------------------------------------------------------------------------- + + +[wxID_PLCOPENEDITORTOOLBARSELECTION, wxID_PLCOPENEDITORTOOLBARCOMMENT, + wxID_PLCOPENEDITORTOOLBARVARIABLE, wxID_PLCOPENEDITORTOOLBARBLOCK, + wxID_PLCOPENEDITORTOOLBARCONNECTION, wxID_PLCOPENEDITORTOOLBARWIRE, + wxID_PLCOPENEDITORTOOLBARPOWERRAIL, wxID_PLCOPENEDITORTOOLBARRUNG, + wxID_PLCOPENEDITORTOOLBARCOIL, wxID_PLCOPENEDITORTOOLBARCONTACT, + wxID_PLCOPENEDITORTOOLBARBRANCH, wxID_PLCOPENEDITORTOOLBARINITIALSTEP, + wxID_PLCOPENEDITORTOOLBARSTEP, wxID_PLCOPENEDITORTOOLBARTRANSITION, + wxID_PLCOPENEDITORTOOLBARACTIONBLOCK, wxID_PLCOPENEDITORTOOLBARDIVERGENCE, + wxID_PLCOPENEDITORTOOLBARJUMP, +] = [wx.NewId() for _init_coll_DefaultToolBar_Items in range(17)] + +ToolBarItems = { + "FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", "Images/comment.png", "Create a new comment"), + (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", "Images/variable.png", "Create a new variable"), + (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", "Images/block.png", "Create a new block"), + (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "Images/connection.png", "Create a new connection"), + (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARWIRE, "OnWireTool", "Images/wire.png", "Create a new wire")], + "LD" : [(True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", "Images/comment.png", "Create a new comment"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", "Images/powerrail.png", "Create a new power rail"), + (False, DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARRUNG, "OnRungTool", "Images/rung.png", "Create a new rung"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCOIL, "OnCoilTool", "Images/coil.png", "Create a new coil"), + (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", "Images/contact.png", "Create a new contact"), + (False, DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARBRANCH, "OnBranchTool", "Images/branch.png", "Create a new branch"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", "Images/variable.png", "Create a new variable"), + (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", "Images/block.png", "Create a new block"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "Images/connection.png", "Create a new connection"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARWIRE, "OnWireTool", "Images/wire.png", "Create a new wire")], + "SFC" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", "Images/comment.png", "Create a new comment"), + (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARINITIALSTEP, "OnInitialStepTool", "Images/initial_step.png", "Create a new initial step"), + (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARSTEP, "OnStepTool", "Images/step.png", "Create a new step"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARTRANSITION, "OnTransitionTool", "Images/transition.png", "Create a new transition"), + (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARACTIONBLOCK, "OnActionBlockTool", "Images/action.png", "Create a new action block"), + (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARDIVERGENCE, "OnDivergenceTool", "Images/divergence.png", "Create a new divergence"), + (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARJUMP, "OnJumpTool", "Images/jump.png", "Create a new jump"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", "Images/variable.png", "Create a new variable"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", "Images/block.png", "Create a new block"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", "Images/connection.png", "Create a new connection"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", "Images/powerrail.png", "Create a new power rail"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", "Images/contact.png", "Create a new contact"), + (True, FREEDRAWING_MODE, wxID_PLCOPENEDITORTOOLBARWIRE, "OnWireTool", "Images/wire.png", "Create a new wire")], + "ST" : [], + "IL" : [] +} + class PLCOpenEditor(wx.Frame): _custom_classes = {'wx.SashWindow' : ['Viewer']} @@ -242,6 +274,8 @@ id=wxID_PLCOPENEDITORFILEMENUITEMS6) self.Bind(wx.EVT_MENU, self.OnGenerateProgramMenu, id=wxID_PLCOPENEDITORFILEMENUITEMS7) + self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, + id=wxID_PLCOPENEDITORFILEMENUITEMS9) self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wxID_PLCOPENEDITORFILEMENUITEMS11) @@ -351,16 +385,16 @@ self.ToolBar = wxToolBar(id=wxID_PLCOPENEDITORTOOLBAR, name='ToolBar', parent=self.EditorPanel, pos=wx.Point(0, 0), size=wx.Size(0, 40), style=wxTB_HORIZONTAL | wxNO_BORDER) - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORTOOLBARITEMS0, + self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORTOOLBARSELECTION, wxBitmap(os.path.join(CWD, 'Images/select.png')), wxNullBitmap, "Select an object") self.Bind(wx.EVT_TOOL, self.OnSelectionTool, - id=wxID_PLCOPENEDITORTOOLBARITEMS0) + id=wxID_PLCOPENEDITORTOOLBARSELECTION) self.ProjectTree = wx.TreeCtrl(id=wxID_PLCOPENEDITORPROJECTTREE, name='treeCtrl1', parent=self.splitterWindow1, pos=wx.Point(0, 0), size=wx.Size(-1, -1), style=wx.TR_HAS_BUTTONS|wx.TR_EDIT_LABELS|wx.TR_SINGLE|wx.SUNKEN_BORDER) - self.Bind(wx.EVT_RIGHT_UP, self.OnProjectTreeRightUp) + self.ProjectTree.Bind(wx.EVT_RIGHT_UP, self.OnProjectTreeRightUp) self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnProjectTreeBeginDrag, id=wxID_PLCOPENEDITORPROJECTTREE) self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnProjectTreeItemBeginEdit, @@ -391,11 +425,16 @@ self.RefreshProjectTree() self.CurrentToolBar = [] + self.CurrentLanguage = "" + self.DrawingMode = DRIVENDRAWING_MODE self.RefreshFileMenu() self.RefreshEditMenu() self.RefreshToolBar() + def GetDrawingMode(self): + return self.DrawingMode + def RefreshFileMenu(self): if self.FileMenu: if self.Controler.HasOpenedProject(): @@ -441,6 +480,20 @@ self.EditMenu.FindItemByPosition(5).Enable(False) self.EditMenu.FindItemByPosition(6).Enable(False) + def ShowProperties(self): + old_values = self.Controler.GetProjectProperties() + old_values["projectName"] = self.Controler.GetProjectName() + dialog = ProjectDialog(self) + dialog.SetValues(old_values) + if dialog.ShowModal() == wxID_OK: + new_values = dialog.GetValues() + projectname = new_values.pop("projectName") + new_values["creationDateTime"] = old_values["creationDateTime"] + self.Controler.SetProjectName(projectname) + self.Controler.SetProjectProperties(new_values) + self.RefreshProjectTree() + dialog.Destroy() + def OnNewProjectMenu(self, event): dialog = ProjectDialog(self) if dialog.ShowModal() == wxID_OK: @@ -529,7 +582,7 @@ if filepath != "": directory, filename = os.path.split(filepath) else: - directory, filename = os.getcwd(), "%s.od"%self.Controler.GetProjectName() + directory, filename = os.getcwd(), "%s.xml"%self.Controler.GetProjectName() dialog = wxFileDialog(self, "Choose a file", directory, filename, "PLCOpen files (*.xml)|*.xml|All files|*.*", wxSAVE|wxOVERWRITE_PROMPT) if dialog.ShowModal() == wxID_OK: filepath = dialog.GetPath() @@ -545,6 +598,10 @@ message.Destroy() dialog.Destroy() + def OnPropertiesMenu(self, event): + self.ShowProperties() + event.Skip() + def OnQuitMenu(self, event): self.ToolBar.Reparent(self) self.Controler.Reset() @@ -557,7 +614,7 @@ window = self.TabsOpened.GetPage(selected) if not isinstance(window, TextViewer): window.SetMode(MODE_SELECTION) - self.ToolBar.ToggleTool(wxID_PLCOPENEDITORTOOLBARITEMS0, True) + self.ToolBar.ToggleTool(wxID_PLCOPENEDITORTOOLBARSELECTION, True) def ResetToolToggle(self, id): tool = self.ToolBar.FindById(id) @@ -569,101 +626,134 @@ self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION) event.Skip() - def OnSFCCommentTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORSFCTOOLBARITEMS1) + def OnCommentTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARCOMMENT) selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT) event.Skip() - def OnSFCInitialStepTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORSFCTOOLBARITEMS2) - selected = self.TabsOpened.GetSelection() - if selected != -1: - self.TabsOpened.GetPage(selected).SetMode(MODE_INITIAL_STEP) - event.Skip() - - def OnSFCStepTool(self, event): - selected = self.TabsOpened.GetSelection() - if selected != -1: - self.TabsOpened.GetPage(selected).AddStep() - event.Skip() - - def OnSFCActionBlockTool(self, event): - selected = self.TabsOpened.GetSelection() - if selected != -1: - self.TabsOpened.GetPage(selected).AddStepAction() - event.Skip() - - def OnSFCDivergenceTool(self, event): - selected = self.TabsOpened.GetSelection() - if selected != -1: - self.TabsOpened.GetPage(selected).AddDivergence() - event.Skip() - - def OnSFCJumpTool(self, event): - selected = self.TabsOpened.GetSelection() - if selected != -1: - self.TabsOpened.GetPage(selected).AddJump() - event.Skip() - - def OnFBDCommentTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORFBDTOOLBARITEMS1) - selected = self.TabsOpened.GetSelection() - if selected != -1: - self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT) - event.Skip() - - def OnFBDVariableTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORFBDTOOLBARITEMS2) + def OnVariableTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARVARIABLE) selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE) event.Skip() - def OnFBDBlockTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORFBDTOOLBARITEMS3) + def OnBlockTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARBLOCK) selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK) event.Skip() - def OnFBDConnectionTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORFBDTOOLBARITEMS4) + def OnConnectionTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARCONNECTION) selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION) event.Skip() - def OnFBDWireTool(self, event): - self.ResetToolToggle(wxID_PLCOPENEDITORFBDTOOLBARITEMS5) + def OnWireTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARWIRE) selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).SetMode(MODE_WIRE) event.Skip() - def OnLDCoilTool(self, event): + def OnPowerRailTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARPOWERRAIL) + selected = self.TabsOpened.GetSelection() + if selected != -1: + self.TabsOpened.GetPage(selected).SetMode(MODE_POWERRAIL) + event.Skip() + + def OnRungTool(self, event): selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).AddRung() event.Skip() - def OnLDContactTool(self, event): + def OnCoilTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARCOIL) selected = self.TabsOpened.GetSelection() if selected != -1: - self.TabsOpened.GetPage(selected).AddContact() - event.Skip() - - def OnLDBlockTool(self, event): + self.TabsOpened.GetPage(selected).SetMode(MODE_COIL) + event.Skip() + + def OnContactTool(self, event): + if self.DrawingMode == FREEDRAWING_MODE: + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARCONTACT) selected = self.TabsOpened.GetSelection() if selected != -1: - self.TabsOpened.GetPage(selected).AddBlock() - event.Skip() - - def OnLDBranchTool(self, event): + if self.DrawingMode == FREEDRAWING_MODE: + self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT) + else: + self.TabsOpened.GetPage(selected).AddContact() + event.Skip() + + def OnBranchTool(self, event): selected = self.TabsOpened.GetSelection() if selected != -1: self.TabsOpened.GetPage(selected).AddBranch() + event.Skip() + + def OnInitialStepTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARINITIALSTEP) + selected = self.TabsOpened.GetSelection() + if selected != -1: + self.TabsOpened.GetPage(selected).SetMode(MODE_INITIALSTEP) + event.Skip() + + def OnStepTool(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARSTEP) + selected = self.TabsOpened.GetSelection() + if selected != -1: + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.TabsOpened.GetPage(selected).SetMode(MODE_STEP) + else: + self.TabsOpened.GetPage(selected).AddStep() + event.Skip() + + def OnActionBlockTool(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARACTIONBLOCK) + selected = self.TabsOpened.GetSelection() + if selected != -1: + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.TabsOpened.GetPage(selected).SetMode(MODE_ACTION) + else: + self.TabsOpened.GetPage(selected).AddStepAction() + event.Skip() + + def OnTransitionTool(self, event): + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARTRANSITION) + selected = self.TabsOpened.GetSelection() + if selected != -1: + self.TabsOpened.GetPage(selected).SetMode(MODE_TRANSITION) + event.Skip() + + def OnDivergenceTool(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARDIVERGENCE) + selected = self.TabsOpened.GetSelection() + if selected != -1: + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.TabsOpened.GetPage(selected).SetMode(MODE_DIVERGENCE) + else: + self.TabsOpened.GetPage(selected).AddDivergence() + event.Skip() + + def OnJumpTool(self, event): + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.ResetToolToggle(wxID_PLCOPENEDITORTOOLBARJUMP) + selected = self.TabsOpened.GetSelection() + if selected != -1: + if self.GetDrawingMode() == FREEDRAWING_MODE: + self.TabsOpened.GetPage(selected).SetMode(MODE_JUMP) + else: + self.TabsOpened.GetPage(selected).AddJump() event.Skip() def OnPouSelectedChanged(self, event): @@ -785,18 +875,7 @@ name = self.ProjectTree.GetItemText(selected) data = self.ProjectTree.GetPyData(selected) if name == "Properties": - old_values = self.Controler.GetProjectProperties() - old_values["projectName"] = self.Controler.GetProjectName() - dialog = ProjectDialog(self) - dialog.SetValues(old_values) - if dialog.ShowModal() == wxID_OK: - new_values = dialog.GetValues() - projectname = new_values.pop("projectName") - new_values["creationDateTime"] = old_values["creationDateTime"] - self.Controler.SetProjectName(projectname) - self.Controler.SetProjectProperties(new_values) - self.RefreshProjectTree() - dialog.Destroy() + self.ShowProperties() elif data == ITEM_CLASS: item = self.ProjectTree.GetItemParent(selected) item_type = self.ProjectTree.GetPyData(item) @@ -889,7 +968,7 @@ varlist.append(var["Name"]) if idx != None: if language == "FBD": - new_window = FBD_Viewer(self.TabsOpened, self, self.Controler) + new_window = Viewer(self.TabsOpened, self, self.Controler) elif language == "LD": new_window = LD_Viewer(self.TabsOpened, self, self.Controler) elif language == "SFC": @@ -1017,92 +1096,29 @@ item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie) while item.IsOk(): to_delete.append(item) - item, root_cookie = self.ProjectTree.GetNextChild(item, root_cookie) + item, root_cookie = self.ProjectTree.GetNextChild(root, root_cookie) for item in to_delete: self.ProjectTree.Delete(item) - + def ResetToolBar(self): for item in self.CurrentToolBar: + self.Unbind(wx.EVT_MENU, id=item) self.ToolBar.DeleteTool(item) def RefreshToolBar(self): language = self.Controler.GetCurrentElementEditingBodyType() - if language == "SFC": - if self.CurrentToolBar != SFC_ITEMS: - self.ResetToolBar() - self.CurrentToolBar = SFC_ITEMS - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS1, - wxBitmap(os.path.join(CWD, 'Images/comment.png')), wxNullBitmap, "Create a new comment") - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS2, - wxBitmap(os.path.join(CWD, 'Images/initial_step.png')), wxNullBitmap, "Create a new initial step") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS3, - wxBitmap(os.path.join(CWD, 'Images/step.png')), "Create a new step") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS4, - wxBitmap(os.path.join(CWD, 'Images/action.png')), "Add action block to step") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS5, - wxBitmap(os.path.join(CWD, 'Images/divergence.png')), "Create a new divergence") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORSFCTOOLBARITEMS6, - wxBitmap(os.path.join(CWD, 'Images/jump.png')), "Create a new jump") - self.Bind(wx.EVT_TOOL, self.OnSFCCommentTool, - id=wxID_PLCOPENEDITORSFCTOOLBARITEMS1) - self.Bind(wx.EVT_TOOL, self.OnSFCInitialStepTool, - id=wxID_PLCOPENEDITORSFCTOOLBARITEMS2) - self.Bind(wx.EVT_TOOL, self.OnSFCStepTool, - id=wxID_PLCOPENEDITORSFCTOOLBARITEMS3) - self.Bind(wx.EVT_TOOL, self.OnSFCActionBlockTool, - id=wxID_PLCOPENEDITORSFCTOOLBARITEMS4) - self.Bind(wx.EVT_TOOL, self.OnSFCDivergenceTool, - id=wxID_PLCOPENEDITORSFCTOOLBARITEMS5) - self.Bind(wx.EVT_TOOL, self.OnSFCJumpTool, - id=wxID_PLCOPENEDITORSFCTOOLBARITEMS6) - elif language == "FBD": - if self.CurrentToolBar != FBD_ITEMS: - self.ResetToolBar() - self.CurrentToolBar = FBD_ITEMS - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS1, - wxBitmap(os.path.join(CWD, 'Images/comment.png')), wxNullBitmap, "Create a new comment") - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS2, - wxBitmap(os.path.join(CWD, 'Images/variable.png')), wxNullBitmap, "Create a new variable") - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS3, - wxBitmap(os.path.join(CWD, 'Images/block.png')), wxNullBitmap, "Create a new block") - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS4, - wxBitmap(os.path.join(CWD, 'Images/connection.png')), wxNullBitmap, "Create a new connection") - self.ToolBar.AddRadioTool(wxID_PLCOPENEDITORFBDTOOLBARITEMS5, - wxBitmap(os.path.join(CWD, 'Images/wire.png')), wxNullBitmap, "Create a new wire") - self.Bind(wx.EVT_TOOL, self.OnFBDCommentTool, - id=wxID_PLCOPENEDITORFBDTOOLBARITEMS1) - self.Bind(wx.EVT_TOOL, self.OnFBDVariableTool, - id=wxID_PLCOPENEDITORFBDTOOLBARITEMS2) - self.Bind(wx.EVT_TOOL, self.OnFBDBlockTool, - id=wxID_PLCOPENEDITORFBDTOOLBARITEMS3) - self.Bind(wx.EVT_TOOL, self.OnFBDConnectionTool, - id=wxID_PLCOPENEDITORFBDTOOLBARITEMS4) - self.Bind(wx.EVT_TOOL, self.OnFBDWireTool, - id=wxID_PLCOPENEDITORFBDTOOLBARITEMS5) - elif language == "LD": - if self.CurrentToolBar != LD_ITEMS: - self.ResetToolBar() - self.CurrentToolBar = LD_ITEMS - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS1, - wxBitmap(os.path.join(CWD, 'Images/coil.png')), "Create a new rung") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS2, - wxBitmap(os.path.join(CWD, 'Images/contact.png')), "Create a new contact") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS3, - wxBitmap(os.path.join(CWD, 'Images/block.png')), "Create a new block") - self.ToolBar.AddSimpleTool(wxID_PLCOPENEDITORLDTOOLBARITEMS4, - wxBitmap(os.path.join(CWD, 'Images/branch.png')), "Create a new branch") - self.Bind(wx.EVT_TOOL, self.OnLDCoilTool, - id=wxID_PLCOPENEDITORLDTOOLBARITEMS1) - self.Bind(wx.EVT_TOOL, self.OnLDContactTool, - id=wxID_PLCOPENEDITORLDTOOLBARITEMS2) - self.Bind(wx.EVT_TOOL, self.OnLDBlockTool, - id=wxID_PLCOPENEDITORLDTOOLBARITEMS3) - self.Bind(wx.EVT_TOOL, self.OnLDBranchTool, - id=wxID_PLCOPENEDITORLDTOOLBARITEMS4) - else: - if len(self.CurrentToolBar) > 0: - self.ResetToolBar() - self.CurrentToolBar = [] + if language and language != self.CurrentLanguage: + self.ResetToolBar() + self.CurrentLanguage = language + self.CurrentToolBar = [] + for radio, modes, id, method, picture, help in ToolBarItems[language]: + if modes & self.DrawingMode: + if radio or self.DrawingMode == FREEDRAWING_MODE: + self.ToolBar.AddRadioTool(id, wxBitmap(os.path.join(CWD, picture)), wxNullBitmap, help) + else: + self.ToolBar.AddSimpleTool(id, wxBitmap(os.path.join(CWD, picture)), help) + self.Bind(wx.EVT_TOOL, getattr(self, method), id=id) + self.CurrentToolBar.append(id) self.ResetCurrentMode() def RefreshTabsOpenedTitles(self): @@ -2063,7 +2079,7 @@ self.OptionList = "Yes,No" self.TypeList = "" - for value in TypeHierarchy.keys(): + for value, parent in TypeHierarchy_list: if not value.startswith("ANY"): self.TypeList += "%s,"%value self.TypeList = self.TypeList[:-1] @@ -2208,6 +2224,7 @@ self.RefreshValues() def RefreshValues(self): + self.VariablesGrid.SetGridCursor(0, 0) data = [] for variable in self.Values: if variable["Class"] in self.ClassList: diff -r 36d378bd852e -r dae55dd9ee14 RessourceEditor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RessourceEditor.py Mon Jul 09 11:10:14 2007 +0200 @@ -0,0 +1,509 @@ +#!/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 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 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.grid import * +import wx + +#------------------------------------------------------------------------------- +# 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 SetMode(self, mode): + pass + + 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() diff -r 36d378bd852e -r dae55dd9ee14 SFCViewer.py --- a/SFCViewer.py Sat Jul 07 11:35:17 2007 +0200 +++ b/SFCViewer.py Mon Jul 09 11:10:14 2007 +0200 @@ -23,7 +23,6 @@ #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from wxPython.wx import * -from wxPython.grid import * import wx from types import * @@ -31,6 +30,7 @@ from graphics.GraphicCommons import * from graphics.SFC_Objects import * from Viewer import * +from Dialogs import * class SFC_Viewer(Viewer): @@ -178,8 +178,11 @@ #------------------------------------------------------------------------------- def OnViewerLeftDown(self, event): - if self.Mode == MODE_SELECTION: - pos = event.GetPosition() + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerLeftDown(self, event) + elif self.Mode == MODE_SELECTION: + dc = self.GetLogicalDC() + pos = event.GetLogicalPosition(dc) if event.ControlDown(): element = self.FindElement(pos, True) if element and element not in self.Wires: @@ -207,16 +210,16 @@ self.Refresh() if element: self.SelectedElement = element - self.SelectedElement.OnLeftDown(event, self.Scaling) + self.SelectedElement.OnLeftDown(event, dc, self.Scaling) self.Refresh() else: self.rubberBand.Reset() - self.rubberBand.OnLeftDown(event, self.Scaling) + self.rubberBand.OnLeftDown(event, dc, self.Scaling) elif self.Mode == MODE_COMMENT: self.rubberBand.Reset() - self.rubberBand.OnLeftDown(event, self.Scaling) + self.rubberBand.OnLeftDown(event, self.GetLogicalDC(), self.Scaling) elif self.Mode == MODE_WIRE: - pos = GetScaledEventPosition(event, self.Scaling) + pos = GetScaledEventPosition(event, self.GetLogicalDC(), self.Scaling) wire = Wire(self, [wxPoint(pos.x, pos.y), SOUTH], [wxPoint(pos.x, pos.y), NORTH]) wire.oldPos = pos wire.Handle = (HANDLE_POINT, 0) @@ -231,10 +234,12 @@ event.Skip() def OnViewerLeftUp(self, event): - if self.rubberBand.IsShown(): + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerLeftUp(self, event) + elif self.rubberBand.IsShown(): if self.Mode == MODE_SELECTION: elements = self.SearchElements(self.rubberBand.GetCurrentExtent()) - self.rubberBand.OnLeftUp(event, self.Scaling) + self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) if len(elements) > 0: self.SelectedElement = Graphic_Group(self) self.SelectedElement.SetElements(elements) @@ -242,21 +247,21 @@ self.Refresh() elif self.Mode == MODE_COMMENT: bbox = self.rubberBand.GetCurrentExtent() - self.rubberBand.OnLeftUp(event, self.Scaling) + self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) wxCallAfter(self.AddComment, bbox) - elif self.Mode == MODE_INITIAL_STEP: - wxCallAfter(self.AddInitialStep, GetScaledEventPosition(event, self.Scaling)) + elif self.Mode == MODE_INITIALSTEP: + wxCallAfter(self.AddInitialStep, GetScaledEventPosition(event, self.GetLogicalDC(), self.Scaling)) elif self.Mode == MODE_SELECTION and self.SelectedElement: if self.SelectedElement in self.Wires: self.SelectedElement.SetSelectedSegment(0) else: - self.SelectedElement.OnLeftUp(event, self.Scaling) + self.SelectedElement.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) wxCallAfter(self.SetCursor, wxNullCursor) self.ReleaseMouse() self.Refresh() elif self.Mode == MODE_WIRE and self.SelectedElement: self.SelectedElement.ResetPoints() - self.SelectedElement.OnMotion(event, self.Scaling) + self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling) self.SelectedElement.GeneratePoints() self.SelectedElement.RefreshModel() self.SelectedElement.SetSelected(True) @@ -264,40 +269,49 @@ event.Skip() def OnViewerRightUp(self, event): - pos = event.GetPosition() - element = self.FindElement(pos) - if element: - if self.SelectedElement and self.SelectedElement != element: - self.SelectedElement.SetSelected(False) - self.SelectedElement = element - if self.SelectedElement in self.Wires: - self.SelectedElement.SetSelectedSegment(0) - else: - self.SelectedElement.SetSelected(True) - self.SelectedElement.OnRightUp(event, self.Scaling) - wxCallAfter(self.SetCursor, wxNullCursor) - self.ReleaseMouse() - self.Refresh() + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerRightUp(self, event) + else: + dc = self.GetLogicalDC() + pos = event.GetLogicalPosition(dc) + element = self.FindElement(pos) + if element: + if self.SelectedElement and self.SelectedElement != element: + self.SelectedElement.SetSelected(False) + self.SelectedElement = element + if self.SelectedElement in self.Wires: + self.SelectedElement.SetSelectedSegment(0) + else: + self.SelectedElement.SetSelected(True) + self.SelectedElement.OnRightUp(event, dc, self.Scaling) + wxCallAfter(self.SetCursor, wxNullCursor) + self.ReleaseMouse() + self.Refresh() event.Skip() def OnViewerLeftDClick(self, event): - if self.Mode == MODE_SELECTION and self.SelectedElement: - self.SelectedElement.OnLeftDClick(event, self.Scaling) + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerLeftDClick(self, event) + elif self.Mode == MODE_SELECTION and self.SelectedElement: + self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling) self.Refresh() event.Skip() def OnViewerMotion(self, event): - if self.rubberBand.IsShown(): - self.rubberBand.OnMotion(event, self.Scaling) + if self.GetDrawingMode() == FREEDRAWING_MODE: + Viewer.OnViewerMotion(self, event) + elif self.rubberBand.IsShown(): + self.rubberBand.OnMotion(event, self.GetLogicalDC(), self.Scaling) elif self.Mode == MODE_SELECTION and self.SelectedElement: if self.SelectedElement not in self.Wires: - self.SelectedElement.OnMotion(event, self.Scaling) + self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling) self.Refresh() elif self.Mode == MODE_WIRE and self.SelectedElement: self.SelectedElement.ResetPoints() - self.SelectedElement.OnMotion(event, self.Scaling) + self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling) self.SelectedElement.GeneratePoints() self.Refresh() + Viewer.OnViewerMotion(self, event) event.Skip() #------------------------------------------------------------------------------- @@ -1017,659 +1031,3 @@ def DeleteWire(self, wire): pass - -#------------------------------------------------------------------------------- -# Edit Transition Content Dialog -#------------------------------------------------------------------------------- - -[wxID_TRANSITIONCONTENTDIALOG, wxID_TRANSITIONCONTENTDIALOGMAINPANEL, - wxID_TRANSITIONCONTENTDIALOGREFERENCE, wxID_TRANSITIONCONTENTDIALOGINLINE, - wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, -] = [wx.NewId() for _init_ctrls in range(6)] - -class TransitionContentDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_TRANSITIONCONTENTDIALOG, - name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(300, 200), style=wx.DEFAULT_DIALOG_STYLE, - title='Edit transition') - self.SetClientSize(wx.Size(300, 200)) - - self.MainPanel = wx.Panel(id=wxID_TRANSITIONCONTENTDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(300, 200), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.radioButton1 = wx.RadioButton(id=wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, - label='Reference', name='radioButton1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(114, 24), style=0) - EVT_RADIOBUTTON(self, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON1, self.OnTypeChanged) - self.radioButton1.SetValue(True) - - self.Reference = wx.Choice(id=wxID_TRANSITIONCONTENTDIALOGREFERENCE, - name='Reference', parent=self.MainPanel, pos=wx.Point(48, 48), - size=wx.Size(200, 24), style=0) - - self.radioButton2 = wx.RadioButton(id=wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, - label='Inline', name='radioButton2', parent=self.MainPanel, - pos=wx.Point(24, 72), size=wx.Size(114, 24), style=0) - EVT_RADIOBUTTON(self, wxID_TRANSITIONCONTENTDIALOGRADIOBUTTON2, self.OnTypeChanged) - self.radioButton2.SetValue(False) - - self.Inline = wx.TextCtrl(id=wxID_TRANSITIONCONTENTDIALOGINLINE, - name='Inline', parent=self.MainPanel, pos=wx.Point(48, 96), - size=wx.Size(200, 24), style=0) - - self._init_sizers() - - def __init__(self, parent): - self._init_ctrls(parent) - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - - EVT_BUTTON(self, self.ButtonSizer.GetAffirmativeButton().GetId(), self.OnOK) - - def OnOK(self, event): - error = [] - if self.radioButton1.GetValue() and self.Reference.GetStringSelection() == "": - error.append("Reference") - if self.radioButton2.GetValue() and self.Inline.GetValue() == "": - error.append("Inline") - if len(error) > 0: - text = "" - for i, item in enumerate(error): - if i == 0: - text += item - elif i == len(error) - 1: - text += " and %s"%item - else: - text += ", %s"%item - message = wxMessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - else: - self.EndModal(wxID_OK) - - def OnTypeChanged(self, event): - if self.radioButton1.GetValue(): - self.Reference.Enable(True) - self.Inline.Enable(False) - else: - self.Reference.Enable(False) - self.Inline.Enable(True) - event.Skip() - - def SetTransitions(self, transitions): - for transition in transitions: - self.Reference.Append(transition) - - def SetValues(self, values): - if values["type"] == "reference": - self.radioButton1.SetValue(True) - self.radioButton2.SetValue(False) - self.Reference.Enable(True) - self.Inline.Enable(False) - self.Reference.SetStringSelection(values["value"]) - elif values["type"] == "inline": - self.radioButton1.SetValue(False) - self.radioButton2.SetValue(True) - self.Reference.Enable(False) - self.Inline.Enable(True) - self.Inline.SetValue(values["value"]) - - def GetValues(self): - values = {} - if self.radioButton1.GetValue(): - values["type"] = "reference" - values["value"] = self.Reference.GetStringSelection() - else: - values["type"] = "inline" - values["value"] = self.Inline.GetValue() - return values - -#------------------------------------------------------------------------------- -# Create New Divergence Dialog -#------------------------------------------------------------------------------- - -[wxID_DIVERGENCECREATEDIALOG, wxID_DIVERGENCECREATEDIALOGMAINPANEL, - wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, - wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, - wxID_DIVERGENCECREATEDIALOGSEQUENCES, wxID_DIVERGENCECREATEDIALOGPREVIEW, - wxID_DIVERGENCECREATEDIALOGSTATICTEXT1, wxID_DIVERGENCECREATEDIALOGSTATICTEXT2, - wxID_DIVERGENCECREATEDIALOGSTATICTEXT3, -] = [wx.NewId() for _init_ctrls in range(11)] - -class DivergenceCreateDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_DIVERGENCECREATEDIALOG, - name='DivergencePropertiesDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE, - title='Create a new divergence or convergence') - self.SetClientSize(wx.Size(500, 260)) - - self.MainPanel = wx.Panel(id=wxID_DIVERGENCECREATEDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(600, 220), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.staticText1 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT1, - label='Type:', name='staticText1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(200, 17), style=0) - - self.radioButton1 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, - label='Selection Divergence', name='radioButton1', parent=self.MainPanel, - pos=wx.Point(24, 48), size=wx.Size(200, 24), style=0) - EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON1, self.OnTypeChanged) - self.radioButton1.SetValue(True) - - self.radioButton2 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, - label='Selection Convergence', name='radioButton2', parent=self.MainPanel, - pos=wx.Point(24, 72), size=wx.Size(200, 24), style=0) - EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON2, self.OnTypeChanged) - self.radioButton2.SetValue(False) - - self.radioButton3 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, - label='Simultaneous Divergence', name='radioButton3', parent=self.MainPanel, - pos=wx.Point(24, 96), size=wx.Size(200, 24), style=0) - EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON3, self.OnTypeChanged) - self.radioButton3.SetValue(False) - - self.radioButton4 = wx.RadioButton(id=wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, - label='Simultaneous Convergence', name='radioButton4', parent=self.MainPanel, - pos=wx.Point(24, 120), size=wx.Size(200, 24), style=0) - EVT_RADIOBUTTON(self, wxID_DIVERGENCECREATEDIALOGRADIOBUTTON4, self.OnTypeChanged) - self.radioButton4.SetValue(False) - - self.staticText2 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT2, - label='Number of sequences:', name='staticText2', parent=self.MainPanel, - pos=wx.Point(24, 150), size=wx.Size(200, 17), style=0) - - self.Sequences = wx.SpinCtrl(id=wxID_DIVERGENCECREATEDIALOGSEQUENCES, - name='Sequences', parent=self.MainPanel, pos=wx.Point(24, 174), - size=wx.Size(200, 24), style=0, min=2, max=20) - EVT_SPINCTRL(self, wxID_DIVERGENCECREATEDIALOGSEQUENCES, self.OnSequencesChanged) - - self.staticText3 = wx.StaticText(id=wxID_DIVERGENCECREATEDIALOGSTATICTEXT3, - label='Preview:', name='staticText3', parent=self.MainPanel, - pos=wx.Point(250, 24), size=wx.Size(100, 17), style=0) - - self.Preview = wx.Panel(id=wxID_DIVERGENCECREATEDIALOGPREVIEW, - name='Preview', parent=self.MainPanel, pos=wx.Point(250, 48), - size=wx.Size(225, 150), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER) - self.Preview.SetBackgroundColour(wxColour(255,255,255)) - - self._init_sizers() - - def __init__(self, parent): - self._init_ctrls(parent) - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - - self.Divergence = None - - EVT_PAINT(self, self.OnPaint) - - def GetValues(self): - values = {} - if self.radioButton1.GetValue(): - values["type"] = SELECTION_DIVERGENCE - elif self.radioButton2.GetValue(): - values["type"] = SELECTION_CONVERGENCE - elif self.radioButton3.GetValue(): - values["type"] = SIMULTANEOUS_DIVERGENCE - else: - values["type"] = SIMULTANEOUS_CONVERGENCE - values["number"] = self.Sequences.GetValue() - return values - - def OnTypeChanged(self, event): - self.RefreshPreview() - event.Skip() - - def OnSequencesChanged(self, event): - self.RefreshPreview() - event.Skip() - - def RefreshPreview(self): - dc = wxClientDC(self.Preview) - dc.Clear() - if self.radioButton1.GetValue(): - self.Divergence = SFC_Divergence(self.Preview, SELECTION_DIVERGENCE, self.Sequences.GetValue()) - elif self.radioButton2.GetValue(): - self.Divergence = SFC_Divergence(self.Preview, SELECTION_CONVERGENCE, self.Sequences.GetValue()) - elif self.radioButton3.GetValue(): - self.Divergence = SFC_Divergence(self.Preview, SIMULTANEOUS_DIVERGENCE, self.Sequences.GetValue()) - else: - self.Divergence = SFC_Divergence(self.Preview, SIMULTANEOUS_CONVERGENCE, self.Sequences.GetValue()) - width, height = self.Divergence.GetSize() - clientsize = self.Preview.GetClientSize() - x = (clientsize.width - width) / 2 - y = (clientsize.height - height) / 2 - self.Divergence.SetPosition(x, y) - self.Divergence.Draw(dc) - - def OnPaint(self, event): - self.RefreshPreview() - - -#------------------------------------------------------------------------------- -# Action Block Dialog -#------------------------------------------------------------------------------- - -class ActionTable(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 - # 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 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 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.Parent.ColAlignements[col], wxALIGN_CENTRE) - grid.SetColAttr(col, attr) - grid.SetColSize(col, self.Parent.ColSizes[col]) - - typelist = None - accesslist = None - for row in range(self.GetNumberRows()): - for col in range(self.GetNumberCols()): - editor = None - renderer = None - readonly = False - colname = self.GetColLabelValue(col) - if colname == "Qualifier": - editor = wxGridCellChoiceEditor() - editor.SetParameters(self.Parent.QualifierList) - if colname == "Duration": - editor = wxGridCellTextEditor() - renderer = wxGridCellStringRenderer() - if self.Parent.DurationList[self.data[row]["Qualifier"]]: - readonly = False - else: - readonly = True - self.data[row]["Duration"] = "" - elif colname == "Type": - editor = wxGridCellChoiceEditor() - editor.SetParameters(self.Parent.TypeList) - elif colname == "Value": - type = self.data[row]["Type"] - if type == "Action": - editor = wxGridCellChoiceEditor() - editor.SetParameters(self.Parent.ActionList) - elif type == "Variable": - editor = wxGridCellChoiceEditor() - editor.SetParameters(self.Parent.VariableList) - elif type == "Inline": - editor = wxGridCellTextEditor() - renderer = wxGridCellStringRenderer() - elif colname == "Indicator": - editor = wxGridCellChoiceEditor() - editor.SetParameters(self.Parent.VariableList) - - grid.SetCellEditor(row, col, editor) - grid.SetCellRenderer(row, col, renderer) - grid.SetReadOnly(row, col, readonly) - - 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_ACTIONBLOCKDIALOG, wxID_ACTIONBLOCKDIALOGMAINPANEL, - wxID_ACTIONBLOCKDIALOGVARIABLESGRID, wxID_ACTIONBLOCKDIALOGSTATICTEXT1, - wxID_ACTIONBLOCKDIALOGADDBUTTON,wxID_ACTIONBLOCKDIALOGDELETEBUTTON, - wxID_ACTIONBLOCKDIALOGUPBUTTON, wxID_ACTIONBLOCKDIALOGDOWNBUTTON, -] = [wx.NewId() for _init_ctrls in range(8)] - -class ActionBlockDialog(wx.Dialog): - def _init_coll_flexGridSizer1_Items(self, parent): - # generated method, don't edit - - parent.AddWindow(self.MainPanel, 0, border=0, flag=0) - - def _init_sizers(self): - # generated method, don't edit - self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) - - self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) - - self.SetSizer(self.flexGridSizer1) - - def _init_ctrls(self, prnt): - # generated method, don't edit - wx.Dialog.__init__(self, id=wxID_ACTIONBLOCKDIALOG, - name='ActionBlockDialog', parent=prnt, pos=wx.Point(376, 223), - size=wx.Size(500, 300), style=wx.DEFAULT_DIALOG_STYLE, - title='Edit action block properties') - self.SetClientSize(wx.Size(500, 300)) - - self.MainPanel = wx.Panel(id=wxID_ACTIONBLOCKDIALOGMAINPANEL, - name='MainPanel', parent=self, pos=wx.Point(0, 0), - size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL) - self.MainPanel.SetAutoLayout(True) - - self.staticText1 = wx.StaticText(id=wxID_ACTIONBLOCKDIALOGSTATICTEXT1, - label='Actions:', name='staticText1', parent=self.MainPanel, - pos=wx.Point(24, 24), size=wx.Size(95, 17), style=0) - - self.ActionsGrid = wx.grid.Grid(id=wxID_ACTIONBLOCKDIALOGVARIABLESGRID, - name='ActionsGrid', parent=self.MainPanel, pos=wx.Point(24, 44), - size=wx.Size(450, 150), style=wxVSCROLL) - self.ActionsGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, - 'Sans')) - self.ActionsGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, - False, 'Sans')) - self.ActionsGrid.DisableDragGridSize() - self.ActionsGrid.EnableScrolling(False, True) - EVT_GRID_CELL_CHANGE(self.ActionsGrid, self.OnActionsGridCellChange) - - self.AddButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGADDBUTTON, label='Add', - name='AddButton', parent=self.MainPanel, pos=wx.Point(245, 204), - size=wx.Size(72, 32), style=0) - EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGADDBUTTON, self.OnAddButton) - - self.DeleteButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGDELETEBUTTON, label='Delete', - name='DeleteButton', parent=self.MainPanel, pos=wx.Point(325, 204), - size=wx.Size(72, 32), style=0) - EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGDELETEBUTTON, self.OnDeleteButton) - - self.UpButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGUPBUTTON, label='^', - name='UpButton', parent=self.MainPanel, pos=wx.Point(405, 204), - size=wx.Size(32, 32), style=0) - EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGUPBUTTON, self.OnUpButton) - - self.DownButton = wx.Button(id=wxID_ACTIONBLOCKDIALOGDOWNBUTTON, label='v', - name='DownButton', parent=self.MainPanel, pos=wx.Point(445, 204), - size=wx.Size(32, 32), style=0) - EVT_BUTTON(self, wxID_ACTIONBLOCKDIALOGDOWNBUTTON, self.OnDownButton) - - self._init_sizers() - - def __init__(self, parent): - self._init_ctrls(parent) - self.ButtonSizer = self.CreateButtonSizer(wxOK|wxCANCEL|wxCENTRE) - self.flexGridSizer1.Add(self.ButtonSizer, 1, wxALIGN_RIGHT) - - self.DefaultValue = {"Qualifier" : "N", "Duration" : "", "Type" : "Action", "Value" : "", "Indicator" : ""} - self.Table = ActionTable(self, [], ["Qualifier","Duration","Type","Value","Indicator"]) - self.TypeList = "Action,Variable,Inline" - self.ColSizes = [60, 90, 80, 110, 80] - self.ColAlignements = [wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT, wxALIGN_LEFT] - - self.ActionsGrid.SetTable(self.Table) - self.ActionsGrid.SetRowLabelSize(0) - - self.Table.ResetView(self.ActionsGrid) - - def OnAddButton(self, event): - self.Table.AppendRow(self.DefaultValue.copy()) - self.Table.ResetView(self.ActionsGrid) - event.Skip() - - def OnDeleteButton(self, event): - row = self.ActionsGrid.GetGridCursorRow() - self.Table.RemoveRow(row) - self.Table.ResetView(self.ActionsGrid) - event.Skip() - - def OnUpButton(self, event): - row = self.ActionsGrid.GetGridCursorRow() - self.Table.MoveRow(row, -1, self.ActionsGrid) - self.Table.ResetView(self.ActionsGrid) - event.Skip() - - def OnDownButton(self, event): - row = self.ActionsGrid.GetGridCursorRow() - self.Table.MoveRow(row, 1, self.ActionsGrid) - self.Table.ResetView(self.ActionsGrid) - event.Skip() - - def OnActionsGridCellChange(self, event): - self.Table.ResetView(self.ActionsGrid) - event.Skip() - - def SetQualifierList(self, list): - self.QualifierList = "" - sep = "" - for qualifier in list.keys(): - self.QualifierList += "%s%s"%(sep, qualifier) - sep = "," - self.DurationList = list - - def SetVariableList(self, list): - self.VariableList = "" - sep = "" - for variable in list: - self.VariableList += "%s%s"%(sep, variable["Name"]) - sep = "," - - def SetActionList(self, list): - self.ActionList = "" - sep = "" - for action in list: - self.ActionList += "%s%s"%(sep, action) - sep = "," - - def SetValues(self, actions): - for action in actions: - row = {"Qualifier" : action["qualifier"], "Value" : action["value"]} - if action["type"] == "reference": - if action["value"] in self.ActionList: - row["Type"] = "Action" - elif action["value"] in self.VariableList: - row["Type"] = "Variable" - else: - row["Type"] = "Inline" - else: - row["Type"] = "Inline" - if "duration" in action: - row["Duration"] = action["duration"] - else: - row["Duration"] = "" - if "indicator" in action: - row["Indicator"] = action["indicator"] - else: - row["Indicator"] = "" - self.Table.AppendRow(row) - self.Table.ResetView(self.ActionsGrid) - - def GetValues(self): - values = [] - for data in self.Table.GetData(): - print data - action = {"qualifier" : data["Qualifier"], "value" : data["Value"]} - if data["Type"] in ["Action", "Variable"]: - action["type"] = "reference" - else: - action["type"] = "inline" - if data["Duration"] != "": - action["duration"] = data["Duration"] - if data["Indicator"] != "": - action["indicator"] = data["Indicator"] - values.append(action) - return values - - -#------------------------------------------------------------------------------- -# Edit Step Name Dialog -#------------------------------------------------------------------------------- - -class StepNameDialog(wxTextEntryDialog): - - def __init__(self, parent, message, caption = "Please enter text", defaultValue = "", - style = wxOK|wxCANCEL|wxCENTRE, pos = wxDefaultPosition): - wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) - - self.PouNames = [] - self.Variables = [] - self.StepNames = [] - - EVT_BUTTON(self, self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId(), self.OnOK) - - def OnOK(self, event): - step_name = self.GetSizer().GetItem(1).GetWindow().GetValue() - if step_name == "": - message = wxMessageDialog(self, "You must type a name!", "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - elif not TestIdentifier(step_name): - message = wxMessageDialog(self, "\"%s\" is not a valid identifier!"%step_name, "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - elif step_name.upper() in IEC_KEYWORDS: - message = wxMessageDialog(self, "\"%s\" is a keyword. It can't be used!"%step_name, "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - elif step_name.upper() in self.PouNames: - message = wxMessageDialog(self, "A pou with \"%s\" as name exists!"%step_name, "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - elif step_name.upper() in self.Variables: - message = wxMessageDialog(self, "A variable with \"%s\" as name exists!"%step_name, "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - elif step_name.upper() in self.StepNames: - message = wxMessageDialog(self, "\"%s\" step already exists!"%step_name, "Error", wxOK|wxICON_ERROR) - message.ShowModal() - message.Destroy() - else: - self.EndModal(wxID_OK) - - def SetPouNames(self, pou_names): - self.PouNames = [pou_name.upper() for pou_name in pou_names] - - def SetVariables(self, variables): - self.Variables = [var["Name"].upper() for var in variables] - - def SetStepNames(self, step_names): - self.StepNames = [step_name.upper() for step_name in step_names] diff -r 36d378bd852e -r dae55dd9ee14 TextViewer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextViewer.py Mon Jul 09 11:10:14 2007 +0200 @@ -0,0 +1,321 @@ +#!/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 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 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 * +import wx + +import re + +#------------------------------------------------------------------------------- +# 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.SetUseTabs(0) + + self.Keywords = [] + self.Variables = [] + self.Functions = [] + self.Jumps = [] + self.TextChanged = False + self.TextSyntax = "ST" + + self.Controler = controler + + EVT_KEY_DOWN(self, self.OnKeyDown) + EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded) + EVT_KILL_FOCUS(self, self.OnKillFocus) + + def SetTextSyntax(self, syntax): + self.TextSyntax = syntax + + 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() + + # Code completion + if key == WXK_SPACE and event.ControlDown(): + + line = self.GetCurrentLine() + if line == 0: + start_pos = 0 + else: + start_pos = self.GetLineEndPosition(line - 1) + 1 + end_pos = self.GetCurrentPos() + + lineText = self.GetTextRange(start_pos, end_pos).replace("\t", " ") + words = lineText.split(" ") + words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1] + + kw = [] + + if self.TextSyntax == "IL": + if len(words) == 1: + kw = self.Keywords + elif len(words) == 2: + if words[0].upper() in ["CAL", "CALC", "CALNC"]: + kw = self.Functions + elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]: + kw = self.Jumps + else: + kw = self.Variables + else: + kw = self.Keywords + self.Variables + self.Functions + if len(kw) > 0: + kw.sort() + self.AutoCompSetIgnoreCase(True) + self.AutoCompShow(len(words[-1]), " ".join(kw)) + else: + self.TextChanged = False + wxCallAfter(self.RefreshModel) + event.Skip() + + def OnKillFocus(self, event): + self.AutoCompCancel() + event.Skip() + diff -r 36d378bd852e -r dae55dd9ee14 Viewer.py --- a/Viewer.py Sat Jul 07 11:35:17 2007 +0200 +++ b/Viewer.py Mon Jul 09 11:10:14 2007 +0200 @@ -23,17 +23,19 @@ #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 +from graphics.SFC_Objects import * + +from Dialogs import * + +SCROLLBAR_UNIT = 10 +WINDOW_BORDER = 10 +SCROLL_ZONE = 10 #------------------------------------------------------------------------------- # Graphic elements Viewer base class @@ -107,7 +109,7 @@ # Create a new Viewer def __init__(self, parent, window, controler): - wx.ScrolledWindow.__init__(self, parent, style=wx.SUNKEN_BORDER) + wx.ScrolledWindow.__init__(self, parent, style=wx.SUNKEN_BORDER | wx.HSCROLL | wx.VSCROLL) self._init_menus() # Adding a rubberband to Viewer self.rubberBand = RubberBand(drawingSurface=self) @@ -133,6 +135,8 @@ EVT_RIGHT_UP(self, self.OnViewerRightUp) EVT_MOTION(self, self.OnViewerMotion) EVT_CHAR(self, self.OnChar) + EVT_SCROLLWIN(self, self.OnMoveWindow) + EVT_SIZE(self, self.OnMoveWindow) # Returns a new id def GetNewId(self): @@ -143,6 +147,11 @@ def __del__(self): self.ResetView() + def GetLogicalDC(self): + dc = wxClientDC(self) + self.DoPrepareDC(dc) + return dc + #------------------------------------------------------------------------------- # Reset functions #------------------------------------------------------------------------------- @@ -167,6 +176,10 @@ self.SelectedElement = None self.Refresh() + # Return current drawing mode + def GetDrawingMode(self): + return self.Parent.GetDrawingMode() + #------------------------------------------------------------------------------- # Refresh functions #------------------------------------------------------------------------------- @@ -184,8 +197,27 @@ instance = self.Controler.GetCurrentElementEditingInstanceInfos(exclude=ids) if instance: self.loadInstance(instance, ids) + self.RefreshScrollBar() self.Refresh() + def RefreshScrollBar(self): + xstart, ystart = self.GetViewStart() + window_size = self.GetClientSize() + maxx = maxy = 0 + for element in self.Elements: + posx, posy = element.GetPosition() + width, height = element.GetSize() + maxx = max(maxx, posx + width) + maxy = max(maxy, posy + height) + maxx = max(maxx + WINDOW_BORDER, xstart * SCROLLBAR_UNIT + window_size[0]) + maxy = max(maxy + WINDOW_BORDER, ystart * SCROLLBAR_UNIT + window_size[1]) + if self.rubberBand.IsShown(): + extent = self.rubberBand.GetCurrentExtent() + maxx = max(maxx, extent.x + extent.width) + maxy = max(maxy, extent.y + extent.height) + self.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, + maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, xstart, ystart) + # Load instance from given informations def loadInstance(self, instance, ids): ids.append(instance["id"]) @@ -432,7 +464,7 @@ connected = self.FindElementById(refLocalId) if connected: points = link["points"] - end_connector = connected.GetConnector(wxPoint(points[-1][0], points[-1][1])) + end_connector = connected.GetConnector(wxPoint(points[-1][0], points[-1][1]), link["formalParameter"]) if end_connector: wire = Wire(self) wire.SetPoints(points) @@ -629,18 +661,180 @@ #------------------------------------------------------------------------------- def OnViewerLeftDown(self, event): + if self.Mode == MODE_SELECTION: + dc = self.GetLogicalDC() + pos = event.GetLogicalPosition(dc) + if event.ControlDown() and self.SelectedElement: + element = self.FindElement(pos, True) + if element: + if isinstance(self.SelectedElement, Graphic_Group): + self.SelectedElement.SetSelected(False) + self.SelectedElement.SelectElement(element) + elif self.SelectedElement: + group = Graphic_Group(self) + group.SelectElement(self.SelectedElement) + group.SelectElement(element) + self.SelectedElement = group + elements = self.SelectedElement.GetElements() + if len(elements) == 0: + self.SelectedElement = element + elif len(elements) == 1: + self.SelectedElement = elements[0] + self.SelectedElement.SetSelected(True) + else: + element = self.FindElement(pos) + if self.SelectedElement and self.SelectedElement != element: + self.SelectedElement.SetSelected(False) + self.SelectedElement = None + self.Refresh() + if element: + self.SelectedElement = element + self.SelectedElement.OnLeftDown(event, dc, self.Scaling) + self.Refresh() + else: + self.rubberBand.Reset() + self.rubberBand.OnLeftDown(event, dc, self.Scaling) + elif self.Mode in [MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, + MODE_CONTACT, MODE_COIL, MODE_POWERRAIL, MODE_INITIALSTEP, + MODE_STEP, MODE_TRANSITION, MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION]: + self.rubberBand.Reset() + self.rubberBand.OnLeftDown(event, self.GetLogicalDC(), self.Scaling) + elif self.Mode == MODE_WIRE: + pos = GetScaledEventPosition(event, self.GetLogicalDC(), self.Scaling) + connector = self.FindBlockConnector(pos) + if connector: + if (connector.GetDirection() == EAST): + wire = Wire(self, [wxPoint(pos.x, pos.y), EAST], [wxPoint(pos.x, pos.y), WEST]) + else: + wire = Wire(self, [wxPoint(pos.x, pos.y), WEST], [wxPoint(pos.x, pos.y), EAST]) + wire.oldPos = pos + wire.Handle = (HANDLE_POINT, 0) + wire.ProcessDragging(0, 0) + wire.Handle = (HANDLE_POINT, 1) + self.Wires.append(wire) + self.Elements.append(wire) + if self.SelectedElement: + self.SelectedElement.SetSelected(False) + self.SelectedElement = wire + elif self.SelectedElement: + self.SelectedElement.SetSelected(False) + self.SelectedElement = None + self.Refresh() event.Skip() def OnViewerLeftUp(self, event): + if self.rubberBand.IsShown(): + if self.Mode == MODE_SELECTION: + elements = self.SearchElements(self.rubberBand.GetCurrentExtent()) + self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) + if len(elements) > 0: + self.SelectedElement = Graphic_Group(self) + self.SelectedElement.SetElements(elements) + self.SelectedElement.SetSelected(True) + self.Refresh() + else: + bbox = self.rubberBand.GetCurrentExtent() + self.rubberBand.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) + if self.Mode == MODE_BLOCK: + wxCallAfter(self.AddNewBlock, bbox) + elif self.Mode == MODE_VARIABLE: + wxCallAfter(self.AddNewVariable, bbox) + elif self.Mode == MODE_CONNECTION: + wxCallAfter(self.AddNewConnection, bbox) + elif self.Mode == MODE_COMMENT: + wxCallAfter(self.AddNewComment, bbox) + elif self.Mode == MODE_CONTACT: + wxCallAfter(self.AddNewContact, bbox) + elif self.Mode == MODE_COIL: + wxCallAfter(self.AddNewContact, bbox) + elif self.Mode == MODE_POWERRAIL: + wxCallAfter(self.AddNewPowerRail, bbox) + elif self.Mode == MODE_INITIALSTEP: + wxCallAfter(self.AddNewInitialStep, bbox) + elif self.Mode == MODE_STEP: + wxCallAfter(self.AddNewStep, bbox) + elif self.Mode == MODE_TRANSITION: + wxCallAfter(self.AddNewTransition, bbox) + elif self.Mode == MODE_DIVERGENCE: + wxCallAfter(self.AddNewDivergence, bbox) + elif self.Mode == MODE_JUMP: + wxCallAfter(self.AddNewJump, bbox) + elif self.Mode == MODE_ACTION: + wxCallAfter(self.AddNewActionBlock, bbox) + elif self.Mode == MODE_SELECTION and self.SelectedElement: + self.SelectedElement.OnLeftUp(event, self.GetLogicalDC(), self.Scaling) + wxCallAfter(self.SetCursor, wxNullCursor) + self.ReleaseMouse() + self.Refresh() + elif self.Mode == MODE_WIRE and self.SelectedElement: + dc = self.GetLogicalDC() + pos = GetScaledEventPosition(event, dc, self.Scaling) + connector = self.FindBlockConnector(pos, False) + if connector and connector != self.SelectedElement.StartConnected: + self.SelectedElement.ResetPoints() + self.SelectedElement.OnMotion(event, dc, self.Scaling) + self.SelectedElement.GeneratePoints() + self.SelectedElement.RefreshModel() + self.SelectedElement.SetSelected(True) + else: + self.SelectedElement.Delete() + self.SelectedElement = None + self.Refresh() + if not self.SavedMode: + wxCallAfter(self.Parent.ResetCurrentMode) event.Skip() def OnViewerRightUp(self, event): + pos = event.GetPosition() + element = self.FindElement(pos) + if element: + if self.SelectedElement and self.SelectedElement != element: + self.SelectedElement.SetSelected(False) + self.SelectedElement = element + self.SelectedElement.SetSelected(True) + self.SelectedElement.OnRightUp(event, self.GetLogicalDC(), self.Scaling) + wxCallAfter(self.SetCursor, wxNullCursor) + self.ReleaseMouse() + self.Refresh() event.Skip() def OnViewerLeftDClick(self, event): + if self.Mode == MODE_SELECTION and self.SelectedElement: + self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling) + self.Refresh() event.Skip() def OnViewerMotion(self, event): + if self.rubberBand.IsShown(): + self.rubberBand.OnMotion(event, self.GetLogicalDC(), self.Scaling) + elif self.Mode == MODE_SELECTION and self.SelectedElement: + self.SelectedElement.OnMotion(event, self.GetLogicalDC(), self.Scaling) + self.Refresh() + elif self.Mode == MODE_WIRE and self.SelectedElement: + dc = self.GetLogicalDC() + pos = GetScaledEventPosition(event, dc, self.Scaling) + connector = self.FindBlockConnector(pos, False) + if not connector or self.SelectedElement.EndConnected == None: + self.SelectedElement.ResetPoints() + self.SelectedElement.OnMotion(event, dc, self.Scaling) + self.SelectedElement.GeneratePoints() + self.Refresh() + if (event.Dragging() and self.SelectedElement) or self.rubberBand.IsShown(): + position = event.GetPosition() + move_window = wxPoint() + window_size = self.GetClientSize() + xstart, ystart = self.GetViewStart() + if position.x < SCROLL_ZONE and xstart > 0: + move_window.x = -1 + elif position.x > window_size[0] - SCROLL_ZONE: + move_window.x = 1 + if position.y < SCROLL_ZONE and ystart > 0: + move_window.y = -1 + elif position.y > window_size[1] - SCROLL_ZONE: + move_window.y = 1 + if move_window.x != 0 or move_window.y != 0: + self.Scroll(xstart + move_window.x, ystart + move_window.y) + self.RefreshScrollBar() event.Skip() #------------------------------------------------------------------------------- @@ -648,7 +842,206 @@ #------------------------------------------------------------------------------- def OnChar(self, event): - event.Skip() + keycode = event.GetKeyCode() + if self.Scaling: + scaling = self.Scaling + else: + scaling = (8, 8) + if keycode == WXK_DELETE and self.SelectedElement: + self.SelectedElement.Clean() + self.SelectedElement.Delete() + self.SelectedElement = None + elif keycode == WXK_LEFT and self.SelectedElement: + self.SelectedElement.Move(-scaling[0], 0) + elif keycode == WXK_RIGHT and self.SelectedElement: + self.SelectedElement.Move(scaling[0], 0) + elif keycode == WXK_UP and self.SelectedElement: + self.SelectedElement.Move(0, -scaling[1]) + elif keycode == WXK_DOWN and self.SelectedElement: + self.SelectedElement.Move(0, scaling[1]) + self.Refresh() + event.Skip() + +#------------------------------------------------------------------------------- +# Model adding functions +#------------------------------------------------------------------------------- + + def AddNewBlock(self, bbox): + dialog = BlockPropertiesDialog(self.Parent) + dialog.SetBlockList(self.Controler.GetBlockTypes()) + dialog.SetMinBlockSize((bbox.width, bbox.height)) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + if "name" in values: + block = FBD_Block(self, values["type"], values["name"], id, values["extension"]) + else: + block = FBD_Block(self, values["type"], "", id, values["extension"]) + block.SetPosition(bbox.x, bbox.y) + block.SetSize(values["width"], values["height"]) + self.Blocks.append(block) + self.Elements.append(block) + self.Controler.AddCurrentElementEditingBlock(id) + self.RefreshBlockModel(block) + self.Refresh() + dialog.Destroy() + + def AddNewVariable(self, bbox): + dialog = VariablePropertiesDialog(self.Parent) + dialog.SetMinVariableSize((bbox.width, bbox.height)) + varlist = [] + vars = self.Controler.GetCurrentElementEditingInterfaceVars() + if vars: + for var in vars: + varlist.append((var["Name"], var["Class"], var["Type"])) + returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() + if returntype: + varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) + dialog.SetVariables(varlist) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + variable = FBD_Variable(self, values["type"], values["name"], values["value_type"], id) + variable.SetPosition(bbox.x, bbox.y) + variable.SetSize(values["width"], values["height"]) + self.Blocks.append(variable) + self.Elements.append(variable) + self.Controler.AddCurrentElementEditingVariable(id, values["type"]) + self.RefreshVariableModel(variable) + self.Refresh() + dialog.Destroy() + + def AddNewConnection(self, bbox): + dialog = ConnectionPropertiesDialog(self.Parent) + dialog.SetMinConnectionSize((bbox.width, bbox.height)) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + connection = FBD_Connector(self, values["type"], values["name"], id) + connection.SetPosition(bbox.x, bbox.y) + connection.SetSize(values["width"], values["height"]) + self.Blocks.append(connection) + self.Elements.append(connection) + self.Controler.AddCurrentElementEditingConnection(id, values["type"]) + self.RefreshConnectionModel(connection) + self.Refresh() + dialog.Destroy() + + def AddNewComment(self, bbox): + dialog = wxTextEntryDialog(self.Parent, "Add a new comment", "Please enter comment text", "", wxOK|wxCANCEL|wxTE_MULTILINE) + if dialog.ShowModal() == wxID_OK: + value = dialog.GetValue() + id = self.GetNewId() + comment = Comment(self, value, id) + comment.SetPosition(bbox.x, bbox.y) + min_width, min_height = comment.GetMinSize() + comment.SetSize(max(min_width,bbox.width),max(min_height,bbox.height)) + self.Elements.append(comment) + self.Controler.AddCurrentElementEditingComment(id) + self.RefreshCommentModel(comment) + self.Refresh() + dialog.Destroy() + + def AddNewContact(self, bbox): + dialog = LDElementDialog(self.Parent, "contact") + varlist = [] + vars = self.Controler.GetCurrentElementEditingInterfaceVars() + if vars: + for var in vars: + if var["Class"] != "Output" and var["Type"] == "BOOL": + varlist.append(var["Name"]) + dialog.SetVariables(varlist) + dialog.SetValues({"name":"","type":CONTACT_NORMAL}) + dialog.SetElementSize(bbox.width, bbox.height) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + contact = LD_Contact(self, values["type"], values["name"], id) + contact.SetPosition(bbox.x, bbox.y) + contact.SetSize(values["width"], values["height"]) + self.Blocks.append(contact) + self.Elements.append(contact) + self.Controler.AddCurrentElementEditingContact(id) + self.RefreshContactModel(contact) + self.Refresh() + dialog.Destroy() + + def AddNewCoil(self, bbox): + dialog = LDElementDialog(self.Parent, "coil") + varlist = [] + vars = self.Controler.GetCurrentElementEditingInterfaceVars() + if vars: + for var in vars: + if var["Class"] != "Input" and var["Type"] == "BOOL": + varlist.append(var["Name"]) + returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() + if returntype == "BOOL": + varlist.append(self.Controler.GetCurrentElementEditingName()) + dialog.SetVariables(varlist) + dialog.SetValues({"name":"","type":COIL_NORMAL}) + dialog.SetElementSize(bbox.width, bbox.height) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + coil = LD_Coil(self, values["type"], values["name"], id) + coil.SetPosition(bbox.x, bbox.y) + coil.SetSize(values["width"], values["height"]) + self.Blocks.append(coil) + self.Elements.append(coil) + self.Controler.AddCurrentElementEditingCoil(id) + self.RefreshCoilModel(contact) + self.Refresh() + dialog.Destroy() + + def AddNewPowerRail(self, bbox): + dialog = LDPowerRailDialog(self.Parent) + dialog.SetMinSize((bbox.width, bbox.height)) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + powerrail = LD_PowerRail(self, values["type"], id, [True for i in xrange(values["number"])]) + powerrail.SetPosition(bbox.x, bbox.y) + powerrail.SetSize(values["width"], values["height"]) + self.Blocks.append(powerrail) + self.Elements.append(powerrail) + self.Controler.AddCurrentElementEditingPowerRail(id, values["type"]) + self.RefreshPowerRailModel(powerrail) + self.Refresh() + dialog.Destroy() + + def AddNewTransition(self, bbox): + dialog = TransitionContentDialog(self.Parent) + dialog.SetTransitions(self.Controler.GetCurrentElementEditingTransitions()) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + transition = SFC_Transition(self, values["type"], values["value"], id) + transition.SetPosition(bbox.x, bbox.y) + min_width, min_height = transition.GetMinSize() + transition.SetSize(max(bbox.width, min_width), max(bbox.height, min_height)) + self.Blocks.append(transition) + self.Elements.append(transition) + self.Controler.AddCurrentElementEditingTransition(id) + self.RefreshTransitionModel(transition) + self.Refresh() + dialog.Destroy() + + def AddNewDivergence(self, bbox): + dialog = DivergenceCreateDialog(self.Parent) + dialog.SetMinSize((bbox.width, bbox.height)) + if dialog.ShowModal() == wxID_OK: + id = self.GetNewId() + values = dialog.GetValues() + divergence = SFC_Divergence(self, values["type"], values["number"], id) + divergence.SetPosition(bbox.x, bbox.y) + min_width, min_height = divergence.GetMinSize() + divergence.SetSize(max(bbox.width, min_width), max(bbox.height, min_height)) + self.Blocks.append(divergence) + self.Elements.append(divergence) + self.Controler.AddCurrentElementEditingDivergence(id, values["type"]) + self.RefreshDivergenceModel(divergence) + self.Refresh() + dialog.Destroy() #------------------------------------------------------------------------------- # Model update functions @@ -764,6 +1157,146 @@ infos["connector"] = actionblock.GetConnector() self.Controler.SetCurrentElementEditingActionBlockInfos(actionblockid, infos) + +#------------------------------------------------------------------------------- +# Model delete functions +#------------------------------------------------------------------------------- + + + def DeleteBlock(self, block): + elements = [] + for output in block.GetConnectors()["outputs"]: + for element in output.GetConnectedBlocks(): + if element not in elements: + elements.append(element) + block.Clean() + self.Blocks.remove(block) + self.Elements.remove(block) + self.Controler.RemoveCurrentElementEditingInstance(block.GetId()) + for element in elements: + element.RefreshModel() + + def DeleteVariable(self, variable): + connectors = variable.GetConnectors() + if connectors["output"]: + elements = connectors["output"].GetConnectedBlocks() + else: + elements = [] + variable.Clean() + self.Blocks.remove(variable) + self.Elements.remove(variable) + self.Controler.RemoveCurrentElementEditingInstance(variable.GetId()) + for element in elements: + element.RefreshModel() + + def DeleteConnection(self, connection): + if connection.GetType() == CONTINUATION: + elements = connection.GetConnector().GetConnectedBlocks() + else: + elements = [] + connection.Clean() + self.Blocks.remove(connection) + self.Elements.remove(connection) + self.Controler.RemoveCurrentElementEditingInstance(connection.GetId()) + for element in elements: + element.RefreshModel() + + def DeleteComment(self, comment): + self.Elements.remove(comment) + self.Controler.RemoveCurrentElementEditingInstance(comment.GetId()) + + def DeleteWire(self, wire): + connected = wire.GetConnected() + wire.Clean() + self.Wires.remove(wire) + self.Elements.remove(wire) + for connector in connected: + connector.RefreshParentBlock() + + def DeleteContact(self, contact): + connectors = contact.GetConnectors() + elements = connectors["output"].GetConnectedBlocks() + contact.Clean() + self.Blocks.remove(contact) + self.Elements.remove(contact) + self.Controler.RemoveCurrentElementEditingInstance(contact.GetId()) + for element in elements: + element.RefreshModel() + + def DeleteCoil(self, coil): + connectors = coil.GetConnectors() + elements = connectors["output"].GetConnectedBlocks() + coil.Clean() + self.Blocks.remove(coil) + self.Elements.remove(coil) + self.Controler.RemoveCurrentElementEditingInstance(coil.GetId()) + for element in elements: + element.RefreshModel() + + def DeletePowerRail(self, powerrail): + elements = [] + if powerrail.GetType() == LEFTRAIL: + for connector in powerrail.GetConnectors(): + for element in connector.GetConnectedBlocks(): + if element not in elements: + elements.append(element) + powerrrail.Clean() + self.Blocks.remove(powerrrail) + self.Elements.remove(powerrrail) + self.Controler.RemoveCurrentElementEditingInstance(powerrrail.GetId()) + for element in elements: + element.RefreshModel() + +#------------------------------------------------------------------------------- +# Edit element content functions +#------------------------------------------------------------------------------- + + def EditBlockContent(self, block): + dialog = BlockPropertiesDialog(self.Parent) + dialog.SetBlockList(self.Controler.GetBlockTypes()) + dialog.SetMinBlockSize(block.GetSize()) + values = {"name" : block.GetName(), "type" : block.GetType()} + values["extension"] = block.GetExtension() + dialog.SetValues(values) + if dialog.ShowModal() == wxID_OK: + values = dialog.GetValues() + if "name" in values: + block.SetName(values["name"]) + block.SetSize(values["width"], values["height"]) + block.SetType(values["type"], values["extension"]) + self.RefreshBlockModel(block) + self.Refresh() + dialog.Destroy() + + def EditVariableContent(self, variable): + dialog = VariablePropertiesDialog(self.Parent) + dialog.SetMinVariableSize(variable.GetSize()) + varlist = [] + vars = self.Controler.GetCurrentElementEditingInterfaceVars() + if vars: + for var in vars: + varlist.append((var["Name"], var["Class"], var["Type"])) + returntype = self.Controler.GetCurrentElementEditingInterfaceReturnType() + if returntype: + varlist.append((self.Controler.GetCurrentElementEditingName(), "Output", returntype)) + dialog.SetVariables(varlist) + values = {"name" : variable.GetName(), "type" : variable.GetType()} + dialog.SetValues(values) + if dialog.ShowModal() == wxID_OK: + old_type = variable.GetType() + values = dialog.GetValues() + variable.SetName(values["name"]) + variable.SetType(values["type"], values["value_type"]) + variable.SetSize(values["width"], values["height"]) + if old_type != values["type"]: + id = variable.GetId() + self.Controler.RemoveCurrentElementEditingInstance(id) + self.Controler.AddCurrentElementEditingVariable(id, values["type"]) + self.RefreshVariableModel(variable) + self.Refresh() + dialog.Destroy() + + #------------------------------------------------------------------------------- # Editing functions #------------------------------------------------------------------------------- @@ -781,8 +1314,12 @@ # Drawing functions #------------------------------------------------------------------------------- + def OnMoveWindow(self, event): + self.RefreshScrollBar() + event.Skip() + def OnPaint(self, event): - dc = wxClientDC(self) + dc = self.GetLogicalDC() dc.Clear() dc.SetPen(wxPen(wxColour(230, 230, 230))) if self.Scaling and self.DrawGrid: @@ -799,778 +1336,8 @@ 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.SetUseTabs(0) - - self.Keywords = [] - self.Variables = [] - self.Functions = [] - self.Jumps = [] - self.TextChanged = False - self.TextSyntax = "ST" - - self.Controler = controler - - EVT_KEY_DOWN(self, self.OnKeyDown) - EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded) - EVT_KILL_FOCUS(self, self.OnKillFocus) - - def SetTextSyntax(self, syntax): - self.TextSyntax = syntax - - 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() - - # Code completion - if key == WXK_SPACE and event.ControlDown(): - - line = self.GetCurrentLine() - if line == 0: - start_pos = 0 - else: - start_pos = self.GetLineEndPosition(line - 1) + 1 - end_pos = self.GetCurrentPos() - - lineText = self.GetTextRange(start_pos, end_pos).replace("\t", " ") - words = lineText.split(" ") - words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1] - - kw = [] - - if self.TextSyntax == "IL": - if len(words) == 1: - kw = self.Keywords - elif len(words) == 2: - if words[0].upper() in ["CAL", "CALC", "CALNC"]: - kw = self.Functions - elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]: - kw = self.Jumps - else: - kw = self.Variables - else: - kw = self.Keywords + self.Variables + self.Functions - if len(kw) > 0: - kw.sort() - self.AutoCompSetIgnoreCase(True) - self.AutoCompShow(len(words[-1]), " ".join(kw)) - else: - self.TextChanged = False - wxCallAfter(self.RefreshModel) - event.Skip() - - def OnKillFocus(self, event): - self.AutoCompCancel() - 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 SetMode(self, mode): - pass - - 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() + if self.rubberBand.IsShown(): + self.rubberBand.Draw() + event.Skip() + + diff -r 36d378bd852e -r dae55dd9ee14 examples/example.xml --- a/examples/example.xml Sat Jul 07 11:35:17 2007 +0200 +++ b/examples/example.xml Mon Jul 09 11:10:14 2007 +0200 @@ -90,7 +90,7 @@ - + @@ -184,7 +184,7 @@ - + @@ -195,7 +195,7 @@ - + diff -r 36d378bd852e -r dae55dd9ee14 graphics/FBD_Objects.py --- a/graphics/FBD_Objects.py Sat Jul 07 11:35:17 2007 +0200 +++ b/graphics/FBD_Objects.py Mon Jul 09 11:10:14 2007 +0200 @@ -40,15 +40,15 @@ class FBD_Block(Graphic_Element): # Create a new block - def __init__(self, parent, type, name, id = None, extension = 0, inputs = [], outputs = []): + def __init__(self, parent, type, name, id = None, extension = 0): Graphic_Element.__init__(self, parent) self.Type = None + self.Extension = None self.Name = name self.Id = id - self.Extension = extension self.Inputs = [] self.Outputs = [] - self.SetType(type) + self.SetType(type, extension) # Destructor def __del__(self): @@ -107,7 +107,16 @@ output.MoveConnected(exclude) # Returns the block connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test each input and output connector + for input in self.Inputs: + if name == input.GetName(): + return input + for output in self.Outputs: + if name == output.GetName(): + return output # Test each input connector for input in self.Inputs: input_pos = input.GetRelPosition() @@ -137,9 +146,10 @@ return None # Changes the block type - def SetType(self, type): - if type != self.Type: + def SetType(self, type, extension): + if type != self.Type or self.Extension != extension: self.Type = type + self.Extension = extension # Find the block definition from type given and create the corresponding # inputs and outputs blocktype = GetBlockType(type) @@ -150,14 +160,14 @@ start = int(inputs[-1][0].replace("IN", "")) for i in xrange(self.Extension - len(blocktype["inputs"])): start += 1 - inputs.append(("IN%d"%start, inputs[-1][1], input[-1][2])) + inputs.append(("IN%d"%start, inputs[-1][1], inputs[-1][2])) else: raise ValueError, "This block type isn't defined" self.Clean() # Extract the inputs properties and create the corresponding connector self.Inputs = [] for input_name, input_type, input_modifier in inputs: - connector = Connector(self, input_name, input_type, wxPoint(0, 0), WEST) + connector = Connector(self, input_name, input_type, wxPoint(0, 0), WEST, onlyone = True) if input_modifier == "negated": connector.SetNegated(True) elif input_modifier != "none": @@ -228,13 +238,13 @@ self.RefreshModel(False) # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the block properties self.Parent.EditBlockContent(self) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnRightUp(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Popup the menu with special items for a block and a connector if one is handled connector = self.TestConnector(pos, False) if connector: @@ -346,7 +356,14 @@ return None # Returns the block connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test input and output connector if they exists + if self.Input and name == self.Input.GetName(): + return self.Input + if self.Output and name == self.Output.GetName(): + return self.Output # Test input connector if it exists if self.Input: input_pos = self.Input.GetRelPosition() @@ -380,7 +397,7 @@ self.Output = None # Create an input or output connector according to variable type if self.Type != INPUT: - self.Input = Connector(self, "", value_type, wxPoint(0, 0), WEST) + self.Input = Connector(self, "", value_type, wxPoint(0, 0), WEST, onlyone = True) if self.Type != OUTPUT: self.Output = Connector(self, "", value_type, wxPoint(0, 0), EAST) self.RefreshConnectors() @@ -404,15 +421,15 @@ return text_width + 10, text_height + 10 # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the variable properties self.Parent.EditVariableContent(self) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnRightUp(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Popup the menu with special items for a variable and a connector if it's handled - connector = self.TestConnectors(pos, False) + connector = self.TestConnector(pos, False) if connector: self.Handle = (HANDLE_CONNECTOR, connector) self.Parent.PopupVariableMenu(connector) @@ -466,7 +483,7 @@ self.Size = wxSize(0, 0) # Create an input or output connector according to connection type if self.Type == CONNECTOR: - self.Connector = Connector(self, "", "ANY", wxPoint(0, 0), WEST) + self.Connector = Connector(self, "", "ANY", wxPoint(0, 0), WEST, onlyone = True) else: self.Connector = Connector(self, "", "ANY", wxPoint(0, 0), EAST) self.RefreshConnectors() @@ -514,7 +531,7 @@ return None # Returns the connection connector - def GetConnector(self, position = None): + def GetConnector(self, position = None, name = None): return self.Connector # Returns the connection type @@ -538,7 +555,7 @@ return text_width + text_height + 20, text_height + 10 # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): + def OnRightUp(self, event, dc, scaling): # Popup the default menu self.Parent.PopupDefaultMenu() diff -r 36d378bd852e -r dae55dd9ee14 graphics/GraphicCommons.py --- a/graphics/GraphicCommons.py Sat Jul 07 11:35:17 2007 +0200 +++ b/graphics/GraphicCommons.py Mon Jul 09 11:10:14 2007 +0200 @@ -55,7 +55,7 @@ # SFC constants SFC_STEP_DEFAULT_SIZE = (40, 30) # Default size of a SFC step SFC_TRANSITION_SIZE = (20, 2) # Size of a SFC transition -SFC_DEFAULT_SEQUENCE_INTERVAL = 80 # Default size of the interval between two divergence branches +SFC_DEFAULT_SEQUENCE_INTERVAL = 40 # Default size of the interval between two divergence branches SFC_SIMULTANEOUS_SEQUENCE_EXTRA = 20 # Size of extra lines for simultaneous divergence and convergence SFC_JUMP_SIZE = (12, 13) # Size of a SFC jump to step SFC_WIRE_MIN_SIZE = 25 # Size of a wire between two elements @@ -80,7 +80,12 @@ # Contants for defining which mode is selected for each view [MODE_SELECTION, MODE_BLOCK, MODE_VARIABLE, MODE_CONNECTION, MODE_COMMENT, MODE_WIRE, - MODE_INITIAL_STEP] = range(7) + MODE_COIL, MODE_CONTACT, MODE_POWERRAIL, MODE_INITIALSTEP, MODE_STEP, MODE_TRANSITION, + MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(15) + +# Contants for defining which drawing mode is selected for app +[FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2] + """ Basic vector operations for calculate wire points @@ -115,8 +120,8 @@ Function that calculates the nearest point of the grid defined by scaling for the given point """ -def GetScaledEventPosition(event, scaling): - pos = event.GetPosition() +def GetScaledEventPosition(event, dc, scaling): + pos = event.GetLogicalPosition(dc) if scaling: pos.x = round(float(pos.x) / float(scaling[0])) * scaling[0] pos.y = round(float(pos.y) / float(scaling[1])) * scaling[1] @@ -166,8 +171,8 @@ return self.currentBox # Method called when a new box starts to be edited - def OnLeftDown(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnLeftDown(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Save the point for calculate the box position and size self.startPoint = pos self.currentBox = wxRect(pos.x, pos.y, 0, 0) @@ -175,8 +180,8 @@ self.Redraw() # Method called when dragging with a box edited - def OnMotion(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnMotion(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Save the last position and size of the box for erasing it self.lastBox = wxRect(self.currentBox.x, self.currentBox.y, self.currentBox.width, self.currentBox.height) @@ -196,7 +201,7 @@ self.Redraw() # Method called when dragging is stopped - def OnLeftUp(self, event, scaling): + def OnLeftUp(self, event, dc, scaling): self.drawingSurface.SetCursor(wxNullCursor) self.lastBox = self.currentBox self.currentBox = None @@ -204,7 +209,7 @@ # Method that erase the last box and draw the new box def Redraw(self): - dc = wxClientDC(self.drawingSurface) + dc = self.drawingSurface.GetLogicalDC() dc.SetPen(wxPen(wxWHITE, 1, wxDOT)) dc.SetBrush(wxTRANSPARENT_BRUSH) dc.SetLogicalFunction(wxXOR) @@ -217,6 +222,27 @@ dc.DrawRectangle(self.currentBox.x, self.currentBox.y, self.currentBox.width, self.currentBox.height) + # Erase last box + def Erase(self): + dc = self.drawingSurface.GetLogicalDC() + dc.SetPen(wxPen(wxWHITE, 1, wxDOT)) + dc.SetBrush(wxTRANSPARENT_BRUSH) + dc.SetLogicalFunction(wxXOR) + if self.lastBox: + dc.DrawRectangle(self.lastBox.x, self.lastBox.y, self.lastBox.width, + self.lastBox.height) + + # Draw current box + def Draw(self): + dc = self.drawingSurface.GetLogicalDC() + dc.SetPen(wxPen(wxWHITE, 1, wxDOT)) + dc.SetBrush(wxTRANSPARENT_BRUSH) + dc.SetLogicalFunction(wxXOR) + if self.currentBox: + # Draw current box + dc.DrawRectangle(self.currentBox.x, self.currentBox.y, self.currentBox.width, + self.currentBox.height) + #------------------------------------------------------------------------------- # Graphic element base class @@ -335,8 +361,8 @@ return 0, 0 # Method called when a LeftDown event have been generated - def OnLeftDown(self, event, scaling): - pos = event.GetPosition() + def OnLeftDown(self, event, dc, scaling): + pos = event.GetLogicalPosition(dc) # Test if an handle have been clicked result = self.TestHandle(pos) # Find which type of handle have been clicked, @@ -359,14 +385,14 @@ self.Parent.SetCursor(wxStockCursor(wxCURSOR_HAND)) self.SetSelected(False) # Initializes the last position - self.oldPos = GetScaledEventPosition(event, scaling) + self.oldPos = GetScaledEventPosition(event, dc, scaling) # Method called when a LeftUp event have been generated - def OnLeftUp(self, event, scaling): + def OnLeftUp(self, event, dc, scaling): # If a dragging have been initiated if self.Dragging and self.oldPos: # Calculate the movement of cursor and refreshes the element state - pos = GetScaledEventPosition(event, scaling) + pos = GetScaledEventPosition(event, dc, scaling) movex = pos.x - self.oldPos.x movey = pos.y - self.oldPos.y self.ProcessDragging(movex, movey) @@ -375,20 +401,20 @@ self.oldPos = None # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): + def OnRightUp(self, event, dc, scaling): self.SetSelected(True) self.oldPos = None # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): pass # Method called when a Motion event have been generated - def OnMotion(self, event, scaling): + def OnMotion(self, event, dc, scaling): # If the cursor is dragging and the element have been clicked if event.Dragging() and self.oldPos: # Calculate the movement of cursor - pos = GetScaledEventPosition(event, scaling) + pos = GetScaledEventPosition(event, dc, scaling) movex = pos.x - self.oldPos.x movey = pos.y - self.oldPos.y # If movement is greater than MIN_MOVE then a dragging is initiated @@ -400,7 +426,7 @@ self.ProcessDragging(movex, movey) # If cursor just pass over the element, changes the cursor if it is on a handle else: - pos = event.GetPosition() + pos = event.GetLogicalPosition(dc) handle = self.TestHandle(pos) if handle == (1, 1) or handle == (3, 3): wxCallAfter(self.Parent.SetCursor, wxStockCursor(wxCURSOR_SIZENWSE)) @@ -614,7 +640,7 @@ class Connector: # Create a new connector - def __init__(self, parent, name, type, position, direction, negated = False, edge = "none"): + def __init__(self, parent, name, type, position, direction, negated = False, edge = "none", onlyone = False): self.ParentBlock = parent self.Name = name self.Type = type @@ -623,6 +649,7 @@ self.Wires = [] self.Negated = negated self.Edge = edge + self.OneConnected = onlyone self.Pen = wxBLACK_PEN # Change the connector pen @@ -758,6 +785,22 @@ def RefreshParentBlock(self): self.ParentBlock.RefreshModel(False) + # Returns all the blocks connected to this connector + def GetConnectedBlocks(self): + blocks = [] + for wire, handle in self.Wires: + # Get other connector connected to each wire + if handle == 0: + connector = blocks.GetEndConnected() + else: + connector = blocks.GetStartConnected() + # Get parent block for this connector + if connector: + block = connector.GetParentBlock() + if block not in blocks: + blocks.append(block) + return blocks + # Returns the connector negated property def IsNegated(self): return self.Negated @@ -779,7 +822,7 @@ # Tests if the point given is near from the end point of this connector def TestPoint(self, pt, exclude = True): parent_pos = self.ParentBlock.GetPosition() - if not (len(self.Wires) > 0 and self.Direction == WEST and exclude): + if not (len(self.Wires) > 0 and self.OneConnected and exclude): # Calculate a square around the end point of this connector x = parent_pos[0] + self.Pos.x + self.Direction[0] * CONNECTOR_SIZE - ANCHOR_DISTANCE y = parent_pos[1] + self.Pos.y + self.Direction[1] * CONNECTOR_SIZE - ANCHOR_DISTANCE @@ -872,6 +915,14 @@ def SetSize(width, height): pass + # Returns connector to which start point is connected + def GetStartConnected(self): + return self.StartConnected + + # Returns connector to which end point is connected + def GetEndConnected(self): + return self.EndConnected + # Unconnect the start and end points def Clean(self): if self.StartConnected: @@ -1084,11 +1135,11 @@ return connected # Returns the id of the block connected to the first or the last wire point - def GetConnectedId(self, index): + def GetConnectedInfos(self, index): if index == 0 and self.StartConnected: - return self.StartConnected.GetBlockId() + return self.StartConnected.GetBlockId(), self.StartConnected.GetName() elif index == -1 and self.EndConnected: - return self.EndConnected.GetBlockId() + return self.EndConnected.GetBlockId(), self.StartConnected.GetName() return None # Update the wire points position by keeping at most possible the current positions @@ -1423,8 +1474,8 @@ self.RefreshModel() # Method called when a LeftDown event have been generated - def OnLeftDown(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnLeftDown(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Test if a point have been handled #result = self.TestPoint(pos) #if result != None: @@ -1441,12 +1492,12 @@ self.Handle = (HANDLE_SEGMENT, result) # Execute the default method for a graphic element else: - Graphic_Element.OnLeftDown(self, event, scaling) + Graphic_Element.OnLeftDown(self, event, dc, scaling) self.oldPos = pos # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnRightUp(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Test if a segment has been handled result = self.TestSegment(pos) if result != None: @@ -1455,16 +1506,16 @@ self.Parent.PopupWireMenu() else: # Execute the default method for a graphic element - Graphic_Element.OnRightUp(self, event, scaling) + Graphic_Element.OnRightUp(self, event, dc, scaling) # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): self.ResetPoints() self.GeneratePoints() # Method called when a Motion event have been generated - def OnMotion(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnMotion(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) if not event.Dragging(): # Test if a segment has been handled result = self.TestSegment(pos) @@ -1485,10 +1536,10 @@ # self.OverStart = False # self.OverEnd = False # Execute the default method for a graphic element - Graphic_Element.OnMotion(self, event, scaling) + Graphic_Element.OnMotion(self, event, dc, scaling) else: # Execute the default method for a graphic element - Graphic_Element.OnMotion(self, event, scaling) + Graphic_Element.OnMotion(self, event, dc, scaling) # Refreshes the wire state according to move defined and handle selected def ProcessDragging(self, movex, movey): @@ -1648,7 +1699,7 @@ self.SetSize(width, height) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): + def OnRightUp(self, event, dc, scaling): # Popup the default menu self.Parent.PopupDefaultMenu() @@ -1657,7 +1708,7 @@ self.Parent.RefreshCommentModel(self) # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the comment content self.Parent.EditCommentContent(self) diff -r 36d378bd852e -r dae55dd9ee14 graphics/LD_Objects.py --- a/graphics/LD_Objects.py Sat Jul 07 11:35:17 2007 +0200 +++ b/graphics/LD_Objects.py Mon Jul 09 11:10:14 2007 +0200 @@ -43,6 +43,9 @@ Graphic_Element.__init__(self, parent) self.Type = type self.Id = id + self.Extensions = [LD_LINE_SIZE / 2, LD_LINE_SIZE / 2] + if len(connectors) < 1: + connectors = [True] # Create a connector or a blank according to 'connectors' and add it in # the connectors list self.Connectors = [] @@ -56,10 +59,14 @@ # Forbids to change the power rail size def SetSize(self, width, height): - pass + if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.SetSize(self, width, height) + self.RefreshConnectors() # Forbids to select a power rail def HitTest(self, pt): + if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + return Graphic_Element.HitTest(self, pt) or self.TestConnector(pt, False) != None return False # Deletes this power rail by calling the appropriate method @@ -75,17 +82,17 @@ # Refresh the power rail bounding box def RefreshBoundingBox(self): dc = wxClientDC(self.Parent) - if self.Type == LEFTRAIL: - bbx_x = self.Pos.x - elif self.Type == RIGHTRAIL: - bbx_x = self.Pos.x - CONNECTOR_SIZE - self.BoundingBox = wxRect(bbx_x, self.Pos.y, self.Size[0] + CONNECTOR_SIZE + 1, self.Size[1] + 1) + self.BoundingBox = wxRect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1] + 1) # Refresh the power rail size def RefreshSize(self): self.Size = wxSize(2, LD_LINE_SIZE * len(self.Connectors)) self.RefreshBoundingBox() + # Returns the block minimum size + def GetMinSize(self): + return 2, LD_LINE_SIZE * len(self.Connectors) + # Add a connector or a blank to this power rail at the last place def AddConnector(self, connector = True): self.InsertConnector(len(self.Connectors), connector) @@ -103,6 +110,26 @@ self.RefreshSize() self.RefreshConnectors() + # Moves the divergence connector given + def MoveConnector(self, connector, movey): + position = connector.GetRelPosition() + connector.SetPosition(wxPoint(position.x, position.y + movey)) + miny = self.Size[1] + maxy = 0 + for connect in self.Connectors: + connect_pos = connect.GetRelPosition() + miny = min(miny, connect_pos.y) + maxy = max(maxy, connect_pos.y) + min_pos = self.Pos.y + miny - self.Extensions[0] + self.Pos.y = min(min_pos, self.Pos.y) + if min_pos == self.Pos.y: + for connect in self.Connectors: + connect_pos = connect.GetRelPosition() + connect.SetPosition(wxPoint(connect_pos.x, connect_pos.y - miny + self.Extensions[0])) + self.Size[1] = max(maxy - miny + self.Extensions[0] + self.Extensions[1], self.Size[1]) + connector.MoveConnected() + self.RefreshBoundingBox() + # Returns the index in connectors list for the connector given def GetConnectorIndex(self, connector): if connector in self.Connectors: @@ -123,7 +150,7 @@ # Refresh the positions of the power rail connectors def RefreshConnectors(self): - position = LD_LINE_SIZE / 2 + position = self.Extensions[0] for connector in self.Connectors: if connector: if self.Type == LEFTRAIL: @@ -140,7 +167,13 @@ connector.MoveConnected(exclude) # Returns the power rail connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test each connector if it exists + for connector in self.Connectors: + if connector and name == connector.GetName(): + return connector for connector in self.Connectors: if connector: connector_pos = connector.GetRelPosition() @@ -163,6 +196,63 @@ def GetType(self): return self.Type + # Method called when a LeftDown event have been generated + def OnLeftDown(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) + # Test if a connector have been handled + connector = self.TestConnector(pos, False) + if connector: + self.Handle = (HANDLE_CONNECTOR, connector) + self.Parent.SetCursor(wxStockCursor(wxCURSOR_HAND)) + self.Selected = False + # Initializes the last position + self.oldPos = GetScaledEventPosition(event, dc, scaling) + else: + self.RealConnectors = {"Inputs":[],"Outputs":[]} + for input in self.Inputs: + position = input.GetRelPosition() + self.RealConnectors["Inputs"].append(float(position.x)/float(self.Size[0])) + for output in self.Outputs: + position = output.GetRelPosition() + self.RealConnectors["Outputs"].append(float(position.x)/float(self.Size[0])) + Graphic_Element.OnLeftDown(self, event, dc, scaling) + + # Method called when a LeftUp event have been generated + def OnLeftUp(self, event, dc, scaling): + self.RealConnectors = None + handle_type, handle = self.Handle + if handle_type == HANDLE_CONNECTOR: + wires = handle.GetWires() + if len(wires) != 1: + return + if handle == wires[0][0].StartConnected: + block = wires[0][0].EndConnected.GetParentBlock() + else: + block = wires[0][0].StartConnected.GetParentBlock() + block.RefreshModel(False) + Graphic_Element.OnLeftUp(self, event, dc, scaling) + + # Method called when a RightUp event have been generated + def OnRightUp(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) + # Popup the menu with special items for a block and a connector if one is handled + connector = self.TestConnector(pos, False) + if connector: + self.Handle = (HANDLE_CONNECTOR, connector) + # self.Parent.PopupDivergenceMenu(True) + #else: + # Popup the divergence menu without delete branch + # self.Parent.PopupDivergenceMenu(False) + + # Refreshes the divergence state according to move defined and handle selected + def ProcessDragging(self, movex, movey): + handle_type, handle = self.Handle + # A connector has been handled + if handle_type == HANDLE_CONNECTOR: + self.MoveConnector(handle, movey) + else: + Graphic_Element.ProcessDragging(self, movex, movey) + # Refreshes the power rail model def RefreshModel(self, move=True): self.Parent.RefreshPowerRailModel(self) @@ -214,7 +304,9 @@ # Forbids to change the contact size def SetSize(self, width, height): - pass + if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.SetSize(self, width, height) + self.RefreshConnectors() # Delete this contact by calling the appropriate method def Delete(self): @@ -243,13 +335,24 @@ bbx_height = self.Size[1] self.BoundingBox = wxRect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1) + # Returns the block minimum size + def GetMinSize(self): + return LD_ELEMENT_SIZE + # Refresh the position of wire connected to contact def RefreshConnected(self, exclude = []): self.Input.MoveConnected(exclude) self.Output.MoveConnected(exclude) # Returns the contact connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test input and output connector + if name == self.Input.GetName(): + return self.Input + if name == self.Output.GetName(): + return self.Output # Test input connector input_pos = self.Input.GetRelPosition() if position.x == self.Pos.x + input_pos.x and position.y == self.Pos.y + input_pos.y: @@ -274,6 +377,12 @@ return self.Output return None + # Refresh the positions of the block connectors + def RefreshConnectors(self): + self.Input.SetPosition(wxPoint(0, self.Size[1] / 2 + 1)) + self.Output.SetPosition(wxPoint(self.Size[0], self.Size[1] / 2 + 1)) + self.RefreshConnected() + # Changes the contact name def SetName(self, name): self.Name = name @@ -291,7 +400,7 @@ return self.Type # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the contact properties self.Parent.EditContactContent(self) @@ -359,7 +468,9 @@ # Forbids to change the contact size def SetSize(self, width, height): - pass + if isinstance(self.Parent, wxPanel) or self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.SetSize(self, width, height) + self.RefreshConnectors() # Delete this coil by calling the appropriate method def Delete(self): @@ -387,6 +498,10 @@ bbx_y = self.Pos.y bbx_height = self.Size[1] self.BoundingBox = wxRect(bbx_x, bbx_y, bbx_width + 1, bbx_height + 1) + + # Returns the block minimum size + def GetMinSize(self): + return LD_ELEMENT_SIZE # Refresh the position of wire connected to coil def RefreshConnected(self, exclude = []): @@ -394,7 +509,14 @@ self.Output.MoveConnected(exclude) # Returns the coil connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test input and output connector + if self.Input and name == self.Input.GetName(): + return self.Input + if self.Output and name == self.Output.GetName(): + return self.Output # Test input connector input_pos = self.Input.GetRelPosition() if position.x == self.Pos.x + input_pos.x and position.y == self.Pos.y + input_pos.y: @@ -419,6 +541,12 @@ return self.Output return None + # Refresh the positions of the block connectors + def RefreshConnectors(self): + self.Input.SetPosition(wxPoint(0, self.Size[1] / 2 + 1)) + self.Output.SetPosition(wxPoint(self.Size[0], self.Size[1] / 2 + 1)) + self.RefreshConnected() + # Changes the coil name def SetName(self, name): self.Name = name @@ -436,7 +564,7 @@ return self.Type # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the coil properties self.Parent.EditCoilContent(self) diff -r 36d378bd852e -r dae55dd9ee14 graphics/SFC_Objects.py --- a/graphics/SFC_Objects.py Sat Jul 07 11:35:17 2007 +0200 +++ b/graphics/SFC_Objects.py Mon Jul 09 11:10:14 2007 +0200 @@ -148,7 +148,16 @@ self.Action.MoveConnected(exclude) # Returns the step connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test input, output and action connector if they exists + if self.Input and name == self.Input.GetName(): + return self.Input + if self.Output and name == self.Output.GetName(): + return self.Output + if self.Action and name == self.Action.GetName(): + return self.Action # Test input connector if it exists if self.Input: input_pos = self.Input.GetRelPosition() @@ -312,7 +321,10 @@ # Resize the divergence from position and size given def Resize(self, x, y, width, height): - self.UpdateSize(width, height) + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.UpdateSize(width, height) + else: + Graphic_Element.Resize(self, x, y, width, height) # Method called when a LeftDClick event have been generated def OnLeftDClick(self, event, scaling): @@ -320,7 +332,7 @@ self.Parent.EditStepContent(self) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): + def OnRightUp(self, event, dc, scaling): # Popup the menu with special items for a step self.Parent.PopupDefaultMenu() @@ -329,7 +341,10 @@ handle_type, handle = self.Handle if handle_type == HANDLE_MOVE: action_block = None - if self.Initial: + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + self.Move(movex, movey) + self.RefreshConnected() + elif self.Initial: self.MoveActionBlock((movex, movey)) self.Move(movex, movey, self.Parent.Wires) self.RefreshOutputPosition((movex, movey)) @@ -371,8 +386,11 @@ action_block.RefreshModel(False) # If step has moved, refresh the model of wires connected to output if move: - self.RefreshInputModel() - self.RefreshOutputModel(self.Initial) + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.RefreshInputModel() + self.RefreshOutputModel(self.Initial) + elif self.Output: + self.Output.RefreshWires() # Draws step def Draw(self, dc): @@ -423,11 +441,13 @@ # Forbids to change the transition size def SetSize(self, width, height): - pass + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.SetSize(self, width, height) # Forbids to resize the transition def Resize(self, x, y, width, height): - pass + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.Resize(self, x, y, width, height) # Delete this transition by calling the appropriate method def Delete(self): @@ -479,7 +499,14 @@ self.Output.MoveConnected(exclude) # Returns the transition connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test input and output connector + if name == self.Input.GetName(): + return self.Input + if name == self.Output.GetName(): + return self.Output # Test input connector input_pos = self.Input.GetRelPosition() if position.x == self.Pos.x + input_pos.x and position.y == self.Pos.y + input_pos.y: @@ -568,31 +595,35 @@ output_block.MoveActionBlock((diffx, 0)) output_block.Move(diffx, 0) output_block.RefreshOutputPosition() - + # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the transition properties self.Parent.EditTransitionContent(self) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): + def OnRightUp(self, event, dc, scaling): # Popup the menu with special items for a step self.Parent.PopupDefaultMenu() # Refreshes the transition state according to move defined and handle selected def ProcessDragging(self, movex, movey): - self.Move(movex, 0) - self.RefreshInputPosition() - self.RefreshOutputPosition() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.Move(movex, 0) + self.RefreshInputPosition() + self.RefreshOutputPosition() + else: + Graphic_Element.ProcessDragging(self, movex, movey) # Refresh input element model def RefreshInputModel(self): - input = self.GetPreviousConnector() - if input: - input_block = input.GetParentBlock() - input_block.RefreshModel(False) - if not isinstance(input_block, SFC_Divergence): - input_block.RefreshInputModel() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + input = self.GetPreviousConnector() + if input: + input_block = input.GetParentBlock() + input_block.RefreshModel(False) + if not isinstance(input_block, SFC_Divergence): + input_block.RefreshInputModel() # Refresh output element model def RefreshOutputModel(self, move=False): @@ -608,8 +639,11 @@ self.Parent.RefreshTransitionModel(self) # If transition has moved, refresh the model of wires connected to output if move: - self.RefreshInputModel() - self.RefreshOutputModel() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.RefreshInputModel() + self.RefreshOutputModel() + else: + self.Output.RefreshWires() # Draws transition def Draw(self, dc): @@ -672,7 +706,8 @@ # Forbids to resize the divergence def Resize(self, x, y, width, height): - pass + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.Resize(self, x, y, width, height) # Delete this divergence by calling the appropriate method def Delete(self): @@ -774,7 +809,16 @@ self.RefreshBoundingBox() # Returns the divergence connector that starts with the point given if it exists - def GetConnector(self, position): + def GetConnector(self, position, name = None): + # if a name is given + if name: + # Test each input and output connector + for input in self.Inputs: + if name == input.GetName(): + return input + for output in self.Outputs: + if name == output.GetName(): + return output # Test input connector for input in self.Inputs: input_pos = input.GetPosition(False) @@ -808,23 +852,27 @@ for i, input in enumerate(self.Inputs): position = input.GetRelPosition() if self.RealConnectors: - input.SetPosition(wxPoint(int(round(self.RealConnectors["Inputs"][i] * width)), position.y)) + input.SetPosition(wxPoint(int(round(self.RealConnectors["Inputs"][i] * width)), 0)) else: - input.SetPosition(wxPoint(int(round(float(position.x)*float(width)/float(self.Size[0]))), position.y)) + input.SetPosition(wxPoint(int(round(float(position.x)*float(width)/float(self.Size[0]))), 0)) input.MoveConnected() for i, output in enumerate(self.Outputs): position = output.GetRelPosition() if self.RealConnectors: - output.SetPosition(wxPoint(int(round(self.RealConnectors["Outputs"][i] * width)), position.y)) + output.SetPosition(wxPoint(int(round(self.RealConnectors["Outputs"][i] * width)), self.Size[1])) else: - output.SetPosition(wxPoint(int(round(float(position.x)*float(width)/float(self.Size[0]))), position.y)) + output.SetPosition(wxPoint(int(round(float(position.x)*float(width)/float(self.Size[0]))), self.Size[1])) output.MoveConnected() - self.Size = wxSize(width, self.Size[1]) + self.Size = wxSize(width, height) self.RefreshBoundingBox() # Returns the divergence minimum size def GetMinSize(self): - return 0, self.Size[1] + if self.Type in [SELECTION_DIVERGENCE, SELECTION_CONVERGENCE]: + return 0, 1 + elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]: + return 0, 3 + return 0, 0 # Refresh the position of the block connected to connector def RefreshConnectedPosition(self, connector): @@ -847,7 +895,7 @@ next_block.RefreshInputPosition() else: next_block.RefreshOutputPosition() - + # Refresh the position of this divergence def RefreshPosition(self): y = 0 @@ -885,8 +933,8 @@ output_block.RefreshOutputPosition(move) # Method called when a LeftDown event have been generated - def OnLeftDown(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnLeftDown(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Test if a connector have been handled connector = self.TestConnector(pos, False) if connector: @@ -894,7 +942,7 @@ self.Parent.SetCursor(wxStockCursor(wxCURSOR_HAND)) self.Selected = False # Initializes the last position - self.oldPos = GetScaledEventPosition(event, scaling) + self.oldPos = GetScaledEventPosition(event, dc, scaling) else: self.RealConnectors = {"Inputs":[],"Outputs":[]} for input in self.Inputs: @@ -903,10 +951,10 @@ for output in self.Outputs: position = output.GetRelPosition() self.RealConnectors["Outputs"].append(float(position.x)/float(self.Size[0])) - Graphic_Element.OnLeftDown(self, event, scaling) + Graphic_Element.OnLeftDown(self, event, dc, scaling) # Method called when a LeftUp event have been generated - def OnLeftUp(self, event, scaling): + def OnLeftUp(self, event, dc, scaling): self.RealConnectors = None handle_type, handle = self.Handle if handle_type == HANDLE_CONNECTOR: @@ -923,11 +971,11 @@ block.RefreshInputModel() else: block.RefreshOutputModel() - Graphic_Element.OnLeftUp(self, event, scaling) + Graphic_Element.OnLeftUp(self, event, dc, scaling) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): - pos = GetScaledEventPosition(event, scaling) + def OnRightUp(self, event, dc, scaling): + pos = GetScaledEventPosition(event, dc, scaling) # Popup the menu with special items for a block and a connector if one is handled connector = self.TestConnector(pos, False) if connector: @@ -943,11 +991,14 @@ # A connector has been handled if handle_type == HANDLE_CONNECTOR: self.MoveConnector(handle, movex) - self.RefreshConnectedPosition(handle) + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.RefreshConnectedPosition(handle) + elif self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.ProcessDragging(self, movex, movey) # Refresh output element model def RefreshOutputModel(self, move=False): - if move: + if move and self.Parent.GetDrawingMode() != FREEDRAWING_MODE: for output in self.Outputs: wires = output.GetWires() if len(wires) != 1: @@ -962,7 +1013,11 @@ self.Parent.RefreshDivergenceModel(self) # If divergence has moved, refresh the model of wires connected to outputs if move: - self.RefreshOutputModel() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.RefreshOutputModel() + else: + for output in self.Outputs: + output.RefreshWires() # Draws divergence def Draw(self, dc): @@ -974,8 +1029,8 @@ elif self.Type in [SIMULTANEOUS_DIVERGENCE, SIMULTANEOUS_CONVERGENCE]: dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y, self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y) - dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y + 3, - self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y + 3) + dc.DrawLine(self.Pos.x - SFC_SIMULTANEOUS_SEQUENCE_EXTRA, self.Pos.y + self.Size[1], + self.Pos.x + self.Size[0] + SFC_SIMULTANEOUS_SEQUENCE_EXTRA + 1, self.Pos.y + self.Size[1]) # Draw inputs and outputs connectors for input in self.Inputs: input.Draw(dc) @@ -1004,15 +1059,17 @@ # Destructor def __del__(self): - self.Inputs = None + self.Input = None # Forbids to change the jump size def SetSize(self, width, height): - pass + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.SetSize(self, width, height) # Forbids to resize jump def Resize(self, x, y, width, height): - pass + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + Graphic_Element.Resize(self, x, y, width, height) # Delete this jump by calling the appropriate method def Delete(self): @@ -1020,8 +1077,7 @@ # Unconnect input def Clean(self): - if self.Input: - self.Input.UnConnect() + self.Input.UnConnect() # Refresh the jump bounding box def RefreshBoundingBox(self): @@ -1034,19 +1090,23 @@ # Returns the connector connected to input def GetPreviousConnector(self): - if self.Input: - wires = self.Input.GetWires() - if len(wires) == 1: - return wires[0][0].EndConnected + wires = self.Input.GetWires() + if len(wires) == 1: + return wires[0][0].EndConnected return None + # Refresh the element connectors position + def RefreshConnectors(self): + self.Input.SetPosition(wxPoint(self.Size[0] / 2, 0)) + self.RefreshConnected() + # Refresh the position of wires connected to jump def RefreshConnected(self, exclude = []): if self.Input: self.Input.MoveConnected(exclude) # Returns input jump connector - def GetConnector(self, position = None): + def GetConnector(self, position = None, name = None): return self.Input # Test if point given is on jump input connector @@ -1091,28 +1151,32 @@ pass # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the jump properties self.Parent.EditJumpContent(self) # Method called when a RightUp event have been generated - def OnRightUp(self, event, scaling): + def OnRightUp(self, event, dc, scaling): # Popup the default menu self.Parent.PopupDefaultMenu() # Refreshes the jump state according to move defined and handle selected def ProcessDragging(self, movex, movey): - self.Move(movex, 0) - self.RefreshInputPosition() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.Move(movex, 0) + self.RefreshInputPosition() + else: + Graphic_Element.ProcessDragging(self, movex, movey) # Refresh input element model def RefreshInputModel(self): - input = self.GetPreviousConnector() - if input: - input_block = input.GetParentBlock() - input_block.RefreshModel(False) - if not isinstance(input_block, SFC_Divergence): - input_block.RefreshInputModel() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + input = self.GetPreviousConnector() + if input: + input_block = input.GetParentBlock() + input_block.RefreshModel(False) + if not isinstance(input_block, SFC_Divergence): + input_block.RefreshInputModel() # Refresh output element model def RefreshOutputModel(self, move=False): @@ -1122,7 +1186,8 @@ def RefreshModel(self, move=True): self.Parent.RefreshJumpModel(self) if move: - self.RefreshInputModel() + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + self.RefreshInputModel() # Draws divergence def Draw(self, dc): @@ -1171,10 +1236,19 @@ def GetLineNumber(self): return len(self.Actions) + def GetLineSize(self): + if len(self.Actions) > 1: + return self.Size[1] / len(self.Actions) + else: + return SFC_ACTION_MIN_SIZE[1] + # Forbids to resize the action block def Resize(self, x, y, width, height): - if x == 0: - self.SetSize(width, self.Size[1]) + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + if x == 0: + self.SetSize(width, self.Size[1]) + else: + Graphic_Element.Resize(self, x, y, width, height) # Delete this action block by calling the appropriate method def Delete(self): @@ -1193,7 +1267,7 @@ self.Input.MoveConnected(exclude) # Returns input action block connector - def GetConnector(self, position = None): + def GetConnector(self, position = None, name = None): return self.Input # Test if point given is on action block input connector @@ -1219,8 +1293,12 @@ if "indicator" in action and action["indicator"] != "": width, height = dc.GetTextExtent(action["indicator"]) self.ColSize[2] = max(self.ColSize[2], width + 10) - self.Size = wxSize(max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2], - SFC_ACTION_MIN_SIZE[0]), len(self.Actions) * SFC_ACTION_MIN_SIZE[1]) + if self.Parent.GetDrawingMode() == FREEDRAWING_MODE: + line_size = self.GetLineSize() + self.Size = wxSize(self.ColSize[0] + self.ColSize[1] + self.ColSize[2], len(self.Actions) * line_size) + else: + self.Size = wxSize(max(self.ColSize[0] + self.ColSize[1] + self.ColSize[2], + SFC_ACTION_MIN_SIZE[0]), len(self.Actions) * SFC_ACTION_MIN_SIZE[1]) self.RefreshBoundingBox() if self.Input: wires = self.Input.GetWires() @@ -1239,21 +1317,25 @@ SFC_ACTION_MIN_SIZE[0]), len(self.Actions) * SFC_ACTION_MIN_SIZE[1] # Method called when a LeftDClick event have been generated - def OnLeftDClick(self, event, scaling): + def OnLeftDClick(self, event, dc, scaling): # Edit the action block properties self.Parent.EditActionBlockContent(self) # Refreshes the action block state according to move defined and handle selected def ProcessDragging(self, movex, movey): - handle_type, handle = self.Handle - if handle_type == HANDLE_MOVE: - wires = self.Input.GetWires() - if len(wires) == 1: - input_pos = wires[0][0].EndConnected.GetPosition(False) - if self.Pos.x - input_pos.x + movex >= SFC_WIRE_MIN_SIZE: - self.Move(movex, 0) + if self.Parent.GetDrawingMode() != FREEDRAWING_MODE: + handle_type, handle = self.Handle + if handle_type == HANDLE_MOVE: + wires = self.Input.GetWires() + if len(wires) == 1: + input_pos = wires[0][0].EndConnected.GetPosition(False) + if self.Pos.x - input_pos.x + movex >= SFC_WIRE_MIN_SIZE: + self.Move(movex, 0) + else: + Graphic_Element.ProcessDragging(self, movex, movey) else: Graphic_Element.ProcessDragging(self, movex, movey) + # Refreshes the action block model def RefreshModel(self, move=True): @@ -1270,27 +1352,29 @@ self.Pos.x + colsize[0], self.Pos.y + self.Size[1]) dc.DrawLine(self.Pos.x + colsize[0] + colsize[1], self.Pos.y, self.Pos.x + colsize[0] + colsize[1], self.Pos.y + self.Size[1]) + line_size = self.GetLineSize() for i, action in enumerate(self.Actions): if i != 0: - dc.DrawLine(self.Pos.x, self.Pos.y + i * SFC_ACTION_MIN_SIZE[1], - self.Pos.x + self.Size[0], self.Pos.y + i * SFC_ACTION_MIN_SIZE[1]) + dc.DrawLine(self.Pos.x, self.Pos.y + i * line_size, + self.Pos.x + self.Size[0], self.Pos.y + i * line_size) text_width, text_height = dc.GetTextExtent(action["qualifier"]) if "duration" in action: dc.DrawText(action["qualifier"], self.Pos.x + (colsize[0] - text_width) / 2, - self.Pos.y + i * SFC_ACTION_MIN_SIZE[1] + SFC_ACTION_MIN_SIZE[1] / 2 - text_height) + self.Pos.y + i * line_size + line_size / 2 - text_height) text_width, text_height = dc.GetTextExtent(action["duration"]) dc.DrawText(action["duration"], self.Pos.x + (colsize[0] - text_width) / 2, - self.Pos.y + i * SFC_ACTION_MIN_SIZE[1] + SFC_ACTION_MIN_SIZE[1] / 2) + self.Pos.y + i * line_size + line_size / 2) else: dc.DrawText(action["qualifier"], self.Pos.x + (colsize[0] - text_width) / 2, - self.Pos.y + i * SFC_ACTION_MIN_SIZE[1] + (SFC_ACTION_MIN_SIZE[1] - text_height) / 2) + self.Pos.y + i * line_size + (line_size - text_height) / 2) text_width, text_height = dc.GetTextExtent(action["value"]) dc.DrawText(action["value"], self.Pos.x + colsize[0] + (colsize[1] - text_width) / 2, - self.Pos.y + i * SFC_ACTION_MIN_SIZE[1] + (SFC_ACTION_MIN_SIZE[1] - text_height) / 2) + self.Pos.y + i * line_size + (line_size - text_height) / 2) if "indicator" in action: text_width, text_height = dc.GetTextExtent(action["indicator"]) dc.DrawText(action["indicator"], self.Pos.x + colsize[0] + colsize[1] + (colsize[2] - text_width) / 2, - self.Pos.y + i * SFC_ACTION_MIN_SIZE[1] + (SFC_ACTION_MIN_SIZE[1] - text_height) / 2) + self.Pos.y + i * line_size + (line_size - text_height) / 2) # Draw input connector self.Input.Draw(dc) Graphic_Element.Draw(self, dc) + diff -r 36d378bd852e -r dae55dd9ee14 plcopen/TC6_XML_V10_B.xsd --- a/plcopen/TC6_XML_V10_B.xsd Sat Jul 07 11:35:17 2007 +0200 +++ b/plcopen/TC6_XML_V10_B.xsd Mon Jul 09 11:10:14 2007 +0200 @@ -571,7 +571,7 @@ - + The single byte character string type @@ -579,7 +579,7 @@ - + The wide character (WORD) string type diff -r 36d378bd852e -r dae55dd9ee14 plcopen/plcopen.py --- a/plcopen/plcopen.py Sat Jul 07 11:35:17 2007 +0200 +++ b/plcopen/plcopen.py Mon Jul 09 11:10:14 2007 +0200 @@ -966,6 +966,17 @@ return None setattr(cls, "getConnectionPoints", getConnectionPoints) + def setConnectionParameter(self, idx, parameter): + if self.content: + self.content["value"][idx].setFormalParameter(parameter) + setattr(cls, "setConnectionParameter", setConnectionParameter) + + def getConnectionParameter(self, idx): + if self.content: + return self.content["value"][idx].getFormalParameter() + return None + setattr(cls, "getConnectionParameter", getConnectionParameter) + if "connectionPointOut" in PLCOpenClasses: cls = PLCOpenClasses["connectionPointOut"] diff -r 36d378bd852e -r dae55dd9ee14 plcopen/structures.py --- a/plcopen/structures.py Sat Jul 07 11:35:17 2007 +0200 +++ b/plcopen/structures.py Mon Jul 09 11:10:14 2007 +0200 @@ -159,8 +159,7 @@ ("ANY_INT", "ANY_NUM"), ("ANY_SINT", "ANY_INT"), ("ANY_UINT", "ANY_INT"), - ("REAL", "ANY_REAL"), - ("LREAL", "ANY_REAL"), + ("BOOL", "ANY_BIT"), ("SINT", "ANY_SINT"), ("INT", "ANY_SINT"), ("DINT", "ANY_SINT"), @@ -169,17 +168,19 @@ ("UINT", "ANY_UINT"), ("UDINT", "ANY_UINT"), ("ULINT", "ANY_UINT"), + ("REAL", "ANY_REAL"), + ("LREAL", "ANY_REAL"), ("TIME", "ANY_MAGNITUDE"), - ("BOOL", "ANY_BIT"), + ("DATE", "ANY_DATE"), + ("TOD", "ANY_DATE"), + ("DT", "ANY_DATE"), + ("STRING", "ANY_STRING"), ("BYTE", "ANY_NBIT"), ("WORD", "ANY_NBIT"), ("DWORD", "ANY_NBIT"), - ("LWORD", "ANY_NBIT"), - ("STRING", "ANY_STRING"), - #("WSTRING", "ANY_STRING"), # TODO - ("DATE", "ANY_DATE"), - ("TOD", "ANY_DATE"), - ("DT", "ANY_DATE")] + ("LWORD", "ANY_NBIT") + #("WSTRING", "ANY_STRING") # TODO +] TypeHierarchy = dict(TypeHierarchy_list) diff -r 36d378bd852e -r dae55dd9ee14 test.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test.xml Mon Jul 09 11:10:14 2007 +0200 @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + +