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)
object.old_menu = appuifw.app.menu
object.old_exit_key_handler = appuifw.app.exit_key_handler
object.old_title=appuifw.app.title
- object.lock = Ao_lock()
def restore_gui(object):
appuifw.app.body = object.old_gui
appuifw.app.exit_key_handler = object.old_exit_key_handler
appuifw.app.title = object.old_title
-
-class ListView(object):
+class View(object):
def __init__(self):
- self.view = appuifw.Listbox(self.items(),self.change_entry)
+ self.title = None
+ self.view = None
+ self.lock = Ao_lock()
+ self.exit_flag = False
+ super(View, self).__init__()
def set_title(self, title):
self.title = title
-
- def change_entry(self):
- pass
-
+
+ def set_view(self, view):
+ """
+ Sets the main view to be displayed (e.g., an appuifw.Listbox
+ instance).
+ """
+ self.view = view
+
def run(self):
self.adjustment = None
- appuifw.app.screen=COMMON_CONFIG['screen'].encode('utf-8')
save_gui(self)
+ appuifw.app.screen=COMMON_CONFIG['screen'].encode('utf-8')
appuifw.app.title=self.title
appuifw.app.body=self.view
appuifw.app.exit_key_handler=self.exit
except:
pass
restore_gui(self)
+
def exit(self):
self.exit_flag = True
self.lock.signal()
def update(self,subject=None):
- #logger.log(u'Updated %s'%repr(self))
+ """
+ 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()
- #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 refresh(self):
+ """
+ Called when the current view must be updated. Never call
+ directly. Subclasses should extend this method, not update.
+ """
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.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.
+
+ 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).
+ """
+ pass
+
+ 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 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()
super(WidgetBasedListView,self).__init__()
- self.exit_flag = False
def run(self):
self.refresh()
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):
return self.widgets[self.selected_index()]
-class KeyBindingView(object):
+class KeyBindingView(View):
def __init__(self):
self.binding_map = {}
+ super(KeyBindingView,self).__init__()
def set_keybindings(self, binding_map):
"""
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():
class EditableListView(SearchableListView,KeyBindingView):
def __init__(self):
- KeyBindingView.__init__(self)
super(EditableListView, self).__init__()
def key_and_menu_bindings(self,selected_index):
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):