Laurent@814: #!/usr/bin/env python Laurent@814: # -*- coding: utf-8 -*- Laurent@814: andrej@1571: # This file is part of Beremiz, a Integrated Development Environment for andrej@1571: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. Laurent@814: # andrej@1571: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD Laurent@814: # andrej@1571: # See COPYING file for copyrights details. Laurent@814: # andrej@1571: # This program is free software; you can redistribute it and/or andrej@1571: # modify it under the terms of the GNU General Public License andrej@1571: # as published by the Free Software Foundation; either version 2 andrej@1571: # of the License, or (at your option) any later version. Laurent@814: # andrej@1571: # This program is distributed in the hope that it will be useful, andrej@1571: # but WITHOUT ANY WARRANTY; without even the implied warranty of andrej@1571: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrej@1571: # GNU General Public License for more details. Laurent@814: # andrej@1571: # You should have received a copy of the GNU General Public License andrej@1571: # along with this program; if not, write to the Free Software andrej@1571: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Laurent@814: Laurent@814: import wx Laurent@814: import wx.lib.buttons Laurent@814: import wx.grid Laurent@814: laurent@831: from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT Laurent@814: from controls import CustomGrid, CustomTable, DurationCellEditor laurent@831: from dialogs.DurationEditorDialog import IEC_TIME_MODEL Laurent@814: from EditorPanel import EditorPanel Laurent@814: from util.BitmapLibrary import GetBitmap andrej@1657: from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS, DefaultType Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Configuration Editor class Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Edouard@1420: [ID_CONFIGURATIONEDITOR, Laurent@814: ] = [wx.NewId() for _init_ctrls in range(1)] Laurent@814: Laurent@814: class ConfigurationEditor(EditorPanel): Edouard@1420: Laurent@814: ID = ID_CONFIGURATIONEDITOR Laurent@814: VARIABLE_PANEL_TYPE = "config" Edouard@1420: Laurent@814: def GetBufferState(self): Laurent@814: return self.Controler.GetBufferState() Edouard@1420: Laurent@814: def Undo(self): Laurent@814: self.Controler.LoadPrevious() Laurent@814: self.ParentWindow.CloseTabsWithoutModel() Edouard@1420: Laurent@814: def Redo(self): Laurent@814: self.Controler.LoadNext() Laurent@814: self.ParentWindow.CloseTabsWithoutModel() Edouard@1420: Laurent@814: def HasNoModel(self): Laurent@814: return self.Controler.GetEditedElement(self.TagName) is None Laurent@814: Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Resource Editor class Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: def GetTasksTableColnames(): Laurent@814: _ = lambda x : x Laurent@814: return [_("Name"), _("Triggering"), _("Single"), _("Interval"), _("Priority")] Laurent@814: Laurent@814: def GetTaskTriggeringOptions(): Laurent@814: _ = lambda x : x Laurent@814: return [_("Interrupt"), _("Cyclic")] Laurent@814: TASKTRIGGERINGOPTIONS_DICT = dict([(_(option), option) for option in GetTaskTriggeringOptions()]) Laurent@814: Edouard@1423: SingleCellEditor = lambda *x : wx.grid.GridCellChoiceEditor() Edouard@1423: Edouard@1423: def CheckSingle(single, varlist): Edouard@1423: return single in varlist Edouard@1423: Edouard@1423: Laurent@814: def GetInstancesTableColnames(): Laurent@814: _ = lambda x : x Laurent@814: return [_("Name"), _("Type"), _("Task")] Laurent@814: Laurent@814: class ResourceTable(CustomTable): Edouard@1420: Laurent@814: """ Laurent@814: A custom wx.grid.Grid Table using user supplied data Laurent@814: """ Laurent@814: def __init__(self, parent, data, colnames): Laurent@814: # The base class must be initialized *first* Laurent@814: CustomTable.__init__(self, parent, data, colnames) Laurent@814: self.ColAlignements = [] Laurent@814: self.ColSizes = [] Edouard@1420: Laurent@814: def GetColAlignements(self): Laurent@814: return self.ColAlignements Edouard@1420: Laurent@814: def SetColAlignements(self, list): Laurent@814: self.ColAlignements = list Laurent@814: Laurent@814: def GetColSizes(self): Laurent@814: return self.ColSizes Edouard@1420: Laurent@814: def SetColSizes(self, list): Laurent@814: self.ColSizes = list Laurent@814: Laurent@814: def GetValue(self, row, col): Laurent@814: if row < self.GetNumberRows(): Laurent@814: colname = self.GetColLabelValue(col, False) andrej@1657: value = self.data[row].get(colname, "") Laurent@814: if colname == "Triggering": Laurent@814: return _(value) Laurent@814: return value Edouard@1420: Laurent@814: def SetValue(self, row, col, value): Laurent@814: if col < len(self.colnames): Laurent@814: colname = self.GetColLabelValue(col, False) Laurent@814: if colname == "Triggering": Laurent@814: value = TASKTRIGGERINGOPTIONS_DICT[value] Laurent@814: self.data[row][colname] = value Edouard@1420: Laurent@814: def _updateColAttrs(self, grid): Laurent@814: """ Laurent@814: wx.grid.Grid -> update the column attributes to add the Laurent@814: appropriate renderer given the column name. Laurent@814: Laurent@814: Otherwise default to the default renderer. Laurent@814: """ Edouard@1420: Laurent@814: for col in range(self.GetNumberCols()): Laurent@814: attr = wx.grid.GridCellAttr() Laurent@814: attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE) Laurent@814: grid.SetColAttr(col, attr) Laurent@814: grid.SetColSize(col, self.ColSizes[col]) Edouard@1420: Laurent@814: for row in range(self.GetNumberRows()): Laurent@814: row_highlights = self.Highlights.get(row, {}) Laurent@814: for col in range(self.GetNumberCols()): Laurent@814: editor = None Laurent@814: renderer = None Laurent@879: error = False Laurent@814: colname = self.GetColLabelValue(col, False) Laurent@814: grid.SetReadOnly(row, col, False) Laurent@814: if colname == "Name": Laurent@814: editor = wx.grid.GridCellTextEditor() Laurent@814: renderer = wx.grid.GridCellStringRenderer() Laurent@814: elif colname == "Interval": Laurent@1275: editor = DurationCellEditor(self, colname) Laurent@814: renderer = wx.grid.GridCellStringRenderer() Laurent@814: if self.GetValueByName(row, "Triggering") != "Cyclic": Laurent@814: grid.SetReadOnly(row, col, True) Laurent@879: interval = self.GetValueByName(row, colname) Laurent@879: if interval != "" and IEC_TIME_MODEL.match(interval.upper()) is None: Laurent@879: error = True Laurent@814: elif colname == "Single": Edouard@1423: editor = SingleCellEditor(self,colname) Laurent@814: editor.SetParameters(self.Parent.VariableList) Laurent@814: if self.GetValueByName(row, "Triggering") != "Interrupt": Laurent@814: grid.SetReadOnly(row, col, True) Edouard@1423: single = self.GetValueByName(row, colname) Edouard@1423: if single != "" and not CheckSingle(single,self.Parent.VariableList): Edouard@1423: error = True Laurent@814: elif colname == "Triggering": Laurent@814: editor = wx.grid.GridCellChoiceEditor() Laurent@1026: editor.SetParameters(",".join(map(_, GetTaskTriggeringOptions()))) Laurent@814: elif colname == "Type": Laurent@814: editor = wx.grid.GridCellChoiceEditor() Laurent@814: editor.SetParameters(self.Parent.TypeList) Laurent@814: elif colname == "Priority": Laurent@814: editor = wx.grid.GridCellNumberEditor() Laurent@814: editor.SetParameters("0,65535") Laurent@814: elif colname == "Task": Laurent@814: editor = wx.grid.GridCellChoiceEditor() Laurent@814: editor.SetParameters(self.Parent.TaskList) Edouard@1420: Laurent@814: grid.SetCellEditor(row, col, editor) Laurent@814: grid.SetCellRenderer(row, col, renderer) Edouard@1420: Laurent@879: if error: laurent@831: highlight_colours = ERROR_HIGHLIGHT laurent@831: else: laurent@831: highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1] Laurent@814: grid.SetCellBackgroundColour(row, col, highlight_colours[0]) Laurent@814: grid.SetCellTextColour(row, col, highlight_colours[1]) Laurent@814: self.ResizeRow(grid, row) Laurent@814: Edouard@1420: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Highlights showing functions Laurent@814: #------------------------------------------------------------------------------- Laurent@814: Laurent@814: def AddHighlight(self, infos, highlight_type): Laurent@814: row_highlights = self.Highlights.setdefault(infos[0], {}) Laurent@814: col_highlights = row_highlights.setdefault(infos[1], []) Laurent@814: col_highlights.append(highlight_type) Edouard@1420: Laurent@814: def ClearHighlights(self, highlight_type=None): Laurent@814: if highlight_type is None: Laurent@814: self.Highlights = {} Laurent@814: else: Laurent@814: for row, row_highlights in self.Highlights.iteritems(): Laurent@814: row_items = row_highlights.items() Laurent@814: for col, col_highlights in row_items: Laurent@814: if highlight_type in col_highlights: Laurent@814: col_highlights.remove(highlight_type) Laurent@814: if len(col_highlights) == 0: Laurent@814: row_highlights.pop(col) Laurent@814: Laurent@814: Laurent@814: Laurent@814: class ResourceEditor(EditorPanel): Edouard@1420: Laurent@814: VARIABLE_PANEL_TYPE = "resource" Laurent@814: Laurent@814: def _init_Editor(self, parent): Laurent@814: self.Editor = wx.Panel(parent, style=wx.SUNKEN_BORDER|wx.TAB_TRAVERSAL) Edouard@1420: Laurent@814: main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) Laurent@814: main_sizer.AddGrowableCol(0) Laurent@814: main_sizer.AddGrowableRow(0) Laurent@814: main_sizer.AddGrowableRow(1) Edouard@1420: Laurent@814: tasks_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) Laurent@814: tasks_sizer.AddGrowableCol(0) Laurent@814: tasks_sizer.AddGrowableRow(1) Edouard@1420: main_sizer.AddSizer(tasks_sizer, border=5, Laurent@814: flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) Edouard@1420: Laurent@814: tasks_buttons_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) Laurent@814: tasks_buttons_sizer.AddGrowableCol(0) Laurent@814: tasks_buttons_sizer.AddGrowableRow(0) Laurent@814: tasks_sizer.AddSizer(tasks_buttons_sizer, flag=wx.GROW) Edouard@1420: Laurent@814: tasks_label = wx.StaticText(self.Editor, label=_(u'Tasks:')) Laurent@814: tasks_buttons_sizer.AddWindow(tasks_label, flag=wx.ALIGN_BOTTOM) Edouard@1420: Laurent@814: for name, bitmap, help in [ Laurent@814: ("AddTaskButton", "add_element", _("Add task")), Laurent@814: ("DeleteTaskButton", "remove_element", _("Remove task")), Laurent@814: ("UpTaskButton", "up", _("Move task up")), Laurent@814: ("DownTaskButton", "down", _("Move task down"))]: Edouard@1420: button = wx.lib.buttons.GenBitmapButton(self.Editor, Laurent@814: bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER) Laurent@814: button.SetToolTipString(help) Laurent@814: setattr(self, name, button) Laurent@814: tasks_buttons_sizer.AddWindow(button) Edouard@1420: Laurent@814: self.TasksGrid = CustomGrid(self.Editor, style=wx.VSCROLL) Laurent@814: self.TasksGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnTasksGridCellChange) Laurent@814: tasks_sizer.AddWindow(self.TasksGrid, flag=wx.GROW) Edouard@1420: Laurent@814: instances_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) Laurent@814: instances_sizer.AddGrowableCol(0) Laurent@814: instances_sizer.AddGrowableRow(1) Edouard@1420: main_sizer.AddSizer(instances_sizer, border=5, Laurent@814: flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT) Edouard@1420: Laurent@814: instances_buttons_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0) Laurent@814: instances_buttons_sizer.AddGrowableCol(0) Laurent@814: instances_buttons_sizer.AddGrowableRow(0) Laurent@814: instances_sizer.AddSizer(instances_buttons_sizer, flag=wx.GROW) Edouard@1420: Laurent@814: instances_label = wx.StaticText(self.Editor, label=_(u'Instances:')) Laurent@814: instances_buttons_sizer.AddWindow(instances_label, flag=wx.ALIGN_BOTTOM) Edouard@1420: Laurent@814: for name, bitmap, help in [ Laurent@814: ("AddInstanceButton", "add_element", _("Add instance")), Laurent@814: ("DeleteInstanceButton", "remove_element", _("Remove instance")), Laurent@814: ("UpInstanceButton", "up", _("Move instance up")), Laurent@814: ("DownInstanceButton", "down", _("Move instance down"))]: Edouard@1420: button = wx.lib.buttons.GenBitmapButton(self.Editor, Laurent@814: bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER) Laurent@814: button.SetToolTipString(help) Laurent@814: setattr(self, name, button) Laurent@814: instances_buttons_sizer.AddWindow(button) Edouard@1420: Laurent@814: self.InstancesGrid = CustomGrid(self.Editor, style=wx.VSCROLL) Edouard@1420: self.InstancesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, Laurent@814: self.OnInstancesGridCellChange) Laurent@814: instances_sizer.AddWindow(self.InstancesGrid, flag=wx.GROW) Edouard@1420: Laurent@814: self.Editor.SetSizer(main_sizer) Edouard@1420: Laurent@814: def __init__(self, parent, tagname, window, controler): Laurent@814: EditorPanel.__init__(self, parent, tagname, window, controler) Edouard@1420: Laurent@814: self.RefreshHighlightsTimer = wx.Timer(self, -1) Laurent@814: self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer) Edouard@1420: Laurent@814: self.TasksDefaultValue = {"Name" : "", "Triggering" : "", "Single" : "", "Interval" : "", "Priority" : 0} Laurent@814: self.TasksTable = ResourceTable(self, [], GetTasksTableColnames()) Laurent@814: self.TasksTable.SetColAlignements([wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT]) Laurent@814: self.TasksTable.SetColSizes([200, 100, 100, 150, 100]) Laurent@814: self.TasksGrid.SetTable(self.TasksTable) Laurent@814: self.TasksGrid.SetButtons({"Add": self.AddTaskButton, Laurent@814: "Delete": self.DeleteTaskButton, Laurent@814: "Up": self.UpTaskButton, Laurent@814: "Down": self.DownTaskButton}) Edouard@1420: Laurent@814: def _AddTask(new_row): Laurent@814: self.TasksTable.InsertRow(new_row, self.TasksDefaultValue.copy()) Laurent@814: self.RefreshModel() Laurent@814: self.RefreshView() Laurent@814: return new_row Laurent@814: setattr(self.TasksGrid, "_AddRow", _AddTask) Edouard@1420: Laurent@814: def _DeleteTask(row): Laurent@814: self.TasksTable.RemoveRow(row) Laurent@814: self.RefreshModel() Laurent@814: self.RefreshView() Laurent@814: setattr(self.TasksGrid, "_DeleteRow", _DeleteTask) Edouard@1420: Laurent@814: def _MoveTask(row, move): Laurent@814: new_row = self.TasksTable.MoveRow(row, move) Laurent@814: if new_row != row: Laurent@814: self.RefreshModel() Laurent@814: self.RefreshView() Laurent@814: return new_row Laurent@814: setattr(self.TasksGrid, "_MoveRow", _MoveTask) Edouard@1420: Laurent@814: self.TasksGrid.SetRowLabelSize(0) Laurent@814: self.TasksTable.ResetView(self.TasksGrid) Laurent@814: self.TasksGrid.RefreshButtons() Edouard@1420: Laurent@814: self.InstancesDefaultValue = {"Name" : "", "Type" : "", "Task" : ""} Laurent@814: self.InstancesTable = ResourceTable(self, [], GetInstancesTableColnames()) Laurent@814: self.InstancesTable.SetColAlignements([wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]) Laurent@814: self.InstancesTable.SetColSizes([200, 150, 150]) Laurent@814: self.InstancesGrid.SetTable(self.InstancesTable) Laurent@814: self.InstancesGrid.SetButtons({"Add": self.AddInstanceButton, Laurent@814: "Delete": self.DeleteInstanceButton, Laurent@814: "Up": self.UpInstanceButton, Laurent@814: "Down": self.DownInstanceButton}) Edouard@1420: Laurent@814: def _AddInstance(new_row): Laurent@814: self.InstancesTable.InsertRow(new_row, self.InstancesDefaultValue.copy()) Laurent@814: self.RefreshModel() Laurent@814: self.RefreshView() Laurent@814: return new_row Laurent@814: setattr(self.InstancesGrid, "_AddRow", _AddInstance) Edouard@1420: Laurent@814: def _DeleteInstance(row): Laurent@814: self.InstancesTable.RemoveRow(row) Laurent@814: self.RefreshModel() Laurent@814: self.RefreshView() Laurent@814: setattr(self.InstancesGrid, "_DeleteRow", _DeleteInstance) Edouard@1420: Laurent@814: def _MoveInstance(row, move): Laurent@814: new_row = max(0, min(row + move, self.InstancesTable.GetNumberRows() - 1)) Laurent@814: if new_row != row: Laurent@814: if self.InstancesTable.GetValueByName(row, "Task") != self.InstancesTable.GetValueByName(new_row, "Task"): Edouard@1420: return row Laurent@814: self.InstancesTable.MoveRow(row, move) Laurent@814: self.RefreshModel() Laurent@814: self.RefreshView() Laurent@814: return new_row Laurent@814: setattr(self.InstancesGrid, "_MoveRow", _MoveInstance) Edouard@1420: Laurent@814: def _RefreshInstanceButtons(): Laurent@814: if self: Laurent@814: rows = self.InstancesTable.GetNumberRows() Laurent@814: row = self.InstancesGrid.GetGridCursorRow() Laurent@814: self.DeleteInstanceButton.Enable(rows > 0) Edouard@1420: self.UpInstanceButton.Enable(row > 0 and Laurent@814: self.InstancesTable.GetValueByName(row, "Task") == self.InstancesTable.GetValueByName(row - 1, "Task")) Edouard@1420: self.DownInstanceButton.Enable(0 <= row < rows - 1 and Laurent@814: self.InstancesTable.GetValueByName(row, "Task") == self.InstancesTable.GetValueByName(row + 1, "Task")) Laurent@814: setattr(self.InstancesGrid, "RefreshButtons", _RefreshInstanceButtons) Edouard@1420: Laurent@814: self.InstancesGrid.SetRowLabelSize(0) Laurent@814: self.InstancesTable.ResetView(self.InstancesGrid) Laurent@814: self.InstancesGrid.RefreshButtons() Edouard@1420: Laurent@814: self.TasksGrid.SetFocus() Edouard@1420: Laurent@814: def __del__(self): Laurent@814: self.RefreshHighlightsTimer.Stop() Laurent@814: Laurent@814: def RefreshTypeList(self): Laurent@814: self.TypeList = "" Laurent@814: blocktypes = self.Controler.GetBlockResource() Laurent@814: for blocktype in blocktypes: Laurent@814: self.TypeList += ",%s"%blocktype Laurent@814: Laurent@814: def RefreshTaskList(self): Laurent@814: self.TaskList = "" Laurent@814: for row in xrange(self.TasksTable.GetNumberRows()): Laurent@814: self.TaskList += ",%s"%self.TasksTable.GetValueByName(row, "Name") Laurent@814: Laurent@814: def RefreshVariableList(self): Laurent@814: self.VariableList = "" Laurent@814: for variable in self.Controler.GetEditedResourceVariables(self.TagName): Laurent@814: self.VariableList += ",%s"%variable Edouard@1420: Laurent@814: def RefreshModel(self): Laurent@814: self.Controler.SetEditedResourceInfos(self.TagName, self.TasksTable.GetData(), self.InstancesTable.GetData()) Laurent@814: self.RefreshBuffer() Edouard@1420: Laurent@814: # Buffer the last model state Laurent@814: def RefreshBuffer(self): Laurent@814: self.Controler.BufferProject() Laurent@814: self.ParentWindow.RefreshTitle() Laurent@814: self.ParentWindow.RefreshFileMenu() Laurent@814: self.ParentWindow.RefreshEditMenu() Laurent@814: Laurent@814: def GetBufferState(self): Laurent@814: return self.Controler.GetBufferState() Edouard@1420: Laurent@814: def Undo(self): Laurent@814: self.Controler.LoadPrevious() Laurent@814: self.ParentWindow.CloseTabsWithoutModel() Edouard@1420: Laurent@814: def Redo(self): Laurent@814: self.Controler.LoadNext() Laurent@814: self.ParentWindow.CloseTabsWithoutModel() Edouard@1420: Laurent@814: def HasNoModel(self): Laurent@814: return self.Controler.GetEditedElement(self.TagName) is None Laurent@814: Laurent@814: def RefreshView(self, variablepanel=True): Laurent@814: EditorPanel.RefreshView(self, variablepanel) Edouard@1420: Laurent@814: tasks, instances = self.Controler.GetEditedResourceInfos(self.TagName) Laurent@814: self.TasksTable.SetData(tasks) Laurent@814: self.InstancesTable.SetData(instances) Laurent@814: self.RefreshTypeList() Laurent@814: self.RefreshTaskList() Laurent@814: self.RefreshVariableList() Laurent@814: self.TasksTable.ResetView(self.TasksGrid) Laurent@814: self.InstancesTable.ResetView(self.InstancesGrid) Laurent@814: self.TasksGrid.RefreshButtons() Laurent@814: self.InstancesGrid.RefreshButtons() Edouard@1420: andrej@1657: def ShowErrorMessage(self, message): andrej@1657: dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) andrej@1657: dialog.ShowModal() andrej@1657: dialog.Destroy() andrej@1657: Laurent@814: def OnTasksGridCellChange(self, event): Laurent@814: row, col = event.GetRow(), event.GetCol() andrej@1604: if self.TasksTable.GetColLabelValue(col, False) == "Name": andrej@1657: value = self.TasksTable.GetValue(row, col) andrej@1657: message = None andrej@1657: andrej@1657: if not TestIdentifier(value): andrej@1657: message = _("\"%s\" is not a valid identifier!") % value andrej@1657: elif value.upper() in IEC_KEYWORDS: andrej@1657: message = _("\"%s\" is a keyword. It can't be used!") % value andrej@1657: elif value.upper() in [var["Name"].upper() for i, var in enumerate(self.TasksTable.data) if i!=row]: andrej@1657: message = _("A task with the same name already exists!") andrej@1657: if message is not None: andrej@1657: event.Veto() andrej@1657: wx.CallAfter(self.ShowErrorMessage, message) andrej@1657: return andrej@1657: Laurent@814: tasklist = [name for name in self.TaskList.split(",") if name != ""] Laurent@814: for i in xrange(self.TasksTable.GetNumberRows()): Laurent@814: task = self.TasksTable.GetValueByName(i, "Name") Laurent@814: if task in tasklist: Laurent@814: tasklist.remove(task) Laurent@814: if len(tasklist) > 0: andrej@1611: old_name = tasklist[0].upper() Laurent@814: new_name = self.TasksTable.GetValue(row, col) Laurent@814: for i in xrange(self.InstancesTable.GetNumberRows()): andrej@1611: name = self.InstancesTable.GetValueByName(i, "Task").upper() andrej@1611: if old_name == name: Laurent@814: self.InstancesTable.SetValueByName(i, "Task", new_name) Laurent@814: self.RefreshModel() Laurent@814: colname = self.TasksTable.GetColLabelValue(col, False) Edouard@1423: if colname in ["Triggering", "Name", "Single", "Interval"]: Laurent@814: wx.CallAfter(self.RefreshView, False) Laurent@814: event.Skip() Laurent@814: Laurent@814: def OnInstancesGridCellChange(self, event): andrej@1657: row, col = event.GetRow(), event.GetCol() andrej@1657: if self.InstancesTable.GetColLabelValue(col, False) == "Name": andrej@1657: value = self.InstancesTable.GetValue(row, col) andrej@1657: message = None andrej@1657: andrej@1657: if not TestIdentifier(value): andrej@1657: message = _("\"%s\" is not a valid identifier!") % value andrej@1657: elif value.upper() in IEC_KEYWORDS: andrej@1657: message = _("\"%s\" is a keyword. It can't be used!") % value andrej@1657: elif value.upper() in [var["Name"].upper() for i ,var in enumerate(self.InstancesTable.data) if i!=row]: andrej@1657: message = _("An instance with the same name already exists!") andrej@1657: if message is not None: andrej@1657: event.Veto() andrej@1657: wx.CallAfter(self.ShowErrorMessage, message) andrej@1657: return andrej@1657: Laurent@814: self.RefreshModel() Laurent@814: self.ParentWindow.RefreshPouInstanceVariablesPanel() Laurent@814: self.InstancesGrid.RefreshButtons() Laurent@814: event.Skip() Laurent@814: Laurent@814: #------------------------------------------------------------------------------- Laurent@814: # Highlights showing functions Laurent@814: #------------------------------------------------------------------------------- Edouard@1420: Laurent@814: def OnRefreshHighlightsTimer(self, event): Laurent@814: self.RefreshView() Laurent@814: event.Skip() Edouard@1420: Laurent@814: def AddHighlight(self, infos, start, end, highlight_type): Laurent@899: EditorPanel.AddHighlight(self, infos, start, end, highlight_type) Edouard@1420: Laurent@814: if infos[0] == "task": Laurent@814: self.TasksTable.AddHighlight(infos[1:], highlight_type) Laurent@814: elif infos[0] == "instance": Laurent@814: self.InstancesTable.AddHighlight(infos[1:], highlight_type) Laurent@814: self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True) Laurent@814: Laurent@814: def ClearHighlights(self, highlight_type=None): Laurent@814: EditorPanel.ClearHighlights(self, highlight_type) Edouard@1420: Laurent@814: self.TasksTable.ClearHighlights(highlight_type) Laurent@814: self.InstancesTable.ClearHighlights(highlight_type) Laurent@814: self.TasksTable.ResetView(self.TasksGrid) Laurent@814: self.InstancesTable.ResetView(self.InstancesGrid)