
from __future__ import with_statement

import gobject
import gtk
import gtksourceview2

from glitch.gtk import GtkCamera

create = """
import OpenGL.GL as gl

import glitch
from glitch.limbo.lights import (
    DiffuseLight, LightSwitch)
from glitch.limbo.objects import (
  Cube, Sphere)
from glitch.limbo.material import Material

c = Material(r=1, children=[Cube()])
translate = glitch.Translate(children=[c])
camera.children = [LightSwitch(children=[
    DiffuseLight(y=2, z=2, children=[translate])])]
"""
update = """
from math import sin

translate.x = 2 * sin(t/10.0)
camera.refresh()
"""
error_color = gtk.gdk.Color(1.0, 0.7, 0.7)
white = gtk.gdk.Color(1.0, 1.0, 1.0)
update_code = None
t = 0

def make_srcview(initial_text):
    buffer = gtksourceview2.Buffer()
    buffer.set_language(python)
    buffer.set_text(initial_text)

    srcview = gtksourceview2.View(buffer)
    srcview.set_size_request(400, -1)

    frame = gtk.Frame()
    frame.props.shadow_type = gtk.SHADOW_IN
    frame.add(srcview)
    return (frame, srcview, buffer)

def view_compile(view, name):
    buffer = view.props.buffer
    source = buffer.get_text(*buffer.get_bounds())

    try:
        code = compile(source, name, 'exec')
    except Exception, e:
        view.modify_base(gtk.STATE_NORMAL, error_color)
        raise e
    else:
        view.modify_base(gtk.STATE_NORMAL, white)

    return code

def change_timeout(view):
    global change_timeout_id
    global update_code
    print 'compiling...',

    with camera:
        try:
            if view == srcview1:
                code = view_compile(view, 'create')
            else:
                update_code = view_compile(view, 'update')
        except Exception, e:
            print
            print e
        else:
            print 'ok'

            if view == srcview1:
                try:
                    exec code in globals()
                except Exception, e:
                    print e

    change_timeout_id = None

def tick():
    global t
    t += 1

    try:
        exec update_code in globals()
    except Exception, e:
        print e

    return True

def buffer_changed(buffer, view):
    global change_timeout_id

    if change_timeout_id is not None:
        gobject.source_remove(change_timeout_id)

    change_timeout_id = gobject.timeout_add(1000, change_timeout, view)

if __name__ == '__main__':
    change_timeout_id = None

    mgr = gtksourceview2.LanguageManager()
    python = mgr.get_language('python')

    w = gtk.Window()
    w.connect('destroy', lambda w: gtk.main_quit())

    hbox = gtk.HBox()
    vbox = gtk.VBox(spacing=1)

    (srcview1_frame, srcview1, buffer1) = make_srcview(create)
    (srcview2_frame, srcview2, buffer2) = make_srcview(update)
    buffer1.connect('changed', buffer_changed, srcview1)
    buffer2.connect('changed', buffer_changed, srcview2)

    camera = GtkCamera(eye=[1, 0, 3])

    vbox.pack_start(srcview1_frame, True)
    vbox.pack_start(srcview2_frame, True)
    hbox.pack_start(vbox, False)
    hbox.pack_start(camera, True)

    w.add(hbox)
    w.show_all()

    exec create
    update_code = view_compile(srcview2, 'update')
    gobject.timeout_add(1000 / 30, tick)

    gtk.main()

