#
#		Python GUI - Scrollable Views - Generic
#

from Geometry import rect_sized, add_pt, sub_pt
from Properties import overridable_property
from Views import View

default_extent = (0, 0, 300, 300)
default_line_scroll_amount = (16, 16)

class ScrollableView(View):
    """A ScrollableView is a View with scrolling support."""
    
    scrolling = overridable_property('scrolling',
        "String containing 'h' for horizontal and 'v' for vertical scrolling.")
    
    hscrolling = overridable_property('hscrolling',
        "True if horizontal scrolling is enabled.")
    
    vscrolling = overridable_property('vscrolling',
        "True if vertical scrolling is enabled.")
    
    extent = overridable_property('extent',
        "Limits of scrollable area in local coordinates.")

    scroll_offset = overridable_property('scroll_offset',
        "Current scrolling position.")

    line_scroll_amount = overridable_property('line_scroll_amount',
        "Tuple specifying horizontal and vertical line scrolling increments.")

    #scroll_bars = overridable_property('scroll_bars',
    #	"Attached ScrollBar instances.")
    #
    ##  _scroll_bars          [ScrollBar]

    def get_scrolling(self):
        chars = []
        if self.hscrolling:
            chars.append('h')
        if self.vscrolling:
            chars.append('v')
        return ''.join(chars)
    
    def set_scrolling(self, value):
        self.hscrolling = 'h' in value
        self.vscrolling = 'v' in value

    def viewed_rect(self):
        """Return the rectangle in local coordinates bounding the currently
        visible part of the extent."""
        return rect_sized(self.scroll_offset, self.size)
    
    #
    #		Coordinate transformation
    #

    def local_to_container_offset(self):
        return sub_pt(self.position, self.scroll_offset)

    #
    #		Scrolling
    #

    def h_line_scroll_amount(self):
        """Return the horizontal line scroll increment."""
        return self.line_scroll_amount[0]

    def v_line_scroll_amount(self):
        """Return the vertical line scroll increment."""
        return self.line_scroll_amount[1]

    def h_page_scroll_amount(self):
        """Return the horizontal page scroll increment."""
        return self.width - self.h_line_scroll_amount()

    def v_page_scroll_amount(self):
        """Return the vertical page scroll increment."""
        return self.height - self.v_line_scroll_amount()

    def scroll_by(self, dx, dy):
        """Scroll by the given amount horizontally and vertically."""
        self.scroll_offset = add_pt(self.scroll_offset, (dx, dy))

    def scroll_line_left(self):
        """Called by horizontal scroll bar to scroll left by one line."""
        self.scroll_by(-self.h_line_scroll_amount(), 0)

    def scroll_line_right(self):
        """Called by horizontal scroll bar to scroll right by one line."""
        self.scroll_by(self.h_line_scroll_amount(), 0)

    def scroll_line_up(self):
        """Called by vertical scroll bar to scroll up by one line."""
        self.scroll_by(0, -self.v_line_scroll_amount())

    def scroll_line_down(self):
        """Called by vertical scroll bar to scroll down by one line."""
        self.scroll_by(0, self.v_line_scroll_amount())

    def scroll_page_left(self):
        """Called by horizontal scroll bar to scroll left by one page."""
        self.scroll_by(-self.h_page_scroll_amount(), 0)

    def scroll_page_right(self):
        """Called by horizontal scroll bar to scroll right by one page."""
        self.scroll_by(self.h_page_scroll_amount(), 0)

    def scroll_page_up(self):
        """Called by vertical scroll bar to scroll up by one page."""
        self.scroll_by(0, -self.v_page_scroll_amount())

    def scroll_page_down(self):
        """Called by vertical scroll bar to scroll down by one page."""
        self.scroll_by(0, self.v_page_scroll_amount())
