X-Git-Url: http://pileus.org/git/?p=grits;a=blobdiff_plain;f=src%2Fobjects%2Fgrits-object.c;h=a1e80ec24c2d01745bf619185fc48f69ebf1a13d;hp=b321b6e994493a3ff71e1abb732870f7cf5256d7;hb=e8af1dabca07d2b7a26369d845a81efeae3e08a0;hpb=3ea7566fadf5490c46e04cb3a2a6cc8e02ac05e6 diff --git a/src/objects/grits-object.c b/src/objects/grits-object.c index b321b6e..a1e80ec 100644 --- a/src/objects/grits-object.c +++ b/src/objects/grits-object.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Andy Spencer + * Copyright (C) 2009-2011 Andy Spencer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,24 +30,29 @@ #include #include -#include +#include "gtkgl.h" #include "grits-object.h" +#include "grits-marshal.h" +/* Constants */ +enum { + SIG_ENTER, + SIG_LEAVE, + SIG_CLICKED, + SIG_BUTTON_PRESS, + SIG_BUTTON_RELEASE, + SIG_KEY_PRESS, + SIG_KEY_RELEASE, + SIG_MOTION, + NUM_SIGNALS, +}; +static guint signals[NUM_SIGNALS]; -/** - * grits_object_draw: - * @object: the object - * @opengl: the viewer the object is being displayed in - * - * Perform any OpenGL commands necessasairy to draw the object. - * - * The GL_PROJECTION and GL_MODELVIEW matricies and GL_ALL_ATTRIB_BITS will be - * restored to the default state after the call to draw. - */ -void grits_object_draw(GritsObject *object, GritsOpenGL *opengl) +void grits_object_pickdraw(GritsObject *object, GritsOpenGL *opengl, gboolean pick) { GritsObjectClass *klass = GRITS_OBJECT_GET_CLASS(object); + if (!klass->draw) { g_warning("GritsObject: draw - Unimplemented"); return; @@ -57,6 +62,14 @@ void grits_object_draw(GritsObject *object, GritsOpenGL *opengl) if (object->hidden) return; + /* Skip object with no signals when picking */ + for (int i = 0; pick; i++) { + if (i == NUM_SIGNALS) + return; + if (g_signal_has_handler_pending(object, signals[i], 0, FALSE)) + break; + } + /* Support GritsTester */ if (!GRITS_IS_OPENGL(opengl)) { g_debug("GritsObject: draw - drawing raw object"); @@ -64,7 +77,7 @@ void grits_object_draw(GritsObject *object, GritsOpenGL *opengl) return; } - /* Calculae distance for LOD and horizon tests */ + /* Calculate distance for LOD and horizon tests */ GritsPoint *center = &object->center; if ((!(object->skip & GRITS_SKIP_LOD) || !(object->skip & GRITS_SKIP_HORIZON)) && @@ -111,7 +124,10 @@ void grits_object_draw(GritsObject *object, GritsOpenGL *opengl) object->center.lon, object->center.elev); - klass->draw(object, opengl); + if (pick && klass->pick) + klass->pick(object, opengl); + else + klass->draw(object, opengl); if (!(object->skip & GRITS_SKIP_STATE)) { glPopAttrib(); @@ -121,12 +137,98 @@ void grits_object_draw(GritsObject *object, GritsOpenGL *opengl) g_mutex_unlock(opengl->sphere_lock); } +/** + * grits_object_draw: + * @object: the object + * @opengl: the viewer the object is being displayed in + * + * Perform any OpenGL commands necessasairy to draw the object. + * + * The GL_PROJECTION and GL_MODELVIEW matricies and GL_ALL_ATTRIB_BITS will be + * restored to the default state after the call to draw. + */ +void grits_object_draw(GritsObject *object, GritsOpenGL *opengl) +{ + grits_object_pickdraw(object, opengl, FALSE); +} + +void grits_object_hide(GritsObject *object, gboolean hidden) +{ + GritsObjectClass *klass = GRITS_OBJECT_GET_CLASS(object); + object->hidden = hidden; + if (klass->hide) + klass->hide(object, hidden); +} + void grits_object_queue_draw(GritsObject *object) { if (object->viewer) gtk_widget_queue_draw(GTK_WIDGET(object->viewer)); } +void grits_object_set_cursor(GritsObject *object, GdkCursorType cursor) +{ + // Used by grits OpenGL + object->cursor = gdk_cursor_new(cursor); +} + +/* Event handling */ +void grits_object_pick(GritsObject *object, GritsOpenGL *opengl) +{ + grits_object_pickdraw(object, opengl, TRUE); +} + +gboolean grits_object_set_pointer(GritsObject *object, GdkEvent *event, gboolean selected) +{ + gboolean rval = FALSE; + if (selected) { + if (!object->state.selected) + g_signal_emit(object, signals[SIG_ENTER], 0, event, &rval); + object->state.selected = TRUE; + } else { + if (object->state.selected) + g_signal_emit(object, signals[SIG_LEAVE], 0, event, &rval); + object->state.selected = FALSE; + } + return rval; +} + +gboolean grits_object_event(GritsObject *object, GdkEvent *event) +{ + const int map[GDK_EVENT_LAST] = { + [GDK_BUTTON_PRESS ] SIG_BUTTON_PRESS, + [GDK_2BUTTON_PRESS ] SIG_BUTTON_PRESS, + [GDK_3BUTTON_PRESS ] SIG_BUTTON_PRESS, + [GDK_BUTTON_RELEASE] SIG_BUTTON_RELEASE, + [GDK_KEY_PRESS ] SIG_KEY_PRESS, + [GDK_KEY_RELEASE ] SIG_KEY_RELEASE, + [GDK_MOTION_NOTIFY ] SIG_MOTION, + }; + if (!object->state.selected) + return FALSE; + guint sig = map[event->type]; + gboolean rval = FALSE; + + /* Handle button click */ + if (sig == SIG_BUTTON_PRESS) + object->state.clicking = TRUE; + if (sig == SIG_BUTTON_RELEASE && object->state.clicking) + g_signal_emit(object, signals[SIG_CLICKED], 0, event, &rval); + if (sig == SIG_BUTTON_RELEASE || sig == SIG_MOTION) + object->state.clicking = FALSE; + + /* Emit this signal */ + if (rval == FALSE) { + if (!g_signal_has_handler_pending(object, signals[sig], 0, FALSE)) + return FALSE; + g_signal_emit(object, signals[sig], 0, event, &rval); + } + + if (rval == TRUE) + g_debug("GritsObject: breaking chained event"); + return rval; +} + /* GObject stuff */ G_DEFINE_ABSTRACT_TYPE(GritsObject, grits_object, G_TYPE_OBJECT); static void grits_object_init(GritsObject *object) @@ -138,4 +240,157 @@ static void grits_object_init(GritsObject *object) static void grits_object_class_init(GritsObjectClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + /** + * GritsObject::enter: + * @object: the object. + * + * The ::enter signal is emitted when the pointer moves over the object + */ + signals[SIG_ENTER] = g_signal_new( + "enter", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::leave: + * @object: the object. + * + * The ::leave signal is emitted when the pointer moves away from the + * object + */ + signals[SIG_LEAVE] = g_signal_new( + "leave", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::clicked: + * @object: the object. + * + * The ::clicked signal is emitted when the user clicks on the object + */ + signals[SIG_CLICKED] = g_signal_new( + "clicked", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::button-press: + * @object: the object. + * @event: the GdkEventButton which triggered this signal + * + * The ::button-press signal is emitted when a button (typically from a + * mouse) is pressed. + */ + signals[SIG_BUTTON_PRESS] = g_signal_new( + "button-press", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::button-release: + * @object: the object. + * @event: the GdkEventButton which triggered this signal + * + * The ::button-release signal is emitted when a button (typically from + * a mouse) is released. + */ + signals[SIG_BUTTON_RELEASE] = g_signal_new( + "button-release", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::key-press: + * @object: the object. + * @event: the GdkEventKey which triggered this signal + * + * The ::key-press signal is emitted when a key is pressed. + */ + signals[SIG_KEY_PRESS] = g_signal_new( + "key-press", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::key-release: + * @object: the object. + * @event: the GdkEventKey which triggered this signal + * + * The ::key-release signal is emitted when a key is released. + */ + signals[SIG_KEY_RELEASE] = g_signal_new( + "key-release", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); + + /** + * GritsViewer::motion: + * @object: the object. + * @event: the GdkEventMotion which triggered this signal + * + * The ::motion signal is emitted the pointer moves over the object + */ + signals[SIG_MOTION] = g_signal_new( + "motion", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + grits_cclosure_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, + G_TYPE_POINTER); }