#
#   Python GUI - Drawing - Gtk
#

from gtk import gdk
from Geometry import sect_rect
from StdFonts import application_font
from GCanvases import Canvas as GCanvas
from GCanvasPaths import CanvasPaths as GCanvasPaths

class Canvas(GCanvas, GCanvasPaths):

    def __init__(self, gdk_drawable, origin, clip_rect):
        self._gdk_drawable = gdk_drawable
        self._gdk_gc = gdk.GC(gdk_drawable)
        self._origin = origin
        self._font = application_font
        self._gstack = []
        self._gdk_set_clip_rect(clip_rect)
        GCanvas.__init__(self)
        GCanvasPaths.__init__(self)
        self.initgraphics()
    
    def get_forecolor(self):
        return self._forecolor
    
    def set_forecolor(self, c):
        self._forecolor = c
        self._gdk_gc.set_rgb_fg_color(c._gdk_color)
    
    def get_backcolor(self):
        return self._backcolor
    
    def set_backcolor(self, c):
        self._backcolor = c
        self._gdk_gc.set_rgb_bg_color(c._gdk_color)
    
    def get_pensize(self):
        return self._gdk_gc.line_width
    
    def set_pensize(self, d):
        self._gdk_gc.line_width = int(round(d))
    
    def get_font(self):
        return self._font
    
    def set_font(self, f):
        self._font = f
    
    #def initclip(self):
    #	self._gdk_set_clip_rect(self._initial_clip_rect)
    
    def rectclip(self, r):
        self._gdk_set_clip_rect(sect_rect(self._clip_rect, r))
    
    def _gdk_set_clip_rect(self, r):
        self._clip_rect = r
        l, t, r, b = r
        self._gdk_gc.set_clip_rectangle((l, t, r - l, b - t))
    
    def gsave(self):
        self._gstack.append((
            self._current_point,
            self._forecolor, 
            self._backcolor,
            self._gdk_gc.line_width,
            self._font,
            self._clip_rect))
    
    def grestore(self):
        gdk_gc = self._gdk_gc
        (self._current_point,
            forecolor, 
            backcolor,
            gdk_gc.line_width,
            self._font,
            clip_rect) = self._gstack.pop()
        self._forecolor = forecolor
        self._backcolor = backcolor
        gdk_gc.set_rgb_fg_color(forecolor._gdk_color)
        gdk_gc.set_rgb_bg_color(backcolor._gdk_color)
        self._gdk_set_clip_rect(clip_rect)
    
    def stroke(self):
        gdk_drawable =  self._gdk_drawable
        gdk_gc = self._gdk_gc
        for subpath in self._path:
            closed = (subpath[0] is subpath[-1])
            if closed:
                gdk_drawable.draw_polygon(gdk_gc, 0, subpath)
            else:
                gdk_drawable.draw_lines(gdk_gc, subpath)
    
    def fill(self):
        gdk_drawable =  self._gdk_drawable
        gdk_gc = self._gdk_gc
        for subpath in self._path:
            gdk_drawable.draw_polygon(gdk_gc, 1, subpath)
    
    def show_text(self, text):
        x, y = self._current_point
        font = self._font
        layout = font._get_pango_layout(text, True)
        self._gdk_drawable.draw_layout(self._gdk_gc, x, y - font.ascent, layout)
        dx = layout.get_pixel_size()[0]
        self._current_point = (x + dx, y)

    def stroke_rect(self, r):
        l, t, w, h = self._rect_coords(r)
        self._gdk_drawable.draw_rectangle(self._gdk_gc, 0,
            l, t, w, h)
    
    def frame_rect(self, r):
        l, t, w, h = self._frame_coords(r)
        self._gdk_drawable.draw_rectangle(self._gdk_gc, 0,
            l, t, w, h)
    
    def fill_rect(self, r):
        l, t, w, h = self._rect_coords(r)
        self._gdk_drawable.draw_rectangle(self._gdk_gc, 1,
            l, t, w, h)
    
    def stroke_oval(self, r):
        l, t, w, h = self._rect_coords(r)
        self._gdk_drawable.draw_arc(self._gdk_gc, 0,
            l, t, w, h, 0, 23040) # 360 * 64
    
    def frame_oval(self, r):
        l, t, w, h = self._frame_coords(r)
        self._gdk_drawable.draw_arc(self._gdk_gc, 0,
            l, t, w, h, 0, 23040) # 360 * 64
    
    def fill_oval(self, r):
        l, t, w, h = self._rect_coords(r)
        self._gdk_drawable.draw_arc(self._gdk_gc, 1,
            l, t, w, h, 0, 23040) # 360 * 64
    
    def stroke_arc(self, center, radius, start_angle, arc_angle):
        l, t, w, h = self._rect_coords(_arc_rect(center, radius))
        ga1, ga2 = _gdk_angles(start_angle, arc_angle)
        self._gdk_drawable.draw_arc(self._gdk_gc, 0,
            l, t, w, h, ga1, ga2)

    #def frame_arc(self, r, a1, a2):
    def frame_arc(self, center, radius, start_angle, arc_angle):
        l, t, w, h = self._frame_coords(_arc_rect(center, radius))
        ga1, ga2 = _gdk_angles(start_angle, arc_angle)
        self._gdk_drawable.draw_arc(self._gdk_gc, 0,
            l, t, w, h, ga1, ga2)
    
    #def fill_arc(self, r, a1, a2):
    def fill_arc(self, center, radius, start_angle, arc_angle):
        l, t, w, h = self._rect_coords(_arc_rect(center, radius))
        ga1, ga2 = _gdk_angles(start_angle, arc_angle)
        self._gdk_drawable.draw_arc(self._gdk_gc, 1,
            l, t, w, h, ga1, ga2)
    
    def _coords(self, x, y):
        x0, y0 = self._origin
        return int(round(x0 + x)), int(round(y0 + y))

    def _rect_coords(self, (l, t, r, b)):
        x0, y0 = self._origin
        l = int(round(x0 + l))
        t = int(round(y0 + t))
        r = int(round(x0 + r))
        b = int(round(y0 + b))
        return l, t, r - l, b - t
    
    def _frame_coords(self, r):
        l, t, w, h = self._rect_coords(r)
        d = self._gdk_gc.line_width
        e = d // 2
        return l + e, t + e, w - d, h - d
    

def _gdk_angles(start_angle, arc_angle):
    start = int(round(start_angle * 64))
    arc = int(round(arc_angle * 64))
    return -start, -arc

def _arc_rect((cx, cy), r):
    return (cx - r, cy - r, cx + r, cy + r)

