]>
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
):
371 self
.sizerHor
.OnSize(evt
)
372 self
.sizerVer
.OnSize(evt
)
373 self
.creatorHor
.OnSize(evt
)
374 self
.creatorVer
.OnSize(evt
)
375 self
.detail
.OnSize(evt
)
376 self
.closer
.OnSize(evt
)
379 wx
.CallAfter(doresize
)
381 #----------------------------------------------------------------------
384 class MultiClient(wx
.Window
):
385 def __init__(self
,parent
,childCls
):
386 w
,h
= self
.CalcSize(parent
)
387 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
390 style
= wx
.CLIP_CHILDREN | wx
.SUNKEN_BORDER
)
391 self
.child
= childCls(self
)
392 self
.child
.MoveXY(2,2)
393 self
.normalColour
= self
.GetBackgroundColour()
394 self
.selected
= False
396 self
.Bind(wx
.EVT_SET_FOCUS
,self
.OnSetFocus
)
397 self
.Bind(wx
.EVT_CHILD_FOCUS
,self
.OnChildFocus
)
401 self
.selected
= False
402 self
.SetBackgroundColour(self
.normalColour
)
406 self
.GetParent().multiView
.UnSelect()
408 self
.SetBackgroundColour(wx
.Colour(255,255,0)) # Yellow
411 def CalcSize(self
,parent
):
412 w
,h
= parent
.GetSize()
417 def OnSize(self
,evt
):
418 w
,h
= self
.CalcSize(self
.GetParent())
419 self
.SetDimensions(0,0,w
,h
)
420 w
,h
= self
.GetClientSize()
421 self
.child
.SetSize((w
-4,h
-4))
423 def SetNewChildCls(self
,childCls
):
427 self
.child
= childCls(self
)
428 self
.child
.MoveXY(2,2)
430 def OnSetFocus(self
,evt
):
433 def OnChildFocus(self
,evt
):
435 ## from Funcs import FindFocusedChild
436 ## child = FindFocusedChild(self)
437 ## child.Bind(wx.EVT_KILL_FOCUS,self.OnChildKillFocus)
440 #----------------------------------------------------------------------
443 class MultiSizer(wx
.Window
):
444 def __init__(self
,parent
,side
):
446 x
,y
,w
,h
= self
.CalcSizePos(parent
)
447 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
450 style
= wx
.CLIP_CHILDREN
)
452 self
.px
= None # Previous X
453 self
.py
= None # Previous Y
454 self
.isDrag
= False # In Dragging
455 self
.dragTarget
= None # View being sized
457 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
458 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
459 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
460 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
461 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
463 self
.SetBackgroundColour(wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_3DFACE
))
466 def CalcSizePos(self
,parent
):
467 pw
,ph
= parent
.GetSize()
468 if self
.side
== MV_HOR
:
471 w
= pw
- CR_SIZE
- SH_SIZE
- 2
475 y
= CR_SIZE
+ 2 + SH_SIZE
477 h
= ph
- CR_SIZE
- SH_SIZE
- 4 - SH_SIZE
# For Closer
480 def OnSize(self
,evt
):
481 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
482 self
.SetDimensions(x
,y
,w
,h
)
484 def OnLeave(self
,evt
):
485 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
487 def OnEnter(self
,evt
):
488 if not self
.GetParent().CanSize(not self
.side
):
490 if self
.side
== MV_HOR
:
491 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZENS
))
493 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZEWE
))
495 def OnMouseMove(self
,evt
):
497 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
498 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
499 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
500 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
504 def OnPress(self
,evt
):
505 self
.dragTarget
= self
.GetParent().SizeTarget(not self
.side
)
508 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
509 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
510 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
515 def OnRelease(self
,evt
):
517 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
520 if self
.side
== MV_HOR
:
521 self
.dragTarget
.SizeLeaf(self
.GetParent(),
522 self
.py
,not self
.side
)
524 self
.dragTarget
.SizeLeaf(self
.GetParent(),
525 self
.px
,not self
.side
)
526 self
.dragTarget
= None
530 #----------------------------------------------------------------------
533 class MultiCreator(wx
.Window
):
534 def __init__(self
,parent
,side
):
536 x
,y
,w
,h
= self
.CalcSizePos(parent
)
537 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
540 style
= wx
.CLIP_CHILDREN
)
542 self
.px
= None # Previous X
543 self
.py
= None # Previous Y
544 self
.isDrag
= False # In Dragging
546 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
547 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
548 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
549 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
550 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
551 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
553 def CalcSizePos(self
,parent
):
554 pw
,ph
= parent
.GetSize()
555 if self
.side
== MV_HOR
:
562 y
= 4 + SH_SIZE
# Make provision for closer
567 def OnSize(self
,evt
):
568 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
569 self
.SetDimensions(x
,y
,w
,h
)
571 def OnLeave(self
,evt
):
572 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
574 def OnEnter(self
,evt
):
575 if self
.side
== MV_HOR
:
576 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_HAND
))
578 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_POINT_LEFT
))
580 def OnMouseMove(self
,evt
):
582 parent
= self
.GetParent()
583 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
584 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
585 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
586 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
590 def OnPress(self
,evt
):
592 parent
= self
.GetParent()
593 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
594 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
595 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
598 def OnRelease(self
,evt
):
600 parent
= self
.GetParent()
601 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
605 if self
.side
== MV_HOR
:
606 parent
.AddLeaf(MV_VER
,self
.py
)
608 parent
.AddLeaf(MV_HOR
,self
.px
)
612 def OnPaint(self
,evt
):
613 dc
= wx
.PaintDC(self
)
614 dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour(),wx
.SOLID
))
617 highlight
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
), 1, wx
.SOLID
)
618 shadow
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
), 1, wx
.SOLID
)
619 black
= wx
.Pen(wx
.BLACK
,1,wx
.SOLID
)
626 dc
.DrawLine(0,0, 0,h
)
627 dc
.DrawLine(0,0, w
,0)
629 dc
.DrawLine(0,h
, w
+1,h
)
630 dc
.DrawLine(w
,0, w
,h
)
632 dc
.DrawLine(w
-1,2, w
-1,h
)
634 #----------------------------------------------------------------------
637 class MultiCloser(wx
.Window
):
638 def __init__(self
,parent
):
639 x
,y
,w
,h
= self
.CalcSizePos(parent
)
640 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
643 style
= wx
.CLIP_CHILDREN
)
648 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
649 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
650 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
651 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
652 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
654 def OnLeave(self
,evt
):
655 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
658 def OnEnter(self
,evt
):
659 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_BULLSEYE
))
662 def OnPress(self
,evt
):
666 def OnRelease(self
,evt
):
667 if self
.down
and self
.entered
:
668 self
.GetParent().DestroyLeaf()
673 def OnPaint(self
,evt
):
674 dc
= wx
.PaintDC(self
)
675 dc
.SetBackground(wx
.Brush(wx
.RED
,wx
.SOLID
))
678 def CalcSizePos(self
,parent
):
679 pw
,ph
= parent
.GetSize()
686 def OnSize(self
,evt
):
687 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
688 self
.SetDimensions(x
,y
,w
,h
)
691 #----------------------------------------------------------------------
694 class EmptyChild(wx
.Window
):
695 def __init__(self
,parent
):
696 wx
.Window
.__init
__(self
,parent
,-1, style
= wx
.CLIP_CHILDREN
)
699 #----------------------------------------------------------------------
702 def DrawSash(win
,x
,y
,direction
):
704 dc
.StartDrawingOnTopWin(win
)
705 bmp
= wx
.EmptyBitmap(8,8)
707 bdc
.SelectObject(bmp
)
708 bdc
.DrawRectangle(-1,-1, 10,10)
714 brush
= wx
.Brush(wx
.Colour(0,0,0))
715 brush
.SetStipple(bmp
)
718 dc
.SetLogicalFunction(wx
.XOR
)
720 body_w
,body_h
= win
.GetClientSize()
731 if direction
== MV_HOR
:
736 x
,y
= win
.ClientToScreenXY(x
,y
)
741 if direction
== MV_HOR
:
742 dc
.DrawRectangle(x
,y
-2, w
,4)
744 dc
.DrawRectangle(x
-2,y
, 4,h
)