--- trunk/src/osm-gps-map-osd-classic.c 2009/08/21 13:20:40 71
+++ trunk/src/osm-gps-map-osd-classic.c 2009/09/09 11:50:50 103
@@ -17,10 +17,19 @@
* with this program. If not, see .
*/
-#include "config.h"
+#include "config.h"
+#include // abs
+#include // M_PI/cos()
/* parameters that can be overwritten from the config file: */
-/* OSM_GPS_MAP_OSD_DIAMETER */
+/* OSD_DIAMETER */
+/* OSD_X, OSD_Y */
+
+#ifndef OSD_SCALE_FONT_SIZE
+#define OSD_SCALE_FONT_SIZE 12
+#endif
+#define OSD_SCALE_W (10*OSD_SCALE_FONT_SIZE)
+#define OSD_SCALE_H (5*OSD_SCALE_FONT_SIZE/2)
#ifndef USE_CAIRO
#error "OSD control display lacks a non-cairo implementation!"
@@ -29,70 +38,43 @@
#include
#include "osm-gps-map.h"
+#include "osm-gps-map-osd-classic.h"
//the osd controls
typedef struct {
- GdkPixmap *backup;
- gint backup_x, backup_y;
-
+ /* the offscreen representation of the OSD */
cairo_surface_t *overlay;
- OsmGpsMapOsdGpsCallback cb;
- gpointer data;
-} osd_priv_t;
-
-/* the osd structure mainly contains various callbacks */
-/* required to draw and update the OSD */
-typedef struct {
-
- void(enable_gps)(OsmGpsMap *, OsmGpsMapOsdGpsCallback, gpointer);
- void(restore)(OsmGpsMap*);
- void(draw)(OsmGpsMap *, gint, gint);
- void(render)(OsmGpsMapPrivate *);
- osd_button_t(*check)(gint, gint); /* check if x/y lies within OSD */
- void(free)(gpointer);
-
- gpointer priv;
-} osm_gps_map_osd_t;
-
-static osm_gps_map_osd_t osd_classic = {
- .restore = osm_gps_map_osd_restore,
- .draw = osm_gps_map_osd_draw_controls,
- .check = osm_gps_map_osd_check,
- .render = osm_gps_map_osd_render,
- .enable_gps = osm_gps_map_osd_enable_gps,
- .free = osm_gps_map_osd_free,
- .priv = NULL;
-}
-
-/* this is the only function that's externally visible */
-osm_gps_map_osd_t *
-osm_gps_map_osd_classic_init(void)
-{
- return osd_classic;
-}
-
-static void
-osm_gps_map_osd_free(gpointer priv_ptr)
-{
- osd_priv_t *priv = (osd_priv_t *)priv_ptr;
+#ifdef OSD_SCALE
+ cairo_surface_t *scale;
+ int scale_zoom;
+#endif
+#ifdef OSD_SOURCE_SEL
+ /* values to handle the "source" menu */
+ cairo_surface_t *map_source;
+ gboolean expanded;
+ gint shift, dir, count;
+ gint handler_id;
+ gint width, height;
+#endif
- g_free(priv);
-}
+} osd_priv_t;
/* position and extent of bounding box */
+#ifndef OSD_X
#define OSD_X (10)
-#define OSD_Y (10)
+#endif
-#define OSD_COLOR 0.5, 0.5, 1
-#define OSD_COLOR_DISABLED 0.8, 0.8, 0.8
+#ifndef OSD_Y
+#define OSD_Y (10)
+#endif
/* parameters of the direction shape */
-#ifndef OSM_GPS_MAP_OSD_DIAMETER
+#ifndef OSD_DIAMETER
#define D_RAD (30) // diameter of dpad
#else
-#define D_RAD (OSM_GPS_MAP_OSD_DIAMETER)
+#define D_RAD (OSD_DIAMETER)
#endif
#define D_TIP (4*D_RAD/5) // distance of arrow tip from dpad center
#define D_LEN (D_RAD/4) // length of arrow
@@ -102,25 +84,44 @@
#define Z_STEP (D_RAD/4) // distance between dpad and zoom
#define Z_RAD (D_RAD/2) // radius of "caps" of zoom bar
+#ifdef OSD_SHADOW_ENABLE
/* shadow also depends on control size */
#define OSD_SHADOW (D_RAD/6)
+#else
+#define OSD_SHADOW (0)
+#endif
+
+/* normally the GPS button is in the center of the dpad. if there's */
+/* no dpad it will go into the zoom area */
+#if defined(OSD_GPS_BUTTON) && defined(OSD_NO_DPAD)
+#define Z_GPS 1
+#else
+#define Z_GPS 0
+#endif
/* total width and height of controls incl. shadow */
-#define OSD_W (2*D_RAD + OSD_SHADOW)
+#define OSD_W (2*D_RAD + OSD_SHADOW + Z_GPS * 2 * Z_RAD)
+#if !Z_GPS
#define OSD_H (2*D_RAD + Z_STEP + 2*Z_RAD + OSD_SHADOW)
+#else
+#define OSD_H (2*Z_RAD + OSD_SHADOW)
+#endif
+#ifdef OSD_SHADOW_ENABLE
#define OSD_LBL_SHADOW (OSD_SHADOW/2)
+#endif
+
+#define Z_TOP ((1-Z_GPS) * (2 * D_RAD + Z_STEP))
-#define Z_TOP (2 * D_RAD + Z_STEP)
#define Z_MID (Z_TOP + Z_RAD)
#define Z_BOT (Z_MID + Z_RAD)
#define Z_LEFT (Z_RAD)
-#define Z_RIGHT (2 * D_RAD - Z_RAD)
-
+#define Z_RIGHT (2 * D_RAD - Z_RAD + Z_GPS * 2 * Z_RAD)
+#define Z_CENTER ((Z_RIGHT + Z_LEFT)/2)
/* create the cairo shape used for the zoom buttons */
static void
-osm_gps_map_osd_zoom_shape(cairo_t *cr, gint x, gint y)
+osd_zoom_shape(cairo_t *cr, gint x, gint y)
{
cairo_move_to (cr, x+Z_LEFT, y+Z_TOP);
cairo_line_to (cr, x+Z_RIGHT, y+Z_TOP);
@@ -129,12 +130,73 @@
cairo_arc (cr, x+Z_LEFT, y+Z_MID, Z_RAD, M_PI/2, -M_PI/2);
}
+/* ------------------- color/shadow functions ----------------- */
+
+#ifndef OSD_COLOR
+/* if no color has been specified we just use the gdks default colors */
+static void
+osd_labels(cairo_t *cr, gint width, gboolean enabled,
+ GdkColor *fg, GdkColor *disabled) {
+ if(enabled) gdk_cairo_set_source_color(cr, fg);
+ else gdk_cairo_set_source_color(cr, disabled);
+ cairo_set_line_width (cr, width);
+}
+#else
+static void
+osd_labels(cairo_t *cr, gint width, gboolean enabled) {
+ if(enabled) cairo_set_source_rgb (cr, OSD_COLOR);
+ else cairo_set_source_rgb (cr, OSD_COLOR_DISABLED);
+ cairo_set_line_width (cr, width);
+}
+#endif
+
+#ifdef OSD_SHADOW_ENABLE
+static void
+osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {
+ cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);
+ cairo_set_line_width (cr, width);
+}
+#endif
+
+#ifndef OSD_NO_DPAD
/* create the cairo shape used for the dpad */
static void
-osm_gps_map_osd_dpad_shape(cairo_t *cr, gint x, gint y)
+osd_dpad_shape(cairo_t *cr, gint x, gint y)
{
cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI);
}
+#endif
+
+#ifdef OSD_SHADOW_ENABLE
+static void
+osd_shape_shadow(cairo_t *cr) {
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
+ cairo_fill (cr);
+ cairo_stroke (cr);
+}
+#endif
+
+#ifndef OSD_COLOR
+/* if no color has been specified we just use the gdks default colors */
+static void
+osd_shape(cairo_t *cr, GdkColor *bg, GdkColor *fg) {
+ gdk_cairo_set_source_color(cr, bg);
+ cairo_fill_preserve (cr);
+ gdk_cairo_set_source_color(cr, fg);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+}
+#else
+static void
+osd_shape(cairo_t *cr) {
+ cairo_set_source_rgb (cr, OSD_COLOR_BG);
+ cairo_fill_preserve (cr);
+ cairo_set_source_rgb (cr, OSD_COLOR);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+}
+#endif
+
static gboolean
osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad)
@@ -142,20 +204,23 @@
return( pow(cx - x, 2) + pow(cy - y, 2) < rad * rad);
}
+#ifndef OSD_NO_DPAD
/* check whether x/y is within the dpad */
static osd_button_t
-osm_gps_map_osd_check_dpad(gint x, gint y)
+osd_check_dpad(gint x, gint y)
{
/* within entire dpad circle */
- if( osm_gps_map_in_circle(x, y, OSD_X + D_RAD, OSD_Y + D_RAD, D_RAD))
+ if( osm_gps_map_in_circle(x, y, D_RAD, D_RAD, D_RAD))
{
/* convert into position relative to dpads centre */
- x -= (OSD_X + D_RAD);
- y -= (OSD_Y + D_RAD);
+ x -= D_RAD;
+ y -= D_RAD;
+#ifdef OSD_GPS_BUTTON
/* check for dpad center goes here! */
if( osm_gps_map_in_circle(x, y, 0, 0, D_RAD/3))
return OSD_GPS;
+#endif
if( y < 0 && abs(x) < abs(y))
return OSD_UP;
@@ -173,67 +238,430 @@
}
return OSD_NONE;
}
+#endif
/* check whether x/y is within the zoom pads */
static osd_button_t
-osm_gps_map_osd_check_zoom(gint x, gint y) {
- if( x > OSD_X && x < (OSD_X + OSD_W) && y > Z_TOP && y < (OSD_Y+Z_BOT)) {
+osd_check_zoom(gint x, gint y) {
+ if( x > 0 && x < OSD_W && y > Z_TOP && y < Z_BOT) {
/* within circle around (-) label */
- if( osm_gps_map_in_circle(x, y, OSD_X + Z_LEFT, OSD_Y + Z_MID, Z_RAD))
- return OSD_OUT;
-
- /* between center of (-) button and center of entire zoom control area */
- if(x > OSD_LEFT && x < OSD_X + D_RAD)
+ if( osm_gps_map_in_circle(x, y, Z_LEFT, Z_MID, Z_RAD))
return OSD_OUT;
/* within circle around (+) label */
- if( osm_gps_map_in_circle(x, y, OSD_X + Z_RIGHT, OSD_Y + Z_MID, Z_RAD))
+ if( osm_gps_map_in_circle(x, y, Z_RIGHT, Z_MID, Z_RAD))
return OSD_IN;
+#if Z_GPS == 1
+ /* within square around center */
+ if( x > Z_CENTER - Z_RAD && x < Z_CENTER + Z_RAD)
+ return OSD_GPS;
+#endif
+
+ /* between center of (-) button and center of entire zoom control area */
+ if(x > OSD_LEFT && x < D_RAD)
+ return OSD_OUT;
+
/* between center of (+) button and center of entire zoom control area */
- if(x < OSD_RIGHT && x > OSD_X + D_RAD)
+ if(x < OSD_RIGHT && x > D_RAD)
return OSD_IN;
}
return OSD_NONE;
}
+#ifdef OSD_SOURCE_SEL
+
+/* place source selection at right border */
+#define OSD_S_RAD (Z_RAD)
+#define OSD_S_X (-OSD_X)
+#define OSD_S_Y (OSD_Y)
+#define OSD_S_PW (2 * Z_RAD)
+#define OSD_S_W (OSD_S_PW)
+#define OSD_S_PH (2 * Z_RAD)
+#define OSD_S_H (OSD_S_PH + OSD_SHADOW)
+
+/* size of usable area when expanded */
+#define OSD_S_AREA_W (priv->width)
+#define OSD_S_AREA_H (priv->height)
+#define OSD_S_EXP_W (OSD_S_PW + OSD_S_AREA_W + OSD_SHADOW)
+#define OSD_S_EXP_H (OSD_S_AREA_H + OSD_SHADOW)
+
+/* internal value to draw the arrow on the "puller" */
+#define OSD_S_D0 (OSD_S_RAD/2)
+#ifndef OSD_FONT_SIZE
+#define OSD_FONT_SIZE 16.0
+#endif
+#define OSD_TEXT_BORDER (OSD_FONT_SIZE/2)
+#define OSD_TEXT_SKIP (OSD_FONT_SIZE/8)
+
+/* draw the shape of the source selection OSD, either only the puller (not expanded) */
+/* or the entire menu incl. the puller (expanded) */
+static void
+osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) {
+ if(!priv->expanded) {
+ /* just draw the puller */
+ cairo_move_to (cr, x + OSD_S_PW, y + OSD_S_PH);
+ cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
+ cairo_line_to (cr, x + OSD_S_PW, y);
+ } else {
+ /* draw the puller and the area itself */
+ cairo_move_to (cr, x + OSD_S_PW + OSD_S_AREA_W, y + OSD_S_AREA_H);
+ cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_AREA_H);
+ if(OSD_S_Y > 0) {
+ cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_PH);
+ cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
+ } else {
+ cairo_arc (cr, x+OSD_S_RAD, y+OSD_S_AREA_H-OSD_S_RAD, OSD_S_RAD, M_PI/2, -M_PI/2);
+ cairo_line_to (cr, x + OSD_S_PW, y + OSD_S_AREA_H - OSD_S_PH);
+ cairo_line_to (cr, x + OSD_S_PW, y);
+ }
+ cairo_line_to (cr, x + OSD_S_PW + OSD_S_AREA_W, y);
+ cairo_close_path (cr);
+ }
+}
+
+static void
+osd_source_content(osm_gps_map_osd_t *osd, cairo_t *cr, gint offset) {
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+
+ int py = offset + OSD_S_RAD - OSD_S_D0;
+
+ if(!priv->expanded) {
+ /* draw the "puller" open (<) arrow */
+ cairo_move_to (cr, offset + OSD_S_RAD + OSD_S_D0/2, py);
+ cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0);
+ cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0);
+ } else {
+ if(OSD_S_Y < 0)
+ py += OSD_S_AREA_H - OSD_S_PH;
+
+ /* draw the "puller" close (>) arrow */
+ cairo_move_to (cr, offset + OSD_S_RAD - OSD_S_D0/2, py);
+ cairo_rel_line_to (cr, +OSD_S_D0, +OSD_S_D0);
+ cairo_rel_line_to (cr, -OSD_S_D0, +OSD_S_D0);
+ cairo_stroke(cr);
+
+ /* don't draw a shadow for the text content */
+ if(offset == 1) {
+ gint source;
+ g_object_get(osd->widget, "map-source", &source, NULL);
+
+ cairo_select_font_face (cr, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, OSD_FONT_SIZE);
+
+ int i, step = (priv->height - 2*OSD_TEXT_BORDER) /
+ OSM_GPS_MAP_SOURCE_LAST;
+ for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
+ cairo_text_extents_t extents;
+ const char *src = osm_gps_map_source_get_friendly_name(i);
+ cairo_text_extents (cr, src, &extents);
+
+ int x = offset + OSD_S_PW + OSD_TEXT_BORDER;
+ int y = offset + step * (i-1) + OSD_TEXT_BORDER;
+
+ /* draw filled rectangle if selected */
+ if(source == i) {
+ cairo_rectangle(cr, x - OSD_TEXT_BORDER/2,
+ y - OSD_TEXT_SKIP,
+ priv->width - OSD_TEXT_BORDER,
+ step + OSD_TEXT_SKIP);
+ cairo_fill(cr);
+
+ /* temprarily draw with background color */
+#ifndef OSD_COLOR
+ GdkColor bg = osd->widget->style->bg[GTK_STATE_NORMAL];
+ gdk_cairo_set_source_color(cr, &bg);
+#else
+ cairo_set_source_rgb (cr, OSD_COLOR_BG);
+#endif
+ }
+
+ cairo_move_to (cr, x, y + OSD_TEXT_SKIP - extents.y_bearing);
+ cairo_show_text (cr, src);
+
+ /* restore color */
+ if(source == i) {
+#ifndef OSD_COLOR
+ GdkColor fg = osd->widget->style->fg[GTK_STATE_NORMAL];
+ gdk_cairo_set_source_color(cr, &fg);
+#else
+ cairo_set_source_rgb (cr, OSD_COLOR);
+#endif
+ }
+ }
+ }
+ }
+}
+
+static void
+osd_render_source_sel(osm_gps_map_osd_t *osd) {
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+
+#ifndef OSD_COLOR
+ GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
+ GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];
+ GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];
+#endif
+
+ /* draw source selector */
+ cairo_t *cr = cairo_create(priv->map_source);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
+ cairo_paint(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+
+#ifdef OSD_SHADOW_ENABLE
+ osd_source_shape(priv, cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
+ osd_shape_shadow(cr);
+#endif
+
+ osd_source_shape(priv, cr, 1, 1);
+#ifndef OSD_COLOR
+ osd_shape(cr, &bg, &fg);
+#else
+ osd_shape(cr);
+#endif
+
+#ifdef OSD_SHADOW_ENABLE
+ osd_labels_shadow(cr, Z_RAD/3, TRUE);
+ osd_source_content(osd, cr, 1+OSD_LBL_SHADOW);
+ cairo_stroke (cr);
+#endif
+#ifndef OSD_COLOR
+ osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);
+#else
+ osd_labels(cr, Z_RAD/3, TRUE);
+#endif
+ osd_source_content(osd, cr, 1);
+ cairo_stroke (cr);
+
+ cairo_destroy(cr);
+}
+
+/* re-allocate the buffer used to draw the menu. This is used */
+/* to collapse/expand the buffer */
+static void
+osd_source_reallocate(osm_gps_map_osd_t *osd) {
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+
+ /* re-allocate offscreen bitmap */
+ g_assert (priv->map_source);
+
+ int w = OSD_S_W, h = OSD_S_H;
+ if(priv->expanded) {
+ cairo_text_extents_t extents;
+
+ /* determine content size */
+ cairo_t *cr = cairo_create(priv->map_source);
+ cairo_select_font_face (cr, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, OSD_FONT_SIZE);
+
+ /* calculate menu size */
+ int i, max_h = 0, max_w = 0;
+ for(i=OSM_GPS_MAP_SOURCE_NULL+1;i<=OSM_GPS_MAP_SOURCE_LAST;i++) {
+ const char *src = osm_gps_map_source_get_friendly_name(i);
+ cairo_text_extents (cr, src, &extents);
+
+ if(extents.width > max_w) max_w = extents.width;
+ if(extents.height > max_h) max_h = extents.height;
+ }
+ cairo_destroy(cr);
+
+ priv->width = max_w + 2*OSD_TEXT_BORDER;
+ priv->height = OSM_GPS_MAP_SOURCE_LAST *
+ (max_h + 2*OSD_TEXT_SKIP) + 2*OSD_TEXT_BORDER;
+
+ w = OSD_S_EXP_W;
+ h = OSD_S_EXP_H;
+ }
+
+ cairo_surface_destroy(priv->map_source);
+ priv->map_source =
+ cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w+2, h+2);
+
+ osd_render_source_sel(osd);
+}
+
+#define OSD_HZ 15
+#define OSD_TIME 500
+
+static gboolean osd_source_animate(gpointer data) {
+ osm_gps_map_osd_t *osd = (osm_gps_map_osd_t*)data;
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+ int diff = OSD_S_EXP_W - OSD_S_W - OSD_S_X;
+ gboolean done = FALSE;
+ priv->count += priv->dir;
+
+ /* shifting in */
+ if(priv->dir < 0) {
+ if(priv->count <= 0) {
+ priv->count = 0;
+ done = TRUE;
+ }
+ } else {
+ if(priv->count >= 1000) {
+ priv->expanded = FALSE;
+ osd_source_reallocate(osd);
+
+ priv->count = 1000;
+ done = TRUE;
+ }
+ }
+
+
+ /* count runs linearly from 0 to 1000, map this nicely onto a position */
+
+ /* nicer sinoid mapping */
+ float m = 0.5-cos(priv->count * M_PI / 1000.0)/2;
+ priv->shift = (osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X) +
+ m * diff;
+
+ osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
+
+ if(done)
+ priv->handler_id = 0;
+
+ return !done;
+}
+
+/* switch between expand and collapse mode of source selection */
+static void
+osd_source_toggle(osm_gps_map_osd_t *osd)
+{
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+
+ /* ignore clicks while animation is running */
+ if(priv->handler_id)
+ return;
+
+ /* expand immediately, collapse is handle at the end of the collapse animation */
+ if(!priv->expanded) {
+ priv->expanded = TRUE;
+ osd_source_reallocate(osd);
+
+ priv->count = 1000;
+ priv->shift = osd->widget->allocation.width - OSD_S_W;
+ priv->dir = -1000/OSD_HZ;
+ } else {
+ priv->count = 0;
+ priv->shift = osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
+ priv->dir = +1000/OSD_HZ;
+ }
+
+ priv->handler_id = gtk_timeout_add(OSD_TIME/OSD_HZ, osd_source_animate, osd);
+}
+
+/* check if the user clicked inside the source selection area */
+static osd_button_t
+osd_source_check(osm_gps_map_osd_t *osd, gint x, gint y) {
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+
+ if(!priv->expanded)
+ x -= osd->widget->allocation.width - OSD_S_W;
+ else
+ x -= osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
+
+ if(OSD_S_Y > 0)
+ y -= OSD_S_Y;
+ else
+ y -= osd->widget->allocation.height - OSD_S_PH + OSD_S_Y;
+
+ /* within square around puller? */
+ if(y > 0 && y < OSD_S_PH && x > 0 && x < OSD_S_PW) {
+ /* really within puller shape? */
+ if(x > Z_RAD || osm_gps_map_in_circle(x, y, Z_RAD, Z_RAD, Z_RAD)) {
+ /* expand source selector */
+ osd_source_toggle(osd);
+
+ /* tell upper layers that user clicked some background element */
+ /* of the OSD */
+ return OSD_BG;
+ }
+ }
+
+ /* check for clicks into data area */
+ if(priv->expanded && !priv->handler_id) {
+ /* re-adjust from puller top to content top */
+ if(OSD_S_Y < 0)
+ y += OSD_S_EXP_H - OSD_S_PH;
+
+ if(x > OSD_S_PW &&
+ x < OSD_S_PW + OSD_S_EXP_W &&
+ y > 0 &&
+ y < OSD_S_EXP_H) {
+
+ int step = (priv->height - 2*OSD_TEXT_BORDER)
+ / OSM_GPS_MAP_SOURCE_LAST;
+
+ y -= OSD_TEXT_BORDER - OSD_TEXT_SKIP;
+ y /= step;
+ y += 1;
+
+ gint old = 0;
+ g_object_get(osd->widget, "map-source", &old, NULL);
+
+ if(y > OSM_GPS_MAP_SOURCE_NULL &&
+ y <= OSM_GPS_MAP_SOURCE_LAST &&
+ old != y) {
+ g_object_set(osd->widget, "map-source", y, NULL);
+
+ osd_render_source_sel(osd);
+ osm_gps_map_repaint(OSM_GPS_MAP(osd->widget));
+ }
+
+ /* return "clicked in OSD background" to prevent further */
+ /* processing by application */
+ return OSD_BG;
+ }
+ }
+
+ return OSD_NONE;
+}
+#endif // OSD_SOURCE_SEL
+
static osd_button_t
-osm_gps_map_osd_check(gint x, gint y) {
+osd_check(osm_gps_map_osd_t *osd, gint x, gint y) {
osd_button_t but = OSD_NONE;
+#ifdef OSD_SOURCE_SEL
+ /* the source selection area is handles internally */
+ but = osd_source_check(osd, x, y);
+ if(but != OSD_NONE)
+ return but;
+#endif
+
+ x -= OSD_X;
+ y -= OSD_Y;
+
+ if(OSD_X < 0)
+ x -= (osd->widget->allocation.width - OSD_W);
+
+ if(OSD_Y < 0)
+ y -= (osd->widget->allocation.height - OSD_H);
+
/* first do a rough test for the OSD area. */
/* this is just to avoid an unnecessary detailed test */
- if(x > OSD_X && x < OSD_X + OSD_W &&
- y > OSD_Y && y < OSD_Y + OSD_H) {
- but = osm_gps_map_osd_check_dpad(x, y);
+ if(x > 0 && x < OSD_W && y > 0 && y < OSD_H) {
+#ifndef OSD_NO_DPAD
+ but = osd_check_dpad(x, y);
+#endif
if(but == OSD_NONE)
- but = osm_gps_map_osd_check_zoom(x, y);
+ but = osd_check_zoom(x, y);
}
return but;
}
-static void
-osm_gps_map_osd_shape_shadow(cairo_t *cr) {
- cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
- cairo_fill (cr);
- cairo_stroke (cr);
-}
-
-static void
-osm_gps_map_osd_shape(cairo_t *cr) {
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_fill_preserve (cr);
- cairo_set_source_rgb (cr, OSD_COLOR);
- cairo_set_line_width (cr, 1);
- cairo_stroke (cr);
-}
-
+#ifndef OSD_NO_DPAD
static void
-osm_gps_map_osd_dpad_labels(cairo_t *cr, gint x, gint y) {
+osd_dpad_labels(cairo_t *cr, gint x, gint y) {
/* move reference to dpad center */
x += D_RAD;
y += D_RAD;
@@ -256,18 +684,22 @@
cairo_rel_line_to (cr, offset[i][2][0], offset[i][2][1]);
}
}
+#endif
-/* draw the sattelite dish icon in the center of the dpad */
-#define GPS_V0 (D_RAD/8)
+#ifdef OSD_GPS_BUTTON
+/* draw the satellite dish icon in the center of the dpad */
+#define GPS_V0 (D_RAD/7)
#define GPS_V1 (D_RAD/10)
#define GPS_V2 (D_RAD/5)
/* draw a satellite receiver dish */
+/* this is either drawn in the center of the dpad (if present) */
+/* or in the middle of the zoom area */
static void
-osm_gps_map_osd_dpad_gps(cairo_t *cr, gint x, gint y) {
+osd_dpad_gps(cairo_t *cr, gint x, gint y) {
/* move reference to dpad center */
- x += D_RAD;
- y += D_RAD + GPS_V0;
+ x += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD * 3;
+ y += (1-Z_GPS) * D_RAD + Z_GPS * Z_RAD + GPS_V0;
cairo_move_to (cr, x-GPS_V0, y+GPS_V0);
cairo_rel_line_to (cr, +GPS_V0, -GPS_V0);
@@ -282,11 +714,12 @@
cairo_move_to (cr, x, y-GPS_V2);
cairo_rel_line_to (cr, +GPS_V1, -GPS_V1);
}
+#endif
#define Z_LEN (2*Z_RAD/3)
static void
-osm_gps_map_osd_zoom_labels(cairo_t *cr, gint x, gint y) {
+osd_zoom_labels(cairo_t *cr, gint x, gint y) {
cairo_move_to (cr, x + Z_LEFT - Z_LEN, y + Z_MID);
cairo_line_to (cr, x + Z_LEFT + Z_LEN, y + Z_MID);
@@ -296,130 +729,396 @@
cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
}
+/* various parameters used to create the scale */
+#define OSD_SCALE_H2 (OSD_SCALE_H/2)
+#define OSD_SCALE_TICK (2*OSD_SCALE_FONT_SIZE/3)
+#define OSD_SCALE_M (OSD_SCALE_H2 - OSD_SCALE_TICK)
+#define OSD_SCALE_I (OSD_SCALE_H2 + OSD_SCALE_TICK)
+#define OSD_SCALE_FD (OSD_SCALE_FONT_SIZE/4)
+
static void
-osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {
- if(enabled) cairo_set_source_rgb (cr, OSD_COLOR);
- else cairo_set_source_rgb (cr, OSD_COLOR_DISABLED);
- cairo_set_line_width (cr, width);
- cairo_stroke (cr);
-}
+osd_render_scale(osm_gps_map_osd_t *osd)
+{
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
-static void
-osm_gps_map_osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {
- cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);
- cairo_set_line_width (cr, width);
+ /* this only needs to be rendered if the zoom has changed */
+ gint zoom;
+ g_object_get(OSM_GPS_MAP(osd->widget), "zoom", &zoom, NULL);
+ if(zoom == priv->scale_zoom)
+ return;
+
+ priv->scale_zoom = zoom;
+
+ float m_per_pix = osm_gps_map_get_scale(OSM_GPS_MAP(osd->widget));
+
+ /* first fill with transparency */
+ cairo_t *cr = cairo_create(priv->scale);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
+ // pink for testing: cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.2);
+ cairo_paint(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+
+ /* determine the size of the scale width in meters */
+ float width = (OSD_SCALE_W-OSD_SCALE_FONT_SIZE/6) * m_per_pix;
+
+ /* scale this to useful values */
+ int exp = logf(width)*M_LOG10E;
+ int mant = width/pow(10,exp);
+ int width_metric = mant * pow(10,exp);
+ char *dist_str = NULL;
+ if(width_metric<1000)
+ dist_str = g_strdup_printf("%u m", width_metric);
+ else
+ dist_str = g_strdup_printf("%u km", width_metric/1000);
+ width_metric /= m_per_pix;
+
+ /* and now the hard part: scale for useful imperial values :-( */
+ /* try to convert to feet, 1ft == 0.3048 m */
+ width /= 0.3048;
+ float imp_scale = 0.3048;
+ char *dist_imp_unit = "ft";
+
+ if(width >= 100) {
+ /* 1yd == 3 feet */
+ width /= 3.0;
+ imp_scale *= 3.0;
+ dist_imp_unit = "yd";
+
+ if(width >= 1760.0) {
+ /* 1mi == 1760 yd */
+ width /= 1760.0;
+ imp_scale *= 1760.0;
+ dist_imp_unit = "mi";
+ }
+ }
+
+ /* also convert this to full tens/hundreds */
+ exp = logf(width)*M_LOG10E;
+ mant = width/pow(10,exp);
+ int width_imp = mant * pow(10,exp);
+ char *dist_str_imp = g_strdup_printf("%u %s", width_imp, dist_imp_unit);
+
+ /* convert back to pixels */
+ width_imp *= imp_scale;
+ width_imp /= m_per_pix;
+
+ cairo_select_font_face (cr, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, OSD_SCALE_FONT_SIZE);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+
+ cairo_text_extents_t extents;
+ cairo_text_extents (cr, dist_str, &extents);
+
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6);
+ cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD);
+ cairo_text_path (cr, dist_str);
+ cairo_stroke (cr);
+ cairo_move_to (cr, 2*OSD_SCALE_FD,
+ OSD_SCALE_H2+OSD_SCALE_FD + extents.height);
+ cairo_text_path (cr, dist_str_imp);
cairo_stroke (cr);
+
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_move_to (cr, 2*OSD_SCALE_FD, OSD_SCALE_H2-OSD_SCALE_FD);
+ cairo_show_text (cr, dist_str);
+ cairo_move_to (cr, 2*OSD_SCALE_FD,
+ OSD_SCALE_H2+OSD_SCALE_FD + extents.height);
+ cairo_show_text (cr, dist_str_imp);
+
+ g_free(dist_str);
+ g_free(dist_str_imp);
+
+ /* draw white line */
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
+ cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/3);
+ cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M);
+ cairo_rel_line_to (cr, 0, OSD_SCALE_TICK);
+ cairo_rel_line_to (cr, width_metric, 0);
+ cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
+ cairo_stroke(cr);
+ cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I);
+ cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
+ cairo_rel_line_to (cr, width_imp, 0);
+ cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK);
+ cairo_stroke(cr);
+
+ /* draw black line */
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width (cr, OSD_SCALE_FONT_SIZE/6);
+ cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_M);
+ cairo_rel_line_to (cr, 0, OSD_SCALE_TICK);
+ cairo_rel_line_to (cr, width_metric, 0);
+ cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
+ cairo_stroke(cr);
+ cairo_move_to (cr, OSD_SCALE_FONT_SIZE/6, OSD_SCALE_I);
+ cairo_rel_line_to (cr, 0, -OSD_SCALE_TICK);
+ cairo_rel_line_to (cr, width_imp, 0);
+ cairo_rel_line_to (cr, 0, +OSD_SCALE_TICK);
+ cairo_stroke(cr);
+
+ cairo_destroy(cr);
}
static void
-osm_gps_map_osd_render(OsmGpsMapPrivate *priv) {
+osd_render(osm_gps_map_osd_t *osd)
+{
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
+
+#ifndef OSD_COLOR
+ GdkColor bg = GTK_WIDGET(osd->widget)->style->bg[GTK_STATE_NORMAL];
+ GdkColor fg = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_NORMAL];
+ GdkColor da = GTK_WIDGET(osd->widget)->style->fg[GTK_STATE_INSENSITIVE];
+#endif
/* first fill with transparency */
- cairo_t *cr = cairo_create(priv->osd.overlay);
+ cairo_t *cr = cairo_create(priv->overlay);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
cairo_paint(cr);
-
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
/* --------- draw zoom and dpad shape shadow ----------- */
- gint x = 0, y = 0;
-
- osm_gps_map_osd_zoom_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);
- osm_gps_map_osd_shape_shadow(cr);
- osm_gps_map_osd_dpad_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);
- osm_gps_map_osd_shape_shadow(cr);
+#ifdef OSD_SHADOW_ENABLE
+ osd_zoom_shape(cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
+ osd_shape_shadow(cr);
+#ifndef OSD_NO_DPAD
+ osd_dpad_shape(cr, 1+OSD_SHADOW, 1+OSD_SHADOW);
+ osd_shape_shadow(cr);
+#endif
+#endif
/* --------- draw zoom and dpad shape ----------- */
- osm_gps_map_osd_zoom_shape(cr, x, y);
- osm_gps_map_osd_shape(cr);
- osm_gps_map_osd_dpad_shape(cr, x, y);
- osm_gps_map_osd_shape(cr);
+ osd_zoom_shape(cr, 1, 1);
+#ifndef OSD_COLOR
+ osd_shape(cr, &bg, &fg);
+#else
+ osd_shape(cr);
+#endif
+#ifndef OSD_NO_DPAD
+ osd_dpad_shape(cr, 1, 1);
+#ifndef OSD_COLOR
+ osd_shape(cr, &bg, &fg);
+#else
+ osd_shape(cr);
+#endif
+#endif
/* --------- draw zoom and dpad labels --------- */
- osm_gps_map_osd_zoom_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
- osm_gps_map_osd_dpad_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
- osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);
- osm_gps_map_osd_dpad_gps(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
- osm_gps_map_osd_labels_shadow(cr, Z_RAD/6, priv->osd.cb != NULL);
-
- osm_gps_map_osd_zoom_labels(cr, x, y);
- osm_gps_map_osd_dpad_labels(cr, x, y);
- osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);
- osm_gps_map_osd_dpad_gps(cr, x, y);
- osm_gps_map_osd_labels(cr, Z_RAD/6, priv->osd.cb != NULL);
+#ifdef OSD_SHADOW_ENABLE
+ osd_labels_shadow(cr, Z_RAD/3, TRUE);
+ osd_zoom_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
+#ifndef OSD_NO_DPAD
+ osd_dpad_labels(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
+#endif
+ cairo_stroke(cr);
+#ifdef OSD_GPS_BUTTON
+ osd_labels_shadow(cr, Z_RAD/6, osd->cb != NULL);
+ osd_dpad_gps(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW);
+ cairo_stroke(cr);
+#endif
+#endif
+
+#ifndef OSD_COLOR
+ osd_labels(cr, Z_RAD/3, TRUE, &fg, &da);
+#else
+ osd_labels(cr, Z_RAD/3, TRUE);
+#endif
+ osd_zoom_labels(cr, 1, 1);
+#ifndef OSD_NO_DPAD
+ osd_dpad_labels(cr, 1, 1);
+#endif
+ cairo_stroke(cr);
+
+#ifndef OSD_COLOR
+ osd_labels(cr, Z_RAD/6, osd->cb != NULL, &fg, &da);
+#else
+ osd_labels(cr, Z_RAD/6, osd->cb != NULL);
+#endif
+#ifdef OSD_GPS_BUTTON
+ osd_dpad_gps(cr, 1, 1);
+#endif
+ cairo_stroke(cr);
cairo_destroy(cr);
+
+#ifdef OSD_SOURCE_SEL
+ osd_render_source_sel(osd);
+#endif
+
+#ifdef OSD_SCALE
+ osd_render_scale(osd);
+#endif
}
static void
-osm_gps_map_osd_draw_controls (OsmGpsMap *map, gint xoffset, gint yoffset)
+osd_draw(osm_gps_map_osd_t *osd, GdkDrawable *drawable)
{
- OsmGpsMapPrivate *priv = map->priv;
-
- /* backup previous contents */
- if(!priv->osd.backup)
- priv->osd.backup = gdk_pixmap_new(priv->pixmap, OSD_W+2, OSD_H+2, -1);
-
- gint x = OSD_X + EXTRA_BORDER + xoffset;
- gint y = OSD_Y + EXTRA_BORDER + yoffset;
-
- /* create backup of background */
- gdk_draw_drawable(priv->osd.backup,
- GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],
- priv->pixmap, x-1, y-1, 0, 0, OSD_W+2, OSD_H+2);
-
- priv->osd.backup_x = x-1;
- priv->osd.backup_y = y-1;
+ osd_priv_t *priv = (osd_priv_t*)osd->priv;
/* OSD itself uses some off-screen rendering, so check if the */
/* offscreen buffer is present and create it if not */
- if(!priv->osd.overlay) {
+ if(!priv->overlay) {
/* create overlay ... */
- priv->osd.overlay =
- cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);
+ priv->overlay =
+ cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W+2, OSD_H+2);
+
+#ifdef OSD_SOURCE_SEL
+ /* the initial OSD state is alway not-expanded */
+ priv->map_source =
+ cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ OSD_S_W+2, OSD_S_H+2);
+#endif
+
+#ifdef OSD_SCALE
+ priv->scale =
+ cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ OSD_SCALE_W, OSD_SCALE_H);
+ priv->scale_zoom = -1;
+#endif
+
/* ... and render it */
- osm_gps_map_osd_render(priv);
+ osd_render(osd);
}
// now draw this onto the original context
- cairo_t *cr = gdk_cairo_create(priv->pixmap);
- cairo_set_source_surface(cr, priv->osd.overlay, x, y);
+ cairo_t *cr = gdk_cairo_create(drawable);
+
+ int x = OSD_X, y = OSD_Y;
+ if(OSD_X < 0)
+ x = osd->widget->allocation.width - OSD_W + OSD_X;
+
+ if(OSD_Y < 0)
+ y = osd->widget->allocation.height - OSD_H + OSD_Y;
+
+ cairo_set_source_surface(cr, priv->overlay, x, y);
cairo_paint(cr);
+
+#ifdef OSD_SOURCE_SEL
+ if(!priv->handler_id) {
+ /* the OSD source selection is not being animated */
+ if(!priv->expanded)
+ x = osd->widget->allocation.width - OSD_S_W;
+ else
+ x = osd->widget->allocation.width - OSD_S_EXP_W + OSD_S_X;
+ } else
+ x = priv->shift;
+
+ y = OSD_S_Y;
+ if(OSD_S_Y < 0) {
+ if(!priv->expanded)
+ y = osd->widget->allocation.height - OSD_S_H + OSD_S_Y;
+ else
+ y = osd->widget->allocation.height - OSD_S_EXP_H + OSD_S_Y;
+ }
+
+ cairo_set_source_surface(cr, priv->map_source, x, y);
+ cairo_paint(cr);
+#endif
+
+#ifdef OSD_SCALE
+ x = OSD_X;
+ y = -OSD_Y;
+ if(x < 0) x += osd->widget->allocation.width - OSD_SCALE_W;
+ if(y < 0) y += osd->widget->allocation.height - OSD_SCALE_H;
+
+ cairo_set_source_surface(cr, priv->scale, x, y);
+ cairo_paint(cr);
+#endif
+
cairo_destroy(cr);
}
static void
-osm_gps_map_osd_restore (OsmGpsMap *map)
+osd_free(osm_gps_map_osd_t *osd)
{
- OsmGpsMapPrivate *priv = map->priv;
+ osd_priv_t *priv = (osd_priv_t *)(osd->priv);
- /* restore backup of previous contents */
- if(priv->osd.backup) {
- /* create backup of background */
- gdk_draw_drawable(priv->pixmap,
- GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],
- priv->osd.backup, 0, 0,
- priv->osd.backup_x, priv->osd.backup_y, OSD_W+2, OSD_H+2);
- }
+ if (priv->overlay)
+ cairo_surface_destroy(priv->overlay);
+
+#ifdef OSD_SOURCE_SEL
+ if(priv->handler_id)
+ gtk_timeout_remove(priv->handler_id);
+
+ if (priv->map_source)
+ cairo_surface_destroy(priv->map_source);
+#endif
+
+#ifdef OSD_SCALE
+ if (priv->scale)
+ cairo_surface_destroy(priv->scale);
+#endif
+
+ g_free(priv);
}
-static void
-osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdGpsCallback cb, gpointer data)
+static gboolean
+osd_busy(osm_gps_map_osd_t *osd)
{
- OsmGpsMapPrivate *priv;
+#ifdef OSD_SOURCE_SEL
+ osd_priv_t *priv = (osd_priv_t *)(osd->priv);
+ return (priv->handler_id != 0);
+#else
+ return FALSE;
+#endif
+}
+
+static osm_gps_map_osd_t osd_classic = {
+ .widget = NULL,
+
+ .draw = osd_draw,
+ .check = osd_check,
+ .render = osd_render,
+ .free = osd_free,
+ .busy = osd_busy,
+
+ .cb = NULL,
+ .data = NULL,
+
+ .priv = NULL
+};
+
+/* this is the only function that's externally visible */
+void
+osm_gps_map_osd_classic_init(OsmGpsMap *map)
+{
+ osd_priv_t *priv = osd_classic.priv = g_new0(osd_priv_t, 1);
+
+ osd_classic.priv = priv;
+
+ osm_gps_map_register_osd(map, &osd_classic);
+}
- g_return_if_fail (OSM_IS_GPS_MAP (map));
- priv = map->priv;
+#ifdef OSD_GPS_BUTTON
+/* below are osd specific functions which aren't used by osm-gps-map */
+/* but instead are to be used by the main application */
+void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdCallback cb,
+ gpointer data) {
+ osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
+ g_return_if_fail (osd);
- priv->osd.cb = cb;
- priv->osd.data = data;
+ osd->cb = cb;
+ osd->data = data;
/* this may have changed the state of the gps button */
/* we thus re-render the overlay */
- osm_gps_map_osd_render(priv);
+ osd->render(osd);
- osm_gps_map_map_redraw_idle(map);
+ osm_gps_map_redraw(map);
+}
+#endif
+
+osd_button_t
+osm_gps_map_osd_check(OsmGpsMap *map, gint x, gint y) {
+ osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);
+ g_return_val_if_fail (osd, OSD_NONE);
+
+ return osd_check(osd, x, y);
}