]>
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'] = 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 self
.SetBackgroundColour(wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_3DFACE
))
308 def GetSaveData(self
):
310 saveData
['detailClass'] = str(self
.detail
.child
.__class
__)
311 if hasattr(self
.detail
.child
,'GetSaveData'):
312 attr
= getattr(self
.detail
.child
,'GetSaveData')
316 saveData
['detail'] = dData
317 v1
,v2
= self
.GetPosition()
320 v1
,v2
= self
.GetSize()
325 def SetSaveData(self
,data
):
326 dChild
= data
['detailClass']
327 mod
= dChild
.split('.')[0]
328 exec 'import %s' % mod
329 detClass
= eval(dChild
)
330 self
.SetDimensions(data
['x'],data
['y'],data
['w'],data
['h'])
332 self
.detail
= MultiClient(self
,detClass
)
333 dData
= data
.get('detail',None)
335 if hasattr(self
.detail
.child
,'SetSaveData'):
336 attr
= getattr(self
.detail
.child
,'SetSaveData')
340 self
.detail
.OnSize(None)
343 self
.detail
.UnSelect()
345 def DefaultChildChanged(self
):
346 self
.detail
.SetNewChildCls(self
.multiView
._defChild
)
348 def AddLeaf(self
,direction
,pos
):
351 if direction
== MV_VER
:
352 if pos
> h
- 10: return
354 if pos
> w
- 10: return
355 self
.GetParent().AddLeaf(direction
,self
,pos
)
357 def DestroyLeaf(self
):
358 self
.GetParent().DestroyLeaf(self
)
360 def SizeTarget(self
,side
):
361 return self
.GetParent().SizeTarget(side
,self
)
363 def CanSize(self
,side
):
364 return self
.GetParent().CanSize(side
,self
)
366 def OnSize(self
,evt
):
367 self
.sizerHor
.OnSize(evt
)
368 self
.sizerVer
.OnSize(evt
)
369 self
.creatorHor
.OnSize(evt
)
370 self
.creatorVer
.OnSize(evt
)
371 self
.detail
.OnSize(evt
)
372 self
.closer
.OnSize(evt
)
374 #----------------------------------------------------------------------
377 class MultiClient(wx
.Window
):
378 def __init__(self
,parent
,childCls
):
379 w
,h
= self
.CalcSize(parent
)
380 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
383 style
= wx
.CLIP_CHILDREN | wx
.SUNKEN_BORDER
)
384 self
.child
= childCls(self
)
385 self
.child
.MoveXY(2,2)
386 self
.normalColour
= self
.GetBackgroundColour()
387 self
.selected
= False
389 self
.Bind(wx
.EVT_SET_FOCUS
,self
.OnSetFocus
)
390 self
.Bind(wx
.EVT_CHILD_FOCUS
,self
.OnChildFocus
)
394 self
.selected
= False
395 self
.SetBackgroundColour(self
.normalColour
)
399 self
.GetParent().multiView
.UnSelect()
401 self
.SetBackgroundColour(wx
.Colour(255,255,0)) # Yellow
404 def CalcSize(self
,parent
):
405 w
,h
= parent
.GetSize()
410 def OnSize(self
,evt
):
411 w
,h
= self
.CalcSize(self
.GetParent())
412 self
.SetDimensions(0,0,w
,h
)
413 w
,h
= self
.GetClientSize()
414 self
.child
.SetSize((w
-4,h
-4))
416 def SetNewChildCls(self
,childCls
):
420 self
.child
= childCls(self
)
421 self
.child
.MoveXY(2,2)
423 def OnSetFocus(self
,evt
):
426 def OnChildFocus(self
,evt
):
428 ## from Funcs import FindFocusedChild
429 ## child = FindFocusedChild(self)
430 ## child.Bind(wx.EVT_KILL_FOCUS,self.OnChildKillFocus)
433 #----------------------------------------------------------------------
436 class MultiSizer(wx
.Window
):
437 def __init__(self
,parent
,side
):
439 x
,y
,w
,h
= self
.CalcSizePos(parent
)
440 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
443 style
= wx
.CLIP_CHILDREN
)
445 self
.px
= None # Previous X
446 self
.py
= None # Previous Y
447 self
.isDrag
= False # In Dragging
448 self
.dragTarget
= None # View being sized
450 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
451 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
452 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
453 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
454 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
456 self
.SetBackgroundColour(wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_3DFACE
))
459 def CalcSizePos(self
,parent
):
460 pw
,ph
= parent
.GetSize()
461 if self
.side
== MV_HOR
:
464 w
= pw
- CR_SIZE
- SH_SIZE
- 2
468 y
= CR_SIZE
+ 2 + SH_SIZE
470 h
= ph
- CR_SIZE
- SH_SIZE
- 4 - SH_SIZE
# For Closer
473 def OnSize(self
,evt
):
474 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
475 self
.SetDimensions(x
,y
,w
,h
)
477 def OnLeave(self
,evt
):
478 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
480 def OnEnter(self
,evt
):
481 if not self
.GetParent().CanSize(not self
.side
):
483 if self
.side
== MV_HOR
:
484 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZENS
))
486 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_SIZEWE
))
488 def OnMouseMove(self
,evt
):
490 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
491 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
492 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
493 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
497 def OnPress(self
,evt
):
498 self
.dragTarget
= self
.GetParent().SizeTarget(not self
.side
)
501 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
502 self
.px
,self
.py
= self
.dragTarget
.ScreenToClientXY(self
.px
,self
.py
)
503 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
508 def OnRelease(self
,evt
):
510 DrawSash(self
.dragTarget
,self
.px
,self
.py
,self
.side
)
513 if self
.side
== MV_HOR
:
514 self
.dragTarget
.SizeLeaf(self
.GetParent(),
515 self
.py
,not self
.side
)
517 self
.dragTarget
.SizeLeaf(self
.GetParent(),
518 self
.px
,not self
.side
)
519 self
.dragTarget
= None
523 #----------------------------------------------------------------------
526 class MultiCreator(wx
.Window
):
527 def __init__(self
,parent
,side
):
529 x
,y
,w
,h
= self
.CalcSizePos(parent
)
530 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
533 style
= wx
.CLIP_CHILDREN
)
535 self
.px
= None # Previous X
536 self
.py
= None # Previous Y
537 self
.isDrag
= False # In Dragging
539 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
540 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
541 self
.Bind(wx
.EVT_MOTION
,self
.OnMouseMove
)
542 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
543 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
544 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
546 def CalcSizePos(self
,parent
):
547 pw
,ph
= parent
.GetSize()
548 if self
.side
== MV_HOR
:
555 y
= 4 + SH_SIZE
# Make provision for closer
560 def OnSize(self
,evt
):
561 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
562 self
.SetDimensions(x
,y
,w
,h
)
564 def OnLeave(self
,evt
):
565 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
567 def OnEnter(self
,evt
):
568 if self
.side
== MV_HOR
:
569 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_HAND
))
571 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_POINT_LEFT
))
573 def OnMouseMove(self
,evt
):
575 parent
= self
.GetParent()
576 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
577 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
578 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
579 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
583 def OnPress(self
,evt
):
585 parent
= self
.GetParent()
586 self
.px
,self
.py
= self
.ClientToScreenXY(evt
.m_x
,evt
.m_y
)
587 self
.px
,self
.py
= parent
.ScreenToClientXY(self
.px
,self
.py
)
588 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
591 def OnRelease(self
,evt
):
593 parent
= self
.GetParent()
594 DrawSash(parent
,self
.px
,self
.py
,self
.side
)
598 if self
.side
== MV_HOR
:
599 parent
.AddLeaf(MV_VER
,self
.py
)
601 parent
.AddLeaf(MV_HOR
,self
.px
)
605 def OnPaint(self
,evt
):
606 dc
= wx
.PaintDC(self
)
607 dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour(),wx
.SOLID
))
610 highlight
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
), 1, wx
.SOLID
)
611 shadow
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
), 1, wx
.SOLID
)
612 black
= wx
.Pen(wx
.BLACK
,1,wx
.SOLID
)
619 dc
.DrawLine(0,0, 0,h
)
620 dc
.DrawLine(0,0, w
,0)
622 dc
.DrawLine(0,h
, w
+1,h
)
623 dc
.DrawLine(w
,0, w
,h
)
625 dc
.DrawLine(w
-1,2, w
-1,h
)
627 #----------------------------------------------------------------------
630 class MultiCloser(wx
.Window
):
631 def __init__(self
,parent
):
632 x
,y
,w
,h
= self
.CalcSizePos(parent
)
633 wx
.Window
.__init
__(self
,id = -1,parent
= parent
,
636 style
= wx
.CLIP_CHILDREN
)
641 self
.Bind(wx
.EVT_LEFT_DOWN
,self
.OnPress
)
642 self
.Bind(wx
.EVT_LEFT_UP
,self
.OnRelease
)
643 self
.Bind(wx
.EVT_PAINT
,self
.OnPaint
)
644 self
.Bind(wx
.EVT_LEAVE_WINDOW
,self
.OnLeave
)
645 self
.Bind(wx
.EVT_ENTER_WINDOW
,self
.OnEnter
)
647 def OnLeave(self
,evt
):
648 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_ARROW
))
651 def OnEnter(self
,evt
):
652 self
.SetCursor(wx
.StockCursor(wx
.CURSOR_BULLSEYE
))
655 def OnPress(self
,evt
):
659 def OnRelease(self
,evt
):
660 if self
.down
and self
.entered
:
661 self
.GetParent().DestroyLeaf()
666 def OnPaint(self
,evt
):
667 dc
= wx
.PaintDC(self
)
668 dc
.SetBackground(wx
.Brush(wx
.RED
,wx
.SOLID
))
671 def CalcSizePos(self
,parent
):
672 pw
,ph
= parent
.GetSize()
679 def OnSize(self
,evt
):
680 x
,y
,w
,h
= self
.CalcSizePos(self
.GetParent())
681 self
.SetDimensions(x
,y
,w
,h
)
684 #----------------------------------------------------------------------
687 class EmptyChild(wx
.Window
):
688 def __init__(self
,parent
):
689 wx
.Window
.__init
__(self
,parent
,-1, style
= wx
.CLIP_CHILDREN
)
692 #----------------------------------------------------------------------
695 def DrawSash(win
,x
,y
,direction
):
697 dc
.StartDrawingOnTopWin(win
)
698 bmp
= wx
.EmptyBitmap(8,8)
700 bdc
.SelectObject(bmp
)
701 bdc
.DrawRectangle(-1,-1, 10,10)
707 brush
= wx
.Brush(wx
.Colour(0,0,0))
708 brush
.SetStipple(bmp
)
711 dc
.SetLogicalFunction(wx
.XOR
)
713 body_w
,body_h
= win
.GetClientSize()
724 if direction
== MV_HOR
:
729 x
,y
= win
.ClientToScreenXY(x
,y
)
734 if direction
== MV_HOR
:
735 dc
.DrawRectangle(x
,y
-2, w
,4)
737 dc
.DrawRectangle(x
-2,y
, 4,h
)