You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
6.2 KiB
205 lines
6.2 KiB
from kivy.uix.boxlayout import BoxLayout
|
|
from kivy.adapters.dictadapter import DictAdapter
|
|
from kivy.adapters.listadapter import ListAdapter
|
|
from kivy.properties import ObjectProperty, ListProperty, AliasProperty
|
|
from kivy.uix.listview import (ListItemButton, ListItemLabel, CompositeListItem,
|
|
ListView)
|
|
from kivy.lang import Builder
|
|
from kivy.metrics import dp, sp
|
|
|
|
Builder.load_string('''
|
|
<GridView>
|
|
header_view: header_view
|
|
content_view: content_view
|
|
BoxLayout:
|
|
orientation: 'vertical'
|
|
padding: '0dp', '2dp'
|
|
BoxLayout:
|
|
id: header_box
|
|
orientation: 'vertical'
|
|
size_hint: 1, None
|
|
height: '30dp'
|
|
ListView:
|
|
id: header_view
|
|
BoxLayout:
|
|
id: content_box
|
|
orientation: 'vertical'
|
|
ListView:
|
|
id: content_view
|
|
|
|
<-HorizVertGrid>
|
|
header_view: header_view
|
|
content_view: content_view
|
|
ScrollView:
|
|
id: scrl
|
|
do_scroll_y: False
|
|
RelativeLayout:
|
|
size_hint_x: None
|
|
width: max(scrl.width, dp(sum(root.widths)))
|
|
BoxLayout:
|
|
orientation: 'vertical'
|
|
padding: '0dp', '2dp'
|
|
BoxLayout:
|
|
id: header_box
|
|
orientation: 'vertical'
|
|
size_hint: 1, None
|
|
height: '30dp'
|
|
ListView:
|
|
id: header_view
|
|
BoxLayout:
|
|
id: content_box
|
|
orientation: 'vertical'
|
|
ListView:
|
|
id: content_view
|
|
|
|
''')
|
|
|
|
class GridView(BoxLayout):
|
|
"""Workaround solution for grid view by using 2 list view.
|
|
Sometimes the height of lines is shown properly."""
|
|
|
|
def _get_hd_adpt(self):
|
|
return self.ids.header_view.adapter
|
|
|
|
header_adapter = AliasProperty(_get_hd_adpt, None)
|
|
'''
|
|
'''
|
|
|
|
def _get_cnt_adpt(self):
|
|
return self.ids.content_view.adapter
|
|
|
|
content_adapter = AliasProperty(_get_cnt_adpt, None)
|
|
'''
|
|
'''
|
|
|
|
headers = ListProperty([])
|
|
'''
|
|
'''
|
|
|
|
widths = ListProperty([])
|
|
'''
|
|
'''
|
|
|
|
data = ListProperty([])
|
|
'''
|
|
'''
|
|
|
|
getter = ObjectProperty(lambda item, i: item[i])
|
|
'''
|
|
'''
|
|
on_context_menu = ObjectProperty(None)
|
|
|
|
def __init__(self, **kwargs):
|
|
self._from_widths = False
|
|
super(GridView, self).__init__(**kwargs)
|
|
#self.on_headers(self, self.headers)
|
|
|
|
def on_widths(self, instance, value):
|
|
if not self.get_root_window():
|
|
return
|
|
self._from_widths = True
|
|
self.on_headers(instance, self.headers)
|
|
self._from_widths = False
|
|
|
|
def on_headers(self, instance, value):
|
|
if not self._from_widths:
|
|
return
|
|
if not (value and self.canvas and self.headers):
|
|
return
|
|
widths = self.widths
|
|
if len(self.widths) != len(value):
|
|
return
|
|
#if widths is not None:
|
|
# widths = ['%sdp' % i for i in widths]
|
|
|
|
def generic_args_converter(row_index,
|
|
item,
|
|
is_header=True,
|
|
getter=self.getter):
|
|
cls_dicts = []
|
|
_widths = self.widths
|
|
getter = self.getter
|
|
on_context_menu = self.on_context_menu
|
|
|
|
for i, header in enumerate(self.headers):
|
|
kwargs = {
|
|
'padding': ('2dp','2dp'),
|
|
'halign': 'center',
|
|
'valign': 'middle',
|
|
'size_hint_y': None,
|
|
'shorten': True,
|
|
'height': '30dp',
|
|
'text_size': (_widths[i], dp(30)),
|
|
'text': getter(item, i),
|
|
}
|
|
|
|
kwargs['font_size'] = '9sp'
|
|
if is_header:
|
|
kwargs['deselected_color'] = kwargs['selected_color'] =\
|
|
[0, 1, 1, 1]
|
|
else: # this is content
|
|
kwargs['deselected_color'] = 1, 1, 1, 1
|
|
if on_context_menu is not None:
|
|
kwargs['on_press'] = on_context_menu
|
|
|
|
if widths is not None: # set width manually
|
|
kwargs['size_hint_x'] = None
|
|
kwargs['width'] = widths[i]
|
|
|
|
cls_dicts.append({
|
|
'cls': ListItemButton,
|
|
'kwargs': kwargs,
|
|
})
|
|
|
|
return {
|
|
'id': item[-1],
|
|
'size_hint_y': None,
|
|
'height': '30dp',
|
|
'cls_dicts': cls_dicts,
|
|
}
|
|
|
|
def header_args_converter(row_index, item):
|
|
return generic_args_converter(row_index, item)
|
|
|
|
def content_args_converter(row_index, item):
|
|
return generic_args_converter(row_index, item, is_header=False)
|
|
|
|
|
|
self.ids.header_view.adapter = ListAdapter(data=[self.headers],
|
|
args_converter=header_args_converter,
|
|
selection_mode='single',
|
|
allow_empty_selection=False,
|
|
cls=CompositeListItem)
|
|
|
|
self.ids.content_view.adapter = ListAdapter(data=self.data,
|
|
args_converter=content_args_converter,
|
|
selection_mode='single',
|
|
allow_empty_selection=False,
|
|
cls=CompositeListItem)
|
|
self.content_adapter.bind_triggers_to_view(self.ids.content_view._trigger_reset_populate)
|
|
|
|
class HorizVertGrid(GridView):
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from kivy.app import App
|
|
class MainApp(App):
|
|
|
|
def build(self):
|
|
data = []
|
|
for i in range(90):
|
|
data.append((str(i), str(i)))
|
|
self.data = data
|
|
return Builder.load_string('''
|
|
BoxLayout:
|
|
orientation: 'vertical'
|
|
HorizVertGrid:
|
|
on_parent: if args[1]: self.content_adapter.data = app.data
|
|
headers:['Address', 'Previous output']
|
|
widths: [400, 500]
|
|
|
|
<Label>
|
|
font_size: '16sp'
|
|
''')
|
|
MainApp().run()
|
|
|