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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2560 - (hide annotations)
Tue Feb 8 20:25:22 2005 UTC (20 years ago) by bh
Original Path: trunk/thuban/Thuban/UI/dock.py
File MIME type: text/x-python
File size: 14134 byte(s)
Compatibility with wxPython 2.5.  The changes should make it work
better with 2.5 while still keeping compatibility with 2.4.  There
are still problems with 2.5, though.

* Thuban/UI/dock.py (DockableWindow.__CreateBorder): Pass the size
of a spacer as a single item.

* Thuban/UI/classifier.py (ClassGroupPropertiesCtrl): Derive only
from wxControl

* Thuban/UI/legend.py (LegendTree): When running with wxPython <
2.5, add an implementation of the GetFirstChild method that does
not require the second parameter.
(LegendTree.find_layer, LegendTree._OnMsgMapLayersAdded)
(LegendTree._OnMsgMapLayersRemoved, LegendTree.DeleteAllItems)
(LegendTree.DeleteChildren, LegendTree.__ShowHideLayer): Do not
pass the second parameter to GetFirstChild

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26