]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/gridmovers.py
part of the revert of 1.8 got botched
[wxWidgets.git] / wxPython / wx / lib / gridmovers.py
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 #----------------------------------------------------------------------------
12 # 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
13 #
14 # o 2.5 Compatability changes
15 #
16 # 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
17 #
18 # o wxGridColMoveEvent -> GridColMoveEvent
19 # o wxGridRowMoveEvent -> GridRowMoveEvent
20 # o wxGridColMover -> GridColMover
21 # o wxGridRowMover -> GridRowMover
22 #
23
24
25 import wx
26 import wx.grid
27
28 #----------------------------------------------------------------------------
29 # event class and macros
30 #
31 # New style 12/7/03
32 #
33
34 wxEVT_COMMAND_GRID_COL_MOVE = wx.NewEventType()
35 wxEVT_COMMAND_GRID_ROW_MOVE = wx.NewEventType()
36
37 EVT_GRID_COL_MOVE = wx.PyEventBinder(wxEVT_COMMAND_GRID_COL_MOVE, 1)
38 EVT_GRID_ROW_MOVE = wx.PyEventBinder(wxEVT_COMMAND_GRID_ROW_MOVE, 1)
39
40 #----------------------------------------------------------------------------
41
42 class GridColMoveEvent(wx.PyCommandEvent):
43 def __init__(self, id, dCol, bCol):
44 wx.PyCommandEvent.__init__(self, id = id)
45 self.SetEventType(wxEVT_COMMAND_GRID_COL_MOVE)
46 self.moveColumn = dCol
47 self.beforeColumn = bCol
48
49 def GetMoveColumn(self):
50 return self.moveColumn
51
52 def GetBeforeColumn(self):
53 return self.beforeColumn
54
55
56 class GridRowMoveEvent(wx.PyCommandEvent):
57 def __init__(self, id, dRow, bRow):
58 wx.PyCommandEvent.__init__(self,id = id)
59 self.SetEventType(wxEVT_COMMAND_GRID_ROW_MOVE)
60 self.moveRow = dRow
61 self.beforeRow = bRow
62
63 def GetMoveRow(self):
64 return self.moveRow
65
66 def GetBeforeRow(self):
67 return self.beforeRow
68
69
70 #----------------------------------------------------------------------------
71 # graft new methods into the wxGrid class
72
73 def _ColToRect(self,col):
74 if self.GetNumberRows() > 0:
75 rect = self.CellToRect(0,col)
76 else:
77 rect = wx.Rect()
78 rect.height = self.GetColLabelSize()
79 rect.width = self.GetColSize(col)
80
81 for cCol in range(0,col):
82 rect.x += self.GetColSize(cCol)
83
84 rect.y = self.GetGridColLabelWindow().GetPosition()[1]
85 return rect
86
87 wx.grid.Grid.ColToRect = _ColToRect
88
89
90 def _RowToRect(self,row):
91 if self.GetNumberCols() > 0:
92 rect = self.CellToRect(row,0)
93 else:
94 rect = wx.Rect()
95 rect.width = self.GetRowLabelSize()
96 rect.height = self.GetRowSize(row)
97
98 for cRow in range(0,row):
99 rect.y += self.GetRowSize(cRow)
100
101 rect.x = self.GetGridRowLabelWindow().GetPosition()[0]
102 return rect
103
104 wx.grid.Grid.RowToRect = _RowToRect
105
106
107 #----------------------------------------------------------------------------
108
109 class ColDragWindow(wx.Window):
110 def __init__(self,parent,image,dragCol):
111 wx.Window.__init__(self,parent,-1, style=wx.SIMPLE_BORDER)
112 self.image = image
113 self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
114 self.ux = parent.GetScrollPixelsPerUnit()[0]
115 self.moveColumn = dragCol
116
117 self.Bind(wx.EVT_PAINT, self.OnPaint)
118
119 def DisplayAt(self,pos,y):
120 x = self.GetPositionTuple()[0]
121 if x == pos:
122 self.Refresh() # Need to display insertion point
123 else:
124 self.MoveXY(pos,y)
125
126 def GetMoveColumn(self):
127 return self.moveColumn
128
129 def _GetInsertionInfo(self):
130 parent = self.GetParent()
131 sx = parent.GetViewStart()[0] * self.ux
132 sx -= parent._rlSize
133 x = self.GetPosition()[0]
134 w = self.GetSize()[0]
135 sCol = parent.XToCol(x + sx)
136 eCol = parent.XToCol(x + w + sx)
137 iPos = xPos = xCol = 99999
138 centerPos = x + sx + (w / 2)
139
140 for col in range(sCol,eCol + 1):
141 cx = parent.ColToRect(col)[0]
142
143 if abs(cx - centerPos) < iPos:
144 iPos = abs(cx - centerPos)
145 xCol = col
146 xPos = cx
147
148 if xCol < 0 or xCol > parent.GetNumberCols():
149 xCol = parent.GetNumberCols()
150
151 return (xPos - sx - x,xCol)
152
153 def GetInsertionColumn(self):
154 return self._GetInsertionInfo()[1]
155
156 def GetInsertionPos(self):
157 return self._GetInsertionInfo()[0]
158
159 def OnPaint(self,evt):
160 dc = wx.PaintDC(self)
161 w,h = self.GetSize()
162 dc.DrawBitmap(self.image, 0,0)
163 dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
164 dc.SetBrush(wx.TRANSPARENT_BRUSH)
165 dc.DrawRectangle(0,0, w,h)
166 iPos = self.GetInsertionPos()
167 dc.DrawLine(iPos,h - 10, iPos,h)
168
169
170
171
172 class RowDragWindow(wx.Window):
173 def __init__(self,parent,image,dragRow):
174 wx.Window.__init__(self,parent,-1, style=wx.SIMPLE_BORDER)
175 self.image = image
176 self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
177 self.uy = parent.GetScrollPixelsPerUnit()[1]
178 self.moveRow = dragRow
179
180 self.Bind(wx.EVT_PAINT, self.OnPaint)
181
182 def DisplayAt(self,x,pos):
183 y = self.GetPosition()[1]
184 if y == pos:
185 self.Refresh() # Need to display insertion point
186 else:
187 self.MoveXY(x,pos)
188
189 def GetMoveRow(self):
190 return self.moveRow
191
192 def _GetInsertionInfo(self):
193 parent = self.GetParent()
194 sy = parent.GetViewStart()[1] * self.uy
195 sy -= parent._clSize
196 y = self.GetPosition()[1]
197 h = self.GetSize()[1]
198 sRow = parent.YToRow(y + sy)
199 eRow = parent.YToRow(y + h + sy)
200 iPos = yPos = yRow = 99999
201 centerPos = y + sy + (h / 2)
202
203 for row in range(sRow,eRow + 1):
204 cy = parent.RowToRect(row)[1]
205
206 if abs(cy - centerPos) < iPos:
207 iPos = abs(cy - centerPos)
208 yRow = row
209 yPos = cy
210
211 if yRow < 0 or yRow > parent.GetNumberRows():
212 yRow = parent.GetNumberRows()
213
214 return (yPos - sy - y,yRow)
215
216 def GetInsertionRow(self):
217 return self._GetInsertionInfo()[1]
218
219 def GetInsertionPos(self):
220 return self._GetInsertionInfo()[0]
221
222 def OnPaint(self,evt):
223 dc = wx.PaintDC(self)
224 w,h = self.GetSize()
225 dc.DrawBitmap(self.image, 0,0)
226 dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
227 dc.SetBrush(wx.TRANSPARENT_BRUSH)
228 dc.DrawRectangle(0,0, w,h)
229 iPos = self.GetInsertionPos()
230 dc.DrawLine(w - 10,iPos, w,iPos)
231
232 #----------------------------------------------------------------------------
233
234 class GridColMover(wx.EvtHandler):
235 def __init__(self,grid):
236 wx.EvtHandler.__init__(self)
237
238 self.grid = grid
239 self.grid._rlSize = self.grid.GetRowLabelSize()
240 self.lwin = grid.GetGridColLabelWindow()
241 self.lwin.PushEventHandler(self)
242 self.colWin = None
243 self.ux = self.grid.GetScrollPixelsPerUnit()[0]
244 self.startX = -10
245 self.cellX = 0
246 self.didMove = False
247 self.isDragging = False
248
249 self.Bind(wx.EVT_MOTION, self.OnMouseMove)
250 self.Bind(wx.EVT_LEFT_DOWN, self.OnPress)
251 self.Bind(wx.EVT_LEFT_UP, self.OnRelease)
252
253 def OnMouseMove(self,evt):
254 if self.isDragging:
255 if abs(self.startX - evt.m_x) >= 3:
256 self.didMove = True
257 sx,y = self.grid.GetViewStart()
258 w,h = self.lwin.GetClientSize()
259 x = sx * self.ux
260
261 if (evt.m_x + x) < x:
262 x = evt.m_x + x
263 elif evt.m_x > w:
264 x += evt.m_x - w
265
266 if x < 1: x = 0
267 else: x /= self.ux
268
269 if x != sx:
270 if wx.Platform == '__WXMSW__':
271 self.colWin.Show(False)
272
273 self.grid.Scroll(x,y)
274
275 x,y = self.lwin.ClientToScreenXY(evt.m_x,0)
276 x,y = self.grid.ScreenToClientXY(x,y)
277
278 if not self.colWin.IsShown():
279 self.colWin.Show(True)
280
281 px = x - self.cellX
282
283 if px < 0 + self.grid._rlSize: px = 0 + self.grid._rlSize
284
285 if px > w - self.colWin.GetSize()[0] + self.grid._rlSize:
286 px = w - self.colWin.GetSize()[0] + self.grid._rlSize
287
288 self.colWin.DisplayAt(px,y)
289 return
290
291 evt.Skip()
292
293 def OnPress(self,evt):
294 self.startX = evt.m_x
295 sx = self.grid.GetViewStart()[0] * self.ux
296 sx -= self.grid._rlSize
297 px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y)
298 px,py = self.grid.ScreenToClientXY(px,py)
299
300 if self.grid.XToEdgeOfCol(px + sx) != wx.NOT_FOUND:
301 evt.Skip()
302 return
303
304 self.isDragging = True
305 self.didMove = False
306 col = self.grid.XToCol(px + sx)
307 rect = self.grid.ColToRect(col)
308 self.cellX = px + sx - rect.x
309 size = self.lwin.GetSize()
310 rect.y = 0
311 rect.x -= sx + self.grid._rlSize
312 rect.height = size[1]
313 colImg = self._CaptureImage(rect)
314 self.colWin = ColDragWindow(self.grid,colImg,col)
315 self.colWin.Show(False)
316 self.lwin.CaptureMouse()
317 evt.Skip()
318
319 def OnRelease(self,evt):
320 if self.isDragging:
321 self.lwin.ReleaseMouse()
322 self.colWin.Show(False)
323 self.isDragging = False
324
325 if not self.didMove:
326 px = self.lwin.ClientToScreenXY(self.startX,0)[0]
327 px = self.grid.ScreenToClientXY(px,0)[0]
328 sx = self.grid.GetViewStart()[0] * self.ux
329 sx -= self.grid._rlSize
330 col = self.grid.XToCol(px+sx)
331
332 if col != wx.NOT_FOUND:
333 self.grid.SelectCol(col,evt.m_controlDown)
334
335 return
336 else:
337 bCol = self.colWin.GetInsertionColumn()
338 dCol = self.colWin.GetMoveColumn()
339 wx.PostEvent(self,
340 GridColMoveEvent(self.grid.GetId(), dCol, bCol))
341
342 self.colWin.Destroy()
343 evt.Skip()
344
345 def _CaptureImage(self,rect):
346 bmp = wx.EmptyBitmap(rect.width,rect.height)
347 memdc = wx.MemoryDC()
348 memdc.SelectObject(bmp)
349 dc = wx.WindowDC(self.lwin)
350 memdc.Blit(0,0, rect.width, rect.height, dc, rect.x, rect.y)
351 memdc.SelectObject(wx.NullBitmap)
352 return bmp
353
354
355 class GridRowMover(wx.EvtHandler):
356 def __init__(self,grid):
357 wx.EvtHandler.__init__(self)
358
359 self.grid = grid
360 self.grid._clSize = self.grid.GetColLabelSize()
361 self.lwin = grid.GetGridRowLabelWindow()
362 self.lwin.PushEventHandler(self)
363 self.rowWin = None
364 self.uy = self.grid.GetScrollPixelsPerUnit()[1]
365 self.startY = -10
366 self.cellY = 0
367 self.didMove = False
368 self.isDragging = False
369
370 self.Bind(wx.EVT_MOTION, self.OnMouseMove)
371 self.Bind(wx.EVT_LEFT_DOWN, self.OnPress)
372 self.Bind(wx.EVT_LEFT_UP, self.OnRelease)
373
374 def OnMouseMove(self,evt):
375 if self.isDragging:
376 if abs(self.startY - evt.m_y) >= 3:
377 self.didMove = True
378 x,sy = self.grid.GetViewStart()
379 w,h = self.lwin.GetClientSizeTuple()
380 y = sy * self.uy
381
382 if (evt.m_y + y) < y:
383 y = evt.m_y + y
384 elif evt.m_y > h:
385 y += evt.m_y - h
386
387 if y < 1:
388 y = 0
389 else:
390 y /= self.uy
391
392 if y != sy:
393 if wx.Platform == '__WXMSW__':
394 self.rowWin.Show(False)
395
396 self.grid.Scroll(x,y)
397
398 x,y = self.lwin.ClientToScreenXY(0,evt.m_y)
399 x,y = self.grid.ScreenToClientXY(x,y)
400
401 if not self.rowWin.IsShown():
402 self.rowWin.Show(True)
403
404 py = y - self.cellY
405
406 if py < 0 + self.grid._clSize:
407 py = 0 + self.grid._clSize
408
409 if py > h - self.rowWin.GetSize()[1] + self.grid._clSize:
410 py = h - self.rowWin.GetSize()[1] + self.grid._clSize
411
412 self.rowWin.DisplayAt(x,py)
413 return
414
415 evt.Skip()
416
417 def OnPress(self,evt):
418 self.startY = evt.m_y
419 sy = self.grid.GetViewStart()[1] * self.uy
420 sy -= self.grid._clSize
421 px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y)
422 px,py = self.grid.ScreenToClientXY(px,py)
423
424 if self.grid.YToEdgeOfRow(py + sy) != wx.NOT_FOUND:
425 evt.Skip()
426 return
427
428 self.isDragging = True
429 self.didMove = False
430 row = self.grid.YToRow(py + sy)
431 rect = self.grid.RowToRect(row)
432 self.cellY = py + sy - rect.y
433 size = self.lwin.GetSize()
434 rect.x = 0
435 rect.y -= sy + self.grid._clSize
436 rect.width = size[0]
437 rowImg = self._CaptureImage(rect)
438 self.rowWin = RowDragWindow(self.grid,rowImg,row)
439 self.rowWin.Show(False)
440 self.lwin.CaptureMouse()
441 evt.Skip()
442
443 def OnRelease(self,evt):
444 if self.isDragging:
445 self.lwin.ReleaseMouse()
446 self.rowWin.Show(False)
447 self.isDragging = False
448
449 if not self.didMove:
450 py = self.lwin.ClientToScreenXY(0,self.startY)[1]
451 py = self.grid.ScreenToClientXY(0,py)[1]
452 sy = self.grid.GetViewStart()[1] * self.uy
453 sy -= self.grid._clSize
454 row = self.grid.YToRow(py + sy)
455
456 if row != wx.NOT_FOUND:
457 self.grid.SelectRow(row,evt.m_controlDown)
458 return
459 else:
460 bRow = self.rowWin.GetInsertionRow()
461 dRow = self.rowWin.GetMoveRow()
462
463 wx.PostEvent(self,
464 GridRowMoveEvent(self.grid.GetId(), dRow, bRow))
465
466 self.rowWin.Destroy()
467 evt.Skip()
468
469 def _CaptureImage(self,rect):
470 bmp = wx.EmptyBitmap(rect.width,rect.height)
471 memdc = wx.MemoryDC()
472 memdc.SelectObject(bmp)
473 dc = wx.WindowDC(self.lwin)
474 memdc.Blit(0,0, rect.width, rect.height, dc, rect.x, rect.y)
475 memdc.SelectObject(wx.NullBitmap)
476 return bmp
477
478
479 #----------------------------------------------------------------------------