/[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 659 - (hide annotations)
Mon Apr 14 14:07:05 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/dock.py
File MIME type: text/x-python
File size: 13736 byte(s)
Fixes some window resizing problems most noticable under windows.

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     """Classes for creating dockable windows"""
9    
10     __version__ = "$Revision$"
11    
12 jonathan 651 import resource
13    
14 jonathan 561 from Thuban import _
15    
16     from wxPython.wx import *
17    
18     from Thuban.Lib.connector import Publisher
19    
20 jonathan 566 from dialogs import NonModalDialog
21    
22 jonathan 561 from messages import DOCKABLE_DOCKED, DOCKABLE_UNDOCKED, DOCKABLE_CLOSED
23    
24     ID_BUTTON_DOCK = 4001
25 jonathan 571 ID_BUTTON_CLOSE = 4002
26 jonathan 561
27 jonathan 571 PANEL_ID = 3141
28    
29 jonathan 651 DOCK_BMP = "dock_12"
30     UNDOCK_BMP = "undock_12"
31     CLOSE_BMP = "close_12"
32    
33 jonathan 561 class DockPanel(wxPanel):
34    
35     def __init__(self, parent, id):
36    
37 jonathan 571 if not isinstance(parent, DockableWindow):
38     raise TypeError("")
39 jonathan 561
40 jonathan 571 wxPanel.__init__(self, parent.GetCurrentParent(), id)
41 jonathan 561
42 jonathan 659 self.parent = parent
43    
44 jonathan 571 #self.SetDockParent(None)
45 jonathan 659 #parent.SetPanel(self)
46 jonathan 571
47 jonathan 659 def Create(self):
48     self.parent.SetPanel(self)
49    
50 jonathan 561 def SetDockParent(self, parent):
51 jonathan 571 self.__dockParent = parent
52 jonathan 561
53     def GetDockParent(self):
54 jonathan 571 return self.__dockParent
55 jonathan 561
56 jonathan 571 def SetDock(self, dock):
57     #if dock == self.IsDocked(): return
58    
59     if dock:
60     self.Dock()
61     else:
62     self.UnDock()
63    
64 jonathan 561 def Dock(self):
65     self.GetDockParent().Dock()
66    
67     def UnDock(self):
68     self.GetDockParent().UnDock()
69    
70     def IsDocked(self):
71     return self.GetDockParent().IsDocked()
72    
73 jonathan 571 class DockableWindow(Publisher):
74 jonathan 561
75 jonathan 571 def __getattr__(self, attr):
76     return getattr(self.__topWindow, attr)
77    
78 jonathan 659 def __init__(self, parent, id, name, title, dockWindow, orient):
79     """Create the dockable window.
80 jonathan 561
81 jonathan 659 Initially, the window is hidden, but in an undocked state.
82     """
83    
84 jonathan 571 if not isinstance(parent, DockFrame): raise TypeError("")
85 jonathan 561
86 jonathan 571 self.__parent = parent
87     self.__id = id
88     self.__name = name
89 jonathan 561
90 jonathan 571 self.__orientation = orient
91 jonathan 561
92 jonathan 571 self.__dockWindow = dockWindow
93     self.__floatWindow = wxFrame(parent, id, title)
94 jonathan 561
95 jonathan 571 self.__docked = False
96     if self.__docked:
97     self.__topWindow = self.__dockWindow
98     else:
99     self.__topWindow = self.__floatWindow
100 jonathan 561
101 jonathan 571 self.__floatSize = None
102     self.__floatPosition = None
103    
104 jonathan 659 self.__dockPanel = None
105 jonathan 571 self.__panel = None
106    
107     self.__dockWindow.Hide()
108     self.__floatWindow.Hide()
109    
110     EVT_CLOSE(self, self._OnClose)
111    
112     ##
113     # Public methods
114     #
115    
116     def GetName(self):
117     return self.__name
118    
119     def SetPanel(self, panel):
120    
121 jonathan 561 if not isinstance(panel, DockPanel):
122     raise TypeError("")
123    
124 jonathan 571 self.__panel = panel
125     self.__panel.SetDockParent(self)
126 jonathan 561 self.__CreateBorder()
127 jonathan 571
128     self.SetDock(self.__docked)
129    
130     def GetPanel(self):
131     return self.__panel
132 jonathan 561
133 jonathan 571 def GetCurrentParent(self):
134     return self.__topWindow
135    
136 jonathan 561 def SetDock(self, dock):
137 jonathan 571
138     self.__CheckAllGood()
139    
140 jonathan 561 if dock:
141     self.Dock()
142     else:
143     self.UnDock()
144    
145     def Dock(self):
146 jonathan 571 self.__CheckAllGood()
147 jonathan 561
148 jonathan 571 wasVisible = self.IsShown()
149 jonathan 561
150 jonathan 571 if wasVisible: self.Show(False)
151 jonathan 561
152 jonathan 571 self.__docked = True
153 jonathan 561
154 jonathan 571 #
155     # save window information
156     #
157     self.__floatSize = self.GetSize()
158     self.__floatPosition = self.GetPosition()
159 jonathan 561
160 jonathan 571 #
161     # reparent
162     #
163     self.__topWindow = self.__dockWindow
164     self.__dockPanel.Reparent(self.__topWindow)
165 jonathan 561
166 jonathan 657 if self.__bmpUnDock is not None:
167     self.__dockButton.SetBitmapLabel(self.__bmpUnDock)
168     self.__dockButton.SetBitmapFocus(self.__bmpUnDock)
169 jonathan 651 self.__dockButton.SetToolTip(wxToolTip(_("Undock")))
170     else:
171     self.__dockButton.SetLabel(_("Undock"))
172 jonathan 561
173 jonathan 571 self.SetDockSize(self.__dockWindow.GetSize())
174 jonathan 561
175 jonathan 571 if wasVisible: self.Show(True)
176    
177     #self.__parent._UpdateDocks()
178    
179     self.issue(DOCKABLE_DOCKED, self.__id, self)
180    
181 jonathan 561 def UnDock(self):
182 jonathan 571 self.__CheckAllGood()
183 jonathan 561
184 jonathan 571 wasVisible = self.IsShown()
185 jonathan 561
186 jonathan 571 if wasVisible: self.Show(False)
187    
188     self.__docked = False
189 jonathan 561
190 jonathan 571 #
191     # reparent
192     #
193     self.__topWindow = self.__floatWindow
194     self.__dockPanel.Reparent(self.__topWindow)
195 jonathan 561
196 jonathan 657 if self.__bmpDock is not None:
197     self.__dockButton.SetBitmapLabel(self.__bmpDock)
198     self.__dockButton.SetBitmapFocus(self.__bmpDock)
199 jonathan 651 self.__dockButton.SetToolTip(wxToolTip(_("Dock")))
200     else:
201     self.__dockButton.SetLabel(_("Dock"))
202 jonathan 561
203 jonathan 571 if wasVisible: self.Show()
204 jonathan 561
205 jonathan 571 #
206     # restore window information
207     #
208 jonathan 577 if self.__floatPosition is not None: self.SetPosition(self.__floatPosition)
209     if self.__floatSize is not None: self.SetSize(self.__floatSize)
210 jonathan 561
211 jonathan 620 self.__dockPanel.SetSize(self.__topWindow.GetClientSize())
212    
213 jonathan 571 self.issue(DOCKABLE_UNDOCKED, self.__id, self)
214 jonathan 561
215     def IsDocked(self):
216 jonathan 571 self.__CheckAllGood()
217 jonathan 561
218 jonathan 571 return self.__docked
219 jonathan 561
220    
221 jonathan 571 def Show(self, show = True):
222     if show:
223     self.__DoShow()
224     else:
225     self.__DoHide()
226 jonathan 561
227 jonathan 571 def SetDockSize(self, rect = None):
228 jonathan 561
229 jonathan 571 w0, h0 = self.__dockPanel.GetBestSize()
230     w, h = self.__panel.GetBestSize()
231 jonathan 561
232 jonathan 571 if (w, h) < (w0, h0):
233     w = w0
234     h = h0
235 jonathan 659
236 jonathan 571 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 jonathan 561
251    
252 jonathan 577 def Destroy(self):
253     self.__panel.Destroy()
254 jonathan 571 self.__floatWindow.Destroy()
255     self.__dockWindow.Destroy()
256 jonathan 631 self.__parent.OnDockDestroy(self)
257 jonathan 577
258 jonathan 571 ##
259     # Event handlers
260     #
261 jonathan 561
262 jonathan 571 def _OnButtonClose(self, event):
263 jonathan 583 #self.Close()
264 jonathan 631 self.Show(False)
265 jonathan 561
266 jonathan 571 def _OnClose(self, force = False):
267 jonathan 631 self.Show(False)
268 jonathan 561
269 jonathan 571 def _OnToggleDock(self, event):
270     self.__CheckAllGood()
271 jonathan 561
272 jonathan 571 self.SetDock(not self.IsDocked())
273 jonathan 561
274 jonathan 571 ##
275     # Private methods
276     #
277 jonathan 561
278 jonathan 571 def __CheckAllGood(self):
279     if self.__panel is None:
280     raise TypeError("")
281 jonathan 561
282 jonathan 571 def __DoShow(self):
283     if self.IsShown(): return
284 jonathan 561
285 jonathan 571 self.__topWindow.Show()
286 jonathan 561
287 jonathan 571 #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     if self.__topWindow is self.__dockWindow:
298     self.__parent._UpdateDocks()
299    
300    
301     def __CreateBorder(self):
302    
303     #self.__panel.Reparent(self) # Make sure we hang on to the panel
304    
305     self.__dockPanel = wxPanel(self.__topWindow, -1, style=wxSUNKEN_BORDER)
306    
307 jonathan 657 self.__panel.Reparent(self.__dockPanel)
308     self.__panel.SetId(PANEL_ID)
309    
310 jonathan 571 if self.__orientation == wxLAYOUT_VERTICAL:
311     sizer = wxBoxSizer(wxVERTICAL)
312     headerBoxOrient = wxHORIZONTAL
313 jonathan 561 else:
314 jonathan 571 sizer = wxBoxSizer(wxHORIZONTAL)
315     headerBoxOrient = wxVERTICAL
316    
317 jonathan 561
318 jonathan 571 headerBox = wxStaticBoxSizer(
319     wxStaticBox(self.__dockPanel, -1, ""), headerBoxOrient)
320 jonathan 561
321 jonathan 651 #buttonBox = wxBoxSizer(wxHORIZONTAL)
322 jonathan 561
323 jonathan 571 #
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 jonathan 620 style = wxALIGN_CENTRE)
329 jonathan 561
330 jonathan 651 font = text.GetFont()
331     font.SetPointSize(10)
332     text.SetFont(font)
333    
334 jonathan 561 #
335     # Perhaps using wxToggleButton would be better, but it's only
336     # supported under wxMSW and wxGTK as of v2.4.0.3
337     #
338 jonathan 657 self.__bmpDock = \
339 jonathan 651 resource.GetBitmapResource(DOCK_BMP, wxBITMAP_TYPE_XPM)
340 jonathan 657 self.__bmpUnDock = \
341 jonathan 651 resource.GetBitmapResource(UNDOCK_BMP, wxBITMAP_TYPE_XPM)
342 jonathan 561
343 jonathan 657 if self.__bmpDock is not None \
344     and self.__bmpUnDock is not None:
345 jonathan 651 self.__dockButton = wxBitmapButton(
346     self.__dockPanel, ID_BUTTON_DOCK,
347 jonathan 657 self.__bmpUnDock,
348     size = wxSize(self.__bmpDock.GetWidth() + 4,
349     self.__bmpDock.GetHeight() + 4),
350 jonathan 651 style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
351     else:
352 jonathan 657 self.__bmpDock = \
353     self.__bmpUnDock = None
354 jonathan 561
355 jonathan 651 self.__dockButton = wxButton(
356     self.__dockPanel, ID_BUTTON_DOCK,
357     "WW", style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
358 jonathan 561
359 jonathan 651 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 jonathan 571 if self.__orientation == wxLAYOUT_VERTICAL:
375     headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
376 jonathan 651 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 jonathan 571 else:
380 jonathan 651 headerBox.Add(closeX, 0, wxALIGN_RIGHT | wxBOTTOM, 4)
381     headerBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
382 jonathan 571 headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
383 jonathan 561
384 jonathan 571 sizer.Add(headerBox, 0, wxGROW, 0)
385     sizer.Add(self.__panel, 1, wxGROW, 0)
386 jonathan 561
387 jonathan 659 self.__dockPanel.SetAutoLayout(True)
388     self.__dockPanel.SetSizer(sizer)
389     sizer.SetSizeHints(self.__dockPanel)
390 jonathan 571
391 jonathan 659 sizer.SetSizeHints(self.__topWindow)
392 jonathan 571
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 jonathan 577 self.__update_lock = 0
405 jonathan 571
406     self.SetMainWindow(None)
407    
408 jonathan 577
409     EVT_SIZE(self, self._OnSashSize)
410     EVT_CLOSE(self, self._OnClose)
411    
412 jonathan 571 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 jonathan 577
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 jonathan 571 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 jonathan 631 def OnDockDestroy(self, win):
462 jonathan 571 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 jonathan 577 if self.__update_lock == 0:
471     wxLayoutAlgorithm().LayoutWindow(self, self.__mainWindow)
472 jonathan 571
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 jonathan 605 assert isinstance(panel, DockPanel)
483 jonathan 571 win = panel.GetDockParent()
484 jonathan 605 assert isinstance(win, DockableWindow)
485 jonathan 571
486 jonathan 605 assert win.IsDocked()
487 jonathan 571
488     rect = event.GetDragRect()
489    
490     win.SetDockSize(rect)
491    
492     self._UpdateDocks()
493    
494     def _OnSashSize(self, event):
495     self._UpdateDocks()
496    
497     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     self.openWindows[name] = win
503    

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26