]> err.no Git - mapper/commitdiff
Compass Widget:
authorKaj-Michael Lang <milang@tal.org>
Tue, 6 May 2008 10:53:19 +0000 (13:53 +0300)
committerKaj-Michael Lang <milang@tal.org>
Tue, 6 May 2008 10:53:19 +0000 (13:53 +0300)
- Use a little cairo if available
- Fixes to timer handling
- Don't bother refreshing in mark set if nothing changed

src/gtkcompass.c

index 1e6e985eb1d92e379e1ad9cf9ac462b7668348b1..66fc1a30b2f3ad52dd9fa9119a9b5a4edcef6ec0 100644 (file)
 
 #include <glib/gstdio.h>
 #include <glib-object.h>
+#include "config.h"
 #include "gtkcompass.h"
 
+typedef struct _GtkCompassPriv GtkCompassPriv;
+struct _GtkCompassPriv { 
+       PangoContext *context;
+       PangoLayout *layout;
+       PangoFontDescription *fontdesc;
+       gint esid;
+#ifdef WITH_CAIRO
+       cairo_t *ct;
+#endif
+       gboolean dest_valid;
+       gboolean way_valid;
+       GdkGC *gc_h;
+       GdkGC *gc_w;
+       GdkGC *gc_d;
+};
+
+typedef enum {
+       CMARK_HEADING,
+       CMARK_WAYPOINT,
+       CMARK_DESTINATION,
+} GtkCompassMarkType;
+
 static void gtk_compass_finalize (GObject *object);
 static void gtk_compass_size_request (GtkWidget *widget, GtkRequisition *requisition);
 static void gtk_compass_size_allocate (GtkWidget *widget, GtkAllocation *allocate);
 static gboolean gtk_compass_expose (GtkWidget *widget, GdkEventExpose *event);
 static void gtk_compass_realize (GtkWidget *widget);
+
 static void gtk_compass_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
 static void gtk_compass_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
 static void gtk_compass_paint(GtkCompass *compass);
 static gboolean gtk_compass_refresh_cb(GtkWidget *widget);
-
+static void gtk_compass_draw_mark(GtkCompass *compass, GtkCompassMarkType mtype, gfloat angle, gint size);
 static gboolean gtk_compass_cb_button_press(GtkWidget *widget, GdkEventButton *event);
 
 G_DEFINE_TYPE(GtkCompass, gtk_compass, GTK_TYPE_WIDGET);
@@ -49,19 +74,11 @@ G_DEFINE_TYPE(GtkCompass, gtk_compass, GTK_TYPE_WIDGET);
                (x) = (b); \
 }
 
-typedef struct _GtkCompassPriv GtkCompassPriv;
-struct _GtkCompassPriv
-{ 
-PangoContext *context;
-PangoLayout *layout;
-PangoFontDescription *fontdesc;
-gint esid;
-gboolean dest_valid;
-gboolean way_valid;
-GdkGC *gc_h;
-GdkGC *gc_w;
-GdkGC *gc_d;
-};
+#ifdef WITH_CAIRO
+#define MARK_COLOR_HEADING 0,0,0
+#define MARK_COLOR_WAYPOINT 0,0.9,0
+#define MARK_COLOR_DESTINATION 0.9,0,0.9
+#endif
 
 #define GTK_COMPASS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_COMPASS_TYPE, GtkCompassPriv))
 
@@ -158,7 +175,13 @@ g_return_if_fail(GTK_IS_COMPASS(object));
 compass=GTK_COMPASS(object);
 priv=GTK_COMPASS_GET_PRIVATE(compass);
 
-g_source_remove(priv->esid);
+#ifdef WITH_CAIRO
+if (priv->ct)
+       cairo_destroy(priv->ct);
+#endif
+
+if (priv->esid!=0)
+       g_source_remove(priv->esid);
 
 if (GTK_WIDGET(object)->parent && GTK_WIDGET_MAPPED(object)) {
        gtk_widget_unmap(GTK_WIDGET(object));
@@ -276,20 +299,54 @@ gdk_gc_set_line_attributes(priv->gc_w, 6, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOI
 }
 
 static void
-gtk_compass_draw_mark(GtkCompass *compass, GdkGC *gc, gfloat angle, gint size)
+gtk_compass_draw_mark(GtkCompass *compass, GtkCompassMarkType mtype, gfloat angle, gint size)
 {
 GtkWidget *widget;
+GtkCompassPriv *priv;
 gint hs;
+GdkGC *gc;
 
 widget=GTK_WIDGET(compass);
+priv=GTK_COMPASS_GET_PRIVATE(compass);
 
 hs=compass->size/2;
 
+#ifdef WITH_CAIRO
+g_return_if_fail(priv->ct);
+switch (mtype) {
+       case CMARK_DESTINATION:
+               cairo_set_source_rgb(priv->ct, MARK_COLOR_DESTINATION);
+       break;
+       case CMARK_WAYPOINT:
+               cairo_set_source_rgb(priv->ct, MARK_COLOR_WAYPOINT);
+       break;
+       case CMARK_HEADING:
+       default:
+               cairo_set_source_rgb(priv->ct, MARK_COLOR_HEADING);
+       break;
+}
+cairo_move_to(priv->ct, compass->xoffset+hs+((hs-size)*sinf(angle)), compass->yoffset+compass->size-((hs-size)*cosf(angle)));
+cairo_line_to(priv->ct,        compass->xoffset+hs+((hs+size)*sinf(angle)), compass->yoffset+compass->size-((hs+size)*cosf(angle)));
+cairo_stroke(priv->ct);
+#else
+switch (mtype) {
+       case CMARK_DESTINATION:
+               gc=priv->gc_d;
+       break;
+       case CMARK_WAYPOINT:
+               gc=priv->gc_w;
+       break;
+       case CMARK_HEADING:
+       default:
+               gc=priv->gc_h;
+       break;
+}
 gdk_draw_line(widget->window,gc,
        compass->xoffset+hs+((hs-size)*sinf(angle)),
        compass->yoffset+compass->size-((hs-size)*cosf(angle)),
        compass->xoffset+hs+((hs+size)*sinf(angle)),
        compass->yoffset+compass->size-((hs+size)*cosf(angle)));
+#endif
 }
 
 static void
@@ -327,37 +384,38 @@ pango_layout_set_font_description(priv->layout, priv->fontdesc);
 pango_layout_set_text(priv->layout, htext, -1);
 pango_layout_get_pixel_size(priv->layout, &x, &y);
 
-gdk_draw_layout(widget->window,
-       priv->gc_h,
+#ifdef WITH_CAIRO
+cairo_set_source_rgb(priv->ct, 0, 0, 0);
+cairo_arc(priv->ct, compass->xoffset+hsize, compass->yoffset+size, hsize+fs, M_PI, 2 * M_PI);
+cairo_set_source_rgb(priv->ct, 1, 1, 1);
+cairo_fill_preserve(priv->ct);
+cairo_set_source_rgb(priv->ct, 0, 0, 0);
+cairo_stroke(priv->ct);
+#else
+gdk_draw_arc(widget->window, priv->gc_h, FALSE, compass->xoffset, compass->yoffset+hsize, size - fs, size - fs, 0, 64 * 360);
+#endif
+
+gdk_draw_layout(widget->window,        priv->gc_h,
        compass->xoffset+hsize-x/2,
        compass->yoffset+size-y-2, priv->layout);
 
-gdk_draw_arc(widget->window,
-       priv->gc_h,
-       FALSE,
-       compass->xoffset, compass->yoffset+hsize, size - fs, size - fs, 0, 64 * 360);
-
 /* Simple arrow for heading */
-gdk_draw_line(widget->window,
-       priv->gc_h,
+gdk_draw_line(widget->window, priv->gc_h,
        compass->xoffset + hsize + 3,
        compass->yoffset + size - y - 5,
        compass->xoffset + hsize, compass->yoffset + hsize + 5);
 
-gdk_draw_line(widget->window,
-       priv->gc_h,
+gdk_draw_line(widget->window, priv->gc_h,
        compass->xoffset + hsize - 3,
        compass->yoffset + size - y - 5,
        compass->xoffset + hsize, compass->yoffset + hsize + 5);
 
-gdk_draw_line(widget->window,
-       priv->gc_h,
+gdk_draw_line(widget->window, priv->gc_h,
        compass->xoffset + hsize - 3,
        compass->yoffset + size - y - 5,
        compass->xoffset + hsize, compass->yoffset + size - y - 8);
 
-gdk_draw_line(widget->window,
-       priv->gc_h,
+gdk_draw_line(widget->window, priv->gc_h,
        compass->xoffset + hsize + 3,
        compass->yoffset + size - y - 5,
        compass->xoffset + hsize, compass->yoffset + size - y - 8);
@@ -402,7 +460,7 @@ for (i = 0; i < 5; i++) {
 
        tmp = ((dir - compass->heading) * (1.f / 180.f)) * G_PI;
 
-       gtk_compass_draw_mark(compass, priv->gc_h, tmp, 6);
+       gtk_compass_draw_mark(compass, CMARK_HEADING, tmp, 8);
 
        x = fsize[i];
        if (abs((guint) (compass->heading / 45) * 45 - compass->heading)
@@ -422,12 +480,12 @@ for (i = 0; i < 5; i++) {
 
 if (priv->dest_valid) {
        tmp=((compass->dest_heading-compass->heading) * (1.f / 180.f)) * G_PI;
-       gtk_compass_draw_mark(compass, priv->gc_d, tmp, 10);
+       gtk_compass_draw_mark(compass, CMARK_DESTINATION, tmp, 10);
 }
 
 if (priv->way_valid) {
        tmp=((compass->way_heading-compass->heading) * (1.f / 180.f)) * G_PI;
-       gtk_compass_draw_mark(compass, priv->gc_w, tmp, 10);
+       gtk_compass_draw_mark(compass, CMARK_WAYPOINT, tmp, 10);
 }
 
 return;
@@ -444,10 +502,17 @@ g_return_val_if_fail(event != NULL, FALSE);
 
 compass=GTK_COMPASS(widget);
 priv=GTK_COMPASS_GET_PRIVATE(compass);
-if (priv->esid==0) {
-       priv->esid=g_timeout_add(300,(GSourceFunc)gtk_compass_refresh_cb, compass);
-}
+#ifdef WITH_CAIRO
+priv->ct=gdk_cairo_create(widget->window);
+#endif
 gtk_compass_paint(compass);
+
+if (priv->esid==0)
+       priv->esid=g_timeout_add(300,(GSourceFunc)gtk_compass_refresh_cb, compass);
+#ifdef WITH_CAIRO
+cairo_destroy(priv->ct);
+priv->ct=NULL;
+#endif
 return TRUE;
 }
 
@@ -489,7 +554,7 @@ if (tmp>5) {
        compass->heading=compass->data->heading;
 }
 
-gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);
+gtk_widget_queue_draw(widget);
 return TRUE;
 }
 
@@ -497,7 +562,7 @@ void
 gtk_compass_refresh(GtkWidget *widget)
 {
 g_return_if_fail(GTK_IS_COMPASS(widget));
-gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);
+gtk_widget_queue_draw(widget);
 }
 
 void 
@@ -511,10 +576,11 @@ g_return_if_fail(GTK_IS_COMPASS(widget));
 compass=GTK_COMPASS(widget);
 priv=GTK_COMPASS_GET_PRIVATE(compass);
 
-priv->way_valid=valid;
-compass->way_heading=heading;
-
-gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);
+if (priv->way_valid!=valid || compass->way_heading!=heading) {
+       priv->way_valid=valid;
+       compass->way_heading=heading;
+       gtk_widget_queue_draw(widget);
+}
 }
 
 void 
@@ -528,8 +594,9 @@ g_return_if_fail(GTK_IS_COMPASS(widget));
 compass=GTK_COMPASS(widget);
 priv=GTK_COMPASS_GET_PRIVATE(compass);
 
-priv->dest_valid=valid;
-compass->dest_heading=heading;
-
-gtk_widget_queue_draw_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);
+if (priv->dest_valid!=valid || compass->dest_heading!=heading) {
+       priv->dest_valid=valid;
+       compass->dest_heading=heading;
+       gtk_widget_queue_draw(widget);
+}
 }