diff --git a/examples/widgets/lists/README.md b/examples/widgets/lists/README.md index e0750b68f..b76121fe8 100644 --- a/examples/widgets/lists/README.md +++ b/examples/widgets/lists/README.md @@ -142,3 +142,17 @@ Notes from Adapter.py: - Might there be other useful converters to put in kivy/adapters/args_converters.py, in addition to the default simple string converter? + +- SelectableView was moved out of adapters.mixins and into uix/listview. Was + this the correct thing to do? Are there other cases of view definitions + outside of uix? + +- Clean up Factory registrations in examples -- when needed? which classes + have been added to kivy/factory_registers.py. + +- CustomListItem, the name for the class created in the examples, list_kv.py, + and list_cascade.py, and also in the test_adapters.py file, is defined only + in the Builder.load_string() call. Better document the special nature of + this in API explanations. (You can't refer to it as a normal class). + + diff --git a/examples/widgets/lists/list_cascade_images.py b/examples/widgets/lists/list_cascade_images.py index a5a6a3323..1a9b3b261 100644 --- a/examples/widgets/lists/list_cascade_images.py +++ b/examples/widgets/lists/list_cascade_images.py @@ -1,5 +1,5 @@ from kivy.adapters.dictadapter import DictAdapter -from kivy.adapters.mixins.selection import SelectableView +from kivy.uix.selectableview import SelectableDataItem from kivy.uix.boxlayout import BoxLayout from kivy.uix.gridlayout import GridLayout from kivy.uix.listview import ListView, ListItemButton diff --git a/examples/widgets/lists/list_kv.py b/examples/widgets/lists/list_kv.py index ae0d4ca8c..21f927411 100644 --- a/examples/widgets/lists/list_kv.py +++ b/examples/widgets/lists/list_kv.py @@ -1,5 +1,5 @@ from kivy.adapters.dictadapter import DictAdapter -from kivy.adapters.mixins.selection import SelectableView +from kivy.uix.selectableview import SelectableDataItem from kivy.uix.listview import ListView, ListItemButton from kivy.uix.gridlayout import GridLayout from kivy.uix.boxlayout import BoxLayout @@ -8,6 +8,8 @@ from kivy.factory import Factory from fixtures import integers_dict +# [TODO] Will SelectableView be in the kivy/factory_registers.py, +# as a result of setup.py? ListItemButton? others? Factory.register('SelectableView', cls=SelectableView) Factory.register('ListItemButton', cls=ListItemButton) diff --git a/kivy/adapters/dictadapter.py b/kivy/adapters/dictadapter.py index f6e2e901b..320705532 100644 --- a/kivy/adapters/dictadapter.py +++ b/kivy/adapters/dictadapter.py @@ -18,7 +18,9 @@ From :class:`Adapter`, :class:`SimpleListAdapter` gets these properties: - args_converter, an optional function to transform data item argument sets, in preparation for either a cls instantiation, - or a kv template invocation + or a kv template invocation. If no args_converter is + provided, a default one is set, that assumes that the + data items are strings. From the :class:`SelectionSupport` mixin, :class:`DictAdapter` has these properties: diff --git a/kivy/adapters/mixins/selection.py b/kivy/adapters/mixins/selection.py index 5959946e3..48455f7ac 100644 --- a/kivy/adapters/mixins/selection.py +++ b/kivy/adapters/mixins/selection.py @@ -24,39 +24,6 @@ class SelectableDataItem(object): self.is_selected = False -class SelectableView(object): - '''The :class:`SelectableView` mixin is used in list item classes that are - to be instantiated in a list view, which uses a list adapter. select() - and deselect() are to be overridden with display code to mark items as - selected or not, if desired. - ''' - - index = NumericProperty(-1) - '''The index into the underlying data list or the data item this view - represents. - ''' - - is_selected = BooleanProperty(False) - '''A SelectableView instance carries this property, and is kept in - sync with the equivalent property in the data item it represents. - ''' - - def __init__(self, **kwargs): - super(SelectableView, self).__init__(**kwargs) - - def select(self, *args): - '''The list item is responsible for updating the display for - being selected, if desired. - ''' - pass - - def deselect(self, *args): - '''The list item is responsible for updating the display for - being unselected, if desired. - ''' - pass - - class SelectionSupport(EventDispatcher): '''The :class:`SelectionSupport` mixin is used for selection. Any "collection" view, such as :class:`ListView`. diff --git a/kivy/tests/test_adapters.py b/kivy/tests/test_adapters.py index 0fabaab9b..bdf0592fa 100644 --- a/kivy/tests/test_adapters.py +++ b/kivy/tests/test_adapters.py @@ -5,12 +5,16 @@ Adapter tests import unittest +from kivy.adapters.mixins.selection import SelectableDataItem +from kivy.uix.selectableview import SelectableView from kivy.uix.listview import ListItemButton from kivy.uix.label import Label + from kivy.adapters.adapter import Adapter from kivy.adapters.listadapter import SimpleListAdapter from kivy.adapters.listadapter import ListAdapter -from kivy.adapters.mixins.selection import SelectableDataItem + +from kivy.factory import Factory from kivy.lang import Builder from nose.tools import raises @@ -235,6 +239,10 @@ class FruitsListAdapter(ListAdapter): [f for f in fruit_data_items if f.name in category['fruits']] +# [TODO] Needed if setup.py run normally, after merge to master? +Factory.register('SelectableView', cls=SelectableView) +Factory.register('ListItemButton', cls=ListItemButton) + Builder.load_string(''' [CustomListItem@SelectableView+BoxLayout]: index: ctx.index @@ -278,6 +286,24 @@ class AdaptersTestCase(unittest.TestCase): msg = 'adapter: a cls or template must be defined' self.assertEqual(str(cm.exception), msg) + with self.assertRaises(Exception) as cm: + fruit_categories_list_adapter = \ + Adapter(data='cat', + args_converter=dummy_converter, + cls=None) + + msg = 'adapter: a cls or template must be defined' + self.assertEqual(str(cm.exception), msg) + + with self.assertRaises(Exception) as cm: + fruit_categories_list_adapter = \ + Adapter(data='cat', + args_converter=dummy_converter, + template=None) + + msg = 'adapter: a cls or template must be defined' + self.assertEqual(str(cm.exception), msg) + with self.assertRaises(Exception) as cm: fruit_categories_list_adapter = \ Adapter(data='cat', @@ -337,6 +363,14 @@ class AdaptersTestCase(unittest.TestCase): adapter_2 = Adapter(**kwargs_2) self.assertEqual(adapter_2.args_converter, list_item_args_converter) + adapter = Adapter(data='cat', cls=Label) + self.assertEqual(adapter.get_count(), 1) + self.assertEqual(adapter.get_item(0), 'cat') + + adapter = Adapter(data=None, cls=Label) + self.assertEqual(adapter.get_count(), 0) + self.assertEqual(adapter.get_item(0), None) + def test_instantiating_simple_list_adapter(self): # with no data with self.assertRaises(Exception) as cm: @@ -470,6 +504,8 @@ class AdaptersTestCase(unittest.TestCase): self.assertEqual(str(cm.exception), msg) def test_view_from_list_adapter(self): + + # First with a class. list_item_args_converter = \ lambda selectable: {'text': selectable.name, 'size_hint_y': None, @@ -484,3 +520,21 @@ class AdaptersTestCase(unittest.TestCase): view = fruit_categories_list_adapter.get_view(0) self.assertTrue(isinstance(view, ListItemButton)) + + # Now with a template. + list_item_args_converter = \ + lambda selectable: {'text': selectable.name, + 'is_selected': selectable.is_selected, + 'size_hint_y': None, + 'height': 25} + + fruit_categories_list_adapter = \ + ListAdapter(data=category_data_items, + args_converter=list_item_args_converter, + selection_mode='single', + allow_empty_selection=False, + template='CustomListItem') + + view = fruit_categories_list_adapter.get_view(0) + self.assertEqual(view.__class__.__name__, 'CustomListItem') + diff --git a/kivy/uix/listview.py b/kivy/uix/listview.py index 9794cc862..9d73cfbf2 100644 --- a/kivy/uix/listview.py +++ b/kivy/uix/listview.py @@ -288,8 +288,8 @@ from kivy.uix.button import Button from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.adapters.listadapter import SimpleListAdapter -from kivy.adapters.mixins.selection import SelectableView from kivy.uix.abstractview import AbstractView +from kivy.uix.selectableview import SelectableView from kivy.properties import ObjectProperty, DictProperty, \ NumericProperty, ListProperty, BooleanProperty from kivy.lang import Builder