# # Python GUI - Windows - Generic # import Exceptions from GUI.Properties import overridable_property from GUI import Container from GUI import application class Window(Container): """Top-level Container.""" menus = overridable_property('menus', "Menus to be available when this window is active.") document = overridable_property('document', "Document with which this window is associated.") title = overridable_property('title', "Title of the window.") auto_position = overridable_property('auto_position', "Whether to position automatically when first shown.") target = overridable_property('target', "Current target for key events and menu messages.") tab_chain = overridable_property('tab_chain', "List of subcomponents in tabbing order.") visible = overridable_property('visible', "Whether the window is currently shown.") keeps_document_open = True _default_width = 200 _default_height = 200 _modal_styles = ('modal_dialog', 'alert') _dialog_styles = ('nonmodal_dialog', 'modal_dialog', 'alert') _menus = [] _document = None _closable = 0 _auto_position = True _tab_chain = None def __init__(self, style = 'standard', closable = None, **kwds): if closable is None: raise Exceptions.InternalError( "'closable' parameter unspecified in call to generic Window.__init__") Container.__init__(self, **kwds) self._style = style self._dialog_style = style.find('dialog') >= 0 self._closable = closable application()._add_window(self) def destroy(self): """Detaches the window from document and application and removes it from the screen.""" self.set_document(None) application()._remove_window(self) Container.destroy(self) # # Message handling # def next_handler(self): if self._document: return self._document else: return application() def dispatch(self, message, *args): self.target.handle(message, *args) # # Menus # def get_menus(self): return self._menus def set_menus(self, x): self._menus = x # # Document association # def get_document(self): return self._document def set_document(self, x): if self._document != x: if self._document: self._document._windows.remove(self) self._document = x if self._document: self._document._windows.append(self) self.update_title() # # Title # def update_title(self): """Update the window's title after a change in its document's title.""" doc = self._document if doc: self.set_title(doc.title) # # Showing and Positioning # def get_auto_position(self): return self._auto_position def set_auto_position(self, v): self._auto_position = v def center(self): """Position the window in the centre of the screen.""" print "GWindow.center" ### sl, st, sr, sb = self._screen_rect() w, h = self.size l = (sr - sl - w) // 2 t = (sb - st - h) // 2 self.position = (l, t) def centre(self): self.center() def show(self): if self._auto_position: if self._style == 'standard': self._stagger() else: self.center() self._auto_position = False self._show() def _stagger(self): pass def _show(self): self.visible = True def hide(self): self.visible = False # # Menu commands # def setup_menus(self, m): Container.setup_menus(self, m) app = application() if self._closable: m.close_cmd.enabled = 1 def close_cmd(self): """If this window is the only window belonging to a document whose keeps_document_open attribute is true, then close the document, else destroy the window.""" # app = application() # if not app._may_close_a_window(): # #print "GWindow.close_cmd: Quitting the application" ### # app.quit_cmd() # else: doc = self._document n = 0 if doc: for win in doc._windows: if win is not self and win.keeps_document_open: n += 1 if doc and n == 0: doc.close_cmd() else: self.destroy() # # Tabbing # def get_tab_chain(self): chain = self._tab_chain if chain is None: chain = [] self._build_tab_chain(chain) self._tab_chain = chain #print "Window.get_tab_chain:", chain ### return chain def _invalidate_tab_chain(self): self._tab_chain = None def _tab_to_next(self): self._tab_to(1) def _tab_to_prev(self): self._tab_to(-1) def _tab_to(self, direction): #print "GWindow._tab_to:", direction ### chain = self.tab_chain if chain: old_target = application().target new_target = None n = len(chain) try: i = chain.index(old_target) except ValueError: if direction > 0: i = -1 else: i = n k = n while k: k -= 1 i = (i + direction) % n comp = chain[i] if comp._is_targetable(): new_target = comp break if new_target: if old_target: old_target._tab_out() new_target._tab_in() def key_down(self, event): #print "GWindow.key_down:", event ### if self._generic_tabbing and event.char == '\t': #print "GWindow.key_down: doing generic tabbing" ### if event.shift: self._tab_to_prev() else: self._tab_to_next() else: Container.key_down(self, event) # def _default_key_event(self, event): # #print "GWindow._default_key_event" ### # self.pass_event_to_next_handler(event) # # Other # def get_window(self): return self def first_dispatcher(self): return self def _document_needs_saving(self, state): pass def modal_event_loop(self): """Loop reading and handling events for the given window until exit_event_loop() is called. Interaction with other windows is prevented (although enabled application-wide menu commands can be used).""" # Implementations can override this together with exit_modal_event_loop() # to implement modal event loops in a different way. application()._event_loop(self) def exit_modal_event_loop(self): # Cause the current call to modal_event_loop() to exit. application()._exit_event_loop()