#! /usr/bin/env python

import string
import sys

import gtk

import piddle
import piddleGTK
import piddletest

from piddle import Color, Font


def gtk_test_1(canvasClass):
    """Test case that exercises the ability to set the background color of
    the piddleGTK.*Canvas classes.  Also tests interactive capability.
    """
    canvas = canvasClass((200, 200))
    #
    canvas.backgroundColor = Color(0.9, 0.9, 0.8)
    canvas.clear()
    canvas.drawLine(10, 10, 190, 190)
    canvas.drawLine(10, 190, 190, 10, Color(1.0,0.0,0.0), 3)
    canvas.drawRect(90, 10, 110, 30, edgeWidth=2,
                    edgeColor=Color(0.0,0.0,0.7))
    canvas.drawRect(90, 170, 110, 190, edgeWidth=2,
                    edgeColor=Color(1.0,0.0,0.0),
                    fillColor=Color(0.0,0.0,0.7))
    canvas.drawLines([(50, 90, 150, 90),
                      (50, 110, 150, 110),
                      (90, 50, 90, 150),
                      (110, 50, 110, 150),
                      ], color=Color(0.0,0.0,1.0), width=2)
    canvas.drawPolygon([(30,10), (51,31), (30,52)],
                       edgeColor=Color(0.0,0.7,0.0), edgeWidth=2)
    canvas.drawPolygon([(130,10), (151,31), (130,52)],
                       edgeColor=Color(0.0,0.6,0.6), edgeWidth=2,
                       fillColor=Color(0.5,0.0,0.0), closed=1)
    canvas.onClick = onClick
    canvas.onOver = onOver
    canvas.onKey = onKey
    return canvas


def strings(canvasClass):
    """Checks font metrics, and also illustrates the standard fonts."""
    def Write(canvas, s, font, curs):
        if font: canvas.defaultFont = font
        text = s
        while text and text[-1] == '\n': text = text[:-1]
        canvas.drawString(text, x=curs[0], y=curs[1])
        if s[-1] == '\n':
            curs[0] = 10
            curs[1] = curs[1] + canvas.fontHeight() + canvas.fontDescent()
        else:
            curs[0] = curs[0] + canvas.stringWidth(s)

    def CenterAndBox(canvas, s, cx=200, y=40):
        "tests string positioning, stringWidth, fontAscent, and fontDescent"
        canvas.drawLine(cx,y-30, cx,y+30, color=piddle.yellow)
        w = canvas
        w = canvas.stringWidth(s)

        canvas.drawLine(cx-w/2, y, cx+w/2, y, color=piddle.red)
        canvas.drawString(s, cx-w/2, y)
        canvas.defaultLineColor = Color(0.7,0.7,1.0)	# light blue
        canvas.drawLine(cx-w/2, y-20, cx-w/2, y+20)	# left
        canvas.drawLine(cx+w/2, y-20, cx+w/2, y+20)	# right
        asc, desc = canvas.fontAscent(), canvas.fontDescent()
        canvas.drawLine(cx-w/2-20, y-asc, cx+w/2+20, y-asc)	# top
        canvas.drawLine(cx-w/2-20, y+desc, cx+w/2+20, y+desc)	# bottom

    def StandardFonts(canvas, Write):
        canvas.defaultLineColor = piddle.black
        curs = [10,70]
        for size in (12, 18):
            for fontname in ("times", "courier", "helvetica", "symbol",
                             "monospaced", "serif", "sansserif"):
                curs[0] = 10
                curs[1] = curs[1] + size*1.5
                Write(canvas, "%s %d " % (fontname,size),
                      Font(face=fontname, size=size), curs)
                Write(canvas, "bold ",
                      Font(face=fontname, size=size, bold=1), curs)
                Write(canvas, "italic ",
                      Font(face=fontname, size=size, italic=1), curs)
                Write(canvas, "underlining",
                      Font(face=fontname, size=size, underline=1), curs)

    canvas = canvasClass( size=(400,400), name="test-strings" )
    # we don't support rotated text yet...
##     canvas.drawString("This is\na multi-line\nstring!!!",
##                       280, 120, angle=45 )
    CenterAndBox(canvas, "spam, spam, spam, baked beans, and spam!")
    StandardFonts(canvas, Write)
    return canvas


def font_mapping(canvasClass):
    f = TextDisplay("Font Conversion Test")
    fonts = [
        Font(),
        Font(bold=1),
        Font(size=24, italic=1),
        Font(bold=1, italic=1),
        Font(face='courier'),
        Font(face='monospaced'),
        ]
    for font in fonts:
        key = piddleGTK._font_to_key(font)
        xlfd = piddleGTK._fontkey_to_xlfd(key)
        f.write("%s\n" % font)
        f.write("    %s\n" % `key`)
        f.write("    %s\n\n" % xlfd)
    # just have to have a .flush() method:
    return f


# List of (description, function) pairs that should be used to create the
# test selection dialog.  Similar to the piddletest.tests list, but allows
# more human-friendly names for the tests.
#
testitems = [
    ("Background Color", gtk_test_1),
    ("Non-rotated Text", strings),
    ("Font Mapping", font_mapping),
    ]


def onClick(canvas, x, y):
    canvas.setInfoLine("onClick(%s, %s)" % (x, y))

def onOver(canvas, x, y):
    canvas.setInfoLine("onOver(%s, %s)" % (x, y))

def onKey(canvas, key, modifiers):
    canvas.setInfoLine("onKey(%s, %s)" % (`key`, modifiers))


class TextDisplay:
    def __init__(self, title):
        top = gtk.GtkDialog()
        top.set_title(title)
        # set up the text widget at the top:
        scrwin = gtk.GtkScrolledWindow()
        scrwin.set_border_width(10)
        scrwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
        text = self.__text = gtk.GtkText(vadj=scrwin.get_vadjustment())
        text.freeze()
        scrwin.add(text)
        top.vbox.pack_start(scrwin)
        # set up the dismiss button:
        button = gtk.GtkButton("Dismiss")
        button.connect("clicked",
                       lambda button, top=top: top.destroy())
        bbox = gtk.GtkHButtonBox()
        bbox.set_layout(gtk.BUTTONBOX_END)
        bbox.pack_end(button)
        top.action_area.pack_end(bbox)
        # all done!
        top.set_default_size(500, 300)
        top.show_all()

    def write(self, s):
        self.__text.insert_defaults(s)

    def flush(self):
        self.__text.thaw()


class Test:
    def __init__(self, test):
        self.test = test
    def __call__(self, button):
        canvas = self.test(piddleGTK.GTKCanvas)
        canvas.flush()
        #piddletest.runtest("piddleGTK", self.test)


def make_test_info(test):
    return (string.capitalize(test.__name__), test)


def main():
    top = gtk.GtkWindow()
    bbox = gtk.GtkVButtonBox()
    bbox.set_spacing(0)
    top.add(bbox)
    top.connect("destroy", gtk.mainquit)
    top.connect("delete_event", gtk.mainquit)
    tests = map(make_test_info, piddletest.tests)
    tests.extend(testitems)
    for name, test in tests:
        b = gtk.GtkButton(name)
        b.connect("clicked", Test(test))
        bbox.pack_start(b)
    top.show_all()
    gtk.mainloop()


if __name__ == "__main__":
    main()
