URI: 
       tgridview.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
       tgridview.py (6337B)
       ---
            1 from kivy.uix.boxlayout import BoxLayout
            2 from kivy.adapters.dictadapter import DictAdapter
            3 from kivy.adapters.listadapter import ListAdapter
            4 from kivy.properties import ObjectProperty, ListProperty, AliasProperty
            5 from kivy.uix.listview import (ListItemButton, ListItemLabel, CompositeListItem,
            6                                ListView)
            7 from kivy.lang import Builder
            8 from kivy.metrics import dp, sp
            9 
           10 Builder.load_string('''
           11 <GridView>
           12     header_view: header_view
           13     content_view: content_view
           14     BoxLayout:
           15         orientation: 'vertical'
           16         padding: '0dp', '2dp'
           17         BoxLayout:
           18             id: header_box
           19             orientation: 'vertical'
           20             size_hint: 1, None
           21             height: '30dp'
           22             ListView:
           23                 id: header_view
           24         BoxLayout:
           25             id: content_box
           26             orientation: 'vertical'
           27             ListView:
           28                 id: content_view
           29 
           30 <-HorizVertGrid>
           31     header_view: header_view
           32     content_view: content_view
           33     ScrollView:
           34         id: scrl
           35         do_scroll_y: False
           36         RelativeLayout:
           37             size_hint_x: None
           38             width: max(scrl.width, dp(sum(root.widths)))
           39             BoxLayout:
           40                 orientation: 'vertical'
           41                 padding: '0dp', '2dp'
           42                 BoxLayout:
           43                     id: header_box
           44                     orientation: 'vertical'
           45                     size_hint: 1, None
           46                     height: '30dp'
           47                     ListView:
           48                         id: header_view
           49                 BoxLayout:
           50                     id: content_box
           51                     orientation: 'vertical'
           52                     ListView:
           53                         id: content_view
           54 
           55 ''')
           56 
           57 class GridView(BoxLayout):
           58     """Workaround solution for grid view by using 2 list view.
           59     Sometimes the height of lines is shown properly."""
           60 
           61     def _get_hd_adpt(self):
           62         return self.ids.header_view.adapter
           63 
           64     header_adapter = AliasProperty(_get_hd_adpt, None)
           65     '''
           66     '''
           67 
           68     def _get_cnt_adpt(self):
           69         return self.ids.content_view.adapter
           70 
           71     content_adapter = AliasProperty(_get_cnt_adpt, None)
           72     '''
           73     '''
           74 
           75     headers = ListProperty([])
           76     '''
           77     '''
           78 
           79     widths = ListProperty([])
           80     '''
           81     '''
           82 
           83     data = ListProperty([])
           84     '''
           85     '''
           86 
           87     getter = ObjectProperty(lambda item, i: item[i])
           88     '''
           89     '''
           90     on_context_menu = ObjectProperty(None)
           91 
           92     def __init__(self, **kwargs):
           93         self._from_widths = False
           94         super(GridView, self).__init__(**kwargs)
           95         #self.on_headers(self, self.headers)
           96 
           97     def on_widths(self, instance, value):
           98         if not self.get_root_window():
           99             return
          100         self._from_widths = True
          101         self.on_headers(instance, self.headers)
          102         self._from_widths = False
          103 
          104     def on_headers(self, instance, value):
          105         if not self._from_widths:
          106             return
          107         if not (value and self.canvas and self.headers):
          108             return
          109         widths = self.widths
          110         if len(self.widths) != len(value):
          111             return
          112         #if widths is not None:
          113         #    widths = ['%sdp' % i for i in widths]
          114 
          115         def generic_args_converter(row_index,
          116                                    item,
          117                                    is_header=True,
          118                                    getter=self.getter):
          119             cls_dicts = []
          120             _widths = self.widths
          121             getter = self.getter
          122             on_context_menu = self.on_context_menu
          123 
          124             for i, header in enumerate(self.headers):
          125                 kwargs = {
          126                     'padding': ('2dp','2dp'),
          127                     'halign': 'center',
          128                     'valign': 'middle',
          129                     'size_hint_y': None,
          130                     'shorten': True,
          131                     'height': '30dp',
          132                     'text_size': (_widths[i], dp(30)),
          133                     'text': getter(item, i),
          134                 }
          135 
          136                 kwargs['font_size'] = '9sp'
          137                 if is_header:
          138                     kwargs['deselected_color'] = kwargs['selected_color']  =\
          139                         [0, 1, 1, 1]
          140                 else:  # this is content
          141                     kwargs['deselected_color'] = 1, 1, 1, 1
          142                     if on_context_menu is not None:
          143                         kwargs['on_press'] = on_context_menu
          144 
          145                 if widths is not None:  # set width manually
          146                     kwargs['size_hint_x'] = None
          147                     kwargs['width'] = widths[i]
          148 
          149                 cls_dicts.append({
          150                     'cls': ListItemButton,
          151                     'kwargs': kwargs,
          152                 })
          153 
          154             return {
          155                 'id': item[-1],
          156                 'size_hint_y': None,
          157                 'height': '30dp',
          158                 'cls_dicts': cls_dicts,
          159             }
          160 
          161         def header_args_converter(row_index, item):
          162             return generic_args_converter(row_index, item)
          163 
          164         def content_args_converter(row_index, item):
          165             return generic_args_converter(row_index, item, is_header=False)
          166 
          167 
          168         self.ids.header_view.adapter = ListAdapter(data=[self.headers],
          169                                    args_converter=header_args_converter,
          170                                    selection_mode='single',
          171                                    allow_empty_selection=False,
          172                                    cls=CompositeListItem)
          173 
          174         self.ids.content_view.adapter = ListAdapter(data=self.data,
          175                                    args_converter=content_args_converter,
          176                                    selection_mode='single',
          177                                    allow_empty_selection=False,
          178                                    cls=CompositeListItem)
          179         self.content_adapter.bind_triggers_to_view(self.ids.content_view._trigger_reset_populate)
          180 
          181 class HorizVertGrid(GridView):
          182     pass
          183 
          184 
          185 if __name__ == "__main__":
          186     from kivy.app import App
          187     class MainApp(App):
          188 
          189         def build(self):
          190             data = []
          191             for i in range(90):
          192                 data.append((str(i), str(i)))
          193             self.data = data
          194             return Builder.load_string('''
          195 BoxLayout:
          196     orientation: 'vertical'
          197     HorizVertGrid:
          198         on_parent: if args[1]: self.content_adapter.data = app.data
          199         headers:['Address', 'Previous output']
          200         widths: [400, 500]
          201 
          202 <Label>
          203     font_size: '16sp'
          204 ''')
          205     MainApp().run()