#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);
(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))
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));
}
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
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);
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)
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;
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;
}
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;
}
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
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
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);
+}
}