]>
Commit | Line | Data |
---|---|---|
d14a1e28 RD |
1 | #---------------------------------------------------------------------------- |
2 | # Name: GridColMover.py | |
3 | # Purpose: Grid Column Mover Extension | |
4 | # | |
5 | # Author: Gerrit van Dyk (email: gerritvd@decillion.net) | |
6 | # | |
7 | # Version 0.1 | |
8 | # Date: Nov 19, 2002 | |
9 | # RCS-ID: $Id$ | |
10 | # Licence: wxWindows license | |
11 | #---------------------------------------------------------------------------- | |
1fded56b | 12 | |
d14a1e28 RD |
13 | from wxPython.wx import * |
14 | from wxPython.grid import wxGrid | |
1fded56b | 15 | |
d14a1e28 RD |
16 | #---------------------------------------------------------------------------- |
17 | # event class and macors | |
18 | ||
19 | ||
20 | wxEVT_COMMAND_GRID_COL_MOVE = wxNewEventType() | |
21 | wxEVT_COMMAND_GRID_ROW_MOVE = wxNewEventType() | |
22 | ||
23 | def EVT_GRID_COL_MOVE(win, id, func): | |
24 | win.Connect(id, -1, wxEVT_COMMAND_GRID_COL_MOVE, func) | |
25 | ||
26 | def EVT_GRID_ROW_MOVE(win,id,func): | |
27 | win.Connect(id, -1, wxEVT_COMMAND_GRID_ROW_MOVE, func) | |
28 | ||
29 | ||
30 | class wxGridColMoveEvent(wxPyCommandEvent): | |
31 | def __init__(self, id, dCol, bCol): | |
32 | wxPyCommandEvent.__init__(self, id = id) | |
33 | self.SetEventType(wxEVT_COMMAND_GRID_COL_MOVE) | |
34 | self.moveColumn = dCol | |
35 | self.beforeColumn = bCol | |
36 | ||
37 | def GetMoveColumn(self): | |
38 | return self.moveColumn | |
39 | ||
40 | def GetBeforeColumn(self): | |
41 | return self.beforeColumn | |
42 | ||
43 | ||
44 | class wxGridRowMoveEvent(wxPyCommandEvent): | |
45 | def __init__(self, id, dRow, bRow): | |
46 | wxPyCommandEvent.__init__(self,id = id) | |
47 | self.SetEventType(wxEVT_COMMAND_GRID_ROW_MOVE) | |
48 | self.moveRow = dRow | |
49 | self.beforeRow = bRow | |
50 | ||
51 | def GetMoveRow(self): | |
52 | return self.moveRow | |
53 | ||
54 | def GetBeforeRow(self): | |
55 | return self.beforeRow | |
56 | ||
57 | ||
58 | #---------------------------------------------------------------------------- | |
59 | # graft new methods into the wxGrid class | |
60 | ||
61 | def _ColToRect(self,col): | |
62 | if self.GetNumberRows() > 0: | |
63 | rect = self.CellToRect(0,col) | |
64 | else: | |
65 | rect = wxRect() | |
66 | rect.height = self.GetColLabelSize() | |
67 | rect.width = self.GetColSize(col) | |
68 | for cCol in range(0,col): | |
69 | rect.x += self.GetColSize(cCol) | |
70 | rect.y = self.GetGridColLabelWindow().GetPosition()[1] | |
71 | return rect | |
72 | ||
73 | wxGrid.ColToRect = _ColToRect | |
74 | ||
75 | ||
76 | def _RowToRect(self,row): | |
77 | if self.GetNumberCols() > 0: | |
78 | rect = self.CellToRect(row,0) | |
79 | else: | |
80 | rect = wxRect() | |
81 | rect.width = self.GetRowLabelSize() | |
82 | rect.height = self.GetRowSize(row) | |
83 | for cRow in range(0,row): | |
84 | rect.y += self.GetRowSize(cRow) | |
85 | rect.x = self.GetGridRowLabelWindow().GetPosition()[0] | |
86 | return rect | |
87 | ||
88 | wxGrid.RowToRect = _RowToRect | |
89 | ||
90 | ||
91 | #---------------------------------------------------------------------------- | |
92 | ||
93 | class ColDragWindow(wxWindow): | |
94 | def __init__(self,parent,image,dragCol): | |
95 | wxWindow.__init__(self,parent,wxSIMPLE_BORDER) | |
96 | self.image = image | |
97 | self.SetSize((self.image.GetWidth(),self.image.GetHeight())) | |
98 | self.ux = parent.GetScrollPixelsPerUnit()[0] | |
99 | self.moveColumn = dragCol | |
100 | ||
101 | EVT_PAINT(self,self.OnPaint) | |
102 | ||
103 | def DisplayAt(self,pos,y): | |
104 | x = self.GetPositionTuple()[0] | |
105 | if x == pos: | |
106 | self.Refresh() # Need to display insertion point | |
107 | else: | |
108 | self.MoveXY(pos,y) | |
109 | ||
110 | def GetMoveColumn(self): | |
111 | return self.moveColumn | |
112 | ||
113 | def _GetInsertionInfo(self): | |
114 | parent = self.GetParent() | |
115 | sx = parent.GetViewStart()[0] * self.ux | |
116 | sx -= parent._rlSize | |
117 | x = self.GetPositionTuple()[0] | |
118 | w = self.GetSizeTuple()[0] | |
119 | sCol = parent.XToCol(x + sx) | |
120 | eCol = parent.XToCol(x + w + sx) | |
121 | iPos = xPos = xCol = 99999 | |
122 | centerPos = x + sx + (w / 2) | |
123 | for col in range(sCol,eCol + 1): | |
124 | cx = parent.ColToRect(col)[0] | |
125 | if abs(cx - centerPos) < iPos: | |
126 | iPos = abs(cx - centerPos) | |
127 | xCol = col | |
128 | xPos = cx | |
129 | if xCol < 0 or xCol > parent.GetNumberCols(): | |
130 | xCol = parent.GetNumberCols() | |
131 | return (xPos - sx - x,xCol) | |
132 | ||
133 | def GetInsertionColumn(self): | |
134 | return self._GetInsertionInfo()[1] | |
135 | ||
136 | def GetInsertionPos(self): | |
137 | return self._GetInsertionInfo()[0] | |
138 | ||
139 | def OnPaint(self,evt): | |
140 | dc = wxPaintDC(self) | |
141 | w,h = self.GetSize() | |
142 | dc.DrawBitmap(self.image,0,0) | |
143 | dc.SetPen(wxPen(wxBLACK,1,wxSOLID)) | |
144 | dc.SetBrush(wxTRANSPARENT_BRUSH) | |
145 | dc.DrawRectangle(0,0,w,h) | |
146 | iPos = self.GetInsertionPos() | |
147 | dc.DrawLine(iPos,h - 10,iPos,h) | |
148 | ||
149 | ||
150 | ||
151 | ||
152 | class RowDragWindow(wxWindow): | |
153 | def __init__(self,parent,image,dragRow): | |
154 | wxWindow.__init__(self,parent,wxSIMPLE_BORDER) | |
155 | self.image = image | |
156 | self.SetSize((self.image.GetWidth(),self.image.GetHeight())) | |
157 | self.uy = parent.GetScrollPixelsPerUnit()[1] | |
158 | self.moveRow = dragRow | |
159 | ||
160 | EVT_PAINT(self,self.OnPaint) | |
161 | ||
162 | def DisplayAt(self,x,pos): | |
163 | y = self.GetPositionTuple()[1] | |
164 | if y == pos: | |
165 | self.Refresh() # Need to display insertion point | |
166 | else: | |
167 | self.MoveXY(x,pos) | |
168 | ||
169 | def GetMoveRow(self): | |
170 | return self.moveRow | |
171 | ||
172 | def _GetInsertionInfo(self): | |
173 | parent = self.GetParent() | |
174 | sy = parent.GetViewStart()[1] * self.uy | |
175 | sy -= parent._clSize | |
176 | y = self.GetPositionTuple()[1] | |
177 | h = self.GetSizeTuple()[1] | |
178 | sRow = parent.YToRow(y + sy) | |
179 | eRow = parent.YToRow(y + h + sy) | |
180 | iPos = yPos = yRow = 99999 | |
181 | centerPos = y + sy + (h / 2) | |
182 | for row in range(sRow,eRow + 1): | |
183 | cy = parent.RowToRect(row)[1] | |
184 | if abs(cy - centerPos) < iPos: | |
185 | iPos = abs(cy - centerPos) | |
186 | yRow = row | |
187 | yPos = cy | |
188 | if yRow < 0 or yRow > parent.GetNumberRows(): | |
189 | yRow = parent.GetNumberRows() | |
190 | return (yPos - sy - y,yRow) | |
191 | ||
192 | def GetInsertionRow(self): | |
193 | return self._GetInsertionInfo()[1] | |
194 | ||
195 | def GetInsertionPos(self): | |
196 | return self._GetInsertionInfo()[0] | |
197 | ||
198 | def OnPaint(self,evt): | |
199 | dc = wxPaintDC(self) | |
200 | w,h = self.GetSize() | |
201 | dc.DrawBitmap(self.image,0,0) | |
202 | dc.SetPen(wxPen(wxBLACK,1,wxSOLID)) | |
203 | dc.SetBrush(wxTRANSPARENT_BRUSH) | |
204 | dc.DrawRectangle(0,0,w,h) | |
205 | iPos = self.GetInsertionPos() | |
206 | dc.DrawLine(w - 10,iPos,w,iPos) | |
207 | ||
208 | #---------------------------------------------------------------------------- | |
209 | ||
210 | class wxGridColMover(wxEvtHandler): | |
211 | def __init__(self,grid): | |
212 | wxEvtHandler.__init__(self) | |
213 | ||
214 | self.grid = grid | |
215 | self.grid._rlSize = self.grid.GetRowLabelSize() | |
216 | self.lwin = grid.GetGridColLabelWindow() | |
217 | self.lwin.PushEventHandler(self) | |
218 | self.colWin = None | |
219 | self.ux = self.grid.GetScrollPixelsPerUnit()[0] | |
220 | self.startX = -10 | |
221 | self.cellX = 0 | |
222 | self.didMove = False | |
223 | self.isDragging = False | |
224 | ||
225 | EVT_MOTION(self,self.OnMouseMove) | |
226 | EVT_LEFT_DOWN(self,self.OnPress) | |
227 | EVT_LEFT_UP(self,self.OnRelease) | |
228 | ||
229 | def OnMouseMove(self,evt): | |
230 | if self.isDragging: | |
231 | if abs(self.startX - evt.m_x) >= 3: | |
232 | self.didMove = True | |
233 | sx,y = self.grid.GetViewStart() | |
234 | w,h = self.lwin.GetClientSizeTuple() | |
235 | x = sx * self.ux | |
236 | if (evt.m_x + x) < x: | |
237 | x = evt.m_x + x | |
238 | elif evt.m_x > w: | |
239 | x += evt.m_x - w | |
240 | if x < 1: x = 0 | |
241 | else: x /= self.ux | |
242 | if x != sx: | |
243 | if wxPlatform == '__WXMSW__': | |
244 | self.colWin.Show(False) | |
245 | self.grid.Scroll(x,y) | |
246 | x,y = self.lwin.ClientToScreenXY(evt.m_x,0) | |
247 | x,y = self.grid.ScreenToClientXY(x,y) | |
248 | if not self.colWin.IsShown(): | |
249 | self.colWin.Show(True) | |
250 | px = x - self.cellX | |
251 | if px < 0 + self.grid._rlSize: px = 0 + self.grid._rlSize | |
252 | if px > w - self.colWin.GetSizeTuple()[0] + self.grid._rlSize: | |
253 | px = w - self.colWin.GetSizeTuple()[0] + self.grid._rlSize | |
254 | self.colWin.DisplayAt(px,y) | |
255 | return | |
256 | evt.Skip() | |
257 | ||
258 | def OnPress(self,evt): | |
259 | self.startX = evt.m_x | |
260 | sx = self.grid.GetViewStart()[0] * self.ux | |
261 | sx -= self.grid._rlSize | |
262 | px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y) | |
263 | px,py = self.grid.ScreenToClientXY(px,py) | |
264 | if self.grid.XToEdgeOfCol(px + sx) != wxNOT_FOUND: | |
265 | evt.Skip() | |
266 | return | |
267 | ||
268 | self.isDragging = True | |
269 | self.didMove = False | |
270 | col = self.grid.XToCol(px + sx) | |
271 | rect = self.grid.ColToRect(col) | |
272 | self.cellX = px + sx - rect.x | |
273 | size = self.lwin.GetSizeTuple() | |
274 | rect.y = 0 | |
275 | rect.x -= sx + self.grid._rlSize | |
276 | rect.height = size[1] | |
277 | colImg = self._CaptureImage(rect) | |
278 | self.colWin = ColDragWindow(self.grid,colImg,col) | |
279 | self.colWin.Show(False) | |
280 | self.lwin.CaptureMouse() | |
281 | ||
282 | def OnRelease(self,evt): | |
283 | if self.isDragging: | |
284 | self.lwin.ReleaseMouse() | |
285 | self.colWin.Show(False) | |
286 | self.isDragging = False | |
287 | if not self.didMove: | |
288 | px = self.lwin.ClientToScreenXY(self.startX,0)[0] | |
289 | px = self.grid.ScreenToClientXY(px,0)[0] | |
290 | sx = self.grid.GetViewStart()[0] * self.ux | |
291 | sx -= self.grid._rlSize | |
292 | col = self.grid.XToCol(px+sx) | |
293 | if col != wxNOT_FOUND: | |
294 | self.grid.SelectCol(col,evt.m_controlDown) | |
295 | return | |
296 | else: | |
297 | bCol = self.colWin.GetInsertionColumn() | |
298 | dCol = self.colWin.GetMoveColumn() | |
299 | wxPostEvent(self,wxGridColMoveEvent(self.grid.GetId(), | |
300 | dCol,bCol)) | |
301 | self.colWin.Destroy() | |
302 | evt.Skip() | |
303 | ||
304 | def _CaptureImage(self,rect): | |
305 | bmp = wxEmptyBitmap(rect.width,rect.height) | |
306 | memdc = wxMemoryDC() | |
307 | memdc.SelectObject(bmp) | |
308 | dc = wxWindowDC(self.lwin) | |
309 | memdc.Blit(0,0,rect.width,rect.height,dc,rect.x,rect.y) | |
310 | memdc.SelectObject(wxNullBitmap) | |
311 | return bmp | |
312 | ||
313 | ||
314 | ||
315 | class wxGridRowMover(wxEvtHandler): | |
316 | def __init__(self,grid): | |
317 | wxEvtHandler.__init__(self) | |
318 | ||
319 | self.grid = grid | |
320 | self.grid._clSize = self.grid.GetColLabelSize() | |
321 | self.lwin = grid.GetGridRowLabelWindow() | |
322 | self.lwin.PushEventHandler(self) | |
323 | self.rowWin = None | |
324 | self.uy = self.grid.GetScrollPixelsPerUnit()[1] | |
325 | self.startY = -10 | |
326 | self.cellY = 0 | |
327 | self.didMove = False | |
328 | self.isDragging = False | |
329 | ||
330 | EVT_MOTION(self,self.OnMouseMove) | |
331 | EVT_LEFT_DOWN(self,self.OnPress) | |
332 | EVT_LEFT_UP(self,self.OnRelease) | |
333 | ||
334 | def OnMouseMove(self,evt): | |
335 | if self.isDragging: | |
336 | if abs(self.startY - evt.m_y) >= 3: | |
337 | self.didMove = True | |
338 | x,sy = self.grid.GetViewStart() | |
339 | w,h = self.lwin.GetClientSizeTuple() | |
340 | y = sy * self.uy | |
341 | if (evt.m_y + y) < y: | |
342 | y = evt.m_y + y | |
343 | elif evt.m_y > h: | |
344 | y += evt.m_y - h | |
345 | if y < 1: y = 0 | |
346 | else: y /= self.uy | |
347 | if y != sy: | |
348 | if wxPlatform == '__WXMSW__': | |
349 | self.rowWin.Show(False) | |
350 | self.grid.Scroll(x,y) | |
351 | x,y = self.lwin.ClientToScreenXY(0,evt.m_y) | |
352 | x,y = self.grid.ScreenToClientXY(x,y) | |
353 | if not self.rowWin.IsShown(): | |
354 | self.rowWin.Show(True) | |
355 | py = y - self.cellY | |
356 | if py < 0 + self.grid._clSize: py = 0 + self.grid._clSize | |
357 | if py > h - self.rowWin.GetSizeTuple()[1] + self.grid._clSize: | |
358 | py = h - self.rowWin.GetSizeTuple()[1] + self.grid._clSize | |
359 | self.rowWin.DisplayAt(x,py) | |
360 | return | |
361 | evt.Skip() | |
362 | ||
363 | def OnPress(self,evt): | |
364 | self.startY = evt.m_y | |
365 | sy = self.grid.GetViewStart()[1] * self.uy | |
366 | sy -= self.grid._clSize | |
367 | px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y) | |
368 | px,py = self.grid.ScreenToClientXY(px,py) | |
369 | if self.grid.YToEdgeOfRow(py + sy) != wxNOT_FOUND: | |
370 | evt.Skip() | |
371 | return | |
372 | ||
373 | self.isDragging = True | |
374 | self.didMove = False | |
375 | row = self.grid.YToRow(py + sy) | |
376 | rect = self.grid.RowToRect(row) | |
377 | self.cellY = py + sy - rect.y | |
378 | size = self.lwin.GetSizeTuple() | |
379 | rect.x = 0 | |
380 | rect.y -= sy + self.grid._clSize | |
381 | rect.width = size[0] | |
382 | rowImg = self._CaptureImage(rect) | |
383 | self.rowWin = RowDragWindow(self.grid,rowImg,row) | |
384 | self.rowWin.Show(False) | |
385 | self.lwin.CaptureMouse() | |
386 | ||
387 | def OnRelease(self,evt): | |
388 | if self.isDragging: | |
389 | self.lwin.ReleaseMouse() | |
390 | self.rowWin.Show(False) | |
391 | self.isDragging = False | |
392 | if not self.didMove: | |
393 | py = self.lwin.ClientToScreenXY(0,self.startY)[1] | |
394 | py = self.grid.ScreenToClientXY(0,py)[1] | |
395 | sy = self.grid.GetViewStart()[1] * self.uy | |
396 | sy -= self.grid._clSize | |
397 | row = self.grid.YToRow(py + sy) | |
398 | if row != wxNOT_FOUND: | |
399 | self.grid.SelectRow(row,evt.m_controlDown) | |
400 | return | |
401 | else: | |
402 | bRow = self.rowWin.GetInsertionRow() | |
403 | dRow = self.rowWin.GetMoveRow() | |
404 | wxPostEvent(self,wxGridRowMoveEvent(self.grid.GetId(), | |
405 | dRow,bRow)) | |
406 | self.rowWin.Destroy() | |
407 | evt.Skip() | |
408 | ||
409 | def _CaptureImage(self,rect): | |
410 | bmp = wxEmptyBitmap(rect.width,rect.height) | |
411 | memdc = wxMemoryDC() | |
412 | memdc.SelectObject(bmp) | |
413 | dc = wxWindowDC(self.lwin) | |
414 | memdc.Blit(0,0,rect.width,rect.height,dc,rect.x,rect.y) | |
415 | memdc.SelectObject(wxNullBitmap) | |
416 | return bmp | |
417 | ||
418 | ||
419 | #---------------------------------------------------------------------------- |