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: andrej@1853: andrej@1853: from __future__ import absolute_import Laurent@814: import wx Laurent@814: import wx.lib.buttons Laurent@814: import wx.grid andrej@2432: from six.moves import xrange 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 andrej@1853: from editors.EditorPanel import EditorPanel Laurent@814: from util.BitmapLibrary import GetBitmap andrej@1834: from util.TranslationCatalogs import NoTranslate andrej@1850: from plcopen.structures import TestIdentifier, IEC_KEYWORDS andrej@1782: andrej@1782: andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: # Configuration Editor class andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: Laurent@814: andrej@1773: [ andrej@1773: ID_CONFIGURATIONEDITOR, Laurent@814: ] = [wx.NewId() for _init_ctrls in range(1)] Laurent@814: andrej@1736: 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: andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: # Resource Editor class andrej@1782: # ------------------------------------------------------------------------------- Laurent@814: Laurent@814: def GetTasksTableColnames(): andrej@1762: _ = NoTranslate Laurent@814: return [_("Name"), _("Triggering"), _("Single"), _("Interval"), _("Priority")] Laurent@814: andrej@1736: Laurent@814: def GetTaskTriggeringOptions(): andrej@1762: _ = NoTranslate Laurent@814: return [_("Interrupt"), _("Cyclic")] andrej@1749: andrej@1749: andrej@1762: def SingleCellEditor(*x): andrej@1762: return wx.grid.GridCellChoiceEditor() Edouard@1423: andrej@1736: Edouard@1423: def CheckSingle(single, varlist): Edouard@1423: return single in varlist Edouard@1423: Edouard@1423: Laurent@814: def GetInstancesTableColnames(): andrej@1762: _ = NoTranslate Laurent@814: return [_("Name"), _("Type"), _("Task")] Laurent@814: andrej@1736: Laurent@814: class ResourceTable(CustomTable): 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 = [] andrej@2301: self.TASKTRIGGERINGOPTIONS_DICT = dict([(_(option), option) andrej@2301: for option in GetTaskTriggeringOptions()]) 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": andrej@2301: value = self.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": andrej@1740: 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) andrej@1740: 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: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Highlights showing functions andrej@1782: # ------------------------------------------------------------------------------- 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: andrej@1847: 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: class ResourceEditor(EditorPanel): Edouard@1420: Laurent@814: VARIABLE_PANEL_TYPE = "resource" Laurent@814: Laurent@814: def _init_Editor(self, parent): andrej@1745: 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, andrej@1768: 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, andrej@1768: bitmap=GetBitmap(bitmap), andrej@1768: size=wx.Size(28, 28), andrej@1768: 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, andrej@1768: 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"))]: andrej@1768: button = wx.lib.buttons.GenBitmapButton( andrej@1768: self.Editor, bitmap=GetBitmap(bitmap), andrej@1768: 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) andrej@1768: self.InstancesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 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: surkovsv93@1968: self.TasksDefaultValue = {"Name": "task0", "Triggering": "Cyclic", surkovsv93@1968: "Single": "", "Interval": "T#20ms", "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): surkovsv93@1968: if new_row > 0: surkovsv93@1968: row_content = self.TasksTable.data[new_row-1].copy() surkovsv93@1968: old_name = row_content['Name'] surkovsv93@1968: row_content['Name'] =\ surkovsv93@1968: self.Controler.GenerateNewName(self.TagName, old_name, old_name+'%d') surkovsv93@1968: else: surkovsv93@1968: row_content = self.TasksDefaultValue.copy() surkovsv93@1968: surkovsv93@1968: self.TasksTable.InsertRow(new_row, row_content) 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: surkovsv93@1968: self.InstancesDefaultValue = {"Name": "instance0", "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): surkovsv93@1968: if new_row > 0: surkovsv93@1968: row_content = self.InstancesTable.data[new_row - 1].copy() surkovsv93@1968: old_name = row_content['Name'] surkovsv93@1968: row_content['Name'] =\ surkovsv93@1968: self.Controler.GenerateNewName(self.TagName, old_name, old_name+'%d') surkovsv93@1968: else: surkovsv93@1968: row_content = self.InstancesDefaultValue.copy() surkovsv93@1968: surkovsv93@1968: self.InstancesTable.InsertRow(new_row, row_content) 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) andrej@1768: self.UpInstanceButton.Enable( andrej@1768: row > 0 and Laurent@814: self.InstancesTable.GetValueByName(row, "Task") == self.InstancesTable.GetValueByName(row - 1, "Task")) andrej@1768: self.DownInstanceButton.Enable( andrej@1768: 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: andrej@1734: self.TypeList += ",%s" % blocktype Laurent@814: Laurent@814: def RefreshTaskList(self): Laurent@814: self.TaskList = "" Laurent@814: for row in xrange(self.TasksTable.GetNumberRows()): andrej@1734: 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): andrej@1734: 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@1745: 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@1742: 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) andrej@2232: if self.TasksTable.GetColLabelValue(col, False) == "Triggering": andrej@2232: self.TasksTable.SetValueByName(row, "Interval", "T#20ms") 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@1742: 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: andrej@1782: # ------------------------------------------------------------------------------- andrej@1782: # Highlights showing functions andrej@1782: # ------------------------------------------------------------------------------- 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)