/[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 1527 - (show annotations)
Wed Jul 30 15:43:28 2003 UTC (21 years, 7 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/dock.py
File MIME type: text/x-python
File size: 14132 byte(s)
Add docstrings.

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 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 __version__ = "$Revision$"
18
19 import resource
20
21 from Thuban import _
22
23 from wxPython.wx import *
24
25 from Thuban.Lib.connector import Publisher
26
27 from dialogs import NonModalDialog
28
29 from messages import DOCKABLE_DOCKED, DOCKABLE_UNDOCKED, DOCKABLE_CLOSED
30
31 ID_BUTTON_DOCK = 4001
32 ID_BUTTON_CLOSE = 4002
33
34 PANEL_ID = 3141
35
36 DOCK_BMP = "dock_12"
37 UNDOCK_BMP = "undock_12"
38 CLOSE_BMP = "close_12"
39
40 class DockPanel(wxPanel):
41 """A DockPanel is a panel that should be derived from to create panels
42 that can be docked in a DockFrame.
43 """
44
45 def __init__(self, parent, id):
46 """parent should be a DockableWindow created from
47 DockFrame.CreateDock().
48 """
49
50 if not isinstance(parent, DockableWindow):
51 raise TypeError("")
52
53 wxPanel.__init__(self, parent.GetCurrentParent(), id)
54
55 self.parent = parent
56
57 #self.SetDockParent(None)
58 #parent.SetPanel(self)
59
60 def Create(self):
61 self.parent.SetPanel(self)
62
63 def SetDockParent(self, parent):
64 self.__dockParent = parent
65
66 def GetDockParent(self):
67 return self.__dockParent
68
69 def SetDock(self, dock):
70 """Specifically set the docked state of the panel
71 to dock (True or False).
72 """
73 #if dock == self.IsDocked(): return
74
75 if dock:
76 self.Dock()
77 else:
78 self.UnDock()
79
80 def Dock(self):
81 """Dock the panel in the DockFrame."""
82 self.GetDockParent().Dock()
83
84 def UnDock(self):
85 """Undock the panel in the DockFrame."""
86 self.GetDockParent().UnDock()
87
88 def IsDocked(self):
89 """Return True if the panel is docked."""
90 return self.GetDockParent().IsDocked()
91
92 class DockableWindow(Publisher):
93
94 def __getattr__(self, attr):
95 return getattr(self.__topWindow, attr)
96
97 def __init__(self, parent, id, name, title, dockWindow, orient):
98 """Create the dockable window.
99
100 Initially, the window is hidden, but in an undocked state.
101 """
102
103 if not isinstance(parent, DockFrame): raise TypeError("")
104
105 self.__parent = parent
106 self.__id = id
107 self.__name = name
108
109 self.__orientation = orient
110
111 self.__dockWindow = dockWindow
112 self.__floatWindow = wxFrame(parent, id, title)
113
114 self.__docked = False
115 if self.__docked:
116 self.__topWindow = self.__dockWindow
117 else:
118 self.__topWindow = self.__floatWindow
119
120 self.__floatSize = None
121 self.__floatPosition = None
122
123 self.__dockPanel = None
124 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 if not isinstance(panel, DockPanel):
141 raise TypeError("")
142
143 self.__panel = panel
144 self.__panel.SetDockParent(self)
145 self.__CreateBorder()
146
147 self.SetDock(self.__docked)
148
149 def GetPanel(self):
150 return self.__panel
151
152 def GetCurrentParent(self):
153 return self.__topWindow
154
155 def SetDock(self, dock):
156
157 self.__CheckAllGood()
158
159 if dock:
160 self.Dock()
161 else:
162 self.UnDock()
163
164 def Dock(self):
165 """Dock the window."""
166 self.__CheckAllGood()
167
168 wasVisible = self.IsShown()
169
170 if wasVisible: self.Show(False)
171
172 self.__docked = True
173
174 #
175 # save window information
176 #
177 self.__floatSize = self.GetSize()
178 self.__floatPosition = self.GetPosition()
179
180 #
181 # reparent
182 #
183 self.__topWindow = self.__dockWindow
184 self.__dockPanel.Reparent(self.__topWindow)
185
186 self.__dockButton.SetBitmapLabel(self.__bmpUnDock)
187 self.__dockButton.SetBitmapFocus(self.__bmpUnDock)
188 self.__dockButton.SetBitmapSelected(self.__bmpUnDock)
189 self.__dockButton.SetBitmapDisabled(self.__bmpUnDock)
190 self.__dockButton.SetToolTip(wxToolTip(_("Undock")))
191
192 self.SetDockSize(self.__dockWindow.GetSize())
193
194 if wasVisible: self.Show(True)
195
196 self.issue(DOCKABLE_DOCKED, self.__id, self)
197
198 def UnDock(self):
199 """Undock the window."""
200 self.__CheckAllGood()
201
202 wasVisible = self.IsShown()
203
204 if wasVisible: self.Show(False)
205
206 self.__docked = False
207
208 #
209 # reparent
210 #
211 self.__topWindow = self.__floatWindow
212 self.__dockPanel.Reparent(self.__topWindow)
213
214 self.__dockButton.SetBitmapLabel(self.__bmpDock)
215 self.__dockButton.SetBitmapFocus(self.__bmpDock)
216 self.__dockButton.SetBitmapSelected(self.__bmpDock)
217 self.__dockButton.SetBitmapDisabled(self.__bmpDock)
218 self.__dockButton.SetToolTip(wxToolTip(_("Dock")))
219
220 if wasVisible: self.Show()
221
222 #
223 # restore window information
224 #
225 if self.__floatPosition is not None:
226 self.SetPosition(self.__floatPosition)
227 if self.__floatSize is not None:
228 self.SetSize(self.__floatSize)
229
230 self.__dockPanel.SetSize(self.__topWindow.GetClientSize())
231
232 self.issue(DOCKABLE_UNDOCKED, self.__id, self)
233
234 def IsDocked(self):
235 self.__CheckAllGood()
236 return self.__docked
237
238 def Show(self, show = True):
239 """Show or hide the window."""
240 if show:
241 self.__DoShow()
242 else:
243 self.__DoHide()
244
245 def SetDockSize(self, rect = None):
246 """Set the size of the dock window to rect."""
247
248 w0, h0 = self.__dockPanel.GetBestSize()
249 w, h = self.__panel.GetBestSize()
250
251 if (w, h) < (w0, h0):
252 w = w0
253 h = h0
254
255 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
270
271 def Destroy(self):
272 self.__panel.Destroy()
273 self.__floatWindow.Destroy()
274 self.__dockWindow.Destroy()
275 self.__parent.OnDockDestroy(self)
276
277 ##
278 # Event handlers
279 #
280
281 def _OnButtonClose(self, event):
282 #self.Close()
283 self.Show(False)
284
285 def _OnClose(self, force = False):
286 self.Show(False)
287
288 def _OnToggleDock(self, event):
289 self.__CheckAllGood()
290
291 self.SetDock(not self.IsDocked())
292
293 ##
294 # Private methods
295 #
296
297 def __CheckAllGood(self):
298 if self.__panel is None:
299 raise TypeError("")
300
301 def __DoShow(self):
302 if self.IsShown(): return
303
304 self.__topWindow.Show()
305
306 if self.__topWindow is self.__dockWindow:
307 self.__parent._UpdateDocks()
308
309 def __DoHide(self):
310 if not self.IsShown(): return
311
312 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 self.__panel.Reparent(self.__dockPanel)
322 self.__panel.SetId(PANEL_ID)
323
324 if self.__orientation == wxLAYOUT_VERTICAL:
325 sizer = wxBoxSizer(wxVERTICAL)
326 headerBoxOrient = wxHORIZONTAL
327 else:
328 sizer = wxBoxSizer(wxHORIZONTAL)
329 headerBoxOrient = wxVERTICAL
330
331
332 headerBox = wxStaticBoxSizer(
333 wxStaticBox(self.__dockPanel, -1, ""), headerBoxOrient)
334
335 #
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 style = wxALIGN_CENTRE)
341 font = text.GetFont()
342 font.SetPointSize(10)
343 text.SetFont(font)
344
345 #
346 # load the dock/undock/close bitmaps
347 # and create the buttons
348 #
349 self.__bmpDock = \
350 resource.GetBitmapResource(DOCK_BMP, wxBITMAP_TYPE_XPM)
351 self.__bmpUnDock = \
352 resource.GetBitmapResource(UNDOCK_BMP, wxBITMAP_TYPE_XPM)
353
354 if self.__docked:
355 bmp = self.__bmpDock
356 else:
357 bmp = self.__bmpUnDock
358
359 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
365 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 #
374 # fill in the sizer in an order appropriate to the orientation
375 #
376 if self.__orientation == wxLAYOUT_VERTICAL:
377 headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
378 headerBox.Add(1, 5, 1, wxGROW)
379 headerBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
380 headerBox.Add(closeX, 0, wxALIGN_RIGHT | wxLEFT, 4)
381 else:
382 headerBox.Add(closeX, 0, wxALIGN_RIGHT | wxBOTTOM, 4)
383 headerBox.Add(self.__dockButton, 0, wxALIGN_RIGHT, 0)
384 headerBox.Add(text, 0, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL, 0)
385
386 sizer.Add(headerBox, 0, wxGROW, 0)
387 sizer.Add(self.__panel, 1, wxGROW, 0)
388
389
390 self.__dockPanel.SetAutoLayout(True)
391 self.__dockPanel.SetSizer(sizer)
392 sizer.SetSizeHints(self.__dockPanel)
393 sizer.SetSizeHints(self.__floatWindow)
394
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 """A DockFrame is a frame that will contain dockable panels."""
401
402 def __init__(self, parent, id, title, position, size):
403 wxFrame.__init__(self, parent, id, title, position, size)
404
405 self.openWindows = {}
406
407 self.__update_lock = 0
408
409 self.SetMainWindow(None)
410
411
412 EVT_SIZE(self, self._OnSashSize)
413 EVT_CLOSE(self, self.OnClose)
414
415 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
423 def OnClose(self, event):
424
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 def CreateDock(self, name, id, title, align):
442 """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
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 """Return a reference to a dock that has name."""
467 return self.openWindows.get(name)
468
469 def OnDockDestroy(self, win):
470 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 if self.__update_lock == 0:
479 wxLayoutAlgorithm().LayoutWindow(self, self.__mainWindow)
480
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 assert isinstance(panel, DockPanel)
491 win = panel.GetDockParent()
492 assert isinstance(win, DockableWindow)
493
494 assert win.IsDocked()
495
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