<commit_before>'''
List View
===========

.. versionadded:: 1.4

The :class:`ListView` widget provides a scrollable/pannable viewport that is
clipped at the scrollview's bounding box, which contains a list of items.

'''

__all__ = ('ListView', )

from kivy.clock import Clock
from kivy.event import EventDispatcher
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, DictProperty, \
                            NumericProperty
from kivy.lang import Builder
from math import ceil, floor
from kivy.uix.mixins.selection import SelectionSupport

Builder.load_string('''
<ListView>:
    container: container
    ScrollView:
        pos: root.pos
        on_scroll_y: root._scroll(args[1])
        do_scroll_x: False
        GridLayout:
            cols: 1
            id: container
            size_hint_y: None
''')


class Adapter(SelectionSupport, EventDispatcher):
    '''Adapter is a bridge between an AbstractView and the data.
    '''

    cls = ObjectProperty(None)

    template = ObjectProperty(None)

    converter = ObjectProperty(None)

    def __init__(self, **kwargs):
        self.register_event_type('on_select')
        if kwargs['selection_mode'] is not None:
            if kwargs['selection_mode'] in ['single', 'multiple', 'filter']:
                self.selection_mode = kwargs['selection_mode']
        super(Adapter, self).__init__(**kwargs)
        if self.cls is None and self.template is None:
            raise Exception('A cls or template must be defined')
        if self.cls is not None and self.template is not None:
            raise Exception('Cannot use cls and template at the same time')

    def get_count(self):
        raise NotImplementedError()

    def get_item(self, index):
        raise NotImplementedError()

    def get_view(self, index):
        item = self.get_item(index)
        if item is None:
            return None
        if self.converter:
            item = self.converter(item)
        if self.cls:
            print 'CREATE VIEW FOR', index
            item_instance = self.cls(
                selection_callback=self.select_object,
                **item)
            return item_instance
        return Builder.template(self.template, **item)

    # This is for the list adapter, if it wants to get selection events.
    def on_select(self, *args):
        pass

    # Things to think about:
    #
    # There are other possibilities:
    #
    #         Additional possibilities, to those stubbed out in
    #         methods below.
    #
    #             - a boolean for whether or not editing of items is allowed
    #             - a boolean for whether or not to destroy on removal (if
    #               applicable)
    #             - guards for adding, removing, sorting items
    #

    def add_item(self, item):
        pass

    def remove_item(self, item):
        pass

    def replace_item(self, item):
        pass

    # This method would have an associated sort_key property.
    def sorted_items(self):
        pass
<commit_msg>Added a todo list.<commit_after>'''
List View
===========

.. versionadded:: 1.4

The :class:`ListView` widget provides a scrollable/pannable viewport that is
clipped at the scrollview's bounding box, which contains a list of items.

[TODO]:

    - Are multiple levels of abstraction needed? Explain why. (Adapter,
      ListAdapter, AbstractView, ListView).
    - Consider an associated "object adapter" (a.k.a., "object controller")
      that is bound to the selection.
    - Also, what about an associated "array adapter/controller" bound to the
      selection? (For a cascade of several listviews).
    - Add associated SortableItem mixin, to be used by list item classes
      in a manner similar to the SelectableItem mixin.
    - Add a sort_by property for use with sortable items.
    - Review the use of arranged_objects in association with sortable items.
      (Presently arranged_objects is a list of strings -- are these just the
       strings representing the items, which are instances of the provided
       cls input argument?)
    - Test layout -- presently problematic for how to use size_hint and
      height -- item can become undefined in the cls list item instantiation
      if the listview's size_hint and/or height is not set "correctly."
    - Work on items marked [TODO] below.

    Examples (in examples/widgets):

    - Improve master-detail example:
        - Fix layout, in association with layout item above, and also for an
          improved detail view.
        - Add fruit images.
    - Provide examples of display changes for selected and unselected. Now
      the example in master-detail uses buttons in the list item, but the
      selection display, using background, only partially works.
    - Add an example where selection doesn't just change background color
      or font, but animates.

    Other Possibilities:

    - Consider a horizontally scrolling variant.
    - Is it possible to have dynamic item height, for use in a master-detail
      list view in this manner? http://www.zkoss.org/zkdemo/grid/master_detail
      (Would this be a new widget called MasterDetailListView, or would the
       listview widget having a facility for use in this way?)
    - Make a separate master-detail example that works like an iphone-style
      animated "source list" that has "disclosure" buttons per item, on the
      right, that when clicked will expand to fill the entire list view area
      (useful on mobile devices especially). Similar question as above --
       would listview be given expanded functionality or would this become
       another kind of "master-detail" widget?)
'''

__all__ = ('ListView', )

from kivy.clock import Clock
from kivy.event import EventDispatcher
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, DictProperty, \
                            NumericProperty
from kivy.lang import Builder
from math import ceil, floor
from kivy.uix.mixins.selection import SelectionSupport

Builder.load_string('''
<ListView>:
    container: container
    ScrollView:
        pos: root.pos
        on_scroll_y: root._scroll(args[1])
        do_scroll_x: False
        GridLayout:
            cols: 1
            id: container
            size_hint_y: None
''')


class Adapter(SelectionSupport, EventDispatcher):
    '''Adapter is a bridge between an AbstractView and the data.
    '''

    cls = ObjectProperty(None)

    template = ObjectProperty(None)

    converter = ObjectProperty(None)

    def __init__(self, **kwargs):
        self.register_event_type('on_select')
        if kwargs['selection_mode'] is not None:
            if kwargs['selection_mode'] in ['single', 'multiple', 'filter']:
                self.selection_mode = kwargs['selection_mode']
        super(Adapter, self).__init__(**kwargs)
        if self.cls is None and self.template is None:
            raise Exception('A cls or template must be defined')
        if self.cls is not None and self.template is not None:
            raise Exception('Cannot use cls and template at the same time')

    def get_count(self):
        raise NotImplementedError()

    def get_item(self, index):
        raise NotImplementedError()

    def get_view(self, index):
        item = self.get_item(index)
        if item is None:
            return None
        if self.converter:
            item = self.converter(item)
        if self.cls:
            print 'CREATE VIEW FOR', index
            item_instance = self.cls(
                selection_callback=self.select_object,
                **item)
            return item_instance
        return Builder.template(self.template, **item)

    # This is for the list adapter, if it wants to get selection events.
    def on_select(self, *args):
        pass

    # [TODO] Things to think about:
    #
    # There are other possibilities:
    #
    #         Additional possibilities, to those stubbed out in
    #         methods below.
    #
    #             - a boolean for whether or not editing of items is allowed
    #             - a boolean for whether or not to destroy on removal (if
    #               applicable)
    #             - guards for adding, removing, sorting items
    #

    # [TODO]
    def add_item(self, item):
        pass

    # [TODO]
    def remove_item(self, item):
        pass

    # [TODO]
    def replace_item(self, item):
        pass

    # [TODO]
    # This method would have an associated sort_key property.
    def sorted_items(self):
        pass

{'fraction_non_alphanumeric': 0.0749710312862109, 'fraction_numerical': 0.0009269988412514484, 'mean_word_length': 2.425, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6470495', 'n_tokens_mistral': 2312, 'n_tokens_neox': 2243, 'n_words': 885}