Removed observer registration system and changed to use Kivy bindings system directly to the selection ListProperty.

This commit is contained in:
Jeff Pittman 2012-07-15 08:07:20 -05:00
parent ac00f0a46c
commit 4a2d6d07ac
5 changed files with 30 additions and 52 deletions

View File

@ -49,15 +49,15 @@ class FruitsListView(SelectionObserver, ListView):
super(FruitsListView, self).__init__(**kwargs)
# Observed selection is fruit categories list.
def observed_selection_changed(self, observed_selection):
if len(observed_selection.selection) == 0:
def observed_selection_changed(self, list_adapter, selection):
if len(list_adapter.selection) == 0:
return
# Clear the previously built views.
self.item_view_instances = {}
# Single selection is operational for fruit categories list.
selected_object = observed_selection.selection[0]
selected_object = list_adapter.selection[0]
if type(selected_object) is str:
fruit_category = selected_object
@ -72,7 +72,7 @@ class FruitsListView(SelectionObserver, ListView):
self.populate()
self.canvas.ask_update()
#self.canvas.ask_update()
print 'just added or updated fruit category'
@ -95,12 +95,14 @@ class DetailView(SelectionObserver, GridLayout):
self.add_widget(
Label(text=str(fruit_data[self.fruit_name][category])))
def observed_selection_changed(self, observed_selection):
if len(observed_selection.selection) == 0:
def observed_selection_changed(self, list_adapter, selection):
if len(list_adapter.selection) == 0:
return
selected_object = observed_selection.selection[0]
selected_object = list_adapter.selection[0]
# Resetting self.fruit_name will trigger call to redraw().
# [TODO] Why not direct call to redraw here? (And remove binding).
if type(selected_object) is str:
self.fruit_name = selected_object
else:
@ -159,8 +161,8 @@ class CascadingView(GridLayout):
# Set the fruits_list_view as an observer of the selection of
# the fruit category.
self.fruit_categories_list_adapter.register_selection_observer(
self.fruits_list_view)
self.fruit_categories_list_adapter.bind(
selection=self.fruits_list_view.observed_selection_changed)
# Detail view, for a given fruit, on the right:
#
@ -169,9 +171,10 @@ class CascadingView(GridLayout):
# Manually initialize detail view to show first object of list view,
# which will be auto-selected, but the observed_selection_changed
# call would have already fired.
# call would have already fired. [TODO] Evaluate this statement.
#
self.fruits_list_adapter.register_selection_observer(self.detail_view)
self.fruits_list_adapter.bind(
selection=self.detail_view.observed_selection_changed)
# Data from http://www.fda.gov/Food/LabelingNutrition/\
# FoodLabelingGuidanceRegulatoryInformation/\

View File

@ -161,11 +161,11 @@ class DetailView(SelectionObserver, GridLayout):
self.add_widget(
Label(text=str(fruit_data[self.fruit_name][category])))
def observed_selection_changed(self, observed_selection):
if len(observed_selection.selection) == 0:
def observed_selection_changed(self, list_adapter, selection):
if len(list_adapter.selection) == 0:
return
selected_object = observed_selection.selection[0]
selected_object = list_adapter.selection[0]
if type(selected_object) is str:
self.fruit_name = selected_object
@ -214,7 +214,8 @@ class MasterDetailView(GridLayout):
# which will be auto-selected, but the observed_selection_changed
# call would have already fired.
#
self.list_adapter.register_selection_observer(self.detail_view)
self.list_adapter.bind(
selection=self.detail_view.observed_selection_changed)
# Data from http://www.fda.gov/Food/LabelingNutrition/\
# FoodLabelingGuidanceRegulatoryInformation/\

View File

@ -64,11 +64,11 @@ class DetailView(SelectionObserver, GridLayout):
self.add_widget(
Label(text=str(fruit_data[self.fruit_name][category])))
def observed_selection_changed(self, observed_selection):
if len(observed_selection.selection) == 0:
def observed_selection_changed(self, list_adapter, selection):
if len(list_adapter.selection) == 0:
return
selected_object = observed_selection.selection[0]
selected_object = list_adapter.selection[0]
if type(selected_object) is str:
self.fruit_name = selected_object
@ -114,13 +114,8 @@ class MasterDetailView(GridLayout):
self.detail_view = DetailView(size_hint=(.7, 1.0))
self.add_widget(self.detail_view)
# Manually initialize detail view to show first object of list view,
# which will be auto-selected, but the observed_selection_changed
# call would have already fired.
#
self.list_adapter.register_selection_observer(self.detail_view)
self.list_adapter.update_selection()
self.list_adapter.bind(
selection=self.detail_view.observed_selection_changed)
# Data from http://www.fda.gov/Food/LabelingNutrition/\
# FoodLabelingGuidanceRegulatoryInformation/\

View File

@ -34,8 +34,13 @@ item_view_instances.
strings representing the item_view_instances, which are instances of
the provided cls input argument?). If so, formalize and document.
- Address question about "pushing" out to registered selection observers,
vs. using the built-in Kivy event dispatching for an "on_select" event.
vs. using the built-in Kivy bindings system
(Will event dispatching work instead of registering/pushing?). Merits?
ANSWER: Use built-in Kivy system -- no need for observer registration
system and pushing out to registered observers. Just bind
observers to the selection ListProperty.
- Work on item_view_instances marked [TODO] in the code.
Examples (in examples/widgets):
@ -143,7 +148,6 @@ class ListAdapter(SelectionSupport, Adapter):
def __init__(self, data, **kwargs):
if type(data) not in (tuple, list):
raise Exception('ListAdapter: input must be a tuple or list')
self.register_event_type('on_select')
super(ListAdapter, self).__init__(**kwargs)
# Reset and update selection, in SelectionSupport, if data
@ -161,9 +165,6 @@ class ListAdapter(SelectionSupport, Adapter):
return None
return self.data[index]
def on_select(self, *args):
pass
def get_view(self, index):
item = self.get_item(index)
if item is None:

View File

@ -64,25 +64,12 @@ class SelectionSupport(object):
# all but simple displays of list items.
allow_empty_selection = BooleanProperty(True)
registered_selection_observers = ListProperty([])
def __init__(self, **kwargs):
super(SelectionSupport, self).__init__(**kwargs)
self.bind(data=self.initialize_selection,
selection_mode=self.initialize_selection,
allow_empty_selection=self.initialize_selection)
def register_selection_observer(self, obs):
if isinstance(obs, SelectionObserver):
self.registered_selection_observers.append(obs)
obs.observed_selection_changed(self)
print 'registered_selection_observers:', \
len(self.registered_selection_observers)
def unregister_selection_observer(self, obs):
if obs in self.registered_selection_observers:
self.registered_selection_observers.remove(obs)
def handle_selection(self, obj):
if obj not in self.selection:
if self.selection_mode == 'single' and len(self.selection) > 0:
@ -92,12 +79,6 @@ class SelectionSupport(object):
else:
self.deselect_object(obj)
# dispatch will use the Kivy property-observing system.
#
# update_selection will push out to registered selection observers.
#
# Which is the way to go?
#
self.dispatch('on_select')
self.update_selection()
print 'selection is now', self.selection
@ -137,9 +118,6 @@ class SelectionSupport(object):
print 'selecting first data item view', v, v.is_selected
self.handle_selection(self.get_view(0))
for obs in self.registered_selection_observers:
obs.observed_selection_changed(self)
# Is this needed as special case for resetting? Or can update_selection
# be modified for this case?
def initialize_selection(self, *args):