laurent@577: #!/usr/bin/env python laurent@577: # -*- coding: utf-8 -*- laurent@577: laurent@577: #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor laurent@577: #based on the plcopen standard. laurent@577: # laurent@577: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD laurent@577: # laurent@577: #See COPYING file for copyrights details. laurent@577: # laurent@577: #This library is free software; you can redistribute it and/or laurent@577: #modify it under the terms of the GNU General Public laurent@577: #License as published by the Free Software Foundation; either laurent@577: #version 2.1 of the License, or (at your option) any later version. laurent@577: # laurent@577: #This library is distributed in the hope that it will be useful, laurent@577: #but WITHOUT ANY WARRANTY; without even the implied warranty of laurent@577: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU laurent@577: #General Public License for more details. laurent@577: # laurent@577: #You should have received a copy of the GNU General Public laurent@577: #License along with this library; if not, write to the Free Software laurent@577: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA laurent@577: laurent@577: import wx laurent@577: import wx.grid laurent@577: laurent@577: class CustomGrid(wx.grid.Grid): laurent@577: laurent@577: def __init__(self, *args, **kwargs): laurent@577: wx.grid.Grid.__init__(self, *args, **kwargs) laurent@577: laurent@600: self.Editable = True laurent@600: laurent@606: self.AddButton = None laurent@606: self.DeleteButton = None laurent@606: self.UpButton = None laurent@606: self.DownButton = None laurent@606: laurent@606: self.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, 'Sans')) laurent@606: self.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, False, 'Sans')) laurent@606: self.SetSelectionBackground(wx.WHITE) laurent@606: self.SetSelectionForeground(wx.BLACK) laurent@614: self.DisableDragRowSize() laurent@606: Laurent@714: self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnSelectCell) Laurent@714: self.Bind(wx.grid.EVT_GRID_EDITOR_HIDDEN, self.OnEditorHidden) laurent@577: self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) laurent@577: laurent@577: def SetDefaultValue(self, default_value): laurent@577: self.DefaultValue = default_value laurent@577: laurent@600: def SetEditable(self, editable=True): laurent@600: self.Editable = editable laurent@600: self.RefreshButtons() laurent@600: laurent@577: def SetButtons(self, buttons): laurent@577: for name in ["Add", "Delete", "Up", "Down"]: laurent@577: button = buttons.get(name, None) laurent@577: setattr(self, "%sButton" % name, button) laurent@577: if button is not None: laurent@577: button.Bind(wx.EVT_BUTTON, getattr(self, "On%sButton" % name)) laurent@577: laurent@577: def RefreshButtons(self): laurent@672: if self: laurent@672: rows = self.Table.GetNumberRows() laurent@672: row = self.GetGridCursorRow() laurent@672: if self.AddButton is not None: laurent@672: self.AddButton.Enable(self.Editable) laurent@672: if self.DeleteButton is not None: laurent@672: self.DeleteButton.Enable(self.Editable and rows > 0) laurent@672: if self.UpButton is not None: laurent@672: self.UpButton.Enable(self.Editable and row > 0) laurent@672: if self.DownButton is not None: laurent@672: self.DownButton.Enable(self.Editable and 0 <= row < rows - 1) laurent@577: laurent@577: def CloseEditControl(self): laurent@662: row, col = self.GetGridCursorRow(), self.GetGridCursorCol() laurent@662: if row != -1 and col != -1: laurent@662: self.SetGridCursor(row, col) laurent@577: laurent@577: def AddRow(self): laurent@577: self.CloseEditControl() laurent@577: new_row = self.GetGridCursorRow() + 1 laurent@577: col = max(self.GetGridCursorCol(), 0) laurent@577: if getattr(self, "_AddRow", None) is not None: laurent@577: new_row = self._AddRow(new_row) laurent@577: else: laurent@577: self.Table.InsertRow(new_row, self.DefaultValue.copy()) laurent@577: self.Table.ResetView(self) laurent@577: self.SetGridCursor(new_row, col) laurent@577: self.MakeCellVisible(new_row, col) laurent@577: self.RefreshButtons() laurent@577: laurent@577: def DeleteRow(self): laurent@577: self.CloseEditControl() laurent@577: row = self.GetGridCursorRow() laurent@577: if row >= 0: laurent@577: col = self.GetGridCursorCol() laurent@577: if getattr(self, "_DeleteRow", None) is not None: laurent@577: self._DeleteRow(row) laurent@577: else: laurent@577: self.Table.RemoveRow(row) laurent@577: self.Table.ResetView(self) laurent@577: new_row = min(row, self.Table.GetNumberRows() - 1) laurent@577: self.SetGridCursor(new_row, col) laurent@577: self.MakeCellVisible(new_row, col) laurent@577: self.RefreshButtons() laurent@577: laurent@577: def MoveRow(self, row, move): laurent@577: self.CloseEditControl() laurent@577: col = self.GetGridCursorCol() laurent@577: if getattr(self, "_MoveRow", None) is not None: laurent@577: new_row = self._MoveRow(row, move) laurent@577: else: laurent@577: new_row = self.Table.MoveRow(row, move) laurent@577: if new_row != row: laurent@577: self.Table.ResetView(self) laurent@577: if new_row != row: laurent@577: self.SetGridCursor(new_row, col) laurent@577: self.MakeCellVisible(new_row, col) laurent@577: self.RefreshButtons() laurent@577: laurent@577: def OnAddButton(self, event): laurent@577: self.AddRow() laurent@577: self.SetFocus() laurent@577: event.Skip() laurent@577: laurent@577: def OnDeleteButton(self, event): laurent@577: self.DeleteRow() laurent@577: self.SetFocus() laurent@577: event.Skip() laurent@577: laurent@577: def OnUpButton(self, event): laurent@577: self.MoveRow(self.GetGridCursorRow(), -1) laurent@577: self.SetFocus() laurent@577: event.Skip() laurent@577: laurent@577: def OnDownButton(self, event): laurent@577: self.MoveRow(self.GetGridCursorRow(), 1) laurent@577: self.SetFocus() laurent@577: event.Skip() laurent@577: laurent@577: def OnSelectCell(self, event): laurent@577: wx.CallAfter(self.RefreshButtons) laurent@577: event.Skip() laurent@577: laurent@655: def OnEditorHidden(self, event): laurent@655: wx.CallAfter(self.SetFocus) laurent@655: event.Skip() laurent@655: laurent@577: def OnKeyDown(self, event): laurent@577: key_handled = False laurent@577: keycode = event.GetKeyCode() laurent@577: if keycode == wx.WXK_TAB: laurent@577: row = self.GetGridCursorRow() laurent@577: col = self.GetGridCursorCol() laurent@577: if event.ShiftDown(): laurent@577: if row < 0 or col == 0: laurent@577: self.Navigate(wx.NavigationKeyEvent.IsBackward) laurent@577: key_handled = True laurent@577: elif row < 0 or col == self.Table.GetNumberCols() - 1: laurent@577: self.Navigate(wx.NavigationKeyEvent.IsForward) laurent@577: key_handled = True laurent@600: elif keycode in (wx.WXK_ADD, wx.WXK_NUMPAD_ADD) and self.Editable: laurent@577: self.AddRow() laurent@577: key_handled = True laurent@600: elif keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and self.Editable: laurent@577: self.DeleteRow() laurent@577: key_handled = True laurent@600: elif keycode == wx.WXK_UP and event.ShiftDown() and self.Editable: laurent@577: self.MoveRow(self.GetGridCursorRow(), -1) laurent@577: key_handled = True laurent@600: elif keycode == wx.WXK_DOWN and event.ShiftDown() and self.Editable: laurent@577: self.MoveRow(self.GetGridCursorRow(), 1) laurent@577: key_handled = True laurent@577: if not key_handled: laurent@577: event.Skip()