#
#   PyGUI - OpenGL View - Gtk/GtkGLExt
#

try:
    from gtk import gdkgl, gtkgl
    from OpenGL.GL import glViewport
except ImportError, e:
    raise ImportError("OpenGL support is not available (%s)" % e)

from GUI.GGLConfig import GLConfig as GGLConfig, GLConfigError
from GUI.GGLViews import GLView as GGLView
from GUI.GGLPixmaps import GLPixmap as GGLPixmap
from GUI import ImageBase
from GUI.GtkPixmaps import GtkPixmap
from GUI.GLContexts import GLContext
from GUI.GLTextures import Texture
from GUI.GLDisplayLists import DisplayList

#------------------------------------------------------------------------------

def gtk_find_config_default(attr, mode_bit):
    try:
        cfg = gdkgl.Config(mode = mode_bit)
        value = cfg.get_attrib(attr)[0]
    except gdkgl.NoMatches:
        value = 0
    print "default for attr", attr, "=", value
    return value

#------------------------------------------------------------------------------

class GLConfig(GGLConfig):
    
    _alpha = False
    _color_size = 1
    _alpha_size = 1
    _depth_size = 1
    _stencil_size = 1
    _accum_size = 1
    
    def _gtk_get_config(self):
        csize = self._color_size
        asize = 0
        dsize = 0
        ssize = 0
        acsize = 0
        aasize = 0
        if self._alpha:
            asize = self._alpha_size
        if self._depth_buffer:
            dsize = self._depth_size
        if self._stencil_buffer:
            ssize = self._stencil_size
        if self._accum_buffer:
            acsize = self._accum_size
            if self._alpha:
                aasize = acsize
        attrs = [
            gdkgl.RGBA,
            gdkgl.RED_SIZE, csize,
            gdkgl.GREEN_SIZE, csize,
            gdkgl.BLUE_SIZE, csize,
            gdkgl.ALPHA_SIZE, asize,
            gdkgl.AUX_BUFFERS, self._aux_buffers,
            gdkgl.DEPTH_SIZE, dsize,
            gdkgl.STENCIL_SIZE, ssize,
            gdkgl.ACCUM_RED_SIZE, acsize,
            gdkgl.ACCUM_GREEN_SIZE, acsize,
            gdkgl.ACCUM_BLUE_SIZE, acsize,
            gdkgl.ACCUM_ALPHA_SIZE, aasize,
        ]
        if self._double_buffer:
            attrs += [gdkgl.DOUBLEBUFFER]
        if self._stereo:
            attrs += [gdkgl.STEREO]
        if self._multisample:
            attrs += [
                gdkgl.SAMPLE_BUFFERS, 1,
                gdkgl.SAMPLES, self._samples_per_pixel
            ]
        result = self._gdkgl_config(attrs)
        if not result and self._double_buffer:
            attrs.remove(gdkgl.DOUBLEBUFFER)
            result = self._gdkgl_config(attrs)
        if not result:
            raise GLConfigError
        return result
    
    def _gdkgl_config(self, attrs):
        try:
            return gdkgl.Config(attrib_list = attrs)
        except gdkgl.NoMatches:
            return None
    
    def _gtk_set_config(self, gtk_config):
        def attr(key):
            return gtk_config.get_attrib(key)[0]
        self._color_size = attr(gdkgl.RED_SIZE)
        self._alpha_size = attr(gdkgl.ALPHA_SIZE)
        self._alpha = gtk_config.has_alpha()
        self._double_buffer = gtk_config.is_double_buffered()
        self._stereo = gtk_config.is_stereo()
        self._aux_buffers = attr(gdkgl.AUX_BUFFERS)
        self._depth_size = attr(gdkgl.DEPTH_SIZE)
        self._depth_buffer = gtk_config.has_depth_buffer()
        self._stencil_size = attr(gdkgl.STENCIL_SIZE)
        self._stencil_buffer = gtk_config.has_stencil_buffer()
        self._accum_size = attr(gdkgl.ACCUM_RED_SIZE)
        self._accum_buffer = gtk_config.has_accum_buffer()
        self._multisample = attr(gdkgl.SAMPLE_BUFFERS) <> 0
        self._samples_per_pixel = attr(gdkgl.SAMPLES)
    
    def supported(self, mode = 'both'):
        try:
            gtk_config = self._gtk_get_config()
            pf = GLConfig.__new__(GLConfig)
            pf._gtk_set_config(gtk_config)
            return pf
        except GLConfigError:
            return None

#------------------------------------------------------------------------------

class GLView(GGLView):

    _first_expose = 0

    def __init__(self, config = None, share_group = None, **kwds):
        pf = GLConfig._from_args(config, kwds)
        GLContext.__init__(self, share_group, pf, kwds)
        gtk_share = self._gtk_get_share()
        area = gtkgl.DrawingArea(glconfig = self._gl_config, share_list = gtk_share,
            render_type = gdkgl.RGBA_TYPE)
        area.show()
        self._gtk_connect_after(area, "realize", self._gtk_realize_signal)
        self._gtk_connect(area, "expose-event", self._gtk_expose_event_signal)
        GGLView.__init__(self, _gtk_outer = area, _gtk_input = area,
            _gtk_focus = area)
        self.set(**kwds)

    def _resized(self, delta):
        self.with_context(self._update_viewport)
    
    def _gtk_get_gl_context(self):
        if not self._gl_context:
            self._gtk_inner_widget.realize()
        return self._gl_context
    
    def _gtk_realize_signal(self):
        #print "GLView._gtk_realize_signal" ###
        area = self._gtk_inner_widget
        self._gl_drawable = area.get_gl_drawable()
        self._gl_context = area.get_gl_context()
        self.with_context(self.init_context)
    
    def _gtk_expose_event_signal(self, gtk_event):
        #print "GLView._gtk_expose_event_signal" ###
        if not self._first_expose:
            self.with_context(self._update_viewport)
            self._first_expose = 1
        try:
            self.with_context(self._render, flush = True)
        except:
            import sys, traceback
            sys.stderr.write("\n<<<<<<<<<< Exception while rendering a GLView\n")
            traceback.print_exc()
            sys.stderr.write(">>>>>>>>>>\n\n")
    
    def invalidate(self):
        gtk_window = self._gtk_outer_widget.window
        if gtk_window:
            width, height = self.size
            gtk_window.invalidate_rect((0, 0, width, height), 0)

#------------------------------------------------------------------------------

class GLPixmap(GtkPixmap, GGLPixmap):

    def __init__(self, width, height, config = None, share_group = None, **kwds):
        pf = GLConfig._from_args(config, kwds)
        GLContext.__init__(self, share_group, pf, kwds)
        gl_config = pf._gtk_get_config()
        self._gl_config = gl_config
#		if share:
#			gtk_share = share.shared_context._gtk_get_gl_context()
#		else:
#			gtk_share = None
        gtk_share = self._gtk_get_share()
        GtkPixmap.__init__(self, width, height)
        gdk_pixmap = self._gdk_pixmap
        gdkgl.ext(gdk_pixmap)
        self._gl_drawable = gdk_pixmap.set_gl_capability(glconfig = gl_config)
        print "GLPixmap: self._gl_drawable =", self._gl_drawable ###
        self._gl_context = gdkgl.Context(
            self._gl_drawable,
            direct = False,
            share_list = gtk_share,
            render_type = gdkgl.RGBA_TYPE
        )
        print "GLPixmap: self._gl_context =", self._gl_context ###
        ImageBase.__init__(self, **kwds)
        self.with_context(self._init_context)
        print "GLPixmap: initialised context" ###

#	def _init_context(self):
#		width, height = self.size
#		glViewport(0, 0, int(width), int(height))
#		print "GLPixmap: Set viewport to", width, height ###
#		self.init_context()

    