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
andrej@1812: # Copyright (C) 2017: Andrey Skvortsov
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: 
Laurent@814: import re
Laurent@814: 
Laurent@814: import wx
Laurent@814: import wx.grid
Laurent@814: import wx.lib.buttons
Edouard@1412: from plcopen.structures import IEC_KEYWORDS, TestIdentifier, DefaultType
Laurent@814: from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD
andrej@1812: from controls import CustomEditableListBox, CustomGrid, CustomTable, CustomIntCtrl
Laurent@864: from dialogs import ArrayTypeDialog
andrej@1853: from editors.EditorPanel import EditorPanel
Laurent@814: from util.BitmapLibrary import GetBitmap
andrej@1762: from util.TranslationCatalogs import NoTranslate
Laurent@814: 
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: #                                    Helpers
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
andrej@2439: DIMENSION_MODEL = re.compile(r"([0-9]+)\.\.([0-9]+)$")
Laurent@814: 
andrej@1736: 
Edouard@2737: def AppendMenu(parent, help, kind, text):
edouard@3449:     return parent.Append(wx.MenuItem(helpString=help, id=wx.ID_ANY, kind=kind, text=text))
Laurent@814: 
andrej@1736: 
Laurent@814: def GetElementsTableColnames():
andrej@1762:     _ = NoTranslate
Laurent@814:     return ["#", _("Name"), _("Type"), _("Initial Value")]
Laurent@814: 
andrej@1736: 
Laurent@814: def GetDatatypeTypes():
andrej@1762:     _ = NoTranslate
Laurent@814:     return [_("Directly"), _("Subrange"), _("Enumerated"), _("Array"), _("Structure")]
andrej@1749: 
andrej@1749: 
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: #                            Structure Elements Table
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
andrej@1736: 
Laurent@814: class ElementsTable(CustomTable):
Edouard@1412: 
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.old_value = None
Edouard@1412: 
Laurent@814:     def GetValue(self, row, col):
Laurent@814:         if row < self.GetNumberRows():
Laurent@814:             if col == 0:
Laurent@814:                 return row + 1
Laurent@864:             colname = self.GetColLabelValue(col, False)
Laurent@864:             value = self.data[row].get(colname, "")
andrej@1735: 
andrej@2450:             if colname == "Type" and isinstance(value, tuple):
Laurent@864:                 if value[0] == "array":
andrej@1833:                     return "ARRAY [%s] OF %s" % (",".join(map("..".join, value[2])), value[1])
andrej@1508:             return value
Edouard@1412: 
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 == "Name":
Laurent@814:                 self.old_value = self.data[row][colname]
Laurent@814:             self.data[row][colname] = value
Edouard@1412: 
Laurent@814:     def GetOldValue(self):
Laurent@814:         return self.old_value
Edouard@1412: 
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@1412: 
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@814:                 colname = self.GetColLabelValue(col, False)
Laurent@814:                 if col != 0:
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 == "Initial Value":
Laurent@814:                         editor = wx.grid.GridCellTextEditor()
Laurent@814:                         renderer = wx.grid.GridCellStringRenderer()
Laurent@814:                     elif colname == "Type":
Laurent@814:                         editor = wx.grid.GridCellTextEditor()
Laurent@814:                 else:
Laurent@814:                     grid.SetReadOnly(row, col, True)
Edouard@1412: 
Laurent@814:                 grid.SetCellEditor(row, col, editor)
Laurent@814:                 grid.SetCellRenderer(row, col, renderer)
Edouard@1412: 
Laurent@814:                 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)
Edouard@1412: 
Laurent@814:     def AddHighlight(self, infos, highlight_type):
Laurent@814:         row_highlights = self.Highlights.setdefault(infos[0], {})
Laurent@814:         if infos[1] == "initial":
Laurent@814:             col_highlights = row_highlights.setdefault("initial value", [])
Laurent@814:         else:
Laurent@814:             col_highlights = row_highlights.setdefault(infos[1], [])
Laurent@814:         col_highlights.append(highlight_type)
Laurent@814: 
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: #                          Datatype Editor class
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
andrej@1736: 
Laurent@814: class DataTypeEditor(EditorPanel):
Edouard@1412: 
Laurent@814:     def _init_Editor(self, parent):
Laurent@814:         self.Editor = wx.Panel(parent, style=wx.SUNKEN_BORDER)
Edouard@1412: 
Laurent@814:         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
Laurent@814:         self.MainSizer.AddGrowableCol(0)
Laurent@814:         self.MainSizer.AddGrowableRow(1)
Edouard@1412: 
Laurent@814:         top_sizer = wx.BoxSizer(wx.HORIZONTAL)
edouard@3303:         self.MainSizer.Add(top_sizer, border=5,
andrej@1768:                                 flag=wx.GROW | wx.TOP | wx.LEFT | wx.RIGHT)
Edouard@1412: 
Laurent@814:         derivation_type_label = wx.StaticText(self.Editor, label=_('Derivation Type:'))
edouard@3303:         top_sizer.Add(derivation_type_label, border=5,
andrej@1768:                             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT)
Edouard@1412: 
Laurent@814:         self.DerivationType = wx.ComboBox(self.Editor,
andrej@1768:                                           size=wx.Size(200, -1), style=wx.CB_READONLY)
Laurent@814:         self.Bind(wx.EVT_COMBOBOX, self.OnDerivationTypeChanged, self.DerivationType)
edouard@3303:         top_sizer.Add(self.DerivationType, border=5, flag=wx.GROW | wx.RIGHT)
Edouard@1412: 
Laurent@814:         typeinfos_staticbox = wx.StaticBox(self.Editor, label=_('Type infos:'))
Laurent@814:         typeinfos_sizer = wx.StaticBoxSizer(typeinfos_staticbox, wx.HORIZONTAL)
edouard@3303:         self.MainSizer.Add(typeinfos_sizer, border=5,
andrej@1768:                                 flag=wx.GROW | wx.BOTTOM | wx.LEFT | wx.RIGHT)
Edouard@1412: 
Laurent@814:         # Panel for Directly derived data types
Laurent@814: 
Laurent@814:         self.DirectlyPanel = wx.Panel(self.Editor, style=wx.TAB_TRAVERSAL)
edouard@3303:         typeinfos_sizer.Add(self.DirectlyPanel, 1)
Edouard@1412: 
Laurent@814:         directly_panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
Edouard@1412: 
Edouard@1412:         directly_basetype_label = wx.StaticText(self.DirectlyPanel,
andrej@1768:                                                 label=_('Base Type:'))
edouard@3303:         directly_panel_sizer.Add(directly_basetype_label, 1, border=5,
andrej@1768:                                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
Laurent@814:         self.DirectlyBaseType = wx.ComboBox(self.DirectlyPanel, style=wx.CB_READONLY)
Laurent@947:         self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, self.DirectlyBaseType)
edouard@3303:         directly_panel_sizer.Add(self.DirectlyBaseType, 1, border=5,
andrej@1768:                                        flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         directly_initialvalue_label = wx.StaticText(self.DirectlyPanel,
andrej@1768:                                                     label=_('Initial Value:'))
edouard@3303:         directly_panel_sizer.Add(directly_initialvalue_label, 1, border=5,
andrej@1768:                                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
Edouard@1412:         self.DirectlyInitialValue = wx.TextCtrl(self.DirectlyPanel,
andrej@1768:                                                 style=wx.TE_PROCESS_ENTER | wx.TE_RICH)
Laurent@814:         self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, self.DirectlyInitialValue)
edouard@3303:         directly_panel_sizer.Add(self.DirectlyInitialValue, 1, border=5,
andrej@1768:                                        flag=wx.ALL)
Edouard@1412: 
Laurent@814:         self.DirectlyPanel.SetSizer(directly_panel_sizer)
Edouard@1412: 
Laurent@814:         # Panel for Subrange data types
Laurent@814: 
Laurent@814:         self.SubrangePanel = wx.Panel(self.Editor, style=wx.TAB_TRAVERSAL)
edouard@3303:         typeinfos_sizer.Add(self.SubrangePanel, 1)
Edouard@1412: 
Laurent@814:         subrange_panel_sizer = wx.GridSizer(cols=4, hgap=5, rows=3, vgap=0)
Edouard@1412: 
Laurent@814:         subrange_basetype_label = wx.StaticText(self.SubrangePanel,
andrej@1768:                                                 label=_('Base Type:'))
edouard@3303:         subrange_panel_sizer.Add(subrange_basetype_label, 1, border=5,
andrej@1768:                                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
Laurent@814:         self.SubrangeBaseType = wx.ComboBox(self.SubrangePanel, style=wx.CB_READONLY)
Edouard@1412:         self.Bind(wx.EVT_COMBOBOX, self.OnSubrangeBaseTypeChanged,
andrej@1768:                   self.SubrangeBaseType)
edouard@3303:         subrange_panel_sizer.Add(self.SubrangeBaseType, 1, border=5,
andrej@1768:                                        flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         subrange_initialvalue_label = wx.StaticText(self.SubrangePanel,
andrej@1768:                                                     label=_('Initial Value:'))
edouard@3303:         subrange_panel_sizer.Add(subrange_initialvalue_label, 1, border=5,
andrej@1768:                                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
andrej@1812:         self.SubrangeInitialValue = CustomIntCtrl(self.SubrangePanel, style=wx.TAB_TRAVERSAL)
andrej@1812:         self.SubrangeInitialValue.Bind(CustomIntCtrl.EVT_CUSTOM_INT, self.OnInfosChanged)
edouard@3303:         subrange_panel_sizer.Add(self.SubrangeInitialValue, 1, border=5,
andrej@1768:                                        flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         subrange_minimum_label = wx.StaticText(self.SubrangePanel, label=_('Minimum:'))
edouard@3303:         subrange_panel_sizer.Add(subrange_minimum_label, 1, border=5,
andrej@1768:                                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
andrej@1812:         self.SubrangeMinimum = CustomIntCtrl(self.SubrangePanel, style=wx.TAB_TRAVERSAL)
andrej@1812:         self.SubrangeMinimum.Bind(CustomIntCtrl.EVT_CUSTOM_INT, self.OnSubrangeMinimumChanged)
edouard@3303:         subrange_panel_sizer.Add(self.SubrangeMinimum, 1, border=5,
andrej@1768:                                        flag=wx.GROW | wx.ALL)
Edouard@1412: 
kinsamanka@3750:         for dummy in range(2):
edouard@3303:             subrange_panel_sizer.Add(wx.Size(0, 0), 1)
Edouard@1412: 
Laurent@814:         subrange_maximum_label = wx.StaticText(self.SubrangePanel,
andrej@1768:                                                label=_('Maximum:'))
edouard@3303:         subrange_panel_sizer.Add(subrange_maximum_label, 1, border=5,
andrej@1768:                                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
andrej@1812:         self.SubrangeMaximum = CustomIntCtrl(self.SubrangePanel, style=wx.TAB_TRAVERSAL)
andrej@1812:         self.SubrangeMaximum.Bind(CustomIntCtrl.EVT_CUSTOM_INT, self.OnSubrangeMaximumChanged)
Edouard@1412: 
edouard@3303:         subrange_panel_sizer.Add(self.SubrangeMaximum, 1, border=5,
andrej@1768:                                        flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         self.SubrangePanel.SetSizer(subrange_panel_sizer)
Edouard@1412: 
Laurent@814:         # Panel for Enumerated data types
Edouard@1412: 
Laurent@814:         self.EnumeratedPanel = wx.Panel(self.Editor, style=wx.TAB_TRAVERSAL)
edouard@3303:         typeinfos_sizer.Add(self.EnumeratedPanel, 1)
Edouard@1412: 
Laurent@814:         enumerated_panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
Edouard@1412: 
andrej@1768:         self.EnumeratedValues = CustomEditableListBox(
andrej@1878:             self.EnumeratedPanel,
andrej@1878:             label=_("Values:"),
edouard@3303:             style=(wx.adv.EL_ALLOW_NEW |
edouard@3303:                    wx.adv.EL_ALLOW_EDIT |
edouard@3303:                    wx.adv.EL_ALLOW_DELETE))
Laurent@814:         setattr(self.EnumeratedValues, "_OnLabelEndEdit", self.OnEnumeratedValueEndEdit)
Laurent@814:         for func in ["_OnAddButton", "_OnDelButton", "_OnUpButton", "_OnDownButton"]:
Laurent@814:             setattr(self.EnumeratedValues, func, self.OnEnumeratedValuesChanged)
edouard@3303:         enumerated_panel_sizer.Add(self.EnumeratedValues, 1, border=5,
andrej@1768:                                          flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         enumerated_panel_rightsizer = wx.BoxSizer(wx.HORIZONTAL)
edouard@3303:         enumerated_panel_sizer.Add(enumerated_panel_rightsizer, 1)
Edouard@1412: 
Laurent@814:         enumerated_initialvalue_label = wx.StaticText(self.EnumeratedPanel,
andrej@1768:                                                       label=_('Initial Value:'))
edouard@3303:         enumerated_panel_rightsizer.Add(enumerated_initialvalue_label, 1,
andrej@1768:                                               border=5,
andrej@1768:                                               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
Edouard@1412:         self.EnumeratedInitialValue = wx.ComboBox(self.EnumeratedPanel,
andrej@1768:                                                   style=wx.CB_READONLY)
Laurent@814:         self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, self.EnumeratedInitialValue)
edouard@3303:         enumerated_panel_rightsizer.Add(self.EnumeratedInitialValue, 1,
andrej@1768:                                               border=5, flag=wx.ALL)
Edouard@1412: 
Laurent@814:         self.EnumeratedPanel.SetSizer(enumerated_panel_sizer)
Edouard@1412: 
Laurent@814:         # Panel for Array data types
Laurent@814: 
Laurent@814:         self.ArrayPanel = wx.Panel(self.Editor, style=wx.TAB_TRAVERSAL)
edouard@3303:         typeinfos_sizer.Add(self.ArrayPanel, 1)
Edouard@1412: 
Laurent@814:         array_panel_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=0)
Laurent@814:         array_panel_sizer.AddGrowableCol(0)
Laurent@814:         array_panel_sizer.AddGrowableCol(1)
Laurent@814:         array_panel_sizer.AddGrowableRow(1)
Edouard@1412: 
Laurent@814:         array_panel_leftSizer = wx.BoxSizer(wx.HORIZONTAL)
edouard@3303:         array_panel_sizer.Add(array_panel_leftSizer, flag=wx.GROW)
Edouard@1412: 
Laurent@814:         array_basetype_label = wx.StaticText(self.ArrayPanel, label=_('Base Type:'))
edouard@3303:         array_panel_leftSizer.Add(array_basetype_label, 1, border=5,
andrej@1768:                                         flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
Laurent@814:         self.ArrayBaseType = wx.ComboBox(self.ArrayPanel, style=wx.CB_READONLY)
Laurent@814:         self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, self.ArrayBaseType)
edouard@3303:         array_panel_leftSizer.Add(self.ArrayBaseType, 1, border=5,
andrej@1768:                                         flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         array_panel_rightsizer = wx.BoxSizer(wx.HORIZONTAL)
edouard@3303:         array_panel_sizer.Add(array_panel_rightsizer, flag=wx.GROW)
Edouard@1412: 
Laurent@814:         array_initialvalue_label = wx.StaticText(self.ArrayPanel,
andrej@1768:                                                  label=_('Initial Value:'))
edouard@3303:         array_panel_rightsizer.Add(array_initialvalue_label, 1, border=5,
andrej@1768:                                          flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL)
Edouard@1412: 
Laurent@814:         self.ArrayInitialValue = wx.TextCtrl(self.ArrayPanel,
andrej@1768:                                              style=wx.TE_PROCESS_ENTER | wx.TE_RICH)
Laurent@814:         self.Bind(wx.EVT_TEXT_ENTER, self.OnReturnKeyPressed, self.ArrayInitialValue)
edouard@3303:         array_panel_rightsizer.Add(self.ArrayInitialValue, 1, border=5,
andrej@1768:                                          flag=wx.ALL)
andrej@1768: 
andrej@1768:         self.ArrayDimensions = CustomEditableListBox(
andrej@1878:             self.ArrayPanel,
andrej@1878:             label=_("Dimensions:"),
edouard@3303:             style=(wx.adv.EL_ALLOW_NEW |
edouard@3303:                    wx.adv.EL_ALLOW_EDIT |
edouard@3303:                    wx.adv.EL_ALLOW_DELETE))
Edouard@1412:         for func in ["_OnLabelEndEdit", "_OnAddButton", "_OnDelButton",
Laurent@814:                      "_OnUpButton", "_OnDownButton"]:
Laurent@814:             setattr(self.ArrayDimensions, func, self.OnDimensionsChanged)
edouard@3303:         array_panel_sizer.Add(self.ArrayDimensions, 0, border=5,
andrej@1768:                                     flag=wx.GROW | wx.ALL)
Edouard@1412: 
Laurent@814:         self.ArrayPanel.SetSizer(array_panel_sizer)
Edouard@1412: 
Laurent@814:         # Panel for Structure data types
Edouard@1412: 
Laurent@814:         self.StructurePanel = wx.Panel(self.Editor, style=wx.TAB_TRAVERSAL)
edouard@3303:         typeinfos_sizer.Add(self.StructurePanel, 1)
Edouard@1412: 
Laurent@814:         structure_panel_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0)
Laurent@814:         structure_panel_sizer.AddGrowableCol(0)
Laurent@814:         structure_panel_sizer.AddGrowableRow(1)
Edouard@1412: 
Laurent@814:         structure_button_sizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
Laurent@814:         structure_button_sizer.AddGrowableCol(0)
Laurent@814:         structure_button_sizer.AddGrowableRow(0)
edouard@3303:         structure_panel_sizer.Add(structure_button_sizer, 0, border=5,
andrej@1768:                                        flag=wx.ALL | wx.GROW)
Edouard@1412: 
Laurent@814:         structure_elements_label = wx.StaticText(self.StructurePanel,
andrej@1768:                                                  label=_('Elements :'))
edouard@3303:         structure_button_sizer.Add(structure_elements_label, flag=wx.ALIGN_BOTTOM)
Edouard@1412: 
Laurent@814:         for name, bitmap, help in [
Laurent@814:                 ("StructureAddButton", "add_element", _("Add element")),
Laurent@814:                 ("StructureDeleteButton", "remove_element", _("Remove element")),
Laurent@814:                 ("StructureUpButton", "up", _("Move element up")),
Laurent@814:                 ("StructureDownButton", "down", _("Move element down"))]:
Laurent@814:             button = wx.lib.buttons.GenBitmapButton(self.StructurePanel,
andrej@1768:                                                     bitmap=GetBitmap(bitmap),
andrej@1768:                                                     size=wx.Size(28, 28),
andrej@1768:                                                     style=wx.NO_BORDER)
edouard@3303:             button.SetToolTip(help)
Laurent@814:             setattr(self, name, button)
edouard@3303:             structure_button_sizer.Add(button)
Edouard@1412: 
Edouard@1412:         self.StructureElementsGrid = CustomGrid(self.StructurePanel,
andrej@1768:                                                 size=wx.Size(0, 150), style=wx.VSCROLL)
edouard@3449:         self.StructureElementsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGED,
andrej@1768:                                         self.OnStructureElementsGridCellChange)
Edouard@1412:         self.StructureElementsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
andrej@1768:                                         self.OnStructureElementsGridEditorShown)
edouard@3303:         structure_panel_sizer.Add(self.StructureElementsGrid, flag=wx.GROW)
Edouard@1412: 
Laurent@814:         self.StructurePanel.SetSizer(structure_panel_sizer)
Edouard@1412: 
Laurent@814:         self.Editor.SetSizer(self.MainSizer)
Edouard@1412: 
Laurent@814:     def __init__(self, parent, tagname, window, controler):
Laurent@814:         EditorPanel.__init__(self, parent, tagname, window, controler)
Edouard@1412: 
andrej@1739:         self.StructureElementDefaultValue = {"Name": "", "Type": DefaultType, "Initial Value": ""}
Laurent@814:         self.StructureElementsTable = ElementsTable(self, [], GetElementsTableColnames())
Laurent@814:         self.StructureColSizes = [40, 150, 100, 250]
Laurent@814:         self.StructureColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
Edouard@1412: 
Laurent@814:         self.StructureElementsGrid.SetTable(self.StructureElementsTable)
Laurent@814:         self.StructureElementsGrid.SetButtons({"Add": self.StructureAddButton,
Laurent@814:                                                "Delete": self.StructureDeleteButton,
Laurent@814:                                                "Up": self.StructureUpButton,
Laurent@814:                                                "Down": self.StructureDownButton})
Edouard@1412: 
andrej@1821:         self.DATATYPE_TYPES_DICT = dict([(_(datatype), datatype) for datatype in GetDatatypeTypes()])
andrej@1821: 
Laurent@814:         def _AddStructureElement(new_row):
Laurent@814:             self.StructureElementsTable.InsertRow(new_row, self.StructureElementDefaultValue.copy())
Laurent@814:             self.RefreshTypeInfos()
Laurent@814:             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
Laurent@814:             return new_row
Laurent@814:         setattr(self.StructureElementsGrid, "_AddRow", _AddStructureElement)
Edouard@1412: 
Laurent@814:         def _DeleteStructureElement(row):
Laurent@814:             self.StructureElementsTable.RemoveRow(row)
Laurent@814:             self.RefreshTypeInfos()
Laurent@814:             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
Laurent@814:         setattr(self.StructureElementsGrid, "_DeleteRow", _DeleteStructureElement)
Edouard@1412: 
Laurent@814:         def _MoveStructureElement(row, move):
Laurent@814:             new_row = self.StructureElementsTable.MoveRow(row, move)
Laurent@814:             if new_row != row:
Laurent@814:                 self.RefreshTypeInfos()
Laurent@814:                 self.StructureElementsTable.ResetView(self.StructureElementsGrid)
Laurent@814:             return new_row
Laurent@814:         setattr(self.StructureElementsGrid, "_MoveRow", _MoveStructureElement)
Edouard@1412: 
Laurent@814:         self.StructureElementsGrid.SetRowLabelSize(0)
Laurent@814:         for col in range(self.StructureElementsTable.GetNumberCols()):
Laurent@814:             attr = wx.grid.GridCellAttr()
Laurent@814:             attr.SetAlignment(self.StructureColAlignements[col], wx.ALIGN_CENTRE)
Laurent@814:             self.StructureElementsGrid.SetColAttr(col, attr)
Laurent@814:             self.StructureElementsGrid.SetColMinimalWidth(col, self.StructureColSizes[col])
Laurent@814:             self.StructureElementsGrid.AutoSizeColumn(col, False)
Laurent@814:         self.StructureElementsGrid.RefreshButtons()
Edouard@1412: 
Laurent@814:         for datatype in GetDatatypeTypes():
Laurent@814:             self.DerivationType.Append(_(datatype))
Laurent@814:         self.SubrangePanel.Hide()
Laurent@814:         self.EnumeratedPanel.Hide()
Laurent@814:         self.ArrayPanel.Hide()
Laurent@814:         self.StructurePanel.Hide()
Laurent@814:         self.CurrentPanel = "Directly"
Laurent@814:         self.Highlights = []
Laurent@814:         self.Initializing = False
Edouard@1412: 
Laurent@814:         self.HighlightControls = {
Laurent@814:             ("Directly", "base"): self.DirectlyBaseType,
Laurent@814:             ("Directly", "initial"): self.DirectlyInitialValue,
Laurent@814:             ("Subrange", "base"): self.SubrangeBaseType,
Laurent@814:             ("Subrange", "lower"): self.SubrangeMinimum,
Laurent@814:             ("Subrange", "upper"): self.SubrangeMaximum,
Laurent@814:             ("Subrange", "initial"): self.SubrangeInitialValue,
Laurent@814:             ("Enumerated", "value"): self.EnumeratedValues,
Laurent@814:             ("Enumerated", "initial"): self.EnumeratedInitialValue,
Laurent@814:             ("Array", "initial"): self.ArrayInitialValue,
Laurent@814:             ("Array", "base"): self.ArrayBaseType,
Laurent@814:             ("Array", "range"): self.ArrayDimensions,
Laurent@814:         }
Edouard@1412: 
Laurent@814:         self.RefreshHighlightsTimer = wx.Timer(self, -1)
Laurent@814:         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
Edouard@1412: 
Laurent@814:     def GetBufferState(self):
Laurent@814:         return self.Controler.GetBufferState()
Edouard@1412: 
Laurent@814:     def Undo(self):
Laurent@814:         self.Controler.LoadPrevious()
Laurent@814:         self.ParentWindow.CloseTabsWithoutModel()
Edouard@1412: 
Laurent@814:     def Redo(self):
Laurent@814:         self.Controler.LoadNext()
Laurent@814:         self.ParentWindow.CloseTabsWithoutModel()
Edouard@1412: 
Laurent@814:     def HasNoModel(self):
Laurent@814:         return self.Controler.GetEditedElement(self.TagName) is None
Edouard@1412: 
Laurent@814:     def RefreshView(self):
Laurent@814:         self.Initializing = True
Laurent@814:         self.DirectlyBaseType.Clear()
Laurent@814:         self.ArrayBaseType.Clear()
Laurent@814:         for datatype in self.Controler.GetDataTypes(self.TagName):
Laurent@814:             self.DirectlyBaseType.Append(datatype)
Laurent@814:             self.ArrayBaseType.Append(datatype)
Laurent@814:         self.DirectlyBaseType.SetSelection(0)
Laurent@814:         self.SubrangeBaseType.Clear()
Laurent@814:         words = self.TagName.split("::")
Laurent@814:         for base_type in self.Controler.GetSubrangeBaseTypes(words[1]):
Laurent@814:             self.SubrangeBaseType.Append(base_type)
Laurent@814:         self.SubrangeBaseType.SetSelection(0)
Laurent@814:         self.RefreshBoundsRange()
Laurent@814:         type_infos = self.Controler.GetDataTypeInfos(self.TagName)
Laurent@814:         if type_infos is not None:
Laurent@814:             datatype = type_infos["type"]
Laurent@814:             self.DerivationType.SetStringSelection(_(datatype))
Laurent@814:             if type_infos["type"] == "Directly":
Laurent@814:                 self.DirectlyBaseType.SetStringSelection(type_infos["base_type"])
Laurent@814:                 self.DirectlyInitialValue.SetValue(type_infos["initial"])
Laurent@814:             elif type_infos["type"] == "Subrange":
Laurent@814:                 self.SubrangeBaseType.SetStringSelection(type_infos["base_type"])
Laurent@814:                 self.RefreshBoundsRange()
Laurent@814:                 self.SubrangeMinimum.SetValue(int(type_infos["min"]))
Laurent@814:                 self.SubrangeMaximum.SetValue(int(type_infos["max"]))
Laurent@814:                 self.RefreshSubrangeInitialValueRange()
Laurent@814:                 if type_infos["initial"] != "":
Laurent@814:                     self.SubrangeInitialValue.SetValue(int(type_infos["initial"]))
Laurent@814:                 else:
Laurent@814:                     self.SubrangeInitialValue.SetValue(type_infos["min"])
Laurent@814:             elif type_infos["type"] == "Enumerated":
Laurent@814:                 self.EnumeratedValues.SetStrings(type_infos["values"])
Laurent@814:                 self.RefreshEnumeratedValues()
Laurent@814:                 self.EnumeratedInitialValue.SetStringSelection(type_infos["initial"])
Laurent@814:             elif type_infos["type"] == "Array":
Laurent@814:                 self.ArrayBaseType.SetStringSelection(type_infos["base_type"])
kinsamanka@3750:                 self.ArrayDimensions.SetStrings(list(map("..".join, type_infos["dimensions"])))
Laurent@814:                 self.ArrayInitialValue.SetValue(type_infos["initial"])
Laurent@814:             elif type_infos["type"] == "Structure":
Laurent@814:                 self.StructureElementsTable.SetData(type_infos["elements"])
Laurent@814:             self.RefreshDisplayedInfos()
Laurent@814:         self.ShowHighlights()
Laurent@814:         self.StructureElementsTable.ResetView(self.StructureElementsGrid)
Laurent@814:         self.StructureElementsGrid.RefreshButtons()
Laurent@814:         self.Initializing = False
Edouard@1412: 
Laurent@814:     def OnDerivationTypeChanged(self, event):
Laurent@814:         wx.CallAfter(self.RefreshDisplayedInfos)
Laurent@814:         wx.CallAfter(self.RefreshTypeInfos)
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def OnReturnKeyPressed(self, event):
Laurent@814:         self.RefreshTypeInfos()
Edouard@1412: 
Laurent@814:     def OnInfosChanged(self, event):
Laurent@814:         self.RefreshTypeInfos()
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def OnSubrangeBaseTypeChanged(self, event):
Laurent@814:         self.RefreshBoundsRange()
Laurent@814:         self.RefreshTypeInfos()
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def OnSubrangeMinimumChanged(self, event):
Laurent@814:         if not self.Initializing:
Laurent@814:             wx.CallAfter(self.SubrangeMinimum.SetValue, min(self.SubrangeMaximum.GetValue(), self.SubrangeMinimum.GetValue()))
Laurent@814:             wx.CallAfter(self.RefreshSubrangeInitialValueRange)
Laurent@814:             wx.CallAfter(self.RefreshTypeInfos)
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def OnSubrangeMaximumChanged(self, event):
Laurent@814:         if not self.Initializing:
Laurent@814:             wx.CallAfter(self.SubrangeMaximum.SetValue, max(self.SubrangeMinimum.GetValue(), self.SubrangeMaximum.GetValue()))
Laurent@814:             wx.CallAfter(self.RefreshSubrangeInitialValueRange)
Laurent@814:             wx.CallAfter(self.RefreshTypeInfos)
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def OnDimensionsChanged(self, event):
Laurent@814:         wx.CallAfter(self.RefreshTypeInfos)
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def OnEnumeratedValueEndEdit(self, event):
Laurent@814:         text = event.GetText()
Laurent@814:         values = self.EnumeratedValues.GetStrings()
Laurent@814:         index = event.GetIndex()
Laurent@814:         if index >= len(values) or values[index].upper() != text.upper():
Laurent@814:             if text.upper() in [value.upper() for value in values]:
andrej@1745:                 message = wx.MessageDialog(self, _("\"%s\" value already defined!") % text, _("Error"), wx.OK | wx.ICON_ERROR)
Laurent@814:                 message.ShowModal()
Laurent@814:                 message.Destroy()
Laurent@814:                 event.Veto()
Laurent@814:             elif text.upper() in IEC_KEYWORDS:
andrej@1745:                 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!") % text, _("Error"), wx.OK | wx.ICON_ERROR)
Laurent@814:                 message.ShowModal()
Laurent@814:                 message.Destroy()
Laurent@814:             else:
Laurent@814:                 initial_selected = None
Laurent@814:                 if index < len(values) and self.EnumeratedInitialValue.GetStringSelection() == values[index]:
Laurent@814:                     initial_selected = text
Laurent@814:                 wx.CallAfter(self.RefreshEnumeratedValues, initial_selected)
Laurent@814:                 wx.CallAfter(self.RefreshTypeInfos)
Laurent@814:                 event.Skip()
Laurent@814:         else:
Laurent@814:             event.Skip()
Edouard@1412: 
Laurent@814:     def OnEnumeratedValuesChanged(self, event):
Laurent@814:         wx.CallAfter(self.RefreshEnumeratedValues)
Laurent@814:         wx.CallAfter(self.RefreshTypeInfos)
Laurent@814:         event.Skip()
Edouard@1412: 
andrej@1658:     def ShowErrorMessage(self, message):
andrej@1745:         dialog = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR)
andrej@1658:         dialog.ShowModal()
andrej@1658:         dialog.Destroy()
andrej@1735: 
Laurent@814:     def OnStructureElementsGridCellChange(self, event):
Laurent@814:         row, col = event.GetRow(), event.GetCol()
Laurent@947:         colname = self.StructureElementsTable.GetColLabelValue(col, False)
Laurent@814:         value = self.StructureElementsTable.GetValue(row, col)
Laurent@814:         if colname == "Name":
andrej@1658:             message = None
Laurent@814:             if not TestIdentifier(value):
andrej@1734:                 message = _("\"%s\" is not a valid identifier!") % value
Laurent@814:             elif value.upper() in IEC_KEYWORDS:
andrej@1734:                 message = _("\"%s\" is a keyword. It can't be used!") % value
andrej@1753: #            elif value.upper() in self.PouNames:
andrej@1753: #                message = _("A pou with \"%s\" as name exists!")%value
Laurent@814:             elif value.upper() in [var["Name"].upper() for idx, var in enumerate(self.StructureElementsTable.GetData()) if idx != row]:
andrej@1734:                 message = _("An element named \"%s\" already exists in this structure!") % value
Laurent@814:             else:
Laurent@814:                 self.RefreshTypeInfos()
Laurent@814:                 wx.CallAfter(self.StructureElementsTable.ResetView, self.StructureElementsGrid)
andrej@1753: #                old_value = self.Table.GetOldValue()
andrej@1753: #                if old_value != "":
andrej@1753: #                    self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_value, value)
andrej@1753: #                self.Controler.BufferProject()
Laurent@814:                 event.Skip()
andrej@1658: 
andrej@1658:             if message is not None:
andrej@1658:                 event.Veto()
andrej@1658:                 wx.CallAfter(self.ShowErrorMessage, message)
Laurent@814:         else:
Laurent@814:             self.RefreshTypeInfos()
Laurent@814:             wx.CallAfter(self.StructureElementsTable.ResetView, self.StructureElementsGrid)
Laurent@814:             event.Skip()
Edouard@1412: 
Laurent@814:     def OnStructureElementsGridSelectCell(self, event):
Laurent@814:         wx.CallAfter(self.RefreshStructureButtons)
Laurent@814:         event.Skip()
Edouard@1412: 
Laurent@814:     def OnStructureElementsGridEditorShown(self, event):
Edouard@1412:         row, col = event.GetRow(), event.GetCol()
Laurent@947:         if self.StructureElementsTable.GetColLabelValue(col, False) == "Type":
Laurent@814:             type_menu = wx.Menu(title='')
Edouard@1412: 
Laurent@814:             base_menu = wx.Menu(title='')
Laurent@814:             for base_type in self.Controler.GetBaseTypes():
Edouard@2737:                 new_entry = AppendMenu(base_menu, help='', kind=wx.ITEM_NORMAL, text=base_type)
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.GetElementTypeFunction(base_type), new_entry)
Edouard@2737:             type_menu.AppendMenu(wx.ID_ANY, _("Base Types"), base_menu)
Edouard@1412: 
Laurent@814:             datatype_menu = wx.Menu(title='')
Laurent@814:             for datatype in self.Controler.GetDataTypes(self.TagName, False):
Edouard@2737:                 new_entry = AppendMenu(datatype_menu, help='', kind=wx.ITEM_NORMAL, text=datatype)
Edouard@2737:                 self.Bind(wx.EVT_MENU, self.GetElementTypeFunction(datatype), new_entry)
Edouard@2737:             type_menu.AppendMenu(wx.ID_ANY, _("User Data Types"), datatype_menu)
Edouard@2737: 
Edouard@2737:             new_entry = AppendMenu(type_menu, help='', kind=wx.ITEM_NORMAL, text=_("Array"))
Edouard@2737:             self.Bind(wx.EVT_MENU, self.ElementArrayTypeFunction, new_entry)
Laurent@864: 
Laurent@814:             rect = self.StructureElementsGrid.BlockToDeviceRect((row, col), (row, col))
edouard@3303:             self.StructureElementsGrid.PopupMenu(type_menu, rect.x + rect.width, rect.y + self.StructureElementsGrid.GetColLabelSize())
Laurent@814:             type_menu.Destroy()
Laurent@814:             event.Veto()
Laurent@814:         else:
Laurent@814:             event.Skip()
Laurent@814: 
Laurent@814:     def GetElementTypeFunction(self, base_type):
Laurent@814:         def ElementTypeFunction(event):
Laurent@814:             row = self.StructureElementsGrid.GetGridCursorRow()
Laurent@814:             self.StructureElementsTable.SetValueByName(row, "Type", base_type)
Laurent@814:             self.RefreshTypeInfos()
Laurent@814:             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
Laurent@814:         return ElementTypeFunction
Laurent@814: 
Laurent@864:     def ElementArrayTypeFunction(self, event):
Laurent@864:         row = self.StructureElementsGrid.GetGridCursorRow()
Edouard@1412:         dialog = ArrayTypeDialog(self,
Edouard@1412:                                  self.Controler.GetDataTypes(self.TagName),
Laurent@864:                                  self.StructureElementsTable.GetValueByName(row, "Type"))
Laurent@864:         if dialog.ShowModal() == wx.ID_OK:
Laurent@864:             self.StructureElementsTable.SetValueByName(row, "Type", dialog.GetValue())
Laurent@864:             self.RefreshTypeInfos()
Laurent@864:             self.StructureElementsTable.ResetView(self.StructureElementsGrid)
Laurent@864:         dialog.Destroy()
Laurent@864: 
Laurent@814:     def RefreshDisplayedInfos(self):
andrej@1821:         selected = self.DATATYPE_TYPES_DICT[self.DerivationType.GetStringSelection()]
Laurent@814:         if selected != self.CurrentPanel:
Laurent@814:             if self.CurrentPanel == "Directly":
Laurent@814:                 self.DirectlyPanel.Hide()
Laurent@814:             elif self.CurrentPanel == "Subrange":
Laurent@814:                 self.SubrangePanel.Hide()
Laurent@814:             elif self.CurrentPanel == "Enumerated":
Laurent@814:                 self.EnumeratedPanel.Hide()
Laurent@814:             elif self.CurrentPanel == "Array":
Laurent@814:                 self.ArrayPanel.Hide()
Laurent@814:             elif self.CurrentPanel == "Structure":
Laurent@814:                 self.StructurePanel.Hide()
Laurent@814:             self.CurrentPanel = selected
Laurent@814:             if selected == "Directly":
Laurent@814:                 self.DirectlyPanel.Show()
Laurent@814:             elif selected == "Subrange":
Laurent@814:                 self.SubrangePanel.Show()
Laurent@814:             elif selected == "Enumerated":
Laurent@814:                 self.EnumeratedPanel.Show()
Laurent@814:             elif selected == "Array":
Laurent@814:                 self.ArrayPanel.Show()
Laurent@814:             elif selected == "Structure":
Laurent@814:                 self.StructurePanel.Show()
Laurent@814:             self.MainSizer.Layout()
Laurent@814: 
Laurent@814:     def RefreshEnumeratedValues(self, initial_selected=None):
Laurent@814:         if initial_selected is None:
Laurent@814:             initial_selected = self.EnumeratedInitialValue.GetStringSelection()
Laurent@814:         self.EnumeratedInitialValue.Clear()
Laurent@814:         self.EnumeratedInitialValue.Append("")
Laurent@814:         for value in self.EnumeratedValues.GetStrings():
Laurent@814:             self.EnumeratedInitialValue.Append(value)
Laurent@814:         self.EnumeratedInitialValue.SetStringSelection(initial_selected)
Laurent@814: 
Laurent@814:     def RefreshBoundsRange(self):
Laurent@814:         range = self.Controler.GetDataTypeRange(self.SubrangeBaseType.GetStringSelection())
Laurent@814:         if range is not None:
Laurent@814:             min_value, max_value = range
andrej@1812:             self.SubrangeMinimum.SetBounds(min_value, max_value)
Laurent@814:             self.SubrangeMinimum.SetValue(min(max(min_value, self.SubrangeMinimum.GetValue()), max_value))
andrej@1812:             self.SubrangeMaximum.SetBounds(min_value, max_value)
Laurent@814:             self.SubrangeMaximum.SetValue(min(max(min_value, self.SubrangeMaximum.GetValue()), max_value))
Laurent@814: 
Laurent@814:     def RefreshSubrangeInitialValueRange(self):
andrej@1812:         self.SubrangeInitialValue.SetBounds(self.SubrangeMinimum.GetValue(), self.SubrangeMaximum.GetValue())
Laurent@814: 
Laurent@814:     def RefreshTypeInfos(self):
andrej@1821:         selected = self.DATATYPE_TYPES_DICT[self.DerivationType.GetStringSelection()]
andrej@1739:         infos = {"type": selected}
Laurent@814:         if selected == "Directly":
Laurent@814:             infos["base_type"] = self.DirectlyBaseType.GetStringSelection()
Laurent@814:             infos["initial"] = self.DirectlyInitialValue.GetValue()
Laurent@814:         elif selected == "Subrange":
Laurent@814:             infos["base_type"] = self.SubrangeBaseType.GetStringSelection()
Laurent@814:             infos["min"] = str(self.SubrangeMinimum.GetValue())
Laurent@814:             infos["max"] = str(self.SubrangeMaximum.GetValue())
Laurent@814:             initial_value = self.SubrangeInitialValue.GetValue()
Laurent@814:             if initial_value == infos["min"]:
Laurent@814:                 infos["initial"] = ""
Laurent@814:             else:
Laurent@814:                 infos["initial"] = str(initial_value)
Laurent@814:         elif selected == "Enumerated":
Laurent@814:             infos["values"] = self.EnumeratedValues.GetStrings()
Laurent@814:             infos["initial"] = self.EnumeratedInitialValue.GetStringSelection()
Laurent@814:         elif selected == "Array":
Laurent@814:             infos["base_type"] = self.ArrayBaseType.GetStringSelection()
Laurent@814:             infos["dimensions"] = []
Laurent@814:             for dimensions in self.ArrayDimensions.GetStrings():
Laurent@814:                 result = DIMENSION_MODEL.match(dimensions)
Laurent@814:                 if result is None:
andrej@1745:                     message = wx.MessageDialog(self, _("\"%s\" value isn't a valid array dimension!") % dimensions, _("Error"), wx.OK | wx.ICON_ERROR)
Laurent@814:                     message.ShowModal()
Laurent@814:                     message.Destroy()
Laurent@814:                     self.RefreshView()
Laurent@814:                     return
Laurent@814:                 bounds = result.groups()
Laurent@814:                 if int(bounds[0]) >= int(bounds[1]):
andrej@1745:                     message = wx.MessageDialog(self, _("\"%s\" value isn't a valid array dimension!\nRight value must be greater than left value.") % dimensions, _("Error"), wx.OK | wx.ICON_ERROR)
Laurent@814:                     message.ShowModal()
Laurent@814:                     message.Destroy()
Laurent@814:                     self.RefreshView()
Laurent@814:                     return
Laurent@814:                 infos["dimensions"].append(bounds)
Laurent@814:             infos["initial"] = self.ArrayInitialValue.GetValue()
Laurent@814:         elif selected == "Structure":
Laurent@814:             infos["elements"] = self.StructureElementsTable.GetData()
Laurent@814:             infos["initial"] = ""
Laurent@814:         self.Controler.SetDataTypeInfos(self.TagName, infos)
Laurent@814:         self.ParentWindow.RefreshTitle()
Laurent@814:         self.ParentWindow.RefreshFileMenu()
Laurent@814:         self.ParentWindow.RefreshEditMenu()
Laurent@814: 
andrej@1782:     # -------------------------------------------------------------------------------
andrej@1782:     #                        Highlights showing functions
andrej@1782:     # -------------------------------------------------------------------------------
Laurent@814: 
Laurent@814:     def OnRefreshHighlightsTimer(self, event):
Laurent@814:         self.RefreshView()
Laurent@814:         event.Skip()
Laurent@814: 
Laurent@814:     def ClearHighlights(self, highlight_type=None):
Laurent@814:         if highlight_type is None:
Laurent@814:             self.Highlights = []
Laurent@814:         else:
Laurent@814:             self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
kinsamanka@3750:         for control in self.HighlightControls.values():
Laurent@814:             if isinstance(control, (wx.ComboBox, wx.SpinCtrl)):
Laurent@814:                 control.SetBackgroundColour(wx.NullColour)
Laurent@814:                 control.SetForegroundColour(wx.NullColour)
Laurent@814:             elif isinstance(control, wx.TextCtrl):
andrej@1812:                 value = control.GetValueStr() if isinstance(control, CustomIntCtrl) else \
andrej@1812:                         control.GetValue()
Laurent@814:                 control.SetStyle(0, len(value), wx.TextAttr(wx.NullColour))
edouard@3303:             elif isinstance(control, wx.adv.EditableListBox):
Laurent@814:                 listctrl = control.GetListCtrl()
kinsamanka@3750:                 for i in range(listctrl.GetItemCount()):
Laurent@814:                     listctrl.SetItemBackgroundColour(i, wx.NullColour)
Laurent@814:                     listctrl.SetItemTextColour(i, wx.NullColour)
Laurent@814:         self.StructureElementsTable.ClearHighlights(highlight_type)
Laurent@814:         self.RefreshView()
Laurent@814: 
andrej@1739:     def AddHighlight(self, infos, start, end, highlight_type):
Laurent@814:         self.Highlights.append((infos, start, end, highlight_type))
Laurent@814:         self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
Laurent@814: 
Laurent@814:     def ShowHighlights(self):
Laurent@814:         type_infos = self.Controler.GetDataTypeInfos(self.TagName)
Laurent@814:         for infos, start, end, highlight_type in self.Highlights:
Laurent@814:             if infos[0] == "struct":
Laurent@814:                 self.StructureElementsTable.AddHighlight(infos[1:], highlight_type)
Laurent@814:             else:
Laurent@814:                 control = self.HighlightControls.get((type_infos["type"], infos[0]), None)
Laurent@814:                 if control is not None:
Laurent@814:                     if isinstance(control, (wx.ComboBox, wx.SpinCtrl)):
Laurent@814:                         control.SetBackgroundColour(highlight_type[0])
Laurent@814:                         control.SetForegroundColour(highlight_type[1])
Laurent@814:                     elif isinstance(control, wx.TextCtrl):
Laurent@814:                         control.SetStyle(start[1], end[1] + 1, wx.TextAttr(highlight_type[1], highlight_type[0]))
edouard@3303:                     elif isinstance(control, wx.adv.EditableListBox):
Laurent@814:                         listctrl = control.GetListCtrl()
Laurent@814:                         listctrl.SetItemBackgroundColour(infos[1], highlight_type[0])
Laurent@814:                         listctrl.SetItemTextColour(infos[1], highlight_type[1])
Laurent@814:                         listctrl.Select(listctrl.FocusedItem, False)