]> err.no Git - mapper/commitdiff
Start to make proper gtk widgets of the gps info displays.
authorKaj-Michael Lang <milang@onion.tal.org>
Wed, 26 Sep 2007 12:11:53 +0000 (15:11 +0300)
committerKaj-Michael Lang <milang@onion.tal.org>
Wed, 26 Sep 2007 12:11:53 +0000 (15:11 +0300)
src/gtkgps.c [new file with mode: 0644]
src/gtkgps.h [new file with mode: 0644]

diff --git a/src/gtkgps.c b/src/gtkgps.c
new file mode 100644 (file)
index 0000000..4f20b3d
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ *
+ * GtkGps: Display GPS information
+ * Copyright (C) 2007 Kaj-Michael Lang
+ * Originanl non-widget version Copyright Cezary Jackiewicz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <math.h>
+
+#include <glib/gstdio.h>
+#include <glib-object.h>
+#include "gtkgps.h"
+
+static void gtk_gps_finalize (GObject *object);
+static void gtk_gps_size_request (GtkWidget *widget, GtkRequisition *requisition);
+static void gtk_gps_size_allocate (GtkWidget *widget, GtkAllocation *allocate);
+static gint gtk_gps_expose (GtkWidget *widget, GdkEventExpose *event);
+static void gtk_gps_realize (GtkWidget *widget);
+static void gtk_gps_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void gtk_gps_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static gint gtk_gps_paint(GtkGps *gps);
+
+G_DEFINE_TYPE(GtkGps, gtk_gps, GTK_TYPE_WIDGET);
+
+#define PADDING (15)
+
+#define BOUND(x, a, b) { \
+    if((x) < (a)) \
+        (x) = (a); \
+    else if((x) > (b)) \
+        (x) = (b); \
+}
+
+static void
+gtk_gps_class_init (GtkGpsClass *class)
+{
+GObjectClass *object_class;
+GtkWidgetClass *widget_class;
+       
+object_class = (GObjectClass*) class;
+widget_class = (GtkWidgetClass*) class;
+       
+object_class->finalize = gtk_gps_finalize;
+object_class->set_property = gtk_gps_set_property;
+object_class->get_property = gtk_gps_get_property;
+       
+widget_class->size_request = gtk_gps_size_request;
+widget_class->expose_event = gtk_gps_expose;
+widget_class->realize = gtk_gps_realize;
+widget_class->size_allocate = gtk_gps_size_allocate;
+}
+
+static void
+gtk_gps_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+GtkGps *gps;
+g_return_if_fail(GTK_IS_GPS(object));
+gps=GTK_GPS(object);
+switch (prop_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+}
+}
+
+static void
+gtk_gps_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec   *pspec)
+{
+GtkGps *gps;
+g_return_if_fail(GTK_IS_GPS(object));
+gps=GTK_GPS(object);
+switch (prop_id) {
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+}
+}
+
+static void
+gtk_gps_init (GtkGps *gps)
+{
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+
+gps->satinview=0;
+gps->satinuse=0;
+gps->gc1=NULL;
+gps->gc2=NULL;
+gps->gc3=NULL;
+gps->width=400;
+gps->height=300;
+}
+
+GtkWidget*
+gtk_gps_new(void)
+{
+GtkGps *gps;
+gps = gtk_type_new(gtk_gps_get_type ());
+return GTK_WIDGET(gps);
+}
+
+static void
+gtk_gps_finalize(GObject *object)
+{
+GtkGps *gps;
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+       
+g_return_if_fail(GTK_IS_GPS(object));
+gps=GTK_GPS(object);
+
+if (GTK_WIDGET(object)->parent && GTK_WIDGET_MAPPED(object)) {
+       gtk_widget_unmap(GTK_WIDGET(object));
+}
+
+G_OBJECT_CLASS(gtk_gps_parent_class)->finalize(object);
+}
+
+static void
+gtk_gps_size_request(GtkWidget *widget, GtkRequisition *requisition)
+{
+GtkGps *gps;
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+       
+g_return_if_fail(GTK_IS_GPS(widget));
+g_return_if_fail(requisition != NULL);
+       
+gps = GTK_GPS (widget);
+       
+requisition->width=400;
+requisition->height=300;
+gps->width=400 - 10;
+gps->height=300 - 10;
+}
+
+static void
+gtk_gps_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+GtkGps *gps;
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+
+g_return_if_fail(GTK_IS_GPS(widget));
+g_return_if_fail(allocation!=NULL);
+
+gps=GTK_GPS (widget);
+
+widget->allocation = *allocation;
+
+if (GTK_WIDGET_REALIZED (widget)) {
+       gdk_window_move_resize (widget->window,
+               allocation->x, allocation->y,
+               allocation->width, allocation->height);
+}
+
+gps->width=allocation->width-PADDING;
+gps->height=allocation->height-PADDING;
+}
+
+static void 
+gtk_gps_realize (GtkWidget *widget)
+{
+GtkGps *gps;
+GdkColor color;
+GdkWindowAttr attributes;
+gint attributes_mask;
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+
+g_return_if_fail (GTK_IS_GPS(widget));
+GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+gps=GTK_GPS(widget);
+
+attributes.x=widget->allocation.x;
+attributes.y=widget->allocation.y;
+attributes.width=widget->allocation.width;
+attributes.height=widget->allocation.height;
+attributes.wclass=GDK_INPUT_OUTPUT;
+attributes.window_type=GDK_WINDOW_CHILD;
+attributes.event_mask=gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK ;
+attributes.visual=gtk_widget_get_visual(widget);
+attributes.colormap=gtk_widget_get_colormap(widget);
+
+attributes_mask=GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+widget->window=gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask);
+widget->style=gtk_style_attach(widget->style, widget->window);
+
+gdk_window_set_user_data(widget->window, widget);
+gtk_style_set_background(widget->style, widget->window, GTK_STATE_ACTIVE);
+
+gps->sat_details_context=gtk_widget_get_pango_context(widget);
+gps->sat_details_layout=pango_layout_new(gps->sat_details_context);
+gps->sat_details_fontdesc=pango_font_description_new();
+pango_font_description_set_family(gps->sat_details_fontdesc, "Sans Serif");
+pango_font_description_set_size(gps->sat_details_fontdesc, 12*PANGO_SCALE);
+pango_layout_set_font_description(gps->sat_details_layout, gps->sat_details_fontdesc);
+pango_layout_set_alignment(gps->sat_details_layout, PANGO_ALIGN_CENTER);
+
+if (!gps->gc1) {
+       color.red=0;
+       color.green=0;
+       color.blue=0;
+       gps->gc1=gdk_gc_new(widget->window);
+       gdk_gc_set_rgb_fg_color(gps->gc1, &color);
+}
+
+if (!gps->gc2) {
+       color.red=0;
+       color.green=0;
+       color.blue=0xffff;
+       gps->gc2=gdk_gc_new(widget->window);
+       gdk_gc_set_rgb_fg_color(gps->gc2, &color);
+}
+
+if (!gps->gc3) {
+       color.red=0xffff;
+       color.green=0xffff;
+       color.blue=0xffff;
+       gps->gc3=gdk_gc_new(widget->window);
+       gdk_gc_set_rgb_fg_color(gps->gc3, &color);
+}
+}
+
+static gint
+gtk_gps_paint(GtkGps *gps)
+{
+GdkGC *gc;
+GtkWidget *widget;
+guint i, j, x, y, size, halfsize, xoffset, yoffset;
+guint x1, y1, x0, y0;
+gfloat tmp;
+gchar buffer[16];
+guint line[12]={0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330};
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+
+widget=GTK_WIDGET(gps);
+
+if (!GTK_WIDGET_MAPPED(widget))
+       return TRUE;
+
+x0=0;
+y0=0;
+
+size=MIN(gps->width, gps->height);
+halfsize=size/2;
+if (gps->width>gps->height) {
+       xoffset=x0+(gps->width-gps->height-PADDING)/2;
+       yoffset=y0+5;
+} else {
+       xoffset=x0+5;
+       yoffset=y0+(gps->height-gps->width-PADDING)/2;
+}
+
+/* 90 */
+gdk_draw_arc(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+            FALSE,
+            xoffset + 2, yoffset + 2, size - 4, size - 4, 0, 64 * 360);
+
+/* 60 */
+gdk_draw_arc(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+            FALSE,
+            xoffset + size / 6, yoffset + size / 6,
+            size / 6 * 4, size / 6 * 4, 0, 64 * 360);
+
+/* 30 */
+gdk_draw_arc(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+            FALSE,
+            xoffset + size / 6 * 2, yoffset + size / 6 * 2,
+            size / 6 * 2, size / 6 * 2, 0, 64 * 360);
+
+for (i = 0; i < 6; i++) {
+       /* line */
+       tmp = (line[i] * (1.f / 180.f)) * G_PI;
+       gdk_draw_line(widget->window,
+                     widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+                     xoffset + halfsize + (halfsize - 2) * sinf(tmp),
+                     yoffset + halfsize - (halfsize - 2) * cosf(tmp),
+                     xoffset + halfsize - (halfsize - 2) * sinf(tmp),
+                     yoffset + halfsize + (halfsize - 2) * cosf(tmp));
+}
+
+for (i = 0; i < 12; i++) {
+       tmp = (line[i] * (1.f / 180.f)) * G_PI;
+       /* azimuth */
+       if (line[i] == 0)
+               g_snprintf(buffer, 16, "N");
+       else
+               g_snprintf(buffer, 16, "%d°", line[i]);
+       pango_layout_set_text(gps->sat_details_layout, buffer, -1);
+       pango_layout_get_pixel_size(gps->sat_details_layout, &x, &y);
+       gdk_draw_layout(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
+                       (xoffset + halfsize + (halfsize - size / 12) * sinf(tmp)) - x / 2,
+                       (yoffset + halfsize - (halfsize - size / 12) * cosf(tmp)) - y / 2,
+                       gps->sat_details_layout);
+}
+
+/* elevation 30 */
+tmp = (30 * (1.f / 180.f)) * G_PI;
+g_snprintf(buffer, 16, "30°");
+pango_layout_set_text(gps->sat_details_layout, buffer, -1);
+pango_layout_get_pixel_size(gps->sat_details_layout, &x, &y);
+gdk_draw_layout(widget->window,        widget->style->fg_gc[GTK_STATE_NORMAL],
+               (xoffset + halfsize + size / 6 * 2 * sinf(tmp)) - x / 2,
+               (yoffset + halfsize - size / 6 * 2 * cosf(tmp)) - y / 2,
+               gps->sat_details_layout);
+
+/* elevation 60 */
+tmp = (30 * (1.f / 180.f)) * G_PI;
+g_snprintf(buffer, 16, "60°");
+pango_layout_set_text(gps->sat_details_layout, buffer, -1);
+pango_layout_get_pixel_size(gps->sat_details_layout, &x, &y);
+gdk_draw_layout(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
+               (xoffset + halfsize + size / 6 * sinf(tmp)) - x / 2,
+               (yoffset + halfsize - size / 6 * cosf(tmp)) - y / 2, 
+               gps->sat_details_layout);
+
+for (i=0;i<gps->satinview;i++) {
+       /* Sat used or not */
+       gc=gps->gc1;
+       for (j=0;j<gps->satinuse;j++) {
+               if (gps->satforfix[j]==gps->gps_sat[i].prn) {
+                       gc=gps->gc2;
+                       break;
+               }
+       }
+
+       tmp = (gps->gps_sat[i].azimuth * (1.f / 180.f)) * G_PI;
+       x = xoffset + halfsize + (90 - gps->gps_sat[i].elevation) * halfsize / 90 * sinf(tmp);
+       y = yoffset + halfsize - (90 - gps->gps_sat[i].elevation) * halfsize / 90 * cosf(tmp);
+
+       gdk_draw_arc(widget->window, gc, TRUE, x - 10, y - 10, 20, 20, 0, 64 * 360);
+
+       g_snprintf(buffer, 6, "%02d", gps->gps_sat[i].prn);
+       pango_layout_set_text(gps->sat_details_layout, buffer, -1);
+       pango_layout_get_pixel_size(gps->sat_details_layout, &x1, &y1);
+       gdk_draw_layout(widget->window, gps->gc3, x - x1 / 2, y - y1 / 2, gps->sat_details_layout);
+}
+
+g_printf("%s(): return\n", __PRETTY_FUNCTION__);
+return TRUE;
+}
+
+static gint
+gtk_gps_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+g_return_val_if_fail(GTK_IS_GPS(widget), FALSE);
+g_return_val_if_fail(event != NULL, FALSE);
+
+gtk_gps_paint(GTK_GPS(widget));
+return TRUE;
+}
+
+void 
+gtk_gps_set_satellite_data(GtkWidget *widget, guint sat, gboolean fix, guint prn, guint elevation, guint azimuth, guint snr)
+{
+GtkGps *gps;
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+g_return_if_fail(GTK_IS_GPS (widget));
+
+gps=GTK_GPS(widget);
+
+if (sat>12)
+       sat=12;
+
+BOUND(elevation, 0, 90);
+BOUND(azimuth, 0, 360);
+BOUND(snr, 0, 99);
+gps->gps_sat[sat].prn=prn;
+gps->gps_sat[sat].elevation=elevation;
+gps->gps_sat[sat].azimuth=azimuth;
+gps->gps_sat[sat].snr=snr;
+if (fix)
+       gps->satforfix[sat]=prn;
+else
+       gps->satforfix[sat]=-1;
+g_printf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+void
+gtk_gps_set_satellite_in_view(GtkWidget *widget, guint sat)
+{
+GtkGps *gps;
+
+g_printf("%s()\n", __PRETTY_FUNCTION__);
+g_return_if_fail(GTK_IS_GPS(widget));
+
+gps=GTK_GPS(widget);
+
+if (sat>12)
+       sat=12;
+
+gps->satinview=sat;
+gtk_gps_paint(gps);
+
+g_printf("%s(): return\n", __PRETTY_FUNCTION__);
+}
diff --git a/src/gtkgps.h b/src/gtkgps.h
new file mode 100644 (file)
index 0000000..51f224e
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *
+ * GtkGps: Display GPS satellite information
+ * Copyright (C) 2007 Kaj-Michael Lang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_GPS_H__
+#define __GTK_GPS_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_GPS_TYPE                   (gtk_GPS_get_type ())
+#define GTK_GPS(obj)                   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_GPS_TYPE, GtkGps))
+#define GTK_GPS_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_GPS_TYPE, GtkGpsClass))
+#define GTK_IS_GPS(obj)                        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_GPS_TYPE))
+
+typedef struct _GtkGps                 GtkGps;
+typedef struct _GtkGpsClass            GtkGpsClass;
+
+typedef struct _GtkGpsSatelliteData GtkGpsSatelliteData;
+struct _GtkGpsSatelliteData {
+       guint prn;
+       guint elevation;
+       guint azimuth;
+       guint snr;
+};
+
+struct _GtkGps {
+       GtkWidget parent;
+       GtkWidget widget;
+       GdkGC *gc1;
+       GdkGC *gc2;
+       GdkGC *gc3;
+       gint width, height;
+
+       PangoContext *sat_details_context;
+       PangoLayout *sat_details_layout;
+       PangoFontDescription *sat_details_fontdesc;
+       PangoContext *sat_details_expose_context;
+       PangoLayout *sat_details_expose_layout;
+       PangoFontDescription *sat_details_expose_fontdesc;
+
+       GtkGpsSatelliteData gps_sat[12];
+       guint satinview;
+       guint satinuse;
+       guint satforfix[12];
+};
+
+struct _GtkGpsClass {
+       GtkWidgetClass parent_class;
+};
+
+GType gtk_gps_get_type(void);
+GtkWidget* gtk_gps_new(void);
+void gtk_gps_set_satellite_data(GtkWidget *widget, guint sat, gboolean fix, guint prn, guint elevation, guint azimuth, guint snr);
+void gtk_gps_set_satellite_in_view(GtkWidget *widget, guint sat);
+
+G_END_DECLS
+
+#endif /* __GTK_GPS_H__ */