]>
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(int(data
['x']), int(data
['y']), int(data
['w']), int(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(int(v1x
), int(v1y
), int(v1w
), int(v1h
)) 
 282         self
.view2
.SetDimensions(int(v2x
), int(v2y
), int(v2w
), int(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
)