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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26