mirror of https://github.com/kivy/kivy.git
263 lines
10 KiB
Python
263 lines
10 KiB
Python
from kivy.adapters.dictadapter import DictAdapter
|
|
from kivy.properties import NumericProperty, ListProperty, \
|
|
BooleanProperty, AliasProperty, ObjectProperty
|
|
from kivy.uix.boxlayout import BoxLayout
|
|
from kivy.uix.gridlayout import GridLayout
|
|
from kivy.uix.listview import ListView, ListItemButton
|
|
from kivy.uix.label import Label
|
|
from kivy.uix.button import Button
|
|
from kivy.uix.widget import Widget
|
|
|
|
|
|
class OpsDictAdapter(DictAdapter):
|
|
|
|
listview_id = NumericProperty(0)
|
|
owning_view = ObjectProperty(None)
|
|
|
|
def __init__(self, **kwargs):
|
|
self.listview_id = kwargs['listview_id']
|
|
super(OpsDictAdapter, self).__init__(**kwargs)
|
|
|
|
def on_selection_change(self, *args):
|
|
for i in range(len(self.selection)):
|
|
listview_selection_buttons[self.listview_id][i].text = \
|
|
self.selection[i].text
|
|
|
|
if self.listview_id is 0:
|
|
# Scroll to the most recently selected item.
|
|
if len(self.selection) > 0:
|
|
print('selection', self.selection)
|
|
self.owning_view.scroll_to(
|
|
index=self.sorted_keys.index(self.selection[-1].text))
|
|
|
|
elif self.listview_id is 1:
|
|
# Scroll to the selected item that is the minimum of a sort.
|
|
if len(self.selection) > 0:
|
|
self.owning_view.scroll_to(
|
|
index=self.sorted_keys.index(
|
|
sorted([sel.text for sel in self.selection])[0]))
|
|
|
|
elif self.listview_id is 2:
|
|
# Scroll to the selected item that is the maximum of a sort.
|
|
if len(self.selection) > 0:
|
|
self.owning_view.scroll_to(
|
|
index=self.sorted_keys.index(
|
|
sorted([sel.text for sel in self.selection])[-1]))
|
|
|
|
|
|
class SelectionMonitor(Widget):
|
|
|
|
def get_count_string(self):
|
|
return "Total sel: " + str(self.sel_count_0 +
|
|
self.sel_count_1 +
|
|
self.sel_count_2 +
|
|
self.sel_count_3 +
|
|
self.sel_count_4 +
|
|
self.sel_count_5 +
|
|
self.sel_count_6)
|
|
|
|
def set_count_string(self, value):
|
|
self.count_string = value
|
|
|
|
sel_count_0 = NumericProperty(0)
|
|
sel_count_1 = NumericProperty(0)
|
|
sel_count_2 = NumericProperty(0)
|
|
sel_count_3 = NumericProperty(0)
|
|
sel_count_4 = NumericProperty(0)
|
|
sel_count_5 = NumericProperty(0)
|
|
sel_count_6 = NumericProperty(0)
|
|
|
|
count_string = AliasProperty(get_count_string,
|
|
set_count_string,
|
|
bind=('sel_count_0',
|
|
'sel_count_1',
|
|
'sel_count_2',
|
|
'sel_count_3',
|
|
'sel_count_4',
|
|
'sel_count_5',
|
|
'sel_count_6'))
|
|
|
|
def __init__(self, **kwargs):
|
|
super(SelectionMonitor, self).__init__(**kwargs)
|
|
|
|
def update_sel_count_0(self, adapter, *args):
|
|
self.sel_count_0 = len(adapter.selection)
|
|
|
|
def update_sel_count_1(self, adapter, *args):
|
|
self.sel_count_1 = len(adapter.selection)
|
|
|
|
def update_sel_count_2(self, adapter, *args):
|
|
self.sel_count_2 = len(adapter.selection)
|
|
|
|
def update_sel_count_3(self, adapter, *args):
|
|
self.sel_count_3 = len(adapter.selection)
|
|
|
|
def update_sel_count_4(self, adapter, *args):
|
|
self.sel_count_4 = len(adapter.selection)
|
|
|
|
def update_sel_count_5(self, adapter, *args):
|
|
self.sel_count_5 = len(adapter.selection)
|
|
|
|
def update_sel_count_6(self, adapter, *args):
|
|
self.sel_count_6 = len(adapter.selection)
|
|
|
|
|
|
letters_dict = \
|
|
{l: {'text': l, 'is_selected': False} for l in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'}
|
|
|
|
listview_selection_buttons = {}
|
|
|
|
|
|
class OpsView(BoxLayout):
|
|
'''Seven list views are shown at the bottom, each focusing on one of the
|
|
available operations for collection adapters: scroll_to, trim_to_sel,
|
|
trim_left_of_sel, etc. At the top is a display that shows individual
|
|
items selected across the seven lists, along with a total of all selected
|
|
items for the lists.
|
|
'''
|
|
def __init__(self, **kwargs):
|
|
kwargs['orientation'] = 'vertical'
|
|
super(OpsView, self).__init__(**kwargs)
|
|
|
|
# UPPER PANEL
|
|
#
|
|
# Create an upper panel with labels for items selected in the
|
|
# listviews shown in the lower panel.
|
|
#
|
|
upper_panel = BoxLayout()
|
|
|
|
grid_layout = GridLayout(cols=1,
|
|
row_force_default=True,
|
|
row_default_height=40)
|
|
|
|
# On the left side of the upper panel, show the selected items. There
|
|
# is a total possible of 5 for each listview, so 5 buttons are made.
|
|
#
|
|
for listview_id in range(7):
|
|
box_layout = BoxLayout()
|
|
listview_selection_buttons[listview_id] = []
|
|
|
|
box_layout.add_widget(
|
|
Label(text="Listview #{0} selection".format(listview_id)))
|
|
|
|
for i in range(5):
|
|
button = Button(size_hint_x=None, width=50,
|
|
size_hint_y=None, height=35,
|
|
background_color=[.25, .25, .6, 1.0])
|
|
listview_selection_buttons[listview_id].append(button)
|
|
box_layout.add_widget(button)
|
|
|
|
grid_layout.add_widget(box_layout)
|
|
|
|
upper_panel.add_widget(grid_layout)
|
|
|
|
# On the right side of the upper panel, show the total selected count.
|
|
|
|
total_selection_button = Button(text="Total: 0",
|
|
size_hint=(.5, 1.0),
|
|
background_color=[.25, .25, .6, 1.0])
|
|
selection_monitor = SelectionMonitor()
|
|
selection_monitor.bind(
|
|
count_string=total_selection_button.setter('text'))
|
|
|
|
upper_panel.add_widget(total_selection_button)
|
|
|
|
self.add_widget(upper_panel)
|
|
|
|
# LOWER PANEL
|
|
#
|
|
# Show 6 listviews with either a header label or a header button.
|
|
#
|
|
grid_layout = GridLayout(cols=7)
|
|
|
|
list_item_args_converter = \
|
|
lambda row_index, rec: {'text': rec['text'],
|
|
'size_hint_y': None,
|
|
'height': 25}
|
|
|
|
letters = [l for l in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
|
|
|
|
adapters = []
|
|
|
|
# Create 7 listviews, limiting selection to 5 items for the first 3,
|
|
# and allowing unlimited selection for the others, by setting the
|
|
# selection limit to 1000.
|
|
#
|
|
# Use OpsDictAdapter, from above, which will post selections to
|
|
# the display in the top panel.
|
|
#
|
|
listview_header_widgets = [Label(text="scroll_to rec",
|
|
size_hint_y=None,
|
|
height=25),
|
|
Label(text="scroll_to min",
|
|
size_hint_y=None,
|
|
height=25),
|
|
Label(text="scroll_to max",
|
|
size_hint_y=None,
|
|
height=25),
|
|
Button(text="trim_left_of_sel",
|
|
size_hint_y=None,
|
|
height=25),
|
|
Button(text="trim_right_of_sel",
|
|
size_hint_y=None,
|
|
height=25),
|
|
Button(text="trim_to_sel",
|
|
size_hint_y=None,
|
|
height=25),
|
|
Button(text="cut_to_sel",
|
|
size_hint_y=None,
|
|
height=25)]
|
|
|
|
for listview_id in range(7):
|
|
|
|
box_layout = BoxLayout(orientation='vertical')
|
|
|
|
letters_dict_adapter = \
|
|
OpsDictAdapter(
|
|
listview_id=listview_id,
|
|
sorted_keys=letters[:],
|
|
data=letters_dict,
|
|
args_converter=list_item_args_converter,
|
|
selection_mode='multiple',
|
|
selection_limit=5 if listview_id < 3 else 1000,
|
|
allow_empty_selection=True,
|
|
cls=ListItemButton)
|
|
|
|
adapters.append(letters_dict_adapter)
|
|
|
|
letters_list_view = ListView(adapter=letters_dict_adapter)
|
|
|
|
letters_dict_adapter.owning_view = letters_list_view
|
|
|
|
box_layout.add_widget(listview_header_widgets[listview_id])
|
|
box_layout.add_widget(letters_list_view)
|
|
|
|
grid_layout.add_widget(box_layout)
|
|
|
|
# Bind selection of each list to the selection monitor.
|
|
adapters[0].bind(selection=selection_monitor.update_sel_count_0)
|
|
adapters[1].bind(selection=selection_monitor.update_sel_count_1)
|
|
adapters[2].bind(selection=selection_monitor.update_sel_count_2)
|
|
adapters[3].bind(selection=selection_monitor.update_sel_count_3)
|
|
adapters[4].bind(selection=selection_monitor.update_sel_count_4)
|
|
adapters[5].bind(selection=selection_monitor.update_sel_count_5)
|
|
adapters[6].bind(selection=selection_monitor.update_sel_count_6)
|
|
|
|
# For the last three listviews, bind the header buttons to the trim
|
|
# op method in the associated dict adapter instance.
|
|
button_3 = listview_header_widgets[3]
|
|
button_4 = listview_header_widgets[4]
|
|
button_5 = listview_header_widgets[5]
|
|
button_6 = listview_header_widgets[6]
|
|
button_3.bind(on_release=adapters[3].trim_left_of_sel)
|
|
button_4.bind(on_release=adapters[4].trim_right_of_sel)
|
|
button_5.bind(on_release=adapters[5].trim_to_sel)
|
|
button_6.bind(on_release=adapters[6].cut_to_sel)
|
|
|
|
self.add_widget(grid_layout)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
from kivy.base import runTouchApp
|
|
runTouchApp(OpsView(width=800))
|