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