Attachment 'gtkmdi.py'
Download 1 #!/usr/bin/python
2 # -*- coding: UTF-8 -*-
3 '''模块名
4 @version: $Id$
5 @author: U{Jiahua Huang <[email protected]>}
6 @license: LGPL
7 '''
8
9 import gtk, gobject
10
11 import sys
12 _print = lambda *args: None
13 _print = lambda *args: sys.stdout.write(' '.join([str(i) for i in args]) + '\n')
14
15 try: import i18n
16 except: from gettext import gettext as _
17
18 class GtkMdiTabbar(gtk.Notebook):
19 homogeneous_tabs = False
20
21 def __init__(self):
22 self.__gobject_init__()
23 self.set_scrollable(True)
24 self.popup_enable()
25 self.set_homogeneous_tabs(self.homogeneous_tabs)
26 self.unset_flags(gtk.CAN_FOCUS)
27 ##
28 self._is_action_jn = False
29 ##
30 #self.connect("grab-focus", self.on_focus)
31 #self.connect("focus-tab", self.on_focus_tab)
32 self.connect("create-window", self.on_create_window)
33 self.connect("page-reordered", self.on_page_reordered)
34 self.connect("change-current-page", self.on_change_current_page)
35 self.connect("select-page", self.on_select_page)
36 self.connect("switch-page", self.on_switch_page)
37 pass
38
39 def add(self, child):
40 p = gtk.EventBox()
41 child.tab = p
42 p.p = child
43 label = gtk.Label(child.title)
44 self.append_page(p, label)
45 self.set_tab_detachable(p, True)
46 self.show_all()
47 pass
48
49 def action_tab(self, child):
50 n = self.page_num(child.tab)
51 self._is_action_jn = True
52 self.set_current_page(n)
53 pass
54
55 def get_child_by_n(self, n):
56 p = self.get_nth_page(n)
57 if p:
58 return p.p
59 return
60
61 def get_n_by_child(self, child):
62 return self.page_num(child.tab)
63
64 def on_focus_tab(self, widget, *args):
65 _print('on_focus_tab:', widget, args)
66 pass
67
68 def remove(self, child):
69 p = self.page_num(child.tab)
70 if p:
71 self.remove_page(p)
72 pass
73 pass
74
75 def on_focus(self, *args):
76 _print('on_focus:', args)
77 pass
78
79 def on_create_window(self, page, x, y, *args):
80 # when a detachable tab is dropped on the root window.
81 _print('on_create_window:', page, x, y, args)
82 pass
83
84 def on_page_reordered(self, widget, child, page_num, *args):
85 _print('on_page_reordered:', widget, child, page_num, args)
86 pass
87
88 def on_change_current_page(self, widget, offset, *args):
89 _print('on_change_current_page:', widget, offset, args)
90 pass
91
92 def on_switch_page(self, widget, page, page_num, *args):
93 if self._is_action_jn:
94 self._is_action_jn = False
95 return
96 _print('on_switch_page:', widget, page, page_num, args)
97 self.get_nth_page(page_num).p.action()
98 pass
99
100 def on_select_page(self, widget, move_focus, *args):
101 _print('on_select_page:', widget, move_focus, args)
102 pass
103
104 class GtkMdiWindow(gtk.EventBox):
105 __gtype_name__ = 'GtkMdiWindow'
106 __gsignals__ = {
107 'switch': (gobject.SIGNAL_RUN_LAST, None, ()),
108 }
109 bg_title = gtk.gdk.Color('#377F0C')
110 fg_title = gtk.gdk.Color('#ffffff')
111 defalut_max = False
112 def __init__(self, child=gtk.Alignment(), title="", icon=None, skiptaskbar=False):
113 self.__gobject_init__()
114 self.title = title
115 self.icon = icon
116 self._is_in_move = False
117 self._is_in_resize_rb = False
118 self._is_max = False
119 self._is_min = False
120 ##
121 self._old_x = 0
122 self._old_y = 0
123 self.modify_bg(gtk.STATE_NORMAL, self.bg_title)
124 ##
125 self._child = child
126 self.child_focus = child.child_focus
127 self.child_get = child.child_get
128 self.child_get_property = child.child_get_property
129 self.child_notify = child.child_notify
130 self.children = child.children
131 self.child_set = child.child_set
132 self.child_set_property = child.child_set_property
133 self.child_type = child.child_type
134 ##
135 self.unset_flags(gtk.CAN_FOCUS)
136 self.connect("set_focus_child", self.on_focus)
137 self.connect("grab_focus", self.on_focus)
138 ## move, resize
139 self.connect("event", self.on_title_event)
140 ##
141 self.vbox1 = gtk.VBox(False, 0)
142 ## MDI Window Border
143 self.vbox1.set_border_width(3)
144 #self.vbox1.connect("set_focus_child", self.on_focus)
145 #self.vbox1.connect("grab_focus", self.on_focus)
146 #self.vbox1.connect("expose_event", self.on_focus)
147 #self.vbox1.connect("focus", self.on_focus)
148
149 ## simulate MDI Window Title
150 self.titlebar = gtk.HBox(False, 0)
151 self.titlebar.unset_flags(gtk.CAN_FOCUS)
152 self.titlebar.show()
153
154 self.icon_label = gtk.Label("")
155 self.icon_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
156 self.icon_label.set_padding(5, 0)
157 self.icon_label.set_markup("v")
158 self.icon_label.show()
159 ##
160 eventbox = gtk.EventBox()
161 eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
162 eventbox.connect("button_release_event", self.on_icon)
163 eventbox.add(self.icon_label)
164 self.titlebar.pack_start(eventbox, False, False, 0)
165
166 self.title_label = gtk.Label(title)
167 self.title_label.set_padding(10, 0)
168 self.title_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
169 self.title_label.show()
170 self.titlebar.pack_start(self.title_label)
171
172
173 ## min, max, close button
174 self.min_label = gtk.Label("")
175 self.min_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
176 self.min_label.set_padding(5, 0)
177 self.min_label.set_tooltip_markup(_("Iconify Window"))
178 self.min_label.set_markup("_")
179 self.min_label.show()
180 ##
181 eventbox = gtk.EventBox()
182 eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
183 eventbox.connect("button_press_event", self.on_min)
184 eventbox.add(self.min_label)
185 self.titlebar.pack_start(eventbox, False, False, 0)
186
187 self.max_label = gtk.Label("")
188 self.max_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
189 self.max_label.set_padding(5, 0)
190 self.max_label.set_tooltip_markup(_("Maximize Window"))
191 self.max_label.set_markup("+")
192 self.max_label.show()
193 ##
194 eventbox = gtk.EventBox()
195 eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
196 eventbox.connect("button_release_event", self.on_max)
197 eventbox.add(self.max_label)
198 self.titlebar.pack_start(eventbox, False, False, 0)
199
200 self.close_label = gtk.Label("")
201 self.close_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
202 self.close_label.modify_bg(gtk.STATE_NORMAL, self.bg_title)
203 self.close_label.set_padding(5, 0)
204 self.close_label.set_tooltip_markup(_("Close Window"))
205 self.close_label.set_markup("x")
206 self.close_label.show()
207 ##
208 eventbox = gtk.EventBox()
209 eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
210 eventbox.connect("button_release_event", self.on_close)
211 eventbox.add(self.close_label)
212 self.titlebar.pack_start(eventbox, False, False, 0)
213
214 self.vbox1.pack_start(self.titlebar, False, False, 0)
215
216 ## MDI Window Area
217 #self.mdi_alignment = gtk.Alignment(0.5, 0.5, 0, 0)
218 #self.mdi_alignment.show()
219 #self.vbox1.pack_start(self.mdi_alignment)
220 self._child_box = gtk.EventBox()
221 self._child_box.add(self._child)
222 self.vbox1.pack_start(self._child_box, True, True, 0)
223 ##
224 self.add(self.vbox1)
225 self.show_all()
226 pass
227
228 def _raise(self, *args):
229 try:
230 window = self.get_window() or self.get_window(1)
231 if window:
232 gtk.gdk.Window.raise_(window)
233 self.emit("switch", )
234 pass
235 pass
236 except:
237 pass
238 pass
239
240 def lower(self, *args):
241 try:
242 window = self.get_window() or self.get_window(1)
243 if window:
244 gtk.gdk.Window.lower(window)
245 pass
246 pass
247 except:
248 pass
249 pass
250
251 def action(self):
252 _print('action:', self)
253 if self._is_min:
254 self.unmax()
255 pass
256 self._raise()
257 self._child.grab_focus()
258 pass
259
260 def on_focus(self, widget, *args):
261 _print('on_focus:', widget, args)
262 self._raise()
263 if widget and 'mditabbar' in self.parent.parent.__dict__:
264 mditabbar = self.parent.parent.mditabbar
265 mditabbar.action_tab(self)
266 pass
267 pass
268
269 def on_title_event(self, widget, event):
270 #_print('on_title_event', widget, event)
271 # for move
272 if event.type == gtk.gdk.BUTTON_PRESS:
273 if event.button == 3:
274 self.on_menu(widget, event)
275 return
276 else:
277 self.on_focus(self)
278 self._child.grab_focus()
279 self._px, self._py = self.parent.get_pointer()
280 ## MdiWindow x, y
281 self._wx, self._wy = self.get_window().get_position()
282 ## MdiArea width, height
283 i, t, self._aw, self._ah = self.parent.get_allocation()
284 ## MdiWindow width, height
285 i, t, self._w, self._h = self.get_allocation()
286 ##
287 self._ox = self._wx - self._px
288 self._oy = self._wy - self._py
289 if self._w - event.x < 20 and self._h - event.y < 20:
290 self._is_in_resize_rb = True
291 pass
292 else:
293 self._is_in_move = True
294 pass
295 return
296 return
297 elif event.type == gtk.gdk.BUTTON_RELEASE:
298 self._is_in_move = False
299 self._is_in_resize_rb = False
300 return
301 ## move MdiWindow
302 elif self._is_in_move and event.type == gtk.gdk.MOTION_NOTIFY:
303 px, py = self.parent.get_pointer()
304 if px < 5: px = 5
305 if py < 0: py = 0
306 if px > self._aw: px = self._aw
307 if py > self._ah: py = self._ah
308 mx = px + self._ox
309 my = py + self._oy
310 #self.move(mx, my)
311 self.parent.move(self, mx, my)
312 return
313 ## resize MdiWindow
314 elif self._is_in_resize_rb and event.type == gtk.gdk.MOTION_NOTIFY:
315 x, y = event.x, event.y
316 px, py = self.parent.get_pointer()
317 if x < 30: x = 30
318 if y < 30: y = 30
319 if px > self._aw: x = self.get_allocation()[2]
320 if py > self._ah: y = self.get_allocation()[3]
321 self.set_size_request(int(x), int(y))
322 return
323 pass
324
325 def on_menu(self, widget, event):
326 _print('on_menu:', widget, event)
327 pass
328
329 def on_icon(self, widget, event):
330 if event.button == 1:
331 _print('on_icon:', widget, event)
332 pass
333
334 def on_min(self, widget, event):
335 if event.button == 1:
336 _print('on_min:', widget, event)
337 self.min()
338 pass
339
340 def on_unmax(self, widget, event):
341 if event.button != 1: return
342 _print('on_unmax:', widget, event)
343 self.unmax()
344
345
346 def on_max(self, widget, event):
347 if event.button != 1: return
348 self.max()
349 pass
350
351 def on_close(self, widget, event):
352 if event.button == 1:
353 _print('on_close:', widget, event)
354 self.close()
355 pass
356 pass
357
358 def move(self, x, y):
359 _print('move:', x, y)
360 self.parent.move(self, x, y)
361 pass
362
363 def min(self, *args):
364 self._is_min = True
365 # save MdiWindow position x, y
366 self._old_wx, self._old_wy = self.get_window().get_position()
367 # save MdiWindow width, height
368 i, t, self._old_w, self._old_h = self.get_allocation()
369 self.parent.grab_focus()
370 #self.lower()
371 self.hide()
372 if 'mditabbar' in self.parent.parent.__dict__:
373 mditabbar = self.parent.parent.mditabbar
374 mditabbar.next_page()
375 pass
376 pass
377
378 def max(self, *args):
379 i, t, self._w, self._h = self.get_allocation()
380 i, t, self._aw, self._ah = self.parent.get_allocation()
381 if self._w < self._aw or self._h < self._ah:
382 self._is_max = False
383 pass
384 if self._is_max: return self.unmax()
385 ##
386 self._is_max = True
387 self._is_min = False
388 # save MdiWindow position x, y
389 self._old_wx, self._old_wy = self.get_window().get_position()
390 # save MdiWindow width, height
391 i, t, self._old_w, self._old_h = self.get_allocation()
392 self.move(0, 0)
393 self.set_size_request(self._aw, self._ah)
394 pass
395
396 def unmax(self, *args):
397 self._is_max = False
398 self._is_min = False
399 self.set_size_request(self._old_w, self._old_h)
400 self.move(self._old_wx, self._old_wy)
401 self.show_all()
402 pass
403
404 def close(self, *args):
405 if 'mditabbar' in self.parent.parent.__dict__:
406 mditabbar = self.parent.parent.mditabbar
407 mditabbar.remove(self)
408 pass
409 self.destroy()
410 pass
411
412 class GtkMdiArea(gtk.Layout):
413 __gtype_name__ = 'GtkMdiArea'
414 __gsignals__ = {
415 'switch-window': (gobject.SIGNAL_RUN_LAST, None, (gtk.Widget,)),
416 }
417 need_resize = 1L
418 def __init__(self):
419 self.__gobject_init__()
420 #self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color("#003300"))
421 self._old_w = 0
422 self._old_h = 0
423 self.unset_flags(gtk.CAN_FOCUS)
424 self.connect("size-allocate", self.on_resize)
425 pass
426
427 def add(self, mdiwindow, x=0, y=0):
428 gtk.Layout.put(self, mdiwindow, x, y)
429 mdiwindow.connect("switch", self.on_switch)
430 pass
431
432 def on_resize(self, widget, rectangle):
433 i, t, w, h = rectangle
434 if self._old_w == w and self._old_h == h:
435 return
436 _print('on_resize:', widget, rectangle)
437 self._old_w, self._old_h = w, h
438 for p in self.children():
439 if p._is_max:
440 p.set_size_request(w, h)
441 pass
442 pass
443 pass
444
445 def on_switch(self, widget, *args):
446 _print('on_switch', self, widget, args)
447 self.emit("switch-window", widget)
448 if 'mditabbar' in self.parent.__dict__:
449 mditabbar = self.parent.mditabbar
450 mditabbar.action_tab(widget)
451 pass
452 pass
453
454 class GtkMdi(gtk.Table):
455 def __init__(self):
456 self.__gobject_init__()
457 self.mdiarea = GtkMdiArea()
458 self.mditabbar = GtkMdiTabbar()
459 ## table.attach(widget, left_attach=0, right_attach=1, top_attach=0, bottom_attach=1)
460 self.attach(self.mditabbar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 0, 0)
461 self.attach(self.mdiarea, 0, 1, 1, 2)
462 pass
463
464 def set_tab_pos(self, pos):
465 # pos: 0: left, 1: right, 2: top, 3: bottom
466 pass
467
468 def add(self, mdiwindow, x=0, y=0):
469 self.mdiarea.add(mdiwindow, x, y)
470 self.mditabbar.add(mdiwindow)
471 pass
472
473 def tab_top(self, *args):
474 pass
475
476
477 def _demo():
478 _print('main')
479 w = gtk.Window()
480 w.set_title("Test MDI")
481 w.set_default_size(500, 500)
482 mdi = GtkMdi()
483 ##
484 ts = gtk.ScrolledWindow()
485 ts.add(gtk.TextView())
486 ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
487 ts.set_size_request(150, 150)
488 mw = GtkMdiWindow(ts, 'MDI Document 1')
489 mdi.add(mw, 0, 0)
490 ##
491 ts = gtk.ScrolledWindow()
492 ts.add(gtk.TextView())
493 ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
494 ts.set_size_request(150, 150)
495 mw = GtkMdiWindow(ts, 'MDI Document 2')
496 mdi.add(mw, 30, 30)
497 ##
498 ts = gtk.ScrolledWindow()
499 ts.add(gtk.TextView())
500 ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
501 ts.set_size_request(150, 150)
502 mw = GtkMdiWindow(ts, 'MDI Document 3')
503 mdi.add(mw, 60, 60)
504
505
506 w.add(mdi)
507 w.show_all()
508 w.connect('delete-event', gtk.main_quit)
509 gtk.main()
510
511 if __name__=="__main__":
512 _demo()
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.
