#
#   Python GUI - Views - Gtk
#

from math import floor, ceil
import gtk
from gtk import gdk
from Canvases import Canvas
from Events import Event
from GViews import View as GView, _default_line_scroll_amount
from GtkInput import GtkInput

class View(GView, GtkInput):

    def __init__(self, **kwds):
        self._extent_origin = (0, 0)
        gtk_layout = gtk.Layout()
        gtk_layout.add_events(gdk.EXPOSURE_MASK)
        gtk_layout.show()
        self._gtk_connect(gtk_layout, 'expose-event',
            self._gtk_expose_event_signal)
        GView.__init__(self, _gtk_outer = gtk_layout)
        GtkInput.__init__(self, gtk_layout)
        self.set_line_scroll_amount(_default_line_scroll_amount)
        self.set(**kwds)
    
    #
    #		Getting properties
    #
    
    def get_extent(self):
        l, t = self._extent_origin
        w, h = self._gtk_outer_widget.get_size()
        return (l, t, l + w, t + h)
    
    def get_scroll_offset(self):
        hadj, vadj = self._gtk_adjustments()
        return int(hadj.value), int(vadj.value)

    def get_line_scroll_amount(self):
        x0, y0 = self._extent_origin
        hadj, vadj = self._gtk_adjustments()
        return x0 + hadj.step_increment, y0 + vadj.step_increment
    
    def _gtk_adjustments(self):
        gtk_widget = self._gtk_outer_widget
        hadj = gtk_widget.get_hadjustment()
        vadj = gtk_widget.get_vadjustment()
        return hadj, vadj

    #
    #		Setting properties
    #

    def set_extent(self, (l, t, r, b)):
        w = r - l
        h = b - t
        self._extent_origin = (l, t)
        self._gtk_outer_widget.set_size(w, h)

    def set_scroll_offset(self, (x, y)):
        """Set the scroll offset."""
        x0, y0 = self._extent_origin
        hadj, vadj = self._gtk_adjustments()
        hadj.value = float(x - x0)
        vadj.value = float(y - y0)
    
    def set_line_scroll_amount(self, (dx, dy)):
        hadj, vadj = self._gtk_adjustments()
        hadj.step_increment = float(dx) # Amazingly, ints are not
        vadj.step_increment = float(dy) # acceptable here.
    
    #
    #		Other methods
    #

    def with_canvas(self, proc):
        hadj, vadj = self._gtk_adjustments()
        clip = rect_sized((hadj.value, vadj.value), self.size)
        canvas = Canvas(self._gtk_outer_widget.bin_window, self._extent_origin, clip)
        proc(canvas)
    
    def invalidate_rect(self, (l, t, r, b)):
        gdk_window = self._gtk_outer_widget.bin_window
        x0, y0 = self._extent_origin
        gdk_rect = (int(floor(l - x0)), int(floor(t - y0)),
            int(ceil(r - l)), int(ceil(b - t)))
        #print "View.invalidate_rect: gdk_rect =", gdk_rect ###
        gdk_window.invalidate_rect(gdk_rect, 0)

    #
    #		Internal
    #

    def _gtk_expose_event_signal(self, gtk_event):
        #print "View._gtk_expose_event_signal:", self ###
        l, t, w, h = gtk_event.area
        clip = (l, t, l + w, t + h)
        #print "...clip =", clip ###
        gtk_layout = self._gtk_outer_widget
        canvas = Canvas(gtk_layout.bin_window, self._extent_origin, clip)
        self.draw(canvas)
