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@1881: kinsamanka@3750: Laurent@814: import wx Laurent@814: Laurent@814: from dialogs.BrowseLocationsDialog import BrowseLocationsDialog Laurent@814: andrej@1736: kinsamanka@3789: class LocationCellControl(wx.Control): andrej@1730: Laurent@814: ''' Laurent@814: Custom cell editor control with a text box and a button that launches Laurent@814: the BrowseLocationsDialog. Laurent@814: ''' Laurent@814: def __init__(self, parent): kinsamanka@3789: wx.Control.__init__(self, parent) andrej@1730: Laurent@814: main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=0) Laurent@814: main_sizer.AddGrowableCol(0) Laurent@814: main_sizer.AddGrowableRow(0) andrej@1730: Laurent@814: # create location text control andrej@1730: self.Location = wx.TextCtrl(self, size=wx.Size(0, -1), andrej@1768: style=wx.TE_PROCESS_ENTER) Laurent@814: self.Location.Bind(wx.EVT_KEY_DOWN, self.OnLocationChar) edouard@3303: main_sizer.Add(self.Location, flag=wx.GROW) andrej@1730: Laurent@814: # create browse button Laurent@814: self.BrowseButton = wx.Button(self, label='...', size=wx.Size(30, -1)) Laurent@814: self.BrowseButton.Bind(wx.EVT_BUTTON, self.OnBrowseButtonClick) edouard@3303: main_sizer.Add(self.BrowseButton, flag=wx.GROW) andrej@1730: Laurent@814: self.Bind(wx.EVT_SIZE, self.OnSize) andrej@1730: Laurent@814: self.SetSizer(main_sizer) Laurent@814: Laurent@855: self.Controller = None Laurent@814: self.VarType = None Laurent@814: self.Default = False Edouard@2574: self.VariableName = None Laurent@814: Laurent@855: def SetController(self, controller): Laurent@855: self.Controller = controller Laurent@814: Laurent@814: def SetVarType(self, vartype): Laurent@814: self.VarType = vartype Laurent@814: Laurent@855: def GetVarType(self): Laurent@855: return self.VarType Laurent@855: Laurent@814: def SetValue(self, value): Laurent@814: self.Default = value Edouard@2574: self.VariableName = None Edouard@2574: self.VarType = None Laurent@814: self.Location.SetValue(value) andrej@1730: Laurent@814: def GetValue(self): Laurent@814: return self.Location.GetValue() Laurent@814: Edouard@2573: def GetName(self): Edouard@2573: return self.VariableName edouard@2579: Laurent@814: def OnSize(self, event): Laurent@814: self.Layout() Laurent@814: Laurent@814: def OnBrowseButtonClick(self, event): Laurent@814: # pop up the location browser dialog Laurent@855: dialog = BrowseLocationsDialog(self, self.VarType, self.Controller) Laurent@814: if dialog.ShowModal() == wx.ID_OK: Laurent@814: infos = dialog.GetValues() Laurent@1004: else: Laurent@1004: infos = None Laurent@1004: dialog.Destroy() andrej@1730: Laurent@1004: if infos is not None: Laurent@1004: location = infos["location"] Laurent@814: # set the location Laurent@1004: if not infos["location"].startswith("%"): andrej@1768: dialog = wx.SingleChoiceDialog( andrej@1768: self, andrej@1768: _("Select a variable class:"), andrej@1768: _("Variable class"), andrej@1768: [_("Input"), _("Output"), _("Memory")], andrej@1768: wx.DEFAULT_DIALOG_STYLE | wx.OK | wx.CANCEL) Laurent@1004: if dialog.ShowModal() == wx.ID_OK: Laurent@1004: selected = dialog.GetSelection() Laurent@1004: else: Laurent@1004: selected = None Laurent@1004: dialog.Destroy() Laurent@1004: if selected is None: Laurent@1004: self.Location.SetFocus() Laurent@1004: return Laurent@1004: if selected == 0: Laurent@1004: location = "%I" + location Laurent@1004: elif selected == 1: Laurent@1004: location = "%Q" + location Laurent@1004: else: Laurent@1004: location = "%M" + location andrej@1730: Laurent@1004: self.Location.SetValue(location) Edouard@2574: self.VariableName = infos["var_name"] Laurent@855: self.VarType = infos["IEC_type"] Laurent@814: Edouard@2575: # when user selected something, end editing immediately Edouard@2575: # so that changes over multiple colums appear Edouard@2575: wx.CallAfter(self.Parent.Parent.CloseEditControl) Edouard@2575: Laurent@814: self.Location.SetFocus() Laurent@814: Laurent@814: def OnLocationChar(self, event): Laurent@814: keycode = event.GetKeyCode() Laurent@814: if keycode in [wx.WXK_RETURN, wx.WXK_TAB]: Laurent@814: self.Parent.Parent.ProcessEvent(event) Laurent@814: elif keycode == wx.WXK_ESCAPE: Laurent@814: self.Location.SetValue(self.Default) Laurent@814: self.Parent.Parent.CloseEditControl() Laurent@814: else: Laurent@814: event.Skip() Laurent@814: Laurent@814: def SetInsertionPoint(self, i): Laurent@814: self.Location.SetInsertionPoint(i) andrej@1730: Laurent@814: def SetFocus(self): Laurent@814: self.Location.SetFocus() Laurent@814: andrej@1736: edouard@3305: class LocationCellEditor(wx.grid.GridCellEditor): Laurent@814: ''' Laurent@814: Grid cell editor that uses LocationCellControl to display a browse button. Laurent@814: ''' Laurent@814: def __init__(self, table, controller): edouard@3305: wx.grid.GridCellEditor.__init__(self) andrej@1730: Laurent@814: self.Table = table Laurent@814: self.Controller = controller Laurent@814: Laurent@814: def Create(self, parent, id, evt_handler): Laurent@814: self.CellControl = LocationCellControl(parent) Laurent@814: self.SetControl(self.CellControl) Laurent@814: if evt_handler: Laurent@814: self.CellControl.PushEventHandler(evt_handler) Laurent@814: Laurent@814: def BeginEdit(self, row, col, grid): Laurent@814: self.CellControl.Enable() Laurent@855: self.CellControl.SetController(self.Controller) Laurent@814: self.CellControl.SetValue(self.Table.GetValueByName(row, 'Location')) Laurent@814: if isinstance(self.CellControl, LocationCellControl): Laurent@855: self.CellControl.SetVarType(self.Table.GetValueByName(row, 'Type')) Laurent@814: self.CellControl.SetFocus() Laurent@814: edouard@3546: def EndEdit(self, row, col, grid, old_loc): Laurent@814: loc = self.CellControl.GetValue() Laurent@814: changed = loc != old_loc Laurent@814: if changed: Edouard@2573: name = self.CellControl.GetName() Edouard@2574: if name is not None: Edouard@2574: message = self.Table.Parent.CheckVariableName(name, row) Edouard@2574: if message is not None: Edouard@2574: wx.CallAfter(self.Table.Parent.ShowErrorMessage, message) Edouard@2574: return None edouard@2579: old_name = self.Table.GetValueByName(row, 'Name') Edouard@2574: self.Table.SetValueByName(row, 'Name', name) Edouard@2574: self.Table.Parent.OnVariableNameChange(old_name, name) Laurent@814: self.Table.SetValueByName(row, 'Location', loc) Edouard@2574: var_type = self.CellControl.GetVarType() Edouard@2574: if var_type is not None: Edouard@2574: self.Table.SetValueByName(row, 'Type', var_type) edouard@3970: Laurent@814: self.CellControl.Disable() Laurent@814: return changed andrej@1730: edouard@3546: def ApplyEdit(self, row, col, grid): edouard@3546: pass andrej@1730: Laurent@814: def SetSize(self, rect): kinsamanka@3789: self.CellControl.SetSize(rect.x + 1, rect.y, kinsamanka@3789: rect.width, rect.height, kinsamanka@3789: wx.SIZE_ALLOW_MINUS_ONE) Laurent@814: Laurent@814: def Clone(self): Laurent@814: return LocationCellEditor(self.Table, self.Controller)