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@1881: 
andrej@1881: from __future__ import absolute_import
Laurent@814: import re
Laurent@814: 
Laurent@814: import wx
Laurent@814: 
Laurent@814: from controls import CustomEditableListBox
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@1782: # -------------------------------------------------------------------------------
Laurent@814: #                             Array Type Dialog
andrej@1782: # -------------------------------------------------------------------------------
Laurent@814: 
andrej@1736: 
Laurent@814: class ArrayTypeDialog(wx.Dialog):
andrej@1730: 
Laurent@814:     def __init__(self, parent, datatypes, infos):
andrej@1694:         wx.Dialog.__init__(self, parent, title=_('Edit array type properties'))
andrej@1730: 
Laurent@814:         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
Laurent@814:         main_sizer.AddGrowableCol(0)
Laurent@814:         main_sizer.AddGrowableRow(1)
andrej@1730: 
Laurent@814:         top_sizer = wx.BoxSizer(wx.HORIZONTAL)
andrej@1730:         main_sizer.AddSizer(top_sizer, border=20,
andrej@1768:                             flag=wx.GROW | wx.TOP | wx.LEFT | wx.RIGHT)
andrej@1730: 
Laurent@814:         basetype_label = wx.StaticText(self, label=_('Base Type:'))
Laurent@814:         top_sizer.AddWindow(basetype_label, 1, flag=wx.ALIGN_BOTTOM)
andrej@1730: 
Laurent@814:         self.BaseType = wx.ComboBox(self, style=wx.CB_READONLY)
Laurent@814:         top_sizer.AddWindow(self.BaseType, 1, flag=wx.GROW)
andrej@1730: 
andrej@1730:         self.Dimensions = CustomEditableListBox(self, label=_("Dimensions:"),
andrej@1768:                                                 style=(wx.gizmos.EL_ALLOW_NEW |
andrej@1768:                                                        wx.gizmos.EL_ALLOW_EDIT |
andrej@1768:                                                        wx.gizmos.EL_ALLOW_DELETE))
andrej@1730:         for func in ["_OnLabelEndEdit",
andrej@1730:                      "_OnAddButton",
andrej@1730:                      "_OnDelButton",
andrej@1730:                      "_OnUpButton",
Laurent@814:                      "_OnDownButton"]:
Laurent@814:             setattr(self.Dimensions, func, self.OnDimensionsChanged)
andrej@1730:         main_sizer.AddSizer(self.Dimensions, border=20,
andrej@1768:                             flag=wx.GROW | wx.LEFT | wx.RIGHT)
andrej@1730: 
andrej@1745:         button_sizer = self.CreateButtonSizer(wx.OK | wx.CANCEL | wx.CENTRE)
Laurent@814:         self.Bind(wx.EVT_BUTTON, self.OnOK, button_sizer.GetAffirmativeButton())
andrej@1730:         main_sizer.AddSizer(button_sizer, border=20,
andrej@1768:                             flag=wx.ALIGN_RIGHT | wx.BOTTOM | wx.LEFT | wx.RIGHT)
andrej@1730: 
Laurent@814:         self.SetSizer(main_sizer)
andrej@1730: 
Laurent@814:         for datatype in datatypes:
Laurent@814:             self.BaseType.Append(datatype)
andrej@1730: 
andrej@2450:         if isinstance(infos, tuple) and infos[0] == "array":
Laurent@814:             self.BaseType.SetStringSelection(infos[1])
andrej@1833:             self.Dimensions.SetStrings(map("..".join, infos[2]))
Laurent@814:         elif infos in datatypes:
Laurent@814:             self.BaseType.SetStringSelection(infos)
andrej@1730: 
Laurent@814:         self.BaseType.SetFocus()
andrej@1694:         self.Fit()
andrej@1730: 
Laurent@814:     def GetDimensions(self):
andrej@1726:         message = None
Laurent@814:         dimensions_list = []
andrej@1726:         dimension_strings = self.Dimensions.GetStrings()
andrej@1726:         if len(dimension_strings) == 0:
andrej@1726:             message = _("Empty dimension isn't allowed.")
andrej@1726: 
andrej@1726:         for dimensions in dimension_strings:
Laurent@814:             result = DIMENSION_MODEL.match(dimensions)
Laurent@814:             if result is None:
andrej@1734:                 message = _("\"%s\" value isn't a valid array dimension!") % dimensions
andrej@1726:                 break
Laurent@814:             bounds = result.groups()
Laurent@814:             if int(bounds[0]) >= int(bounds[1]):
andrej@1734:                 message = _("\"%s\" value isn't a valid array dimension!\nRight value must be greater than left value.") % dimensions
andrej@1726:                 break
Laurent@814:             dimensions_list.append(bounds)
andrej@1726: 
andrej@1726:         if message is not None:
andrej@1745:             dlg = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR)
andrej@1726:             dlg.ShowModal()
andrej@1726:             dlg.Destroy()
andrej@1726:             return None
Laurent@814:         return dimensions_list
andrej@1730: 
Laurent@814:     def OnDimensionsChanged(self, event):
Laurent@814:         wx.CallAfter(self.GetDimensions)
Laurent@814:         event.Skip()
andrej@1730: 
Laurent@814:     def OnOK(self, event):
Laurent@814:         if self.GetDimensions() is not None:
Laurent@814:             self.EndModal(wx.ID_OK)
andrej@1730: 
Laurent@814:     def GetValue(self):
Laurent@814:         return "array", self.BaseType.GetStringSelection(), self.GetDimensions()