]>
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 licensie
11 #----------------------------------------------------------------------
12 # 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14 # o 2.5 compatability update.
25 #----------------------------------------------------------------------
27 class wxMultiSash(wx
.Window
):
28 def __init__(self
, *_args
,**_kwargs
):
29 apply(wx
.Window
.__init
__,(self
,) + _args
,_kwargs
)
30 self
._defChild
= EmptyChild
31 self
.child
= wxMultiSplit(self
,self
,(0,0),self
.GetSize())
32 self
.Bind(wx
.EVT_SIZE
,self
.OnMultiSize
)
34 def SetDefaultChildClass(self
,childCls
):
35 self
._defChild
= childCls
36 self
.child
.DefaultChildChanged()
38 def OnMultiSize(self
,evt
):
39 self
.child
.SetSize(self
.GetSize())
46 self
.child
= wxMultiSplit(self
,self
,(0,0),self
.GetSize())
48 self
.child
.OnSize(None)
50 def GetSaveData(self
):
52 saveData
['_defChild'] = str(self
._defChild
)
53 saveData
['child'] = self
.child
.GetSaveData()
56 def SetSaveData(self
,data
):
57 dChild
= data
['_defChild']
58 mod
= dChild
.split('.')[0]
59 exec 'import %s' % mod
60 self
._defChild
= eval(dChild
)
62 self
.child
= wxMultiSplit(self
,self
,wxPoint(0,0),self
.GetSize())
63 self
.child
.SetSaveData(data
['child'])
65 self
.OnMultiSize(None)
66 self
.child
.OnSize(None)
69 #----------------------------------------------------------------------
72 class wxMultiSplit(wx
.Window
):
73 def __init__(self
,multiView
,parent
,pos
,size
,view1
= None):
74 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,pos
= pos
,size
= size
,
75 style
= wx
.CLIP_CHILDREN
)
76 self
.multiView
= multiView
80 self
.view1
.Reparent(self
)
81 self
.view1
.MoveXY(0,0)
83 self
.view1
= wxMultiViewLeaf(self
.multiView
,self
,
87 self
.Bind(wx
.EVT_SIZE
,self
.OnSize
)
89 def GetSaveData(self
):
92 saveData
['view1'] = self
.view1
.GetSaveData()
93 if isinstance(self
.view1
,wxMultiSplit
):
94 saveData
['view1IsSplit'] = 1
96 saveData
['view2'] = self
.view2
.GetSaveData()
97 if isinstance(self
.view2
,wxMultiSplit
):
98 saveData
['view2IsSplit'] = 1
99 saveData
['direction'] = self
.direction
100 v1
,v2
= self
.GetPosition()
103 v1
,v2
= self
.GetSize()
108 def SetSaveData(self
,data
):
109 self
.direction
= data
['direction']
110 self
.SetDimensions(data
['x'],data
['y'],data
['w'],data
['h'])
111 v1Data
= data
.get('view1',None)
113 isSplit
= data
.get('view1IsSplit',None)
116 self
.view1
= wxMultiSplit(self
.multiView
,self
,
117 (0,0),self
.GetSize())
119 self
.view1
= wxMultiViewLeaf(self
.multiView
,self
,
120 (0,0),self
.GetSize())
121 self
.view1
.SetSaveData(v1Data
)
124 v2Data
= data
.get('view2',None)
126 isSplit
= data
.get('view2IsSplit',None)
129 self
.view2
= wxMultiSplit(self
.multiView
,self
,
130 (0,0),self
.GetSize())
132 self
.view2
= wxMultiViewLeaf(self
.multiView
,self
,
133 (0,0),self
.GetSize())
134 self
.view2
.SetSaveData(v2Data
)
138 self
.view1
.OnSize(None)
140 self
.view2
.OnSize(None)
144 self
.view1
.UnSelect()
146 self
.view2
.UnSelect()
148 def DefaultChildChanged(self
):
150 self
.view1
.DefaultChildChanged()
152 def AddLeaf(self
,direction
,caller
,pos
):
154 if caller
== self
.view1
:
155 self
.view1
= wxMultiSplit(self
.multiView
,self
,
156 caller
.GetPosition(),
159 self
.view1
.AddLeaf(direction
,caller
,pos
)
161 self
.view2
= wxMultiSplit(self
.multiView
,self
,
162 caller
.GetPosition(),
165 self
.view2
.AddLeaf(direction
,caller
,pos
)
167 self
.direction
= direction
169 if direction
== MV_HOR
:
177 self
.view2
= wxMultiViewLeaf(self
.multiView
, self
, (x
,y
), (w1
,h1
))
178 self
.view1
.SetSize((w2
,h2
))
179 self
.view2
.OnSize(None)
181 def DestroyLeaf(self
,caller
):
182 if not self
.view2
: # We will only have 2 windows if
183 return # we need to destroy any
184 parent
= self
.GetParent() # Another splitview
185 if parent
== self
.multiView
: # We'r at the root
186 if caller
== self
.view1
:
188 self
.view1
= self
.view2
194 self
.view1
.SetSize(self
.GetSize())
195 self
.view1
.Move(self
.GetPosition())
198 x
,y
= self
.GetPosition()
199 if caller
== self
.view1
:
200 if self
== parent
.view1
:
201 parent
.view1
= self
.view2
203 parent
.view2
= self
.view2
204 self
.view2
.Reparent(parent
)
205 self
.view2
.SetDimensions(x
,y
,w
,h
)
207 if self
== parent
.view1
:
208 parent
.view1
= self
.view1
210 parent
.view2
= self
.view1
211 self
.view1
.Reparent(parent
)
212 self
.view1
.SetDimensions(x
,y
,w
,h
)
217 def CanSize(self
,side
,view
):
218 if self
.SizeTarget(side
,view
):
222 def SizeTarget(self
,side
,view
):
223 if self
.direction
== side
and self
.view2
and view
== self
.view1
:
225 parent
= self
.GetParent()
226 if parent
!= self
.multiView
:
227 return parent
.SizeTarget(side
,self
)
230 def SizeLeaf(self
,leaf
,pos
,side
):
231 if self
.direction
!= side
:
233 if not (self
.view1
and self
.view2
):
238 if pos
> w
- 10: return
240 if pos
> h
- 10: return
242 self
.view1
.SetDimensions(0,0,pos
,h
)
243 self
.view2
.SetDimensions(pos
,0,w
-pos
,h
)
245 self
.view1
.SetDimensions(0,0,w
,pos
)
246 self
.view2
.SetDimensions(0,pos
,w
,h
-pos
)
248 def OnSize(self
,evt
):
250 self
.view1
.SetSize(self
.GetSize())
251 self
.view1
.OnSize(None)
253 v1w
,v1h
= self
.view1
.GetSize()
254 v2w
,v2h
= self
.view2
.GetSize()
255 v1x
,v1y
= self
.view1
.GetPosition()
256 v2x
,v2y
= self
.view2
.GetPosition()
260 ratio
= float(w
) / float((v1w
+ v2w
))
268 ratio
= float(h
) / float((v1h
+ v2h
))
275 self
.view1
.SetDimensions(v1x
,v1y
,v1w
,v1h
)
276 self
.view2
.SetDimensions(v2x
,v2y
,v2w
,v2h
)
277 self
.view1
.OnSize(None)
278 self
.view2
.OnSize(None)
281 #----------------------------------------------------------------------
284 class wxMultiViewLeaf(wx
.Window
):
285 def __init__(self
,multiView
,parent
,pos
,size
):
286 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,pos
= pos
,size
= size
,
287 style
= wx
.CLIP_CHILDREN
)
288 self
.multiView
= multiView
290 self
.sizerHor
= MultiSizer(self
,MV_HOR
)
291 self
.sizerVer
= MultiSizer(self
,MV_VER
)
292 self
.creatorHor
= MultiCreator(self
,MV_HOR
)
293 self
.creatorVer
= MultiCreator(self
,MV_VER
)
294 self
.detail
= MultiClient(self
,multiView
._defChild
)
295 self
.closer
= MultiCloser(self
)
297 self
.Bind(wx
.EVT_SIZE
,self
.OnSize
)
299 def GetSaveData(self
):
301 saveData
['detailClass'] = str(self
.detail
.child
.__class
__)
302 if hasattr(self
.detail
.child
,'GetSaveData'):
303 attr
= getattr(self
.detail
.child
,'GetSaveData')
307 saveData
['detail'] = dData
308 v1
,v2
= self
.GetPosition()
311 v1
,v2
= self
.GetSize()
316 def SetSaveData(self
,data
):
317 dChild
= data
['detailClass']
318 mod
= dChild
.split('.')[0]
319 exec 'import %s' % mod
320 detClass
= eval(dChild
)
321 self
.SetDimensions(data
['x'],data
['y'],data
['w'],data
['h'])
323 self
.detail
= MultiClient(self
,detClass
)
324 dData
= data
.get('detail',None)
326 if hasattr(self
.detail
.child
,'SetSaveData'):
327 attr
= getattr(self
.detail
.child
,'SetSaveData')
331 self
.detail
.OnSize(None)
334 self
.detail
.UnSelect()
336 def DefaultChildChanged(self
):
337 self
.detail
.SetNewChildCls(self
.multiView
._defChild
)
339 def AddLeaf(self
,direction
,pos
):
342 if direction
== MV_VER
:
343 if pos
> h
- 10: return
345 if pos
> w
- 10: return
346 self
.GetParent().AddLeaf(direction
,self
,pos
)
348 def DestroyLeaf(self
):
349 self
.GetParent().DestroyLeaf(self
)
351 def SizeTarget(self
,side
):
352 return self
.GetParent().SizeTarget(side
,self
)
354 def CanSize(self
,side
):
355 return self
.GetParent().CanSize(side
,self
)
357 def OnSize(self
,evt
):
358 self
.sizerHor
.OnSize(evt
)
359 self
.sizerVer
.OnSize(evt
)
360 self
.creatorHor
.OnSize(evt
)
361 self
.creatorVer
.OnSize(evt
)
362 self
.detail
.OnSize(evt
)
363 self
.closer
.OnSize(evt
)
365 #----------------------------------------------------------------------
368 class MultiClient(wx
.Window
):
369 def __init__(self
,parent
,childCls
):
370 w
,h
= self
.CalcSize(parent
)
371 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
374 style
= wx
.CLIP_CHILDREN | wx
.SUNKEN_BORDER
)
375 self
.child
= childCls(self
)
376 self
.child
.MoveXY(2,2)
377 self
.normalColour
= self
.GetBackgroundColour()
378 self
.selected
= False
380 self
.Bind(wx
.EVT_SET_FOCUS
,self
.OnSetFocus
)
381 self
.Bind(wx
.EVT_CHILD_FOCUS
,self
.OnChildFocus
)
385 self
.selected
= False
386 self
.SetBackgroundColour(self
.normalColour
)
390 self
.GetParent().multiView
.UnSelect()
392 self
.SetBackgroundColour(wx
.Colour(255,255,0)) # Yellow
395 def CalcSize(self
,parent
):
396 w
,h
= parent
.GetSize()
401 def OnSize(self
,evt
):
402 w
,h
= self
.CalcSize(self
.GetParent())
403 self
.SetDimensions(0,0,w
,h
)
404 w
,h
= self
.GetClientSize()
405 self
.child
.SetSize((w
-4,h
-4))
407 def SetNewChildCls(self
,childCls
):
411 self
.child
= childCls(self
)
412 self
.child
.MoveXY(2,2)
414 def OnSetFocus(self
,evt
):
417 def OnChildFocus(self
,evt
):
419 ## from Funcs import FindFocusedChild
420 ## child = FindFocusedChild(self)
421 ## child.Bind(wx.EVT_KILL_FOCUS,self.OnChildKillFocus)
424 #----------------------------------------------------------------------
427 class MultiSizer(wx
.Window
):
428 def __init__(self
,parent
,side
):
430 x
,y
,w
,h
= self
.CalcSizePos(parent
)
431 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
434 style
= wx
.CLIP_CHILDREN
)
436 self
.px
= None # Previous X
437 self
.py
= None # Previous Y
438 self
.isDrag
= False # In Dragging
439 self
.dragTarget
= None # View being sized
441 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
442 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
443 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
444 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
445 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
447 def CalcSizePos(self
,parent
):
448 pw
,ph
= parent
.GetSize()
449 if self
.side
== MV_HOR
:
452 w
= pw
- CR_SIZE
- SH_SIZE
- 2
456 y
= CR_SIZE
+ 2 + SH_SIZE
458 h
= ph
- CR_SIZE
- SH_SIZE
- 4 - SH_SIZE
# For Closer
461 def OnSize(self
,evt
):
462 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
463 self
.SetDimensions(x
,y
,w
,h
)
465 def OnLeave(self
,evt
):
466 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
468 def OnEnter(self
,evt
):
469 if not self
.GetParent().CanSize(not self
.side
):
471 if self
.side
== MV_HOR
:
472 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZENS
))
474 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZEWE
))
476 def OnMouseMove(self
,evt
):
478 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
479 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
480 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
481 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
485 def OnPress(self
,evt
):
486 self
.dragTarget
= self
.GetParent().SizeTarget(not self
.side
)
489 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
490 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
491 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
496 def OnRelease(self
,evt
):
498 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
501 if self
.side
== MV_HOR
:
502 self
.dragTarget
.SizeLeaf(self
.GetParent(),
503 self
.py
,not self
.side
)
505 self
.dragTarget
.SizeLeaf(self
.GetParent(),
506 self
.px
,not self
.side
)
507 self
.dragTarget
= None
511 #----------------------------------------------------------------------
514 class MultiCreator(wx
.Window
):
515 def __init__(self
,parent
,side
):
517 x
,y
,w
,h
= self
.CalcSizePos(parent
)
518 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
521 style
= wx
.CLIP_CHILDREN
)
523 self
.px
= None # Previous X
524 self
.py
= None # Previous Y
525 self
.isDrag
= False # In Dragging
527 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
528 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
529 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
530 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
531 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
532 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
534 def CalcSizePos(self
,parent
):
535 pw
,ph
= parent
.GetSize()
536 if self
.side
== MV_HOR
:
543 y
= 4 + SH_SIZE
# Make provision for closer
548 def OnSize(self
,evt
):
549 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
550 self
.SetDimensions(x
,y
,w
,h
)
552 def OnLeave(self
,evt
):
553 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
555 def OnEnter(self
,evt
):
556 if self
.side
== MV_HOR
:
557 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_HAND
))
559 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_POINT_LEFT
))
561 def OnMouseMove(self
,evt
):
563 parent
= self
.GetParent()
564 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
565 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
566 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
567 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
571 def OnPress(self
,evt
):
573 parent
= self
.GetParent()
574 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
575 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
576 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
579 def OnRelease(self
,evt
):
581 parent
= self
.GetParent()
582 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
586 if self
.side
== MV_HOR
:
587 parent
.AddLeaf(MV_VER
,self
.py
)
589 parent
.AddLeaf(MV_HOR
,self
.px
)
593 def OnPaint(self
,evt
):
594 dc
= wx
.PaintDC(self
)
595 dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour(),wx
.SOLID
))
598 highlight
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
), 1, wx
.SOLID
)
599 shadow
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
), 1, wx
.SOLID
)
600 black
= wx
.Pen(wx
.BLACK
,1,wx
.SOLID
)
607 dc
.DrawLine((0,0), (0,h
))
608 dc
.DrawLine((0,0), (w
,0))
610 dc
.DrawLine((0,h
), (w
+1,h
))
611 dc
.DrawLine((w
,0), (w
,h
))
613 dc
.DrawLine((w
-1,2), (w
-1,h
))
615 #----------------------------------------------------------------------
618 class MultiCloser(wx
.Window
):
619 def __init__(self
,parent
):
620 x
,y
,w
,h
= self
.CalcSizePos(parent
)
621 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
624 style
= wx
.CLIP_CHILDREN
)
629 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
630 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
631 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
632 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
633 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
635 def OnLeave(self
,evt
):
636 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
639 def OnEnter(self
,evt
):
640 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_BULLSEYE
))
643 def OnPress(self
,evt
):
647 def OnRelease(self
,evt
):
648 if self
.down
and self
.entered
:
649 self
.GetParent().DestroyLeaf()
654 def OnPaint(self
,evt
):
655 dc
= wx
.PaintDC(self
)
656 dc
.SetBackground(wx
.Brush(wx
.RED
,wx
.SOLID
))
659 def CalcSizePos(self
,parent
):
660 pw
,ph
= parent
.GetSize()
667 def OnSize(self
,evt
):
668 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
669 self
.SetDimensions(x
,y
,w
,h
)
672 #----------------------------------------------------------------------
675 class EmptyChild(wx
.Window
):
676 def __init__(self
,parent
):
677 wx
.Window
.__init
__(self
,parent
,-1, style
= wx
.CLIP_CHILDREN
)
680 #----------------------------------------------------------------------
683 def DrawSash(win
,x
,y
,direction
):
685 dc
.StartDrawingOnTopWin(win
)
686 bmp
= wx
.EmptyBitmap(8,8)
688 bdc
.SelectObject(bmp
)
689 bdc
.DrawRectangle((-1,-1), (10,10))
695 brush
= wx
.Brush(wx
.Colour(0,0,0))
696 brush
.SetStipple(bmp
)
699 dc
.SetLogicalFunction(wx
.XOR
)
701 body_w
,body_h
= win
.GetClientSize()
712 if direction
== MV_HOR
:
717 x
,y
= win
.ClientToScreenXY(x
,y
)
722 if direction
== MV_HOR
:
723 dc
.DrawRectangle((x
,y
-2), (w
,4))
725 dc
.DrawRectangle((x
-2,y
), (4,h
))