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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 631 - (show annotations)
Wed Apr 9 10:10:38 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/dock.py
File MIME type: text/x-python
File size: 12461 byte(s)
It was decided that if the user closes
a dockable window the window should simply hide itself. That
way if the user wants to show the dock again it appears in the
same place as it was when it was closed.
(DockableWindow.Destroy): Call renamed method OnDockDestroy().
(DockableWindow._OnButtonClose): Hide the window instead of
        destroying it.
(DockableWindow._OnClose): Hide the window instead of destroying it.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26