1 ''' drawingOnGridColumnLabel.py
2 2003-12-03
3
4 This example shows a wxGrid with some sample columns, where the column
5 headers draw sort indicators when clicked. The example does not actually
6 do the sorting of the data, as it is intended to show how to draw on the
7 grid's column headers.
8
9 by Paul McNett (p@ulmcnett.com) and whoever wrote the GridCustTable.py demo,
10 from which I pulled the CustomDataTable() class.
11
12 I didn't know what to do until Robin pointed out an undocumented method in
13 wxGrid: GetGridColLabelWindow(), which returns a reference to the wxWindow
14 that makes up the column header for the grid. From there, I could trap that
15 window's Paint event, and draw the column labels myself, including graphical
16 sort indicators.
17 '''
18
19 from wxPython.wx import *
20 from wxPython.grid import *
21
22 class CustomDataTable(wxPyGridTableBase):
23 """ From the wxPython demo
24 """
25
26 def __init__(self):
27 wxPyGridTableBase.__init__(self)
28
29 self.colLabels = ['ID', 'Description', 'Severity', 'Priority', 'Platform',
30 'Opened?', 'Fixed?', 'Tested?', 'TestFloat']
31
32 self.dataTypes = [wxGRID_VALUE_NUMBER,
33 wxGRID_VALUE_STRING,
34 wxGRID_VALUE_CHOICE + ':only in a million years!,wish list,minor,normal,major,critical',
35 wxGRID_VALUE_NUMBER + ':1,5',
36 wxGRID_VALUE_CHOICE + ':all,MSW,GTK,other',
37 wxGRID_VALUE_BOOL,
38 wxGRID_VALUE_BOOL,
39 wxGRID_VALUE_BOOL,
40 wxGRID_VALUE_FLOAT + ':6,2',
41 ]
42
43 self.data = [
44 [1010, "The foo doesn't bar", "major", 1, 'MSW', 1, 1, 1, 1.12],
45 [1011, "I've got a wicket in my wocket", "wish list", 2, 'other', 0, 0, 0, 1.50],
46 [1012, "Rectangle() returns a triangle", "critical", 5, 'all', 0, 0, 0, 1.56]
47
48 ]
49
50
51
52
53
54 def GetNumberRows(self):
55 return len(self.data) + 1
56
57 def GetNumberCols(self):
58 return len(self.data[0])
59
60 def IsEmptyCell(self, row, col):
61 try:
62 return not self.data[row][col]
63 except IndexError:
64 return true
65
66
67
68
69
70 def GetValue(self, row, col):
71 try:
72 return self.data[row][col]
73 except IndexError:
74 return ''
75
76 def SetValue(self, row, col, value):
77 try:
78 self.data[row][col] = value
79 except IndexError:
80
81 self.data.append([''] * self.GetNumberCols())
82 self.SetValue(row, col, value)
83
84
85 msg = wxGridTableMessage(self,
86 wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
87 1)
88
89 self.GetView().ProcessTableMessage(msg)
90
91 class MyGrid(wxGrid):
92 def __init__(self, parent):
93
94 wxGrid.__init__(self, parent, -1)
95 table = CustomDataTable()
96 self.SetTable(table, true)
97
98 self.SetRowLabelSize(0)
99 self.SetMargins(0,0)
100 self.AutoSizeColumns(False)
101
102
103 self.sortedColumn = -1
104 self.sortedColumnDescending = False
105
106
107 columnLabelWindow = self.GetGridColLabelWindow()
108 EVT_PAINT(columnLabelWindow, self.OnColumnHeaderPaint)
109
110
111 EVT_GRID_LABEL_LEFT_CLICK(self, self.OnGridLabelLeftClick)
112
113 def OnColumnHeaderPaint(self, evt):
114 w = self.GetGridColLabelWindow()
115 dc = wxPaintDC(w)
116 clientRect = w.GetClientRect()
117 font = dc.GetFont()
118
119
120
121
122 totColSize = -self.GetViewStart()[0]*self.GetScrollPixelsPerUnit()[0]
123 for col in range(self.GetNumberCols()):
124 dc.SetBrush(wxBrush("WHEAT", wxTRANSPARENT))
125 dc.SetTextForeground(wxBLACK)
126 colSize = self.GetColSize(col)
127 rect = (totColSize,0,colSize,32)
128 dc.DrawRectangle(rect[0] - (col<>0 and 1 or 0), rect[1],
129 rect[2] + (col<>0 and 1 or 0), rect[3])
130 totColSize += colSize
131
132 if col == self.sortedColumn:
133 font.SetWeight(wxBOLD)
134
135
136 left = rect[0] + 3
137 top = rect[1] + 3
138
139 dc.SetBrush(wxBrush("WHEAT", wxSOLID))
140 if self.sortedColumnDescending:
141 dc.DrawPolygon([(left,top), (left+6,top), (left+3,top+4)])
142 else:
143 dc.DrawPolygon([(left+3,top), (left+6, top+4), (left, top+4)])
144 else:
145 font.SetWeight(wxNORMAL)
146
147 dc.SetFont(font)
148 dc.DrawLabel("%s" % self.GetTable().colLabels[col],
149 rect, wxALIGN_CENTER | wxALIGN_TOP)
150
151
152 def OnGridLabelLeftClick(self, evt):
153 self.processSort(evt.GetCol())
154
155 def processSort(self, gridCol=None):
156 if gridCol == None:
157 gridCol = self.GetGridCursorCol()
158
159 descending = False
160 if gridCol == self.sortedColumn:
161 if self.sortedColumnDescending == False:
162 descending = True
163
164 self.sortedColumn = gridCol
165 self.sortedColumnDescending = descending
166 self.Refresh()
167
168 if __name__ == "__main__":
169
170 app = wxPySimpleApp()
171 frame = wxFrame(None, -1, "Click on any column header")
172 frame.SetSize((400,200))
173 object = MyGrid(frame)
174 object.SetFocus()
175 frame.Show(1)
176 app.MainLoop()