]>
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
))