Contents of /trunk/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 228 - (hide annotations)
Thu Dec 3 20:07:13 2009 UTC (14 years, 5 months ago) by harbaum
File MIME type: text/plain
File size: 50112 byte(s)
Various small bug fixes
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 harbaum 223 /* TODO:
21     */
22    
23 harbaum 1 #include <math.h>
24     #include <string.h>
25     #include <ctype.h>
26    
27 harbaum 77 #include <glib.h>
28     #include <glib/gstdio.h>
29    
30 harbaum 1 #include "gpxview.h"
31    
32 harbaum 190 #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
33     #include <hildon/hildon-entry.h>
34 harbaum 216 #include <hildon/hildon-touch-selector.h>
35     #include <hildon/hildon-picker-button.h>
36     #include <hildon/hildon-picker-dialog.h>
37 harbaum 190 #endif
38    
39 harbaum 221 float roundf(float x);
40    
41 harbaum 223 /* Enable special fremantle UI elements. These particular widgets */
42     /* don't use any hildon/fremantle specific parts and can thus even */
43     /* be used under plain gtk. This is mainly for testing and developemt */
44 harbaum 217 #ifdef FREMANTLE
45 harbaum 221 #define PRESET_PICKER_DIALOG
46     #define COORDINATE_PICKER
47 harbaum 217 #endif
48    
49 harbaum 1 char strlastchr(char *str) {
50     return str[strlen(str)]-1;
51     }
52    
53     /* make sure the entire path "dir" exists and create it if not */
54     int checkdir(char *dir) {
55     struct stat filestat;
56     char *p = dir, tmp;
57    
58     /* don't try to create root dir */
59     if(p[0] == '/') p++;
60    
61     do {
62     while(*p && *p != '/') p++;
63     tmp = *p;
64     *p = 0;
65    
66     int err = stat(dir, &filestat);
67     if(err) {
68     if(mkdir(dir, S_IRWXU) != 0) {
69     perror("mkdir()");
70     *p++ = tmp;
71     return -1;
72     }
73     } else {
74     if(!filestat.st_mode & S_IFDIR) {
75     printf("File %s exists and is _no_ directory\n", dir);
76     *p++ = tmp;
77     return -1;
78     }
79     }
80    
81     *p++ = tmp;
82     } while(tmp && strchr(p, '/'));
83    
84     return 0;
85     }
86    
87     void pos_lat_str(char *str, int len, float latitude) {
88     char *c = _("N");
89     float integral, fractional;
90    
91 harbaum 13 if(isnan(latitude))
92     str[0] = 0;
93     else {
94     if(latitude < 0) { latitude = fabs(latitude); c = _("S"); }
95     fractional = modff(latitude, &integral);
96 harbaum 1
97 harbaum 13 snprintf(str, len, "%s %02d° %06.3f'", c, (int)integral, fractional*60.0);
98     }
99 harbaum 1 }
100    
101     GtkWidget *pos_lat(float latitude, int size, int strikethrough) {
102     char str[32];
103    
104     pos_lat_str(str, sizeof(str), latitude);
105     return gtk_label_attrib(str, size, strikethrough);
106     }
107    
108     void pos_lon_str(char *str, int len, float longitude) {
109     char *c = _("E");
110     float integral, fractional;
111    
112 harbaum 13 if(isnan(longitude))
113     str[0] = 0;
114     else {
115     if(longitude < 0) { longitude = fabs(longitude); c = _("W"); }
116     fractional = modff(longitude, &integral);
117 harbaum 1
118 harbaum 13 snprintf(str, len, "%s %03d° %06.3f'", c, (int)integral, fractional*60.0);
119     }
120 harbaum 1 }
121    
122     GtkWidget *pos_lon(float longitude, int size, int strikethrough) {
123     char str[32];
124    
125     pos_lon_str(str, sizeof(str), longitude);
126     return gtk_label_attrib(str, size, strikethrough);
127     }
128    
129     float pos_parse_lat(char *str) {
130     int integral_int;
131     float fractional;
132     char c;
133    
134     if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
135     c = toupper(c);
136    
137     if(c != 'S' && c != 'N')
138     return NAN;
139    
140     /* prevent -0.0 */
141     if(!integral_int && (fractional == 0.0))
142     return 0.0;
143    
144     return ((c == 'S')?-1:+1) * (integral_int + fractional/60.0);
145     }
146    
147     return NAN;
148     }
149    
150     float pos_parse_lon(char *str) {
151     int integral_int;
152     float fractional;
153     char c;
154    
155     if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
156     c = toupper(c);
157    
158     /* O is german "Ost" for "East" */
159     if(c != 'E' && c != 'W' && c != 'O')
160     return NAN;
161    
162     /* prevent -0.0 */
163     if(!integral_int && (fractional == 0.0))
164     return 0.0;
165    
166     return ((c == 'W')?-1:+1) * (integral_int + fractional/60.0);
167     }
168    
169     return NAN;
170     }
171    
172     const char *pos_get_bearing_str(pos_t from, pos_t to) {
173     static const char *bear_str[]={
174 harbaum 185 "N", "NE", "E", "SE", "S", "SW", "W", "NW", "" };
175    
176     float bearing = gpx_pos_get_bearing(from, to);
177     if(!isnan(bearing)) {
178     int idx = (bearing+22.5)/45.0;
179     /* make sure we stay in icon bounds */
180     while(idx < 0) idx += 8;
181     while(idx > 7) idx -= 8;
182     return _(bear_str[idx]);
183     }
184    
185     return bear_str[8]; // empty string
186 harbaum 1 }
187    
188     /* the maemo font size is quite huge, so we adjust some fonts */
189     /* differently on maemo and non-maemo. Basically "BIG" does nothing */
190     /* on maemo and "SMALL" only does something on maemo */
191     #ifdef USE_MAEMO
192     #define MARKUP_SMALL "<span size='small'>%s</span>"
193     GtkWidget *gtk_label_small(char *str) {
194     GtkWidget *label = gtk_label_new("");
195     char *markup = g_markup_printf_escaped(MARKUP_SMALL, str);
196     gtk_label_set_markup(GTK_LABEL(label), markup);
197     g_free(markup);
198     return label;
199     }
200     #else
201     #define MARKUP_BIG "<span size='x-large'>%s</span>"
202     GtkWidget *gtk_label_big(char *str) {
203     GtkWidget *label = gtk_label_new("");
204     char *markup = g_markup_printf_escaped(MARKUP_BIG, str);
205     gtk_label_set_markup(GTK_LABEL(label), markup);
206     g_free(markup);
207     return label;
208     }
209     #endif
210    
211     void gtk_label_attrib_set(GtkWidget *label,
212     char *str, int size, int strikethrough) {
213     char format[80];
214    
215     snprintf(format, sizeof(format), "<span%s%s%s>%%s</span>",
216     #ifdef USE_MAEMO
217     (size==SIZE_SMALL)?" size='small'":"",
218     #else
219     (size==SIZE_BIG)?" size='x-large'":"",
220     #endif
221     strikethrough?" strikethrough='yes'":"",
222     (strikethrough==STRIKETHROUGH_RED)?" strikethrough_color='red'":"");
223    
224     char *markup = g_markup_printf_escaped(format, str);
225     // printf("markup = %s\n", markup);
226     gtk_label_set_markup(GTK_LABEL(label), markup);
227     g_free(markup);
228     }
229    
230     GtkWidget *gtk_label_attrib(char *str, int size, int strikethrough) {
231     GtkWidget *label = gtk_label_new("");
232     gtk_label_attrib_set(label, str, size, strikethrough);
233     return label;
234     }
235    
236     GtkWidget *gtk_button_attrib(char *str, int size, int strikethrough) {
237     GtkWidget *button = gtk_button_new_with_label("");
238     gtk_label_attrib_set(gtk_bin_get_child(GTK_BIN(button)),
239     str, size, strikethrough);
240     return button;
241     }
242    
243     void textbox_disable(GtkWidget *widget) {
244     gtk_editable_set_editable(GTK_EDITABLE(widget), FALSE);
245     gtk_widget_set_sensitive(widget, FALSE);
246     }
247    
248     void textbox_enable(GtkWidget *widget) {
249     gtk_widget_set_sensitive(widget, TRUE);
250     gtk_editable_set_editable(GTK_EDITABLE(widget), TRUE);
251     }
252    
253     pos_t *get_pos(appdata_t *appdata) {
254     pos_t *pos = &appdata->home;
255    
256     if(appdata->active_location) {
257     int i = appdata->active_location-1;
258     location_t *loc = appdata->location;
259     while(i--) loc = loc->next;
260     pos = &loc->pos;
261     }
262    
263     if(appdata->use_gps) {
264     pos = gps_get_pos(appdata);
265    
266     if(!pos) pos = &appdata->gps; /* use saved position */
267     else appdata->gps = *pos; /* save position */
268     }
269     return pos;
270     }
271    
272     void distance_str(char *str, int len, float dist, gboolean imperial) {
273 harbaum 34 if(isnan(dist))
274     snprintf(str, len, "---");
275     else if(imperial) {
276 harbaum 1 /* 1 mil = 1760 yd = 5280 ft ... */
277     if(dist<0.018) snprintf(str, len, "%.1f ft", dist*5280.0);
278     else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0);
279     else if(dist<0.55) snprintf(str, len, "%.0f yd", dist*1760.0);
280     else if(dist<10.0) snprintf(str, len, "%.2f mi", dist);
281     else if(dist<100.0) snprintf(str, len, "%.1f mi", dist);
282     else snprintf(str, len, "%.0f mi", dist);
283     } else {
284     if(dist<0.01) snprintf(str, len, "%.2f m", dist*1000.0);
285     else if(dist<0.1) snprintf(str, len, "%.1f m", dist*1000.0);
286     else if(dist<1.0) snprintf(str, len, "%.0f m", dist*1000.0);
287     else if(dist<100.0) snprintf(str, len, "%.1f km", dist);
288     else snprintf(str, len, "%.0f km", dist);
289     }
290     }
291    
292     /* return distance in miles or kilometers */
293     float distance_parse(char *str, gboolean imperial) {
294     char unit[4];
295     float val = NAN;
296    
297     if(sscanf(str, "%f %3s", &val, unit) == 2) {
298     gboolean fimp = FALSE;
299    
300     if(strcasecmp(unit, "ft") == 0) { fimp = TRUE; val /= 5280.0; }
301     else if(strcasecmp(unit, "yd") == 0) { fimp = TRUE; val /= 1760.0; }
302     else if(strcasecmp(unit, "mi") == 0) { fimp = TRUE; }
303     else if(strcasecmp(unit, "m") == 0) { fimp = FALSE; val /= 1000.0; }
304     else if(strcasecmp(unit, "km") == 0) { fimp = FALSE; }
305     else val = NAN;
306    
307     /* found imperial and metric requested? convert miles into kilometers */
308     if(fimp & !imperial) val *= 1.609344;
309    
310     /* found metric and imperial requested? convert kilometers into miles */
311     if(!fimp & imperial) val /= 1.609344;
312     }
313     return val;
314     }
315    
316 harbaum 221 /* ------------------ coordinate picker tool --------------------------- */
317    
318 harbaum 223 #ifndef COORDINATE_PICKER
319 harbaum 1 static gboolean mark(GtkWidget *widget, gboolean valid) {
320     gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);
321     return valid;
322     }
323    
324 harbaum 226 GtkWidget *red_entry_new_with_text(char *str) {
325 harbaum 223 GdkColor color;
326    
327     GtkWidget *widget = entry_new();
328     gdk_color_parse("#ff0000", &color);
329     gtk_widget_modify_text(widget, TAG_STATE, &color);
330 harbaum 226 if(str) gtk_entry_set_text(GTK_ENTRY(widget), str);
331    
332 harbaum 223 return widget;
333     }
334    
335 harbaum 1 static void callback_modified_lat(GtkWidget *widget, gpointer data ) {
336     float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
337     mark(widget, !isnan(i));
338     }
339 harbaum 221 #else
340 harbaum 223 static void picker_center_iter(GtkWidget *view, GtkTreeIter *iter) {
341     /* select new iter */
342     GtkTreeSelection *selection =
343     gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
344     GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
345     gtk_tree_selection_select_iter(selection, iter);
346     GtkTreePath *path =
347     gtk_tree_model_get_path(model, iter);
348     gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view),
349     path, NULL, TRUE, 0.5, 0.5);
350     gtk_tree_path_free(path);
351     }
352    
353     static void on_picker_activated(GtkTreeView *treeview,
354     GtkTreePath *path,
355     GtkTreeViewColumn *col,
356     gpointer userdata) {
357     gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeview),
358     path, NULL, TRUE, 0.5, 0.5);
359     }
360    
361     #define DUMMY_NUM 1
362    
363     static void dummy_append(GtkListStore *store, int n) {
364     GtkTreeIter iter;
365    
366     while(n--) {
367     gtk_list_store_append (store, &iter);
368     gtk_list_store_set(store, &iter, 0, "", 1, -1, 2, FALSE, -1);
369     }
370     }
371    
372     static GtkWidget *string_picker_create(const char *str[], int sel) {
373 harbaum 221 #ifndef FREMANTLE
374     GtkWidget *view = gtk_tree_view_new();
375     #else
376     GtkWidget *view = hildon_gtk_tree_view_new(HILDON_UI_MODE_EDIT);
377     #endif
378 harbaum 1
379 harbaum 221 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
380     GtkTreeSelection *selection =
381     gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
382    
383     /* --- "char" column --- */
384     GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
385     g_object_set(renderer, "xalign", 0.5, NULL );
386     gtk_tree_view_insert_column_with_attributes(
387 harbaum 223 GTK_TREE_VIEW(view), -1, "str", renderer,
388     "text", 0,
389     "sensitive", 2,
390     NULL);
391 harbaum 221
392 harbaum 223 GtkListStore *store =
393     gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN);
394 harbaum 221
395 harbaum 223 dummy_append(store, DUMMY_NUM);
396 harbaum 221
397 harbaum 223 /* add strings */
398     GtkTreeIter iter, siter;
399     int i;
400     for(i=0;*str;str++,i++) {
401     gtk_list_store_append (store, &iter);
402     gtk_list_store_set(store, &iter, 0, _(*str), 1, i, 2, TRUE, -1);
403     if(i == sel) siter = iter;
404     }
405    
406     dummy_append(store, DUMMY_NUM);
407    
408 harbaum 221 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
409     g_object_unref(store);
410    
411 harbaum 223 #ifndef FREMANTLE
412     g_signal_connect(view, "row-activated",
413     (GCallback)on_picker_activated, NULL);
414     #else
415     g_signal_connect(view, "hildon-row-tapped",
416     (GCallback)on_picker_activated, NULL);
417     #endif
418    
419 harbaum 221 /* select right character */
420 harbaum 223 gtk_tree_selection_select_iter(selection, &siter);
421     picker_center_iter(view, &siter);
422 harbaum 221
423     /* put this inside a scrolled view */
424     #ifndef USE_PANNABLE_AREA
425     GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
426     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
427     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
428     gtk_container_add(GTK_CONTAINER(scrolled_window), view);
429     return scrolled_window;
430     #else
431     GtkWidget *pannable_area = hildon_pannable_area_new();
432     gtk_container_add(GTK_CONTAINER(pannable_area), view);
433     return pannable_area;
434     #endif
435     }
436    
437     static int picker_get(GtkWidget *widget) {
438     GtkWidget *view = gtk_bin_get_child(GTK_BIN(widget));
439    
440     GtkTreeSelection *sel =
441     gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
442    
443     GtkTreeModel *model;
444     GtkTreeIter iter;
445    
446     /* there should never be an unseletced column. But if */
447     /* it is, we count it as zero */
448     if(!gtk_tree_selection_get_selected(sel, &model, &iter))
449     return 0;
450    
451     int retval = 0;
452     gtk_tree_model_get(model, &iter, 1, &retval, -1);
453     return retval;
454     }
455    
456     static GtkWidget *digit_picker_create(int min, int max, int sel) {
457     #ifndef FREMANTLE
458     GtkWidget *view = gtk_tree_view_new();
459     #else
460     GtkWidget *view = hildon_gtk_tree_view_new(HILDON_UI_MODE_EDIT);
461     #endif
462    
463     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
464     GtkTreeSelection *selection =
465     gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
466    
467     /* --- "digit" column --- */
468     GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
469     g_object_set(renderer, "xalign", 0.5, NULL );
470     gtk_tree_view_insert_column_with_attributes(
471 harbaum 223 GTK_TREE_VIEW(view), -1, "digit", renderer,
472     "text", 0,
473     "sensitive", 2,
474     NULL);
475 harbaum 221
476 harbaum 223 GtkListStore *store =
477     gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN);
478 harbaum 221
479 harbaum 223 dummy_append(store, DUMMY_NUM);
480    
481 harbaum 221 /* add digits */
482     int i;
483     GtkTreeIter siter;
484     for(i=min;i<=max;i++) {
485     char str[2] = { '0'+i, 0 };
486     GtkTreeIter iter;
487     /* Append a row and fill in some data */
488     gtk_list_store_append (store, &iter);
489 harbaum 223 gtk_list_store_set(store, &iter, 0, str, 1, i, 2, TRUE, -1);
490 harbaum 221
491     if(i == sel) siter = iter;
492     }
493    
494 harbaum 223 dummy_append(store, DUMMY_NUM);
495    
496 harbaum 221 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
497     g_object_unref(store);
498    
499 harbaum 223 #ifndef FREMANTLE
500     g_signal_connect(view, "row-activated",
501     (GCallback)on_picker_activated, NULL);
502     #else
503     g_signal_connect(view, "hildon-row-tapped",
504     (GCallback)on_picker_activated, NULL);
505     #endif
506    
507 harbaum 221 gtk_tree_selection_select_iter(selection, &siter);
508 harbaum 223 picker_center_iter(view, &siter);
509 harbaum 221
510     /* put this inside a scrolled view */
511     #ifndef USE_PANNABLE_AREA
512     GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
513     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
514     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
515     gtk_container_add(GTK_CONTAINER(scrolled_window), view);
516     return scrolled_window;
517     #else
518     GtkWidget *pannable_area = hildon_pannable_area_new();
519     gtk_container_add(GTK_CONTAINER(pannable_area), view);
520     return pannable_area;
521     #endif
522     }
523    
524     static gint on_lat_picker_button_press(GtkWidget *button,
525     GdkEventButton *event, gpointer data) {
526    
527     if(event->type == GDK_BUTTON_PRESS) {
528     GtkWidget *dialog =
529     gtk_dialog_new_with_buttons(_("Latitude"),
530     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
531     GTK_DIALOG_MODAL,
532     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
533     _("Done"), GTK_RESPONSE_ACCEPT,
534     NULL);
535    
536 harbaum 223 gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
537 harbaum 221
538     int i, lat = (int)g_object_get_data(G_OBJECT(button), "latitude");
539    
540     /* parse latitude into components */
541     int sign = (lat>=0)?0:1;
542     lat = abs(lat);
543     int deg = lat / 60000;
544     int min = (lat /1000)%60;
545     int minfrac = lat % 1000;
546    
547     GtkWidget *signw, *degw[2], *minw[2], *minfracw[3];
548    
549    
550     /* create N/S 89° 99.999 */
551     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
552 harbaum 223 static const char *ns[] = { "N", "S", NULL };
553 harbaum 221 gtk_box_pack_start_defaults(GTK_BOX(hbox),
554 harbaum 223 signw = string_picker_create(ns, sign));
555 harbaum 221
556     gtk_box_pack_start_defaults(GTK_BOX(hbox),
557     degw[0] = digit_picker_create(0,8, deg/10));
558     gtk_box_pack_start_defaults(GTK_BOX(hbox),
559     degw[1] = digit_picker_create(0,9, deg%10));
560     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("°"), FALSE, FALSE, 0);
561    
562     gtk_box_pack_start_defaults(GTK_BOX(hbox),
563     minw[0] = digit_picker_create(0,5, min/10));
564     gtk_box_pack_start_defaults(GTK_BOX(hbox),
565     minw[1] = digit_picker_create(0,9, min%10));
566     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("."), FALSE, FALSE, 0);
567    
568     gtk_box_pack_start_defaults(GTK_BOX(hbox),
569     minfracw[0] = digit_picker_create(0,9, minfrac/100));
570     gtk_box_pack_start_defaults(GTK_BOX(hbox),
571     minfracw[1] = digit_picker_create(0,9, (minfrac/10)%10));
572     gtk_box_pack_start_defaults(GTK_BOX(hbox),
573     minfracw[2] = digit_picker_create(0,9, minfrac%10));
574    
575     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
576    
577     gtk_widget_show_all(dialog);
578     if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
579    
580     /* parse degrees ... */
581     for(deg=0,i=0;i<2;i++)
582     deg = 10 * deg + picker_get(degw[i]);
583    
584     /* ... minutes ... */
585     for(min=0,i=0;i<2;i++)
586     min = 10 * min + picker_get(minw[i]);
587    
588     /* ... and fractions of minutes */
589     for(minfrac=0,i=0;i<3;i++)
590     minfrac = 10 * minfrac + picker_get(minfracw[i]);
591    
592 harbaum 223 /* parse N/S */
593     if(deg | min | minfrac)
594     sign = picker_get(signw)?-1:1;
595     else
596     sign = 1; // theres no S 00 00.000
597    
598 harbaum 221 float latitude = sign * (deg + min/60.0 + minfrac/60000.0);
599     lat_entry_set(button, latitude);
600     }
601    
602     gtk_widget_destroy(dialog);
603    
604     return TRUE;
605     }
606     return FALSE;
607     }
608     #endif
609    
610 harbaum 1 /* a entry that is colored red when being "active" */
611     GtkWidget *lat_entry_new(float lat) {
612 harbaum 221 char str[32];
613     pos_lat_str(str, sizeof(str), lat);
614    
615     #ifndef COORDINATE_PICKER
616 harbaum 226 GtkWidget *widget = red_entry_new_with_text(str);
617 harbaum 190
618 harbaum 1 g_signal_connect(G_OBJECT(widget), "changed",
619     G_CALLBACK(callback_modified_lat), NULL);
620    
621 harbaum 221 #else
622     GtkWidget *widget = gtk_button_new_with_label(str);
623    
624     #ifdef FREMANTLE
625     hildon_gtk_widget_set_theme_size(widget,
626     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
627     #endif
628     int lat_int = (int)roundf(lat * 60000);
629     g_object_set_data(G_OBJECT(widget), "latitude", (gpointer)lat_int);
630     gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
631     (GtkSignalFunc)on_lat_picker_button_press, NULL);
632     #endif
633 harbaum 223
634 harbaum 1 return widget;
635     }
636    
637 harbaum 221 #ifndef COORDINATE_PICKER
638 harbaum 1 static void callback_modified_lon(GtkWidget *widget, gpointer data ) {
639     float i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
640     mark(widget, !isnan(i));
641     }
642 harbaum 221 #else
643     static gint on_lon_picker_button_press(GtkWidget *button,
644     GdkEventButton *event, gpointer data) {
645 harbaum 1
646 harbaum 221 if(event->type == GDK_BUTTON_PRESS) {
647     GtkWidget *dialog =
648     gtk_dialog_new_with_buttons(_("Longitude"),
649     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
650     GTK_DIALOG_MODAL,
651     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
652     _("Done"), GTK_RESPONSE_ACCEPT,
653     NULL);
654    
655 harbaum 223 gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
656 harbaum 221
657     int i, lat = (int)g_object_get_data(G_OBJECT(button), "longitude");
658    
659     /* parse latitude into components */
660     int sign = (lat>=0)?0:1;
661     lat = abs(lat);
662     int deg = lat / 60000;
663     int min = (lat /1000)%60;
664     int minfrac = lat % 1000;
665    
666     GtkWidget *signw, *degw[3], *minw[2], *minfracw[3];
667    
668     /* create E/W 179° 99.999 */
669     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
670 harbaum 223 static const char *ew[] = { "E", "W", NULL };
671 harbaum 221 gtk_box_pack_start_defaults(GTK_BOX(hbox),
672 harbaum 223 signw = string_picker_create(ew, sign));
673 harbaum 221
674     gtk_box_pack_start_defaults(GTK_BOX(hbox),
675     degw[0] = digit_picker_create(0,1, deg/100));
676     gtk_box_pack_start_defaults(GTK_BOX(hbox),
677     degw[1] = digit_picker_create(0,9, (deg/10)%10));
678     gtk_box_pack_start_defaults(GTK_BOX(hbox),
679     degw[2] = digit_picker_create(0,9, deg%10));
680     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("°"), FALSE, FALSE, 0);
681    
682     gtk_box_pack_start_defaults(GTK_BOX(hbox),
683     minw[0] = digit_picker_create(0,5, min/10));
684     gtk_box_pack_start_defaults(GTK_BOX(hbox),
685     minw[1] = digit_picker_create(0,9, min%10));
686     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("."), FALSE, FALSE, 0);
687    
688     gtk_box_pack_start_defaults(GTK_BOX(hbox),
689     minfracw[0] = digit_picker_create(0,9, minfrac/100));
690     gtk_box_pack_start_defaults(GTK_BOX(hbox),
691     minfracw[1] = digit_picker_create(0,9, (minfrac/10)%10));
692     gtk_box_pack_start_defaults(GTK_BOX(hbox),
693     minfracw[2] = digit_picker_create(0,9, minfrac%10));
694    
695     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
696    
697     gtk_widget_show_all(dialog);
698     if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
699    
700     /* parse degrees ... */
701     for(deg=0,i=0;i<3;i++)
702     deg = 10 * deg + picker_get(degw[i]);
703    
704     /* ... minutes ... */
705     for(min=0,i=0;i<2;i++)
706     min = 10 * min + picker_get(minw[i]);
707    
708     /* ... and fractions of minutes */
709     for(minfrac=0,i=0;i<3;i++)
710     minfrac = 10 * minfrac + picker_get(minfracw[i]);
711    
712 harbaum 223 if(deg | min | minfrac)
713     sign = picker_get(signw)?-1:1;
714     else
715     sign = 1; // theres no W 00 00.000
716    
717 harbaum 221 float longitude = sign * (deg + min/60.0 + minfrac/60000.0);
718     lon_entry_set(button, longitude);
719     }
720    
721     gtk_widget_destroy(dialog);
722    
723     return TRUE;
724     }
725     return FALSE;
726     }
727     #endif
728    
729 harbaum 1 /* a entry that is colored red when filled with invalid coordinate */
730     GtkWidget *lon_entry_new(float lon) {
731 harbaum 221 char str[32];
732     pos_lon_str(str, sizeof(str), lon);
733    
734     #ifndef COORDINATE_PICKER
735 harbaum 226 GtkWidget *widget = red_entry_new_with_text(str);
736 harbaum 1 g_signal_connect(G_OBJECT(widget), "changed",
737     G_CALLBACK(callback_modified_lon), NULL);
738    
739 harbaum 221 #else
740     GtkWidget *widget = gtk_button_new_with_label(str);
741    
742     #ifdef FREMANTLE
743     hildon_gtk_widget_set_theme_size(widget,
744     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
745     #endif
746     int lon_int = (int)roundf(lon * 60000);
747     g_object_set_data(G_OBJECT(widget), "longitude", (gpointer)lon_int);
748     gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
749     (GtkSignalFunc)on_lon_picker_button_press, NULL);
750     #endif
751    
752 harbaum 1 return widget;
753     }
754    
755 harbaum 221 float lat_entry_get(GtkWidget *widget) {
756     #ifndef COORDINATE_PICKER
757 harbaum 1 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
758 harbaum 221 #else
759     char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget));
760     #endif
761 harbaum 1 return pos_parse_lat(p);
762     }
763    
764 harbaum 221 float lon_entry_get(GtkWidget *widget) {
765     #ifndef COORDINATE_PICKER
766 harbaum 1 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
767 harbaum 221 #else
768     char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget));
769     #endif
770 harbaum 1 return pos_parse_lon(p);
771     }
772    
773 harbaum 221 void lat_entry_set(GtkWidget *widget, float lat) {
774     char str[32];
775     pos_lat_str(str, sizeof(str)-1, lat);
776     #ifndef COORDINATE_PICKER
777     gtk_entry_set_text(GTK_ENTRY(widget), str);
778     #else
779     gtk_button_set_label(GTK_BUTTON(widget), str);
780     int lat_int = (int)roundf(lat * 60000);
781     g_object_set_data(G_OBJECT(widget), "latitude", (gpointer)lat_int);
782 harbaum 223 g_signal_emit_by_name(widget, "changed");
783 harbaum 221 #endif
784     }
785    
786     void lon_entry_set(GtkWidget *widget, float lon) {
787     char str[32];
788     pos_lon_str(str, sizeof(str)-1, lon);
789     #ifndef COORDINATE_PICKER
790     gtk_entry_set_text(GTK_ENTRY(widget), str);
791     #else
792     gtk_button_set_label(GTK_BUTTON(widget), str);
793     int lon_int = (int)roundf(lon * 60000);
794     g_object_set_data(G_OBJECT(widget), "longitude", (gpointer)lon_int);
795 harbaum 223 g_signal_emit_by_name(widget, "changed");
796 harbaum 221 #endif
797     }
798    
799     void lat_label_set(GtkWidget *widget, float lat) {
800     char str[32];
801     pos_lat_str(str, sizeof(str)-1, lat);
802     gtk_label_set(GTK_LABEL(widget), str);
803     }
804    
805     void lon_label_set(GtkWidget *widget, float lon) {
806     char str[32];
807     pos_lon_str(str, sizeof(str)-1, lon);
808     gtk_label_set(GTK_LABEL(widget), str);
809     }
810    
811     void lat_label_attrib_set(GtkWidget *widget, float lat,
812     int size, int strikethrough) {
813     char str[32];
814     pos_lat_str(str, sizeof(str)-1, lat);
815     gtk_label_attrib_set(widget, str, size, strikethrough);
816     }
817    
818     void lon_label_attrib_set(GtkWidget *widget, float lon,
819     int size, int strikethrough) {
820     char str[32];
821     pos_lon_str(str, sizeof(str)-1, lon);
822     gtk_label_attrib_set(widget, str, size, strikethrough);
823     }
824    
825 harbaum 223 #ifndef COORDINATE_PICKER
826 harbaum 1 static void callback_modified_dist(GtkWidget *widget, gpointer data ) {
827     /* don't care for metric/imperial since we only want to know if this */
828     /* is parseable at all */
829 harbaum 223 float i =
830     distance_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);
831 harbaum 1 mark(widget, !isnan(i));
832     }
833 harbaum 223 #else
834     static gint on_dist_picker_button_press(GtkWidget *button,
835     GdkEventButton *event, gpointer data) {
836 harbaum 1
837 harbaum 223 if(event->type == GDK_BUTTON_PRESS) {
838     GtkWidget *dialog =
839     gtk_dialog_new_with_buttons(_("Distance"),
840     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
841     GTK_DIALOG_MODAL,
842     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
843     _("Done"), GTK_RESPONSE_ACCEPT,
844     NULL);
845    
846     gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
847    
848     /* distance is given in m or ft (depending on mil) */
849     int i, dist = (int)g_object_get_data(G_OBJECT(button), "distance");
850     gboolean mil = (gboolean)g_object_get_data(G_OBJECT(button), "mil");
851     int unit = 0;
852    
853     /* parse distance into components */
854     if(mil) {
855     /* 1 mil = 1760 yd = 5280 ft. 1yd = 3 ft */
856     if(dist<95) { unit = 0; dist *= 100; }
857     else if(dist<2904) { unit = 1; dist = 100 * dist / 3; }
858     else { unit = 2; dist = 5 * dist / 264; }
859     } else {
860     if(dist<1000) { unit = 3; dist *= 100; }
861     else { unit = 4; dist /= 10; }
862     }
863    
864     GtkWidget *distw[4], *fracw[2], *unitw;
865    
866     /* create xxxx.x unit */
867     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
868    
869     gtk_box_pack_start_defaults(GTK_BOX(hbox),
870     distw[0] = digit_picker_create(0,9, (dist/100000)%10));
871     gtk_box_pack_start_defaults(GTK_BOX(hbox),
872     distw[1] = digit_picker_create(0,9, (dist/10000)%10));
873     gtk_box_pack_start_defaults(GTK_BOX(hbox),
874     distw[2] = digit_picker_create(0,9, (dist/1000)%10));
875     gtk_box_pack_start_defaults(GTK_BOX(hbox),
876     distw[3] = digit_picker_create(0,9, (dist/100)%10));
877     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" . "), FALSE, FALSE, 0);
878     gtk_box_pack_start_defaults(GTK_BOX(hbox),
879     fracw[0] = digit_picker_create(0,9, (dist/10)%10));
880     gtk_box_pack_start_defaults(GTK_BOX(hbox),
881     fracw[1] = digit_picker_create(0,9, (dist/1)%10));
882    
883     static const char *units[] = { "ft", "yd", "mi", "m", "km", NULL };
884     gtk_box_pack_start_defaults(GTK_BOX(hbox),
885     unitw = string_picker_create(units, unit));
886    
887     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
888    
889     gtk_widget_show_all(dialog);
890     if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
891    
892     /* parse distance */
893     for(dist=0,i=0;i<4;i++)
894     dist = 10 * dist + picker_get(distw[i]);
895    
896     for(i=0;i<2;i++)
897     dist = 10 * dist + picker_get(fracw[i]);
898    
899     unit = picker_get(unitw);
900     if(unit == 0) { dist /= 100; } // ft
901     else if(unit == 1) { dist = 3*dist/100; } // yd
902     else if(unit == 2) { dist = 528*dist/10; } // mi
903     else if(unit == 3) { dist /= 100; } // m
904     else if(unit == 4) { dist *= 10; } // km
905    
906     /* user may have switched between metric and imperial */
907     float distance;
908     if(unit <= 2) {
909     distance = dist / 5280.0;
910     if(!mil) distance *= 1.609344;
911     } else {
912     distance = dist / 1000.0;
913     if( mil) distance /= 1.609344;
914     }
915    
916     dist_entry_set(button, distance, mil);
917     }
918    
919     gtk_widget_destroy(dialog);
920    
921     return TRUE;
922     }
923     return FALSE;
924     }
925     #endif
926    
927 harbaum 1 /* a entry that is colored red when filled with invalid distance */
928     GtkWidget *dist_entry_new(float dist, gboolean mil) {
929 harbaum 223 char str[32];
930     distance_str(str, sizeof(str), dist, mil);
931    
932     #ifndef COORDINATE_PICKER
933 harbaum 226 GtkWidget *widget = red_entry_new_with_text(str);
934 harbaum 1 g_signal_connect(G_OBJECT(widget), "changed",
935     G_CALLBACK(callback_modified_dist), NULL);
936    
937 harbaum 223 #else
938     GtkWidget *widget = gtk_button_new_with_label(str);
939    
940     #ifdef FREMANTLE
941     hildon_gtk_widget_set_theme_size(widget,
942     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
943     #endif
944     int dist_int = (int)roundf(dist * 1000); // km -> m
945     if(mil) dist_int = (int)roundf(dist * 5280.0); // mi -> ft
946    
947     g_object_set_data(G_OBJECT(widget), "distance", (gpointer)dist_int);
948     g_object_set_data(G_OBJECT(widget), "mil", (gpointer)mil);
949     gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
950     (GtkSignalFunc)on_dist_picker_button_press, NULL);
951     #endif
952    
953 harbaum 1 return widget;
954     }
955    
956 harbaum 223 float dist_entry_get(GtkWidget *widget, gboolean mil) {
957     #ifndef COORDINATE_PICKER
958 harbaum 1 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
959 harbaum 223 #else
960     char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget));
961     #endif
962 harbaum 1 return distance_parse(p, mil);
963     }
964    
965 harbaum 223 void dist_entry_set(GtkWidget *widget, float dist, gboolean mil) {
966     char str[32];
967     distance_str(str, sizeof(str), dist, mil);
968    
969     #ifndef COORDINATE_PICKER
970     gtk_entry_set_text(GTK_ENTRY(widget), str);
971     #else
972     int dist_int = (int)roundf(dist * 1000); // km -> m
973     if(mil) dist_int = (int)roundf(dist * 5280.0); // mi -> ft
974     g_object_set_data(G_OBJECT(widget), "distance", (gpointer)dist_int);
975     g_object_set_data(G_OBJECT(widget), "mil", (gpointer)mil);
976     gtk_button_set_label(GTK_BUTTON(widget), str);
977     #endif
978     }
979    
980 harbaum 1 #ifndef USE_MAEMO
981     #ifdef ENABLE_BROWSER_INTERFACE
982     #include <libgnome/gnome-url.h>
983    
984     int browser_url(appdata_t *appdata, char *url) {
985     /* taken from gnome-open, part of libgnome */
986     GError *err = NULL;
987     gnome_url_show(url, &err);
988     return 0;
989     }
990     #endif
991     #endif
992 harbaum 77
993     /* recursively remove an entire file system */
994     void rmdir_recursive(char *path) {
995     GDir *dir = g_dir_open(path, 0, NULL);
996     if(dir) {
997     const char *name = g_dir_read_name(dir);
998     while(name) {
999     char *fullname = g_strdup_printf("%s/%s", path, name);
1000     // printf("deleting %s\n", fullname);
1001    
1002     if(g_file_test(fullname, G_FILE_TEST_IS_DIR))
1003     rmdir_recursive(fullname);
1004     else if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR))
1005     g_remove(fullname);
1006    
1007     g_free(fullname);
1008     name = g_dir_read_name(dir);
1009     }
1010    
1011     g_dir_close(dir);
1012     }
1013     g_rmdir(path);
1014     }
1015    
1016 harbaum 137 #ifdef ENABLE_BROWSER_INTERFACE
1017     static void on_link_clicked(GtkButton *button, gpointer data) {
1018     appdata_t *appdata = (appdata_t*)data;
1019     char *url = g_object_get_data(G_OBJECT(button), "url");
1020     if(url) browser_url(appdata, url);
1021     }
1022     #endif
1023    
1024     /* a button containing a weblink */
1025     GtkWidget *link_button_attrib(appdata_t *appdata, char *str, char *url,
1026     int size, int strikethrough) {
1027    
1028     #ifdef ENABLE_BROWSER_INTERFACE
1029     if(url) {
1030     GtkWidget *button = gtk_button_attrib(str, size, strikethrough);
1031     g_object_set_data(G_OBJECT(button), "url", url);
1032     gtk_signal_connect(GTK_OBJECT(button), "clicked",
1033     (GtkSignalFunc)on_link_clicked, appdata);
1034    
1035     return button;
1036     }
1037     #endif
1038     return gtk_label_attrib(str, size, strikethrough);
1039     }
1040    
1041     #ifdef ENABLE_BROWSER_INTERFACE
1042     static void on_link_id_clicked(GtkButton *button, gpointer data) {
1043     appdata_t *appdata = (appdata_t*)data;
1044    
1045     unsigned int id = (unsigned int)g_object_get_data(G_OBJECT(button), "id");
1046     char *type = g_object_get_data(G_OBJECT(button), "type");
1047    
1048     char *url = g_strdup_printf("http://www.geocaching.com/%s?id=%u",
1049     type, id);
1050    
1051     if(url) {
1052     browser_url(appdata, url);
1053     g_free(url);
1054     }
1055     }
1056     #endif
1057    
1058     GtkWidget *link_button_by_id(appdata_t *appdata, char *str,
1059     const char *type, int id) {
1060    
1061     #ifdef ENABLE_BROWSER_INTERFACE
1062     if(id) {
1063     GtkWidget *ref = gtk_button_new_with_label(str);
1064     #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
1065     // hildon_gtk_widget_set_theme_size(ref,
1066     // (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1067     #endif
1068     g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
1069     g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
1070     gtk_signal_connect(GTK_OBJECT(ref), "clicked",
1071     GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
1072    
1073     return ref;
1074     }
1075     #endif
1076     return gtk_label_new(str);
1077     }
1078    
1079 harbaum 138
1080     GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon,
1081     const char *type, int id) {
1082    
1083     #ifdef ENABLE_BROWSER_INTERFACE
1084     if(id) {
1085     GtkWidget *ref = gtk_button_new();
1086     gtk_button_set_image(GTK_BUTTON(ref), icon);
1087    
1088     #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
1089     // hildon_gtk_widget_set_theme_size(ref,
1090     // (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1091     #endif
1092     g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
1093     g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
1094     gtk_signal_connect(GTK_OBJECT(ref), "clicked",
1095     GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
1096    
1097     return ref;
1098     }
1099     #endif
1100     return icon;
1101     }
1102    
1103 harbaum 165 /* left aligned, word wrapped multiline widget */
1104     GtkWidget *simple_text_widget(char *text) {
1105     GtkWidget *label = gtk_label_new(text);
1106    
1107     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1108     gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD);
1109     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1110    
1111     return label;
1112     }
1113 harbaum 198
1114    
1115     /* a label that is left aligned */
1116     GtkWidget *left_label_new(char *str) {
1117     GtkWidget *widget = gtk_label_new(str);
1118     gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f);
1119     return widget;
1120     }
1121 harbaum 212
1122 harbaum 221 /* ------------- preset coordinate picker tool ----------------- */
1123    
1124 harbaum 217 static void pos_set(GtkWidget *item, float lat, float lon) {
1125 harbaum 212
1126     GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
1127 harbaum 221 lat_entry_set(lat_entry, lat);
1128 harbaum 212
1129     GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
1130 harbaum 221 lon_entry_set(lon_entry, lon);
1131 harbaum 212 }
1132    
1133 harbaum 217 static void cb_gps(GtkWidget *item, gpointer data) {
1134 harbaum 212 appdata_t *appdata = (appdata_t*)data;
1135 harbaum 218 gint id = (gint)g_object_get_data(G_OBJECT(item), "id");
1136     pos_t *pos = NULL;
1137 harbaum 212
1138 harbaum 218 if(!id)
1139     pos = gps_get_pos(appdata);
1140     else if(id == 1)
1141     pos = &appdata->home;
1142     else {
1143     location_t *location = appdata->location;
1144     while(location && id > 2) {
1145     location = location->next;
1146     id--;
1147     }
1148    
1149     if(id == 2)
1150     pos = &location->pos;
1151     }
1152    
1153     if(!pos) pos_set(item, NAN, NAN);
1154     else pos_set(item, pos->lat, pos->lon);
1155 harbaum 212 }
1156    
1157 harbaum 217 static void cb_geomath(GtkWidget *item, gpointer data) {
1158 harbaum 212 appdata_t *appdata = (appdata_t*)data;
1159    
1160     pos_set(item, appdata->geomath.lat, appdata->geomath.lon);
1161     }
1162    
1163     #ifdef ENABLE_OSM_GPS_MAP
1164 harbaum 217 static void cb_map(GtkWidget *item, gpointer data) {
1165 harbaum 212 appdata_t *appdata = (appdata_t*)data;
1166    
1167     pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon);
1168     }
1169     #endif
1170    
1171 harbaum 217 static void cb_cache(GtkWidget *item, gpointer data) {
1172 harbaum 212 appdata_t *appdata = (appdata_t*)data;
1173 harbaum 217
1174 harbaum 212 cache_t *cache = appdata->cur_cache;
1175     g_assert(cache);
1176    
1177 harbaum 217 gint id = (gint)g_object_get_data(G_OBJECT(item), "id");
1178    
1179     if(!id)
1180 harbaum 212 pos_set(item, cache->pos.lat, cache->pos.lon);
1181 harbaum 228 else if(id == 1) {
1182     /* fetch position out of notes dialog since they probably */
1183     /* haven't been saved yet */
1184     pos_t pos = notes_get_pos(appdata->cache_context);
1185     pos_set(item, pos.lat, pos.lon);
1186     } else {
1187 harbaum 212 wpt_t *wpt = cache->wpt;
1188 harbaum 221 while(wpt && id > 2) {
1189 harbaum 212 wpt = wpt->next;
1190 harbaum 217 id--;
1191 harbaum 212 }
1192 harbaum 217
1193 harbaum 221 if(id == 2)
1194 harbaum 217 pos_set(item, wpt->pos.lat, wpt->pos.lon);
1195 harbaum 212 }
1196     }
1197    
1198 harbaum 221 #ifndef PRESET_PICKER_DIALOG
1199 harbaum 212 static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata,
1200     GtkWidget *icon, char *menu_str,
1201 harbaum 217 void(*func)(GtkWidget*, gpointer), gint id,
1202 harbaum 212 GtkWidget *lon_entry, GtkWidget *lat_entry) {
1203    
1204     GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str);
1205    
1206     if(icon)
1207     gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
1208    
1209     g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry);
1210     g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry);
1211 harbaum 217 g_object_set_data(G_OBJECT(item), "id", (gpointer)id);
1212 harbaum 212
1213     if(func)
1214     gtk_signal_connect(GTK_OBJECT(item), "activate",
1215     (GtkSignalFunc)func, appdata);
1216    
1217     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1218    
1219     return item;
1220     }
1221    
1222     static GtkWidget *popup_menu_create(appdata_t *appdata,
1223     GtkWidget *lat_entry, GtkWidget *lon_entry) {
1224     GtkWidget *menu = gtk_menu_new();
1225    
1226 harbaum 223 if(pos_valid(gps_get_pos(appdata)))
1227     menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),
1228     _("GPS position"), cb_gps, 0, lon_entry, lat_entry);
1229 harbaum 218
1230 harbaum 223 if(pos_valid(&appdata->home))
1231     menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),
1232     _("Home"), cb_gps, 1, lon_entry, lat_entry);
1233 harbaum 218
1234     location_t *location = appdata->location;
1235     gint id = 2;
1236     while(location) {
1237 harbaum 223 if(pos_valid(&location->pos))
1238     menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),
1239     location->name, cb_gps, id, lon_entry, lat_entry);
1240 harbaum 218
1241 harbaum 223 id++;
1242 harbaum 218 location = location->next;
1243     }
1244    
1245 harbaum 223 if(pos_valid(&appdata->geomath))
1246     menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),
1247     _("Geomath projection"), cb_geomath, 0, lon_entry, lat_entry);
1248    
1249 harbaum 212 #ifdef ENABLE_OSM_GPS_MAP
1250 harbaum 223 if(pos_valid(&appdata->map.pos))
1251     menu_add(menu, appdata, icon_get_widget(ICON_POS, 20), _("Map position"),
1252     cb_map, 0, lon_entry, lat_entry);
1253 harbaum 212 #endif
1254 harbaum 214
1255 harbaum 212 if(appdata->cur_cache) {
1256     cache_t *cache = appdata->cur_cache;
1257    
1258 harbaum 217 char *name = cache->name;
1259     if(!name) name = cache->id;
1260    
1261 harbaum 221 /* original cache position */
1262 harbaum 223 if(pos_valid(&cache->pos))
1263 harbaum 214 menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
1264 harbaum 217 name, cb_cache, 0, lon_entry, lat_entry);
1265 harbaum 212
1266 harbaum 221 /* overwritten cache position */
1267 harbaum 228 if(appdata->cache_context && notes_get_override(appdata->cache_context))
1268 harbaum 221 menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
1269     _("Modified coordinate"), cb_cache, 1, lon_entry, lat_entry);
1270    
1271 harbaum 212 wpt_t *wpt = cache->wpt;
1272 harbaum 221 gint id = 2;
1273 harbaum 212 while(wpt) {
1274 harbaum 223 if(pos_valid(&wpt->pos)) {
1275     GtkWidget *icon = NULL;
1276     if(wpt->sym != WPT_SYM_UNKNOWN)
1277     icon = icon_get_widget(ICON_POS, wpt->sym);
1278 harbaum 212
1279 harbaum 223 char *name = wpt->desc;
1280     if(!name) name = wpt->cmt;
1281     if(!name) name = wpt->id;
1282    
1283     menu_add(menu, appdata, icon, name, cb_cache, id,
1284     lon_entry, lat_entry);
1285     }
1286 harbaum 217
1287 harbaum 223 id++;
1288 harbaum 212 wpt = wpt->next;
1289     }
1290     }
1291    
1292     gtk_widget_show_all(menu);
1293    
1294     return menu;
1295     }
1296    
1297     static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
1298     gpointer data) {
1299    
1300 harbaum 223 appdata_t *appdata = (appdata_t*)data;
1301    
1302 harbaum 212 if(event->type == GDK_BUTTON_PRESS) {
1303     GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
1304    
1305 harbaum 223 if(menu)
1306     gtk_widget_destroy(menu);
1307    
1308     gpointer lat_entry = g_object_get_data(G_OBJECT(button), "lat_entry");
1309     g_assert(lat_entry);
1310     gpointer lon_entry = g_object_get_data(G_OBJECT(button), "lon_entry");
1311     g_assert(lon_entry);
1312    
1313     menu = popup_menu_create(appdata, lat_entry, lon_entry);
1314     g_object_set_data(G_OBJECT(button), "menu", (gpointer)menu);
1315    
1316 harbaum 212 /* draw a popup menu */
1317     gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1318     event->button, event->time);
1319     return TRUE;
1320     }
1321     return FALSE;
1322     }
1323    
1324     static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
1325     GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
1326 harbaum 223 if(menu) gtk_widget_destroy(menu);
1327 harbaum 212 }
1328     #endif
1329    
1330 harbaum 221 #ifdef PRESET_PICKER_DIALOG
1331 harbaum 212
1332 harbaum 217 enum {
1333 harbaum 221 PRESET_PICKER_COL_ICON = 0,
1334     PRESET_PICKER_COL_NAME,
1335     PRESET_PICKER_COL_ID,
1336     PRESET_PICKER_COL_CB,
1337     PRESET_PICKER_NUM_COLS
1338 harbaum 217 };
1339 harbaum 212
1340 harbaum 221 static void preset_picker_add(GtkListStore *store, appdata_t *appdata,
1341 harbaum 217 GdkPixbuf *icon, char *menu_str,
1342     void(*func)(GtkWidget*, gpointer), gint id) {
1343     GtkTreeIter iter;
1344 harbaum 212
1345 harbaum 217 /* Append a row and fill in some data */
1346     gtk_list_store_append (store, &iter);
1347 harbaum 212
1348 harbaum 217 gtk_list_store_set(store, &iter,
1349 harbaum 221 PRESET_PICKER_COL_ICON, icon,
1350     PRESET_PICKER_COL_NAME, menu_str,
1351     PRESET_PICKER_COL_ID, id,
1352     PRESET_PICKER_COL_CB, func,
1353 harbaum 217 -1);
1354 harbaum 212 }
1355 harbaum 214
1356 harbaum 221 static void on_preset_picker_activated(GtkTreeView *treeview,
1357 harbaum 217 GtkTreePath *path,
1358     GtkTreeViewColumn *col,
1359     gpointer userdata) {
1360     GtkTreeIter iter;
1361     GtkTreeModel *model = gtk_tree_view_get_model(treeview);
1362 harbaum 214
1363 harbaum 217 if(gtk_tree_model_get_iter(model, &iter, path)) {
1364     gint id;
1365     void(*func)(GtkWidget*, gpointer);
1366     gtk_tree_model_get(model, &iter,
1367 harbaum 221 PRESET_PICKER_COL_ID, &id,
1368     PRESET_PICKER_COL_CB, &func,
1369 harbaum 217 -1);
1370    
1371     /* set id on widget as callbacks expect it this way */
1372     g_object_set_data(G_OBJECT(treeview), "id", (gpointer)id);
1373     func(GTK_WIDGET(treeview), userdata);
1374 harbaum 218
1375     gtk_dialog_response(GTK_DIALOG(gtk_widget_get_toplevel(
1376     GTK_WIDGET(treeview))), GTK_RESPONSE_ACCEPT);
1377    
1378 harbaum 217 }
1379 harbaum 214 }
1380 harbaum 216
1381 harbaum 221 static GtkWidget *preset_picker_create(appdata_t *appdata,
1382 harbaum 217 GtkWidget *lat_entry, GtkWidget *lon_entry) {
1383     GtkCellRenderer *renderer;
1384     GtkListStore *store;
1385    
1386     GtkWidget *view = gtk_tree_view_new();
1387 harbaum 216
1388 harbaum 217 g_object_set_data(G_OBJECT(view), "lat_entry", (gpointer)lat_entry);
1389     g_object_set_data(G_OBJECT(view), "lon_entry", (gpointer)lon_entry);
1390 harbaum 216
1391 harbaum 217 /* --- "Icon" column --- */
1392     renderer = gtk_cell_renderer_pixbuf_new();
1393     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
1394 harbaum 221 -1, "Icon", renderer, "pixbuf", PRESET_PICKER_COL_ICON, NULL);
1395 harbaum 216
1396 harbaum 217 /* --- "Name" column --- */
1397     renderer = gtk_cell_renderer_text_new();
1398     g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
1399     GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
1400 harbaum 221 "Name", renderer, "text", PRESET_PICKER_COL_NAME, NULL);
1401 harbaum 217 gtk_tree_view_column_set_expand(column, TRUE);
1402     gtk_tree_view_insert_column(GTK_TREE_VIEW(view), column, -1);
1403 harbaum 216
1404 harbaum 221 store = gtk_list_store_new(PRESET_PICKER_NUM_COLS,
1405 harbaum 217 GDK_TYPE_PIXBUF,
1406     G_TYPE_STRING,
1407     G_TYPE_INT,
1408     G_TYPE_POINTER);
1409 harbaum 216
1410 harbaum 223 if(pos_valid(gps_get_pos(appdata)))
1411     preset_picker_add(store, appdata, icon_get(ICON_POS, 18),
1412     _("GPS position"), cb_gps, 0);
1413 harbaum 218
1414 harbaum 223 if(pos_valid(&appdata->home))
1415     preset_picker_add(store, appdata, icon_get(ICON_POS, 21),
1416     _("Home"), cb_gps, 1);
1417 harbaum 218
1418     location_t *location = appdata->location;
1419     gint id = 2;
1420     while(location) {
1421 harbaum 223 if(pos_valid(&location->pos))
1422     preset_picker_add(store, appdata, icon_get(ICON_POS, 21),
1423     location->name, cb_gps, id);
1424 harbaum 218
1425 harbaum 223 id++;
1426 harbaum 218 location = location->next;
1427     }
1428    
1429 harbaum 223 if(pos_valid(&appdata->geomath))
1430     preset_picker_add(store, appdata, icon_get(ICON_POS, 19),
1431     _("Geomath projection"), cb_geomath, 0);
1432 harbaum 217 #ifdef ENABLE_OSM_GPS_MAP
1433 harbaum 223 if(pos_valid(&appdata->map.pos))
1434     preset_picker_add(store, appdata, icon_get(ICON_POS, 20),
1435     _("Map position"), cb_map, 0);
1436 harbaum 217 #endif
1437 harbaum 216
1438 harbaum 217 if(appdata->cur_cache) {
1439     cache_t *cache = appdata->cur_cache;
1440 harbaum 216
1441 harbaum 217 char *name = cache->name;
1442     if(!name) name = cache->id;
1443 harbaum 223
1444 harbaum 221 /* original cache position */
1445 harbaum 223 if(pos_valid(&cache->pos))
1446 harbaum 221 preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),
1447 harbaum 223 name, cb_cache, 0);
1448 harbaum 216
1449 harbaum 221 /* overwritten cache position */
1450 harbaum 228 if(appdata->cache_context && notes_get_override(appdata->cache_context))
1451 harbaum 221 preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),
1452 harbaum 223 _("Modified coordinate"), cb_cache, 1);
1453 harbaum 221
1454 harbaum 217 wpt_t *wpt = cache->wpt;
1455 harbaum 221 gint id = 2;
1456 harbaum 217 while(wpt) {
1457 harbaum 223 if(pos_valid(&wpt->pos)) {
1458     GdkPixbuf *icon = NULL;
1459     if(wpt->sym != WPT_SYM_UNKNOWN)
1460     icon = icon_get(ICON_POS, wpt->sym);
1461 harbaum 216
1462 harbaum 223 char *name = wpt->desc;
1463     if(!name) name = wpt->cmt;
1464     if(!name) name = wpt->id;
1465 harbaum 216
1466 harbaum 223 preset_picker_add(store, appdata, icon, name, cb_cache, id);
1467     }
1468     id++;
1469 harbaum 217 wpt = wpt->next;
1470     }
1471     }
1472 harbaum 216
1473 harbaum 217 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
1474     g_object_unref(store);
1475    
1476     /* make list react on clicks */
1477     g_signal_connect(view, "row-activated",
1478 harbaum 221 (GCallback)on_preset_picker_activated, appdata);
1479 harbaum 217
1480     /* put this inside a scrolled view */
1481     #ifndef USE_PANNABLE_AREA
1482     GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1483     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
1484     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1485     gtk_container_add(GTK_CONTAINER(scrolled_window), view);
1486     return scrolled_window;
1487     #else
1488     GtkWidget *pannable_area = hildon_pannable_area_new();
1489     gtk_container_add(GTK_CONTAINER(pannable_area), view);
1490     return pannable_area;
1491     #endif
1492 harbaum 216 }
1493    
1494 harbaum 221 static gint on_preset_picker_button_press(GtkWidget *button,
1495 harbaum 217 GdkEventButton *event, gpointer data) {
1496     appdata_t *appdata = (appdata_t*)data;
1497 harbaum 216
1498 harbaum 217 gpointer lat_entry = g_object_get_data(G_OBJECT(button), "lat_entry");
1499     gpointer lon_entry = g_object_get_data(G_OBJECT(button), "lon_entry");
1500    
1501 harbaum 216 if(event->type == GDK_BUTTON_PRESS) {
1502 harbaum 217 GtkWidget *dialog =
1503     gtk_dialog_new_with_buttons(_("Preset coordinates"),
1504     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
1505     GTK_DIALOG_MODAL,
1506     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1507     NULL);
1508 harbaum 216
1509 harbaum 223 gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
1510 harbaum 216
1511 harbaum 217 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1512 harbaum 221 preset_picker_create(appdata, lat_entry, lon_entry));
1513 harbaum 217
1514 harbaum 216 gtk_widget_show_all(dialog);
1515     gtk_dialog_run(GTK_DIALOG(dialog));
1516     gtk_widget_destroy(dialog);
1517    
1518     return TRUE;
1519     }
1520     return FALSE;
1521     }
1522 harbaum 217 #endif
1523 harbaum 216
1524 harbaum 221
1525     GtkWidget *preset_coordinate_picker(appdata_t *appdata,
1526 harbaum 217 GtkWidget *lat_entry, GtkWidget *lon_entry) {
1527 harbaum 216
1528 harbaum 217 GtkWidget *button = gtk_button_new();
1529 harbaum 216
1530     gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
1531 harbaum 217
1532     gtk_widget_set_tooltip_text(button, _("Preset coordinates"));
1533    
1534 harbaum 221 g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry);
1535     g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry);
1536    
1537     #ifndef PRESET_PICKER_DIALOG
1538 harbaum 216 gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
1539 harbaum 217 (GtkSignalFunc)on_popup_button_press, appdata);
1540 harbaum 216
1541 harbaum 217 gtk_signal_connect(GTK_OBJECT(button), "destroy",
1542     (GtkSignalFunc)on_popup_destroy, appdata);
1543    
1544     g_object_set_data(G_OBJECT(button), "menu",
1545     popup_menu_create(appdata, lat_entry, lon_entry));
1546 harbaum 216 #else
1547 harbaum 217 #ifdef FREMANTLE
1548     hildon_gtk_widget_set_theme_size(button,
1549     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1550 harbaum 216 #endif
1551    
1552 harbaum 217 gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
1553 harbaum 221 (GtkSignalFunc)on_preset_picker_button_press, appdata);
1554 harbaum 217 #endif
1555    
1556 harbaum 216 return button;
1557     }
1558 harbaum 217
1559     GtkWidget *entry_new(void) {
1560     #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
1561     return gtk_entry_new();
1562     #else
1563     return hildon_entry_new(HILDON_SIZE_AUTO);
1564 harbaum 216 #endif
1565 harbaum 217 }
1566    
1567     gboolean pos_differ(pos_t *pos1, pos_t *pos2) {
1568     int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;
1569     int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;
1570    
1571     return((lat1 != lat2) || (lon1 != lon2));
1572     }
1573    
1574 harbaum 223 gboolean pos_valid(pos_t *pos) {
1575     if(!pos) return FALSE;
1576     return(!isnan(pos->lat) && !isnan(pos->lon));
1577     }
1578    
1579     void misc_init(void) {
1580     g_signal_new ("changed", GTK_TYPE_BUTTON,
1581     G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
1582     g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
1583     }
1584    
1585     void angle_str(char *str, int len, float angle) {
1586     snprintf(str, len, _("%.1f°"), angle);
1587     }
1588    
1589     float angle_parse(char *str) {
1590     float val;
1591    
1592     if(sscanf(str, _("%f°"), &val) != 1)
1593     val = NAN;
1594    
1595     return val;
1596     }
1597    
1598     #ifndef COORDINATE_PICKER
1599     static void callback_modified_angle(GtkWidget *widget, gpointer data ) {
1600     float i = angle_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
1601     mark(widget, !isnan(i));
1602     }
1603     #else
1604     static gint on_angle_picker_button_press(GtkWidget *button,
1605     GdkEventButton *event, gpointer data) {
1606    
1607     if(event->type == GDK_BUTTON_PRESS) {
1608     GtkWidget *dialog =
1609     gtk_dialog_new_with_buttons(_("Direction"),
1610     GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
1611     GTK_DIALOG_MODAL,
1612     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1613     _("Done"), GTK_RESPONSE_ACCEPT,
1614     NULL);
1615    
1616     gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
1617    
1618     int i, angle = (int)g_object_get_data(G_OBJECT(button), "angle");
1619    
1620     GtkWidget *anglew[3], *fracw;
1621    
1622     /* create xxx.x° */
1623     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
1624    
1625     gtk_box_pack_start_defaults(GTK_BOX(hbox),
1626     anglew[0] = digit_picker_create(0,3, (angle/1000)%10));
1627     gtk_box_pack_start_defaults(GTK_BOX(hbox),
1628     anglew[1] = digit_picker_create(0,9, (angle/100)%10));
1629     gtk_box_pack_start_defaults(GTK_BOX(hbox),
1630     anglew[2] = digit_picker_create(0,9, (angle/10)%10));
1631     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" . "), FALSE, FALSE, 0);
1632     gtk_box_pack_start_defaults(GTK_BOX(hbox),
1633     fracw = digit_picker_create(0,9, (angle/1)%10));
1634     gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("°"), FALSE, FALSE, 0);
1635    
1636     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
1637    
1638     gtk_widget_show_all(dialog);
1639     if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1640    
1641     /* parse angle */
1642     for(angle=0,i=0;i<3;i++)
1643     angle = 10 * angle + picker_get(anglew[i]);
1644    
1645     angle = 10 * angle + picker_get(fracw);
1646    
1647     angle_entry_set(button, angle/10.0);
1648     }
1649    
1650     gtk_widget_destroy(dialog);
1651    
1652     return TRUE;
1653     }
1654     return FALSE;
1655     }
1656     #endif
1657    
1658     GtkWidget *angle_entry_new(float angle) {
1659     char str[32];
1660     angle_str(str, sizeof(str), angle);
1661    
1662     #ifndef COORDINATE_PICKER
1663 harbaum 226 GtkWidget *widget = red_entry_new_with_text(str);
1664 harbaum 223 g_signal_connect(G_OBJECT(widget), "changed",
1665     G_CALLBACK(callback_modified_angle), NULL);
1666     #else
1667     GtkWidget *widget = gtk_button_new_with_label(str);
1668    
1669     #ifdef FREMANTLE
1670     hildon_gtk_widget_set_theme_size(widget,
1671     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1672     #endif
1673     int angle_int = (int)roundf(angle*10.0);
1674     g_object_set_data(G_OBJECT(widget), "angle", (gpointer)angle_int);
1675     gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
1676     (GtkSignalFunc)on_angle_picker_button_press, NULL);
1677     #endif
1678     return widget;
1679     }
1680    
1681     float angle_entry_get(GtkWidget *widget) {
1682     #ifndef COORDINATE_PICKER
1683     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
1684     #else
1685     char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget));
1686     #endif
1687     return angle_parse(p);
1688     }
1689    
1690     void angle_entry_set(GtkWidget *widget, float angle) {
1691     char str[32];
1692     angle_str(str, sizeof(str)-1, angle);
1693     #ifndef COORDINATE_PICKER
1694     gtk_entry_set_text(GTK_ENTRY(widget), str);
1695     #else
1696     gtk_button_set_label(GTK_BUTTON(widget), str);
1697     int angle_int = (int)roundf(angle * 10.0);
1698     g_object_set_data(G_OBJECT(widget), "angle", (gpointer)angle_int);
1699     g_signal_emit_by_name(widget, "changed");
1700     #endif
1701     }
1702