--- trunk/src/osm-gps-map-osd-classic.c 2009/08/30 19:05:44 86 +++ trunk/src/osm-gps-map-osd-classic.c 2009/08/31 12:01:28 87 @@ -19,11 +19,7 @@ #include "config.h" #include // abs -#include // M_PI - -#define OSD_SOURCE_SEL - -#define OSD_Y (-10) +#include // M_PI/cos() /* parameters that can be overwritten from the config file: */ /* OSD_DIAMETER */ @@ -43,10 +39,13 @@ /* the offscreen representation of the OSD */ cairo_surface_t *overlay; + /* values to handle the "source" menu */ cairo_surface_t *map_source; gboolean expanded; gint shift, dir, count; gint handler_id; + gint width, height; + } osd_priv_t; /* position and extent of bounding box */ @@ -128,7 +127,6 @@ if(enabled) gdk_cairo_set_source_color(cr, fg); else gdk_cairo_set_source_color(cr, disabled); cairo_set_line_width (cr, width); - cairo_stroke (cr); } #else static void @@ -136,7 +134,6 @@ 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); } #endif @@ -145,7 +142,6 @@ 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); - cairo_stroke (cr); } #endif @@ -271,14 +267,19 @@ #define OSD_S_PH (2 * Z_RAD) #define OSD_S_H (OSD_S_PH + OSD_SHADOW) -/* size of usable area when exapnded */ -#define OSD_S_AREA_W (200) -#define OSD_S_AREA_H (200) +/* 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) static void osd_source_shape(osd_priv_t *priv, cairo_t *cr, gint x, gint y) { @@ -305,22 +306,77 @@ } static void -osd_source_content(osd_priv_t *priv, cairo_t *cr, gint x, gint y) { - y += OSD_S_RAD - OSD_S_D0; +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, x + OSD_S_RAD + OSD_S_D0/2, y); + 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) - y += OSD_S_AREA_H - OSD_S_PH; + py += OSD_S_AREA_H - OSD_S_PH; /* draw the "puller" close (>) arrow */ - cairo_move_to (cr, x + OSD_S_RAD - OSD_S_D0/2, y); + 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 + } + } + } } } @@ -354,15 +410,17 @@ #endif #ifdef OSD_SHADOW_ENABLE - osd_source_content(priv, cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); osd_labels_shadow(cr, Z_RAD/3, TRUE); + osd_source_content(osd, cr, 1+OSD_LBL_SHADOW); + cairo_stroke (cr); #endif - osd_source_content(priv, cr, 1, 1); #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); } @@ -373,14 +431,42 @@ /* re-allocate offscreen bitmap */ g_assert (priv->map_source); - cairo_surface_destroy(priv->map_source); int w = OSD_S_W, h = OSD_S_H; if(priv->expanded) { + /* ... and right of it the waypoint id */ + 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); + + // printf("Source %d: %s = %f %f\n", i, src, + // extents.width, extents.height); + + 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); @@ -389,7 +475,7 @@ } #define OSD_HZ 15 -#define OSD_TIME 1000 +#define OSD_TIME 500 static gboolean osd_source_animate(gpointer data) { osm_gps_map_osd_t *osd = (osm_gps_map_osd_t*)data; @@ -641,34 +727,39 @@ /* --------- draw zoom and dpad labels --------- */ #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 - osd_labels_shadow(cr, Z_RAD/3, TRUE); + cairo_stroke(cr); #ifdef OSD_GPS_BUTTON - osd_dpad_gps(cr, 1+OSD_LBL_SHADOW, 1+OSD_LBL_SHADOW); 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 - osd_zoom_labels(cr, 1, 1); -#ifndef OSD_NO_DPAD - osd_dpad_labels(cr, 1, 1); -#endif #ifndef OSD_COLOR osd_labels(cr, Z_RAD/3, TRUE, &fg, &da); #else osd_labels(cr, Z_RAD/3, TRUE); #endif -#ifdef OSD_GPS_BUTTON - osd_dpad_gps(cr, 1, 1); + 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); @@ -751,11 +842,20 @@ g_free(priv); } +/* this is the only function that's externally visible */ +static gboolean +osd_busy(osm_gps_map_osd_t *osd) +{ + osd_priv_t *priv = (osd_priv_t *)(osd->priv); + return (priv->handler_id != 0); +} + static osm_gps_map_osd_t osd_classic = { .draw = osd_draw, .check = osd_check, .render = osd_render, .free = osd_free, + .busy = osd_busy, .cb = NULL, .data = NULL,