editors/ResourceEditor.py
branch1.1 Korean release
changeset 968 eee7625de1f7
parent 899 64aa66d481c5
child 1026 96a2dc05651a
equal deleted inserted replaced
808:6e205c1f05a0 968:eee7625de1f7
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard. 
       
     6 #
       
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU General Public
       
    22 #License along with this library; if not, write to the Free Software
       
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    24 
       
    25 import wx
       
    26 import wx.lib.buttons
       
    27 import wx.grid
       
    28 
       
    29 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT
       
    30 from controls import CustomGrid, CustomTable, DurationCellEditor
       
    31 from dialogs.DurationEditorDialog import IEC_TIME_MODEL
       
    32 from EditorPanel import EditorPanel
       
    33 from util.BitmapLibrary import GetBitmap
       
    34 
       
    35 #-------------------------------------------------------------------------------
       
    36 #                          Configuration Editor class
       
    37 #-------------------------------------------------------------------------------
       
    38 
       
    39 [ID_CONFIGURATIONEDITOR, 
       
    40 ] = [wx.NewId() for _init_ctrls in range(1)]
       
    41 
       
    42 class ConfigurationEditor(EditorPanel):
       
    43     
       
    44     ID = ID_CONFIGURATIONEDITOR
       
    45     VARIABLE_PANEL_TYPE = "config"
       
    46     
       
    47     def GetBufferState(self):
       
    48         return self.Controler.GetBufferState()
       
    49         
       
    50     def Undo(self):
       
    51         self.Controler.LoadPrevious()
       
    52         self.ParentWindow.CloseTabsWithoutModel()
       
    53             
       
    54     def Redo(self):
       
    55         self.Controler.LoadNext()
       
    56         self.ParentWindow.CloseTabsWithoutModel()
       
    57     
       
    58     def HasNoModel(self):
       
    59         return self.Controler.GetEditedElement(self.TagName) is None
       
    60 
       
    61 
       
    62 #-------------------------------------------------------------------------------
       
    63 #                            Resource Editor class
       
    64 #-------------------------------------------------------------------------------
       
    65 
       
    66 def GetTasksTableColnames():
       
    67     _ = lambda x : x
       
    68     return [_("Name"), _("Triggering"), _("Single"), _("Interval"), _("Priority")]
       
    69 
       
    70 def GetTaskTriggeringOptions():
       
    71     _ = lambda x : x
       
    72     return [_("Interrupt"), _("Cyclic")]
       
    73 TASKTRIGGERINGOPTIONS_DICT = dict([(_(option), option) for option in GetTaskTriggeringOptions()])
       
    74 
       
    75 def GetInstancesTableColnames():
       
    76     _ = lambda x : x
       
    77     return [_("Name"), _("Type"), _("Task")]
       
    78 
       
    79 class ResourceTable(CustomTable):
       
    80     
       
    81     """
       
    82     A custom wx.grid.Grid Table using user supplied data
       
    83     """
       
    84     def __init__(self, parent, data, colnames):
       
    85         # The base class must be initialized *first*
       
    86         CustomTable.__init__(self, parent, data, colnames)
       
    87         self.ColAlignements = []
       
    88         self.ColSizes = []
       
    89         
       
    90     def GetColAlignements(self):
       
    91         return self.ColAlignements
       
    92     
       
    93     def SetColAlignements(self, list):
       
    94         self.ColAlignements = list
       
    95 
       
    96     def GetColSizes(self):
       
    97         return self.ColSizes
       
    98     
       
    99     def SetColSizes(self, list):
       
   100         self.ColSizes = list
       
   101 
       
   102     def GetValue(self, row, col):
       
   103         if row < self.GetNumberRows():
       
   104             colname = self.GetColLabelValue(col, False)
       
   105             value = str(self.data[row].get(colname, ""))
       
   106             if colname == "Triggering":
       
   107                 return _(value)
       
   108             return value
       
   109         
       
   110     def SetValue(self, row, col, value):
       
   111         if col < len(self.colnames):
       
   112             colname = self.GetColLabelValue(col, False)
       
   113             if colname == "Triggering":
       
   114                 value = TASKTRIGGERINGOPTIONS_DICT[value]
       
   115             self.data[row][colname] = value
       
   116     
       
   117     def _updateColAttrs(self, grid):
       
   118         """
       
   119         wx.grid.Grid -> update the column attributes to add the
       
   120         appropriate renderer given the column name.
       
   121 
       
   122         Otherwise default to the default renderer.
       
   123         """
       
   124         
       
   125         for col in range(self.GetNumberCols()):
       
   126             attr = wx.grid.GridCellAttr()
       
   127             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
       
   128             grid.SetColAttr(col, attr)
       
   129             grid.SetColSize(col, self.ColSizes[col])
       
   130         
       
   131         for row in range(self.GetNumberRows()):
       
   132             row_highlights = self.Highlights.get(row, {})
       
   133             for col in range(self.GetNumberCols()):
       
   134                 editor = None
       
   135                 renderer = None
       
   136                 error = False
       
   137                 colname = self.GetColLabelValue(col, False)
       
   138                 grid.SetReadOnly(row, col, False)
       
   139                 if colname == "Name":
       
   140                     editor = wx.grid.GridCellTextEditor()
       
   141                     renderer = wx.grid.GridCellStringRenderer()
       
   142                 elif colname == "Interval":
       
   143                     editor = DurationCellEditor(self)
       
   144                     renderer = wx.grid.GridCellStringRenderer()
       
   145                     if self.GetValueByName(row, "Triggering") != "Cyclic":
       
   146                         grid.SetReadOnly(row, col, True)
       
   147                     interval = self.GetValueByName(row, colname)
       
   148                     if interval != "" and IEC_TIME_MODEL.match(interval.upper()) is None:
       
   149                         error = True
       
   150                 elif colname == "Single":
       
   151                     editor = wx.grid.GridCellChoiceEditor()
       
   152                     editor.SetParameters(self.Parent.VariableList)
       
   153                     if self.GetValueByName(row, "Triggering") != "Interrupt":
       
   154                         grid.SetReadOnly(row, col, True)
       
   155                 elif colname == "Triggering":
       
   156                     editor = wx.grid.GridCellChoiceEditor()
       
   157                     editor.SetParameters(",".join([""] + map(_, GetTaskTriggeringOptions())))
       
   158                 elif colname == "Type":
       
   159                     editor = wx.grid.GridCellChoiceEditor()
       
   160                     editor.SetParameters(self.Parent.TypeList)
       
   161                 elif colname == "Priority":
       
   162                     editor = wx.grid.GridCellNumberEditor()
       
   163                     editor.SetParameters("0,65535")
       
   164                 elif colname == "Task":
       
   165                     editor = wx.grid.GridCellChoiceEditor()
       
   166                     editor.SetParameters(self.Parent.TaskList)
       
   167                     
       
   168                 grid.SetCellEditor(row, col, editor)
       
   169                 grid.SetCellRenderer(row, col, renderer)
       
   170                 
       
   171                 if error:
       
   172                     highlight_colours = ERROR_HIGHLIGHT
       
   173                 else:
       
   174                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
       
   175                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
       
   176                 grid.SetCellTextColour(row, col, highlight_colours[1])
       
   177             self.ResizeRow(grid, row)
       
   178 
       
   179     
       
   180 #-------------------------------------------------------------------------------
       
   181 #                        Highlights showing functions
       
   182 #-------------------------------------------------------------------------------
       
   183 
       
   184     def AddHighlight(self, infos, highlight_type):
       
   185         row_highlights = self.Highlights.setdefault(infos[0], {})
       
   186         col_highlights = row_highlights.setdefault(infos[1], [])
       
   187         col_highlights.append(highlight_type)
       
   188     
       
   189     def ClearHighlights(self, highlight_type=None):
       
   190         if highlight_type is None:
       
   191             self.Highlights = {}
       
   192         else:
       
   193             for row, row_highlights in self.Highlights.iteritems():
       
   194                 row_items = row_highlights.items()
       
   195                 for col, col_highlights in row_items:
       
   196                     if highlight_type in col_highlights:
       
   197                         col_highlights.remove(highlight_type)
       
   198                     if len(col_highlights) == 0:
       
   199                         row_highlights.pop(col)
       
   200 
       
   201 
       
   202 
       
   203 class ResourceEditor(EditorPanel):
       
   204     
       
   205     VARIABLE_PANEL_TYPE = "resource"
       
   206 
       
   207     def _init_Editor(self, parent):
       
   208         self.Editor = wx.Panel(parent, style=wx.SUNKEN_BORDER|wx.TAB_TRAVERSAL)
       
   209         
       
   210         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
   211         main_sizer.AddGrowableCol(0)
       
   212         main_sizer.AddGrowableRow(0)
       
   213         main_sizer.AddGrowableRow(1)
       
   214         
       
   215         tasks_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
   216         tasks_sizer.AddGrowableCol(0)
       
   217         tasks_sizer.AddGrowableRow(1)
       
   218         main_sizer.AddSizer(tasks_sizer, border=5, 
       
   219               flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
       
   220         
       
   221         tasks_buttons_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
       
   222         tasks_buttons_sizer.AddGrowableCol(0)
       
   223         tasks_buttons_sizer.AddGrowableRow(0)
       
   224         tasks_sizer.AddSizer(tasks_buttons_sizer, flag=wx.GROW)
       
   225         
       
   226         tasks_label = wx.StaticText(self.Editor, label=_(u'Tasks:'))
       
   227         tasks_buttons_sizer.AddWindow(tasks_label, flag=wx.ALIGN_BOTTOM)
       
   228         
       
   229         for name, bitmap, help in [
       
   230                 ("AddTaskButton", "add_element", _("Add task")),
       
   231                 ("DeleteTaskButton", "remove_element", _("Remove task")),
       
   232                 ("UpTaskButton", "up", _("Move task up")),
       
   233                 ("DownTaskButton", "down", _("Move task down"))]:
       
   234             button = wx.lib.buttons.GenBitmapButton(self.Editor, 
       
   235                   bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER)
       
   236             button.SetToolTipString(help)
       
   237             setattr(self, name, button)
       
   238             tasks_buttons_sizer.AddWindow(button)
       
   239         
       
   240         self.TasksGrid = CustomGrid(self.Editor, style=wx.VSCROLL)
       
   241         self.TasksGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnTasksGridCellChange)
       
   242         tasks_sizer.AddWindow(self.TasksGrid, flag=wx.GROW)
       
   243         
       
   244         instances_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
       
   245         instances_sizer.AddGrowableCol(0)
       
   246         instances_sizer.AddGrowableRow(1)
       
   247         main_sizer.AddSizer(instances_sizer, border=5, 
       
   248               flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
       
   249         
       
   250         instances_buttons_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
       
   251         instances_buttons_sizer.AddGrowableCol(0)
       
   252         instances_buttons_sizer.AddGrowableRow(0)
       
   253         instances_sizer.AddSizer(instances_buttons_sizer, flag=wx.GROW)
       
   254         
       
   255         instances_label = wx.StaticText(self.Editor, label=_(u'Instances:'))
       
   256         instances_buttons_sizer.AddWindow(instances_label, flag=wx.ALIGN_BOTTOM)
       
   257         
       
   258         for name, bitmap, help in [
       
   259                 ("AddInstanceButton", "add_element", _("Add instance")),
       
   260                 ("DeleteInstanceButton", "remove_element", _("Remove instance")),
       
   261                 ("UpInstanceButton", "up", _("Move instance up")),
       
   262                 ("DownInstanceButton", "down", _("Move instance down"))]:
       
   263             button = wx.lib.buttons.GenBitmapButton(self.Editor, 
       
   264                   bitmap=GetBitmap(bitmap), size=wx.Size(28, 28), style=wx.NO_BORDER)
       
   265             button.SetToolTipString(help)
       
   266             setattr(self, name, button)
       
   267             instances_buttons_sizer.AddWindow(button)
       
   268         
       
   269         self.InstancesGrid = CustomGrid(self.Editor, style=wx.VSCROLL)
       
   270         self.InstancesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
       
   271               self.OnInstancesGridCellChange)
       
   272         instances_sizer.AddWindow(self.InstancesGrid, flag=wx.GROW)
       
   273         
       
   274         self.Editor.SetSizer(main_sizer)
       
   275         
       
   276     def __init__(self, parent, tagname, window, controler):
       
   277         EditorPanel.__init__(self, parent, tagname, window, controler)
       
   278         
       
   279         self.RefreshHighlightsTimer = wx.Timer(self, -1)
       
   280         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
       
   281         
       
   282         self.TasksDefaultValue = {"Name" : "", "Triggering" : "", "Single" : "", "Interval" : "", "Priority" : 0}
       
   283         self.TasksTable = ResourceTable(self, [], GetTasksTableColnames())
       
   284         self.TasksTable.SetColAlignements([wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT])
       
   285         self.TasksTable.SetColSizes([200, 100, 100, 150, 100])
       
   286         self.TasksGrid.SetTable(self.TasksTable)
       
   287         self.TasksGrid.SetButtons({"Add": self.AddTaskButton,
       
   288                                    "Delete": self.DeleteTaskButton,
       
   289                                    "Up": self.UpTaskButton,
       
   290                                    "Down": self.DownTaskButton})
       
   291         
       
   292         def _AddTask(new_row):
       
   293             self.TasksTable.InsertRow(new_row, self.TasksDefaultValue.copy())
       
   294             self.RefreshModel()
       
   295             self.RefreshView()
       
   296             return new_row
       
   297         setattr(self.TasksGrid, "_AddRow", _AddTask)
       
   298         
       
   299         def _DeleteTask(row):
       
   300             self.TasksTable.RemoveRow(row)
       
   301             self.RefreshModel()
       
   302             self.RefreshView()
       
   303         setattr(self.TasksGrid, "_DeleteRow", _DeleteTask)
       
   304         
       
   305         def _MoveTask(row, move):
       
   306             new_row = self.TasksTable.MoveRow(row, move)
       
   307             if new_row != row:
       
   308                 self.RefreshModel()
       
   309                 self.RefreshView()
       
   310             return new_row
       
   311         setattr(self.TasksGrid, "_MoveRow", _MoveTask)
       
   312         
       
   313         self.TasksGrid.SetRowLabelSize(0)
       
   314         self.TasksTable.ResetView(self.TasksGrid)
       
   315         self.TasksGrid.RefreshButtons()
       
   316         
       
   317         self.InstancesDefaultValue = {"Name" : "", "Type" : "", "Task" : ""}
       
   318         self.InstancesTable = ResourceTable(self, [], GetInstancesTableColnames())
       
   319         self.InstancesTable.SetColAlignements([wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT])
       
   320         self.InstancesTable.SetColSizes([200, 150, 150])
       
   321         self.InstancesGrid.SetTable(self.InstancesTable)
       
   322         self.InstancesGrid.SetButtons({"Add": self.AddInstanceButton,
       
   323                                        "Delete": self.DeleteInstanceButton,
       
   324                                        "Up": self.UpInstanceButton,
       
   325                                        "Down": self.DownInstanceButton})
       
   326         
       
   327         def _AddInstance(new_row):
       
   328             self.InstancesTable.InsertRow(new_row, self.InstancesDefaultValue.copy())
       
   329             self.RefreshModel()
       
   330             self.RefreshView()
       
   331             return new_row
       
   332         setattr(self.InstancesGrid, "_AddRow", _AddInstance)
       
   333         
       
   334         def _DeleteInstance(row):
       
   335             self.InstancesTable.RemoveRow(row)
       
   336             self.RefreshModel()
       
   337             self.RefreshView()
       
   338         setattr(self.InstancesGrid, "_DeleteRow", _DeleteInstance)
       
   339         
       
   340         def _MoveInstance(row, move):
       
   341             new_row = max(0, min(row + move, self.InstancesTable.GetNumberRows() - 1))
       
   342             if new_row != row:
       
   343                 if self.InstancesTable.GetValueByName(row, "Task") != self.InstancesTable.GetValueByName(new_row, "Task"):
       
   344                     return row 
       
   345                 self.InstancesTable.MoveRow(row, move)
       
   346                 self.RefreshModel()
       
   347                 self.RefreshView()
       
   348             return new_row
       
   349         setattr(self.InstancesGrid, "_MoveRow", _MoveInstance)
       
   350         
       
   351         def _RefreshInstanceButtons():
       
   352             if self:
       
   353                 rows = self.InstancesTable.GetNumberRows()
       
   354                 row = self.InstancesGrid.GetGridCursorRow()
       
   355                 self.DeleteInstanceButton.Enable(rows > 0)
       
   356                 self.UpInstanceButton.Enable(row > 0 and 
       
   357                     self.InstancesTable.GetValueByName(row, "Task") == self.InstancesTable.GetValueByName(row - 1, "Task"))
       
   358                 self.DownInstanceButton.Enable(0 <= row < rows - 1 and 
       
   359                     self.InstancesTable.GetValueByName(row, "Task") == self.InstancesTable.GetValueByName(row + 1, "Task"))
       
   360         setattr(self.InstancesGrid, "RefreshButtons", _RefreshInstanceButtons)
       
   361         
       
   362         self.InstancesGrid.SetRowLabelSize(0)
       
   363         self.InstancesTable.ResetView(self.InstancesGrid)
       
   364         self.InstancesGrid.RefreshButtons()
       
   365         
       
   366         self.TasksGrid.SetFocus()
       
   367         
       
   368     def __del__(self):
       
   369         self.RefreshHighlightsTimer.Stop()
       
   370 
       
   371     def RefreshTypeList(self):
       
   372         self.TypeList = ""
       
   373         blocktypes = self.Controler.GetBlockResource()
       
   374         for blocktype in blocktypes:
       
   375             self.TypeList += ",%s"%blocktype
       
   376 
       
   377     def RefreshTaskList(self):
       
   378         self.TaskList = ""
       
   379         for row in xrange(self.TasksTable.GetNumberRows()):
       
   380             self.TaskList += ",%s"%self.TasksTable.GetValueByName(row, "Name")
       
   381 
       
   382     def RefreshVariableList(self):
       
   383         self.VariableList = ""
       
   384         for variable in self.Controler.GetEditedResourceVariables(self.TagName):
       
   385             self.VariableList += ",%s"%variable
       
   386         
       
   387     def RefreshModel(self):
       
   388         self.Controler.SetEditedResourceInfos(self.TagName, self.TasksTable.GetData(), self.InstancesTable.GetData())
       
   389         self.RefreshBuffer()
       
   390         
       
   391     # Buffer the last model state
       
   392     def RefreshBuffer(self):
       
   393         self.Controler.BufferProject()
       
   394         self.ParentWindow.RefreshTitle()
       
   395         self.ParentWindow.RefreshFileMenu()
       
   396         self.ParentWindow.RefreshEditMenu()
       
   397 
       
   398     def GetBufferState(self):
       
   399         return self.Controler.GetBufferState()
       
   400         
       
   401     def Undo(self):
       
   402         self.Controler.LoadPrevious()
       
   403         self.ParentWindow.CloseTabsWithoutModel()
       
   404             
       
   405     def Redo(self):
       
   406         self.Controler.LoadNext()
       
   407         self.ParentWindow.CloseTabsWithoutModel()
       
   408     
       
   409     def HasNoModel(self):
       
   410         return self.Controler.GetEditedElement(self.TagName) is None
       
   411 
       
   412     def RefreshView(self, variablepanel=True):
       
   413         EditorPanel.RefreshView(self, variablepanel)
       
   414         
       
   415         tasks, instances = self.Controler.GetEditedResourceInfos(self.TagName)
       
   416         self.TasksTable.SetData(tasks)
       
   417         self.InstancesTable.SetData(instances)
       
   418         self.RefreshTypeList()
       
   419         self.RefreshTaskList()
       
   420         self.RefreshVariableList()
       
   421         self.TasksTable.ResetView(self.TasksGrid)
       
   422         self.InstancesTable.ResetView(self.InstancesGrid)
       
   423         self.TasksGrid.RefreshButtons()
       
   424         self.InstancesGrid.RefreshButtons()
       
   425         
       
   426     def OnTasksGridCellChange(self, event):
       
   427         row, col = event.GetRow(), event.GetCol()
       
   428         if self.TasksTable.GetColLabelValue(col) == "Name":
       
   429             tasklist = [name for name in self.TaskList.split(",") if name != ""]
       
   430             for i in xrange(self.TasksTable.GetNumberRows()):
       
   431                 task = self.TasksTable.GetValueByName(i, "Name")
       
   432                 if task in tasklist:
       
   433                     tasklist.remove(task)
       
   434             if len(tasklist) > 0:
       
   435                 old_name = tasklist[0]
       
   436                 new_name = self.TasksTable.GetValue(row, col)
       
   437                 for i in xrange(self.InstancesTable.GetNumberRows()):
       
   438                     if self.InstancesTable.GetValueByName(i, "Task") == old_name:
       
   439                         self.InstancesTable.SetValueByName(i, "Task", new_name)
       
   440         self.RefreshModel()
       
   441         colname = self.TasksTable.GetColLabelValue(col, False)
       
   442         if colname in ["Triggering", "Name", "Interval"]:
       
   443             wx.CallAfter(self.RefreshView, False)
       
   444         event.Skip()
       
   445 
       
   446     def OnInstancesGridCellChange(self, event):
       
   447         self.RefreshModel()
       
   448         self.ParentWindow.RefreshPouInstanceVariablesPanel()
       
   449         self.InstancesGrid.RefreshButtons()
       
   450         event.Skip()
       
   451 
       
   452 #-------------------------------------------------------------------------------
       
   453 #                        Highlights showing functions
       
   454 #-------------------------------------------------------------------------------
       
   455     
       
   456     def OnRefreshHighlightsTimer(self, event):
       
   457         self.RefreshView()
       
   458         event.Skip()
       
   459     
       
   460     def AddHighlight(self, infos, start, end, highlight_type):
       
   461         EditorPanel.AddHighlight(self, infos, start, end, highlight_type)
       
   462         
       
   463         if infos[0] == "task":
       
   464             self.TasksTable.AddHighlight(infos[1:], highlight_type)
       
   465         elif infos[0] == "instance":
       
   466             self.InstancesTable.AddHighlight(infos[1:], highlight_type)
       
   467         self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
       
   468 
       
   469     def ClearHighlights(self, highlight_type=None):
       
   470         EditorPanel.ClearHighlights(self, highlight_type)
       
   471         
       
   472         self.TasksTable.ClearHighlights(highlight_type)
       
   473         self.InstancesTable.ClearHighlights(highlight_type)
       
   474         self.TasksTable.ResetView(self.TasksGrid)
       
   475         self.InstancesTable.ResetView(self.InstancesGrid)