X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=src%2Fgui%2Fgui.py;h=a07091b3fb06126b37812e7770ab2b4f746041f9;hb=3f1310771fb7c333ebef7a2f0beac4120a0d8b65;hp=30ae4e2745bd6290ac47487bfdffca6d57c748f9;hpb=f5dcb1ff56f0883463ddd14780bf1f89ce3c222e;p=matthijs%2Fupstream%2Fmobilegtd.git diff --git a/src/gui/gui.py b/src/gui/gui.py index 30ae4e2..a07091b 100644 --- a/src/gui/gui.py +++ b/src/gui/gui.py @@ -62,12 +62,21 @@ def applicable_functions(obj,allowed_function_names): return [eval('obj.%s'%function_name) for function_name in function_names] def get_key(key_name): - if key_name == '': + if not key_name: key = None else: key=eval('EKey%s'%key_name) return key +def key_shortname(key_name): + """ Find the one-character name for a key """ + if not key_name: + return None + elif key_name == 'Backspace': + return 'C' + else: + return key_name + def all_key_names(): return filter(lambda entry:entry[0:4]=='EKey',dir(key_codes)) def all_key_values(): @@ -137,58 +146,79 @@ class View(object): def exit(self): self.exit_flag = True self.lock.signal() - super(View, self).exit() + + def update(self,subject=None): + """ + Update the current view (e.g., make sure refresh is called). We + can't call it directly, since we're in another thread. + """ + if self.lock: + self.lock.signal() def refresh(self): """ - Update the gui after a change in model or some user interaction. - Should be filled by subclasses. + Called when the current view must be updated. Never call + directly. Subclasses should extend this method, not update. """ - super(View, self).refresh() + appuifw.app.menu=self.get_menu_entries() + + def get_menu_entries(self): + """ Returns a list of menu entries to display. Will be + automatically updated on each refresh. + + Each menu entry is a tuple of a title for the entry and a + function to call when the entry is selected. + """ + return [] class ListView(View): def __init__(self): super(ListView, self).__init__() - self.set_view(appuifw.Listbox(self.items(),self.change_entry)) + self.set_view(appuifw.Listbox(self.items(),self.entry_selected)) + self.view.bind(EKeyUpArrow,lambda: self.arrow_key_pressed(-1)) + self.view.bind(EKeyDownArrow,lambda: self.arrow_key_pressed(1)) + + def arrow_key_pressed(self, dir): + """ + This function is called when an arrow key is pressed. Since we + don't get any "current list index has changed" events, we'll + have to create these ourselves this way. - def change_entry(self): + Since the current index is only updated after the key event, + we'll have to adjust the index with the direction of the + keypress (-1 for up, +1 for down). + """ + new_index = (self.selected_index() + dir) % len(self.items()) + self.index_changed(new_index) + + def entry_selected(self): """ This function is called when the user selects an an entry (e.g., navigates to it and push the ok button). """ - super(ListView).change_entry() - - def update(self,subject=None): - #logger.log(u'Updated %s'%repr(self)) - if self.lock: - self.lock.signal() - #pass + pass - def index_changed(self,adjustment=None): - if adjustment: - index = self.selected_index() + adjustment - else: - index = self.selected_index() - if index < 0: - index = len(self.widgets) - 1 - if index >= len(self.widgets): - index = 0 - self.set_bindings_for_selection(index) + def index_changed(self,new_index): + """ + This function is called when the index changes. The given index + is the new index (don't use self.selected_index() here, since it + won't be correct yet!). + """ + pass - def refresh(self): - appuifw.app.menu=self.get_menu_entries() + def items(self): + """ This function should return the list of items to display. + See appuifw.ListBox for valid elements for this list. """ + return [] def set_index(self,index): - if index > len(self.widgets): - index = len(self.widgets) - if index < 0: - index = 0 - self.view.set_list(self.items(),index) + """ Changes the currently selected item to index. """ + self.view.set_list(self.items(),index % len(self.items())) def selected_index(self): + """ Returns the currently selected index. """ return self.view.current() - class WidgetBasedListView(ListView): def __init__(self): self.widgets = self.generate_widgets() @@ -199,6 +229,10 @@ class WidgetBasedListView(ListView): self.set_bindings_for_selection(0) ListView.run(self) + def index_changed(self,new_index): + self.set_bindings_for_selection(new_index) + super(WidgeteBasedListView, self).index_changed(new_index) + def notify(self,object,attribute,new=None,old=None): self.refresh() def refresh(self): @@ -218,7 +252,7 @@ class WidgetBasedListView(ListView): return self.widgets[self.selected_index()] -class KeyBindingView(object): +class KeyBindingView(View): def __init__(self): self.binding_map = {} @@ -248,15 +282,14 @@ class KeyBindingView(object): description=' '+description menu_entries.append((description,function)) menu_entries.append((u'Exit', self.exit)) - return menu_entries + return menu_entries + super(KeyBindingView, self).get_menu_entries() + def set_bindings_for_selection(self,selected_index): self.remove_all_key_bindings() for key,key_name,description,function in self.key_and_menu_bindings(selected_index): if key: self.view.bind(key,function) - self.view.bind(EKeyUpArrow,lambda: self.index_changed(-1)) - self.view.bind(EKeyDownArrow,lambda: self.index_changed(1)) def remove_all_key_bindings(self): for key in all_key_values(): @@ -310,7 +343,7 @@ class EditableListView(SearchableListView,KeyBindingView): key_and_menu_bindings.append((get_key(key),key,description,execute_and_update_function)) return key_and_menu_bindings - def change_entry(self): + def entry_selected(self): self.current_widget().change() self.refresh() def execute_and_update(self,function):