/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/dock.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/dock.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 561 by jonathan, Wed Mar 26 11:06:01 2003 UTC revision 577 by jonathan, Mon Mar 31 18:31:33 2003 UTC
# Line 15  from wxPython.wx import * Line 15  from wxPython.wx import *
15    
16  from Thuban.Lib.connector import Publisher  from Thuban.Lib.connector import Publisher
17    
18    from dialogs import NonModalDialog
19    
20  from messages import DOCKABLE_DOCKED, DOCKABLE_UNDOCKED, DOCKABLE_CLOSED  from messages import DOCKABLE_DOCKED, DOCKABLE_UNDOCKED, DOCKABLE_CLOSED
21    
22    import gc
23    
24  ID_BUTTON_DOCK = 4001  ID_BUTTON_DOCK = 4001
25  ID_BUTTON_UNDOCK = 4002  ID_BUTTON_CLOSE = 4002
26    
27    PANEL_ID = 3141
28    
29  class DockPanel(wxPanel):  class DockPanel(wxPanel):
30    
31      def __init__(self, parent, id):      def __init__(self, parent, id):
32    
33          wxPanel.__init__(self, parent, id)          if not isinstance(parent, DockableWindow):
34                raise TypeError("")
35    
36            wxPanel.__init__(self, parent.GetCurrentParent(), id)
37    
38          self.SetDockParent(None)          #self.SetDockParent(None)
39            parent.SetPanel(self)
40    
41      def SetDockParent(self, parent):      def SetDockParent(self, parent):
42          self.dockParent = parent          self.__dockParent = parent
43    
44      def GetDockParent(self):      def GetDockParent(self):
45          return self.dockParent          return self.__dockParent
46    
47        def SetDock(self, dock):
48            #if dock == self.IsDocked(): return
49    
50            if dock:
51                self.Dock()
52            else:
53                self.UnDock()
54    
55      def Dock(self):      def Dock(self):
56          self.GetDockParent().Dock()          self.GetDockParent().Dock()
# Line 43  class DockPanel(wxPanel): Line 61  class DockPanel(wxPanel):
61      def IsDocked(self):      def IsDocked(self):
62          return self.GetDockParent().IsDocked()          return self.GetDockParent().IsDocked()
63    
64  class DockableWindow(NonModalDialog, Publisher):  class DockableWindow(Publisher):
65    
66        def __getattr__(self, attr):
67    
68            #print attr
69            return getattr(self.__topWindow, attr)
70            #try:
71            #except AttributeError:
72                #raise
73                #return self.__dict__[attr]
74                #return getattr(self, attr)
75                #pass
76    
77      def __init__(self, parent, id, name,      def __init__(self, parent, id, name,
78                   title, dockWindow, panel, docked = False, show = True):                   title, dockWindow, orient): #, panel, docked = False, show = True):
79    
80            if not isinstance(parent, DockFrame): raise TypeError("")
81    
82            self.__parent = parent
83            self.__id     = id
84            self.__name   = name
85    
86            self.__orientation = orient
87    
88            self.__dockWindow  = dockWindow
89            #self.__floatWindow = NonModalDialog(parent, name, title)
90            self.__floatWindow = wxFrame(parent, id, title)
91    
92            self.__docked      = False
93    
94            self.__dockPanel  = None
95    
96            if self.__docked:
97                self.__topWindow = self.__dockWindow
98            else:
99                self.__topWindow = self.__floatWindow
100    
101          NonModalDialog.__init__(self, parent, name, title)          self.__floatSize     = None
102            self.__floatPosition = None
103    
104          self.id = id          self.__panel = None
         self.dockWindow = dockWindow  
         self.docked = docked  
105    
106          self.dockBorder = None          self.__dockWindow.Hide()
107          self.dockBorderParent = self          self.__floatWindow.Hide()
108    
109          self.size = None          EVT_CLOSE(self, self._OnClose)
         self.position = None  
110    
111          self.SetPanel(panel)      ##
112          self.SetDock(self.docked)      # Public methods
113        #
114    
115          self.Show(show)      def GetName(self):
116            return self.__name
117    
118      def SetPanel(self, panel, orient = wxVERTICAL):      def SetPanel(self, panel):
119    
120          if not isinstance(panel, DockPanel):          if not isinstance(panel, DockPanel):
121              raise TypeError("")              raise TypeError("")
122    
123          self.panel = panel          self.__panel = panel
124          self.panel.SetDockParent(self)          self.__panel.SetDockParent(self)
         self.orientation = orient  
125          self.__CreateBorder()          self.__CreateBorder()
126    
127            self.SetDock(self.__docked)
128    
129        def GetPanel(self):
130            return self.__panel
131                    
132        def GetCurrentParent(self):
133            return self.__topWindow
134    
135      def SetDock(self, dock):      def SetDock(self, dock):
136    
137            self.__CheckAllGood()
138    
139          if dock:          if dock:
140              self.Dock()              self.Dock()
141          else:          else:
142              self.UnDock()              self.UnDock()
143    
144      def Dock(self):      def Dock(self):
145          #if self.IsDocked(): return          self.__CheckAllGood()
146    
147            wasVisible = self.IsShown()
148    
149          self.docked = True          if wasVisible: self.Show(False)
150    
151          self.size = self.GetSize()          self.__docked = True
         self.position = self.GetPosition()  
         #print self.position  
152    
153            #
154            # save window information
155            #
156            self.__floatSize = self.GetSize()
157            self.__floatPosition = self.GetPosition()
158    
159            #
160            # reparent
161            #
162            self.__topWindow = self.__dockWindow
163            self.__dockPanel.Reparent(self.__topWindow)
164    
165          NonModalDialog.Hide(self)          self.__dockButton.SetLabel(_("Undock"))
166    
167          self.dockBorderParent = self.dockWindow          self.SetDockSize(self.__dockWindow.GetSize())
         self.dockBorder.Reparent(self.dockBorderParent)  
168    
169          self.dockButton.SetLabel(_("Undock"))          if wasVisible: self.Show(True)
170    
171          self.issue(DOCKABLE_DOCKED, self.id, self)          #self.__parent._UpdateDocks()
172    
173            self.issue(DOCKABLE_DOCKED, self.__id, self)
174    
175      def UnDock(self):      def UnDock(self):
176            self.__CheckAllGood()
177    
178          #if not self.IsDocked(): return          wasVisible = self.IsShown()
179    
180          self.docked = False          if wasVisible: self.Show(False)
   
         self.dockBorderParent = self  
         self.dockBorder.Reparent(self.dockBorderParent)  
181    
182          self.dockButton.SetLabel(_("Dock"))          self.__docked = False
183    
184            #
185            # reparent
186            #
187            self.__topWindow = self.__floatWindow
188            self.__dockPanel.Reparent(self.__topWindow)
189    
190          if self.position is not None:          self.__dockButton.SetLabel(_("Dock"))
             #print self.position  
             self.SetPosition(self.position)  
191    
192          NonModalDialog.Show(self) # this needs to come before SetSize()          if wasVisible: self.Show()
193    
194          if self.size is not None:          #
195              self.SetSize(self.size)          # restore window information
196            #
197            if self.__floatPosition is not None: self.SetPosition(self.__floatPosition)
198            if self.__floatSize     is not None: self.SetSize(self.__floatSize)
199    
200          self.issue(DOCKABLE_UNDOCKED, self.id, self)          self.issue(DOCKABLE_UNDOCKED, self.__id, self)
201    
202      def IsDocked(self):      def IsDocked(self):
203          return self.docked          self.__CheckAllGood()
204    
205      def OnClose(self, event):          return self.__docked
         self.issue(DOCKABLE_CLOSED, self.id, self)  
         NonModalDialog.OnClose(self, event)  
206    
 #   def Show(self, show = True):  
207    
208  #       if show:      def Show(self, show = True):
209            if show:
210                self.__DoShow()
211            else:
212                self.__DoHide()
213    
214  #           if self.IsDocked():      def SetDockSize(self, rect = None):
 #               self.docked = False  
 #               self.Dock()  
 #           else:  
 #               self.docked = True  
 #               self.UnDock()  
 #               #NonModalDialog.Show(self)  
 #       else:  
 #           self.docked = True  
 #           self.UnDock()  
 #           NonModalDialog.Hide(self)  
215    
216      def GetSize(self):          #
217          return self.dockBorder.GetSize()          # adjust the size to get the
218            w0, h0 = self.__dockPanel.GetBestSize()
219            w, h = self.__panel.GetBestSize()
220    
221            #print (w0, h0), (w, h)
222    
223            if (w, h) < (w0, h0):
224                w = w0
225                h = h0
226                                                                                          
227            if rect is not None:
228                rw = rect.width
229                rh = rect.height
230                #print "   ", (rw, rh)
231                if rw < w: rw = w
232                if rh < h: rh = h
233            else:
234                rw = w
235                rh = h
236                                                                                          
237            # these are to account for the border?!!?
238            rw += 8 # XXX: without this the sash isn't visible!?!?!?!
239            rh += 8 # XXX: without this the sash isn't visible!?!?!?!
240                                                                                          
241            self.__dockWindow.SetDefaultSize(wxSize(rw, rh))
242    
     def GetBestSize(self):  
         return self.dockBorder.GetBestSize()  
243    
244      def GetClientSize(self):      def Destroy(self):
245          return self.dockBorder.GetClientSize()          self.__panel.Destroy()
246            self.__floatWindow.Destroy()
247            self.__dockWindow.Destroy()
248            self.__parent.OnDockClose(self)
249            
250        ##
251        # Event handlers
252        #
253    
254      def GetAdjustedBestSize(self):      def _OnButtonClose(self, event):
255          return self.dockBorder.GetAdjustedBestSize()          self.Close()
256    
257      def GetSizeTuple(self):      def _OnClose(self, force = False):
258          return self.dockBorder.GetSizeTuple()          self.Destroy()
259    
260      def _OnDock(self, event):      def _OnToggleDock(self, event):
261            self.__CheckAllGood()
262    
263          self.SetDock(not self.docked)          self.SetDock(not self.IsDocked())
264    
265  #       if self.IsDocked():      ##
266  #           win.SetLabel(_("Undock"))      # Private methods
267  #           self.UnDock()      #
 #       else:  
 #           win.SetLabel(_("Dock"))  
 #           self.Dock()  
268    
269      #def _OnUnDock(self, event):      def __CheckAllGood(self):
270          #self.UnDock()          if self.__panel is None:
271                raise TypeError("")
272    
273      def __CreateBorder(self):      def __DoShow(self):
274            if self.IsShown(): return
275            #print "__DoShow()", self.IsShown()
276    
277            self.__topWindow.Show()
278    
279            #if self.IsDocked():
280                #self.SetDockSize()
281    
282            if self.__topWindow is self.__dockWindow:
283                self.__parent._UpdateDocks()
284                
285        def __DoHide(self):
286            if not self.IsShown(): return
287            #print "__DoHide()", self.IsShown()
288            self.__topWindow.Show(False)
289    
290          self.panel.Reparent(self) # Make sure we hang on to the panel          if self.__topWindow is self.__dockWindow:
291                self.__parent._UpdateDocks()
292    
293    
294          sizer = wxBoxSizer(self.orientation)      def __CreateBorder(self):
295    
296            #self.__panel.Reparent(self) # Make sure we hang on to the panel
297    
298          self.dockBorder = wxPanel(self.dockBorderParent, -1)          self.__dockPanel = wxPanel(self.__topWindow, -1, style=wxSUNKEN_BORDER)
299          #self.dockBorder.SetBackgroundColour(wxColour(255, 0, 0))          #self.__dockPanel.SetBackgroundColour(wxColour(255, 0, 0))
300    
301          if self.orientation == wxVERTICAL:          if self.__orientation == wxLAYOUT_VERTICAL:
302              buttonBoxOrient = wxHORIZONTAL              sizer = wxBoxSizer(wxVERTICAL)
303                headerBoxOrient = wxHORIZONTAL
304          else:          else:
305              buttonBoxOrient = wxVERTICAL              sizer = wxBoxSizer(wxHORIZONTAL)
306                headerBoxOrient = wxVERTICAL
307            
308    
309          buttonBox = wxStaticBoxSizer(          headerBox = wxStaticBoxSizer(
310                          wxStaticBox(self.dockBorder, -1, ""),                          wxStaticBox(self.__dockPanel, -1, ""), headerBoxOrient)
                         buttonBoxOrient)  
311    
312          button = wxStaticText(self.dockBorder, -1,          buttonBox = wxBoxSizer(wxHORIZONTAL)
                               self.GetTitle(),  
                               style = wxSIMPLE_BORDER | wxALIGN_CENTRE)  
         buttonBox.Add(button, 0,  
                       wxSHAPED | wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)  
313    
314          buttonBox.Add(60, 20, 1, wxGROW)          #
315            # ideally, we should be able to rotate this text depending on
316            # our orientation
317            #
318            text = wxStaticText(self.__dockPanel, -1, self.GetTitle(),
319                                 style = wxSIMPLE_BORDER | wxALIGN_CENTRE)
320    
321          #          #
322          # Perhaps using wxToggleButton would be better, but it's only          # Perhaps using wxToggleButton would be better, but it's only
323          # supported under wxMSW and wxGTK as of v2.4.0.3          # supported under wxMSW and wxGTK as of v2.4.0.3
324          #          #
325          self.dockButton = wxButton(self.dockBorder, ID_BUTTON_DOCK,          self.__dockButton = wxButton(self.__dockPanel, ID_BUTTON_DOCK, "WWWWWW",
326              "WWWWWW", style = wxGROW | wxBU_EXACTFIT | wxADJUST_MINSIZE)                                       style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
327          buttonBox.Add(self.dockButton, 0, wxALIGN_RIGHT, 0)  
328            closeX = wxButton(self.__dockPanel, ID_BUTTON_CLOSE, "X",
329                             style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
330    
331            buttonBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
332            buttonBox.Add(closeX, 0, wxALIGN_RIGHT, 0)
333    
334            if self.__orientation == wxLAYOUT_VERTICAL:
335                headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
336                headerBox.Add(1, 20, 1, wxGROW)
337                headerBox.Add(buttonBox, 0, wxGROW | wxALIGN_RIGHT, 0)
338            else:
339                headerBox.Add(buttonBox, 0, wxGROW, 0)
340                headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
341    
342            sizer.Add(headerBox, 0, wxGROW, 0)
343    
344            self.__panel.Reparent(self.__dockPanel)
345            self.__panel.SetId(PANEL_ID)
346    
347            sizer.Add(self.__panel, 1, wxGROW, 0)
348    
349            sizer.Fit(self.__dockPanel)
350    
351            self.__dockPanel.SetSizer(sizer)
352            self.__dockPanel.SetAutoLayout(True)
353    
354            sizer.SetSizeHints(self.__dockPanel)
355    
356            EVT_BUTTON(self.__dockPanel, ID_BUTTON_DOCK, self._OnToggleDock)
357            EVT_BUTTON(self.__dockPanel, ID_BUTTON_CLOSE, self._OnButtonClose)
358    
359    
360    class DockFrame(wxFrame):
361    
362        def __init__(self, parent, id, title, position, size):
363            wxFrame.__init__(self, parent, id, title, position, size)
364    
365            self.openWindows = {}
366    
367            self.__update_lock = 0
368    
369            self.SetMainWindow(None)
370    
371    
372            EVT_SIZE(self, self._OnSashSize)
373            EVT_CLOSE(self, self._OnClose)
374    
375        layout2oppSash = {
376                wxLAYOUT_NONE   : wxSASH_NONE,
377                wxLAYOUT_TOP    : wxSASH_BOTTOM,
378                wxLAYOUT_LEFT   : wxSASH_RIGHT,
379                wxLAYOUT_RIGHT  : wxSASH_LEFT,
380                wxLAYOUT_BOTTOM : wxSASH_TOP }
381    
382    
383        def _OnClose(self, event):
384    
385            self.__update_lock += 1
386    
387            #
388            # child windows are not notified when the parent is destroyed
389            # as of v2.4.0.3 so we need to interate over our children
390            # and tell them to go away.
391            #
392            for key in self.openWindows.keys():
393                win = self.openWindows[key]
394                win.Destroy()
395    
396            self.__update_lock -= 1
397    
398            # should really call _UpdateDocks() here but we don't need to
399            # since we're going away
400    
401        def CreateDock(self, name, id, title, align):
402    
403          #button = wxButton(self.dockBorder, ID_BUTTON_UNDOCK,          if align in (wxLAYOUT_NONE, wxLAYOUT_LEFT, wxLAYOUT_RIGHT):
404          #                      _("Undock"),              orient = wxLAYOUT_VERTICAL
405          #                      style = wxSIMPLE_BORDER | wxBU_EXACTFIT)          else:
406          #buttonBox.Add(button, 0, wxALIGN_RIGHT, 0)              orient = wxLAYOUT_HORIZONTAL
407    
408            sash = wxSashLayoutWindow(self, id, style=wxNO_BORDER|wxSW_3D)
409            sash.SetOrientation(orient)
410            sash.SetAlignment(align)
411            #print align, DockFrame.layout2oppSash[align]
412            sash.SetSashVisible(DockFrame.layout2oppSash[align], True)
413            sash.SetSashBorder(DockFrame.layout2oppSash[align], True)
414    
415            win = DockableWindow(self, id, name, title, sash, orient)
416    
417          sizer.Add(buttonBox, 0, wxGROW, 0)          self.__RegisterDock(name, win)
418            EVT_SASH_DRAGGED(self, id, self._OnSashDragged)
419    
420          self.panel.Reparent(self.dockBorder)          return win
421    
422          sizer.Add(self.panel, 1, wxGROW | wxALL, 0)      def FindRegisteredDock(self, name):
423          self.dockBorder.SetSizer(sizer)          return self.openWindows.get(name)
         self.dockBorder.SetAutoLayout(True)  
424    
425          #self.dockBorderParent.SetAutoLayout(True)      def OnDockClose(self, win):
426            del self.openWindows[win.GetName()]
427            self._UpdateDocks()
428    
429        def SetMainWindow(self, main):
430            self.__mainWindow = main
431            self._UpdateDocks()
432            
433        def _UpdateDocks(self):
434            #print "_UpdateDocks()"
435            if self.__update_lock == 0:
436                wxLayoutAlgorithm().LayoutWindow(self, self.__mainWindow)
437    
438        def _OnSashDragged(self, event):
439            if event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE:
440                return
441    
442            id = event.GetId()
443            sash = self.FindWindowById(id)
444            #assert(isinstance(win, wxPanel))
445            dockPanel = sash.GetChildren()[0]
446            #print dockPanel
447            panel = dockPanel.FindWindowById(PANEL_ID)
448            #print panel
449            assert(isinstance(panel, DockPanel))
450            win = panel.GetDockParent()
451            #print win
452            assert(isinstance(win, DockableWindow))
453    
454            assert(win.IsDocked())
455    
456            rect = event.GetDragRect()
457    
458            win.SetDockSize(rect)
459    
460            self._UpdateDocks()
461    
462        def _OnSashSize(self, event):
463            self._UpdateDocks()
464    
465        def __RegisterDock(self, name, win):
466            if self.FindRegisteredDock(name) is not None:
467                raise ValueError(
468                    "A dockable window is already registered under the name '%s'" % name)
469    
470          EVT_BUTTON(self.dockBorder, ID_BUTTON_DOCK, self._OnDock)          self.openWindows[name] = win
         #EVT_BUTTON(self.dockBorder, ID_BUTTON_UNDOCK, self._OnUnDock)  
471    

Legend:
Removed from v.561  
changed lines
  Added in v.577

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26