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