#!/usr/bin/env python2.4
# I, Adam Olsen, am the original author of this work.  I hereby
# donate it into the public domain, and relinquish any rights I
# may have in it.

from __future__ import division

import cairo
import pygtk
pygtk.require('2.0')
import gtk
import gtk.gdk
import pango
import gobject

class ExtentDemo(gtk.Widget):
    def __init__(self):
        gtk.Widget.__init__(self)
        self.text = "foo"
        self.text = """Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor.\n\tDuis aute irure dolor in reprehenderit in voluptate velit esse."""
        self.modes = [
            (1, 0),  # Logical, Ink?
            ('line', 'cluster', 'run', 'char'),
            (pango.ALIGN_LEFT, pango.ALIGN_CENTER, pango.ALIGN_RIGHT),
        ]
        self.current_modes = [0, 0, 0]
        self.mode_num = 1

    def do_realize(self):
        self.set_flags(self.flags() | gtk.REALIZED)

        self.window = gtk.gdk.Window(
            self.get_parent_window(),
            width=self.allocation.width,
            height=self.allocation.height,
            window_type=gtk.gdk.WINDOW_CHILD,
            wclass=gtk.gdk.INPUT_OUTPUT,
            event_mask=self.get_events() | gtk.gdk.EXPOSURE_MASK)

        self.window.set_user_data(self)

        self.style.attach(self.window)

        self.style.set_background(self.window, gtk.STATE_NORMAL)
        self.window.move_resize(*self.allocation)

    def do_unrealize(self):
        self.window.destroy()

    def do_size_request(self, requisition):
        requisition.width = 800
        requisition.height = 600

    def do_expose_event(self, event):
        context = self.window.cairo_create()
        context.rectangle(event.area.x, event.area.y,
                          event.area.width, event.area.height)
        context.clip()
        pangocontext = self.get_pango_context()

        self.draw(context, pangocontext)

        return False

    def draw(self, context, pangocontext):
        width = self.allocation.width
        font = pango.FontDescription()
        font.set_size(48 * pango.SCALE)
        extentindex, name, align = (self.modes[i][j] for i,j in
                                    enumerate(self.current_modes))

        labellayout = pango.Layout(pangocontext)
        labellayout.set_text(self.mode_name())
        context.move_to(25, 25)
        context.show_layout(labellayout)

        layout = pango.Layout(pangocontext)
        layout.set_font_description(font)
        layout.set_text(self.text)
        layout.set_width(750 * pango.SCALE)
        layout.set_alignment(align)
        context.move_to(25, 50)
        context.show_layout(layout)

        context.set_source_rgba(1, 0, 0, 0.5)
        context.rectangle(25, 50, 750, 550)
        context.stroke()

        li = layout.get_iter()

        if name == 'char':
            return  # char currently just crashes

        while True:
            extents = getattr(li, 'get_%s_extents' % name)()[extentindex]
            context.set_source_rgba(0, 1, 0, 0.5)
            x, y, width, height = self._descale(extents)
            x += 25
            y += 50
            context.rectangle(x, y, width, height)
            context.stroke()

            if not getattr(li, 'next_%s' % name)():
                break

    def mode_name(self):
        extentindex, name, align = self.current_modes

        return '%i: %s %s %s' % (self.mode_num,
                                 ('left', 'center', 'right')[align],
                                 self.modes[1][name],
                                 ('logical', 'ink')[extentindex],
        )

    def cycle_mode(self):
        i = 0
        self.mode_num += 1
        for i in range(len(self.modes)):
            self.current_modes[i] += 1
            if self.current_modes[i] < len(self.modes[i]):
                break
            self.current_modes[i] = 0
        else:
            self.mode_num = 1
        self.queue_draw()

    def key_press_event(self, widget, event):
        if event.string == ' ':
            self.cycle_mode()
        elif event.string == 'q':
            gtk.main_quit()

    def _descale(self, rect):
        return (i / pango.SCALE for i in rect)

    def run(self):
        window = gtk.Window()
        window.add(self)
        window.connect("destroy", gtk.main_quit)
        window.connect("key-press-event", self.key_press_event)
        window.show_all()

        gtk.main()

gobject.type_register(ExtentDemo)


def main():
    ed = ExtentDemo()
    ed.run()

if __name__ == "__main__":
    main()
