]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/multisash.py
   1 #---------------------------------------------------------------------- 
   3 # Purpose:      Multi Sash control 
   5 # Author:       Gerrit van Dyk 
  10 # License:      wxWindows license 
  11 #---------------------------------------------------------------------- 
  12 # 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net) 
  14 # o 2.5 compatability update. 
  16 # 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net) 
  18 # o wxMultiSash -> MultiSash 
  19 # o wxMultiSplit -> MultiSplit wxMultiViewLeaf 
  20 # o wxMultiViewLeaf -> MultiViewLeaf 
  31 #---------------------------------------------------------------------- 
  33 class MultiSash(wx
.Window
): 
  34     def __init__(self
, *_args
,**_kwargs
): 
  35         apply(wx
.Window
.__init
__,(self
,) + _args
,_kwargs
) 
  36         self
._defChild 
= EmptyChild
 
  37         self
.child 
= MultiSplit(self
,self
,(0,0),self
.GetSize()) 
  38         self
.Bind(wx
.EVT_SIZE
,self
.OnMultiSize
) 
  40     def SetDefaultChildClass(self
,childCls
): 
  41         self
._defChild 
= childCls
 
  42         self
.child
.DefaultChildChanged() 
  44     def OnMultiSize(self
,evt
): 
  45         self
.child
.SetSize(self
.GetSize()) 
  52         self
.child 
= MultiSplit(self
,self
,(0,0),self
.GetSize()) 
  54         self
.child
.OnSize(None) 
  56     def GetSaveData(self
): 
  58         saveData
['_defChild'] = str(self
._defChild
) 
  59         saveData
['child'] = self
.child
.GetSaveData() 
  62     def SetSaveData(self
,data
): 
  63         dChild 
= data
['_defChild'] 
  64         mod 
= dChild
.split('.')[0] 
  65         exec 'import %s' % mod
 
  66         self
._defChild 
= eval(dChild
) 
  68         self
.child 
= MultiSplit(self
,self
,wxPoint(0,0),self
.GetSize()) 
  69         self
.child
.SetSaveData(data
['child']) 
  71         self
.OnMultiSize(None) 
  72         self
.child
.OnSize(None) 
  75 #---------------------------------------------------------------------- 
  78 class MultiSplit(wx
.Window
): 
  79     def __init__(self
,multiView
,parent
,pos
,size
,view1 
= None): 
  80         wx
.Window
.__init
__(self
,id = -1,parent 
= parent
,pos 
= pos
,size 
= size
, 
  81                           style 
= wx
.CLIP_CHILDREN
) 
  82         self
.multiView 
= multiView
 
  86             self
.view1
.Reparent(self
) 
  87             self
.view1
.MoveXY(0,0) 
  89             self
.view1 
= MultiViewLeaf(self
.multiView
,self
, 
  93         self
.Bind(wx
.EVT_SIZE
,self
.OnSize
) 
  95     def GetSaveData(self
): 
  98             saveData
['view1'] = self
.view1
.GetSaveData() 
  99             if isinstance(self
.view1
,MultiSplit
): 
 100                 saveData
['view1IsSplit'] = 1 
 102             saveData
['view2'] = self
.view2
.GetSaveData() 
 103             if isinstance(self
.view2
,MultiSplit
): 
 104                 saveData
['view2IsSplit'] = 1 
 105         saveData
['direction'] = self
.direction
 
 106         v1
,v2 
= self
.GetPosition() 
 109         v1
,v2 
= self
.GetSize() 
 114     def SetSaveData(self
,data
): 
 115         self
.direction 
= data
['direction'] 
 116         self
.SetDimensions(data
['x'],data
['y'],data
['w'],data
['h']) 
 117         v1Data 
= data
.get('view1',None) 
 119             isSplit 
= data
.get('view1IsSplit',None) 
 122                 self
.view1 
= MultiSplit(self
.multiView
,self
, 
 123                                           (0,0),self
.GetSize()) 
 125                 self
.view1 
= MultiViewLeaf(self
.multiView
,self
, 
 126                                              (0,0),self
.GetSize()) 
 127             self
.view1
.SetSaveData(v1Data
) 
 130         v2Data 
= data
.get('view2',None) 
 132             isSplit 
= data
.get('view2IsSplit',None) 
 135                 self
.view2 
= MultiSplit(self
.multiView
,self
, 
 136                                           (0,0),self
.GetSize()) 
 138                 self
.view2 
= MultiViewLeaf(self
.multiView
,self
, 
 139                                              (0,0),self
.GetSize()) 
 140             self
.view2
.SetSaveData(v2Data
) 
 144             self
.view1
.OnSize(None) 
 146             self
.view2
.OnSize(None) 
 150             self
.view1
.UnSelect() 
 152             self
.view2
.UnSelect() 
 154     def DefaultChildChanged(self
): 
 156             self
.view1
.DefaultChildChanged() 
 158     def AddLeaf(self
,direction
,caller
,pos
): 
 160             if caller 
== self
.view1
: 
 161                 self
.view1 
= MultiSplit(self
.multiView
,self
, 
 162                                           caller
.GetPosition(), 
 165                 self
.view1
.AddLeaf(direction
,caller
,pos
) 
 167                 self
.view2 
= MultiSplit(self
.multiView
,self
, 
 168                                           caller
.GetPosition(), 
 171                 self
.view2
.AddLeaf(direction
,caller
,pos
) 
 173             self
.direction 
= direction
 
 175             if direction 
== MV_HOR
: 
 183             self
.view2 
= MultiViewLeaf(self
.multiView
, self
, (x
,y
), (w1
,h1
)) 
 184             self
.view1
.SetSize((w2
,h2
)) 
 185             self
.view2
.OnSize(None) 
 187     def DestroyLeaf(self
,caller
): 
 188         if not self
.view2
:              # We will only have 2 windows if 
 189             return                      # we need to destroy any 
 190         parent 
= self
.GetParent()       # Another splitview 
 191         if parent 
== self
.multiView
:    # We'r at the root 
 192             if caller 
== self
.view1
: 
 194                 self
.view1 
= self
.view2
 
 200             self
.view1
.SetSize(self
.GetSize()) 
 201             self
.view1
.Move(self
.GetPosition()) 
 204             x
,y 
= self
.GetPosition() 
 205             if caller 
== self
.view1
: 
 206                 if self 
== parent
.view1
: 
 207                     parent
.view1 
= self
.view2
 
 209                     parent
.view2 
= self
.view2
 
 210                 self
.view2
.Reparent(parent
) 
 211                 self
.view2
.SetDimensions(x
,y
,w
,h
) 
 213                 if self 
== parent
.view1
: 
 214                     parent
.view1 
= self
.view1
 
 216                     parent
.view2 
= self
.view1
 
 217                 self
.view1
.Reparent(parent
) 
 218                 self
.view1
.SetDimensions(x
,y
,w
,h
) 
 223     def CanSize(self
,side
,view
): 
 224         if self
.SizeTarget(side
,view
): 
 228     def SizeTarget(self
,side
,view
): 
 229         if self
.direction 
== side 
and self
.view2 
and view 
== self
.view1
: 
 231         parent 
= self
.GetParent() 
 232         if parent 
!= self
.multiView
: 
 233             return parent
.SizeTarget(side
,self
) 
 236     def SizeLeaf(self
,leaf
,pos
,side
): 
 237         if self
.direction 
!= side
: 
 239         if not (self
.view1 
and self
.view2
): 
 244             if pos 
> w 
- 10: return 
 246             if pos 
> h 
- 10: return 
 248             self
.view1
.SetDimensions(0,0,pos
,h
) 
 249             self
.view2
.SetDimensions(pos
,0,w
-pos
,h
) 
 251             self
.view1
.SetDimensions(0,0,w
,pos
) 
 252             self
.view2
.SetDimensions(0,pos
,w
,h
-pos
) 
 254     def OnSize(self
,evt
): 
 256             self
.view1
.SetSize(self
.GetSize()) 
 257             self
.view1
.OnSize(None) 
 259         v1w
,v1h 
= self
.view1
.GetSize() 
 260         v2w
,v2h 
= self
.view2
.GetSize() 
 261         v1x
,v1y 
= self
.view1
.GetPosition() 
 262         v2x
,v2y 
= self
.view2
.GetPosition() 
 266             ratio 
= float(w
) / float((v1w 
+ v2w
)) 
 274             ratio 
= float(h
) / float((v1h 
+ v2h
)) 
 281         self
.view1
.SetDimensions(v1x
,v1y
,v1w
,v1h
) 
 282         self
.view2
.SetDimensions(v2x
,v2y
,v2w
,v2h
) 
 283         self
.view1
.OnSize(None) 
 284         self
.view2
.OnSize(None) 
 287 #---------------------------------------------------------------------- 
 290 class MultiViewLeaf(wx
.Window
): 
 291     def __init__(self
,multiView
,parent
,pos
,size
): 
 292         wx
.Window
.__init
__(self
,id = -1,parent 
= parent
,pos 
= pos
,size 
= size
, 
 293                           style 
= wx
.CLIP_CHILDREN
) 
 294         self
.multiView 
= multiView
 
 296         self
.sizerHor 
= MultiSizer(self
,MV_HOR
) 
 297         self
.sizerVer 
= MultiSizer(self
,MV_VER
) 
 298         self
.creatorHor 
= MultiCreator(self
,MV_HOR
) 
 299         self
.creatorVer 
= MultiCreator(self
,MV_VER
) 
 300         self
.detail 
= MultiClient(self
,multiView
._defChild
) 
 301         self
.closer 
= MultiCloser(self
) 
 303         self
.Bind(wx
.EVT_SIZE
,self
.OnSize
) 
 305     def GetSaveData(self
): 
 307         saveData
['detailClass'] = str(self
.detail
.child
.__class
__) 
 308         if hasattr(self
.detail
.child
,'GetSaveData'): 
 309             attr 
= getattr(self
.detail
.child
,'GetSaveData') 
 313                     saveData
['detail'] = dData
 
 314         v1
,v2 
= self
.GetPosition() 
 317         v1
,v2 
= self
.GetSize() 
 322     def SetSaveData(self
,data
): 
 323         dChild 
= data
['detailClass'] 
 324         mod 
= dChild
.split('.')[0] 
 325         exec 'import %s' % mod
 
 326         detClass 
= eval(dChild
) 
 327         self
.SetDimensions(data
['x'],data
['y'],data
['w'],data
['h']) 
 329         self
.detail 
= MultiClient(self
,detClass
) 
 330         dData 
= data
.get('detail',None) 
 332             if hasattr(self
.detail
.child
,'SetSaveData'): 
 333                 attr 
= getattr(self
.detail
.child
,'SetSaveData') 
 337         self
.detail
.OnSize(None) 
 340         self
.detail
.UnSelect() 
 342     def DefaultChildChanged(self
): 
 343         self
.detail
.SetNewChildCls(self
.multiView
._defChild
) 
 345     def AddLeaf(self
,direction
,pos
): 
 348         if direction 
== MV_VER
: 
 349             if pos 
> h 
- 10: return 
 351             if pos 
> w 
- 10: return 
 352         self
.GetParent().AddLeaf(direction
,self
,pos
) 
 354     def DestroyLeaf(self
): 
 355         self
.GetParent().DestroyLeaf(self
) 
 357     def SizeTarget(self
,side
): 
 358         return self
.GetParent().SizeTarget(side
,self
) 
 360     def CanSize(self
,side
): 
 361         return self
.GetParent().CanSize(side
,self
) 
 363     def OnSize(self
,evt
): 
 364         self
.sizerHor
.OnSize(evt
) 
 365         self
.sizerVer
.OnSize(evt
) 
 366         self
.creatorHor
.OnSize(evt
) 
 367         self
.creatorVer
.OnSize(evt
) 
 368         self
.detail
.OnSize(evt
) 
 369         self
.closer
.OnSize(evt
) 
 371 #---------------------------------------------------------------------- 
 374 class MultiClient(wx
.Window
): 
 375     def __init__(self
,parent
,childCls
): 
 376         w
,h 
= self
.CalcSize(parent
) 
 377         wx
.Window
.__init
__(self
,id = -1,parent 
= parent
, 
 380                           style 
= wx
.CLIP_CHILDREN | wx
.SUNKEN_BORDER
) 
 381         self
.child 
= childCls(self
) 
 382         self
.child
.MoveXY(2,2) 
 383         self
.normalColour 
= self
.GetBackgroundColour() 
 384         self
.selected 
= False 
 386         self
.Bind(wx
.EVT_SET_FOCUS
,self
.OnSetFocus
) 
 387         self
.Bind(wx
.EVT_CHILD_FOCUS
,self
.OnChildFocus
) 
 391             self
.selected 
= False 
 392             self
.SetBackgroundColour(self
.normalColour
) 
 396         self
.GetParent().multiView
.UnSelect() 
 398         self
.SetBackgroundColour(wx
.Colour(255,255,0)) # Yellow 
 401     def CalcSize(self
,parent
): 
 402         w
,h 
= parent
.GetSize() 
 407     def OnSize(self
,evt
): 
 408         w
,h 
= self
.CalcSize(self
.GetParent()) 
 409         self
.SetDimensions(0,0,w
,h
) 
 410         w
,h 
= self
.GetClientSize() 
 411         self
.child
.SetSize((w
-4,h
-4)) 
 413     def SetNewChildCls(self
,childCls
): 
 417         self
.child 
= childCls(self
) 
 418         self
.child
.MoveXY(2,2) 
 420     def OnSetFocus(self
,evt
): 
 423     def OnChildFocus(self
,evt
): 
 425 ##        from Funcs import FindFocusedChild 
 426 ##        child = FindFocusedChild(self) 
 427 ##        child.Bind(wx.EVT_KILL_FOCUS,self.OnChildKillFocus) 
 430 #---------------------------------------------------------------------- 
 433 class MultiSizer(wx
.Window
): 
 434     def __init__(self
,parent
,side
): 
 436         x
,y
,w
,h 
= self
.CalcSizePos(parent
) 
 437         wx
.Window
.__init
__(self
,id = -1,parent 
= parent
, 
 440                           style 
= wx
.CLIP_CHILDREN
) 
 442         self
.px 
= None                  # Previous X 
 443         self
.py 
= None                  # Previous Y 
 444         self
.isDrag 
= False             # In Dragging 
 445         self
.dragTarget 
= None          # View being sized 
 447         self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
) 
 448         self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
) 
 449         self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
) 
 450         self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
) 
 451         self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
) 
 453     def CalcSizePos(self
,parent
): 
 454         pw
,ph 
= parent
.GetSize() 
 455         if self
.side 
== MV_HOR
: 
 458             w 
= pw 
- CR_SIZE 
- SH_SIZE 
- 2 
 462             y 
= CR_SIZE 
+ 2 + SH_SIZE
 
 464             h 
= ph 
- CR_SIZE 
- SH_SIZE 
- 4 - SH_SIZE 
# For Closer 
 467     def OnSize(self
,evt
): 
 468         x
,y
,w
,h 
= self
.CalcSizePos(self
.GetParent()) 
 469         self
.SetDimensions(x
,y
,w
,h
) 
 471     def OnLeave(self
,evt
): 
 472         self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
)) 
 474     def OnEnter(self
,evt
): 
 475         if not self
.GetParent().CanSize(not self
.side
): 
 477         if self
.side 
== MV_HOR
: 
 478             self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZENS
)) 
 480             self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZEWE
)) 
 482     def OnMouseMove(self
,evt
): 
 484             DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
) 
 485             self
.px
,self
.py 
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
) 
 486             self
.px
,self
.py 
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
) 
 487             DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
) 
 491     def OnPress(self
,evt
): 
 492         self
.dragTarget 
= self
.GetParent().SizeTarget(not self
.side
) 
 495             self
.px
,self
.py 
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
) 
 496             self
.px
,self
.py 
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
) 
 497             DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
) 
 502     def OnRelease(self
,evt
): 
 504             DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
) 
 507             if self
.side 
== MV_HOR
: 
 508                 self
.dragTarget
.SizeLeaf(self
.GetParent(), 
 509                                          self
.py
,not self
.side
) 
 511                 self
.dragTarget
.SizeLeaf(self
.GetParent(), 
 512                                          self
.px
,not self
.side
) 
 513             self
.dragTarget 
= None 
 517 #---------------------------------------------------------------------- 
 520 class MultiCreator(wx
.Window
): 
 521     def __init__(self
,parent
,side
): 
 523         x
,y
,w
,h 
= self
.CalcSizePos(parent
) 
 524         wx
.Window
.__init
__(self
,id = -1,parent 
= parent
, 
 527                           style 
= wx
.CLIP_CHILDREN
) 
 529         self
.px 
= None                  # Previous X 
 530         self
.py 
= None                  # Previous Y 
 531         self
.isDrag 
= False           # In Dragging 
 533         self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
) 
 534         self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
) 
 535         self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
) 
 536         self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
) 
 537         self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
) 
 538         self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
) 
 540     def CalcSizePos(self
,parent
): 
 541         pw
,ph 
= parent
.GetSize() 
 542         if self
.side 
== MV_HOR
: 
 549             y 
= 4 + SH_SIZE             
# Make provision for closer 
 554     def OnSize(self
,evt
): 
 555         x
,y
,w
,h 
= self
.CalcSizePos(self
.GetParent()) 
 556         self
.SetDimensions(x
,y
,w
,h
) 
 558     def OnLeave(self
,evt
): 
 559         self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
)) 
 561     def OnEnter(self
,evt
): 
 562         if self
.side 
== MV_HOR
: 
 563             self
.SetCursor(wx
.StockCursor(wx
.CURSOR_HAND
)) 
 565             self
.SetCursor(wx
.StockCursor(wx
.CURSOR_POINT_LEFT
)) 
 567     def OnMouseMove(self
,evt
): 
 569             parent 
= self
.GetParent() 
 570             DrawSash(parent
,self
.px
,self
.py
,self
.side
) 
 571             self
.px
,self
.py 
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
) 
 572             self
.px
,self
.py 
= parent
.ScreenToClientXY(self
.px
,self
.py
) 
 573             DrawSash(parent
,self
.px
,self
.py
,self
.side
) 
 577     def OnPress(self
,evt
): 
 579         parent 
= self
.GetParent() 
 580         self
.px
,self
.py 
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
) 
 581         self
.px
,self
.py 
= parent
.ScreenToClientXY(self
.px
,self
.py
) 
 582         DrawSash(parent
,self
.px
,self
.py
,self
.side
) 
 585     def OnRelease(self
,evt
): 
 587             parent 
= self
.GetParent() 
 588             DrawSash(parent
,self
.px
,self
.py
,self
.side
) 
 592             if self
.side 
== MV_HOR
: 
 593                 parent
.AddLeaf(MV_VER
,self
.py
) 
 595                 parent
.AddLeaf(MV_HOR
,self
.px
) 
 599     def OnPaint(self
,evt
): 
 600         dc 
= wx
.PaintDC(self
) 
 601         dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour(),wx
.SOLID
)) 
 604         highlight 
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
), 1, wx
.SOLID
) 
 605         shadow 
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
), 1, wx
.SOLID
) 
 606         black 
= wx
.Pen(wx
.BLACK
,1,wx
.SOLID
) 
 613         dc
.DrawLine((0,0), (0,h
)) 
 614         dc
.DrawLine((0,0), (w
,0)) 
 616         dc
.DrawLine((0,h
), (w
+1,h
)) 
 617         dc
.DrawLine((w
,0), (w
,h
)) 
 619         dc
.DrawLine((w
-1,2), (w
-1,h
)) 
 621 #---------------------------------------------------------------------- 
 624 class MultiCloser(wx
.Window
): 
 625     def __init__(self
,parent
): 
 626         x
,y
,w
,h 
= self
.CalcSizePos(parent
) 
 627         wx
.Window
.__init
__(self
,id = -1,parent 
= parent
, 
 630                           style 
= wx
.CLIP_CHILDREN
) 
 635         self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
) 
 636         self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
) 
 637         self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
) 
 638         self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
) 
 639         self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
) 
 641     def OnLeave(self
,evt
): 
 642         self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
)) 
 645     def OnEnter(self
,evt
): 
 646         self
.SetCursor(wx
.StockCursor(wx
.CURSOR_BULLSEYE
)) 
 649     def OnPress(self
,evt
): 
 653     def OnRelease(self
,evt
): 
 654         if self
.down 
and self
.entered
: 
 655             self
.GetParent().DestroyLeaf() 
 660     def OnPaint(self
,evt
): 
 661         dc 
= wx
.PaintDC(self
) 
 662         dc
.SetBackground(wx
.Brush(wx
.RED
,wx
.SOLID
)) 
 665     def CalcSizePos(self
,parent
): 
 666         pw
,ph 
= parent
.GetSize() 
 673     def OnSize(self
,evt
): 
 674         x
,y
,w
,h 
= self
.CalcSizePos(self
.GetParent()) 
 675         self
.SetDimensions(x
,y
,w
,h
) 
 678 #---------------------------------------------------------------------- 
 681 class EmptyChild(wx
.Window
): 
 682     def __init__(self
,parent
): 
 683         wx
.Window
.__init
__(self
,parent
,-1, style 
= wx
.CLIP_CHILDREN
) 
 686 #---------------------------------------------------------------------- 
 689 def DrawSash(win
,x
,y
,direction
): 
 691     dc
.StartDrawingOnTopWin(win
) 
 692     bmp 
= wx
.EmptyBitmap(8,8) 
 694     bdc
.SelectObject(bmp
) 
 695     bdc
.DrawRectangle((-1,-1), (10,10)) 
 701     brush 
= wx
.Brush(wx
.Colour(0,0,0)) 
 702     brush
.SetStipple(bmp
) 
 705     dc
.SetLogicalFunction(wx
.XOR
) 
 707     body_w
,body_h 
= win
.GetClientSize() 
 718     if direction 
== MV_HOR
: 
 723     x
,y 
= win
.ClientToScreenXY(x
,y
) 
 728     if direction 
== MV_HOR
: 
 729         dc
.DrawRectangle((x
,y
-2), (w
,4)) 
 731         dc
.DrawRectangle((x
-2,y
), (4,h
))