| 1 | from wxPython.wx import * |
| 2 | from wxPython.grid import * |
| 3 | |
| 4 | import string, random |
| 5 | |
| 6 | #--------------------------------------------------------------------------- |
| 7 | |
| 8 | class MyCustomRenderer(wxPyGridCellRenderer): |
| 9 | def __init__(self): |
| 10 | wxPyGridCellRenderer.__init__(self) |
| 11 | |
| 12 | def Draw(self, grid, attr, dc, rect, row, col, isSelected): |
| 13 | dc.SetBackgroundMode(wxSOLID) |
| 14 | dc.SetBrush(wxBrush(wxBLACK, wxSOLID)) |
| 15 | dc.SetPen(wxTRANSPARENT_PEN) |
| 16 | dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) |
| 17 | |
| 18 | dc.SetBackgroundMode(wxTRANSPARENT) |
| 19 | dc.SetFont(attr.GetFont()) |
| 20 | |
| 21 | text = grid.GetCellValue(row, col) |
| 22 | colors = [wxRED, wxWHITE, wxCYAN] |
| 23 | x = rect.x + 1 |
| 24 | y = rect.y + 1 |
| 25 | for ch in text: |
| 26 | dc.SetTextForeground(random.choice(colors)) |
| 27 | dc.DrawText(ch, x, y) |
| 28 | w, h = dc.GetTextExtent(ch) |
| 29 | x = x + w |
| 30 | if x > rect.right - 5: |
| 31 | break |
| 32 | |
| 33 | |
| 34 | def GetBestSize(self, grid, attr, dc, row, col): |
| 35 | text = grid.GetCellValue(row, col) |
| 36 | dc.SetFont(attr.GetFont()) |
| 37 | w, h = dc.GetTextExtent(text) |
| 38 | return wxSize(w, h) |
| 39 | |
| 40 | |
| 41 | def Clone(self): |
| 42 | return MyCustomRenderer() |
| 43 | |
| 44 | |
| 45 | #--------------------------------------------------------------------------- |
| 46 | |
| 47 | rendererDemoData = [ |
| 48 | ('wxGridCellStringRenderer\n(the default)', 'this is a text value', wxGridCellStringRenderer, ()), |
| 49 | ('wxGridCellNumberRenderer', '12345', wxGridCellNumberRenderer, ()), |
| 50 | ('wxGridCellFloatRenderer', '1234.5678', wxGridCellFloatRenderer, (6,2)), |
| 51 | ('wxGridCellBoolRenderer', '1', wxGridCellBoolRenderer, ()), |
| 52 | ('MyCustomRenderer', 'This is my renderer', MyCustomRenderer, ()), |
| 53 | ] |
| 54 | |
| 55 | editorDemoData = [ |
| 56 | ('wxGridCellTextEditor\n(the default)', 'Here is some more text', wxGridCellTextEditor, ()), |
| 57 | ('wxGridCellNumberEditor\nwith min,max', '101', wxGridCellNumberEditor, (5, 10005)), |
| 58 | ('wxGridCellNumberEditor\nwithout bounds', '101', wxGridCellNumberEditor, ()), |
| 59 | ('wxGridCellFloatEditor', '1234.5678', wxGridCellFloatEditor, ()), |
| 60 | ('wxGridCellBoolEditor', '1', wxGridCellBoolEditor, ()), |
| 61 | ('wxGridCellChoiceEditor', 'one', wxGridCellChoiceEditor, (['one', 'two', 'three', 'four', |
| 62 | 'kick', 'Microsoft', 'out the', |
| 63 | 'door'], false)), |
| 64 | ] |
| 65 | |
| 66 | |
| 67 | comboDemoData = [ |
| 68 | ('wxGridCellNumberRenderer\nwxGridCellNumberEditor', '20792', wxGridCellNumberRenderer, wxGridCellNumberEditor), |
| 69 | ('wxGridCellBoolRenderer\nwxGridCellBoolEditor', '1', wxGridCellBoolRenderer, wxGridCellBoolEditor), |
| 70 | ] |
| 71 | |
| 72 | |
| 73 | class EditorsAndRenderersGrid(wxGrid): |
| 74 | def __init__(self, parent, log): |
| 75 | wxGrid.__init__(self, parent, -1) |
| 76 | self.log = log |
| 77 | |
| 78 | self.CreateGrid(25, 8) |
| 79 | renCol = 1 |
| 80 | edCol = 4 |
| 81 | |
| 82 | |
| 83 | self.SetCellValue(0, renCol, '''\ |
| 84 | Cell Renderers are used to draw |
| 85 | the contents of the cell when they |
| 86 | need to be refreshed. Different |
| 87 | types of Renderers can be plugged in |
| 88 | to different cells in the grid, it can |
| 89 | even be automatically determined based |
| 90 | on the type of data in the cell. |
| 91 | ''') |
| 92 | |
| 93 | self.SetCellValue(0, edCol, '''\ |
| 94 | Cell Editors are used when the |
| 95 | value of the cell is edited by |
| 96 | the user. An editor class is |
| 97 | wrapped around a an object |
| 98 | derived from wxControl and it |
| 99 | implements some methods required |
| 100 | to integrate with the grid. |
| 101 | ''') |
| 102 | |
| 103 | self.SetCellValue(16, renCol, '''\ |
| 104 | Here are some combinations of Editors and |
| 105 | Renderers used together. |
| 106 | ''') |
| 107 | |
| 108 | row = 2 |
| 109 | for label, value, renderClass, args in rendererDemoData: |
| 110 | renderer = apply(renderClass, args) |
| 111 | self.SetCellValue(row, renCol, label) |
| 112 | self.SetCellValue(row, renCol+1, value) |
| 113 | self.SetCellRenderer(row, renCol+1, renderer) |
| 114 | row = row + 2 |
| 115 | |
| 116 | |
| 117 | row = 2 |
| 118 | for label, value, editorClass, args in editorDemoData: |
| 119 | editor = apply(editorClass, args) |
| 120 | self.SetCellValue(row, edCol, label) |
| 121 | self.SetCellValue(row, edCol+1, value) |
| 122 | self.SetCellEditor(row, edCol+1, editor) |
| 123 | row = row + 2 |
| 124 | |
| 125 | |
| 126 | row = 18 |
| 127 | for label, value, renClass, edClass in comboDemoData: |
| 128 | self.SetCellValue(row, renCol, label) |
| 129 | self.SetCellValue(row, renCol+1, value) |
| 130 | editor = apply(edClass, ()) #args) |
| 131 | renderer = apply(renClass, ()) #args) |
| 132 | self.SetCellEditor(row, renCol+1, editor) |
| 133 | self.SetCellRenderer(row, renCol+1, renderer) |
| 134 | row = row + 2 |
| 135 | |
| 136 | |
| 137 | font = self.GetFont() |
| 138 | font.SetWeight(wxBOLD) |
| 139 | attr = wxGridCellAttr() |
| 140 | attr.SetFont(font) |
| 141 | attr.SetBackgroundColour(wxLIGHT_GREY) |
| 142 | attr.SetReadOnly(true) |
| 143 | attr.SetAlignment(wxRIGHT, -1) |
| 144 | self.SetColAttr(renCol, attr) |
| 145 | attr.IncRef() |
| 146 | self.SetColAttr(edCol, attr) |
| 147 | |
| 148 | # There is a bug in wxGTK for this method... |
| 149 | self.AutoSizeColumns(true) |
| 150 | self.AutoSizeRows(true) |
| 151 | |
| 152 | EVT_GRID_CELL_LEFT_DCLICK(self, self.OnLeftDClick) |
| 153 | |
| 154 | |
| 155 | # I do this because I don't like the default behaviour of not starting the |
| 156 | # cell editor on double clicks, but only a second click. |
| 157 | def OnLeftDClick(self, evt): |
| 158 | if self.CanEnableCellControl(): |
| 159 | self.EnableCellEditControl() |
| 160 | |
| 161 | |
| 162 | #--------------------------------------------------------------------------- |
| 163 | |
| 164 | class TestFrame(wxFrame): |
| 165 | def __init__(self, parent, log): |
| 166 | wxFrame.__init__(self, parent, -1, "Editors and Renderers Demo", size=(640,480)) |
| 167 | grid = EditorsAndRenderersGrid(self, log) |
| 168 | |
| 169 | |
| 170 | |
| 171 | #--------------------------------------------------------------------------- |
| 172 | |
| 173 | if __name__ == '__main__': |
| 174 | import sys |
| 175 | app = wxPySimpleApp() |
| 176 | frame = TestFrame(None, sys.stdout) |
| 177 | frame.Show(true) |
| 178 | app.MainLoop() |
| 179 | |
| 180 | |
| 181 | #--------------------------------------------------------------------------- |