--- /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()