/[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 577 - (show annotations)
Mon Mar 31 18:31:33 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: 12382 byte(s)
(DockableWindow.UnDock): Restore size and
        position (although position doesn't work yet under GTK).
(DockableWindow.Destroy): New. Called when the window must be
        closed. Namely needed when the DockFrame closes and must close
        its children.
(DockFrame): Listen for EVT_CLOSE and destroy all children.

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.issue(DOCKABLE_UNDOCKED, self.__id, self)
201
202 def IsDocked(self):
203 self.__CheckAllGood()
204
205 return self.__docked
206
207
208 def Show(self, show = True):
209 if show:
210 self.__DoShow()
211 else:
212 self.__DoHide()
213
214 def SetDockSize(self, rect = None):
215
216 #
217 # adjust the size to get the
218 w0, h0 = self.__dockPanel.GetBestSize()
219 w, h = self.__panel.GetBestSize()
220
221 #print (w0, h0), (w, h)
222
223 if (w, h) < (w0, h0):
224 w = w0
225 h = h0
226
227 if rect is not None:
228 rw = rect.width
229 rh = rect.height
230 #print " ", (rw, rh)
231 if rw < w: rw = w
232 if rh < h: rh = h
233 else:
234 rw = w
235 rh = h
236
237 # these are to account for the border?!!?
238 rw += 8 # XXX: without this the sash isn't visible!?!?!?!
239 rh += 8 # XXX: without this the sash isn't visible!?!?!?!
240
241 self.__dockWindow.SetDefaultSize(wxSize(rw, rh))
242
243
244 def Destroy(self):
245 self.__panel.Destroy()
246 self.__floatWindow.Destroy()
247 self.__dockWindow.Destroy()
248 self.__parent.OnDockClose(self)
249
250 ##
251 # Event handlers
252 #
253
254 def _OnButtonClose(self, event):
255 self.Close()
256
257 def _OnClose(self, force = False):
258 self.Destroy()
259
260 def _OnToggleDock(self, event):
261 self.__CheckAllGood()
262
263 self.SetDock(not self.IsDocked())
264
265 ##
266 # Private methods
267 #
268
269 def __CheckAllGood(self):
270 if self.__panel is None:
271 raise TypeError("")
272
273 def __DoShow(self):
274 if self.IsShown(): return
275 #print "__DoShow()", self.IsShown()
276
277 self.__topWindow.Show()
278
279 #if self.IsDocked():
280 #self.SetDockSize()
281
282 if self.__topWindow is self.__dockWindow:
283 self.__parent._UpdateDocks()
284
285 def __DoHide(self):
286 if not self.IsShown(): return
287 #print "__DoHide()", self.IsShown()
288 self.__topWindow.Show(False)
289
290 if self.__topWindow is self.__dockWindow:
291 self.__parent._UpdateDocks()
292
293
294 def __CreateBorder(self):
295
296 #self.__panel.Reparent(self) # Make sure we hang on to the panel
297
298 self.__dockPanel = wxPanel(self.__topWindow, -1, style=wxSUNKEN_BORDER)
299 #self.__dockPanel.SetBackgroundColour(wxColour(255, 0, 0))
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 buttonBox = wxBoxSizer(wxHORIZONTAL)
313
314 #
315 # ideally, we should be able to rotate this text depending on
316 # our orientation
317 #
318 text = wxStaticText(self.__dockPanel, -1, self.GetTitle(),
319 style = wxSIMPLE_BORDER | wxALIGN_CENTRE)
320
321 #
322 # Perhaps using wxToggleButton would be better, but it's only
323 # supported under wxMSW and wxGTK as of v2.4.0.3
324 #
325 self.__dockButton = wxButton(self.__dockPanel, ID_BUTTON_DOCK, "WWWWWW",
326 style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
327
328 closeX = wxButton(self.__dockPanel, ID_BUTTON_CLOSE, "X",
329 style = wxBU_EXACTFIT | wxADJUST_MINSIZE)
330
331 buttonBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
332 buttonBox.Add(closeX, 0, wxALIGN_RIGHT, 0)
333
334 if self.__orientation == wxLAYOUT_VERTICAL:
335 headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
336 headerBox.Add(1, 20, 1, wxGROW)
337 headerBox.Add(buttonBox, 0, wxGROW | wxALIGN_RIGHT, 0)
338 else:
339 headerBox.Add(buttonBox, 0, wxGROW, 0)
340 headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
341
342 sizer.Add(headerBox, 0, wxGROW, 0)
343
344 self.__panel.Reparent(self.__dockPanel)
345 self.__panel.SetId(PANEL_ID)
346
347 sizer.Add(self.__panel, 1, wxGROW, 0)
348
349 sizer.Fit(self.__dockPanel)
350
351 self.__dockPanel.SetSizer(sizer)
352 self.__dockPanel.SetAutoLayout(True)
353
354 sizer.SetSizeHints(self.__dockPanel)
355
356 EVT_BUTTON(self.__dockPanel, ID_BUTTON_DOCK, self._OnToggleDock)
357 EVT_BUTTON(self.__dockPanel, ID_BUTTON_CLOSE, self._OnButtonClose)
358
359
360 class DockFrame(wxFrame):
361
362 def __init__(self, parent, id, title, position, size):
363 wxFrame.__init__(self, parent, id, title, position, size)
364
365 self.openWindows = {}
366
367 self.__update_lock = 0
368
369 self.SetMainWindow(None)
370
371
372 EVT_SIZE(self, self._OnSashSize)
373 EVT_CLOSE(self, self._OnClose)
374
375 layout2oppSash = {
376 wxLAYOUT_NONE : wxSASH_NONE,
377 wxLAYOUT_TOP : wxSASH_BOTTOM,
378 wxLAYOUT_LEFT : wxSASH_RIGHT,
379 wxLAYOUT_RIGHT : wxSASH_LEFT,
380 wxLAYOUT_BOTTOM : wxSASH_TOP }
381
382
383 def _OnClose(self, event):
384
385 self.__update_lock += 1
386
387 #
388 # child windows are not notified when the parent is destroyed
389 # as of v2.4.0.3 so we need to interate over our children
390 # and tell them to go away.
391 #
392 for key in self.openWindows.keys():
393 win = self.openWindows[key]
394 win.Destroy()
395
396 self.__update_lock -= 1
397
398 # should really call _UpdateDocks() here but we don't need to
399 # since we're going away
400
401 def CreateDock(self, name, id, title, align):
402
403 if align in (wxLAYOUT_NONE, wxLAYOUT_LEFT, wxLAYOUT_RIGHT):
404 orient = wxLAYOUT_VERTICAL
405 else:
406 orient = wxLAYOUT_HORIZONTAL
407
408 sash = wxSashLayoutWindow(self, id, style=wxNO_BORDER|wxSW_3D)
409 sash.SetOrientation(orient)
410 sash.SetAlignment(align)
411 #print align, DockFrame.layout2oppSash[align]
412 sash.SetSashVisible(DockFrame.layout2oppSash[align], True)
413 sash.SetSashBorder(DockFrame.layout2oppSash[align], True)
414
415 win = DockableWindow(self, id, name, title, sash, orient)
416
417 self.__RegisterDock(name, win)
418 EVT_SASH_DRAGGED(self, id, self._OnSashDragged)
419
420 return win
421
422 def FindRegisteredDock(self, name):
423 return self.openWindows.get(name)
424
425 def OnDockClose(self, win):
426 del self.openWindows[win.GetName()]
427 self._UpdateDocks()
428
429 def SetMainWindow(self, main):
430 self.__mainWindow = main
431 self._UpdateDocks()
432
433 def _UpdateDocks(self):
434 #print "_UpdateDocks()"
435 if self.__update_lock == 0:
436 wxLayoutAlgorithm().LayoutWindow(self, self.__mainWindow)
437
438 def _OnSashDragged(self, event):
439 if event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE:
440 return
441
442 id = event.GetId()
443 sash = self.FindWindowById(id)
444 #assert(isinstance(win, wxPanel))
445 dockPanel = sash.GetChildren()[0]
446 #print dockPanel
447 panel = dockPanel.FindWindowById(PANEL_ID)
448 #print panel
449 assert(isinstance(panel, DockPanel))
450 win = panel.GetDockParent()
451 #print win
452 assert(isinstance(win, DockableWindow))
453
454 assert(win.IsDocked())
455
456 rect = event.GetDragRect()
457
458 win.SetDockSize(rect)
459
460 self._UpdateDocks()
461
462 def _OnSashSize(self, event):
463 self._UpdateDocks()
464
465 def __RegisterDock(self, name, win):
466 if self.FindRegisteredDock(name) is not None:
467 raise ValueError(
468 "A dockable window is already registered under the name '%s'" % name)
469
470 self.openWindows[name] = win
471

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26