# # Python GUI - Windows - Gtk version # import sys import gtk from gtk import gdk from GUI import export from GUI import export from GUI.GGeometry import sub_pt from GUI import Component from GUI import Container from GUI import application from GUI.GWindows import Window as GWindow _default_width = 200 _default_height = 200 _modal_styles = ('modal_dialog', 'alert') _dialog_styles = ('nonmodal_dialog', 'modal_dialog', 'alert') class Window(GWindow): #_pass_key_events_to_platform = False _size = (_default_width, _default_height) _gtk_menubar = None _need_menubar_update = 0 _target = None def __init__(self, style = 'standard', title = "New Window", movable = 1, closable = 1, hidable = None, resizable = 1, zoomable = 1, **kwds): self._all_menus = [] modal = style in _modal_styles if hidable is None: hidable = not modal self._resizable = resizable gtk_win = gtk.Window(gtk.WINDOW_TOPLEVEL) gtk_win.set_gravity(gdk.GRAVITY_STATIC) gtk_win.set_decorated(style <> 'fullscreen' and (movable or closable or hidable or zoomable)) gtk_win.set_resizable(resizable) gtk_win.set_modal(style in _modal_styles) gtk_content = gtk.Layout() gtk_content.show() if style in _dialog_styles: gtk_win.set_type_hint(gdk.WINDOW_TYPE_HINT_DIALOG) gtk_win.add(gtk_content) else: self._gtk_create_menubar() gtk_box = gtk.VBox() gtk_box.show() gtk_box.pack_start(self._gtk_menubar, expand = 0, fill = 0) gtk_box.pack_end(gtk_content, expand = 1, fill = 1) gtk_win.add(gtk_box) self._need_menubar_update = 1 self._gtk_connect(gtk_win, 'configure-event', self._gtk_configure_event) self._gtk_connect(gtk_win, 'key-press-event', self._gtk_key_press_event) self._gtk_connect(gtk_win, 'delete-event', self._gtk_delete_event) GWindow.__init__(self, _gtk_outer = gtk_win, _gtk_inner = gtk_content, _gtk_focus = gtk_content, _gtk_input = gtk_content, style = style, title = title, closable = closable) if style == 'fullscreen': size = (gdk.screen_width(), gdk.screen_height()) else: size = (_default_width, _default_height) self.set_size(size) self.set(**kwds) self.become_target() def _gtk_create_menubar(self): gtk_menubar = gtk.MenuBar() gtk_dummy_item = gtk.MenuItem("") gtk_menubar.append(gtk_dummy_item) gtk_menubar.show_all() h = gtk_menubar.size_request()[1] gtk_menubar.set_size_request(-1, h) gtk_dummy_item.remove_submenu() self._gtk_menubar = gtk_menubar self._gtk_connect(gtk_menubar, 'button-press-event', self._gtk_menubar_button_press_event) def destroy(self): self.hide() GWindow.destroy(self) def set_menus(self, x): GWindow.set_menus(self, x) self._need_menubar_update = 1 if self.visible: self._gtk_update_menubar() def get_title(self): return self._gtk_outer_widget.get_title() def set_title(self, new_title): self._gtk_outer_widget.set_title(new_title) def set_position(self, v): self._position = v self._gtk_outer_widget.move(*v) def set_size(self, new_size): w, h = new_size if self._resizable: h += self._gtk_menubar_height() gtk_resize = self._gtk_outer_widget.resize else: gtk_resize = self._gtk_inner_widget.set_size_request gtk_resize(max(w, 1), max(h, 1)) self._size = new_size def _gtk_configure_event(self, gtk_event): gtk_win = self._gtk_outer_widget self._position = gtk_win.get_position() #self._update_size(gtk_win.get_size()) w, h = gtk_win.get_size() #w, h = self._gtk_inner_widget.get_size() #w, h = self._gtk_inner_widget.size_request() old_size = self._size new_size = (w, h - self._gtk_menubar_height()) #new_size = (w, h) #print "Window._gtk_configure_event:", old_size, "->", new_size ### self._size = new_size if old_size <> new_size: self._resized(sub_pt(new_size, old_size)) def get_visible(self): return self._gtk_outer_widget.get_property('visible') def set_visible(self, new_v): old_v = self.visible self._gtk_outer_widget.set_property('visible', new_v) if new_v and not old_v and self._need_menubar_update: self._gtk_update_menubar() def _show(self): self.set_visible(1) self._gtk_outer_widget.present() # def key_down(self, event): # if event.char == '\t': # if event.shift: # self._tab_to_prev() # else: # self._tab_to_next() # else: # self.pass_to_next_handler('key_down', event) def get_target(self): target = Component._gtk_find_component(self._gtk_outer_widget.get_focus()) return target or self def _screen_rect(self): w = gdk.screen_width() h = gdk.screen_height() return (0, 0, w, h) def _gtk_menubar_height(self): mb = self._gtk_menubar if mb: h = mb.size_request()[1] else: h = 0 #print "Window._gtk_menubar_height -->", h ### return h def _gtk_delete_event(self, event): try: self.close_cmd() except: sys.excepthook(*sys.exc_info()) return 1 def _gtk_update_menubar(self): # # Update the contents of the menubar after either the application # menu list or this window's menu list has changed. We only add # the menu titles at this stage; the menus themselves are attached # during menu setup. We also attach the accel groups associated # with the new menus. # # Things would be simpler if we could attach the menus here, # but attempting to share menus between menubar items provokes # a warning from Gtk, even though it otherwise appears to work. # gtk_menubar = self._gtk_menubar gtk_window = self._gtk_outer_widget # Remove old accel groups for menu in self._all_menus: gtk_window.remove_accel_group(menu._gtk_accel_group) # Detach any existing menus and remove old menu titles if gtk_menubar: for gtk_menubar_item in gtk_menubar.get_children(): gtk_menubar_item.remove_submenu() gtk_menubar_item.destroy() # Install new menu list #all_menus = application().menus + self.menus all_menus = application()._effective_menus_for_window(self) self._all_menus = all_menus # Create new menu titles and attach accel groups for menu in all_menus: if gtk_menubar: gtk_menubar_item = gtk.MenuItem(menu._title) gtk_menubar_item.show() gtk_menubar.append(gtk_menubar_item) gtk_window.add_accel_group(menu._gtk_accel_group) self._need_menubar_update = 0 def _gtk_menubar_button_press_event(self, event): # A button press has occurred in the menu bar. Before pulling # down the menu, perform menu setup and attach the menus to # the menubar items. self._gtk_menu_setup() for (gtk_menubar_item, menu) in \ zip(self._gtk_menubar.get_children(), self._all_menus): gtk_menu = menu._gtk_menu attached_widget = gtk_menu.get_attach_widget() if attached_widget and attached_widget is not gtk_menubar_item: attached_widget.remove_submenu() gtk_menubar_item.set_submenu(gtk_menu) def _gtk_key_press_event(self, gtk_event): # Intercept key presses with the Control key down and update # menus, in case this is a keyboard equivalent for a menu command. if gtk_event.state & gdk.CONTROL_MASK: #print "Window._gtk_key_press_event: doing menu setup" self._gtk_menu_setup() # It appears that GtkWindow caches accelerators, and updates # the cache in an idle task after accelerators change. This # would be too late for us, so we force it to be done now. self._gtk_outer_widget.emit("keys-changed") #print "Window._gtk_key_press_event: done menu setup" def _gtk_menu_setup(self): application()._perform_menu_setup(self._all_menus) def _default_key_event(self, event): self.pass_event_to_next_handler(event) if event._originator is self: event._not_handled = True def dispatch(self, message, *args): self.target.handle(message, *args) _gtk_menubar_height = None def _gtk_find_menubar_height(): global _gtk_menubar_height if _gtk_menubar_height is None: print "Windows: Finding menubar height" item = gtk.MenuItem("X") bar = gtk.MenuBar() bar.append(item) bar.show_all() w, h = bar.size_request() _gtk_menubar_height = h print "...done" return _gtk_menubar_height export(Window)