#include <glib-object.h>
#include "gtkcompass.h"
+#if 0
+#define DEBUG
+#endif
+
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 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);
G_DEFINE_TYPE(GtkCompass, gtk_compass, GTK_TYPE_WIDGET);
#define BOUND(x, a, b) { \
- if((x) < (a)) \
- (x) = (a); \
- else if((x) > (b)) \
- (x) = (b); \
+ if((x) < (a)) \
+ (x) = (a); \
+ else if((x) > (b)) \
+ (x) = (b); \
}
+typedef struct _GtkCompassPriv GtkCompassPriv;
+
+struct _GtkCompassPriv
+{
+PangoContext *context;
+PangoLayout *layout;
+PangoFontDescription *fontdesc;
+};
+
+#define GTK_COMPASS_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_COMPASS, GtkCompassPriv))
+
static void
gtk_compass_class_init (GtkCompassClass *class)
{
widget_class->expose_event = gtk_compass_expose;
widget_class->realize = gtk_compass_realize;
widget_class->size_allocate = gtk_compass_size_allocate;
+
+g_type_class_add_private (object_class, sizeof (GtkCompassPriv));
}
static void
}
static void
-gtk_compass_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+gtk_compass_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
GtkCompass *compass;
g_return_if_fail(GTK_IS_COMPASS(object));
compass=GTK_COMPASS(object);
switch (prop_id) {
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
-gtk_compass_init (GtkCompass *compass)
+gtk_compass_init(GtkCompass *compass)
{
-g_printf("%s()\n", __PRETTY_FUNCTION__);
-
compass->gc_h=NULL;
compass->gc_d=NULL;
compass->gc_w=NULL;
compass->way_valid=FALSE;
compass->width=300;
compass->height=300;
+compass->esid=0;
}
static gboolean
-gtk_compass_cb_button_press(GtkWidget * widget, GdkEventButton * event)
+gtk_compass_cb_button_press(GtkWidget *widget, GdkEventButton *event)
{
GtkCompass *compass;
compass=GTK_COMPASS(widget);
+#ifdef DEBUG
+compass->data->heading=0;
+compass->heading=180;
+#endif
+
return FALSE;
}
compass=gtk_type_new(gtk_compass_get_type ());
widget=GTK_WIDGET(compass);
compass->data=data;
+compass->heading=0;
g_signal_connect(G_OBJECT(widget), "button_press_event", G_CALLBACK(gtk_compass_cb_button_press), NULL);
+
+compass->esid=g_timeout_add(1000,(GSourceFunc)gtk_compass_refresh_cb, compass);
+
return widget;
}
gtk_compass_finalize(GObject *object)
{
GtkCompass *compass;
-
-g_printf("%s()\n", __PRETTY_FUNCTION__);
g_return_if_fail(GTK_IS_COMPASS(object));
compass=GTK_COMPASS(object);
+g_source_remove(compass->esid);
if (GTK_WIDGET(object)->parent && GTK_WIDGET_MAPPED(object)) {
gtk_widget_unmap(GTK_WIDGET(object));
gtk_compass_size_request(GtkWidget *widget, GtkRequisition *requisition)
{
GtkCompass *compass;
-
-g_printf("%s()\n", __PRETTY_FUNCTION__);
g_return_if_fail(GTK_IS_COMPASS(widget));
g_return_if_fail(requisition != NULL);
-compass = GTK_COMPASS (widget);
+compass=GTK_COMPASS(widget);
requisition->width=400;
requisition->height=300;
{
GtkCompass *compass;
-g_printf("%s()\n", __PRETTY_FUNCTION__);
-
g_return_if_fail(GTK_IS_COMPASS(widget));
g_return_if_fail(allocation!=NULL);
GdkWindowAttr attributes;
gint attributes_mask;
-g_printf("%s()\n", __PRETTY_FUNCTION__);
-
g_return_if_fail (GTK_IS_COMPASS(widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
compass=GTK_COMPASS(widget);
color.blue=0x0000;
compass->gc_h=gdk_gc_new(widget->window);
gdk_gc_set_rgb_fg_color(compass->gc_h, &color);
- gdk_gc_set_line_attributes(compass->gc_h, 6, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+ gdk_gc_set_line_attributes(compass->gc_h, 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
}
if (!compass->gc_d) {
}
static void
-gtk_compass_draw_mark(GtkCompass *compass, GdkGC *gc, gdouble t)
+gtk_compass_draw_mark(GtkCompass *compass, GdkGC *gc, gfloat angle, gint size)
{
GtkWidget *widget;
gint hs;
hs=compass->size/2;
gdk_draw_line(widget->window,gc,
- compass->xoffset+hs+((hs-5)*sin(t)),
- compass->yoffset+compass->size-((hs-5)*cos(t)),
- compass->xoffset+hs+((hs+5)*sin(t)),
- compass->yoffset+compass->size-((hs+5)*cos(t)));
+ 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)));
}
static void
gtk_compass_paint(GtkCompass *compass)
{
GtkWidget *widget;
-guint i, x, y, size, hsize;
+guint i, x, y, size, hsize, fs;
gint dir;
gfloat tmp;
gchar *text;
widget=GTK_WIDGET(compass);
size=compass->size;
+#if 1
hsize=size/2;
+#else
+hsize=0;
+#endif
+
+fs=size/41;
+BOUND(fs, 1, 16);
pango_context_set_matrix (compass->context, NULL);
g_snprintf(htext, 8, "%3.0f°", compass->data->heading);
+pango_font_description_set_size(compass->fontdesc, (10+fs) * PANGO_SCALE);
+pango_layout_set_font_description(compass->layout, compass->fontdesc);
pango_layout_set_text(compass->layout, htext, -1);
pango_layout_get_pixel_size(compass->layout, &x, &y);
-gtk_paint_flat_box (widget->style,
- widget->window,
- GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- NULL, widget, "trough", 0, 0,
- compass->width, compass->height);
-
gdk_draw_layout(widget->window,
- widget->style->fg_gc[GTK_STATE_NORMAL],
- compass->xoffset+size/2-x/2,
+ compass->gc_h,
+ compass->xoffset+hsize-x/2,
compass->yoffset+size-y-2, compass->layout);
gdk_draw_arc(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ compass->gc_h,
FALSE,
- compass->xoffset, compass->yoffset+size/2, size, size, 0, 64 * 180);
+ compass->xoffset, compass->yoffset+hsize, size - fs, size - fs, 0, 64 * 360);
/* Simple arrow for heading */
gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- compass->xoffset + size / 2 + 3,
+ compass->gc_h,
+ compass->xoffset + hsize + 3,
compass->yoffset + size - y - 5,
- compass->xoffset + size / 2, compass->yoffset + size / 2 + 5);
+ compass->xoffset + hsize, compass->yoffset + hsize + 5);
gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- compass->xoffset + size / 2 - 3,
+ compass->gc_h,
+ compass->xoffset + hsize - 3,
compass->yoffset + size - y - 5,
- compass->xoffset + size / 2, compass->yoffset + size / 2 + 5);
+ compass->xoffset + hsize, compass->yoffset + hsize + 5);
gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- compass->xoffset + size / 2 - 3,
+ compass->gc_h,
+ compass->xoffset + hsize - 3,
compass->yoffset + size - y - 5,
- compass->xoffset + size / 2, compass->yoffset + size - y - 8);
+ compass->xoffset + hsize, compass->yoffset + size - y - 8);
gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- compass->xoffset + size / 2 + 3,
+ compass->gc_h,
+ compass->xoffset + hsize + 3,
compass->yoffset + size - y - 5,
- compass->xoffset + size / 2, compass->yoffset + size - y - 8);
+ compass->xoffset + hsize, compass->yoffset + size - y - 8);
for (i = 0; i < 5; i++) {
PangoMatrix matrix = PANGO_MATRIX_INIT;
- dir = (gint) (compass->data->heading / 45) * 45 + angle[i];
+ dir = (gint) (compass->heading / 45) * 45 + angle[i];
switch (dir) {
case 0:
break;
}
- tmp = ((dir - compass->data->heading) * (1.f / 180.f)) * G_PI;
- gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- compass->xoffset + size / 2 + ((size / 2 - 5) * sinf(tmp)),
- compass->yoffset + size - ((size / 2 - 5) * cosf(tmp)),
- compass->xoffset + size / 2 + ((size / 2 + 5) * sinf(tmp)),
- compass->yoffset + size - ((size / 2 + 5) * cosf(tmp)));
+ tmp = ((dir - compass->heading) * (1.f / 180.f)) * G_PI;
+
+ gtk_compass_draw_mark(compass, compass->gc_h, tmp, 6);
x = fsize[i];
- if (abs((guint) (compass->data->heading / 45) * 45 - compass->data->heading)
- > abs((guint) (compass->data->heading / 45) * 45 + 45 - compass->data->heading) && (i > 0))
+ if (abs((guint) (compass->heading / 45) * 45 - compass->heading)
+ > abs((guint) (compass->heading / 45) * 45 + 45 - compass->heading) && (i > 0))
x = fsize[i - 1];
- pango_matrix_rotate (&matrix, dir);
- pango_context_set_matrix (compass->context, &matrix);
-
- pango_font_description_set_size(compass->fontdesc, (10 + x) * PANGO_SCALE);
+ pango_font_description_set_size(compass->fontdesc, (10 + x + fs) * PANGO_SCALE);
pango_layout_set_font_description(compass->layout, compass->fontdesc);
pango_layout_set_text(compass->layout, text, -1);
+ pango_matrix_rotate (&matrix, -(dir-compass->heading));
+ pango_context_set_matrix (compass->context, &matrix);
pango_layout_get_pixel_size(compass->layout, &x, &y);
- x = compass->xoffset + size / 2 + ((size / 2 + 15) * sinf(tmp)) - x / 2,
- y = compass->yoffset + size - ((size / 2 + 15) * cosf(tmp)) - y / 2,
- gdk_draw_layout(widget->window,
- widget->style->fg_gc[GTK_STATE_NORMAL],
- x, y, compass->layout);
-
- if (compass->dest_valid) {
- gtk_compass_draw_mark(compass, compass->gc_d, compass->dest_heading);
- }
+ x = compass->xoffset + hsize + ((hsize + 15 + fs) * sinf(tmp)) - x / 2,
+ y = compass->yoffset + size - ((hsize + 15 + fs) * cosf(tmp)) - y / 2,
+ gdk_draw_layout(widget->window, compass->gc_h, x, y, compass->layout);
+}
- if (compass->way_valid) {
- gtk_compass_draw_mark(compass, compass->gc_w, compass->way_heading);
- }
+if (compass->dest_valid) {
+ tmp=((compass->dest_heading-compass->heading) * (1.f / 180.f)) * G_PI;
+ gtk_compass_draw_mark(compass, compass->gc_d, tmp, 10);
}
-return TRUE;
+if (compass->way_valid) {
+ tmp=((compass->way_heading-compass->heading) * (1.f / 180.f)) * G_PI;
+ gtk_compass_draw_mark(compass, compass->gc_w, tmp, 10);
}
+return;
+}
static gboolean
gtk_compass_expose(GtkWidget *widget, GdkEventExpose *event)
{
GtkCompass *compass;
+
g_return_val_if_fail(GTK_IS_COMPASS(widget), FALSE);
g_return_val_if_fail(event != NULL, FALSE);
return TRUE;
}
+static gboolean
+gtk_compass_refresh_cb(GtkWidget *widget)
+{
+GtkCompass *compass;
+gfloat tmp;
+
+g_return_val_if_fail(GTK_IS_COMPASS(widget), FALSE);
+
+compass=GTK_COMPASS(widget);
+
+if ((GTK_WIDGET_MAPPED(widget)==FALSE) || (GTK_WIDGET_VISIBLE(widget)==FALSE)) {
+ compass->heading=compass->data->heading;
+ return TRUE;
+}
+
+if (compass->heading==compass->data->heading)
+ return TRUE;
+
+tmp=fabsf(compass->heading-compass->data->heading);
+if (tmp>5)
+ tmp=tmp/2.2;
+else
+ compass->heading=compass->data->heading;
+
+if (compass->heading<compass->data->heading)
+ compass->heading+=tmp;
+
+if (compass->heading>compass->data->heading)
+ compass->heading-=tmp;
+
+#ifdef DEBUG
+g_printf("%.2f %.2f\n", compass->heading, compass->data->heading);
+#endif
+
+gtk_widget_queue_draw_area(widget, 0, 0, compass->width, compass->height);
+return TRUE;
+}
+
void
gtk_compass_refresh(GtkWidget *widget)
{
GtkCompass *compass;
-g_printf("%s()\n", __PRETTY_FUNCTION__);
g_return_if_fail(GTK_IS_COMPASS(widget));
compass=GTK_COMPASS(widget);
-gtk_compass_paint(compass);
+gtk_widget_queue_draw_area(widget, 0, 0, compass->width, compass->height);
+}
-g_printf("%s(): return\n", __PRETTY_FUNCTION__);
+void
+gtk_compass_set_way_heading(GtkWidget *widget, gboolean valid, gfloat heading)
+{
+GtkCompass *compass;
+g_return_if_fail(GTK_IS_COMPASS(widget));
+
+compass=GTK_COMPASS(widget);
+
+compass->way_valid=valid;
+compass->way_heading=heading;
+
+gtk_widget_queue_draw_area(widget, 0, 0, compass->width, compass->height);
+}
+
+void
+gtk_compass_set_dest_heading(GtkWidget *widget, gboolean valid, gfloat heading)
+{
+GtkCompass *compass;
+g_return_if_fail(GTK_IS_COMPASS(widget));
+
+compass=GTK_COMPASS(widget);
+
+compass->dest_valid=valid;
+compass->dest_heading=heading;
+
+compass=GTK_COMPASS(widget);
+gtk_widget_queue_draw_area(widget, 0, 0, compass->width, compass->height);
}
+