]> Pileus Git - grits/blobdiff - src/objects/grits-object.c
Add mouse enter/leave signals to objects
[grits] / src / objects / grits-object.c
index 3cfd8026c6558d1ae172f1278ab4e7d25317a490..6abc4eb26f3ba70b3ff25a945f2af5918cd38d44 100644 (file)
 
 #include "grits-object.h"
 
-
-/**
- * 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)
+/* Constants */
+enum {
+       SIG_ENTER,
+       SIG_LEAVE,
+       NUM_SIGNALS,
+};
+static guint signals[NUM_SIGNALS];
+
+void grits_object_pickdraw(GritsObject *object, GritsOpenGL *opengl, gboolean pick)
 {
        GritsObjectClass *klass = GRITS_OBJECT_GET_CLASS(object);
        if (!klass->draw) {
@@ -111,7 +108,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,6 +121,21 @@ 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);
@@ -135,6 +150,41 @@ void grits_object_queue_draw(GritsObject *object)
                gtk_widget_queue_draw(GTK_WIDGET(object->viewer));
 }
 
+/* Event handling */
+void grits_object_pick_begin(GritsObject *object, GritsOpenGL *opengl)
+{
+       object->state.picked = FALSE;
+
+       /* Check for connected signals */
+       for (int i = 0; i < NUM_SIGNALS; i++) {
+               if (g_signal_has_handler_pending(object, signals[i], 0, FALSE)) {
+                       /* Someone is watching, render the object _once_ */
+                       glPushName((guint)object);
+                       grits_object_pickdraw(object, opengl, TRUE);
+                       glPopName();
+                       return;
+               }
+       }
+}
+
+void grits_object_pick_pointer(GritsObject *object, double x, double y)
+{
+       object->state.picked = TRUE;
+}
+
+void grits_object_pick_end(GritsObject *object)
+{
+       if (object->state.picked) {
+               if (!object->state.selected)
+                       g_signal_emit(object, signals[SIG_ENTER], 0);
+               object->state.selected = TRUE;
+       } else {
+               if (object->state.selected)
+                       g_signal_emit(object, signals[SIG_LEAVE], 0);
+               object->state.selected = FALSE;
+       }
+}
+
 /* GObject stuff */
 G_DEFINE_ABSTRACT_TYPE(GritsObject, grits_object, G_TYPE_OBJECT);
 static void grits_object_init(GritsObject *object)
@@ -146,4 +196,40 @@ 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,
+                       g_cclosure_marshal_VOID__VOID,
+                       G_TYPE_NONE,
+                       0);
+
+       /**
+        * 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,
+                       g_cclosure_marshal_VOID__VOID,
+                       G_TYPE_NONE,
+                       0);
 }