From: Kaj-Michael Lang Date: Tue, 6 May 2008 10:53:19 +0000 (+0300) Subject: Compass Widget: X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=229e0c6e06ffbd0fbf86d6953c40e0e4873154ac;p=mapper Compass Widget: - Use a little cairo if available - Fixes to timer handling - Don't bother refreshing in mark set if nothing changed --- diff --git a/src/gtkcompass.c b/src/gtkcompass.c index 1e6e985..66fc1a3 100644 --- a/src/gtkcompass.c +++ b/src/gtkcompass.c @@ -26,18 +26,43 @@ #include #include +#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); +} }