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