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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26