# Grid.py: wxGrid objects # $Id: grid.py,v 1.33 2007/03/27 07:01:58 agriggio Exp $ # # Copyright (c) 2002-2007 Alberto Griggio # License: MIT (see license.txt) # THIS PROGRAM COMES WITH NO WARRANTY import wx from wx.grid import * import common, misc from edit_windows import ManagedBase from tree import Tree from widget_properties import * class GridColsProperty(GridProperty): def write(self, outfile, tabs): from xml.sax.saxutils import escape, quoteattr write = outfile.write write(' ' * tabs + '\n') tab_s = ' ' * (tabs+1) import widget_properties value = self.get_value() # this is a list for i in range(len(value)): val = value[i] # this is another list _label = escape(widget_properties._encode(val[0])) _size = escape(widget_properties._encode(val[1])) write('%s%s\n' % (tab_s, quoteattr(_size), _label )) write(' ' * tabs + '\n') def _get_label(self, col): s = [] while True: s.append(chr(ord('A') + col%26)) col = col/26 - 1 if col < 0: break s.reverse() return "".join(s) def add_row(self, event): GridProperty.add_row(self, event) label = self._get_label(self.rows-1) self.grid.SetCellValue(self.rows-1, 0, label) self.grid.SetCellValue(self.rows-1, 1, '-1') def insert_row(self, event): GridProperty.insert_row(self, event) label = self._get_label(self.cur_row) self.grid.SetCellValue(self.cur_row, 0, label) self.grid.SetCellValue(self.cur_row, 1, '-1') # end of class GridColumnsProperty class ColsHandler: def __init__(self, parent): self.parent = parent self.columns = [] self.curr_col = [] self.curr_size = '-1' def start_elem(self, name, attrs): if name == 'column': self.curr_size = attrs.get('size', '-1') def end_elem(self, name): if name == 'columns': self.parent.set_columns(self.columns) self.parent.properties['columns'].set_value(self.columns) return True elif name == 'column': self.columns.append(["".join(self.curr_col), self.curr_size]) self.curr_col = [] return False def char_data(self, data): self.curr_col.append(data) # end of class ColsHandler class EditGrid(ManagedBase): events = [ 'EVT_GRID_CMD_CELL_LEFT_CLICK', 'EVT_GRID_CMD_CELL_RIGHT_CLICK', 'EVT_GRID_CMD_CELL_LEFT_DCLICK', 'EVT_GRID_CMD_CELL_RIGHT_DCLICK', 'EVT_GRID_CMD_LABEL_LEFT_CLICK', 'EVT_GRID_CMD_LABEL_RIGHT_CLICK', 'EVT_GRID_CMD_LABEL_LEFT_DCLICK', 'EVT_GRID_CMD_LABEL_RIGHT_DCLICK', 'EVT_GRID_CMD_CELL_CHANGE', 'EVT_GRID_CMD_SELECT_CELL', 'EVT_GRID_CMD_EDITOR_HIDDEN', 'EVT_GRID_CMD_EDITOR_SHOWN', 'EVT_GRID_CMD_COL_SIZE', 'EVT_GRID_CMD_ROW_SIZE', 'EVT_GRID_CMD_RANGE_SELECT', 'EVT_GRID_CMD_EDITOR_CREATED', ] def __init__(self, name, parent, id, sizer, pos, property_window, show=True): """\ Class to handle wxGrid objects """ # values of properties for the grid: self.row_label_size = 30 self.col_label_size = 30 self.enable_editing = True self.enable_grid_lines = True self.rows_number = 10 self.enable_col_resize = True self.enable_row_resize = True self.enable_grid_resize = True self.lines_color = '#000000' self.label_bg_color = '#C0C0C0' self.selection_mode = 0 # == wxGrid.wxGridSelectCells self.create_grid = True self.columns = [ ['A','-1'] , ['B','-1'] , ['C','-1'] ] ManagedBase.__init__(self, name, 'wxGrid', parent, id, sizer, pos, property_window, show=show) props = self.properties af = self.access_functions af['create_grid'] = (self.get_create_grid, self.set_create_grid) props['create_grid'] = CheckBoxProperty(self, 'create_grid', None, write_always=True) af['row_label_size'] = (self.get_row_label_size, self.set_row_label_size) props['row_label_size'] = SpinProperty(self, 'row_label_size', None, can_disable=True) af['col_label_size'] = (self.get_col_label_size, self.set_col_label_size) props['col_label_size'] = SpinProperty(self, 'col_label_size', None, can_disable=True) af['enable_editing'] = (self.get_enable_editing, self.set_enable_editing) props['enable_editing'] = CheckBoxProperty(self, 'enable_editing', None, write_always=True) af['enable_grid_lines'] = (self.get_enable_grid_lines, self.set_enable_grid_lines) props['enable_grid_lines']= CheckBoxProperty(self, 'enable_grid_lines', None, write_always=True) af['rows_number'] = (self.get_rows_number, self.set_rows_number) props['rows_number'] = SpinProperty(self, 'rows_number', None) af['enable_col_resize'] = (self.get_enable_col_resize, self.set_enable_col_resize) props['enable_col_resize']= CheckBoxProperty(self, 'enable_col_resize', None, write_always=True) af['enable_row_resize'] = (self.get_enable_row_resize, self.set_enable_row_resize) props['enable_row_resize'] = CheckBoxProperty(self, 'enable_row_resize', None, write_always=True) af['enable_grid_resize'] = (self.get_enable_grid_resize, self.set_enable_grid_resize) props['enable_grid_resize'] = CheckBoxProperty(self, 'enable_grid_resize', None, write_always=True) af['lines_color'] = (self.get_lines_color, self.set_lines_color) props['lines_color']= ColorDialogProperty(self, 'lines_color', None) af['label_bg_color'] = (self.get_label_bg_color, self.set_label_bg_color) props['label_bg_color']= ColorDialogProperty(self, 'label_bg_color', None) af['selection_mode'] = (self.get_selection_mode, self.set_selection_mode) props['selection_mode'] = RadioProperty(self, 'selection_mode', None, ['wxGrid.wxGridSelectCells', 'wxGrid.wxGridSelectRows', 'wxGrid.wxGridSelectColumns']) af['columns'] = (self.get_columns, self.set_columns) props['columns'] = GridColsProperty(self, 'columns', None, [ ('Label', GridProperty.STRING), ('Size', GridProperty.INT) ]) def create_properties(self): ManagedBase.create_properties(self) panel = wx.ScrolledWindow(self.notebook, -1, style=wx.TAB_TRAVERSAL) self.properties['create_grid'].display(panel) self.properties['columns'].display(panel) self.properties['rows_number'].display(panel) self.properties['row_label_size'].display(panel) self.properties['col_label_size'].display(panel) self.properties['enable_editing'].display(panel) self.properties['enable_grid_lines'].display(panel) self.properties['enable_col_resize'].display(panel) self.properties['enable_row_resize'].display(panel) self.properties['enable_grid_resize'].display(panel) self.properties['lines_color'].display(panel) self.properties['label_bg_color'].display(panel) self.properties['selection_mode'].display(panel) szr = wx.BoxSizer(wx.VERTICAL) szr.Add(self.properties['create_grid'].panel, 0, wx.EXPAND) szr.Add(wx.StaticLine(panel, -1), 0, wx.ALL|wx.EXPAND, 5) szr.Add(wx.StaticText(panel, -1, _("The following properties are " "meaningful\nonly if 'Create grid' is selected")), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) szr.Add(wx.StaticLine(panel, -1), 0, wx.ALL|wx.EXPAND, 5) szr.Add(self.properties['columns'].panel, 0, wx.ALL|wx.EXPAND, 2) szr.SetItemMinSize(self.properties['columns'].panel, 1, 150) szr.Add(self.properties['rows_number'].panel, 0, wx.EXPAND) szr.Add(self.properties['row_label_size'].panel, 0, wx.EXPAND) szr.Add(self.properties['col_label_size'].panel, 0, wx.EXPAND) szr.Add(self.properties['lines_color'].panel, 0, wx.EXPAND) szr.Add(self.properties['label_bg_color'].panel, 0, wx.EXPAND) szr.Add(self.properties['enable_editing'].panel, 0, wx.EXPAND) szr.Add(self.properties['enable_grid_lines'].panel, 0, wx.EXPAND) szr.Add(self.properties['enable_col_resize'].panel, 0, wx.EXPAND) szr.Add(self.properties['enable_row_resize'].panel, 0, wx.EXPAND) szr.Add(self.properties['enable_grid_resize'].panel, 0, wx.EXPAND) szr.Add(self.properties['selection_mode'].panel, 0, wx.ALL|wx.EXPAND, 5) panel.SetAutoLayout(1) panel.SetSizer(szr) szr.Fit(panel) w, h = panel.GetClientSize() self.notebook.AddPage(panel, _('Widget')) import math panel.SetScrollbars(1, 5, 1, int(math.ceil(h/5.0))) self.properties['columns'].set_col_sizes([-1, 0]) def create_widget(self): self.widget = Grid(self.parent.widget, self.id,(200,200)) self.widget.CreateGrid(self.rows_number, len(self.columns)) if not self.properties['label_bg_color'].is_active(): self.label_bg_color = misc.color_to_string( self.widget.GetLabelBackgroundColour()) self.properties['label_bg_color'].set_value(self.label_bg_color) if not self.properties['lines_color'].is_active(): self.lines_color = misc.color_to_string( self.widget.GetGridLineColour()) self.properties['lines_color'].set_value(self.lines_color) self.widget.SetRowLabelSize(self.row_label_size) self.widget.SetColLabelSize(self.col_label_size) self.widget.EnableEditing(self.enable_editing) self.widget.EnableGridLines(self.enable_grid_lines) self.widget.EnableDragColSize(self.enable_col_resize) self.widget.EnableDragRowSize(self.enable_row_resize) self.widget.EnableDragGridSize(self.enable_grid_resize) self.widget.SetGridLineColour(misc.string_to_color(self.lines_color)) self.widget.SetLabelBackgroundColour(misc.string_to_color( self.label_bg_color)) i = 0 for l, s in self.columns: try: s1 = int(s) except: s1 = 0 self.widget.SetColLabelValue(i, l) if s1 > 0: self.widget.SetColSize(i, s1) i += 1 self.set_selection_mode(self.selection_mode) # following two events are to permit select grid from designer frame EVT_GRID_CELL_LEFT_CLICK(self.widget, self.on_set_focus) EVT_GRID_LABEL_LEFT_CLICK(self.widget, self.on_set_focus) # these are to show the popup menu on right click EVT_GRID_CELL_RIGHT_CLICK(self.widget, self.popup_menu) EVT_GRID_LABEL_RIGHT_CLICK(self.widget, self.popup_menu) def get_create_grid(self): return self.create_grid def set_create_grid(self, value): self.create_grid = bool(int(value)) def get_row_label_size(self): return self.row_label_size def set_row_label_size(self, value): self.row_label_size = int(value) if value and self.widget: self.widget.SetRowLabelSize(self.row_label_size) def get_col_label_size(self): return self.col_label_size def set_col_label_size(self, value): self.col_label_size = int(value) if value and self.widget: self.widget.SetColLabelSize(self.col_label_size) def get_enable_editing(self): return self.enable_editing def set_enable_editing(self, value): self.enable_editing = bool(int(value)) # Do nothing. ## if value and self.widget: ## self.widget.EnableEditing(self.enable_editing) # NO! def get_enable_grid_lines(self): return self.enable_grid_lines def set_enable_grid_lines(self, value): self.enable_grid_lines = bool(int(value)) if self.widget: self.widget.EnableGridLines(self.enable_grid_lines) #self.widget.Update() def get_rows_number(self): return self.rows_number def set_rows_number(self, value): self.rows_number = int(value) # the value the user entered if value > 0 and self.widget: # the value that the grid has actual_rows_number = self.widget.GetNumberRows() if self.rows_number > actual_rows_number: # we have to add rows self.widget.AppendRows(self.rows_number - actual_rows_number) if actual_rows_number > self.rows_number: # we have to delete rows self.widget.DeleteRows(self.rows_number, actual_rows_number - self.rows_number) #self.widget.Update() def get_enable_col_resize(self): return self.enable_col_resize def set_enable_col_resize(self, value): self.enable_col_resize = bool(int(value)) if self.widget: self.widget.EnableDragColSize(self.enable_col_resize) def get_enable_row_resize(self): return self.enable_row_resize def set_enable_row_resize(self, value): self.enable_row_resize = bool(int(value)) if self.widget: self.widget.EnableDragRowSize(self.enable_row_resize) def get_enable_grid_resize(self): return self.enable_grid_resize def set_enable_grid_resize(self, value): self.enable_grid_resize = bool(int(value)) if self.widget: self.widget.EnableDragGridSize(self.enable_grid_resize) def get_lines_color(self): return self.lines_color def set_lines_color(self, value): self.lines_color = str(value) if self.widget: self.widget.SetGridLineColour(misc.string_to_color( self.lines_color)) def get_label_bg_color(self): return self.label_bg_color def set_label_bg_color(self, value): self.label_bg_color = str(value) if self.widget: self.widget.SetLabelBackgroundColour(misc.string_to_color( self.label_bg_color)) def get_selection_mode(self): return self.selection_mode ## if self.selection_mode == wxGrid.wxGridSelectCells: return 0 ## if self.selection_mode == wxGrid.wxGridSelectRows: return 1 ## if self.selection_mode == wxGrid.wxGridSelectColumns: return 2 def set_selection_mode(self, value): _sel_modes = { 'wxGrid.wxGridSelectCells': 0, 'wxGrid.wxGridSelectRows': 1, 'wxGrid.wxGridSelectColumns': 2, } if value in _sel_modes: self.selection_mode = _sel_modes[value] else: try: value = int(value) except: pass else: self.selection_mode = value ## if value == 0: ## self.selection_mode = wxGrid.wxGridSelectCells ## elif value == 1: ## self.selection_mode = wxGrid.wxGridSelectRows ## else: ## self.selection_mode = wxGrid.wxGridSelectColumns # no operation on the grid. def get_columns(self): return self.columns def set_columns(self, cols): # first of all, adjust col number _oldcolnum = len(self.columns) _colnum = len(cols) self.columns = cols if not self.widget: return if _colnum > _oldcolnum: self.widget.AppendCols(_colnum - _oldcolnum) if _colnum < _oldcolnum: self.widget.DeleteCols(0, _oldcolnum - _colnum) i = 0 for l, s in cols: try: s1 = int(s) except: s1 = 0 self.widget.SetColLabelValue(i, misc.wxstr(l)) if s1 > 0: self.widget.SetColSize(i, s1) i += 1 self.widget.ForceRefresh() def get_property_handler(self, name): if name == 'columns': return ColsHandler(self) return ManagedBase.get_property_handler(self, name) # end of class EditGrid def builder(parent, sizer, pos, number=[1]): """\ factory function for EditGrid objects. """ label = 'grid_%d' % number[0] while common.app_tree.has_name(label): number[0] += 1 label = 'grid_%d' % number[0] grid = EditGrid(label, parent, wx.NewId(), sizer, pos, common.property_panel) # A grid should be wx.EXPANDed and 'option' should be 1, # or you can't see it. grid.set_option(1) grid.set_flag("wxEXPAND") node = Tree.Node(grid) grid.node = node grid.show_widget(True) common.app_tree.insert(node, sizer.node, pos-1) def xml_builder(attrs, parent, sizer, sizeritem, pos=None): """\ factory to build EditGrid objects from an xml file """ from xml_parse import XmlParsingError try: label = attrs['name'] except KeyError: raise XmlParsingError, "'name' attribute missing" if sizer is None or sizeritem is None: raise XmlParsingError, "sizer or sizeritem object cannot be None" grid = EditGrid(label, parent, wx.NewId(), sizer, pos, common.property_panel, show=False) sizer.set_item(grid.pos, option=sizeritem.option, flag=sizeritem.flag, border=sizeritem.border) #, size=(100,100)) #HELP# node = Tree.Node(grid) grid.node = node if pos is None: common.app_tree.add(node, sizer.node) else: common.app_tree.insert(node, sizer.node, pos-1) return grid def initialize(): """\ initialization function for the module: returns a wx.BitmapButton to be added to the main palette. """ common.widgets['EditGrid'] = builder common.widgets_from_xml['EditGrid'] = xml_builder return common.make_object_button('EditGrid', 'icons/grid.xpm')