Lightningbeam/PyGUI-2.5.3/GUI/Generic/GScrollableViews.py

169 lines
5.9 KiB
Python

#
# Python GUI - Scrollable Views - Generic
#
from GUI.Geometry import rect_sized, add_pt, sub_pt
from GUI.Properties import overridable_property
from GUI.Geometry import sect_rect
from GUI import DrawableContainer
default_extent = (300, 300)
default_line_scroll_amount = (16, 16)
default_scrolling = 'hv'
class ScrollableView(DrawableContainer):
"""A ScrollableView is a 2D drawing area having its own coordinate
system and clipping area, with support for scrolling."""
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',
"Size 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.")
background_color = overridable_property('background_color',
"Color with which to fill areas outside the extent, or None")
#scroll_bars = overridable_property('scroll_bars',
# "Attached ScrollBar instances.")
#
## _scroll_bars [ScrollBar]
def set(self, **kwds):
if 'scrolling' in kwds:
self.scrolling = kwds.pop('scrolling')
DrawableContainer.set(self, **kwds)
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)
def get_print_extent(self):
return self.extent
def get_background_color(self):
return self._background_color
def set_background_color(self, x):
self._background_color = x
self.invalidate()
#
# 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())
#
# Background drawing
#
def _draw_background(self, canvas, clip_rect):
# If the view has a background color, uses it to fill the parts of the
# clip_rect that are outside the view's extent and returns the remaining
# rectangle. Otherwise, returns the clip_rect unchanged.
color = self._background_color
if color:
vl, vt, vr, vb = clip_rect
ew, eh = self.extent
if vr > ew or vb > eh:
#if getattr(self, "_debug_bg", False): ###
# print "ScrollableView: old backcolor =", canvas.backcolor ###
canvas.gsave()
canvas.backcolor = color
if ew < vr:
#if getattr(self, "_debug_bg", False): ###
# print "ScrollableView: erasing", (ew, vt, vr, vb) ###
canvas.erase_rect((ew, vt, vr, vb))
if eh < vb:
if getattr(self, "_debug_bg", False): ###
print "ScrollableView: erasing", (vl, eh, ew, vb) ###
canvas.erase_rect((vl, eh, ew, vb))
canvas.grestore()
#if getattr(self, "_debug_bg", False): ###
# print "ScrollableView: restored backcolor =", canvas.backcolor ###
return sect_rect(clip_rect, (0, 0, ew, eh))
return clip_rect