]>
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
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_class'] = self
._defChild
.__name
__
59 saveData
['_defChild_mod'] = self
._defChild
.__module
__
60 saveData
['child'] = self
.child
.GetSaveData()
63 def SetSaveData(self
,data
):
64 mod
= data
['_defChild_mod']
65 dChild
= mod
+ '.' + data
['_defChild_class']
66 exec 'import %s' % mod
67 self
._defChild
= eval(dChild
)
69 self
.child
= MultiSplit(self
,self
,wx
.Point(0,0),self
.GetSize())
70 self
.child
.SetSaveData(data
['child'])
72 self
.OnMultiSize(None)
73 self
.child
.OnSize(None)
76 #----------------------------------------------------------------------
79 class MultiSplit(wx
.Window
):
80 def __init__(self
,multiView
,parent
,pos
,size
,view1
= None):
81 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,pos
= pos
,size
= size
,
82 style
= wx
.CLIP_CHILDREN
)
83 self
.multiView
= multiView
87 self
.view1
.Reparent(self
)
88 self
.view1
.MoveXY(0,0)
90 self
.view1
= MultiViewLeaf(self
.multiView
,self
,
94 self
.Bind(wx
.EVT_SIZE
,self
.OnSize
)
96 def GetSaveData(self
):
99 saveData
['view1'] = self
.view1
.GetSaveData()
100 if isinstance(self
.view1
,MultiSplit
):
101 saveData
['view1IsSplit'] = 1
103 saveData
['view2'] = self
.view2
.GetSaveData()
104 if isinstance(self
.view2
,MultiSplit
):
105 saveData
['view2IsSplit'] = 1
106 saveData
['direction'] = self
.direction
107 v1
,v2
= self
.GetPosition()
110 v1
,v2
= self
.GetSize()
115 def SetSaveData(self
,data
):
116 self
.direction
= data
['direction']
117 self
.SetDimensions(int(data
['x']), int(data
['y']), int(data
['w']), int(data
['h']))
118 v1Data
= data
.get('view1',None)
120 isSplit
= data
.get('view1IsSplit',None)
123 self
.view1
= MultiSplit(self
.multiView
,self
,
124 (0,0),self
.GetSize())
126 self
.view1
= MultiViewLeaf(self
.multiView
,self
,
127 (0,0),self
.GetSize())
128 self
.view1
.SetSaveData(v1Data
)
131 v2Data
= data
.get('view2',None)
133 isSplit
= data
.get('view2IsSplit',None)
136 self
.view2
= MultiSplit(self
.multiView
,self
,
137 (0,0),self
.GetSize())
139 self
.view2
= MultiViewLeaf(self
.multiView
,self
,
140 (0,0),self
.GetSize())
141 self
.view2
.SetSaveData(v2Data
)
145 self
.view1
.OnSize(None)
147 self
.view2
.OnSize(None)
151 self
.view1
.UnSelect()
153 self
.view2
.UnSelect()
155 def DefaultChildChanged(self
):
157 self
.view1
.DefaultChildChanged()
159 def AddLeaf(self
,direction
,caller
,pos
):
161 if caller
== self
.view1
:
162 self
.view1
= MultiSplit(self
.multiView
,self
,
163 caller
.GetPosition(),
166 self
.view1
.AddLeaf(direction
,caller
,pos
)
168 self
.view2
= MultiSplit(self
.multiView
,self
,
169 caller
.GetPosition(),
172 self
.view2
.AddLeaf(direction
,caller
,pos
)
174 self
.direction
= direction
176 if direction
== MV_HOR
:
184 self
.view2
= MultiViewLeaf(self
.multiView
, self
, (x
,y
), (w1
,h1
))
185 self
.view1
.SetSize((w2
,h2
))
186 self
.view2
.OnSize(None)
188 def DestroyLeaf(self
,caller
):
189 if not self
.view2
: # We will only have 2 windows if
190 return # we need to destroy any
191 parent
= self
.GetParent() # Another splitview
192 if parent
== self
.multiView
: # We'r at the root
193 if caller
== self
.view1
:
195 self
.view1
= self
.view2
201 self
.view1
.SetSize(self
.GetSize())
202 self
.view1
.Move(self
.GetPosition())
205 x
,y
= self
.GetPosition()
206 if caller
== self
.view1
:
207 if self
== parent
.view1
:
208 parent
.view1
= self
.view2
210 parent
.view2
= self
.view2
211 self
.view2
.Reparent(parent
)
212 self
.view2
.SetDimensions(x
,y
,w
,h
)
214 if self
== parent
.view1
:
215 parent
.view1
= self
.view1
217 parent
.view2
= self
.view1
218 self
.view1
.Reparent(parent
)
219 self
.view1
.SetDimensions(x
,y
,w
,h
)
224 def CanSize(self
,side
,view
):
225 if self
.SizeTarget(side
,view
):
229 def SizeTarget(self
,side
,view
):
230 if self
.direction
== side
and self
.view2
and view
== self
.view1
:
232 parent
= self
.GetParent()
233 if parent
!= self
.multiView
:
234 return parent
.SizeTarget(side
,self
)
237 def SizeLeaf(self
,leaf
,pos
,side
):
238 if self
.direction
!= side
:
240 if not (self
.view1
and self
.view2
):
245 if pos
> w
- 10: return
247 if pos
> h
- 10: return
249 self
.view1
.SetDimensions(0,0,pos
,h
)
250 self
.view2
.SetDimensions(pos
,0,w
-pos
,h
)
252 self
.view1
.SetDimensions(0,0,w
,pos
)
253 self
.view2
.SetDimensions(0,pos
,w
,h
-pos
)
255 def OnSize(self
,evt
):
257 self
.view1
.SetSize(self
.GetSize())
258 self
.view1
.OnSize(None)
260 v1w
,v1h
= self
.view1
.GetSize()
261 v2w
,v2h
= self
.view2
.GetSize()
262 v1x
,v1y
= self
.view1
.GetPosition()
263 v2x
,v2y
= self
.view2
.GetPosition()
267 ratio
= float(w
) / float((v1w
+ v2w
))
275 ratio
= float(h
) / float((v1h
+ v2h
))
282 self
.view1
.SetDimensions(int(v1x
), int(v1y
), int(v1w
), int(v1h
))
283 self
.view2
.SetDimensions(int(v2x
), int(v2y
), int(v2w
), int(v2h
))
284 self
.view1
.OnSize(None)
285 self
.view2
.OnSize(None)
288 #----------------------------------------------------------------------
291 class MultiViewLeaf(wx
.Window
):
292 def __init__(self
,multiView
,parent
,pos
,size
):
293 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,pos
= pos
,size
= size
,
294 style
= wx
.CLIP_CHILDREN
)
295 self
.multiView
= multiView
297 self
.sizerHor
= MultiSizer(self
,MV_HOR
)
298 self
.sizerVer
= MultiSizer(self
,MV_VER
)
299 self
.creatorHor
= MultiCreator(self
,MV_HOR
)
300 self
.creatorVer
= MultiCreator(self
,MV_VER
)
301 self
.detail
= MultiClient(self
,multiView
._defChild
)
302 self
.closer
= MultiCloser(self
)
304 self
.Bind(wx
.EVT_SIZE
,self
.OnSize
)
306 self
.SetBackgroundColour(wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_3DFACE
))
309 def GetSaveData(self
):
311 saveData
['detailClass_class'] = self
.detail
.child
.__class
__.__name
__
312 saveData
['detailClass_mod'] = self
.detail
.child
.__module
__
313 if hasattr(self
.detail
.child
,'GetSaveData'):
314 attr
= getattr(self
.detail
.child
,'GetSaveData')
318 saveData
['detail'] = dData
319 v1
,v2
= self
.GetPosition()
322 v1
,v2
= self
.GetSize()
327 def SetSaveData(self
,data
):
328 mod
= data
['detailClass_mod']
329 dChild
= mod
+ '.' + data
['detailClass_class']
330 exec 'import %s' % mod
331 detClass
= eval(dChild
)
332 self
.SetDimensions(data
['x'],data
['y'],data
['w'],data
['h'])
334 self
.detail
= MultiClient(self
,detClass
)
335 dData
= data
.get('detail',None)
337 if hasattr(self
.detail
.child
,'SetSaveData'):
338 attr
= getattr(self
.detail
.child
,'SetSaveData')
342 self
.detail
.OnSize(None)
345 self
.detail
.UnSelect()
347 def DefaultChildChanged(self
):
348 self
.detail
.SetNewChildCls(self
.multiView
._defChild
)
350 def AddLeaf(self
,direction
,pos
):
353 if direction
== MV_VER
:
354 if pos
> h
- 10: return
356 if pos
> w
- 10: return
357 self
.GetParent().AddLeaf(direction
,self
,pos
)
359 def DestroyLeaf(self
):
360 self
.GetParent().DestroyLeaf(self
)
362 def SizeTarget(self
,side
):
363 return self
.GetParent().SizeTarget(side
,self
)
365 def CanSize(self
,side
):
366 return self
.GetParent().CanSize(side
,self
)
368 def OnSize(self
,evt
):
369 self
.sizerHor
.OnSize(evt
)
370 self
.sizerVer
.OnSize(evt
)
371 self
.creatorHor
.OnSize(evt
)
372 self
.creatorVer
.OnSize(evt
)
373 self
.detail
.OnSize(evt
)
374 self
.closer
.OnSize(evt
)
376 #----------------------------------------------------------------------
379 class MultiClient(wx
.Window
):
380 def __init__(self
,parent
,childCls
):
381 w
,h
= self
.CalcSize(parent
)
382 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
385 style
= wx
.CLIP_CHILDREN | wx
.SUNKEN_BORDER
)
386 self
.child
= childCls(self
)
387 self
.child
.MoveXY(2,2)
388 self
.normalColour
= self
.GetBackgroundColour()
389 self
.selected
= False
391 self
.Bind(wx
.EVT_SET_FOCUS
,self
.OnSetFocus
)
392 self
.Bind(wx
.EVT_CHILD_FOCUS
,self
.OnChildFocus
)
396 self
.selected
= False
397 self
.SetBackgroundColour(self
.normalColour
)
401 self
.GetParent().multiView
.UnSelect()
403 self
.SetBackgroundColour(wx
.Colour(255,255,0)) # Yellow
406 def CalcSize(self
,parent
):
407 w
,h
= parent
.GetSize()
412 def OnSize(self
,evt
):
413 w
,h
= self
.CalcSize(self
.GetParent())
414 self
.SetDimensions(0,0,w
,h
)
415 w
,h
= self
.GetClientSize()
416 self
.child
.SetSize((w
-4,h
-4))
418 def SetNewChildCls(self
,childCls
):
422 self
.child
= childCls(self
)
423 self
.child
.MoveXY(2,2)
425 def OnSetFocus(self
,evt
):
428 def OnChildFocus(self
,evt
):
430 ## from Funcs import FindFocusedChild
431 ## child = FindFocusedChild(self)
432 ## child.Bind(wx.EVT_KILL_FOCUS,self.OnChildKillFocus)
435 #----------------------------------------------------------------------
438 class MultiSizer(wx
.Window
):
439 def __init__(self
,parent
,side
):
441 x
,y
,w
,h
= self
.CalcSizePos(parent
)
442 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
445 style
= wx
.CLIP_CHILDREN
)
447 self
.px
= None # Previous X
448 self
.py
= None # Previous Y
449 self
.isDrag
= False # In Dragging
450 self
.dragTarget
= None # View being sized
452 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
453 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
454 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
455 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
456 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
458 self
.SetBackgroundColour(wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_3DFACE
))
461 def CalcSizePos(self
,parent
):
462 pw
,ph
= parent
.GetSize()
463 if self
.side
== MV_HOR
:
466 w
= pw
- CR_SIZE
- SH_SIZE
- 2
470 y
= CR_SIZE
+ 2 + SH_SIZE
472 h
= ph
- CR_SIZE
- SH_SIZE
- 4 - SH_SIZE
# For Closer
475 def OnSize(self
,evt
):
476 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
477 self
.SetDimensions(x
,y
,w
,h
)
479 def OnLeave(self
,evt
):
480 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
482 def OnEnter(self
,evt
):
483 if not self
.GetParent().CanSize(not self
.side
):
485 if self
.side
== MV_HOR
:
486 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZENS
))
488 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZEWE
))
490 def OnMouseMove(self
,evt
):
492 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
493 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
494 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
495 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
499 def OnPress(self
,evt
):
500 self
.dragTarget
= self
.GetParent().SizeTarget(not self
.side
)
503 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
504 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
505 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
510 def OnRelease(self
,evt
):
512 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
515 if self
.side
== MV_HOR
:
516 self
.dragTarget
.SizeLeaf(self
.GetParent(),
517 self
.py
,not self
.side
)
519 self
.dragTarget
.SizeLeaf(self
.GetParent(),
520 self
.px
,not self
.side
)
521 self
.dragTarget
= None
525 #----------------------------------------------------------------------
528 class MultiCreator(wx
.Window
):
529 def __init__(self
,parent
,side
):
531 x
,y
,w
,h
= self
.CalcSizePos(parent
)
532 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
535 style
= wx
.CLIP_CHILDREN
)
537 self
.px
= None # Previous X
538 self
.py
= None # Previous Y
539 self
.isDrag
= False # In Dragging
541 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
542 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
543 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
544 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
545 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
546 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
548 def CalcSizePos(self
,parent
):
549 pw
,ph
= parent
.GetSize()
550 if self
.side
== MV_HOR
:
557 y
= 4 + SH_SIZE
# Make provision for closer
562 def OnSize(self
,evt
):
563 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
564 self
.SetDimensions(x
,y
,w
,h
)
566 def OnLeave(self
,evt
):
567 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
569 def OnEnter(self
,evt
):
570 if self
.side
== MV_HOR
:
571 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_HAND
))
573 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_POINT_LEFT
))
575 def OnMouseMove(self
,evt
):
577 parent
= self
.GetParent()
578 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
579 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
580 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
581 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
585 def OnPress(self
,evt
):
587 parent
= self
.GetParent()
588 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
589 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
590 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
593 def OnRelease(self
,evt
):
595 parent
= self
.GetParent()
596 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
600 if self
.side
== MV_HOR
:
601 parent
.AddLeaf(MV_VER
,self
.py
)
603 parent
.AddLeaf(MV_HOR
,self
.px
)
607 def OnPaint(self
,evt
):
608 dc
= wx
.PaintDC(self
)
609 dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour(),wx
.SOLID
))
612 highlight
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
), 1, wx
.SOLID
)
613 shadow
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
), 1, wx
.SOLID
)
614 black
= wx
.Pen(wx
.BLACK
,1,wx
.SOLID
)
621 dc
.DrawLine(0,0, 0,h
)
622 dc
.DrawLine(0,0, w
,0)
624 dc
.DrawLine(0,h
, w
+1,h
)
625 dc
.DrawLine(w
,0, w
,h
)
627 dc
.DrawLine(w
-1,2, w
-1,h
)
629 #----------------------------------------------------------------------
632 class MultiCloser(wx
.Window
):
633 def __init__(self
,parent
):
634 x
,y
,w
,h
= self
.CalcSizePos(parent
)
635 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
638 style
= wx
.CLIP_CHILDREN
)
643 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
644 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
645 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
646 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
647 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
649 def OnLeave(self
,evt
):
650 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
653 def OnEnter(self
,evt
):
654 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_BULLSEYE
))
657 def OnPress(self
,evt
):
661 def OnRelease(self
,evt
):
662 if self
.down
and self
.entered
:
663 self
.GetParent().DestroyLeaf()
668 def OnPaint(self
,evt
):
669 dc
= wx
.PaintDC(self
)
670 dc
.SetBackground(wx
.Brush(wx
.RED
,wx
.SOLID
))
673 def CalcSizePos(self
,parent
):
674 pw
,ph
= parent
.GetSize()
681 def OnSize(self
,evt
):
682 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
683 self
.SetDimensions(x
,y
,w
,h
)
686 #----------------------------------------------------------------------
689 class EmptyChild(wx
.Window
):
690 def __init__(self
,parent
):
691 wx
.Window
.__init
__(self
,parent
,-1, style
= wx
.CLIP_CHILDREN
)
694 #----------------------------------------------------------------------
697 def DrawSash(win
,x
,y
,direction
):
699 dc
.StartDrawingOnTopWin(win
)
700 bmp
= wx
.EmptyBitmap(8,8)
702 bdc
.SelectObject(bmp
)
703 bdc
.DrawRectangle(-1,-1, 10,10)
709 brush
= wx
.Brush(wx
.Colour(0,0,0))
710 brush
.SetStipple(bmp
)
713 dc
.SetLogicalFunction(wx
.XOR
)
715 body_w
,body_h
= win
.GetClientSize()
726 if direction
== MV_HOR
:
731 x
,y
= win
.ClientToScreenXY(x
,y
)
736 if direction
== MV_HOR
:
737 dc
.DrawRectangle(x
,y
-2, w
,4)
739 dc
.DrawRectangle(x
-2,y
, 4,h
)