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

Legend:
Removed from v.566  
changed lines
  Added in v.659

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26