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 #----------------------------------------------------------------------------
13 from wxPython
.wx
import *
14 from wxPython
.grid
import wxGrid
16 #----------------------------------------------------------------------------
17 # event class and macors
20 wxEVT_COMMAND_GRID_COL_MOVE
= wxNewEventType()
21 wxEVT_COMMAND_GRID_ROW_MOVE
= wxNewEventType()
23 def EVT_GRID_COL_MOVE(win
, id, func
):
24 win
.Connect(id, -1, wxEVT_COMMAND_GRID_COL_MOVE
, func
)
26 def EVT_GRID_ROW_MOVE(win
,id,func
):
27 win
.Connect(id, -1, wxEVT_COMMAND_GRID_ROW_MOVE
, func
)
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
37 def GetMoveColumn(self
):
38 return self
.moveColumn
40 def GetBeforeColumn(self
):
41 return self
.beforeColumn
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
)
54 def GetBeforeRow(self
):
58 #----------------------------------------------------------------------------
59 # graft new methods into the wxGrid class
61 def _ColToRect(self
,col
):
62 if self
.GetNumberRows() > 0:
63 rect
= self
.CellToRect(0,col
)
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]
73 wxGrid
.ColToRect
= _ColToRect
76 def _RowToRect(self
,row
):
77 if self
.GetNumberCols() > 0:
78 rect
= self
.CellToRect(row
,0)
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]
88 wxGrid
.RowToRect
= _RowToRect
91 #----------------------------------------------------------------------------
93 class ColDragWindow(wxWindow
):
94 def __init__(self
,parent
,image
,dragCol
):
95 wxWindow
.__init
__(self
,parent
,-1, style
=wxSIMPLE_BORDER
)
97 self
.SetSize((self
.image
.GetWidth(),self
.image
.GetHeight()))
98 self
.ux
= parent
.GetScrollPixelsPerUnit()[0]
99 self
.moveColumn
= dragCol
101 EVT_PAINT(self
,self
.OnPaint
)
103 def DisplayAt(self
,pos
,y
):
104 x
= self
.GetPositionTuple()[0]
106 self
.Refresh() # Need to display insertion point
110 def GetMoveColumn(self
):
111 return self
.moveColumn
113 def _GetInsertionInfo(self
):
114 parent
= self
.GetParent()
115 sx
= parent
.GetViewStart()[0] * self
.ux
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
)
129 if xCol
< 0 or xCol
> parent
.GetNumberCols():
130 xCol
= parent
.GetNumberCols()
131 return (xPos
- sx
- x
,xCol
)
133 def GetInsertionColumn(self
):
134 return self
._GetInsertionInfo
()[1]
136 def GetInsertionPos(self
):
137 return self
._GetInsertionInfo
()[0]
139 def OnPaint(self
,evt
):
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
))
152 class RowDragWindow(wxWindow
):
153 def __init__(self
,parent
,image
,dragRow
):
154 wxWindow
.__init
__(self
,parent
,-1, style
=wxSIMPLE_BORDER
)
156 self
.SetSize((self
.image
.GetWidth(),self
.image
.GetHeight()))
157 self
.uy
= parent
.GetScrollPixelsPerUnit()[1]
158 self
.moveRow
= dragRow
160 EVT_PAINT(self
,self
.OnPaint
)
162 def DisplayAt(self
,x
,pos
):
163 y
= self
.GetPositionTuple()[1]
165 self
.Refresh() # Need to display insertion point
169 def GetMoveRow(self
):
172 def _GetInsertionInfo(self
):
173 parent
= self
.GetParent()
174 sy
= parent
.GetViewStart()[1] * self
.uy
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
)
188 if yRow
< 0 or yRow
> parent
.GetNumberRows():
189 yRow
= parent
.GetNumberRows()
190 return (yPos
- sy
- y
,yRow
)
192 def GetInsertionRow(self
):
193 return self
._GetInsertionInfo
()[1]
195 def GetInsertionPos(self
):
196 return self
._GetInsertionInfo
()[0]
198 def OnPaint(self
,evt
):
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
))
208 #----------------------------------------------------------------------------
210 class wxGridColMover(wxEvtHandler
):
211 def __init__(self
,grid
):
212 wxEvtHandler
.__init
__(self
)
215 self
.grid
._rlSize
= self
.grid
.GetRowLabelSize()
216 self
.lwin
= grid
.GetGridColLabelWindow()
217 self
.lwin
.PushEventHandler(self
)
219 self
.ux
= self
.grid
.GetScrollPixelsPerUnit()[0]
223 self
.isDragging
= False
225 EVT_MOTION(self
,self
.OnMouseMove
)
226 EVT_LEFT_DOWN(self
,self
.OnPress
)
227 EVT_LEFT_UP(self
,self
.OnRelease
)
229 def OnMouseMove(self
,evt
):
231 if abs(self
.startX
- evt
.m_x
) >= 3:
233 sx
,y
= self
.grid
.GetViewStart()
234 w
,h
= self
.lwin
.GetClientSizeTuple()
236 if (evt
.m_x
+ x
) < x
:
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)
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
)
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
:
268 self
.isDragging
= True
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()
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()
282 def OnRelease(self
,evt
):
284 self
.lwin
.ReleaseMouse()
285 self
.colWin
.Show(False)
286 self
.isDragging
= False
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
)
297 bCol
= self
.colWin
.GetInsertionColumn()
298 dCol
= self
.colWin
.GetMoveColumn()
299 wxPostEvent(self
,wxGridColMoveEvent(self
.grid
.GetId(),
301 self
.colWin
.Destroy()
304 def _CaptureImage(self
,rect
):
305 bmp
= wxEmptyBitmap(rect
.width
,rect
.height
)
307 memdc
.SelectObject(bmp
)
308 dc
= wxWindowDC(self
.lwin
)
309 memdc
.Blit((0,0), rect
.GetSize(), dc
, rect
.GetPosition())
310 memdc
.SelectObject(wxNullBitmap
)
315 class wxGridRowMover(wxEvtHandler
):
316 def __init__(self
,grid
):
317 wxEvtHandler
.__init
__(self
)
320 self
.grid
._clSize
= self
.grid
.GetColLabelSize()
321 self
.lwin
= grid
.GetGridRowLabelWindow()
322 self
.lwin
.PushEventHandler(self
)
324 self
.uy
= self
.grid
.GetScrollPixelsPerUnit()[1]
328 self
.isDragging
= False
330 EVT_MOTION(self
,self
.OnMouseMove
)
331 EVT_LEFT_DOWN(self
,self
.OnPress
)
332 EVT_LEFT_UP(self
,self
.OnRelease
)
334 def OnMouseMove(self
,evt
):
336 if abs(self
.startY
- evt
.m_y
) >= 3:
338 x
,sy
= self
.grid
.GetViewStart()
339 w
,h
= self
.lwin
.GetClientSizeTuple()
341 if (evt
.m_y
+ y
) < y
:
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)
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
)
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
:
373 self
.isDragging
= True
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()
380 rect
.y
-= sy
+ self
.grid
._clSize
382 rowImg
= self
._CaptureImage
(rect
)
383 self
.rowWin
= RowDragWindow(self
.grid
,rowImg
,row
)
384 self
.rowWin
.Show(False)
385 self
.lwin
.CaptureMouse()
387 def OnRelease(self
,evt
):
389 self
.lwin
.ReleaseMouse()
390 self
.rowWin
.Show(False)
391 self
.isDragging
= False
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
)
402 bRow
= self
.rowWin
.GetInsertionRow()
403 dRow
= self
.rowWin
.GetMoveRow()
404 wxPostEvent(self
,wxGridRowMoveEvent(self
.grid
.GetId(),
406 self
.rowWin
.Destroy()
409 def _CaptureImage(self
,rect
):
410 bmp
= wxEmptyBitmap(rect
.width
,rect
.height
)
412 memdc
.SelectObject(bmp
)
413 dc
= wxWindowDC(self
.lwin
)
414 memdc
.Blit((0,0), rect
.GetSize(), dc
, rect
.GetPosition())
415 memdc
.SelectObject(wxNullBitmap
)
419 #----------------------------------------------------------------------------