/[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 666 by jonathan, Mon Apr 14 16:36:33 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 *
17    
18  from Thuban.Lib.connector import Publisher  from Thuban.Lib.connector import Publisher
19    
20    from dialogs import NonModalDialog
21    
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            wxPanel.__init__(self, parent.GetCurrentParent(), id)
41    
42          self.SetDockParent(None)          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 43  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("")
85                   title, dockWindow, panel, docked = False, show = True):  
86            self.__parent = parent
87            self.__id     = id
88            self.__name   = name
89    
90            self.__orientation = orient
91    
92            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          NonModalDialog.__init__(self, parent, name, title)          self.__floatSize     = None
102            self.__floatPosition = None
103    
104          self.id = id          self.__dockPanel  = None
105          self.dockWindow = dockWindow          self.__panel = None
         self.docked = docked  
106    
107          self.dockBorder = None          self.__dockWindow.Hide()
108          self.dockBorderParent = self          self.__floatWindow.Hide()
109    
110          self.size = None          EVT_CLOSE(self, self._OnClose)
         self.position = None  
111    
112          self.SetPanel(panel)      ##
113          self.SetDock(self.docked)      # Public methods
114        #
115    
116          self.Show(show)      def GetName(self):
117            return self.__name
118    
119      def SetPanel(self, panel, orient = wxVERTICAL):      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            wasVisible = self.IsShown()
149    
150          self.docked = True          if wasVisible: self.Show(False)
151    
152          self.size = self.GetSize()          self.__docked = True
         self.position = self.GetPosition()  
         #print self.position  
153    
154            #
155            # save window information
156            #
157            self.__floatSize = self.GetSize()
158            self.__floatPosition = self.GetPosition()
159    
160            #
161            # reparent
162            #
163            self.__topWindow = self.__dockWindow
164            self.__dockPanel.Reparent(self.__topWindow)
165    
166          NonModalDialog.Hide(self)          #self.__dockButton.SetBitmapLabel(self.__bmpUnDock)
167            #self.__dockButton.SetBitmapFocus(self.__bmpUnDock)
168            self.__dockButton.SetToolTip(wxToolTip(_("Undock")))
169    
170          self.dockBorderParent = self.dockWindow          self.SetDockSize(self.__dockWindow.GetSize())
         self.dockBorder.Reparent(self.dockBorderParent)  
171    
172          self.dockButton.SetLabel(_("Undock"))          if wasVisible: self.Show(True)
173    
174          self.issue(DOCKABLE_DOCKED, self.id, self)          self.issue(DOCKABLE_DOCKED, self.__id, self)
175    
176      def UnDock(self):      def UnDock(self):
177            self.__CheckAllGood()
178    
179          #if not self.IsDocked(): return          wasVisible = self.IsShown()
180    
181          self.docked = False          if wasVisible: self.Show(False)
182    
183            self.__docked = False
184    
185          self.dockBorderParent = self          #
186          self.dockBorder.Reparent(self.dockBorderParent)          # reparent
187            #
188            self.__topWindow = self.__floatWindow
189            self.__dockPanel.Reparent(self.__topWindow)
190    
191          self.dockButton.SetLabel(_("Dock"))          #self.__dockButton.SetBitmapLabel(self.__bmpDock)
192            #self.__dockButton.SetBitmapFocus(self.__bmpDock)
193            self.__dockButton.SetToolTip(wxToolTip(_("Dock")))
194    
195          if self.position is not None:          if wasVisible: self.Show()
             #print self.position  
             self.SetPosition(self.position)  
196    
197          NonModalDialog.Show(self) # this needs to come before SetSize()          #
198            # restore window information
199            #
200            if self.__floatPosition is not None:
201                self.SetPosition(self.__floatPosition)
202            if self.__floatSize is not None:
203                self.SetSize(self.__floatSize)
204    
205          if self.size is not None:          self.__dockPanel.SetSize(self.__topWindow.GetClientSize())
             self.SetSize(self.size)  
206    
207          self.issue(DOCKABLE_UNDOCKED, self.id, self)          self.issue(DOCKABLE_UNDOCKED, self.__id, self)
208    
209      def IsDocked(self):      def IsDocked(self):
210          return self.docked          self.__CheckAllGood()
211            return self.__docked
212    
213      def OnClose(self, event):      def Show(self, show = True):
214          self.issue(DOCKABLE_CLOSED, self.id, self)          if show:
215          NonModalDialog.OnClose(self, event)              self.__DoShow()
216            else:
217                self.__DoHide()
218    
219  #   def Show(self, show = True):      def SetDockSize(self, rect = None):
220    
221  #       if show:          w0, h0 = self.__dockPanel.GetBestSize()
222            w, h = self.__panel.GetBestSize()
223    
224            if (w, h) < (w0, h0):
225                w = w0
226                h = h0
227    
228            if rect is not None:
229                rw = rect.width
230                rh = rect.height
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    
 #           if self.IsDocked():  
 #               self.docked = False  
 #               self.Dock()  
 #           else:  
 #               self.docked = True  
 #               self.UnDock()  
 #               #NonModalDialog.Show(self)  
 #       else:  
 #           self.docked = True  
 #           self.UnDock()  
 #           NonModalDialog.Hide(self)  
243    
244      def GetSize(self):      def Destroy(self):
245          return self.dockBorder.GetSize()          self.__panel.Destroy()
246            self.__floatWindow.Destroy()
247            self.__dockWindow.Destroy()
248            self.__parent.OnDockDestroy(self)
249            
250        ##
251        # Event handlers
252        #
253    
254      def GetBestSize(self):      def _OnButtonClose(self, event):
255          return self.dockBorder.GetBestSize()          #self.Close()
256            self.Show(False)
257    
258      def GetClientSize(self):      def _OnClose(self, force = False):
259          return self.dockBorder.GetClientSize()          self.Show(False)
260    
261      def GetAdjustedBestSize(self):      def _OnToggleDock(self, event):
262          return self.dockBorder.GetAdjustedBestSize()          self.__CheckAllGood()
263    
264      def GetSizeTuple(self):          self.SetDock(not self.IsDocked())
         return self.dockBorder.GetSizeTuple()  
265    
266      def _OnDock(self, event):      ##
267        # Private methods
268        #
269    
270        def __CheckAllGood(self):
271            if self.__panel is None:
272                raise TypeError("")
273    
274          self.SetDock(not self.docked)      def __DoShow(self):
275            if self.IsShown(): return
276    
277  #       if self.IsDocked():          self.__topWindow.Show()
 #           win.SetLabel(_("Undock"))  
 #           self.UnDock()  
 #       else:  
 #           win.SetLabel(_("Dock"))  
 #           self.Dock()  
278    
279      #def _OnUnDock(self, event):          if self.__topWindow is self.__dockWindow:
280          #self.UnDock()              self.__parent._UpdateDocks()
281                
282        def __DoHide(self):
283            if not self.IsShown(): return
284    
285            self.__topWindow.Show(False)
286    
287            if self.__topWindow is self.__dockWindow:
288                self.__parent._UpdateDocks()
289    
290      def __CreateBorder(self):      def __CreateBorder(self):
291    
292          self.panel.Reparent(self) # Make sure we hang on to the panel          self.__dockPanel = wxPanel(self.__topWindow, -1, style=wxSUNKEN_BORDER)
293    
294            self.__panel.Reparent(self.__dockPanel)
295            self.__panel.SetId(PANEL_ID)
296    
297            if self.__orientation == wxLAYOUT_VERTICAL:
298                sizer = wxBoxSizer(wxVERTICAL)
299                headerBoxOrient = wxHORIZONTAL
300            else:
301                sizer = wxBoxSizer(wxHORIZONTAL)
302                headerBoxOrient = wxVERTICAL
303            
304    
305            headerBox = wxStaticBoxSizer(
306                            wxStaticBox(self.__dockPanel, -1, ""), headerBoxOrient)
307    
308            #
309            # ideally, we should be able to rotate this text depending on
310            # our orientation
311            #
312            text = wxStaticText(self.__dockPanel, -1, self.GetTitle(),
313                                 style = wxALIGN_CENTRE)
314            font = text.GetFont()
315            font.SetPointSize(10)
316            text.SetFont(font)
317    
318            #
319            # load the dock/undock/close bitmaps
320            # and create the buttons
321            #
322            self.__bmpDock   = \
323                resource.GetBitmapResource(DOCK_BMP, wxBITMAP_TYPE_XPM)
324            self.__bmpUnDock = \
325                resource.GetBitmapResource(UNDOCK_BMP, wxBITMAP_TYPE_XPM)
326    
327          sizer = wxBoxSizer(self.orientation)          if self.__docked:
328                bmp = self.__bmpDock
329            else:
330                bmp = self.__bmpUnDock
331    
332          self.dockBorder = wxPanel(self.dockBorderParent, -1)          self.__dockButton = wxBitmapButton(
333          #self.dockBorder.SetBackgroundColour(wxColour(255, 0, 0))              self.__dockPanel, ID_BUTTON_DOCK,
334                bmp,
335                size = wxSize(bmp.GetWidth() + 4, bmp.GetHeight() + 4),
336                style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
337    
338            bmp = resource.GetBitmapResource(CLOSE_BMP, wxBITMAP_TYPE_XPM)
339    
340            closeX = wxBitmapButton(self.__dockPanel, ID_BUTTON_CLOSE, bmp,
341                              size = wxSize(bmp.GetWidth() + 4,
342                                            bmp.GetHeight() + 4),
343                              style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
344            closeX.SetToolTip(wxToolTip(_("Close")))
345    
346          if self.orientation == wxVERTICAL:          #
347              buttonBoxOrient = wxHORIZONTAL          # fill in the sizer in an order appropriate to the orientation
348            #
349            if self.__orientation == wxLAYOUT_VERTICAL:
350                headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
351                headerBox.Add(1, 5, 1, wxGROW)
352                headerBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
353                headerBox.Add(closeX, 0, wxALIGN_RIGHT | wxLEFT, 4)
354          else:          else:
355              buttonBoxOrient = wxVERTICAL              headerBox.Add(closeX, 0, wxALIGN_RIGHT | wxBOTTOM, 4)
356                headerBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
357                headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
358    
359            sizer.Add(headerBox, 0, wxGROW, 0)
360            sizer.Add(self.__panel, 1, wxGROW, 0)
361    
362    
363            self.__dockPanel.SetAutoLayout(True)
364            self.__dockPanel.SetSizer(sizer)
365            sizer.SetSizeHints(self.__dockPanel)
366            sizer.SetSizeHints(self.__floatWindow)
367    
368            EVT_BUTTON(self.__dockPanel, ID_BUTTON_DOCK, self._OnToggleDock)
369            EVT_BUTTON(self.__dockPanel, ID_BUTTON_CLOSE, self._OnButtonClose)
370    
371    
372    class DockFrame(wxFrame):
373    
374        def __init__(self, parent, id, title, position, size):
375            wxFrame.__init__(self, parent, id, title, position, size)
376    
377          buttonBox = wxStaticBoxSizer(          self.openWindows = {}
                         wxStaticBox(self.dockBorder, -1, ""),  
                         buttonBoxOrient)  
378    
379          button = wxStaticText(self.dockBorder, -1,          self.__update_lock = 0
                               self.GetTitle(),  
                               style = wxSIMPLE_BORDER | wxALIGN_CENTRE)  
         buttonBox.Add(button, 0,  
                       wxSHAPED | wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)  
380    
381          buttonBox.Add(60, 20, 1, wxGROW)          self.SetMainWindow(None)
382    
383    
384            EVT_SIZE(self, self._OnSashSize)
385            EVT_CLOSE(self, self._OnClose)
386    
387        layout2oppSash = {
388                wxLAYOUT_NONE   : wxSASH_NONE,
389                wxLAYOUT_TOP    : wxSASH_BOTTOM,
390                wxLAYOUT_LEFT   : wxSASH_RIGHT,
391                wxLAYOUT_RIGHT  : wxSASH_LEFT,
392                wxLAYOUT_BOTTOM : wxSASH_TOP }
393    
394    
395        def _OnClose(self, event):
396    
397            self.__update_lock += 1
398    
399          #          #
400          # Perhaps using wxToggleButton would be better, but it's only          # child windows are not notified when the parent is destroyed
401          # supported under wxMSW and wxGTK as of v2.4.0.3          # as of v2.4.0.3 so we need to interate over our children
402            # and tell them to go away.
403          #          #
404          self.dockButton = wxButton(self.dockBorder, ID_BUTTON_DOCK,          for key in self.openWindows.keys():
405              "WWWWWW", style = wxGROW | wxBU_EXACTFIT | wxADJUST_MINSIZE)              win = self.openWindows[key]
406          buttonBox.Add(self.dockButton, 0, wxALIGN_RIGHT, 0)              win.Destroy()
407    
408            self.__update_lock -= 1
409    
410            # should really call _UpdateDocks() here but we don't need to
411            # since we're going away
412    
413        def CreateDock(self, name, id, title, align):
414    
415            if align in (wxLAYOUT_NONE, wxLAYOUT_LEFT, wxLAYOUT_RIGHT):
416                orient = wxLAYOUT_VERTICAL
417            else:
418                orient = wxLAYOUT_HORIZONTAL
419    
420            sash = wxSashLayoutWindow(self, id, style=wxNO_BORDER|wxSW_3D)
421            sash.SetOrientation(orient)
422            sash.SetAlignment(align)
423            sash.SetSashVisible(DockFrame.layout2oppSash[align], True)
424            sash.SetSashBorder(DockFrame.layout2oppSash[align], True)
425    
426            win = DockableWindow(self, id, name, title, sash, orient)
427    
428            self.__RegisterDock(name, win)
429            EVT_SASH_DRAGGED(self, id, self._OnSashDragged)
430    
431            return win
432    
433        def FindRegisteredDock(self, name):
434            return self.openWindows.get(name)
435    
436        def OnDockDestroy(self, win):
437            del self.openWindows[win.GetName()]
438            self._UpdateDocks()
439    
440        def SetMainWindow(self, main):
441            self.__mainWindow = main
442            self._UpdateDocks()
443            
444        def _UpdateDocks(self):
445            if self.__update_lock == 0:
446                wxLayoutAlgorithm().LayoutWindow(self, self.__mainWindow)
447    
448        def _OnSashDragged(self, event):
449            if event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE:
450                return
451    
452            id = event.GetId()
453            sash = self.FindWindowById(id)
454            #assert(isinstance(win, wxPanel))
455            dockPanel = sash.GetChildren()[0]
456            panel = dockPanel.FindWindowById(PANEL_ID)
457            assert isinstance(panel, DockPanel)
458            win = panel.GetDockParent()
459            assert isinstance(win, DockableWindow)
460    
461            assert win.IsDocked()
462    
463          #button = wxButton(self.dockBorder, ID_BUTTON_UNDOCK,          rect = event.GetDragRect()
         #                      _("Undock"),  
         #                      style = wxSIMPLE_BORDER | wxBU_EXACTFIT)  
         #buttonBox.Add(button, 0, wxALIGN_RIGHT, 0)  
464    
465          sizer.Add(buttonBox, 0, wxGROW, 0)          win.SetDockSize(rect)
466    
467          self.panel.Reparent(self.dockBorder)          self._UpdateDocks()
468    
469          sizer.Add(self.panel, 1, wxGROW | wxALL, 0)      def _OnSashSize(self, event):
470          self.dockBorder.SetSizer(sizer)          self._UpdateDocks()
         self.dockBorder.SetAutoLayout(True)  
471    
472          #self.dockBorderParent.SetAutoLayout(True)      def __RegisterDock(self, name, win):
473            if self.FindRegisteredDock(name) is not None:
474                raise ValueError(
475                    "A dockable window is already registered under the name '%s'" % name)
476    
477          EVT_BUTTON(self.dockBorder, ID_BUTTON_DOCK, self._OnDock)          self.openWindows[name] = win
         #EVT_BUTTON(self.dockBorder, ID_BUTTON_UNDOCK, self._OnUnDock)  
478    

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26