Contents of /trunk/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 216 - (hide annotations)
Thu Nov 26 14:32:41 2009 UTC (14 years, 5 months ago) by harbaum
File MIME type: text/plain
File size: 23420 byte(s)
Picker test
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include <math.h>
21     #include <string.h>
22     #include <ctype.h>
23    
24 harbaum 77 #include <glib.h>
25     #include <glib/gstdio.h>
26    
27 harbaum 1 #include "gpxview.h"
28    
29 harbaum 190 #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
30     #include <hildon/hildon-entry.h>
31 harbaum 216 #include <hildon/hildon-touch-selector.h>
32     #include <hildon/hildon-picker-button.h>
33     #include <hildon/hildon-picker-dialog.h>
34 harbaum 190 #endif
35    
36 harbaum 1 char strlastchr(char *str) {
37     return str[strlen(str)]-1;
38     }
39    
40     /* make sure the entire path "dir" exists and create it if not */
41     int checkdir(char *dir) {
42     struct stat filestat;
43     char *p = dir, tmp;
44    
45     /* don't try to create root dir */
46     if(p[0] == '/') p++;
47    
48     do {
49     while(*p && *p != '/') p++;
50     tmp = *p;
51     *p = 0;
52    
53     int err = stat(dir, &filestat);
54     if(err) {
55     if(mkdir(dir, S_IRWXU) != 0) {
56     perror("mkdir()");
57     *p++ = tmp;
58     return -1;
59     }
60     } else {
61     if(!filestat.st_mode & S_IFDIR) {
62     printf("File %s exists and is _no_ directory\n", dir);
63     *p++ = tmp;
64     return -1;
65     }
66     }
67    
68     *p++ = tmp;
69     } while(tmp && strchr(p, '/'));
70    
71     return 0;
72     }
73    
74     void pos_lat_str(char *str, int len, float latitude) {
75     char *c = _("N");
76     float integral, fractional;
77    
78 harbaum 13 if(isnan(latitude))
79     str[0] = 0;
80     else {
81     if(latitude < 0) { latitude = fabs(latitude); c = _("S"); }
82     fractional = modff(latitude, &integral);
83 harbaum 1
84 harbaum 13 snprintf(str, len, "%s %02d° %06.3f'", c, (int)integral, fractional*60.0);
85     }
86 harbaum 1 }
87    
88     GtkWidget *pos_lat(float latitude, int size, int strikethrough) {
89     char str[32];
90    
91     pos_lat_str(str, sizeof(str), latitude);
92     return gtk_label_attrib(str, size, strikethrough);
93     }
94    
95     void pos_lon_str(char *str, int len, float longitude) {
96     char *c = _("E");
97     float integral, fractional;
98    
99 harbaum 13 if(isnan(longitude))
100     str[0] = 0;
101     else {
102     if(longitude < 0) { longitude = fabs(longitude); c = _("W"); }
103     fractional = modff(longitude, &integral);
104 harbaum 1
105 harbaum 13 snprintf(str, len, "%s %03d° %06.3f'", c, (int)integral, fractional*60.0);
106     }
107 harbaum 1 }
108    
109     GtkWidget *pos_lon(float longitude, int size, int strikethrough) {
110     char str[32];
111    
112     pos_lon_str(str, sizeof(str), longitude);
113     return gtk_label_attrib(str, size, strikethrough);
114     }
115    
116     float pos_parse_lat(char *str) {
117     int integral_int;
118     float fractional;
119     char c;
120    
121     if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
122     c = toupper(c);
123    
124     if(c != 'S' && c != 'N')
125     return NAN;
126    
127     /* prevent -0.0 */
128     if(!integral_int && (fractional == 0.0))
129     return 0.0;
130    
131     return ((c == 'S')?-1:+1) * (integral_int + fractional/60.0);
132     }
133    
134     return NAN;
135     }
136    
137     float pos_parse_lon(char *str) {
138     int integral_int;
139     float fractional;
140     char c;
141    
142     if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
143     c = toupper(c);
144    
145     /* O is german "Ost" for "East" */
146     if(c != 'E' && c != 'W' && c != 'O')
147     return NAN;
148    
149     /* prevent -0.0 */
150     if(!integral_int && (fractional == 0.0))
151     return 0.0;
152    
153     return ((c == 'W')?-1:+1) * (integral_int + fractional/60.0);
154     }
155    
156     return NAN;
157     }
158    
159     const char *pos_get_bearing_str(pos_t from, pos_t to) {
160     static const char *bear_str[]={
161 harbaum 185 "N", "NE", "E", "SE", "S", "SW", "W", "NW", "" };
162    
163     float bearing = gpx_pos_get_bearing(from, to);
164     if(!isnan(bearing)) {
165     int idx = (bearing+22.5)/45.0;
166     /* make sure we stay in icon bounds */
167     while(idx < 0) idx += 8;
168     while(idx > 7) idx -= 8;
169     return _(bear_str[idx]);
170     }
171    
172     return bear_str[8]; // empty string
173 harbaum 1 }
174    
175     /* the maemo font size is quite huge, so we adjust some fonts */
176     /* differently on maemo and non-maemo. Basically "BIG" does nothing */
177     /* on maemo and "SMALL" only does something on maemo */
178     #ifdef USE_MAEMO
179     #define MARKUP_SMALL "<span size='small'>%s</span>"
180     GtkWidget *gtk_label_small(char *str) {
181     GtkWidget *label = gtk_label_new("");
182     char *markup = g_markup_printf_escaped(MARKUP_SMALL, str);
183     gtk_label_set_markup(GTK_LABEL(label), markup);
184     g_free(markup);
185     return label;
186     }
187     #else
188     #define MARKUP_BIG "<span size='x-large'>%s</span>"
189     GtkWidget *gtk_label_big(char *str) {
190     GtkWidget *label = gtk_label_new("");
191     char *markup = g_markup_printf_escaped(MARKUP_BIG, str);
192     gtk_label_set_markup(GTK_LABEL(label), markup);
193     g_free(markup);
194     return label;
195     }
196     #endif
197    
198     void gtk_label_attrib_set(GtkWidget *label,
199     char *str, int size, int strikethrough) {
200     char format[80];
201    
202     snprintf(format, sizeof(format), "<span%s%s%s>%%s</span>",
203     #ifdef USE_MAEMO
204     (size==SIZE_SMALL)?" size='small'":"",
205     #else
206     (size==SIZE_BIG)?" size='x-large'":"",
207     #endif
208     strikethrough?" strikethrough='yes'":"",
209     (strikethrough==STRIKETHROUGH_RED)?" strikethrough_color='red'":"");
210    
211     char *markup = g_markup_printf_escaped(format, str);
212     // printf("markup = %s\n", markup);
213     gtk_label_set_markup(GTK_LABEL(label), markup);
214     g_free(markup);
215     }
216    
217     GtkWidget *gtk_label_attrib(char *str, int size, int strikethrough) {
218     GtkWidget *label = gtk_label_new("");
219     gtk_label_attrib_set(label, str, size, strikethrough);
220     return label;
221     }
222    
223     GtkWidget *gtk_button_attrib(char *str, int size, int strikethrough) {
224     GtkWidget *button = gtk_button_new_with_label("");
225     gtk_label_attrib_set(gtk_bin_get_child(GTK_BIN(button)),
226     str, size, strikethrough);
227     return button;
228     }
229    
230     void textbox_disable(GtkWidget *widget) {
231     gtk_editable_set_editable(GTK_EDITABLE(widget), FALSE);
232     gtk_widget_set_sensitive(widget, FALSE);
233     }
234    
235     void textbox_enable(GtkWidget *widget) {
236     gtk_widget_set_sensitive(widget, TRUE);
237     gtk_editable_set_editable(GTK_EDITABLE(widget), TRUE);
238     }
239    
240     pos_t *get_pos(appdata_t *appdata) {
241     pos_t *pos = &appdata->home;
242    
243     if(appdata->active_location) {
244     int i = appdata->active_location-1;
245     location_t *loc = appdata->location;
246     while(i--) loc = loc->next;
247     pos = &loc->pos;
248     }
249    
250     if(appdata->use_gps) {
251     pos = gps_get_pos(appdata);
252    
253     if(!pos) pos = &appdata->gps; /* use saved position */
254     else appdata->gps = *pos; /* save position */
255     }
256     return pos;
257     }
258    
259     void distance_str(char *str, int len, float dist, gboolean imperial) {
260 harbaum 34 if(isnan(dist))
261     snprintf(str, len, "---");
262     else if(imperial) {
263 harbaum 1 /* 1 mil = 1760 yd = 5280 ft ... */
264     if(dist<0.018) snprintf(str, len, "%.1f ft", dist*5280.0);
265     else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0);
266     else if(dist<0.55) snprintf(str, len, "%.0f yd", dist*1760.0);
267     else if(dist<10.0) snprintf(str, len, "%.2f mi", dist);
268     else if(dist<100.0) snprintf(str, len, "%.1f mi", dist);
269     else snprintf(str, len, "%.0f mi", dist);
270     } else {
271     if(dist<0.01) snprintf(str, len, "%.2f m", dist*1000.0);
272     else if(dist<0.1) snprintf(str, len, "%.1f m", dist*1000.0);
273     else if(dist<1.0) snprintf(str, len, "%.0f m", dist*1000.0);
274     else if(dist<100.0) snprintf(str, len, "%.1f km", dist);
275     else snprintf(str, len, "%.0f km", dist);
276     }
277     }
278    
279     /* return distance in miles or kilometers */
280     float distance_parse(char *str, gboolean imperial) {
281     char unit[4];
282     float val = NAN;
283    
284     if(sscanf(str, "%f %3s", &val, unit) == 2) {
285     gboolean fimp = FALSE;
286    
287     if(strcasecmp(unit, "ft") == 0) { fimp = TRUE; val /= 5280.0; }
288     else if(strcasecmp(unit, "yd") == 0) { fimp = TRUE; val /= 1760.0; }
289     else if(strcasecmp(unit, "mi") == 0) { fimp = TRUE; }
290     else if(strcasecmp(unit, "m") == 0) { fimp = FALSE; val /= 1000.0; }
291     else if(strcasecmp(unit, "km") == 0) { fimp = FALSE; }
292     else val = NAN;
293    
294     /* found imperial and metric requested? convert miles into kilometers */
295     if(fimp & !imperial) val *= 1.609344;
296    
297     /* found metric and imperial requested? convert kilometers into miles */
298     if(!fimp & imperial) val /= 1.609344;
299     }
300     return val;
301     }
302    
303     static gboolean mark(GtkWidget *widget, gboolean valid) {
304     gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);
305     return valid;
306     }
307    
308     static void callback_modified_lat(GtkWidget *widget, gpointer data ) {
309     float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
310     mark(widget, !isnan(i));
311     }
312    
313     /* a entry that is colored red when being "active" */
314     GtkWidget *lat_entry_new(float lat) {
315     GdkColor color;
316 harbaum 190
317 harbaum 212 GtkWidget *widget = entry_new();
318 harbaum 1 gdk_color_parse("#ff0000", &color);
319     gtk_widget_modify_text(widget, TAG_STATE, &color);
320    
321     char str[32];
322     pos_lat_str(str, sizeof(str), lat);
323     gtk_entry_set_text(GTK_ENTRY(widget), str);
324    
325     g_signal_connect(G_OBJECT(widget), "changed",
326     G_CALLBACK(callback_modified_lat), NULL);
327    
328     return widget;
329     }
330    
331     static void callback_modified_lon(GtkWidget *widget, gpointer data ) {
332     float i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
333     mark(widget, !isnan(i));
334     }
335    
336     /* a entry that is colored red when filled with invalid coordinate */
337     GtkWidget *lon_entry_new(float lon) {
338     GdkColor color;
339 harbaum 190
340 harbaum 212 GtkWidget *widget = entry_new();
341 harbaum 190 // gtk_entry_set_width_chars(GTK_ENTRY(widget), 14);
342    
343 harbaum 1 gdk_color_parse("#ff0000", &color);
344     gtk_widget_modify_text(widget, TAG_STATE, &color);
345    
346     char str[32];
347     pos_lon_str(str, sizeof(str), lon);
348     gtk_entry_set_text(GTK_ENTRY(widget), str);
349    
350     g_signal_connect(G_OBJECT(widget), "changed",
351     G_CALLBACK(callback_modified_lon), NULL);
352    
353     return widget;
354     }
355    
356    
357     float lat_get(GtkWidget *widget) {
358     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
359     return pos_parse_lat(p);
360     }
361    
362     float lon_get(GtkWidget *widget) {
363     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
364     return pos_parse_lon(p);
365     }
366    
367     static void callback_modified_dist(GtkWidget *widget, gpointer data ) {
368     /* don't care for metric/imperial since we only want to know if this */
369     /* is parseable at all */
370     float i = distance_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);
371     mark(widget, !isnan(i));
372     }
373    
374     /* a entry that is colored red when filled with invalid distance */
375     GtkWidget *dist_entry_new(float dist, gboolean mil) {
376     GdkColor color;
377 harbaum 212 GtkWidget *widget = entry_new();
378 harbaum 1 gdk_color_parse("#ff0000", &color);
379     gtk_widget_modify_text(widget, TAG_STATE, &color);
380    
381     char str[32];
382     distance_str(str, sizeof(str), dist, mil);
383     gtk_entry_set_text(GTK_ENTRY(widget), str);
384    
385     g_signal_connect(G_OBJECT(widget), "changed",
386     G_CALLBACK(callback_modified_dist), NULL);
387    
388     return widget;
389     }
390    
391     float dist_get(GtkWidget *widget, gboolean mil) {
392     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
393     return distance_parse(p, mil);
394     }
395    
396     #ifndef USE_MAEMO
397     #ifdef ENABLE_BROWSER_INTERFACE
398     #include <libgnome/gnome-url.h>
399    
400     int browser_url(appdata_t *appdata, char *url) {
401     /* taken from gnome-open, part of libgnome */
402     GError *err = NULL;
403     gnome_url_show(url, &err);
404     return 0;
405     }
406     #endif
407     #endif
408 harbaum 77
409     /* recursively remove an entire file system */
410     void rmdir_recursive(char *path) {
411     GDir *dir = g_dir_open(path, 0, NULL);
412     if(dir) {
413     const char *name = g_dir_read_name(dir);
414     while(name) {
415     char *fullname = g_strdup_printf("%s/%s", path, name);
416     // printf("deleting %s\n", fullname);
417    
418     if(g_file_test(fullname, G_FILE_TEST_IS_DIR))
419     rmdir_recursive(fullname);
420     else if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR))
421     g_remove(fullname);
422    
423     g_free(fullname);
424     name = g_dir_read_name(dir);
425     }
426    
427     g_dir_close(dir);
428     }
429     g_rmdir(path);
430     }
431    
432 harbaum 137 #ifdef ENABLE_BROWSER_INTERFACE
433     static void on_link_clicked(GtkButton *button, gpointer data) {
434     appdata_t *appdata = (appdata_t*)data;
435     char *url = g_object_get_data(G_OBJECT(button), "url");
436     if(url) browser_url(appdata, url);
437     }
438     #endif
439    
440     /* a button containing a weblink */
441     GtkWidget *link_button_attrib(appdata_t *appdata, char *str, char *url,
442     int size, int strikethrough) {
443    
444     #ifdef ENABLE_BROWSER_INTERFACE
445     if(url) {
446     GtkWidget *button = gtk_button_attrib(str, size, strikethrough);
447     g_object_set_data(G_OBJECT(button), "url", url);
448     gtk_signal_connect(GTK_OBJECT(button), "clicked",
449     (GtkSignalFunc)on_link_clicked, appdata);
450    
451     return button;
452     }
453     #endif
454     return gtk_label_attrib(str, size, strikethrough);
455     }
456    
457     #ifdef ENABLE_BROWSER_INTERFACE
458     static void on_link_id_clicked(GtkButton *button, gpointer data) {
459     appdata_t *appdata = (appdata_t*)data;
460    
461     unsigned int id = (unsigned int)g_object_get_data(G_OBJECT(button), "id");
462     char *type = g_object_get_data(G_OBJECT(button), "type");
463    
464     char *url = g_strdup_printf("http://www.geocaching.com/%s?id=%u",
465     type, id);
466    
467     if(url) {
468     browser_url(appdata, url);
469     g_free(url);
470     }
471     }
472     #endif
473    
474     GtkWidget *link_button_by_id(appdata_t *appdata, char *str,
475     const char *type, int id) {
476    
477     #ifdef ENABLE_BROWSER_INTERFACE
478     if(id) {
479     GtkWidget *ref = gtk_button_new_with_label(str);
480     #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
481     // hildon_gtk_widget_set_theme_size(ref,
482     // (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
483     #endif
484     g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
485     g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
486     gtk_signal_connect(GTK_OBJECT(ref), "clicked",
487     GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
488    
489     return ref;
490     }
491     #endif
492     return gtk_label_new(str);
493     }
494    
495 harbaum 138
496     GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon,
497     const char *type, int id) {
498    
499     #ifdef ENABLE_BROWSER_INTERFACE
500     if(id) {
501     GtkWidget *ref = gtk_button_new();
502     gtk_button_set_image(GTK_BUTTON(ref), icon);
503    
504     #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
505     // hildon_gtk_widget_set_theme_size(ref,
506     // (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
507     #endif
508     g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
509     g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
510     gtk_signal_connect(GTK_OBJECT(ref), "clicked",
511     GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
512    
513     return ref;
514     }
515     #endif
516     return icon;
517     }
518    
519 harbaum 165 /* left aligned, word wrapped multiline widget */
520     GtkWidget *simple_text_widget(char *text) {
521     GtkWidget *label = gtk_label_new(text);
522    
523     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
524     gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD);
525     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
526    
527     return label;
528     }
529 harbaum 198
530    
531     /* a label that is left aligned */
532     GtkWidget *left_label_new(char *str) {
533     GtkWidget *widget = gtk_label_new(str);
534     gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f);
535     return widget;
536     }
537 harbaum 212
538     static void pos_set(GtkMenuItem *item, float lat, float lon) {
539     char str[32];
540    
541     pos_lat_str(str, sizeof(str)-1, lat);
542     GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
543     gtk_entry_set_text(GTK_ENTRY(lat_entry), str);
544    
545     pos_lon_str(str, sizeof(str)-1, lon);
546     GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
547     gtk_entry_set_text(GTK_ENTRY(lon_entry), str);
548     }
549    
550     static void cb_gps(GtkMenuItem *item, gpointer data) {
551     appdata_t *appdata = (appdata_t*)data;
552    
553     pos_t *refpos = get_pos(appdata);
554     if(!refpos) pos_set(item, NAN, NAN);
555     else pos_set(item, refpos->lat, refpos->lon);
556     }
557    
558     static void cb_geomath(GtkMenuItem *item, gpointer data) {
559     appdata_t *appdata = (appdata_t*)data;
560    
561     pos_set(item, appdata->geomath.lat, appdata->geomath.lon);
562     }
563    
564     #ifdef ENABLE_OSM_GPS_MAP
565     static void cb_map(GtkMenuItem *item, gpointer data) {
566     appdata_t *appdata = (appdata_t*)data;
567    
568     pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon);
569     }
570     #endif
571    
572     static const gchar *menu_item_get_label(GtkMenuItem *menu_item) {
573     GList *children, *l;
574     GtkWidget *child;
575     children = gtk_container_get_children (GTK_CONTAINER (menu_item));
576     for (l = g_list_first (children); l != NULL;
577     l = g_list_next (l)) {
578     child = (GtkWidget *)l->data;
579     if (GTK_IS_LABEL (child)) {
580     return gtk_label_get_label (GTK_LABEL (child));
581     }
582     }
583     return NULL;
584     }
585    
586     static void cb_cache(GtkMenuItem *item, gpointer data) {
587     const char *label = menu_item_get_label(item);
588     appdata_t *appdata = (appdata_t*)data;
589    
590     cache_t *cache = appdata->cur_cache;
591     g_assert(cache);
592    
593     if(!strcmp(label, cache->id))
594     pos_set(item, cache->pos.lat, cache->pos.lon);
595     else {
596     wpt_t *wpt = cache->wpt;
597     while(wpt) {
598     if(!strcmp(label, wpt->id)) {
599     pos_set(item, wpt->pos.lat, wpt->pos.lon);
600     return;
601     }
602    
603     wpt = wpt->next;
604     }
605     }
606     }
607    
608     static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata,
609     GtkWidget *icon, char *menu_str,
610     void(*func)(GtkMenuItem*, gpointer),
611     GtkWidget *lon_entry, GtkWidget *lat_entry) {
612    
613     GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str);
614    
615     if(icon)
616     gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
617    
618     g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry);
619     g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry);
620    
621     if(func)
622     gtk_signal_connect(GTK_OBJECT(item), "activate",
623     (GtkSignalFunc)func, appdata);
624    
625     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
626    
627     return item;
628     }
629    
630     static GtkWidget *popup_menu_create(appdata_t *appdata,
631     GtkWidget *lat_entry, GtkWidget *lon_entry) {
632     GtkWidget *menu = gtk_menu_new();
633    
634 harbaum 214 menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),
635 harbaum 213 _("Current position (GPS)"), cb_gps, lon_entry, lat_entry);
636 harbaum 215 menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),
637     _("Geomath projection"), cb_geomath, lon_entry, lat_entry);
638 harbaum 212 #ifdef ENABLE_OSM_GPS_MAP
639 harbaum 215 menu_add(menu, appdata, icon_get_widget(ICON_POS, 20),
640     _("Map position"), cb_map, lon_entry, lat_entry);
641 harbaum 212 #endif
642 harbaum 214
643     printf("popup cache present: %s\n", appdata->cur_cache?"Yes":"No");
644 harbaum 212
645     if(appdata->cur_cache) {
646     cache_t *cache = appdata->cur_cache;
647    
648     if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {
649 harbaum 214 menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
650 harbaum 212 cache->id, cb_cache, lon_entry, lat_entry);
651     }
652    
653     printf("appending cache waypoints\n");
654     wpt_t *wpt = cache->wpt;
655     while(wpt) {
656     GtkWidget *icon = NULL;
657     if(wpt->sym != WPT_SYM_UNKNOWN)
658 harbaum 213 icon = icon_get_widget(ICON_POS, wpt->sym);
659 harbaum 212
660     menu_add(menu, appdata, icon, wpt->id, cb_cache,
661     lon_entry, lat_entry);
662    
663     wpt = wpt->next;
664     }
665     }
666    
667     gtk_widget_show_all(menu);
668    
669     return menu;
670     }
671    
672     static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
673     gpointer data) {
674    
675     if(event->type == GDK_BUTTON_PRESS) {
676     GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
677    
678     /* draw a popup menu */
679     gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
680     event->button, event->time);
681     return TRUE;
682     }
683     return FALSE;
684     }
685    
686     static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
687     GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
688     gtk_widget_destroy(menu);
689     }
690    
691     GtkWidget *coo_popup(appdata_t *appdata,
692     GtkWidget *lat_entry, GtkWidget *lon_entry) {
693    
694     GtkWidget *button = gtk_button_new();
695     #ifdef FREMANTLE
696     hildon_gtk_widget_set_theme_size(button,
697     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
698     #endif
699    
700 harbaum 214 gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
701 harbaum 212
702     gtk_widget_set_tooltip_text(button, _("Preset coordinates"));
703    
704     gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
705     (GtkSignalFunc)on_popup_button_press, appdata);
706    
707     gtk_signal_connect(GTK_OBJECT(button), "destroy",
708     (GtkSignalFunc)on_popup_destroy, appdata);
709    
710     g_object_set_data(G_OBJECT(button), "menu",
711     popup_menu_create(appdata, lat_entry, lon_entry));
712    
713     return button;
714     }
715    
716     GtkWidget *entry_new(void) {
717     #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
718     return gtk_entry_new();
719     #else
720     return hildon_entry_new(HILDON_SIZE_AUTO);
721     #endif
722     }
723 harbaum 214
724     gboolean pos_differ(pos_t *pos1, pos_t *pos2) {
725     int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;
726     int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;
727    
728     return((lat1 != lat2) || (lon1 != lon2));
729     }
730 harbaum 216
731     #ifdef FREMANTLE
732     void selection_changed (HildonTouchSelector * selector,
733     gpointer *user_data) {
734     gchar *current_selection = NULL;
735    
736     current_selection = hildon_touch_selector_get_current_text (selector);
737     g_debug ("Current selection : %s", current_selection);
738     }
739    
740     static GtkWidget *create_customized_selector() {
741     GtkWidget *selector = NULL;
742     GSList *icon_list = NULL;
743     GtkListStore *store_icons = NULL;
744     GSList *item = NULL;
745     GtkCellRenderer *renderer = NULL;
746     HildonTouchSelectorColumn *column = NULL;
747    
748     selector = hildon_touch_selector_new ();
749    
750     icon_list = gtk_stock_list_ids ();
751    
752     store_icons = gtk_list_store_new (1, G_TYPE_STRING);
753     for (item = icon_list; item; item = g_slist_next (item)) {
754     GtkTreeIter iter;
755     gchar *label = item->data;
756    
757     gtk_list_store_append (store_icons, &iter);
758     gtk_list_store_set (store_icons, &iter, 0, label, -1);
759     g_free (label);
760     }
761     g_slist_free (icon_list);
762    
763     renderer = gtk_cell_renderer_pixbuf_new ();
764     gtk_cell_renderer_set_fixed_size (renderer, -1, 100);
765    
766     column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector),
767     GTK_TREE_MODEL (store_icons),
768     renderer, "stock-id", 0, NULL);
769    
770     g_object_set (G_OBJECT (column), "text-column", 0, NULL);
771    
772     hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
773     HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
774    
775    
776     g_signal_connect (G_OBJECT (selector), "changed",
777     G_CALLBACK (selection_changed), NULL);
778    
779     return selector;
780     }
781    
782     static gint on_picker_request(GtkWidget *button, GdkEventButton *event,
783     gpointer data) {
784    
785     if(event->type == GDK_BUTTON_PRESS) {
786     GtkWidget *dialog = hildon_picker_dialog_new(NULL);
787     GtkWidget *selector = create_customized_selector();
788     hildon_picker_dialog_set_selector(HILDON_PICKER_DIALOG(dialog),
789     HILDON_TOUCH_SELECTOR(selector));
790    
791     hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR (selector), 1, -1);
792    
793     gtk_widget_show_all(dialog);
794     gtk_dialog_run(GTK_DIALOG(dialog));
795     gtk_widget_destroy(dialog);
796    
797     return TRUE;
798     }
799     return FALSE;
800     }
801    
802     GtkWidget *picker_button_new(void) {
803     GtkWidget *button;
804    
805     #if 1
806     button = gtk_button_new();
807     hildon_gtk_widget_set_theme_size(button,
808     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
809    
810     gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
811    
812     gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
813     (GtkSignalFunc)on_picker_request, NULL);
814    
815     #else
816     button = hildon_picker_button_new(HILDON_SIZE_AUTO,
817     HILDON_BUTTON_ARRANGEMENT_VERTICAL);
818    
819     hildon_button_set_title(HILDON_BUTTON(button), "Test");
820     hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(button),
821     HILDON_TOUCH_SELECTOR(create_customized_selector()));
822     #endif
823    
824     return button;
825     }
826     #endif