# HG changeset patch # User lbessard # Date 1219418574 -7200 # Node ID d12779e971bd2a1d6e0094b40f655e711445e4f5 # Parent 389f2046e4957352bc1295bf6177a6621f67f510 Adding support for function and functionBlock (standard or user) library diff -r 389f2046e495 -r d12779e971bd PLCOpenEditor.py --- a/PLCOpenEditor.py Fri Aug 22 17:18:12 2008 +0200 +++ b/PLCOpenEditor.py Fri Aug 22 17:22:54 2008 +0200 @@ -52,11 +52,13 @@ [ID_PLCOPENEDITOR, ID_PLCOPENEDITORTREENOTEBOOK, ID_PLCOPENEDITORTYPESTREE, ID_PLCOPENEDITORINSTANCESTREE, ID_PLCOPENEDITORMAINSPLITTER, ID_PLCOPENEDITORSECONDSPLITTER, - ID_PLCOPENEDITOREDITORPANEL, ID_PLCOPENEDITORTABSOPENED, + ID_PLCOPENEDITORTHIRDSPLITTER, ID_PLCOPENEDITORLIBRARYPANEL, + ID_PLCOPENEDITORLIBRARYTREE, ID_PLCOPENEDITORLIBRARYCOMMENT, + ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTOOLBAR, ID_PLCOPENEDITORDEFAULTTOOLBAR, ID_PLCOPENEDITORSFCTOOLBAR, ID_PLCOPENEDITORFBDTOOLBAR, ID_PLCOPENEDITORLDTOOLBAR, -] = [wx.NewId() for _init_ctrls in range(13)] +] = [wx.NewId() for _init_ctrls in range(17)] [ID_PLCOPENEDITORFILEMENUGENERATE, ] = [wx.NewId() for _init_coll_FileMenu_Items in range(1)] @@ -335,6 +337,22 @@ self._init_coll_FileMenu_Items(self.FileMenu) self._init_coll_EditMenu_Items(self.EditMenu) self._init_coll_HelpMenu_Items(self.HelpMenu) + + def _init_coll_MainLibrarySizer_Items(self, parent): + parent.AddWindow(self.LibraryTree, 0, border=0, flag=wx.GROW) + parent.AddSizer(self.LibraryComment, 0, border=0, flag=wx.GROW) + + def _init_coll_MainLibrarySizer_Growables(self, parent): + parent.AddGrowableCol(0) + parent.AddGrowableRow(0) + + def _init_sizers(self): + self.MainLibrarySizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) + + self._init_coll_MainLibrarySizer_Growables(self.MainLibrarySizer) + self._init_coll_MainLibrarySizer_Items(self.MainLibrarySizer) + + self.LibraryPanel.SetSizer(self.MainLibrarySizer) def _init_ctrls(self, prnt): wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name=u'PLCOpenEditor', @@ -430,6 +448,15 @@ self.MainSplitter.SplitVertically(self.TreeNoteBook, self.SecondSplitter, 200) + self.VariablePanelIndexer = VariablePanelIndexer(self.SecondSplitter, self, self.Controler) + + self.ThirdSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORTHIRDSPLITTER, + name='ThirdSplitter', parent=self.SecondSplitter, point=wx.Point(0, 0), + size=wx.Size(0, 0), style=wx.SP_3D) + self.ThirdSplitter.SetMinimumPaneSize(1) + + self.SecondSplitter.SplitHorizontally(self.ThirdSplitter, self.VariablePanelIndexer, -200) + self.TabsOpened = wx.Notebook(id=ID_PLCOPENEDITORTABSOPENED, name='TabsOpened', parent=self.SecondSplitter, pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) @@ -439,22 +466,48 @@ else: wx.EVT_NOTEBOOK_PAGE_CHANGED(self.TabsOpened, ID_PLCOPENEDITORTABSOPENED, self.OnPouSelectedChanged) - else: + + self.LibraryPanel = wx.Panel(id=ID_PLCOPENEDITORLIBRARYPANEL, + name='LibraryPanel', parent=self.ThirdSplitter, pos=wx.Point(0, + 0), size=wx.Size(0, 0), style=wx.SUNKEN_BORDER) + + self.ThirdSplitter.SplitVertically(self.TabsOpened, self.LibraryPanel, -250) + else: + self.VariablePanelIndexer = VariablePanelIndexer(self, self, self.Controler) + self.AUIManager.AddPane(self.VariablePanelIndexer, wx.aui.AuiPaneInfo().Caption("Variables").Bottom().Layer(0).BestSize(wx.Size(800, 200)).CloseButton(False)) + self.TabsOpened = wx.aui.AuiNotebook(self) self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPouSelectedChanged) self.AUIManager.AddPane(self.TabsOpened, wx.aui.AuiPaneInfo().CentrePane()) - - if wx.VERSION < (2, 8, 0): - self.VariablePanelIndexer = VariablePanelIndexer(self.SecondSplitter, self, self.Controler) - - self.SecondSplitter.SplitHorizontally(self.TabsOpened, self.VariablePanelIndexer, -200) - else: - self.VariablePanelIndexer = VariablePanelIndexer(self, self, self.Controler) - self.AUIManager.AddPane(self.VariablePanelIndexer, wx.aui.AuiPaneInfo().Caption("Variables").Bottom().Layer(0).BestSize(wx.Size(800, 200)).CloseButton(False)) - + + self.LibraryPanel = wx.Panel(id=ID_PLCOPENEDITORLIBRARYPANEL, + name='LibraryPanel', parent=self, pos=wx.Point(0, + 0), size=wx.Size(0, 0), style=0) + self.AUIManager.AddPane(self.LibraryPanel, wx.aui.AuiPaneInfo().Caption("Library").Right().Layer(0).BestSize(wx.Size(250, 400)).CloseButton(False)) + self.AUIManager.Update() + if wx.Platform == '__WXMSW__': + treestyle = wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER + else: + treestyle = wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER + self.LibraryTree = wx.TreeCtrl(id=ID_PLCOPENEDITORLIBRARYTREE, + name='LibraryTree', parent=self.LibraryPanel, + pos=wx.Point(0, 0), size=wx.Size(0, 0), + style=treestyle) + self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnLibraryTreeItemSelected, + id=ID_PLCOPENEDITORLIBRARYTREE) + self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnLibraryTreeBeginDrag, + id=ID_PLCOPENEDITORLIBRARYTREE) + + self.LibraryComment = wx.TextCtrl(id=ID_PLCOPENEDITORLIBRARYCOMMENT, + name='LibraryComment', parent=self.LibraryPanel, + pos=wx.Point(0, 0), size=wx.Size(0, 60), + style=wx.TE_READONLY|wx.TE_MULTILINE) + + self._init_sizers() + def __init__(self, parent, controler = None, fileOpen = None): self.ModeSolo = controler == None if self.ModeSolo: @@ -525,6 +578,7 @@ if not self.ModeSolo or fileOpen is not None: self.RefreshTypesTree() self.RefreshInstancesTree() + self.RefreshLibraryTree() self.RefreshFileMenu() self.RefreshEditMenu() @@ -675,6 +729,7 @@ self.RefreshEditMenu() self.RefreshTypesTree() self.RefreshInstancesTree() + self.RefreshLibraryTree() event.Skip() def OnOpenProjectMenu(self, event): @@ -700,6 +755,7 @@ self.Controler.OpenXMLFile(filepath) self.RefreshTypesTree() self.RefreshInstancesTree() + self.RefreshLibraryTree() self.RefreshTitle() self.RefreshFileMenu() self.RefreshEditMenu() @@ -916,6 +972,8 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() + self.RefreshLibraryTree() event.Skip() def OnRedoMenu(self, event): @@ -935,6 +993,8 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() + self.RefreshLibraryTree() event.Skip() def OnCutMenu(self, event): @@ -1022,6 +1082,8 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() + self.RefreshLibraryTree() self.RefreshToolBar() elif isinstance(window, (Viewer, TextViewer)): event = wx.KeyEvent(wx.EVT_CHAR._getEvtType()) @@ -1097,7 +1159,7 @@ #------------------------------------------------------------------------------- -# Project Tree Management Functions +# Types Tree Management Functions #------------------------------------------------------------------------------- def RefreshTypesTree(self): @@ -1106,7 +1168,7 @@ if not root.IsOk(): root = self.TypesTree.AddRoot(infos["name"]) self.GenerateTypesTreeBranch(root, infos) - self.TypesTree.Expand(self.TypesTree.GetRootItem()) + self.TypesTree.Expand(root) def GenerateTypesTreeBranch(self, root, infos, topology=False): to_delete = [] @@ -1577,7 +1639,7 @@ #------------------------------------------------------------------------------- -# Topology Tree Management Functions +# Instances Tree Management Functions #------------------------------------------------------------------------------- def RefreshInstancesTree(self): @@ -1586,7 +1648,7 @@ if not root.IsOk(): root = self.InstancesTree.AddRoot(infos["name"]) self.GenerateInstancesTreeBranch(root, infos) - self.InstancesTree.Expand(self.InstancesTree.GetRootItem()) + self.InstancesTree.Expand(root) def GenerateInstancesTreeBranch(self, root, infos): to_delete = [] @@ -1615,6 +1677,79 @@ self.InstancesTree.Delete(item) #------------------------------------------------------------------------------- +# Library Tree Management Functions +#------------------------------------------------------------------------------- + + def RefreshLibraryTree(self): + to_delete = [] + blocktypes = self.Controler.GetBlockTypes() + if wx.Platform == '__WXMSW__': + root = self.LibraryTree.AddRoot("Block Types") + self.TypeTree.SetPyData(root, {"type" : CATEGORY}) + else: + root = self.LibraryTree.AddRoot("") + if wx.VERSION >= (2, 6, 0): + category_item, root_cookie = self.LibraryTree.GetFirstChild(root) + else: + category_item, root_cookie = self.LibraryTree.GetFirstChild(root, 0) + for category in blocktypes: + print category["name"] + if not category_item.IsOk(): + category_item = self.LibraryTree.AppendItem(root, category["name"]) + if wx.Platform != '__WXMSW__': + category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) + else: + self.LibraryTree.SetItemText(category_item, category["name"]) + self.LibraryTree.SetPyData(category_item, {"type" : CATEGORY}) + if wx.VERSION >= (2, 6, 0): + blocktype_item, category_cookie = self.LibraryTree.GetFirstChild(category_item) + else: + blocktype_item, category_cookie = self.LibraryTree.GetFirstChild(category_item, 0) + for blocktype in category["list"]: + if not blocktype_item.IsOk(): + blocktype_item = self.LibraryTree.AppendItem(category_item, blocktype["name"]) + if wx.Platform != '__WXMSW__': + blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) + else: + self.LibraryTree.SetItemText(blocktype_item, blocktype["name"]) + self.LibraryTree.SetPyData(blocktype_item, {"type" : BLOCK, "block_type" : blocktype["type"], "inputs" : tuple([type for name, type, modifier in blocktype["inputs"]])}) + blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) + while blocktype_item.IsOk(): + to_delete.append(blocktype_item) + blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) + category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) + while category_item.IsOk(): + to_delete.append(category_item) + category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) + for item in to_delete: + self.LibraryTree.Delete(item) + if wx.Platform == '__WXMSW__': + self.LibraryTree.Expand(root) + + def OnLibraryTreeItemSelected(self, event): + selected = event.GetItem() + pydata = self.LibraryTree.GetPyData(selected) + if pydata["type"] != CATEGORY: + blocktype = self.Controler.GetBlockType(self.LibraryTree.GetItemText(selected), pydata["inputs"]) + if blocktype: + self.LibraryComment.SetValue(blocktype["comment"]) + else: + self.LibraryComment.SetValue("") + else: + self.LibraryComment.SetValue("") + event.Skip() + + def OnLibraryTreeBeginDrag(self, event): + selected = event.GetItem() + pydata = self.LibraryTree.GetPyData(selected) + if selected is not None and pydata["type"] == BLOCK: + data = wx.TextDataObject(str((self.LibraryTree.GetItemText(selected), + pydata["block_type"], "", pydata["inputs"]))) + dragSource = wx.DropSource(self.LibraryTree) + dragSource.SetData(data) + dragSource.DoDragDrop() + +#------------------------------------------------------------------------------- # ToolBar Management Functions #------------------------------------------------------------------------------- @@ -1848,6 +1983,7 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshLibraryTree() dialog.Destroy() event.Skip() return OnAddPouMenu @@ -1863,7 +1999,7 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() - dialog.Destroy() + dialog.Destroy() event.Skip() return OnAddTransitionMenu @@ -1892,6 +2028,7 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() dialog.Destroy() event.Skip() @@ -1906,6 +2043,7 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() dialog.Destroy() event.Skip() return OnAddResourceMenu @@ -1949,6 +2087,8 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() + self.RefreshLibraryTree() self.RefreshToolBar() else: message = wx.MessageDialog(self, "%s is used by one or more POUs. It can't be removed!"%selected, "Error", wx.OK|wx.ICON_ERROR) @@ -1956,21 +2096,6 @@ message.Destroy() event.Skip() - def OnRemoveConfigurationMenu(self, event): - selected = self.TypesTree.GetSelection() - if self.TypesTree.GetPyData(selected) == ITEM_CONFIGURATION: - name = self.TypesTree.GetItemText(selected) - self.Controler.ProjectRemoveConfiguration(name) - tagname = self.Controler.ComputeConfigurationName(name) - idx = self.IsOpened(tagname) - if idx is not None: - self.VariablePanelIndexer.RemoveVariablePanel(tagname) - self.TabsOpened.DeletePage(idx) - self.RefreshTitle() - self.RefreshEditMenu() - self.RefreshTypesTree() - event.Skip() - def OnRemoveTransitionMenu(self, event): selected = self.TypesTree.GetSelection() if self.TypesTree.GetPyData(selected) == ITEM_TRANSITION: @@ -2013,6 +2138,22 @@ self.RefreshTypesTree() event.Skip() + def OnRemoveConfigurationMenu(self, event): + selected = self.TypesTree.GetSelection() + if self.TypesTree.GetPyData(selected) == ITEM_CONFIGURATION: + name = self.TypesTree.GetItemText(selected) + self.Controler.ProjectRemoveConfiguration(name) + tagname = self.Controler.ComputeConfigurationName(name) + idx = self.IsOpened(tagname) + if idx is not None: + self.VariablePanelIndexer.RemoveVariablePanel(tagname) + self.TabsOpened.DeletePage(idx) + self.RefreshTitle() + self.RefreshEditMenu() + self.RefreshTypesTree() + self.RefreshInstancesTree() + event.Skip() + def OnRemoveResourceMenu(self, event): selected = self.TypesTree.GetSelection() if self.TypesTree.GetPyData(selected) == ITEM_RESOURCE: @@ -2032,6 +2173,7 @@ self.RefreshTitle() self.RefreshEditMenu() self.RefreshTypesTree() + self.RefreshInstancesTree() event.Skip() def OnPLCOpenEditorMenu(self, event): @@ -3759,6 +3901,7 @@ self.SaveValues() self.RefreshValues() self.RefreshButtons() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnDeleteButton(self, event): @@ -3767,16 +3910,19 @@ self.SaveValues() self.RefreshValues() self.RefreshButtons() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnUpButton(self, event): self.MoveValue(self.VariablesGrid.GetGridCursorRow(), -1) self.RefreshButtons() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnDownButton(self, event): self.MoveValue(self.VariablesGrid.GetGridCursorRow(), 1) self.RefreshButtons() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnVariablesGridCellChange(self, event): @@ -3813,11 +3959,13 @@ self.ParentWindow.RefreshEditor(variablepanel = False) self.ParentWindow.RefreshTitle() self.ParentWindow.RefreshEditMenu() + self.ParentWindow.RefreshInstancesTree() event.Skip() else: self.SaveValues() if colname == "Class": self.Table.ResetView(self.VariablesGrid) + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnVariablesGridEditorShown(self, event): diff -r 389f2046e495 -r d12779e971bd RessourceEditor.py --- a/RessourceEditor.py Fri Aug 22 17:18:12 2008 +0200 +++ b/RessourceEditor.py Fri Aug 22 17:22:54 2008 +0200 @@ -523,6 +523,7 @@ self.InstancesTable.AppendRow(self.InstancesDefaultValue.copy()) self.RefreshModel() self.RefreshView() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnDeleteInstanceButton(self, event): @@ -530,6 +531,7 @@ self.InstancesTable.RemoveRow(row) self.RefreshModel() self.RefreshView() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnUpInstanceButton(self, event): @@ -537,6 +539,7 @@ self.InstancesTable.MoveRow(row, -1, self.InstancesGrid) self.RefreshModel() self.RefreshView() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnDownInstanceButton(self, event): @@ -544,6 +547,7 @@ self.InstancesTable.MoveRow(row, 1, self.InstancesGrid) self.RefreshModel() self.RefreshView() + self.ParentWindow.RefreshInstancesTree() event.Skip() def OnTasksGridCellChange(self, event): @@ -568,6 +572,7 @@ def OnInstancesGridCellChange(self, event): self.RefreshModel() self.RefreshView() + self.ParentWindow.RefreshInstancesTree() event.Skip() #------------------------------------------------------------------------------- diff -r 389f2046e495 -r d12779e971bd Viewer.py --- a/Viewer.py Fri Aug 22 17:18:12 2008 +0200 +++ b/Viewer.py Fri Aug 22 17:22:54 2008 +0200 @@ -108,10 +108,16 @@ message = "\"%s\" is already used by \"%s\"!"%(name, values[0]) else: blockname = values[2] + if len(values) > 3: + blockinputs = values[3] + else: + blockinputs = None if values[1] != "function" and blockname == "": - dialog = wx.TextEntryDialog(self.ParentWindow, "Block name", "Please enter a block name", "", wx.OK|wx.CANCEL|wx.CENTRE) - if dialog.ShowModal(): + dialog = wx.TextEntryDialog(self.ParentWindow.ParentWindow, "Block name", "Please enter a block name", "", wx.OK|wx.CANCEL|wx.CENTRE) + if dialog.ShowModal() == wx.ID_OK: blockname = dialog.GetValue() + else: + return dialog.Destroy() if blockname.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames()]: message = "\"%s\" pou already exists!"%blockname @@ -119,7 +125,7 @@ message = "\"%s\" element for this pou already exists!"%blockname else: id = self.ParentWindow.GetNewId() - block = FBD_Block(self.ParentWindow, values[0], blockname, id) + block = FBD_Block(self.ParentWindow, values[0], blockname, id, inputs = blockinputs) width, height = block.GetMinSize() if scaling is not None: x = round(float(x) / float(scaling[0])) * scaling[0] @@ -1432,6 +1438,7 @@ self.RefreshBuffer() self.RefreshScrollBars() self.ParentWindow.RefreshVariablePanel(self.TagName) + self.ParentWindow.RefreshInstancesTree() block.Refresh() dialog.Destroy() @@ -1721,6 +1728,7 @@ self.RefreshBuffer() self.RefreshScrollBars() self.ParentWindow.RefreshVariablePanel(self.TagName) + self.ParentWindow.RefreshInstancesTree() block.Refresh(rect) dialog.Destroy() @@ -2105,7 +2113,8 @@ for element in elements: element.RefreshModel() wx.CallAfter(self.ParentWindow.RefreshVariablePanel, self.TagName) - + wx.CallAfter(self.ParentWindow.RefreshInstancesTree) + def DeleteVariable(self, variable): connectors = variable.GetConnectors() if connectors["output"]: @@ -2238,6 +2247,8 @@ self.SelectedElement = None self.RefreshBuffer() self.RefreshScrollBars() + self.ParentWindow.RefreshVariablePanel(self.TagName) + self.ParentWindow.RefreshInstancesTree() self.RefreshRect(self.GetScrolledRect(rect), False) def Copy(self): @@ -2255,6 +2266,7 @@ self.RefreshBuffer() self.RefreshScrollBars() self.ParentWindow.RefreshVariablePanel(self.TagName) + self.ParentWindow.RefreshInstancesTree() def CanAddBlock(self, block): if self.CurrentLanguage == "SFC":