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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26