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 #----------------------------------------------------------------------------