]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/gridmovers.py
Patch from Dj Gilcrease adding the FNB_HIDE_ON_SINGLE_TAB flag for
[wxWidgets.git] / wxPython / wx / lib / gridmovers.py
CommitLineData
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#----------------------------------------------------------------------------
b881fc78
RD
12# 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
13#
14# o 2.5 Compatability changes
15#
33785d9f
RD
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
1fded56b 24
b881fc78
RD
25import wx
26import wx.grid
1fded56b 27
d14a1e28 28#----------------------------------------------------------------------------
b881fc78
RD
29# event class and macros
30#
31# New style 12/7/03
32#
d14a1e28 33
b881fc78
RD
34wxEVT_COMMAND_GRID_COL_MOVE = wx.NewEventType()
35wxEVT_COMMAND_GRID_ROW_MOVE = wx.NewEventType()
d14a1e28 36
b881fc78
RD
37EVT_GRID_COL_MOVE = wx.PyEventBinder(wxEVT_COMMAND_GRID_COL_MOVE, 1)
38EVT_GRID_ROW_MOVE = wx.PyEventBinder(wxEVT_COMMAND_GRID_ROW_MOVE, 1)
d14a1e28 39
b881fc78 40#----------------------------------------------------------------------------
d14a1e28 41
33785d9f 42class GridColMoveEvent(wx.PyCommandEvent):
d14a1e28 43 def __init__(self, id, dCol, bCol):
b881fc78 44 wx.PyCommandEvent.__init__(self, id = id)
d14a1e28
RD
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
33785d9f 56class GridRowMoveEvent(wx.PyCommandEvent):
d14a1e28 57 def __init__(self, id, dRow, bRow):
b881fc78 58 wx.PyCommandEvent.__init__(self,id = id)
d14a1e28
RD
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
73def _ColToRect(self,col):
74 if self.GetNumberRows() > 0:
75 rect = self.CellToRect(0,col)
76 else:
a38c6903 77 rect = wx.Rect()
d14a1e28
RD
78 rect.height = self.GetColLabelSize()
79 rect.width = self.GetColSize(col)
b881fc78 80
d14a1e28
RD
81 for cCol in range(0,col):
82 rect.x += self.GetColSize(cCol)
b881fc78 83
d14a1e28
RD
84 rect.y = self.GetGridColLabelWindow().GetPosition()[1]
85 return rect
86
b881fc78 87wx.grid.Grid.ColToRect = _ColToRect
d14a1e28
RD
88
89
90def _RowToRect(self,row):
91 if self.GetNumberCols() > 0:
92 rect = self.CellToRect(row,0)
93 else:
a38c6903 94 rect = wx.Rect()
d14a1e28
RD
95 rect.width = self.GetRowLabelSize()
96 rect.height = self.GetRowSize(row)
b881fc78 97
d14a1e28
RD
98 for cRow in range(0,row):
99 rect.y += self.GetRowSize(cRow)
b881fc78 100
d14a1e28
RD
101 rect.x = self.GetGridRowLabelWindow().GetPosition()[0]
102 return rect
103
b881fc78 104wx.grid.Grid.RowToRect = _RowToRect
d14a1e28
RD
105
106
107#----------------------------------------------------------------------------
108
b881fc78 109class ColDragWindow(wx.Window):
d14a1e28 110 def __init__(self,parent,image,dragCol):
b881fc78 111 wx.Window.__init__(self,parent,-1, style=wx.SIMPLE_BORDER)
d14a1e28
RD
112 self.image = image
113 self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
114 self.ux = parent.GetScrollPixelsPerUnit()[0]
115 self.moveColumn = dragCol
116
b881fc78 117 self.Bind(wx.EVT_PAINT, self.OnPaint)
d14a1e28
RD
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
a6c12911 132 sx -= parent.GetRowLabelSize()
b881fc78
RD
133 x = self.GetPosition()[0]
134 w = self.GetSize()[0]
d14a1e28
RD
135 sCol = parent.XToCol(x + sx)
136 eCol = parent.XToCol(x + w + sx)
137 iPos = xPos = xCol = 99999
138 centerPos = x + sx + (w / 2)
b881fc78 139
d14a1e28
RD
140 for col in range(sCol,eCol + 1):
141 cx = parent.ColToRect(col)[0]
b881fc78 142
d14a1e28
RD
143 if abs(cx - centerPos) < iPos:
144 iPos = abs(cx - centerPos)
145 xCol = col
146 xPos = cx
b881fc78 147
d14a1e28
RD
148 if xCol < 0 or xCol > parent.GetNumberCols():
149 xCol = parent.GetNumberCols()
b881fc78 150
d14a1e28
RD
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):
b881fc78 160 dc = wx.PaintDC(self)
d14a1e28 161 w,h = self.GetSize()
d7403ad2 162 dc.DrawBitmap(self.image, 0,0)
b881fc78
RD
163 dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
164 dc.SetBrush(wx.TRANSPARENT_BRUSH)
d7403ad2 165 dc.DrawRectangle(0,0, w,h)
d14a1e28 166 iPos = self.GetInsertionPos()
d7403ad2 167 dc.DrawLine(iPos,h - 10, iPos,h)
d14a1e28
RD
168
169
170
171
b881fc78 172class RowDragWindow(wx.Window):
d14a1e28 173 def __init__(self,parent,image,dragRow):
b881fc78 174 wx.Window.__init__(self,parent,-1, style=wx.SIMPLE_BORDER)
d14a1e28
RD
175 self.image = image
176 self.SetSize((self.image.GetWidth(),self.image.GetHeight()))
177 self.uy = parent.GetScrollPixelsPerUnit()[1]
178 self.moveRow = dragRow
179
b881fc78 180 self.Bind(wx.EVT_PAINT, self.OnPaint)
d14a1e28
RD
181
182 def DisplayAt(self,x,pos):
b881fc78 183 y = self.GetPosition()[1]
d14a1e28
RD
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
a6c12911 195 sy -= parent.GetColLabelSize()
b881fc78
RD
196 y = self.GetPosition()[1]
197 h = self.GetSize()[1]
d14a1e28
RD
198 sRow = parent.YToRow(y + sy)
199 eRow = parent.YToRow(y + h + sy)
200 iPos = yPos = yRow = 99999
201 centerPos = y + sy + (h / 2)
b881fc78 202
d14a1e28
RD
203 for row in range(sRow,eRow + 1):
204 cy = parent.RowToRect(row)[1]
b881fc78 205
d14a1e28
RD
206 if abs(cy - centerPos) < iPos:
207 iPos = abs(cy - centerPos)
208 yRow = row
209 yPos = cy
b881fc78 210
d14a1e28
RD
211 if yRow < 0 or yRow > parent.GetNumberRows():
212 yRow = parent.GetNumberRows()
b881fc78 213
d14a1e28
RD
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):
b881fc78 223 dc = wx.PaintDC(self)
d14a1e28 224 w,h = self.GetSize()
d7403ad2 225 dc.DrawBitmap(self.image, 0,0)
b881fc78
RD
226 dc.SetPen(wx.Pen(wx.BLACK,1,wx.SOLID))
227 dc.SetBrush(wx.TRANSPARENT_BRUSH)
d7403ad2 228 dc.DrawRectangle(0,0, w,h)
d14a1e28 229 iPos = self.GetInsertionPos()
d7403ad2 230 dc.DrawLine(w - 10,iPos, w,iPos)
d14a1e28
RD
231
232#----------------------------------------------------------------------------
233
33785d9f 234class GridColMover(wx.EvtHandler):
d14a1e28 235 def __init__(self,grid):
b881fc78 236 wx.EvtHandler.__init__(self)
d14a1e28
RD
237
238 self.grid = grid
d14a1e28
RD
239 self.lwin = grid.GetGridColLabelWindow()
240 self.lwin.PushEventHandler(self)
241 self.colWin = None
242 self.ux = self.grid.GetScrollPixelsPerUnit()[0]
243 self.startX = -10
244 self.cellX = 0
245 self.didMove = False
246 self.isDragging = False
247
b881fc78
RD
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)
d14a1e28
RD
251
252 def OnMouseMove(self,evt):
253 if self.isDragging:
a6c12911 254 _rlSize = self.grid.GetRowLabelSize()
f45b8db4
RD
255 if abs(self.startX - evt.m_x) >= 3 \
256 and abs(evt.m_x - self.lastX) >= 3:
257 self.lastX = evt.m_x
d14a1e28
RD
258 self.didMove = True
259 sx,y = self.grid.GetViewStart()
b881fc78 260 w,h = self.lwin.GetClientSize()
d14a1e28 261 x = sx * self.ux
b881fc78 262
d14a1e28
RD
263 if (evt.m_x + x) < x:
264 x = evt.m_x + x
265 elif evt.m_x > w:
266 x += evt.m_x - w
b881fc78 267
d14a1e28
RD
268 if x < 1: x = 0
269 else: x /= self.ux
b881fc78 270
d14a1e28 271 if x != sx:
b881fc78 272 if wx.Platform == '__WXMSW__':
d14a1e28 273 self.colWin.Show(False)
b881fc78 274
d14a1e28 275 self.grid.Scroll(x,y)
b881fc78 276
d14a1e28
RD
277 x,y = self.lwin.ClientToScreenXY(evt.m_x,0)
278 x,y = self.grid.ScreenToClientXY(x,y)
b881fc78 279
d14a1e28
RD
280 if not self.colWin.IsShown():
281 self.colWin.Show(True)
b881fc78 282
d14a1e28 283 px = x - self.cellX
b881fc78 284
a6c12911 285 if px < 0 + _rlSize: px = 0 + _rlSize
b881fc78 286
a6c12911
RD
287 if px > w - self.colWin.GetSize()[0] + _rlSize:
288 px = w - self.colWin.GetSize()[0] + _rlSize
b881fc78 289
d14a1e28
RD
290 self.colWin.DisplayAt(px,y)
291 return
b881fc78 292
d14a1e28
RD
293
294 def OnPress(self,evt):
f45b8db4 295 self.startX = self.lastX = evt.m_x
a6c12911 296 _rlSize = self.grid.GetRowLabelSize()
d14a1e28 297 sx = self.grid.GetViewStart()[0] * self.ux
a6c12911 298 sx -= _rlSize
d14a1e28
RD
299 px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y)
300 px,py = self.grid.ScreenToClientXY(px,py)
b881fc78
RD
301
302 if self.grid.XToEdgeOfCol(px + sx) != wx.NOT_FOUND:
d14a1e28
RD
303 evt.Skip()
304 return
305
306 self.isDragging = True
307 self.didMove = False
308 col = self.grid.XToCol(px + sx)
309 rect = self.grid.ColToRect(col)
310 self.cellX = px + sx - rect.x
b881fc78 311 size = self.lwin.GetSize()
d14a1e28 312 rect.y = 0
a6c12911 313 rect.x -= sx + _rlSize
d14a1e28
RD
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()
1fa4b13e 319 evt.Skip()
d14a1e28
RD
320
321 def OnRelease(self,evt):
322 if self.isDragging:
323 self.lwin.ReleaseMouse()
324 self.colWin.Show(False)
325 self.isDragging = False
b881fc78 326
d14a1e28
RD
327 if not self.didMove:
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
a6c12911 331 sx -= self.grid.GetRowLabelSize()
d14a1e28 332 col = self.grid.XToCol(px+sx)
b881fc78
RD
333
334 if col != wx.NOT_FOUND:
d14a1e28 335 self.grid.SelectCol(col,evt.m_controlDown)
b881fc78 336
d14a1e28
RD
337 return
338 else:
339 bCol = self.colWin.GetInsertionColumn()
340 dCol = self.colWin.GetMoveColumn()
b881fc78 341 wx.PostEvent(self,
33785d9f 342 GridColMoveEvent(self.grid.GetId(), dCol, bCol))
b881fc78 343
d14a1e28
RD
344 self.colWin.Destroy()
345 evt.Skip()
346
347 def _CaptureImage(self,rect):
b881fc78
RD
348 bmp = wx.EmptyBitmap(rect.width,rect.height)
349 memdc = wx.MemoryDC()
d14a1e28 350 memdc.SelectObject(bmp)
b881fc78 351 dc = wx.WindowDC(self.lwin)
d7403ad2 352 memdc.Blit(0,0, rect.width, rect.height, dc, rect.x, rect.y)
b881fc78 353 memdc.SelectObject(wx.NullBitmap)
d14a1e28
RD
354 return bmp
355
356
33785d9f 357class GridRowMover(wx.EvtHandler):
d14a1e28 358 def __init__(self,grid):
b881fc78 359 wx.EvtHandler.__init__(self)
d14a1e28
RD
360
361 self.grid = grid
d14a1e28
RD
362 self.lwin = grid.GetGridRowLabelWindow()
363 self.lwin.PushEventHandler(self)
364 self.rowWin = None
365 self.uy = self.grid.GetScrollPixelsPerUnit()[1]
366 self.startY = -10
367 self.cellY = 0
368 self.didMove = False
369 self.isDragging = False
370
b881fc78
RD
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)
d14a1e28
RD
374
375 def OnMouseMove(self,evt):
376 if self.isDragging:
a6c12911 377 _clSize = self.grid.GetColLabelSize()
f45b8db4
RD
378 if abs(self.startY - evt.m_y) >= 3 \
379 and abs(evt.m_y - self.lastY) >= 3:
380 self.lastY = evt.m_y
d14a1e28
RD
381 self.didMove = True
382 x,sy = self.grid.GetViewStart()
383 w,h = self.lwin.GetClientSizeTuple()
384 y = sy * self.uy
b881fc78 385
d14a1e28
RD
386 if (evt.m_y + y) < y:
387 y = evt.m_y + y
388 elif evt.m_y > h:
389 y += evt.m_y - h
b881fc78
RD
390
391 if y < 1:
392 y = 0
393 else:
394 y /= self.uy
395
d14a1e28 396 if y != sy:
b881fc78 397 if wx.Platform == '__WXMSW__':
d14a1e28 398 self.rowWin.Show(False)
b881fc78 399
d14a1e28 400 self.grid.Scroll(x,y)
b881fc78 401
d14a1e28
RD
402 x,y = self.lwin.ClientToScreenXY(0,evt.m_y)
403 x,y = self.grid.ScreenToClientXY(x,y)
b881fc78 404
d14a1e28
RD
405 if not self.rowWin.IsShown():
406 self.rowWin.Show(True)
b881fc78 407
d14a1e28 408 py = y - self.cellY
b881fc78 409
a6c12911
RD
410 if py < 0 + _clSize:
411 py = 0 + _clSize
b881fc78 412
a6c12911
RD
413 if py > h - self.rowWin.GetSize()[1] + _clSize:
414 py = h - self.rowWin.GetSize()[1] + _clSize
b881fc78 415
d14a1e28
RD
416 self.rowWin.DisplayAt(x,py)
417 return
b881fc78 418
d14a1e28
RD
419
420 def OnPress(self,evt):
f45b8db4 421 self.startY = self.lastY = evt.m_y
a6c12911 422 _clSize = self.grid.GetColLabelSize()
d14a1e28 423 sy = self.grid.GetViewStart()[1] * self.uy
a6c12911 424 sy -= _clSize
d14a1e28
RD
425 px,py = self.lwin.ClientToScreenXY(evt.m_x,evt.m_y)
426 px,py = self.grid.ScreenToClientXY(px,py)
b881fc78
RD
427
428 if self.grid.YToEdgeOfRow(py + sy) != wx.NOT_FOUND:
d14a1e28
RD
429 evt.Skip()
430 return
431
432 self.isDragging = True
433 self.didMove = False
434 row = self.grid.YToRow(py + sy)
435 rect = self.grid.RowToRect(row)
436 self.cellY = py + sy - rect.y
b881fc78 437 size = self.lwin.GetSize()
d14a1e28 438 rect.x = 0
a6c12911 439 rect.y -= sy + _clSize
d14a1e28
RD
440 rect.width = size[0]
441 rowImg = self._CaptureImage(rect)
442 self.rowWin = RowDragWindow(self.grid,rowImg,row)
443 self.rowWin.Show(False)
444 self.lwin.CaptureMouse()
1fa4b13e 445 evt.Skip()
d14a1e28
RD
446
447 def OnRelease(self,evt):
448 if self.isDragging:
449 self.lwin.ReleaseMouse()
450 self.rowWin.Show(False)
451 self.isDragging = False
b881fc78 452
d14a1e28
RD
453 if not self.didMove:
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
a6c12911 457 sy -= self.grid.GetColLabelSize()
d14a1e28 458 row = self.grid.YToRow(py + sy)
b881fc78
RD
459
460 if row != wx.NOT_FOUND:
d14a1e28
RD
461 self.grid.SelectRow(row,evt.m_controlDown)
462 return
463 else:
464 bRow = self.rowWin.GetInsertionRow()
465 dRow = self.rowWin.GetMoveRow()
b881fc78
RD
466
467 wx.PostEvent(self,
33785d9f 468 GridRowMoveEvent(self.grid.GetId(), dRow, bRow))
b881fc78 469
d14a1e28
RD
470 self.rowWin.Destroy()
471 evt.Skip()
472
473 def _CaptureImage(self,rect):
b881fc78
RD
474 bmp = wx.EmptyBitmap(rect.width,rect.height)
475 memdc = wx.MemoryDC()
d14a1e28 476 memdc.SelectObject(bmp)
b881fc78 477 dc = wx.WindowDC(self.lwin)
d7403ad2 478 memdc.Blit(0,0, rect.width, rect.height, dc, rect.x, rect.y)
b881fc78 479 memdc.SelectObject(wx.NullBitmap)
d14a1e28
RD
480 return bmp
481
482
483#----------------------------------------------------------------------------