tuikit/widgets/scrollview.py
changeset 114 26c02bd94bd9
parent 77 fc1989059e19
child 117 8680c2333546
equal deleted inserted replaced
113:6796adfdc7eb 114:26c02bd94bd9
       
     1 from tuikit.core.container import Container
       
     2 from tuikit.layouts.offset import OffsetLayout
       
     3 
       
     4 #from tuikit.layout import AnchorLayout, OffsetLayout
       
     5 #from tuikit.scrollbar import VScrollbar, HScrollbar
       
     6 #from tuikit.common import Borders
       
     7 
       
     8 
       
     9 class Viewport(Container):
       
    10 
       
    11     """Viewport for partial view on widgets.
       
    12 
       
    13     Viewport is special type of Container, which shows partial view
       
    14     on its managed widgets. This view can be moved to show different part
       
    15     and thus allow "scrolling" over the content. Complete view with scrollbars
       
    16     is implemented in ScrollView.
       
    17 
       
    18     """
       
    19 
       
    20     def __init__(self):
       
    21         Container.__init__(self, OffsetLayout)
       
    22 
       
    23 
       
    24 class Scrollview(Container):
       
    25 
       
    26     def __init__(self):
       
    27         Container.__init__(self)
       
    28 
       
    29 
       
    30 class Scrolling:
       
    31     def __init__(self):
       
    32         self.vscroll = VScrollbar()
       
    33         self.vscroll.add_handler('change', self._on_vscroll_change)
       
    34         AnchorLayout.add(self, self.vscroll, halign='right', valign='fill')
       
    35 
       
    36         self.hscroll = HScrollbar()
       
    37         self.hscroll.add_handler('change', self._on_hscroll_change)
       
    38         AnchorLayout.add(self, self.hscroll, halign='fill', valign='bottom')
       
    39 
       
    40     def on_resize(self, ev):
       
    41         self._update_scroll_max()
       
    42 
       
    43     def _connect_child(self, widget):
       
    44         widget.add_handler('sizereq', self._on_child_sizereq)
       
    45         widget.add_handler('spotmove', self._on_child_spotmove)
       
    46         widget.add_handler('scrollreq', self._on_child_scrollreq)
       
    47 
       
    48     def _on_child_sizereq(self, ev):
       
    49         self._update_scroll_max()
       
    50 
       
    51     def _on_child_spotmove(self, ev):
       
    52         child = ev.originator
       
    53         # x
       
    54         spot_x = child.x - self._inner.offset.x + child.spot.x
       
    55         if spot_x < self.hscroll.scroll_pos:
       
    56             self.hscroll.scroll_pos = spot_x
       
    57         if spot_x > (self._inner.width - 1) + self.hscroll.scroll_pos:
       
    58             self.hscroll.scroll_pos = spot_x - (self._inner.width - 1)
       
    59         # y
       
    60         spot_y = child.y - self._inner.offset.y + child.spot.y
       
    61         if spot_y < self.vscroll.scroll_pos:
       
    62             self.vscroll.scroll_pos = spot_y
       
    63         if spot_y > (self._inner.height - 1) + self.vscroll.scroll_pos:
       
    64             self.vscroll.scroll_pos = spot_y - (self._inner.height - 1)
       
    65 
       
    66     def _on_child_scrollreq(self, ev):
       
    67         new_scroll_pos = self.vscroll.scroll_pos + ev.data
       
    68         if new_scroll_pos > self.vscroll.scroll_max:
       
    69             self.vscroll.scroll_pos = self.vscroll.scroll_max
       
    70         elif new_scroll_pos < 0:
       
    71             self.vscroll.scroll_pos = 0
       
    72         else:
       
    73             self.vscroll.scroll_pos = new_scroll_pos
       
    74 
       
    75     def _on_vscroll_change(self, ev):
       
    76         self._inner.offset.y = - self.vscroll.scroll_pos
       
    77 
       
    78     def _on_hscroll_change(self, ev):
       
    79         self._inner.offset.x = - self.hscroll.scroll_pos
       
    80 
       
    81     def _update_scroll_max(self):
       
    82         max_width = 0
       
    83         max_height = 0
       
    84         for child in self._inner.children:
       
    85             posx, posy = child.hint_value('position')
       
    86             child_width = posx + child.sizereq.w
       
    87             if child_width > max_width:
       
    88                 max_width = child_width
       
    89             child_height = posy + child.sizereq.h
       
    90             if child_height > max_height:
       
    91                 max_height = child_height
       
    92         max_width += 1
       
    93         self.hscroll.scroll_max = max_width - self._inner.width
       
    94         self.vscroll.scroll_max = max_height - self._inner.height
       
    95         hscroll_hide = max_width < self._inner.width
       
    96         vscroll_hide = max_height < self._inner.height
       
    97         self._toggle_scrollers(hscroll_hide, vscroll_hide)
       
    98 
       
    99     def _toggle_scrollers(self, hscroll_hide, vscroll_hide):
       
   100         if hscroll_hide:
       
   101             self.hscroll.hide()
       
   102         else:
       
   103             self.hscroll.show()
       
   104         if vscroll_hide:
       
   105             self.vscroll.hide()
       
   106         else:
       
   107             self.vscroll.show()
       
   108         # self._inner.need_resize()
       
   109 
       
   110 
       
   111 class ScrollView(OffsetView, Scrolling):
       
   112     """Scrolling view
       
   113 
       
   114     Shows scrollbars when needed.
       
   115     Scrolling area is determined according to child widget's size request.
       
   116 
       
   117     """
       
   118 
       
   119     def __init__(self):
       
   120         OffsetView.__init__(self)
       
   121         Scrolling.__init__(self)
       
   122 
       
   123     def add(self, widget, **kwargs):
       
   124         OffsetView.add(self, widget, **kwargs)
       
   125         self._connect_child(widget)
       
   126 
       
   127     def _toggle_scrollers(self, hscroll_hide, vscroll_hide):
       
   128         bpad = int(not hscroll_hide)
       
   129         self.vscroll.update_hint('margin', b=bpad)
       
   130         rpad = int(not vscroll_hide)
       
   131         self.hscroll.update_hint('margin', r=rpad)
       
   132         self._inner.update_hint('margin', b=bpad, r=rpad)
       
   133         Scrolling._toggle_scrollers(self, hscroll_hide, vscroll_hide)
       
   134