1 #----------------------------------------------------------------------------
2 # Name: GridColMover.py
3 # Purpose: Grid Column Mover Extension
5 # Author: Gerrit van Dyk (email: gerritvd@decillion.net)
10 # Licence: wxWindows license
11 #----------------------------------------------------------------------------
12 # 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14 # o 2.5 Compatability changes
16 # 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
18 # o wxGridColMoveEvent -> GridColMoveEvent
19 # o wxGridRowMoveEvent -> GridRowMoveEvent
20 # o wxGridColMover -> GridColMover
21 # o wxGridRowMover -> GridRowMover
28 #----------------------------------------------------------------------------
29 # event class and macros
34 wxEVT_COMMAND_GRID_COL_MOVE
= wx
.NewEventType()
35 wxEVT_COMMAND_GRID_ROW_MOVE
= wx
.NewEventType()
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)
40 #----------------------------------------------------------------------------
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
49 def GetMoveColumn(self
):
50 return self
.moveColumn
52 def GetBeforeColumn(self
):
53 return self
.beforeColumn
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
)
66 def GetBeforeRow(self
):
70 #----------------------------------------------------------------------------
71 # graft new methods into the wxGrid class
73 def _ColToRect(self
,col
):
74 if self
.GetNumberRows() > 0:
75 rect
= self
.CellToRect(0,col
)
78 rect
.height
= self
.GetColLabelSize()
79 rect
.width
= self
.GetColSize(col
)
81 for cCol
in range(0,col
):
82 rect
.x
+= self
.GetColSize(cCol
)
84 rect
.y
= self
.GetGridColLabelWindow().GetPosition()[1]
87 wx
.grid
.Grid
.ColToRect
= _ColToRect
90 def _RowToRect(self
,row
):
91 if self
.GetNumberCols() > 0:
92 rect
= self
.CellToRect(row
,0)
95 rect
.width
= self
.GetRowLabelSize()
96 rect
.height
= self
.GetRowSize(row
)
98 for cRow
in range(0,row
):
99 rect
.y
+= self
.GetRowSize(cRow
)
101 rect
.x
= self
.GetGridRowLabelWindow().GetPosition()[0]
104 wx
.grid
.Grid
.RowToRect
= _RowToRect
107 #----------------------------------------------------------------------------
109 class ColDragWindow(wx
.Window
):
110 def __init__(self
,parent
,image
,dragCol
):
111 wx
.Window
.__init
__(self
,parent
,-1, style
=wx
.SIMPLE_BORDER
)
113 self
.SetSize((self
.image
.GetWidth(),self
.image
.GetHeight()))
114 self
.ux
= parent
.GetScrollPixelsPerUnit()[0]
115 self
.moveColumn
= dragCol
117 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
119 def DisplayAt(self
,pos
,y
):
120 x
= self
.GetPositionTuple()[0]
122 self
.Refresh() # Need to display insertion point
126 def GetMoveColumn(self
):
127 return self
.moveColumn
129 def _GetInsertionInfo(self
):
130 parent
= self
.GetParent()
131 sx
= parent
.GetViewStart()[0] * self
.ux
132 sx
-= parent
.GetRowLabelSize()
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)
140 for col
in range(sCol
,eCol
+ 1):
141 cx
= parent
.ColToRect(col
)[0]
143 if abs(cx
- centerPos
) < iPos
:
144 iPos
= abs(cx
- centerPos
)
148 if xCol
< 0 or xCol
> parent
.GetNumberCols():
149 xCol
= parent
.GetNumberCols()
151 return (xPos
- sx
- x
,xCol
)
153 def GetInsertionColumn(self
):
154 return self
._GetInsertionInfo
()[1]
156 def GetInsertionPos(self
):
157 return self
._GetInsertionInfo
()[0]
159 def OnPaint(self
,evt
):
160 dc
= wx
.PaintDC(self
)
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
)
172 class RowDragWindow(wx
.Window
):
173 def __init__(self
,parent
,image
,dragRow
):
174 wx
.Window
.__init
__(self
,parent
,-1, style
=wx
.SIMPLE_BORDER
)
176 self
.SetSize((self
.image
.GetWidth(),self
.image
.GetHeight()))
177 self
.uy
= parent
.GetScrollPixelsPerUnit()[1]
178 self
.moveRow
= dragRow
180 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
182 def DisplayAt(self
,x
,pos
):
183 y
= self
.GetPosition()[1]
185 self
.Refresh() # Need to display insertion point
189 def GetMoveRow(self
):
192 def _GetInsertionInfo(self
):
193 parent
= self
.GetParent()
194 sy
= parent
.GetViewStart()[1] * self
.uy
195 sy
-= parent
.GetColLabelSize()
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)
203 for row
in range(sRow
,eRow
+ 1):
204 cy
= parent
.RowToRect(row
)[1]
206 if abs(cy
- centerPos
) < iPos
:
207 iPos
= abs(cy
- centerPos
)
211 if yRow
< 0 or yRow
> parent
.GetNumberRows():
212 yRow
= parent
.GetNumberRows()
214 return (yPos
- sy
- y
,yRow
)
216 def GetInsertionRow(self
):
217 return self
._GetInsertionInfo
()[1]
219 def GetInsertionPos(self
):
220 return self
._GetInsertionInfo
()[0]
222 def OnPaint(self
,evt
):
223 dc
= wx
.PaintDC(self
)
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
)
232 #----------------------------------------------------------------------------
234 class GridColMover(wx
.EvtHandler
):
235 def __init__(self
,grid
):
236 wx
.EvtHandler
.__init
__(self
)
239 self
.lwin
= grid
.GetGridColLabelWindow()
240 self
.lwin
.PushEventHandler(self
)
242 self
.ux
= self
.grid
.GetScrollPixelsPerUnit()[0]
246 self
.isDragging
= False
248 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
249 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnPress
)
250 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnRelease
)
252 def OnMouseMove(self
,evt
):
254 _rlSize
= self
.grid
.GetRowLabelSize()
255 if abs(self
.startX
- evt
.m_x
) >= 3 \
256 and abs(evt
.m_x
- self
.lastX
) >= 3:
259 sx
,y
= self
.grid
.GetViewStart()
260 w
,h
= self
.lwin
.GetClientSize()
263 if (evt
.m_x
+ x
) < x
:
272 if wx
.Platform
== '__WXMSW__':
273 self
.colWin
.Show(False)
275 self
.grid
.Scroll(x
,y
)
277 x
,y
= self
.lwin
.ClientToScreenXY(evt
.m_x
,0)
278 x
,y
= self
.grid
.ScreenToClientXY(x
,y
)
280 if not self
.colWin
.IsShown():
281 self
.colWin
.Show(True)
285 if px
< 0 + _rlSize
: px
= 0 + _rlSize
287 if px
> w
- self
.colWin
.GetSize()[0] + _rlSize
:
288 px
= w
- self
.colWin
.GetSize()[0] + _rlSize
290 self
.colWin
.DisplayAt(px
,y
)
294 def OnPress(self
,evt
):
295 self
.startX
= self
.lastX
= evt
.m_x
296 _rlSize
= self
.grid
.GetRowLabelSize()
297 sx
= self
.grid
.GetViewStart()[0] * self
.ux
299 px
,py
= self
.lwin
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
300 px
,py
= self
.grid
.ScreenToClientXY(px
,py
)
302 if self
.grid
.XToEdgeOfCol(px
+ sx
) != wx
.NOT_FOUND
:
306 self
.isDragging
= True
308 col
= self
.grid
.XToCol(px
+ sx
)
309 rect
= self
.grid
.ColToRect(col
)
310 self
.cellX
= px
+ sx
- rect
.x
311 size
= self
.lwin
.GetSize()
313 rect
.x
-= sx
+ _rlSize
314 rect
.height
= size
[1]
315 colImg
= self
._CaptureImage
(rect
)
316 self
.colWin
= ColDragWindow(self
.grid
,colImg
,col
)
317 self
.colWin
.Show(False)
318 self
.lwin
.CaptureMouse()
321 def OnRelease(self
,evt
):
323 self
.lwin
.ReleaseMouse()
324 self
.colWin
.Show(False)
325 self
.isDragging
= False
328 px
= self
.lwin
.ClientToScreenXY(self
.startX
,0)[0]
329 px
= self
.grid
.ScreenToClientXY(px
,0)[0]
330 sx
= self
.grid
.GetViewStart()[0] * self
.ux
331 sx
-= self
.grid
.GetRowLabelSize()
332 col
= self
.grid
.XToCol(px
+sx
)
334 if col
!= wx
.NOT_FOUND
:
335 self
.grid
.SelectCol(col
,evt
.m_controlDown
)
339 bCol
= self
.colWin
.GetInsertionColumn()
340 dCol
= self
.colWin
.GetMoveColumn()
342 GridColMoveEvent(self
.grid
.GetId(), dCol
, bCol
))
344 self
.colWin
.Destroy()
347 def _CaptureImage(self
,rect
):
348 bmp
= wx
.EmptyBitmap(rect
.width
,rect
.height
)
349 memdc
= wx
.MemoryDC()
350 memdc
.SelectObject(bmp
)
351 dc
= wx
.WindowDC(self
.lwin
)
352 memdc
.Blit(0,0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
353 memdc
.SelectObject(wx
.NullBitmap
)
357 class GridRowMover(wx
.EvtHandler
):
358 def __init__(self
,grid
):
359 wx
.EvtHandler
.__init
__(self
)
362 self
.lwin
= grid
.GetGridRowLabelWindow()
363 self
.lwin
.PushEventHandler(self
)
365 self
.uy
= self
.grid
.GetScrollPixelsPerUnit()[1]
369 self
.isDragging
= False
371 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
372 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnPress
)
373 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnRelease
)
375 def OnMouseMove(self
,evt
):
377 _clSize
= self
.grid
.GetColLabelSize()
378 if abs(self
.startY
- evt
.m_y
) >= 3 \
379 and abs(evt
.m_y
- self
.lastY
) >= 3:
382 x
,sy
= self
.grid
.GetViewStart()
383 w
,h
= self
.lwin
.GetClientSizeTuple()
386 if (evt
.m_y
+ y
) < y
:
397 if wx
.Platform
== '__WXMSW__':
398 self
.rowWin
.Show(False)
400 self
.grid
.Scroll(x
,y
)
402 x
,y
= self
.lwin
.ClientToScreenXY(0,evt
.m_y
)
403 x
,y
= self
.grid
.ScreenToClientXY(x
,y
)
405 if not self
.rowWin
.IsShown():
406 self
.rowWin
.Show(True)
413 if py
> h
- self
.rowWin
.GetSize()[1] + _clSize
:
414 py
= h
- self
.rowWin
.GetSize()[1] + _clSize
416 self
.rowWin
.DisplayAt(x
,py
)
420 def OnPress(self
,evt
):
421 self
.startY
= self
.lastY
= evt
.m_y
422 _clSize
= self
.grid
.GetColLabelSize()
423 sy
= self
.grid
.GetViewStart()[1] * self
.uy
425 px
,py
= self
.lwin
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
426 px
,py
= self
.grid
.ScreenToClientXY(px
,py
)
428 if self
.grid
.YToEdgeOfRow(py
+ sy
) != wx
.NOT_FOUND
:
432 self
.isDragging
= True
434 row
= self
.grid
.YToRow(py
+ sy
)
435 rect
= self
.grid
.RowToRect(row
)
436 self
.cellY
= py
+ sy
- rect
.y
437 size
= self
.lwin
.GetSize()
439 rect
.y
-= sy
+ _clSize
441 rowImg
= self
._CaptureImage
(rect
)
442 self
.rowWin
= RowDragWindow(self
.grid
,rowImg
,row
)
443 self
.rowWin
.Show(False)
444 self
.lwin
.CaptureMouse()
447 def OnRelease(self
,evt
):
449 self
.lwin
.ReleaseMouse()
450 self
.rowWin
.Show(False)
451 self
.isDragging
= False
454 py
= self
.lwin
.ClientToScreenXY(0,self
.startY
)[1]
455 py
= self
.grid
.ScreenToClientXY(0,py
)[1]
456 sy
= self
.grid
.GetViewStart()[1] * self
.uy
457 sy
-= self
.grid
.GetColLabelSize()
458 row
= self
.grid
.YToRow(py
+ sy
)
460 if row
!= wx
.NOT_FOUND
:
461 self
.grid
.SelectRow(row
,evt
.m_controlDown
)
464 bRow
= self
.rowWin
.GetInsertionRow()
465 dRow
= self
.rowWin
.GetMoveRow()
468 GridRowMoveEvent(self
.grid
.GetId(), dRow
, bRow
))
470 self
.rowWin
.Destroy()
473 def _CaptureImage(self
,rect
):
474 bmp
= wx
.EmptyBitmap(rect
.width
,rect
.height
)
475 memdc
= wx
.MemoryDC()
476 memdc
.SelectObject(bmp
)
477 dc
= wx
.WindowDC(self
.lwin
)
478 memdc
.Blit(0,0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
479 memdc
.SelectObject(wx
.NullBitmap
)
483 #----------------------------------------------------------------------------