Diff of /trunk/src/misc.c

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

revision 137 by harbaum, Mon Oct 19 18:21:20 2009 UTC revision 218 by harbaum, Fri Nov 27 08:58:48 2009 UTC
# Line 26  Line 26 
26    
27  #include "gpxview.h"  #include "gpxview.h"
28    
29    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
30    #include <hildon/hildon-entry.h>
31    #include <hildon/hildon-touch-selector.h>
32    #include <hildon/hildon-picker-button.h>
33    #include <hildon/hildon-picker-dialog.h>
34    #endif
35    
36    #ifdef FREMANTLE
37    #define PICKER_DIALOG
38    #endif
39    
40  char strlastchr(char *str) {  char strlastchr(char *str) {
41    return str[strlen(str)]-1;    return str[strlen(str)]-1;
42  }  }
# Line 151  float pos_parse_lon(char *str) { Line 162  float pos_parse_lon(char *str) {
162    
163  const char *pos_get_bearing_str(pos_t from, pos_t to) {  const char *pos_get_bearing_str(pos_t from, pos_t to) {
164    static const char *bear_str[]={    static const char *bear_str[]={
165      "N", "NE", "E", "SE", "S", "SW", "W", "NW" };      "N", "NE", "E", "SE", "S", "SW", "W", "NW", "" };
166    int idx = (gpx_pos_get_bearing(from, to)+22.5)/45.0;  
167    /* make sure we stay in icon bounds */    float bearing = gpx_pos_get_bearing(from, to);
168    while(idx < 0) idx += 8;    if(!isnan(bearing)) {
169    while(idx > 7) idx -= 8;      int idx = (bearing+22.5)/45.0;
170    return _(bear_str[idx]);      /* make sure we stay in icon bounds */
171        while(idx < 0) idx += 8;
172        while(idx > 7) idx -= 8;
173        return _(bear_str[idx]);
174      }
175    
176      return bear_str[8];  // empty string
177  }  }
178    
179  /* the maemo font size is quite huge, so we adjust some fonts */  /* the maemo font size is quite huge, so we adjust some fonts */
# Line 300  static void callback_modified_lat(GtkWid Line 317  static void callback_modified_lat(GtkWid
317  /* a entry that is colored red when being "active" */  /* a entry that is colored red when being "active" */
318  GtkWidget *lat_entry_new(float lat) {  GtkWidget *lat_entry_new(float lat) {
319    GdkColor color;    GdkColor color;
320    GtkWidget *widget = gtk_entry_new();  
321      GtkWidget *widget = entry_new();
322    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
323    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
324    
# Line 322  static void callback_modified_lon(GtkWid Line 340  static void callback_modified_lon(GtkWid
340  /* a entry that is colored red when filled with invalid coordinate */  /* a entry that is colored red when filled with invalid coordinate */
341  GtkWidget *lon_entry_new(float lon) {  GtkWidget *lon_entry_new(float lon) {
342    GdkColor color;    GdkColor color;
343    GtkWidget *widget = gtk_entry_new();  
344      GtkWidget *widget = entry_new();
345      //  gtk_entry_set_width_chars(GTK_ENTRY(widget), 14);
346    
347    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
348    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
349    
# Line 357  static void callback_modified_dist(GtkWi Line 378  static void callback_modified_dist(GtkWi
378  /* a entry that is colored red when filled with invalid distance */  /* a entry that is colored red when filled with invalid distance */
379  GtkWidget *dist_entry_new(float dist, gboolean mil) {  GtkWidget *dist_entry_new(float dist, gboolean mil) {
380    GdkColor color;    GdkColor color;
381    GtkWidget *widget = gtk_entry_new();    GtkWidget *widget = entry_new();
382    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
383    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
384    
# Line 475  GtkWidget *link_button_by_id(appdata_t * Line 496  GtkWidget *link_button_by_id(appdata_t *
496    return gtk_label_new(str);    return gtk_label_new(str);
497  }  }
498    
499    
500    GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon,
501                                 const char *type, int id) {
502    
503    #ifdef ENABLE_BROWSER_INTERFACE
504      if(id) {
505        GtkWidget *ref = gtk_button_new();
506        gtk_button_set_image(GTK_BUTTON(ref), icon);
507    
508    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
509        //    hildon_gtk_widget_set_theme_size(ref,
510        //         (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
511    #endif
512        g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
513        g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
514        gtk_signal_connect(GTK_OBJECT(ref), "clicked",
515                           GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
516    
517        return ref;
518      }
519    #endif
520      return icon;
521    }
522    
523    /* left aligned, word wrapped multiline widget */
524    GtkWidget *simple_text_widget(char *text) {
525      GtkWidget *label = gtk_label_new(text);
526    
527      gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
528      gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD);
529      gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
530    
531      return label;
532    }
533    
534    
535    /* a label that is left aligned */
536    GtkWidget *left_label_new(char *str) {
537      GtkWidget *widget = gtk_label_new(str);
538      gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f);
539      return widget;
540    }
541    
542    static void pos_set(GtkWidget *item, float lat, float lon) {
543      char str[32];
544    
545      pos_lat_str(str, sizeof(str)-1, lat);
546      GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
547      gtk_entry_set_text(GTK_ENTRY(lat_entry), str);
548    
549      pos_lon_str(str, sizeof(str)-1, lon);
550      GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
551      gtk_entry_set_text(GTK_ENTRY(lon_entry), str);
552    }
553    
554    static void cb_gps(GtkWidget *item, gpointer data) {
555      appdata_t *appdata = (appdata_t*)data;
556      gint id = (gint)g_object_get_data(G_OBJECT(item), "id");
557      pos_t *pos = NULL;
558    
559      if(!id)
560        pos = gps_get_pos(appdata);
561      else if(id == 1)
562        pos = &appdata->home;
563      else {
564        location_t *location = appdata->location;
565        while(location && id > 2) {
566          location = location->next;
567          id--;
568        }
569    
570        if(id == 2)
571          pos = &location->pos;
572      }
573    
574      if(!pos) pos_set(item, NAN, NAN);
575      else     pos_set(item, pos->lat, pos->lon);
576    }
577    
578    static void cb_geomath(GtkWidget *item, gpointer data) {
579      appdata_t *appdata = (appdata_t*)data;
580    
581      pos_set(item, appdata->geomath.lat, appdata->geomath.lon);
582    }
583    
584    #ifdef ENABLE_OSM_GPS_MAP
585    static void cb_map(GtkWidget *item, gpointer data) {
586      appdata_t *appdata = (appdata_t*)data;
587    
588      pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon);
589    }
590    #endif
591    
592    static void cb_cache(GtkWidget *item, gpointer data) {
593      appdata_t *appdata = (appdata_t*)data;
594    
595      cache_t *cache = appdata->cur_cache;
596      g_assert(cache);
597    
598      gint id = (gint)g_object_get_data(G_OBJECT(item), "id");
599    
600      if(!id)
601        pos_set(item, cache->pos.lat, cache->pos.lon);
602      else {
603        wpt_t *wpt = cache->wpt;
604        while(wpt && id > 1) {
605          wpt = wpt->next;
606          id--;
607        }
608    
609        if(id == 1)
610          pos_set(item, wpt->pos.lat, wpt->pos.lon);
611      }
612    }
613    
614    #ifndef PICKER_DIALOG
615    static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata,
616                               GtkWidget *icon, char *menu_str,
617                               void(*func)(GtkWidget*, gpointer), gint id,
618                               GtkWidget *lon_entry, GtkWidget *lat_entry) {
619    
620      GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str);
621    
622      if(icon)
623        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
624    
625      g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry);
626      g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry);
627      g_object_set_data(G_OBJECT(item), "id", (gpointer)id);
628    
629      if(func)
630        gtk_signal_connect(GTK_OBJECT(item), "activate",
631                           (GtkSignalFunc)func, appdata);
632    
633      gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
634    
635      return item;
636    }
637    
638    static GtkWidget *popup_menu_create(appdata_t *appdata,
639                        GtkWidget *lat_entry, GtkWidget *lon_entry) {
640      GtkWidget *menu = gtk_menu_new();
641    
642      menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),
643               _("GPS position"), cb_gps, 0, lon_entry, lat_entry);
644    
645      menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),
646               _("Home"), cb_gps, 1, lon_entry, lat_entry);
647    
648      location_t *location = appdata->location;
649      gint id = 2;
650      while(location) {
651        menu_add(menu, appdata, icon_get_widget(ICON_POS, 21),
652                   location->name, cb_gps, id++, lon_entry, lat_entry);
653    
654        location = location->next;
655      }
656    
657      menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),
658               _("Geomath projection"), cb_geomath, 0, lon_entry, lat_entry);
659    #ifdef ENABLE_OSM_GPS_MAP
660      menu_add(menu, appdata, icon_get_widget(ICON_POS, 20),
661               _("Map position"), cb_map, 0, lon_entry, lat_entry);
662    #endif
663    
664      if(appdata->cur_cache) {
665        cache_t *cache = appdata->cur_cache;
666    
667        char *name = cache->name;
668        if(!name) name = cache->id;
669    
670        if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {
671          menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
672                   name, cb_cache, 0, lon_entry, lat_entry);
673        }
674    
675        wpt_t *wpt = cache->wpt;
676        gint id = 1;
677        while(wpt) {
678          GtkWidget *icon = NULL;
679          if(wpt->sym != WPT_SYM_UNKNOWN)
680            icon = icon_get_widget(ICON_POS, wpt->sym);
681    
682          char *name = wpt->desc;
683          if(!name) name = wpt->cmt;
684          if(!name) name = wpt->id;
685    
686          menu_add(menu, appdata, icon, name, cb_cache, id++,
687                   lon_entry, lat_entry);
688    
689          wpt = wpt->next;
690        }
691      }
692    
693      gtk_widget_show_all(menu);
694    
695      return menu;
696    }
697    
698    static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
699                                      gpointer data) {
700    
701      if(event->type == GDK_BUTTON_PRESS) {
702        GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
703    
704        /* draw a popup menu */
705        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
706                       event->button, event->time);
707        return TRUE;
708      }
709      return FALSE;
710    }
711    
712    static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
713      GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
714      gtk_widget_destroy(menu);
715    }
716    #endif
717    
718    #ifdef PICKER_DIALOG
719    
720    enum {
721      PICKER_COL_ICON = 0,
722      PICKER_COL_NAME,
723      PICKER_COL_ID,
724      PICKER_COL_CB,
725      PICKER_NUM_COLS
726    };
727    
728    static void picker_add(GtkListStore *store,  appdata_t *appdata,
729                           GdkPixbuf *icon, char *menu_str,
730                           void(*func)(GtkWidget*, gpointer), gint id) {
731      GtkTreeIter     iter;
732    
733      /* Append a row and fill in some data */
734      gtk_list_store_append (store, &iter);
735    
736      gtk_list_store_set(store, &iter,
737                         PICKER_COL_ICON, icon,
738                         PICKER_COL_NAME, menu_str,
739                         PICKER_COL_ID, id,
740                         PICKER_COL_CB, func,
741                         -1);
742    }
743    
744    static void on_picker_activated(GtkTreeView        *treeview,
745                                    GtkTreePath        *path,
746                                    GtkTreeViewColumn  *col,
747                                    gpointer            userdata) {
748      GtkTreeIter   iter;
749      GtkTreeModel *model = gtk_tree_view_get_model(treeview);
750    
751      if(gtk_tree_model_get_iter(model, &iter, path)) {
752        gint id;
753        void(*func)(GtkWidget*, gpointer);
754        gtk_tree_model_get(model, &iter,
755                           PICKER_COL_ID, &id,
756                           PICKER_COL_CB, &func,
757                           -1);
758    
759        /* set id on widget as callbacks expect it this way */
760        g_object_set_data(G_OBJECT(treeview), "id", (gpointer)id);
761        func(GTK_WIDGET(treeview), userdata);
762    
763        /* xyz */
764        gtk_dialog_response(GTK_DIALOG(gtk_widget_get_toplevel(
765                        GTK_WIDGET(treeview))), GTK_RESPONSE_ACCEPT);
766    
767      }
768    }
769    
770    static GtkWidget *picker_create(appdata_t *appdata,
771                                    GtkWidget *lat_entry, GtkWidget *lon_entry) {
772      GtkCellRenderer *renderer;
773      GtkListStore    *store;
774    
775      GtkWidget *view = gtk_tree_view_new();
776    
777      g_object_set_data(G_OBJECT(view), "lat_entry", (gpointer)lat_entry);
778      g_object_set_data(G_OBJECT(view), "lon_entry", (gpointer)lon_entry);
779    
780      /* --- "Icon" column --- */
781      renderer = gtk_cell_renderer_pixbuf_new();
782      gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
783          -1, "Icon", renderer, "pixbuf", PICKER_COL_ICON, NULL);
784    
785      /* --- "Name" column --- */
786      renderer = gtk_cell_renderer_text_new();
787      g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
788      GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
789                     "Name", renderer, "text", PICKER_COL_NAME, NULL);
790      gtk_tree_view_column_set_expand(column, TRUE);
791      gtk_tree_view_insert_column(GTK_TREE_VIEW(view), column, -1);
792    
793      store = gtk_list_store_new(PICKER_NUM_COLS,
794                                 GDK_TYPE_PIXBUF,
795                                 G_TYPE_STRING,
796                                 G_TYPE_INT,
797                                 G_TYPE_POINTER);
798    
799      picker_add(store, appdata, icon_get(ICON_POS, 18),
800                 _("GPS position"), cb_gps, 0);
801    
802      picker_add(store, appdata, icon_get(ICON_POS, 21),
803                 _("Home"), cb_gps, 1);
804    
805      location_t *location = appdata->location;
806      gint id = 2;
807      while(location) {
808        picker_add(store, appdata, icon_get(ICON_POS, 21),
809                   location->name, cb_gps, id++);
810    
811        location = location->next;
812      }
813    
814      picker_add(store, appdata, icon_get(ICON_POS, 19),
815                 _("Geomath projection"), cb_geomath, 0);
816    #ifdef ENABLE_OSM_GPS_MAP
817      picker_add(store, appdata, icon_get(ICON_POS, 20),
818                 _("Map position"), cb_map, 0);
819    #endif
820    
821      if(appdata->cur_cache) {
822        cache_t *cache = appdata->cur_cache;
823    
824        char *name = cache->name;
825        if(!name) name = cache->id;
826    
827        if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {
828          picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6),
829                     name, cb_cache, 0);
830        }
831    
832        wpt_t *wpt = cache->wpt;
833        gint id = 1;
834        while(wpt) {
835          GdkPixbuf *icon = NULL;
836          if(wpt->sym != WPT_SYM_UNKNOWN)
837            icon = icon_get(ICON_POS, wpt->sym);
838    
839          char *name = wpt->desc;
840          if(!name) name = wpt->cmt;
841          if(!name) name = wpt->id;
842    
843          picker_add(store, appdata, icon, name, cb_cache, id++);
844          wpt = wpt->next;
845        }
846      }
847    
848    
849      gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
850      g_object_unref(store);
851    
852      /* make list react on clicks */
853      g_signal_connect(view, "row-activated",
854                       (GCallback)on_picker_activated, appdata);
855    
856    #if 0
857      g_signal_connect(view, "destroy",
858                       (GCallback)cachelist_destroy, ce);
859    #endif
860    
861      /* put this inside a scrolled view */
862    #ifndef USE_PANNABLE_AREA
863      GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
864      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
865                                     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
866      gtk_container_add(GTK_CONTAINER(scrolled_window), view);
867      return scrolled_window;
868    #else
869      GtkWidget *pannable_area = hildon_pannable_area_new();
870      gtk_container_add(GTK_CONTAINER(pannable_area), view);
871      return pannable_area;
872    #endif
873    }
874    
875    static gint on_picker_button_press(GtkWidget *button,
876                       GdkEventButton *event, gpointer data) {
877      appdata_t *appdata = (appdata_t*)data;
878    
879      gpointer lat_entry = g_object_get_data(G_OBJECT(button), "lat_entry");
880      gpointer lon_entry = g_object_get_data(G_OBJECT(button), "lon_entry");
881    
882      if(event->type == GDK_BUTTON_PRESS) {
883        GtkWidget *dialog =
884          gtk_dialog_new_with_buttons(_("Preset coordinates"),
885              GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
886                                      GTK_DIALOG_MODAL,
887              GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
888              NULL);
889    
890        gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200);
891    
892        gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
893                                    picker_create(appdata, lat_entry, lon_entry));
894    
895        gtk_widget_show_all(dialog);
896        gtk_dialog_run(GTK_DIALOG(dialog));
897        gtk_widget_destroy(dialog);
898    
899        return TRUE;
900      }
901      return FALSE;
902    }
903    #endif
904    
905    GtkWidget *coo_popup(appdata_t *appdata,
906                         GtkWidget *lat_entry, GtkWidget *lon_entry) {
907    
908      GtkWidget *button = gtk_button_new();
909    
910      gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
911    
912      gtk_widget_set_tooltip_text(button, _("Preset coordinates"));
913    
914    #ifndef PICKER_DIALOG
915      gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
916                         (GtkSignalFunc)on_popup_button_press, appdata);
917    
918      gtk_signal_connect(GTK_OBJECT(button), "destroy",
919                         (GtkSignalFunc)on_popup_destroy, appdata);
920    
921      g_object_set_data(G_OBJECT(button), "menu",
922                        popup_menu_create(appdata, lat_entry, lon_entry));
923    #else
924    #ifdef FREMANTLE
925      hildon_gtk_widget_set_theme_size(button,
926            (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
927    #endif
928    
929      g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry);
930      g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry);
931    
932      gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
933                         (GtkSignalFunc)on_picker_button_press, appdata);
934    #endif
935    
936      return button;
937    }
938    
939    GtkWidget *entry_new(void) {
940    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
941      return gtk_entry_new();
942    #else
943      return hildon_entry_new(HILDON_SIZE_AUTO);
944    #endif
945    }
946    
947    gboolean pos_differ(pos_t *pos1, pos_t *pos2) {
948      int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;
949      int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;
950    
951      return((lat1 != lat2) || (lon1 != lon2));
952    }
953    

Legend:
Removed from v.137  
changed lines
  Added in v.218