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
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
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
.grid
._rlSize
= self
.grid
.GetRowLabelSize()
240 self
.lwin
= grid
.GetGridColLabelWindow()
241 self
.lwin
.PushEventHandler(self
)
243 self
.ux
= self
.grid
.GetScrollPixelsPerUnit()[0]
247 self
.isDragging
= False
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
)
253 def OnMouseMove(self
,evt
):
255 if abs(self
.startX
- evt
.m_x
) >= 3:
257 sx
,y
= self
.grid
.GetViewStart()
258 w
,h
= self
.lwin
.GetClientSize()
261 if (evt
.m_x
+ x
) < x
:
270 if wx
.Platform
== '__WXMSW__':
271 self
.colWin
.Show(False)
273 self
.grid
.Scroll(x
,y
)
275 x
,y
= self
.lwin
.ClientToScreenXY(evt
.m_x
,0)
276 x
,y
= self
.grid
.ScreenToClientXY(x
,y
)
278 if not self
.colWin
.IsShown():
279 self
.colWin
.Show(True)
283 if px
< 0 + self
.grid
._rlSize
: px
= 0 + self
.grid
._rlSize
285 if px
> w
- self
.colWin
.GetSize()[0] + self
.grid
._rlSize
:
286 px
= w
- self
.colWin
.GetSize()[0] + self
.grid
._rlSize
288 self
.colWin
.DisplayAt(px
,y
)
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
)
300 if self
.grid
.XToEdgeOfCol(px
+ sx
) != wx
.NOT_FOUND
:
304 self
.isDragging
= True
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()
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()
318 def OnRelease(self
,evt
):
320 self
.lwin
.ReleaseMouse()
321 self
.colWin
.Show(False)
322 self
.isDragging
= False
325 px
= self
.lwin
.ClientToScreenXY(self
.startX
,0)[0]
326 px
= self
.grid
.ScreenToClientXY(px
,0)[0]
327 sx
= self
.grid
.GetViewStart()[0] * self
.ux
328 sx
-= self
.grid
._rlSize
329 col
= self
.grid
.XToCol(px
+sx
)
331 if col
!= wx
.NOT_FOUND
:
332 self
.grid
.SelectCol(col
,evt
.m_controlDown
)
336 bCol
= self
.colWin
.GetInsertionColumn()
337 dCol
= self
.colWin
.GetMoveColumn()
339 GridColMoveEvent(self
.grid
.GetId(), dCol
, bCol
))
341 self
.colWin
.Destroy()
344 def _CaptureImage(self
,rect
):
345 bmp
= wx
.EmptyBitmap(rect
.width
,rect
.height
)
346 memdc
= wx
.MemoryDC()
347 memdc
.SelectObject(bmp
)
348 dc
= wx
.WindowDC(self
.lwin
)
349 memdc
.Blit(0,0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
350 memdc
.SelectObject(wx
.NullBitmap
)
354 class GridRowMover(wx
.EvtHandler
):
355 def __init__(self
,grid
):
356 wx
.EvtHandler
.__init
__(self
)
359 self
.grid
._clSize
= self
.grid
.GetColLabelSize()
360 self
.lwin
= grid
.GetGridRowLabelWindow()
361 self
.lwin
.PushEventHandler(self
)
363 self
.uy
= self
.grid
.GetScrollPixelsPerUnit()[1]
367 self
.isDragging
= False
369 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
370 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnPress
)
371 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnRelease
)
373 def OnMouseMove(self
,evt
):
375 if abs(self
.startY
- evt
.m_y
) >= 3:
377 x
,sy
= self
.grid
.GetViewStart()
378 w
,h
= self
.lwin
.GetClientSizeTuple()
381 if (evt
.m_y
+ y
) < y
:
392 if wx
.Platform
== '__WXMSW__':
393 self
.rowWin
.Show(False)
395 self
.grid
.Scroll(x
,y
)
397 x
,y
= self
.lwin
.ClientToScreenXY(0,evt
.m_y
)
398 x
,y
= self
.grid
.ScreenToClientXY(x
,y
)
400 if not self
.rowWin
.IsShown():
401 self
.rowWin
.Show(True)
405 if py
< 0 + self
.grid
._clSize
:
406 py
= 0 + self
.grid
._clSize
408 if py
> h
- self
.rowWin
.GetSize()[1] + self
.grid
._clSize
:
409 py
= h
- self
.rowWin
.GetSize()[1] + self
.grid
._clSize
411 self
.rowWin
.DisplayAt(x
,py
)
416 def OnPress(self
,evt
):
417 self
.startY
= evt
.m_y
418 sy
= self
.grid
.GetViewStart()[1] * self
.uy
419 sy
-= self
.grid
._clSize
420 px
,py
= self
.lwin
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
421 px
,py
= self
.grid
.ScreenToClientXY(px
,py
)
423 if self
.grid
.YToEdgeOfRow(py
+ sy
) != wx
.NOT_FOUND
:
427 self
.isDragging
= True
429 row
= self
.grid
.YToRow(py
+ sy
)
430 rect
= self
.grid
.RowToRect(row
)
431 self
.cellY
= py
+ sy
- rect
.y
432 size
= self
.lwin
.GetSize()
434 rect
.y
-= sy
+ self
.grid
._clSize
436 rowImg
= self
._CaptureImage
(rect
)
437 self
.rowWin
= RowDragWindow(self
.grid
,rowImg
,row
)
438 self
.rowWin
.Show(False)
439 self
.lwin
.CaptureMouse()
441 def OnRelease(self
,evt
):
443 self
.lwin
.ReleaseMouse()
444 self
.rowWin
.Show(False)
445 self
.isDragging
= False
448 py
= self
.lwin
.ClientToScreenXY(0,self
.startY
)[1]
449 py
= self
.grid
.ScreenToClientXY(0,py
)[1]
450 sy
= self
.grid
.GetViewStart()[1] * self
.uy
451 sy
-= self
.grid
._clSize
452 row
= self
.grid
.YToRow(py
+ sy
)
454 if row
!= wx
.NOT_FOUND
:
455 self
.grid
.SelectRow(row
,evt
.m_controlDown
)
458 bRow
= self
.rowWin
.GetInsertionRow()
459 dRow
= self
.rowWin
.GetMoveRow()
462 GridRowMoveEvent(self
.grid
.GetId(), dRow
, bRow
))
464 self
.rowWin
.Destroy()
467 def _CaptureImage(self
,rect
):
468 bmp
= wx
.EmptyBitmap(rect
.width
,rect
.height
)
469 memdc
= wx
.MemoryDC()
470 memdc
.SelectObject(bmp
)
471 dc
= wx
.WindowDC(self
.lwin
)
472 memdc
.Blit(0,0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
473 memdc
.SelectObject(wx
.NullBitmap
)
477 #----------------------------------------------------------------------------