--- trunk/src/map-tool.c 2009/08/05 14:11:00 46
+++ trunk/src/map-tool.c 2009/08/12 12:16:05 51
@@ -24,6 +24,8 @@
#include "osm-gps-map.h"
#endif
+#define GPS_DEFAULT_ZOOM 13
+
/* equatorial radius in meters */
#define EQ_RADIUS (6378137.0)
@@ -80,7 +82,7 @@
}
static void map_zoom(map_context_t *context, int step) {
- int zoom;
+ gint zoom;
OsmGpsMap *map = OSM_GPS_MAP(context->widget);
g_object_get(map, "zoom", &zoom, NULL);
zoom = osm_gps_map_set_zoom(map, zoom+step);
@@ -88,6 +90,9 @@
/* enable/disable zoom buttons as required */
gtk_widget_set_sensitive(context->zoomin, zoom<17);
gtk_widget_set_sensitive(context->zoomout, zoom>1);
+
+ /* save new zoom */
+ context->appdata->map.zoom = zoom;
}
static gboolean
@@ -107,7 +112,7 @@
pos_t *refpos = get_pos(context->appdata);
if(refpos && !isnan(refpos->lat) && !isnan(refpos->lon)) {
osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),
- refpos->lat, refpos->lon, 14);
+ refpos->lat, refpos->lon, GPS_DEFAULT_ZOOM);
} else {
/* no coordinates given: display the entire world */
osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),
@@ -118,11 +123,10 @@
}
static GtkWidget
-*map_add_button(const gchar *icon, GCallback cb, gpointer data,
+*map_add_button(int icon, GCallback cb, gpointer data,
char *tooltip) {
GtkWidget *button = gtk_button_new();
- gtk_button_set_image(GTK_BUTTON(button),
- gtk_image_new_from_stock(icon, GTK_ICON_SIZE_BUTTON));
+ gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_MISC, icon));
g_signal_connect(button, "clicked", cb, data);
#ifndef USE_MAEMO
gtk_widget_set_tooltip_text(button, tooltip);
@@ -133,12 +137,22 @@
static gboolean map_gps_update(gpointer data) {
map_context_t *context = (map_context_t*)data;
+ /* get reference position ... */
pos_t *refpos = get_pos(context->appdata);
gboolean ok = (refpos!= NULL) && !isnan(refpos->lat) && !isnan(refpos->lon);
- /* get reference position and go there */
+ /* ... and enable "goto" button if it's valid */
gtk_widget_set_sensitive(context->gps, ok);
+ if(ok) {
+ float heading = context->appdata->use_gps?
+ gps_get_heading(context->appdata):NAN;
+
+ osm_gps_map_draw_gps(OSM_GPS_MAP(context->widget),
+ refpos->lat, refpos->lon, heading);
+ } else
+ osm_gps_map_clear_gps(OSM_GPS_MAP(context->widget));
+
return TRUE;
}
@@ -146,8 +160,31 @@
GdkEventConfigure *event,
map_context_t *context) {
- cb_map_gps(NULL, context);
+ /* set default values if they are invalid */
+ if(!context->appdata->map.zoom ||
+ isnan(context->appdata->map.pos.lat) ||
+ isnan(context->appdata->map.pos.lon)) {
+ printf("no valid map position found\n");
+
+ pos_t *refpos = get_pos(context->appdata);
+ if(refpos && !isnan(refpos->lat) && !isnan(refpos->lon)) {
+ /* use gps position if present */
+ context->appdata->map.pos = *refpos;
+ context->appdata->map.zoom = GPS_DEFAULT_ZOOM;
+ } else {
+ /* use world map otherwise */
+ context->appdata->map.pos.lat = 0.0;
+ context->appdata->map.pos.lon = 0.0;
+ context->appdata->map.zoom = 1;
+ }
+ }
+ /* jump to initial position */
+ osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),
+ context->appdata->map.pos.lat,
+ context->appdata->map.pos.lon,
+ context->appdata->map.zoom);
+
return FALSE;
}
@@ -169,13 +206,16 @@
GMainLoop *loop;
} popup_context_t;
+/* draw shape */
+#define ARROW_BORDER 20
+#define CORNER_RADIUS 10
-#ifndef USE_HILDON
+#ifndef USE_MAEMO
#define POPUP_WIDTH 300
#define POPUP_HEIGHT 100
#else
-#define POPUP_WIDTH 600
-#define POPUP_HEIGHT 200
+#define POPUP_WIDTH 350
+#define POPUP_HEIGHT 120
#endif
static gboolean
@@ -242,10 +282,6 @@
shutdown_loop(context);
}
-/* draw shape */
-#define ARROW_BORDER 20
-#define CORNER_RADIUS 10
-
static void popup_window_shape(GtkWidget *window, int tip_x, int tip_y) {
GdkBitmap *mask = gdk_pixmap_new(NULL, POPUP_WIDTH, POPUP_HEIGHT, 1);
@@ -269,24 +305,26 @@
gdk_gc_set_foreground(gc, &white);
gdk_gc_set_background(gc, &black);
+ /* the tip is always above or below the "bubble" but never at its side */
+ guint tip_offset = (tip_y == 0)?ARROW_BORDER:0;
+
gdk_draw_rectangle(mask, gc, TRUE,
- 0, ARROW_BORDER + CORNER_RADIUS,
+ 0, tip_offset + CORNER_RADIUS,
POPUP_WIDTH,
- POPUP_HEIGHT - 2*CORNER_RADIUS - 2*ARROW_BORDER);
+ POPUP_HEIGHT - 2*CORNER_RADIUS - ARROW_BORDER);
gdk_draw_rectangle(mask, gc, TRUE,
- CORNER_RADIUS, ARROW_BORDER,
+ CORNER_RADIUS, tip_offset,
POPUP_WIDTH - 2*CORNER_RADIUS,
- POPUP_HEIGHT - 2*ARROW_BORDER);
+ POPUP_HEIGHT - ARROW_BORDER);
int off[][2] = {
- { CORNER_RADIUS, ARROW_BORDER + CORNER_RADIUS },
- { POPUP_WIDTH - CORNER_RADIUS,
- ARROW_BORDER + CORNER_RADIUS },
+ { CORNER_RADIUS, tip_offset + CORNER_RADIUS },
+ { POPUP_WIDTH - CORNER_RADIUS, tip_offset + CORNER_RADIUS },
{ POPUP_WIDTH - CORNER_RADIUS,
- POPUP_HEIGHT - CORNER_RADIUS - ARROW_BORDER },
+ POPUP_HEIGHT - CORNER_RADIUS - ARROW_BORDER + tip_offset},
{ CORNER_RADIUS,
- POPUP_HEIGHT - CORNER_RADIUS - ARROW_BORDER}};
+ POPUP_HEIGHT - CORNER_RADIUS - ARROW_BORDER + tip_offset}};
int i;
for(i=0;i<4;i++) {
@@ -305,6 +343,38 @@
gdk_window_shape_combine_mask(window->window, mask, 0, 0);
}
+/* create a left aligned label (normal ones are centered) */
+static GtkWidget *gtk_label_left_new(char *str) {
+ GtkWidget *label = gtk_label_new(str);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.f, .5f);
+ return label;
+}
+
+/* the small labels are actually only on maemo small */
+#ifdef USE_MAEMO
+#define MARKUP_SMALL "%s"
+GtkWidget *gtk_label_small_left_new(char *str) {
+ GtkWidget *label = gtk_label_new("");
+ char *markup = g_markup_printf_escaped(MARKUP_SMALL, str);
+ gtk_label_set_markup(GTK_LABEL(label), markup);
+ g_free(markup);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.f, .5f);
+ return label;
+}
+#define gtk_label_big_left_new(a) gtk_label_left_new(a)
+#else
+#define gtk_label_small_left_new(a) gtk_label_left_new(a)
+#define MARKUP_BIG "%s"
+GtkWidget *gtk_label_big_left_new(char *str) {
+ GtkWidget *label = gtk_label_new("");
+ char *markup = g_markup_printf_escaped(MARKUP_BIG, str);
+ gtk_label_set_markup(GTK_LABEL(label), markup);
+ g_free(markup);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.f, .5f);
+ return label;
+}
+#endif
+
void cache_popup(map_context_t *mcontext, cache_t *cache) {
popup_context_t pcontext;
pcontext.appdata = mcontext->appdata;
@@ -345,15 +415,7 @@
cache->pos.lat, cache->pos.lon,
&sx, &sy);
- printf("screen pos %d/%d\n", sx, sy);
-
gdk_window_get_origin(mcontext->widget->window, &x, &y);
- printf("window = %d/%d +%d+%d %d*%d\n", x, y,
- mcontext->widget->allocation.x,
- mcontext->widget->allocation.y,
- mcontext->widget->allocation.width,
- mcontext->widget->allocation.height
- );
gint ax = 0, ay = 0;
if(sx > mcontext->widget->allocation.width/2)
@@ -362,7 +424,7 @@
if(sy > mcontext->widget->allocation.height/2)
ay = POPUP_HEIGHT;
-#if !defined(USE_HILDON) || (MAEMO_VERSION_MAJOR < 5)
+#if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
GdkColor color;
gdk_color_parse("darkgray", &color);
gtk_widget_modify_bg(GTK_WIDGET(pcontext.window), GTK_STATE_NORMAL, &color);
@@ -373,16 +435,64 @@
y + mcontext->widget->allocation.y + sy - ay);
- GtkWidget *frame = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
- gtk_container_set_border_width(GTK_CONTAINER(frame),
- ARROW_BORDER+CORNER_RADIUS);
- gtk_container_add(GTK_CONTAINER(frame),
- gtk_button_new_with_label(cache->name));
+ GtkWidget *alignment = gtk_alignment_new(0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
+ CORNER_RADIUS/2 + (ay?0:ARROW_BORDER),
+ CORNER_RADIUS/2 + (ay?ARROW_BORDER:0),
+ CORNER_RADIUS, CORNER_RADIUS);
+
+ /* --- actual content ---- */
+ GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(pcontext.window), frame);
+ if(cache->id) {
+ GtkWidget *ihbox = gtk_hbox_new(FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(ihbox),
+ icon_get_widget(ICON_CACHE_TYPE, cache->type),
+ FALSE, FALSE, 5);
+
+ gtk_box_pack_start_defaults(GTK_BOX(ihbox),
+ gtk_label_big_left_new(cache->id));
+
+ gtk_box_pack_start_defaults(GTK_BOX(vbox), ihbox);
+ }
+
+ if(cache->name) {
+ GtkWidget *label = gtk_label_small_left_new(cache->name);
+ gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
+ gtk_box_pack_start_defaults(GTK_BOX(vbox), label);
+ }
+
+ GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
+ if(cache->terrain) {
+ GtkWidget *ihbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(ihbox),
+ gtk_label_small_left_new(_("Terrain:")), FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(ihbox),
+ icon_get_widget(ICON_STARS, (int)(cache->terrain*2-2)),
+ FALSE, FALSE, 5);
+ gtk_box_pack_start_defaults(GTK_BOX(hbox), ihbox);
+ }
+
+ if(cache->difficulty) {
+ GtkWidget *ihbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(ihbox),
+ gtk_label_small_left_new(_("Difficulty:")), FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(ihbox),
+ icon_get_widget(ICON_STARS, (int)(cache->difficulty*2-2)),
+ FALSE, FALSE, 5);
+ gtk_box_pack_start_defaults(GTK_BOX(hbox), ihbox);
+ }
+
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(alignment), vbox);
+ /* ----------------------- */
+
+
+ gtk_container_add(GTK_CONTAINER(pcontext.window), alignment);
- /* --------- give the window its shape ----------- */
+ /* give window its shape */
popup_window_shape(pcontext.window, ax, ay);
gtk_widget_show_all(pcontext.window);
@@ -449,7 +559,7 @@
}
static int dist2pixel(map_context_t *context, float km, float lat) {
- int zoom;
+ gint zoom;
g_object_get(OSM_GPS_MAP(context->widget), "zoom", &zoom, NULL);
/* world at zoom 1 == 512 pixels */
@@ -459,7 +569,7 @@
return 1000.0*km/m_per_pix;
}
-#define CLICK_FUZZ (16)
+#define CLICK_FUZZ (24)
static gboolean
on_map_button_press_event(GtkWidget *widget,
@@ -488,9 +598,9 @@
static gboolean
on_map_button_release_event(GtkWidget *widget,
GdkEventButton *event, map_context_t *context) {
- if(context->press_on) {
- OsmGpsMap *map = OSM_GPS_MAP(context->widget);
+ OsmGpsMap *map = OSM_GPS_MAP(context->widget);
+ if(context->press_on) {
pos_t pos =
coord2pos(osm_gps_map_get_co_ordinates(map, event->x, event->y));
@@ -501,16 +611,36 @@
cache_popup(context, nearest);
}
context->press_on = NULL;
+ } else {
+ /* save new map position */
+ gfloat lat, lon;
+ g_object_get(map, "latitude", &lat, "longitude", &lon, NULL);
+ context->appdata->map.pos.lat = lat;
+ context->appdata->map.pos.lon = lon;
}
return FALSE;
}
+static void save_map_state(map_context_t *context) {
+ /* save map parameters */
+ OsmGpsMap *map = OSM_GPS_MAP(context->widget);
+ gint zoom;
+ g_object_get(map, "zoom", &zoom, NULL);
+ context->appdata->map.zoom = zoom;
+
+ gfloat lat, lon;
+ g_object_get(map, "latitude", &lat, "longitude", &lon, NULL);
+ context->appdata->map.pos.lat = lat;
+ context->appdata->map.pos.lon = lon;
+}
#if MAEMO_VERSION_MAJOR == 5
static void on_window_destroy(GtkWidget *widget, map_context_t *context) {
printf("destroy map view\n");
+ save_map_state(context);
+
/* restore cur_view */
context->appdata->cur_view = context->old_view;
@@ -529,11 +659,17 @@
const char *proxy = get_proxy_uri(appdata);
context->widget = g_object_new(OSM_TYPE_GPS_MAP,
- "repo-uri", MAP_SOURCE_OPENSTREETMAP,
- "tile-cache", path,
- proxy?"proxy-uri":NULL, proxy,
+ "repo-uri", MAP_SOURCE_OPENSTREETMAP,
+ "tile-cache", path,
+ "auto-center", FALSE,
+ "record-trip-history", FALSE,
+ "show-trip-history", FALSE,
NULL);
+ if(proxy)
+ g_object_set(OSM_GPS_MAP(context->widget),
+ "proxy-uri", proxy, NULL);
+
g_free(path);
char *name = NULL;
@@ -590,17 +726,17 @@
GtkWidget *vbox = gtk_vbox_new(FALSE,0);
context->zoomin =
- map_add_button(GTK_STOCK_ZOOM_IN, G_CALLBACK(cb_map_zoomin),
+ map_add_button(10, G_CALLBACK(cb_map_zoomin),
context, _("Zoom in"));
gtk_box_pack_start(GTK_BOX(vbox), context->zoomin, FALSE, FALSE, 0);
context->zoomout =
- map_add_button(GTK_STOCK_ZOOM_OUT, G_CALLBACK(cb_map_zoomout),
+ map_add_button(11, G_CALLBACK(cb_map_zoomout),
context, _("Zoom out"));
gtk_box_pack_start(GTK_BOX(vbox), context->zoomout, FALSE, FALSE, 0);
context->gps =
- map_add_button(GTK_STOCK_HOME, G_CALLBACK(cb_map_gps),
+ map_add_button(9, G_CALLBACK(cb_map_gps),
context, _("Jump to GPS position"));
gtk_widget_set_sensitive(context->gps, FALSE);
/* install handler for timed updates of the gps button */
@@ -625,6 +761,7 @@
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
gtk_widget_show_all(dialog);
gtk_dialog_run(GTK_DIALOG(dialog));
+ save_map_state(context);
gtk_timeout_remove(context->handler_id);
gtk_widget_destroy(dialog);
g_free(context);