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: andrej@1881: from __future__ import absolute_import Laurent@814: import wx Laurent@814: import wx.grid Laurent@814: andrej@1736: Laurent@814: class CustomGrid(wx.grid.Grid): andrej@1735: Laurent@814: def __init__(self, *args, **kwargs): Laurent@814: wx.grid.Grid.__init__(self, *args, **kwargs) andrej@1735: Laurent@814: self.Editable = True andrej@1735: Laurent@814: self.AddButton = None Laurent@814: self.DeleteButton = None Laurent@814: self.UpButton = None Laurent@814: self.DownButton = None andrej@1735: andrej@1568: self.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, 'Sans')) andrej@1568: self.SetLabelFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, 'Sans')) Laurent@814: self.SetSelectionBackground(wx.WHITE) Laurent@814: self.SetSelectionForeground(wx.BLACK) Laurent@814: self.DisableDragRowSize() andrej@1735: Laurent@814: self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnSelectCell) Laurent@814: self.Bind(wx.grid.EVT_GRID_EDITOR_HIDDEN, self.OnEditorHidden) Laurent@814: self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) andrej@1735: Laurent@950: def SetFocus(self): Laurent@950: if self: Laurent@950: wx.grid.Grid.SetFocus(self) andrej@1735: Laurent@814: def SetDefaultValue(self, default_value): Laurent@814: self.DefaultValue = default_value andrej@1735: Laurent@814: def SetEditable(self, editable=True): Laurent@814: self.Editable = editable Laurent@814: self.RefreshButtons() andrej@1735: Laurent@814: def SetButtons(self, buttons): Laurent@814: for name in ["Add", "Delete", "Up", "Down"]: Laurent@814: button = buttons.get(name, None) Laurent@814: setattr(self, "%sButton" % name, button) Laurent@814: if button is not None: Laurent@814: button.Bind(wx.EVT_BUTTON, getattr(self, "On%sButton" % name)) andrej@1735: Laurent@814: def RefreshButtons(self): Laurent@814: if self: Laurent@814: rows = self.Table.GetNumberRows() Laurent@814: row = self.GetGridCursorRow() Laurent@814: if self.AddButton is not None: Laurent@814: self.AddButton.Enable(self.Editable) Laurent@814: if self.DeleteButton is not None: Laurent@814: self.DeleteButton.Enable(self.Editable and rows > 0) Laurent@814: if self.UpButton is not None: Laurent@814: self.UpButton.Enable(self.Editable and row > 0) Laurent@814: if self.DownButton is not None: Laurent@814: self.DownButton.Enable(self.Editable and 0 <= row < rows - 1) andrej@1735: Laurent@814: def CloseEditControl(self): Laurent@814: row, col = self.GetGridCursorRow(), self.GetGridCursorCol() Laurent@814: if row != -1 and col != -1: Laurent@814: self.SetGridCursor(row, col) Laurent@814: Laurent@814: def AddRow(self): Laurent@814: self.CloseEditControl() Laurent@814: new_row = self.GetGridCursorRow() + 1 Laurent@814: col = max(self.GetGridCursorCol(), 0) Laurent@814: if getattr(self, "_AddRow", None) is not None: Laurent@814: new_row = self._AddRow(new_row) Laurent@814: else: Laurent@814: self.Table.InsertRow(new_row, self.DefaultValue.copy()) Laurent@814: self.Table.ResetView(self) Laurent@961: if new_row is not None: Laurent@1196: self.SetSelectedCell(new_row, col) Laurent@814: Laurent@814: def DeleteRow(self): Laurent@814: self.CloseEditControl() Laurent@814: row = self.GetGridCursorRow() Laurent@814: if row >= 0: Laurent@814: col = self.GetGridCursorCol() Laurent@814: if getattr(self, "_DeleteRow", None) is not None: Laurent@814: self._DeleteRow(row) Laurent@814: else: Laurent@814: self.Table.RemoveRow(row) Laurent@814: self.Table.ResetView(self) Laurent@1196: if self.Table.GetNumberRows() > 0: Laurent@1196: self.SetSelectedCell(min(row, self.Table.GetNumberRows() - 1), col) Laurent@814: Laurent@814: def MoveRow(self, row, move): Laurent@814: self.CloseEditControl() Laurent@814: col = self.GetGridCursorCol() Laurent@814: if getattr(self, "_MoveRow", None) is not None: Laurent@814: new_row = self._MoveRow(row, move) Laurent@814: else: Laurent@814: new_row = self.Table.MoveRow(row, move) Laurent@814: if new_row != row: Laurent@814: self.Table.ResetView(self) Laurent@814: if new_row != row: Laurent@1197: self.SetSelectedCell(new_row, col) andrej@1735: Laurent@1196: def SetSelectedCell(self, row, col): Laurent@961: self.SetGridCursor(row, col) Laurent@961: self.MakeCellVisible(row, col) Laurent@961: self.RefreshButtons() andrej@1735: Laurent@814: def OnAddButton(self, event): Laurent@814: self.AddRow() Laurent@814: self.SetFocus() Laurent@814: event.Skip() andrej@1735: Laurent@814: def OnDeleteButton(self, event): Laurent@814: self.DeleteRow() Laurent@814: self.SetFocus() Laurent@814: event.Skip() andrej@1735: Laurent@814: def OnUpButton(self, event): Laurent@814: self.MoveRow(self.GetGridCursorRow(), -1) Laurent@814: self.SetFocus() Laurent@814: event.Skip() andrej@1735: Laurent@814: def OnDownButton(self, event): Laurent@814: self.MoveRow(self.GetGridCursorRow(), 1) Laurent@814: self.SetFocus() Laurent@814: event.Skip() Laurent@814: Laurent@814: def OnSelectCell(self, event): Laurent@814: wx.CallAfter(self.RefreshButtons) Laurent@814: event.Skip() Laurent@814: Laurent@814: def OnEditorHidden(self, event): Laurent@814: wx.CallAfter(self.SetFocus) Laurent@814: event.Skip() Laurent@814: Laurent@814: def OnKeyDown(self, event): Laurent@814: key_handled = False Laurent@814: keycode = event.GetKeyCode() Laurent@814: if keycode == wx.WXK_TAB: Laurent@814: row = self.GetGridCursorRow() Laurent@814: col = self.GetGridCursorCol() Laurent@814: if event.ShiftDown(): Laurent@814: if row < 0 or col == 0: Laurent@814: self.Navigate(wx.NavigationKeyEvent.IsBackward) Laurent@814: key_handled = True Laurent@814: elif row < 0 or col == self.Table.GetNumberCols() - 1: Laurent@814: self.Navigate(wx.NavigationKeyEvent.IsForward) Laurent@814: key_handled = True Laurent@814: elif keycode in (wx.WXK_ADD, wx.WXK_NUMPAD_ADD) and self.Editable: Laurent@814: self.AddRow() Laurent@814: key_handled = True Laurent@814: elif keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and self.Editable: Laurent@814: self.DeleteRow() Laurent@814: key_handled = True Laurent@814: elif keycode == wx.WXK_UP and event.ShiftDown() and self.Editable: Laurent@814: self.MoveRow(self.GetGridCursorRow(), -1) Laurent@814: key_handled = True Laurent@814: elif keycode == wx.WXK_DOWN and event.ShiftDown() and self.Editable: Laurent@814: self.MoveRow(self.GetGridCursorRow(), 1) Laurent@814: key_handled = True Laurent@814: if not key_handled: Laurent@814: event.Skip()