Diff of /trunk/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 221 by harbaum, Mon Nov 30 21:28:04 2009 UTC revision 246 by harbaum, Tue Jan 19 20:26:37 2010 UTC
# Line 17  Line 17 
17   * along with GPXView.  If not, see <http://www.gnu.org/licenses/>.   * along with GPXView.  If not, see <http://www.gnu.org/licenses/>.
18   */   */
19    
20    /* TODO:
21    */
22    
23  #include <math.h>  #include <math.h>
24  #include <string.h>  #include <string.h>
25  #include <ctype.h>  #include <ctype.h>
# Line 26  Line 29 
29    
30  #include "gpxview.h"  #include "gpxview.h"
31    
32    #ifdef ENABLE_OSM_GPS_MAP
33    #include "osm-gps-map.h"
34    #endif
35    
36  #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)  #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
37  #include <hildon/hildon-entry.h>  #include <hildon/hildon-entry.h>
38  #include <hildon/hildon-touch-selector.h>  #include <hildon/hildon-touch-selector.h>
39  #include <hildon/hildon-picker-button.h>  #include <hildon/hildon-picker-button.h>
40  #include <hildon/hildon-picker-dialog.h>  #include <hildon/hildon-picker-dialog.h>
41    #include <hildon/hildon-check-button.h>
42  #endif  #endif
43    
44  float roundf(float x);  float roundf(float x);
45    
46  /* TODO: make coordinate picker support "changed" signal */  /* Enable special fremantle UI elements. These particular widgets */
47    /* don't use any hildon/fremantle specific parts and can thus even */
48    /* be used under plain gtk. This is mainly for testing and developemt */
49  #ifdef FREMANTLE  #ifdef FREMANTLE
50  #define PRESET_PICKER_DIALOG  #define PRESET_PICKER_DIALOG
51  #define COORDINATE_PICKER  #define COORDINATE_PICKER
52  #endif  #endif
53    
54    static const char *decimal_point(void) {
55      static const char *point = ".";
56    
57      struct lconv *lconv = localeconv();
58    
59      if(lconv && lconv->decimal_point)
60        return lconv->decimal_point;
61    
62      return point;
63    }
64    
65  char strlastchr(char *str) {  char strlastchr(char *str) {
66    return str[strlen(str)]-1;    return str[strlen(str)]-1;
67  }  }
# Line 311  float distance_parse(char *str, gboolean Line 331  float distance_parse(char *str, gboolean
331    
332  /* ------------------ coordinate picker tool --------------------------- */  /* ------------------ coordinate picker tool --------------------------- */
333    
334    #ifndef COORDINATE_PICKER
335  static gboolean mark(GtkWidget *widget, gboolean valid) {  static gboolean mark(GtkWidget *widget, gboolean valid) {
336    gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);    gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);
337    return valid;    return valid;
338  }  }
339    
340  #ifndef COORDINATE_PICKER  GtkWidget *red_entry_new_with_text(char *str) {
341      GdkColor color;
342    
343      GtkWidget *widget = entry_new();
344      gdk_color_parse("#ff0000", &color);
345      gtk_widget_modify_text(widget, TAG_STATE, &color);
346      if(str) gtk_entry_set_text(GTK_ENTRY(widget), str);
347    
348      return widget;
349    }
350    
351  static void callback_modified_lat(GtkWidget *widget, gpointer data ) {  static void callback_modified_lat(GtkWidget *widget, gpointer data ) {
352    float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));    float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
353    mark(widget, !isnan(i));    mark(widget, !isnan(i));
354  }  }
355  #else  #else
356  static GtkWidget *letter_picker_create(char *a, char *b, int sel) {  static void picker_center_iter(GtkWidget *view, GtkTreeIter *iter) {
357      /* select new iter */
358      GtkTreeSelection *selection =
359        gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
360      GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
361      gtk_tree_selection_select_iter(selection, iter);
362      GtkTreePath *path =
363        gtk_tree_model_get_path(model, iter);
364      gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view),
365                                   path, NULL, TRUE, 0.5, 0.5);
366      gtk_tree_path_free(path);
367    }
368    
369    static void on_picker_activated(GtkTreeView        *treeview,
370                                    GtkTreePath        *path,
371                                    GtkTreeViewColumn  *col,
372                                    gpointer            userdata) {
373      gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeview),
374                                   path, NULL, TRUE, 0.5, 0.5);
375    }
376    
377    #define DUMMY_NUM  1
378    
379    static void dummy_append(GtkListStore *store, int n) {
380      GtkTreeIter iter;
381    
382      while(n--) {
383        gtk_list_store_append (store, &iter);
384        gtk_list_store_set(store, &iter, 0, "", 1, -1, 2, FALSE, -1);
385      }
386    }
387    
388    static GtkWidget *string_picker_create(const char *str[], int sel) {
389  #ifndef FREMANTLE  #ifndef FREMANTLE
390    GtkWidget *view = gtk_tree_view_new();    GtkWidget *view = gtk_tree_view_new();
391  #else  #else
# Line 337  static GtkWidget *letter_picker_create(c Line 400  static GtkWidget *letter_picker_create(c
400    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
401    g_object_set(renderer, "xalign", 0.5, NULL );    g_object_set(renderer, "xalign", 0.5, NULL );
402    gtk_tree_view_insert_column_with_attributes(    gtk_tree_view_insert_column_with_attributes(
403        GTK_TREE_VIEW(view), -1, "char", renderer, "text", 0, NULL);        GTK_TREE_VIEW(view), -1, "str", renderer,
404          "text", 0,
405          "sensitive", 2,
406          NULL);
407    
408    GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);    GtkListStore *store =
409        gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN);
410    
411    /* add digits */    dummy_append(store, DUMMY_NUM);
412    GtkTreeIter iter_a, iter_b;  
413    gtk_list_store_append (store, &iter_a);    /* add strings */
414    gtk_list_store_set(store, &iter_a, 0, _(a), 1, 0, -1);    GtkTreeIter iter, siter;
415    gtk_list_store_append (store, &iter_b);    int i;
416    gtk_list_store_set(store, &iter_b, 0, _(b), 1, 1, -1);    for(i=0;*str;str++,i++) {
417        gtk_list_store_append (store, &iter);
418        gtk_list_store_set(store, &iter, 0, _(*str), 1, i, 2, TRUE, -1);
419        if(i == sel) siter = iter;
420      }
421    
422      dummy_append(store, DUMMY_NUM);
423    
424    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
425    g_object_unref(store);    g_object_unref(store);
426    
427    #ifndef FREMANTLE
428      g_signal_connect(view, "row-activated",
429                       (GCallback)on_picker_activated, NULL);
430    #else
431      g_signal_connect(view, "hildon-row-tapped",
432                       (GCallback)on_picker_activated, NULL);
433    #endif
434    
435    /* select right character */    /* select right character */
436    GtkTreeIter iter = (!sel)?iter_a:iter_b;    gtk_tree_selection_select_iter(selection, &siter);
437    gtk_tree_selection_select_iter(selection, &iter);    picker_center_iter(view, &siter);
   GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);  
   gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view),  
                                path, NULL, TRUE, 0.5, 0.5);  
   gtk_tree_path_free(path);  
438    
439    /* put this inside a scrolled view */    /* put this inside a scrolled view */
440  #ifndef USE_PANNABLE_AREA  #ifndef USE_PANNABLE_AREA
# Line 392  static int picker_get(GtkWidget *widget) Line 469  static int picker_get(GtkWidget *widget)
469    return retval;    return retval;
470  }  }
471    
   
472  static GtkWidget *digit_picker_create(int min, int max, int sel) {  static GtkWidget *digit_picker_create(int min, int max, int sel) {
473  #ifndef FREMANTLE  #ifndef FREMANTLE
474    GtkWidget *view = gtk_tree_view_new();    GtkWidget *view = gtk_tree_view_new();
# Line 408  static GtkWidget *digit_picker_create(in Line 484  static GtkWidget *digit_picker_create(in
484    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
485    g_object_set(renderer, "xalign", 0.5, NULL );    g_object_set(renderer, "xalign", 0.5, NULL );
486    gtk_tree_view_insert_column_with_attributes(    gtk_tree_view_insert_column_with_attributes(
487        GTK_TREE_VIEW(view), -1, "digit", renderer, "text", 0, NULL);        GTK_TREE_VIEW(view), -1, "digit", renderer,
488          "text", 0,
489          "sensitive", 2,
490          NULL);
491    
492    GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);    GtkListStore *store =
493        gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN);
494    
495      dummy_append(store, DUMMY_NUM);
496    
497    /* add digits */    /* add digits */
498    int i;    int i;
# Line 420  static GtkWidget *digit_picker_create(in Line 502  static GtkWidget *digit_picker_create(in
502      GtkTreeIter     iter;      GtkTreeIter     iter;
503      /* Append a row and fill in some data */      /* Append a row and fill in some data */
504      gtk_list_store_append (store, &iter);      gtk_list_store_append (store, &iter);
505      gtk_list_store_set(store, &iter, 0, str, 1, i, -1);      gtk_list_store_set(store, &iter, 0, str, 1, i, 2, TRUE, -1);
506    
507      if(i == sel) siter = iter;      if(i == sel) siter = iter;
508    }    }
509    
510      dummy_append(store, DUMMY_NUM);
511    
512    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
513    g_object_unref(store);    g_object_unref(store);
514    
515    #ifndef FREMANTLE
516      g_signal_connect(view, "row-activated",
517                       (GCallback)on_picker_activated, NULL);
518    #else
519      g_signal_connect(view, "hildon-row-tapped",
520                       (GCallback)on_picker_activated, NULL);
521    #endif
522    
523    gtk_tree_selection_select_iter(selection, &siter);    gtk_tree_selection_select_iter(selection, &siter);
524    GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &siter);    picker_center_iter(view, &siter);
   gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view),  
                                path, NULL, TRUE, 0.5, 0.5);  
   gtk_tree_path_free(path);  
525    
526    /* put this inside a scrolled view */    /* put this inside a scrolled view */
527  #ifndef USE_PANNABLE_AREA  #ifndef USE_PANNABLE_AREA
# Line 460  static gint on_lat_picker_button_press(G Line 549  static gint on_lat_picker_button_press(G
549            _("Done"),        GTK_RESPONSE_ACCEPT,            _("Done"),        GTK_RESPONSE_ACCEPT,
550            NULL);            NULL);
551    
552      gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200);      gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
553    
554      int i, lat = (int)g_object_get_data(G_OBJECT(button), "latitude");      int i, lat = (int)g_object_get_data(G_OBJECT(button), "latitude");
555    
# Line 476  static gint on_lat_picker_button_press(G Line 565  static gint on_lat_picker_button_press(G
565    
566      /* create N/S 89° 99.999 */      /* create N/S 89° 99.999 */
567      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
568        static const char *ns[] = { "N", "S", NULL };
569      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
570                  signw = letter_picker_create("N","S", sign));                  signw = string_picker_create(ns, sign));
571    
572      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
573                  degw[0] = digit_picker_create(0,8, deg/10));                  degw[0] = digit_picker_create(0,8, deg/10));
# Line 489  static gint on_lat_picker_button_press(G Line 579  static gint on_lat_picker_button_press(G
579                  minw[0] = digit_picker_create(0,5, min/10));                  minw[0] = digit_picker_create(0,5, min/10));
580      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
581                  minw[1] = digit_picker_create(0,9, min%10));                  minw[1] = digit_picker_create(0,9, min%10));
582      gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("."), FALSE, FALSE, 0);      gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(decimal_point()),
583                           FALSE, FALSE, 0);
584    
585      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
586                  minfracw[0] = digit_picker_create(0,9, minfrac/100));                  minfracw[0] = digit_picker_create(0,9, minfrac/100));
# Line 503  static gint on_lat_picker_button_press(G Line 594  static gint on_lat_picker_button_press(G
594      gtk_widget_show_all(dialog);      gtk_widget_show_all(dialog);
595      if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {      if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
596    
       /* parse N/S */  
       sign = picker_get(signw)?-1:1;  
   
597        /* parse degrees ... */        /* parse degrees ... */
598        for(deg=0,i=0;i<2;i++)        for(deg=0,i=0;i<2;i++)
599          deg = 10 * deg + picker_get(degw[i]);          deg = 10 * deg + picker_get(degw[i]);
# Line 518  static gint on_lat_picker_button_press(G Line 606  static gint on_lat_picker_button_press(G
606        for(minfrac=0,i=0;i<3;i++)        for(minfrac=0,i=0;i<3;i++)
607          minfrac = 10 * minfrac + picker_get(minfracw[i]);          minfrac = 10 * minfrac + picker_get(minfracw[i]);
608    
609          /* parse N/S */
610          if(deg | min | minfrac)
611            sign = picker_get(signw)?-1:1;
612          else
613            sign = 1;   // theres no S 00 00.000
614    
615        float latitude = sign * (deg + min/60.0 + minfrac/60000.0);        float latitude = sign * (deg + min/60.0 + minfrac/60000.0);
616        lat_entry_set(button, latitude);        lat_entry_set(button, latitude);
617      }      }
# Line 530  static gint on_lat_picker_button_press(G Line 624  static gint on_lat_picker_button_press(G
624  }  }
625  #endif  #endif
626    
627    /* whatever there is in the entry: if it's illegal make it */
628    #define ILLEGAL_LAT  "X --° --%s---'"
629    #define ILLEGAL_LON  "X ---° --%s---'"
630    
631    static void pos_lat_check(GtkWidget *widget) {
632      if(isnan(lat_entry_get(widget))) {
633        char *str = g_strdup_printf(ILLEGAL_LAT, decimal_point());
634    
635    #ifndef COORDINATE_PICKER
636        mark(widget, FALSE);
637        gtk_entry_set_text(GTK_ENTRY(widget), str);
638    #else
639        gtk_button_set_label(GTK_BUTTON(widget), str);
640    #endif
641    
642        g_free(str);
643      }
644    }
645    
646    static void pos_lon_check(GtkWidget *widget) {
647      if(isnan(lon_entry_get(widget))) {
648        char *str = g_strdup_printf(ILLEGAL_LON, decimal_point());
649    
650    #ifndef COORDINATE_PICKER
651        mark(widget, FALSE);
652        gtk_entry_set_text(GTK_ENTRY(widget), str);
653    #else
654        gtk_button_set_label(GTK_BUTTON(widget), str);
655    #endif
656    
657        g_free(str);
658      }
659    }
660    
661  /* a entry that is colored red when being "active" */  /* a entry that is colored red when being "active" */
662  GtkWidget *lat_entry_new(float lat) {  GtkWidget *lat_entry_new(float lat) {
663    char str[32];    char str[32];
664    pos_lat_str(str, sizeof(str), lat);    pos_lat_str(str, sizeof(str), lat);
665    
666  #ifndef COORDINATE_PICKER  #ifndef COORDINATE_PICKER
667    GdkColor color;    GtkWidget *widget = red_entry_new_with_text(str);
   
   GtkWidget *widget = entry_new();  
   gdk_color_parse("#ff0000", &color);  
   gtk_widget_modify_text(widget, TAG_STATE, &color);  
   
   gtk_entry_set_text(GTK_ENTRY(widget), str);  
668    
669    g_signal_connect(G_OBJECT(widget), "changed",    g_signal_connect(G_OBJECT(widget), "changed",
670                     G_CALLBACK(callback_modified_lat), NULL);                     G_CALLBACK(callback_modified_lat), NULL);
# Line 559  GtkWidget *lat_entry_new(float lat) { Line 681  GtkWidget *lat_entry_new(float lat) {
681    gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",    gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
682                       (GtkSignalFunc)on_lat_picker_button_press, NULL);                       (GtkSignalFunc)on_lat_picker_button_press, NULL);
683  #endif  #endif
684    
685      pos_lat_check(widget);
686    return widget;    return widget;
687  }  }
688    
# Line 581  static gint on_lon_picker_button_press(G Line 704  static gint on_lon_picker_button_press(G
704            _("Done"),        GTK_RESPONSE_ACCEPT,            _("Done"),        GTK_RESPONSE_ACCEPT,
705            NULL);            NULL);
706    
707      gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200);      gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
708    
709      int i, lat = (int)g_object_get_data(G_OBJECT(button), "longitude");      int i, lat = (int)g_object_get_data(G_OBJECT(button), "longitude");
710    
# Line 596  static gint on_lon_picker_button_press(G Line 719  static gint on_lon_picker_button_press(G
719    
720      /* create E/W 179° 99.999 */      /* create E/W 179° 99.999 */
721      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
722        static const char *ew[] = { "E", "W", NULL };
723      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
724                  signw = letter_picker_create("E","W", sign));                  signw = string_picker_create(ew, sign));
725    
726      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
727                  degw[0] = digit_picker_create(0,1, deg/100));                  degw[0] = digit_picker_create(0,1, deg/100));
# Line 611  static gint on_lon_picker_button_press(G Line 735  static gint on_lon_picker_button_press(G
735                  minw[0] = digit_picker_create(0,5, min/10));                  minw[0] = digit_picker_create(0,5, min/10));
736      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
737                  minw[1] = digit_picker_create(0,9, min%10));                  minw[1] = digit_picker_create(0,9, min%10));
738      gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("."), FALSE, FALSE, 0);      gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(decimal_point()),
739                           FALSE, FALSE, 0);
740    
741      gtk_box_pack_start_defaults(GTK_BOX(hbox),      gtk_box_pack_start_defaults(GTK_BOX(hbox),
742                  minfracw[0] = digit_picker_create(0,9, minfrac/100));                  minfracw[0] = digit_picker_create(0,9, minfrac/100));
# Line 625  static gint on_lon_picker_button_press(G Line 750  static gint on_lon_picker_button_press(G
750      gtk_widget_show_all(dialog);      gtk_widget_show_all(dialog);
751      if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {      if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
752    
       /* parse E/W */  
       sign = picker_get(signw)?-1:1;  
   
753        /* parse degrees ... */        /* parse degrees ... */
754        for(deg=0,i=0;i<3;i++)        for(deg=0,i=0;i<3;i++)
755          deg = 10 * deg + picker_get(degw[i]);          deg = 10 * deg + picker_get(degw[i]);
# Line 640  static gint on_lon_picker_button_press(G Line 762  static gint on_lon_picker_button_press(G
762        for(minfrac=0,i=0;i<3;i++)        for(minfrac=0,i=0;i<3;i++)
763          minfrac = 10 * minfrac + picker_get(minfracw[i]);          minfrac = 10 * minfrac + picker_get(minfracw[i]);
764    
765          if(deg | min | minfrac)
766            sign = picker_get(signw)?-1:1;
767          else
768            sign = 1;   // theres no W 00 00.000
769    
770        float longitude = sign * (deg + min/60.0 + minfrac/60000.0);        float longitude = sign * (deg + min/60.0 + minfrac/60000.0);
771        lon_entry_set(button, longitude);        lon_entry_set(button, longitude);
772      }      }
# Line 658  GtkWidget *lon_entry_new(float lon) { Line 785  GtkWidget *lon_entry_new(float lon) {
785    pos_lon_str(str, sizeof(str), lon);    pos_lon_str(str, sizeof(str), lon);
786    
787  #ifndef COORDINATE_PICKER  #ifndef COORDINATE_PICKER
788    GdkColor color;    GtkWidget *widget = red_entry_new_with_text(str);
   
   GtkWidget *widget = entry_new();  
   gdk_color_parse("#ff0000", &color);  
   gtk_widget_modify_text(widget, TAG_STATE, &color);  
   
   gtk_entry_set_text(GTK_ENTRY(widget), str);  
   
789    g_signal_connect(G_OBJECT(widget), "changed",    g_signal_connect(G_OBJECT(widget), "changed",
790                     G_CALLBACK(callback_modified_lon), NULL);                     G_CALLBACK(callback_modified_lon), NULL);
791    
# Line 682  GtkWidget *lon_entry_new(float lon) { Line 802  GtkWidget *lon_entry_new(float lon) {
802                       (GtkSignalFunc)on_lon_picker_button_press, NULL);                       (GtkSignalFunc)on_lon_picker_button_press, NULL);
803  #endif  #endif
804    
805      pos_lon_check(widget);
806    return widget;    return widget;
807  }  }
808    
# Line 712  void lat_entry_set(GtkWidget *widget, fl Line 833  void lat_entry_set(GtkWidget *widget, fl
833    gtk_button_set_label(GTK_BUTTON(widget), str);    gtk_button_set_label(GTK_BUTTON(widget), str);
834    int lat_int = (int)roundf(lat * 60000);    int lat_int = (int)roundf(lat * 60000);
835    g_object_set_data(G_OBJECT(widget), "latitude", (gpointer)lat_int);    g_object_set_data(G_OBJECT(widget), "latitude", (gpointer)lat_int);
836      g_signal_emit_by_name(widget, "changed");
837  #endif  #endif
838      pos_lat_check(widget);
839  }  }
840    
841  void lon_entry_set(GtkWidget *widget, float lon) {  void lon_entry_set(GtkWidget *widget, float lon) {
# Line 724  void lon_entry_set(GtkWidget *widget, fl Line 847  void lon_entry_set(GtkWidget *widget, fl
847    gtk_button_set_label(GTK_BUTTON(widget), str);    gtk_button_set_label(GTK_BUTTON(widget), str);
848    int lon_int = (int)roundf(lon * 60000);    int lon_int = (int)roundf(lon * 60000);
849    g_object_set_data(G_OBJECT(widget), "longitude", (gpointer)lon_int);    g_object_set_data(G_OBJECT(widget), "longitude", (gpointer)lon_int);
850      g_signal_emit_by_name(widget, "changed");
851  #endif  #endif
852      pos_lon_check(widget);
853  }  }
854    
855  void lat_label_set(GtkWidget *widget, float lat) {  void lat_label_set(GtkWidget *widget, float lat) {
# Line 753  void lon_label_attrib_set(GtkWidget *wid Line 878  void lon_label_attrib_set(GtkWidget *wid
878    gtk_label_attrib_set(widget, str, size, strikethrough);    gtk_label_attrib_set(widget, str, size, strikethrough);
879  }  }
880    
881    #ifndef COORDINATE_PICKER
882  static void callback_modified_dist(GtkWidget *widget, gpointer data ) {  static void callback_modified_dist(GtkWidget *widget, gpointer data ) {
883    /* don't care for metric/imperial since we only want to know if this */    /* don't care for metric/imperial since we only want to know if this */
884    /* is parseable at all */    /* is parseable at all */
885    float i = distance_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);    float i =
886        distance_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);
887    mark(widget, !isnan(i));    mark(widget, !isnan(i));
888  }  }
889    #else
890    static gint on_dist_picker_button_press(GtkWidget *button,
891                       GdkEventButton *event, gpointer data) {
892    
893      if(event->type == GDK_BUTTON_PRESS) {
894        GtkWidget *dialog =
895          gtk_dialog_new_with_buttons(_("Distance"),
896              GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
897                                      GTK_DIALOG_MODAL,
898              GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
899              _("Done"),        GTK_RESPONSE_ACCEPT,
900              NULL);
901    
902        gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
903    
904        /* distance is given in m or ft (depending on mil) */
905        int i, dist = (int)g_object_get_data(G_OBJECT(button), "distance");
906        gboolean mil = (gboolean)g_object_get_data(G_OBJECT(button), "mil");
907        int unit = 0;
908    
909        /* parse distance into components */
910        if(mil) {
911          /* 1 mil = 1760 yd = 5280 ft. 1yd = 3 ft */
912          if(dist<95)        { unit = 0; dist *= 100;  }
913          else if(dist<2904) { unit = 1; dist = 100 * dist / 3;  }
914          else               { unit = 2; dist = 5 * dist / 264; }
915        } else {
916          if(dist<1000)      { unit = 3; dist *= 100;  }
917          else               { unit = 4; dist /= 10; }
918        }
919    
920        GtkWidget *distw[4], *fracw[2], *unitw;
921    
922        /* create xxxx.x unit */
923        GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
924    
925        gtk_box_pack_start_defaults(GTK_BOX(hbox),
926                    distw[0] = digit_picker_create(0,9, (dist/100000)%10));
927        gtk_box_pack_start_defaults(GTK_BOX(hbox),
928                    distw[1] = digit_picker_create(0,9, (dist/10000)%10));
929        gtk_box_pack_start_defaults(GTK_BOX(hbox),
930                    distw[2] = digit_picker_create(0,9, (dist/1000)%10));
931        gtk_box_pack_start_defaults(GTK_BOX(hbox),
932                    distw[3] = digit_picker_create(0,9, (dist/100)%10));
933        gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" . "), FALSE, FALSE, 0);
934        gtk_box_pack_start_defaults(GTK_BOX(hbox),
935                    fracw[0] = digit_picker_create(0,9, (dist/10)%10));
936        gtk_box_pack_start_defaults(GTK_BOX(hbox),
937                    fracw[1] = digit_picker_create(0,9, (dist/1)%10));
938    
939        static const char *units[] = { "ft", "yd", "mi", "m", "km", NULL };
940        gtk_box_pack_start_defaults(GTK_BOX(hbox),
941                    unitw = string_picker_create(units, unit));
942    
943        gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
944    
945        gtk_widget_show_all(dialog);
946        if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
947    
948          /* parse distance */
949          for(dist=0,i=0;i<4;i++)
950            dist = 10 * dist + picker_get(distw[i]);
951    
952          for(i=0;i<2;i++)
953            dist = 10 * dist + picker_get(fracw[i]);
954    
955          unit = picker_get(unitw);
956          if(unit == 0)      { dist /= 100; }         // ft
957          else if(unit == 1) { dist = 3*dist/100; }   // yd
958          else if(unit == 2) { dist = 528*dist/10; }  // mi
959          else if(unit == 3) { dist /= 100; }         // m
960          else if(unit == 4) { dist *= 10; }          // km
961    
962          /* user may have switched between metric and imperial */
963          float distance;
964          if(unit <= 2) {
965            distance = dist / 5280.0;
966            if(!mil) distance *=  1.609344;
967          } else {
968            distance = dist / 1000.0;
969            if( mil) distance /=  1.609344;
970          }
971    
972          dist_entry_set(button, distance, mil);
973        }
974    
975        gtk_widget_destroy(dialog);
976    
977        return TRUE;
978      }
979      return FALSE;
980    }
981    #endif
982    
983  /* a entry that is colored red when filled with invalid distance */  /* a entry that is colored red when filled with invalid distance */
984  GtkWidget *dist_entry_new(float dist, gboolean mil) {  GtkWidget *dist_entry_new(float dist, gboolean mil) {
   GdkColor color;  
   GtkWidget *widget = entry_new();  
   gdk_color_parse("#ff0000", &color);  
   gtk_widget_modify_text(widget, TAG_STATE, &color);  
   
985    char str[32];    char str[32];
986    distance_str(str, sizeof(str), dist, mil);    distance_str(str, sizeof(str), dist, mil);
   gtk_entry_set_text(GTK_ENTRY(widget), str);  
987    
988    #ifndef COORDINATE_PICKER
989      GtkWidget *widget = red_entry_new_with_text(str);
990    g_signal_connect(G_OBJECT(widget), "changed",    g_signal_connect(G_OBJECT(widget), "changed",
991                     G_CALLBACK(callback_modified_dist), NULL);                     G_CALLBACK(callback_modified_dist), NULL);
992    
993    #else
994      GtkWidget *widget = gtk_button_new_with_label(str);
995    
996    #ifdef FREMANTLE
997      hildon_gtk_widget_set_theme_size(widget,
998            (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
999    #endif
1000      int dist_int = (int)roundf(dist * 1000);        // km -> m
1001      if(mil) dist_int = (int)roundf(dist * 5280.0);  // mi -> ft
1002    
1003      g_object_set_data(G_OBJECT(widget), "distance", (gpointer)dist_int);
1004      g_object_set_data(G_OBJECT(widget), "mil", (gpointer)mil);
1005      gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
1006                         (GtkSignalFunc)on_dist_picker_button_press, NULL);
1007    #endif
1008    
1009    return widget;    return widget;
1010  }  }
1011    
1012  float dist_get(GtkWidget *widget, gboolean mil) {  float dist_entry_get(GtkWidget *widget, gboolean mil) {
1013    #ifndef COORDINATE_PICKER
1014    char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));    char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
1015    #else
1016      char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget));
1017    #endif
1018    return distance_parse(p, mil);    return distance_parse(p, mil);
1019  }  }
1020    
1021    void dist_entry_set(GtkWidget *widget, float dist, gboolean mil) {
1022      char str[32];
1023      distance_str(str, sizeof(str), dist, mil);
1024    
1025    #ifndef COORDINATE_PICKER
1026      gtk_entry_set_text(GTK_ENTRY(widget), str);
1027    #else
1028      gtk_button_set_label(GTK_BUTTON(widget), str);
1029      int dist_int = (int)roundf(dist * 1000);        // km -> m
1030      if(mil) dist_int = (int)roundf(dist * 5280.0);  // mi -> ft
1031      g_object_set_data(G_OBJECT(widget), "distance", (gpointer)dist_int);
1032      g_object_set_data(G_OBJECT(widget), "mil", (gpointer)mil);
1033      g_signal_emit_by_name(widget, "changed");
1034    #endif
1035    }
1036    
1037  #ifndef USE_MAEMO  #ifndef USE_MAEMO
1038  #ifdef ENABLE_BROWSER_INTERFACE  #ifdef ENABLE_BROWSER_INTERFACE
1039  #include <libgnome/gnome-url.h>  #include <libgnome/gnome-url.h>
# Line 973  static void cb_map(GtkWidget *item, gpoi Line 1225  static void cb_map(GtkWidget *item, gpoi
1225  }  }
1226  #endif  #endif
1227    
1228    #ifdef ENABLE_MAEMO_MAPPER
1229    static void cb_mm(GtkWidget *item, gpointer data) {
1230      appdata_t *appdata = (appdata_t*)data;
1231    
1232      pos_set(item, appdata->mmpos.lat, appdata->mmpos.lon);
1233    }
1234    #endif
1235    
1236  static void cb_cache(GtkWidget *item, gpointer data) {  static void cb_cache(GtkWidget *item, gpointer data) {
1237    appdata_t *appdata = (appdata_t*)data;    appdata_t *appdata = (appdata_t*)data;
1238    
# Line 983  static void cb_cache(GtkWidget *item, gp Line 1243  static void cb_cache(GtkWidget *item, gp
1243    
1244    if(!id)    if(!id)
1245      pos_set(item, cache->pos.lat, cache->pos.lon);      pos_set(item, cache->pos.lat, cache->pos.lon);
1246    else if(id == 1)    else if(id == 1) {
1247      pos_set(item, cache->notes->pos.lat, cache->notes->pos.lon);      /* fetch position out of notes dialog since they probably */
1248    else {      /* haven't been saved yet */
1249        pos_t pos = notes_get_pos(appdata->cache_context);
1250        pos_set(item, pos.lat, pos.lon);
1251      } else {
1252      wpt_t *wpt = cache->wpt;      wpt_t *wpt = cache->wpt;
1253      while(wpt && id > 2) {      while(wpt && id > 2) {
1254        wpt = wpt->next;        wpt = wpt->next;
# Line 1025  static GtkWidget *popup_menu_create(appd Line 1288  static GtkWidget *popup_menu_create(appd
1288                      GtkWidget *lat_entry, GtkWidget *lon_entry) {                      GtkWidget *lat_entry, GtkWidget *lon_entry) {
1289    GtkWidget *menu = gtk_menu_new();    GtkWidget *menu = gtk_menu_new();
1290    
1291    menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),    if(pos_valid(gps_get_pos(appdata)))
1292             _("GPS position"), cb_gps, 0, lon_entry, lat_entry);      menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),
1293                 _("GPS position"), cb_gps, 0, lon_entry, lat_entry);
1294    
1295    menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),    if(pos_valid(&appdata->home))
1296             _("Home"), cb_gps, 1, lon_entry, lat_entry);      menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),
1297                 _("Home"), cb_gps, 1, lon_entry, lat_entry);
1298    
1299    location_t *location = appdata->location;    location_t *location = appdata->location;
1300    gint id = 2;    gint id = 2;
1301    while(location) {    while(location) {
1302      menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),      if(pos_valid(&location->pos))
1303                 location->name, cb_gps, id++, lon_entry, lat_entry);        menu_add(menu, appdata, icon_get_widget(ICON_POS, 17),
1304                   location->name, cb_gps, id, lon_entry, lat_entry);
1305    
1306        id++;
1307      location = location->next;      location = location->next;
1308    }    }
1309    
1310    menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),    if(pos_valid(&appdata->geomath))
1311             _("Geomath projection"), cb_geomath, 0, lon_entry, lat_entry);      menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),
1312                 _("Geomath projection"), cb_geomath, 0, lon_entry, lat_entry);
1313    
1314  #ifdef ENABLE_OSM_GPS_MAP  #ifdef ENABLE_OSM_GPS_MAP
1315    menu_add(menu, appdata, icon_get_widget(ICON_POS, 20),    if(pos_valid(&appdata->map.pos))
1316             _("Map position"), cb_map, 0, lon_entry, lat_entry);      menu_add(menu, appdata, icon_get_widget(ICON_POS, 20), _("Map position"),
1317                 cb_map, 0, lon_entry, lat_entry);
1318    #endif
1319    
1320    #ifdef ENABLE_MAEMO_MAPPER
1321      if(appdata->mmpos_valid) {
1322        menu_add(menu, appdata, icon_get_widget(ICON_POS, 24),
1323                 _("Maemo Mapper position"), cb_mm, 0, lon_entry, lat_entry);
1324      }
1325  #endif  #endif
1326    
1327    if(appdata->cur_cache) {    if(appdata->cur_cache) {
# Line 1054  static GtkWidget *popup_menu_create(appd Line 1331  static GtkWidget *popup_menu_create(appd
1331      if(!name) name = cache->id;      if(!name) name = cache->id;
1332    
1333      /* original cache position */      /* original cache position */
1334      if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {      if(pos_valid(&cache->pos))
1335        menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),        menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
1336                 name, cb_cache, 0, lon_entry, lat_entry);                 name, cb_cache, 0, lon_entry, lat_entry);
     }  
1337    
1338      /* overwritten cache position */      /* overwritten cache position */
1339      if(cache->notes &&      if(appdata->cache_context && notes_get_override(appdata->cache_context))
        !isnan(cache->notes->pos.lat) && !isnan(cache->notes->pos.lon)) {  
1340        menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),        menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
1341                 _("Modified coordinate"), cb_cache, 1, lon_entry, lat_entry);                 _("Modified coordinate"), cb_cache, 1, lon_entry, lat_entry);
     }  
1342    
1343      wpt_t *wpt = cache->wpt;      wpt_t *wpt = cache->wpt;
1344      gint id = 2;      gint id = 2;
1345      while(wpt) {      while(wpt) {
1346        GtkWidget *icon = NULL;        if(pos_valid(&wpt->pos)) {
1347        if(wpt->sym != WPT_SYM_UNKNOWN)          GtkWidget *icon = NULL;
1348          icon = icon_get_widget(ICON_POS, wpt->sym);          if(wpt->sym != WPT_SYM_UNKNOWN)
1349              icon = icon_get_widget(ICON_POS, wpt->sym);
1350        char *name = wpt->desc;  
1351        if(!name) name = wpt->cmt;          char *name = wpt->desc;
1352        if(!name) name = wpt->id;          if(!name) name = wpt->cmt;
1353            if(!name) name = wpt->id;
1354        menu_add(menu, appdata, icon, name, cb_cache, id++,  
1355                 lon_entry, lat_entry);          menu_add(menu, appdata, icon, name, cb_cache, id,
1356                     lon_entry, lat_entry);
1357          }
1358    
1359          id++;
1360        wpt = wpt->next;        wpt = wpt->next;
1361      }      }
1362    }    }
# Line 1092  static GtkWidget *popup_menu_create(appd Line 1369  static GtkWidget *popup_menu_create(appd
1369  static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,  static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
1370                                    gpointer data) {                                    gpointer data) {
1371    
1372      appdata_t *appdata = (appdata_t*)data;
1373    
1374    if(event->type == GDK_BUTTON_PRESS) {    if(event->type == GDK_BUTTON_PRESS) {
1375      GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");      GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
1376    
1377        if(menu)
1378          gtk_widget_destroy(menu);
1379    
1380        gpointer lat_entry = g_object_get_data(G_OBJECT(button), "lat_entry");
1381        g_assert(lat_entry);
1382        gpointer lon_entry = g_object_get_data(G_OBJECT(button), "lon_entry");
1383        g_assert(lon_entry);
1384    
1385        menu = popup_menu_create(appdata, lat_entry, lon_entry);
1386        g_object_set_data(G_OBJECT(button), "menu", (gpointer)menu);
1387    
1388      /* draw a popup menu */      /* draw a popup menu */
1389      gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,      gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1390                     event->button, event->time);                     event->button, event->time);
# Line 1105  static gint on_popup_button_press(GtkWid Line 1395  static gint on_popup_button_press(GtkWid
1395    
1396  static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {  static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
1397    GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");    GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
1398    gtk_widget_destroy(menu);    if(menu) gtk_widget_destroy(menu);
1399  }  }
1400  #endif  #endif
1401    
# Line 1189  static GtkWidget *preset_picker_create(a Line 1479  static GtkWidget *preset_picker_create(a
1479                               G_TYPE_INT,                               G_TYPE_INT,
1480                               G_TYPE_POINTER);                               G_TYPE_POINTER);
1481    
1482    preset_picker_add(store, appdata, icon_get(ICON_POS, 18),    if(pos_valid(gps_get_pos(appdata)))
1483               _("GPS position"), cb_gps, 0);      preset_picker_add(store, appdata, icon_get(ICON_POS, 18),
1484                          _("GPS position"), cb_gps, 0);
1485    
1486    preset_picker_add(store, appdata, icon_get(ICON_POS, 21),    if(pos_valid(&appdata->home))
1487               _("Home"), cb_gps, 1);      preset_picker_add(store, appdata, icon_get(ICON_POS, 21),
1488                          _("Home"), cb_gps, 1);
1489    
1490    location_t *location = appdata->location;    location_t *location = appdata->location;
1491    gint id = 2;    gint id = 2;
1492    while(location) {    while(location) {
1493      preset_picker_add(store, appdata, icon_get(ICON_POS, 21),      if(pos_valid(&location->pos))
1494                 location->name, cb_gps, id++);        preset_picker_add(store, appdata, icon_get(ICON_POS, 17),
1495                            location->name, cb_gps, id);
1496    
1497        id++;
1498      location = location->next;      location = location->next;
1499    }    }
1500    
1501    preset_picker_add(store, appdata, icon_get(ICON_POS, 19),    if(pos_valid(&appdata->geomath))
1502               _("Geomath projection"), cb_geomath, 0);      preset_picker_add(store, appdata, icon_get(ICON_POS, 19),
1503                          _("Geomath projection"), cb_geomath, 0);
1504    
1505  #ifdef ENABLE_OSM_GPS_MAP  #ifdef ENABLE_OSM_GPS_MAP
1506    preset_picker_add(store, appdata, icon_get(ICON_POS, 20),    if(pos_valid(&appdata->map.pos))
1507               _("Map position"), cb_map, 0);      preset_picker_add(store, appdata, icon_get(ICON_POS, 20),
1508                          _("Map position"), cb_map, 0);
1509    #endif
1510    
1511    #ifdef ENABLE_MAEMO_MAPPER
1512      if(appdata->mmpos_valid) {
1513        preset_picker_add(store, appdata, icon_get(ICON_POS, 24),
1514                          _("Maemo Mapper position"), cb_mm, 0);
1515      }
1516  #endif  #endif
1517    
1518    if(appdata->cur_cache) {    if(appdata->cur_cache) {
# Line 1216  static GtkWidget *preset_picker_create(a Line 1520  static GtkWidget *preset_picker_create(a
1520    
1521      char *name = cache->name;      char *name = cache->name;
1522      if(!name) name = cache->id;      if(!name) name = cache->id;
1523    
1524      /* original cache position */      /* original cache position */
1525      if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {      if(pos_valid(&cache->pos))
1526        preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),        preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),
1527                   name, cb_cache, 0);                          name, cb_cache, 0);
     }  
1528    
1529      /* overwritten cache position */      /* overwritten cache position */
1530      if(cache->notes &&      if(appdata->cache_context && notes_get_override(appdata->cache_context))
        !isnan(cache->notes->pos.lat) && !isnan(cache->notes->pos.lon)) {  
1531        preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),        preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),
1532                   _("Modified coordinate"), cb_cache, 1);                          _("Modified coordinate"), cb_cache, 1);
     }  
1533    
1534      wpt_t *wpt = cache->wpt;      wpt_t *wpt = cache->wpt;
1535      gint id = 2;      gint id = 2;
1536      while(wpt) {      while(wpt) {
1537        GdkPixbuf *icon = NULL;        if(pos_valid(&wpt->pos)) {
1538        if(wpt->sym != WPT_SYM_UNKNOWN)          GdkPixbuf *icon = NULL;
1539          icon = icon_get(ICON_POS, wpt->sym);          if(wpt->sym != WPT_SYM_UNKNOWN)
1540              icon = icon_get(ICON_POS, wpt->sym);
1541        char *name = wpt->desc;  
1542        if(!name) name = wpt->cmt;          char *name = wpt->desc;
1543        if(!name) name = wpt->id;          if(!name) name = wpt->cmt;
1544            if(!name) name = wpt->id;
1545    
1546        preset_picker_add(store, appdata, icon, name, cb_cache, id++);          preset_picker_add(store, appdata, icon, name, cb_cache, id);
1547          }
1548          id++;
1549        wpt = wpt->next;        wpt = wpt->next;
1550      }      }
1551    }    }
1552    
   
1553    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
1554    g_object_unref(store);    g_object_unref(store);
1555    
# Line 1277  static gint on_preset_picker_button_pres Line 1580  static gint on_preset_picker_button_pres
1580    
1581    if(event->type == GDK_BUTTON_PRESS) {    if(event->type == GDK_BUTTON_PRESS) {
1582      GtkWidget *dialog =      GtkWidget *dialog =
1583        gtk_dialog_new_with_buttons(_("Preset coordinates"),        gtk_dialog_new_with_buttons(_("Use coordinate"),
1584            GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),            GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
1585                                    GTK_DIALOG_MODAL,                                    GTK_DIALOG_MODAL,
1586            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1587            NULL);            NULL);
1588    
1589      gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200);      gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
1590    
1591      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1592                          preset_picker_create(appdata, lat_entry, lon_entry));                          preset_picker_create(appdata, lat_entry, lon_entry));
# Line 1298  static gint on_preset_picker_button_pres Line 1601  static gint on_preset_picker_button_pres
1601  }  }
1602  #endif  #endif
1603    
 void preset_coordinate_picker_update(appdata_t *appdata, GtkWidget *widget) {  
 #ifndef PRESET_PICKER_DIALOG  
   printf("updating popup menu\n");  
   
   GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");  
   g_assert(menu);  
   gtk_widget_destroy(menu);  
   
   gpointer lat_entry = g_object_get_data(G_OBJECT(widget), "lat_entry");  
   g_assert(lat_entry);  
   gpointer lon_entry = g_object_get_data(G_OBJECT(widget), "lon_entry");  
   g_assert(lon_entry);  
   
   menu = popup_menu_create(appdata, lat_entry, lon_entry);  
   g_object_set_data(G_OBJECT(widget), "menu", (gpointer)menu);  
 #endif  
 }  
1604    
1605  GtkWidget *preset_coordinate_picker(appdata_t *appdata,  GtkWidget *preset_coordinate_picker(appdata_t *appdata,
1606                       GtkWidget *lat_entry, GtkWidget *lon_entry) {                       GtkWidget *lat_entry, GtkWidget *lon_entry) {
1607    
1608    GtkWidget *button = gtk_button_new();    GtkWidget *button = gtk_button_new();
1609    
1610    gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));    gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 22));
   
   gtk_widget_set_tooltip_text(button, _("Preset coordinates"));  
1611    
1612    g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry);  #ifndef USE_MAEMO
1613    g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry);    gtk_widget_set_tooltip_text(button, _("Use coordinate"));
1614    #endif
1615    
1616    g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry);    g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry);
1617    g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry);    g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry);
# Line 1337  GtkWidget *preset_coordinate_picker(appd Line 1622  GtkWidget *preset_coordinate_picker(appd
1622    
1623    gtk_signal_connect(GTK_OBJECT(button), "destroy",    gtk_signal_connect(GTK_OBJECT(button), "destroy",
1624                       (GtkSignalFunc)on_popup_destroy, appdata);                       (GtkSignalFunc)on_popup_destroy, appdata);
   
   g_object_set_data(G_OBJECT(button), "menu",  
                     popup_menu_create(appdata, lat_entry, lon_entry));  
1625  #else  #else
1626  #ifdef FREMANTLE  #ifdef FREMANTLE
1627    hildon_gtk_widget_set_theme_size(button,    hildon_gtk_widget_set_theme_size(button,
# Line 1353  GtkWidget *preset_coordinate_picker(appd Line 1635  GtkWidget *preset_coordinate_picker(appd
1635    return button;    return button;
1636  }  }
1637    
1638  GtkWidget *entry_new(void) {  #if defined(ENABLE_MAEMO_MAPPER) || defined(ENABLE_OSM_GPS_MAP)
1639  #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)  static pos_t goto_pos_get(GtkWidget *item) {
1640    return gtk_entry_new();    pos_t pos;
1641  #else  
1642    return hildon_entry_new(HILDON_SIZE_AUTO);    GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
1643  #endif    pos.lat = lat_entry_get(lat_entry);
1644    
1645      GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
1646      pos.lon = lon_entry_get(lon_entry);
1647    
1648      return  pos;
1649  }  }
1650    
1651  gboolean pos_differ(pos_t *pos1, pos_t *pos2) {  #if defined(ENABLE_MAEMO_MAPPER) && defined(ENABLE_OSM_GPS_MAP)
1652    int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;  #ifdef ENABLE_MAEMO_MAPPER
1653    int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;  static void cb_mm_set(GtkWidget *item, gpointer data) {
1654      appdata_t *appdata = (appdata_t*)data;
1655    
1656    return((lat1 != lat2) || (lon1 != lon2));    pos_t pos = goto_pos_get(item);
1657      if(!isnan(pos.lat) && !isnan(pos.lon))
1658        dbus_mm_set_position(appdata, &pos);
1659    }
1660    #endif
1661    
1662    #ifdef ENABLE_OSM_GPS_MAP
1663    static void cb_map_set(GtkWidget *item, gpointer data) {
1664      appdata_t *appdata = (appdata_t*)data;
1665    
1666      pos_t pos = goto_pos_get(item);
1667      if(!isnan(pos.lat) && !isnan(pos.lon)) {
1668        map(appdata);
1669        osm_gps_map_set_center(OSM_GPS_MAP(appdata->map.context->widget),
1670                                 pos.lat, pos.lon);
1671      }
1672  }  }
1673    #endif
1674    
1675    #ifndef PRESET_PICKER_DIALOG
1676    static GtkWidget *goto_popup_menu_create(appdata_t *appdata,
1677                        GtkWidget *lat_entry, GtkWidget *lon_entry) {
1678      GtkWidget *menu = gtk_menu_new();
1679    
1680    #if defined(ENABLE_OSM_GPS_MAP)
1681      menu_add(menu, appdata, icon_get_widget(ICON_POS, 20),
1682               _("Internal map"), cb_map_set, 0, lon_entry, lat_entry);
1683    #endif
1684    
1685    #if defined(ENABLE_MAEMO_MAPPER)
1686      menu_add(menu, appdata, icon_get_widget(ICON_POS, 24),
1687               _("Maemo Mapper"), cb_mm_set, 0, lon_entry, lat_entry);
1688    #endif
1689    
1690      gtk_widget_show_all(menu);
1691    
1692      return menu;
1693    }
1694    #else
1695    static GtkWidget *goto_picker_create(appdata_t *appdata,
1696                         GtkWidget *lat_entry, GtkWidget *lon_entry) {
1697      GtkCellRenderer *renderer;
1698      GtkListStore    *store;
1699    
1700      GtkWidget *view = gtk_tree_view_new();
1701    
1702      g_object_set_data(G_OBJECT(view), "lat_entry", (gpointer)lat_entry);
1703      g_object_set_data(G_OBJECT(view), "lon_entry", (gpointer)lon_entry);
1704    
1705      /* --- "Icon" column --- */
1706      renderer = gtk_cell_renderer_pixbuf_new();
1707      gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
1708          -1, "Icon", renderer, "pixbuf", PRESET_PICKER_COL_ICON, NULL);
1709    
1710      /* --- "Name" column --- */
1711      renderer = gtk_cell_renderer_text_new();
1712      g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
1713      GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
1714                     "Name", renderer, "text", PRESET_PICKER_COL_NAME, NULL);
1715      gtk_tree_view_column_set_expand(column, TRUE);
1716      gtk_tree_view_insert_column(GTK_TREE_VIEW(view), column, -1);
1717    
1718      store = gtk_list_store_new(PRESET_PICKER_NUM_COLS,
1719                                 GDK_TYPE_PIXBUF,
1720                                 G_TYPE_STRING,
1721                                 G_TYPE_INT,
1722                                 G_TYPE_POINTER);
1723    
1724    #if defined(ENABLE_OSM_GPS_MAP)
1725      preset_picker_add(store, appdata, icon_get(ICON_POS, 20),
1726                        _("Internal map"), cb_map_set, 0);
1727    #endif
1728    
1729    #if defined(ENABLE_MAEMO_MAPPER)
1730      preset_picker_add(store, appdata, icon_get(ICON_POS, 24),
1731                        _("Maemo Mapper"), cb_mm_set, 0);
1732    #endif
1733    
1734      gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
1735      g_object_unref(store);
1736    
1737      /* make list react on clicks */
1738      g_signal_connect(view, "row-activated",
1739                       (GCallback)on_preset_picker_activated, appdata);
1740    
1741      /* put this inside a scrolled view */
1742    #ifndef USE_PANNABLE_AREA
1743      GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1744      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
1745                                     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1746      gtk_container_add(GTK_CONTAINER(scrolled_window), view);
1747      return scrolled_window;
1748    #else
1749      GtkWidget *pannable_area = hildon_pannable_area_new();
1750      gtk_container_add(GTK_CONTAINER(pannable_area), view);
1751      return pannable_area;
1752    #endif
1753    }
1754    #endif
1755    #endif
1756    
1757    static gint on_goto_button_press(GtkWidget *button,
1758                                     GdkEventButton *event, gpointer data) {
1759      appdata_t *appdata = (appdata_t*)data;
1760    
1761      if(event->type == GDK_BUTTON_PRESS) {
1762    
1763    #if defined(ENABLE_MAEMO_MAPPER) && !defined(ENABLE_OSM_GPS_MAP)
1764        /* only maemo mapper is being used */
1765        pos_t pos = goto_pos_get(button);
1766        if(!isnan(pos.lat) && !isnan(pos.lon))
1767          dbus_mm_set_position(appdata, &pos);
1768    #elif !defined(ENABLE_MAEMO_MAPPER) && defined(ENABLE_OSM_GPS_MAP)
1769        /* only internal map is being used */
1770        pos_t pos = goto_pos_get(button);
1771        if(!isnan(pos.lat) && !isnan(pos.lon)) {
1772          map(appdata);
1773          osm_gps_map_set_center(OSM_GPS_MAP(appdata->map.context->widget),
1774                                 pos.lat, pos.lon);
1775        }
1776    #else
1777    
1778        gpointer lat_entry = g_object_get_data(G_OBJECT(button), "lat_entry");
1779        g_assert(lat_entry);
1780        gpointer lon_entry = g_object_get_data(G_OBJECT(button), "lon_entry");
1781        g_assert(lon_entry);
1782    
1783    #ifndef PRESET_PICKER_DIALOG
1784        GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
1785        if(!menu) {
1786          menu = goto_popup_menu_create(appdata, lat_entry, lon_entry);
1787          g_object_set_data(G_OBJECT(button), "menu", (gpointer)menu);
1788        }
1789    
1790        /* draw a popup menu */
1791        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1792                       event->button, event->time);
1793    #else
1794        GtkWidget *dialog =
1795          gtk_dialog_new_with_buttons(_("Show coordinate on map"),
1796              GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
1797                                      GTK_DIALOG_MODAL,
1798              GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1799              NULL);
1800    
1801        gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
1802    
1803        gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1804                            goto_picker_create(appdata, lat_entry, lon_entry));
1805    
1806        gtk_widget_show_all(dialog);
1807        gtk_dialog_run(GTK_DIALOG(dialog));
1808        gtk_widget_destroy(dialog);
1809    #endif
1810    
1811    #endif
1812    
1813        return TRUE;
1814      }
1815      return FALSE;
1816    }
1817    
1818    /* a button which makes the map/maemo mapper go to the associated */
1819    /* position */
1820    GtkWidget *goto_coordinate(appdata_t *appdata,
1821                         GtkWidget *lat_entry, GtkWidget *lon_entry) {
1822    
1823      GtkWidget *button = gtk_button_new();
1824    
1825      gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 23));
1826    
1827    #ifndef USE_MAEMO
1828      gtk_widget_set_tooltip_text(button, _("Show coordinate on map"));
1829    #endif
1830    
1831      g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry);
1832      g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry);
1833    
1834      gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
1835                         (GtkSignalFunc)on_goto_button_press, appdata);
1836    
1837    #ifndef PRESET_PICKER_DIALOG
1838      gtk_signal_connect(GTK_OBJECT(button), "destroy",
1839                         (GtkSignalFunc)on_popup_destroy, appdata);
1840    #else
1841    #ifdef FREMANTLE
1842      hildon_gtk_widget_set_theme_size(button,
1843            (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1844    #endif
1845    #endif
1846    
1847      return button;
1848    }
1849    #else
1850    /* no map installed */
1851    GtkWidget *goto_coordinate(appdata_t *appdata,
1852                         GtkWidget *lat_entry, GtkWidget *lon_entry) {
1853      return gtk_label_new("");
1854    }
1855    #endif
1856    
1857    GtkWidget *entry_new(void) {
1858    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
1859      return gtk_entry_new();
1860    #else
1861      return hildon_entry_new(HILDON_SIZE_AUTO);
1862    #endif
1863    }
1864    
1865    gboolean pos_differ(pos_t *pos1, pos_t *pos2) {
1866      int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;
1867      int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;
1868    
1869      return((lat1 != lat2) || (lon1 != lon2));
1870    }
1871    
1872    gboolean pos_valid(pos_t *pos) {
1873      if(!pos) return FALSE;
1874      return(!isnan(pos->lat) && !isnan(pos->lon));
1875    }
1876    
1877    void misc_init(void) {
1878      g_signal_new ("changed", GTK_TYPE_BUTTON,
1879                    G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
1880                    g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
1881    }
1882    
1883    void angle_str(char *str, int len, float angle) {
1884      snprintf(str, len, _("%.1f°"), angle);
1885    }
1886    
1887    float angle_parse(char *str) {
1888      float val;
1889    
1890      if(sscanf(str, _("%f°"), &val) != 1)
1891        val = NAN;
1892    
1893      return val;
1894    }
1895    
1896    #ifndef COORDINATE_PICKER
1897    static void callback_modified_angle(GtkWidget *widget, gpointer data ) {
1898      float i = angle_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
1899      mark(widget, !isnan(i));
1900    }
1901    #else
1902    static gint on_angle_picker_button_press(GtkWidget *button,
1903                       GdkEventButton *event, gpointer data) {
1904    
1905      if(event->type == GDK_BUTTON_PRESS) {
1906        GtkWidget *dialog =
1907          gtk_dialog_new_with_buttons(_("Direction"),
1908              GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
1909                                      GTK_DIALOG_MODAL,
1910              GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1911              _("Done"),        GTK_RESPONSE_ACCEPT,
1912              NULL);
1913    
1914        gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 210);
1915    
1916        int i, angle = (int)g_object_get_data(G_OBJECT(button), "angle");
1917    
1918        GtkWidget *anglew[3], *fracw;
1919    
1920        /* create xxx.x° */
1921        GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
1922    
1923        gtk_box_pack_start_defaults(GTK_BOX(hbox),
1924                    anglew[0] = digit_picker_create(0,3, (angle/1000)%10));
1925        gtk_box_pack_start_defaults(GTK_BOX(hbox),
1926                    anglew[1] = digit_picker_create(0,9, (angle/100)%10));
1927        gtk_box_pack_start_defaults(GTK_BOX(hbox),
1928                    anglew[2] = digit_picker_create(0,9, (angle/10)%10));
1929        gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(" . "), FALSE, FALSE, 0);
1930        gtk_box_pack_start_defaults(GTK_BOX(hbox),
1931                    fracw = digit_picker_create(0,9, (angle/1)%10));
1932        gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("°"), FALSE, FALSE, 0);
1933    
1934        gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
1935    
1936        gtk_widget_show_all(dialog);
1937        if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1938    
1939          /* parse angle */
1940          for(angle=0,i=0;i<3;i++)
1941            angle = 10 * angle + picker_get(anglew[i]);
1942    
1943          angle = 10 * angle + picker_get(fracw);
1944    
1945          angle_entry_set(button, angle/10.0);
1946        }
1947    
1948        gtk_widget_destroy(dialog);
1949    
1950        return TRUE;
1951      }
1952      return FALSE;
1953    }
1954    #endif
1955    
1956    GtkWidget *angle_entry_new(float angle) {
1957      char str[32];
1958      angle_str(str, sizeof(str), angle);
1959    
1960    #ifndef COORDINATE_PICKER
1961      GtkWidget *widget = red_entry_new_with_text(str);
1962      g_signal_connect(G_OBJECT(widget), "changed",
1963                       G_CALLBACK(callback_modified_angle), NULL);
1964    #else
1965      GtkWidget *widget = gtk_button_new_with_label(str);
1966    
1967    #ifdef FREMANTLE
1968      hildon_gtk_widget_set_theme_size(widget,
1969            (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
1970    #endif
1971      int angle_int = (int)roundf(angle*10.0);
1972      g_object_set_data(G_OBJECT(widget), "angle", (gpointer)angle_int);
1973      gtk_signal_connect(GTK_OBJECT(widget), "button-press-event",
1974                         (GtkSignalFunc)on_angle_picker_button_press, NULL);
1975    #endif
1976      return widget;
1977    }
1978    
1979    float angle_entry_get(GtkWidget *widget) {
1980    #ifndef COORDINATE_PICKER
1981      char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
1982    #else
1983      char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget));
1984    #endif
1985      return angle_parse(p);
1986    }
1987    
1988    void angle_entry_set(GtkWidget *widget, float angle) {
1989      char str[32];
1990      angle_str(str, sizeof(str)-1, angle);
1991    #ifndef COORDINATE_PICKER
1992      gtk_entry_set_text(GTK_ENTRY(widget), str);
1993    #else
1994      gtk_button_set_label(GTK_BUTTON(widget), str);
1995      int angle_int = (int)roundf(angle * 10.0);
1996      g_object_set_data(G_OBJECT(widget), "angle", (gpointer)angle_int);
1997      g_signal_emit_by_name(widget, "changed");
1998    #endif
1999    }
2000    
2001    GtkWidget *toggle_button_new_with_label(char *label) {
2002    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
2003      return gtk_check_button_new_with_label(label);
2004    #else
2005      GtkWidget *cbut = gtk_toggle_button_new_with_label(label);
2006      hildon_gtk_widget_set_theme_size(cbut,
2007               (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
2008      gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(cbut), FALSE);
2009      return cbut;
2010    #endif
2011    }
2012    
2013    void toggle_button_set_active(GtkWidget *button, gboolean active) {
2014      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active);
2015    }
2016    
2017    gboolean toggle_button_get_active(GtkWidget *button) {
2018      return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
2019    }
2020    
2021    GtkWidget *check_button_new_with_label(char *label) {
2022    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
2023      return gtk_check_button_new_with_label(label);
2024    #else
2025      GtkWidget *cbut =
2026        hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT |
2027                                HILDON_SIZE_AUTO_WIDTH);
2028      gtk_button_set_label(GTK_BUTTON(cbut), label);
2029      return cbut;
2030    #endif
2031    }
2032    
2033    void check_button_set_active(GtkWidget *button, gboolean active) {
2034    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
2035      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active);
2036    #else
2037      hildon_check_button_set_active(HILDON_CHECK_BUTTON(button), active);
2038    #endif
2039    }
2040    
2041    gboolean check_button_get_active(GtkWidget *button) {
2042    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
2043      return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
2044    #else
2045      return hildon_check_button_get_active(HILDON_CHECK_BUTTON(button));
2046    #endif
2047    }
2048    
2049    GtkWidget *button_new(void) {
2050      GtkWidget *button = gtk_button_new();
2051    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
2052      hildon_gtk_widget_set_theme_size(button,
2053               (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
2054    #endif
2055      return button;
2056    }
2057    
2058    GtkWidget *button_new_with_label(char *label) {
2059      GtkWidget *button = gtk_button_new_with_label(label);
2060    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
2061      hildon_gtk_widget_set_theme_size(button,
2062               (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
2063    #endif
2064      return button;
2065    }
2066    
2067    static void on_browse(GtkWidget *widget, gpointer data) {
2068      GtkWidget *dialog;
2069    
2070      char **fileptr = g_object_get_data(G_OBJECT(widget), "fileptr");
2071    
2072    #ifdef USE_MAEMO
2073      dialog = hildon_file_chooser_dialog_new(
2074                   GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))),
2075                   GTK_FILE_CHOOSER_ACTION_SAVE);
2076    #else
2077      dialog = gtk_file_chooser_dialog_new(
2078                   g_object_get_data(G_OBJECT(widget), "sel_title"),
2079                   GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))),
2080                   GTK_FILE_CHOOSER_ACTION_SAVE,
2081                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2082                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
2083                   NULL);
2084    #endif
2085    
2086      if(*fileptr) {
2087        printf("set filename <%s>\n", *fileptr);
2088    
2089        if(!g_file_test(*fileptr, G_FILE_TEST_EXISTS)) {
2090          char *last_sep = strrchr(*fileptr, '/');
2091          if(last_sep) {
2092            *last_sep = 0;  // seperate path from file
2093    
2094            /* the user just created a new document */
2095            gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
2096                                                *fileptr);
2097            gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
2098                                              last_sep+1);
2099    
2100            /* restore full filename */
2101            *last_sep = '/';
2102          }
2103        } else
2104          gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), *fileptr);
2105      }
2106    
2107      if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
2108        gchar *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
2109        if(name) {
2110          if(*fileptr) g_free(*fileptr);
2111          *fileptr = g_strdup(name);
2112    
2113    #ifndef FREMANTLE
2114          GtkWidget *label = g_object_get_data(G_OBJECT(widget), "label");
2115          gtk_label_set_text(GTK_LABEL(label), *fileptr);
2116    #else
2117          hildon_button_set_value(HILDON_BUTTON(widget), *fileptr);
2118    #endif
2119        }
2120      }
2121    
2122      gtk_widget_destroy (dialog);
2123    }
2124    
2125    GtkWidget *export_file(char *sel_title, char **filename) {
2126      /* non-fremantle and classic gtk use a rather ugly and */
2127      /* complex layout */
2128    #ifndef FREMANTLE
2129      GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
2130      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
2131      GtkWidget *label = gtk_label_new(_("Export to"));
2132      gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE,0);
2133      gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
2134      GtkWidget *button = button_new_with_label(_("Browse"));
2135      g_object_set_data(G_OBJECT(button), "sel_title", sel_title);
2136      g_object_set_data(G_OBJECT(button), "fileptr", filename);
2137      gtk_signal_connect(GTK_OBJECT(button), "clicked",
2138                         GTK_SIGNAL_FUNC(on_browse), NULL);
2139      gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE,0);
2140      gtk_box_pack_start_defaults(GTK_BOX(vbox), hbox);
2141    
2142      label = gtk_label_new((*filename)?*filename:"");
2143      g_object_set_data(G_OBJECT(button), "label", label);
2144      gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
2145      gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE);
2146    
2147      gtk_box_pack_start_defaults(GTK_BOX(vbox), label);
2148      return vbox;
2149    #else
2150      GtkWidget *button = hildon_button_new_with_text(
2151              (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH),
2152              HILDON_BUTTON_ARRANGEMENT_VERTICAL,
2153              _("Export to"), *filename);
2154      hildon_button_set_title_alignment(HILDON_BUTTON(button), 0.5, 0.5);
2155      hildon_button_set_value_alignment(HILDON_BUTTON(button), 0.5, 0.5);
2156      g_object_set_data(G_OBJECT(button), "sel_title", sel_title);
2157      g_object_set_data(G_OBJECT(button), "fileptr", filename);
2158      gtk_signal_connect(GTK_OBJECT(button), "clicked",
2159                         GTK_SIGNAL_FUNC(on_browse), NULL);
2160      return button;
2161    #endif
2162    }
2163    
2164    #ifdef FREMANTLE
2165    static int number_editor_get(GtkWidget *widget) {
2166      GtkWidget *entry = g_object_get_data(G_OBJECT(widget), "entry");
2167      g_assert(entry);
2168      const char *str = gtk_entry_get_text(GTK_ENTRY(entry));
2169      if(!str) return 0;
2170      return atoi(str);
2171    }
2172    
2173    static void number_editor_set(GtkWidget *widget, int num) {
2174      int min = (int)g_object_get_data(G_OBJECT(widget), "min");
2175      int max = (int)g_object_get_data(G_OBJECT(widget), "max");
2176    
2177      if(num < min) num = min;
2178      if(num > max) num = max;
2179    
2180      GtkWidget *btn_inc =
2181        (GtkWidget*)g_object_get_data(G_OBJECT(widget), "btn_inc");
2182      gtk_widget_set_sensitive(btn_inc, num < max);
2183    
2184      GtkWidget *btn_dec =
2185        (GtkWidget*)g_object_get_data(G_OBJECT(widget), "btn_dec");
2186      gtk_widget_set_sensitive(btn_dec, num > min);
2187    
2188      GtkWidget *entry = g_object_get_data(G_OBJECT(widget), "entry");
2189      g_assert(entry);
2190      char *str = g_strdup_printf("%d", num);
2191      gtk_entry_set_text(GTK_ENTRY(entry), str);
2192      g_free(str);
2193    }
2194    
2195    static void on_number_decrease(GtkWidget *widget, gpointer data) {
2196      number_editor_set(GTK_WIDGET(data),
2197        number_editor_get(GTK_WIDGET(data)) - 1);
2198    }
2199    
2200    static void on_number_increase(GtkWidget *widget, gpointer data) {
2201      number_editor_set(GTK_WIDGET(data),
2202        number_editor_get(GTK_WIDGET(data)) + 1);
2203    }
2204    
2205    static void on_number_changed(GtkWidget *widget, gpointer data) {
2206      number_editor_set(GTK_WIDGET(data),
2207        number_editor_get(GTK_WIDGET(data)));
2208    }
2209    #endif
2210    
2211    GtkWidget *number_editor_new(int current, int min, int max) {
2212    #ifndef USE_MAEMO
2213      GtkObject *adj = gtk_adjustment_new(current, min, max, 1, 10, 10);
2214      return gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
2215    #elif MAEMO_VERSION_MAJOR < 5
2216      GtkWidget *widget = hildon_number_editor_new(min, max);
2217      hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(widget), current);
2218      return widget;
2219    #else
2220      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
2221      g_object_set_data(G_OBJECT(hbox), "min", (gpointer)min);
2222      g_object_set_data(G_OBJECT(hbox), "max", (gpointer)max);
2223    
2224      GtkWidget *btn_dec = button_new_with_label("  -  ");
2225      g_object_set_data(G_OBJECT(hbox), "btn_dec", btn_dec);
2226      gtk_signal_connect(GTK_OBJECT(btn_dec), "clicked",
2227                         (GtkSignalFunc)on_number_decrease, hbox);
2228      gtk_box_pack_start(GTK_BOX(hbox), btn_dec, FALSE, FALSE, 0);
2229    
2230      GtkWidget *entry = hildon_entry_new(HILDON_SIZE_AUTO);
2231      g_object_set_data(G_OBJECT(hbox), "entry", entry);
2232      g_signal_connect(G_OBJECT(entry), "changed",
2233                       G_CALLBACK(on_number_changed), hbox);
2234      gtk_entry_set_width_chars(GTK_ENTRY(entry), 2);
2235      hildon_gtk_entry_set_input_mode(GTK_ENTRY(entry),
2236                                      HILDON_GTK_INPUT_MODE_NUMERIC);
2237      gtk_box_pack_start_defaults(GTK_BOX(hbox), entry);
2238    
2239      GtkWidget *btn_inc = button_new_with_label("  +  ");
2240      g_object_set_data(G_OBJECT(hbox), "btn_inc", btn_inc);
2241      gtk_signal_connect(GTK_OBJECT(btn_inc), "clicked",
2242                         (GtkSignalFunc)on_number_increase, hbox);
2243      gtk_box_pack_start(GTK_BOX(hbox), btn_inc, FALSE, FALSE, 0);
2244    
2245      number_editor_set(hbox, current);
2246    
2247      return hbox;
2248    #endif
2249    }
2250    
2251    int number_editor_get_value(GtkWidget *widget) {
2252    #ifndef USE_MAEMO
2253      return gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
2254    #elif MAEMO_VERSION_MAJOR < 5
2255      return hildon_number_editor_get_value(HILDON_NUMBER_EDITOR(widget));
2256    #else
2257      return number_editor_get(widget);
2258    #endif
2259    }

Legend:
Removed from v.221  
changed lines
  Added in v.246