Diff of /trunk/src/area_edit.c

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

revision 209 by harbaum, Fri Jul 10 19:45:31 2009 UTC revision 248 by harbaum, Tue Jul 28 06:27:25 2009 UTC
# Line 53  typedef struct { Line 53  typedef struct {
53    } mmapper;    } mmapper;
54  #endif  #endif
55    
56    #ifdef ENABLE_OSM_GPS_MAP
57    struct {    struct {
58      GtkWidget *widget;      GtkWidget *widget;
59      GtkWidget *zoomin, *zoomout;      GtkWidget *zoomin, *zoomout, *center, *modesel, *gps;
60      gboolean needs_redraw;      gboolean needs_redraw, drag_mode;
61        gint handler_id;
62        coord_t start;
63    } map;    } map;
64    #endif
65  } context_t;  } context_t;
66    
67  static void parse_and_set_lat(GtkWidget *src, pos_float_t *store) {  static void parse_and_set_lat(GtkWidget *src, pos_float_t *store) {
# Line 73  static void parse_and_set_lon(GtkWidget Line 76  static void parse_and_set_lon(GtkWidget
76      *store = i;      *store = i;
77  }  }
78    
 #define LOG2(x) (log(x) / log(2))  
   
79  static gboolean current_tab_is(context_t *context, gint page_num, char *str) {  static gboolean current_tab_is(context_t *context, gint page_num, char *str) {
80    if(page_num < 0)    if(page_num < 0)
81      page_num =      page_num =
# Line 102  static void on_area_warning_clicked(GtkB Line 103  static void on_area_warning_clicked(GtkB
103      hscale * (context->max.lon - context->min.lon);      hscale * (context->max.lon - context->min.lon);
104    
105    warningf(context->dialog,    warningf(context->dialog,
106     _("The currently selected area is %.02f km² (%.02f mil²) in size. "     _("The currently selected area is %.02f km² (%.02f mi²) in size. "
107       "This is more than the recommended %.02f km² (%.02f mil²).\n\n"       "This is more than the recommended %.02f km² (%.02f mi²).\n\n"
108       "Continuing may result in a big download and low mapping performance "       "Continuing may result in a big download and low mapping performance "
109       "in a densly mapped area (e.g. cities)!"),       "in a densly mapped area (e.g. cities)!"),
110             area, area/(KMPMIL*KMPMIL),             area, area/(KMPMIL*KMPMIL),
# Line 133  static void area_main_update(context_t * Line 134  static void area_main_update(context_t *
134  }  }
135    
136  #ifdef ENABLE_OSM_GPS_MAP  #ifdef ENABLE_OSM_GPS_MAP
137    #define LOG2(x) (log(x) / log(2))
138    
139    static GSList *pos_append_rad(GSList *list, pos_float_t lat, pos_float_t lon) {
140      coord_t *coo = g_new0(coord_t, 1);
141      coo->rlat = lat;
142      coo->rlon = lon;
143      list = g_slist_append(list, coo);
144      return list;
145    }
146    
147    static GSList *pos_append(GSList *list, pos_float_t lat, pos_float_t lon) {
148      return pos_append_rad(list, DEG2RAD(lat), DEG2RAD(lon));
149    }
150    
151  /* the contents of the map tab have been changed */  /* the contents of the map tab have been changed */
152  static void map_update(context_t *context, gboolean forced) {  static void map_update(context_t *context, gboolean forced) {
153    
# Line 142  static void map_update(context_t *contex Line 157  static void map_update(context_t *contex
157      return;      return;
158    }    }
159    
160    pos_float_t center_lat = (context->max.lat + context->min.lat)/2;    /* check if the position is invalid */
161    pos_float_t center_lon = (context->max.lon + context->min.lon)/2;    if(isnan(context->min.lat) || isnan(context->min.lon) ||
162         isnan(context->min.lat) || isnan(context->min.lon)) {
163    /* we know the widgets pixel size, we know the required real size, */  
164    /* we want the zoom! */      /* no coordinates given: display the entire world */
165    double vzoom = LOG2((45.0 * context->map.widget->allocation.height)/      osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->map.widget),
166                        ((context->max.lat - context->min.lat)*32.0));                                0.0, 0.0, 1);
167    
168    double hzoom = LOG2((45.0 * context->map.widget->allocation.width)/      osm_gps_map_clear_tracks(OSM_GPS_MAP(context->map.widget));
169                        ((context->max.lon - context->min.lon)*32.0));    } else {
170    
171    osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget),      pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
172                           center_lat, center_lon);      pos_float_t center_lon = (context->max.lon + context->min.lon)/2;
173    
174    osm_gps_map_set_zoom(OSM_GPS_MAP(context->map.widget), (hzoom+vzoom+0.5)/2);      /* we know the widgets pixel size, we know the required real size, */
175        /* we want the zoom! */
176        double vzoom = LOG2((45.0 * context->map.widget->allocation.height)/
177                            ((context->max.lat - context->min.lat)*32.0));
178    
179        double hzoom = LOG2((45.0 * context->map.widget->allocation.width)/
180                            ((context->max.lon - context->min.lon)*32.0));
181    
182        osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget),
183                               center_lat, center_lon);
184    
185        /* use smallest zoom, so everything fits on screen */
186        osm_gps_map_set_zoom(OSM_GPS_MAP(context->map.widget),
187                             (vzoom < hzoom)?vzoom:hzoom);
188    
189        /* ---------- draw border (as a gps track) -------------- */
190        osm_gps_map_clear_tracks(OSM_GPS_MAP(context->map.widget));
191    
192        GSList *box = pos_append(NULL, context->min.lat, context->min.lon);
193        box = pos_append(box, context->max.lat, context->min.lon);
194        box = pos_append(box, context->max.lat, context->max.lon);
195        box = pos_append(box, context->min.lat, context->max.lon);
196        box = pos_append(box, context->min.lat, context->min.lon);
197    
198        osm_gps_map_add_track(OSM_GPS_MAP(context->map.widget), box);
199      }
200    
201    context->map.needs_redraw = FALSE;    context->map.needs_redraw = FALSE;
202  }  }
203    
# Line 273  static void callback_modified_unit(GtkWi Line 313  static void callback_modified_unit(GtkWi
313  static void callback_fetch_mm_clicked(GtkButton *button, gpointer data) {  static void callback_fetch_mm_clicked(GtkButton *button, gpointer data) {
314    context_t *context = (context_t*)data;    context_t *context = (context_t*)data;
315    
316    if(!dbus_mm_set_position(context->area->osso_context, NULL)) {    if(!dbus_mm_set_position(context->area->appdata->osso_context, NULL)) {
317      errorf(context->dialog,      errorf(context->dialog,
318             _("Unable to communicate with Maemo Mapper. "             _("Unable to communicate with Maemo Mapper. "
319               "You need to have Maemo Mapper installed "               "You need to have Maemo Mapper installed "
# Line 281  static void callback_fetch_mm_clicked(Gt Line 321  static void callback_fetch_mm_clicked(Gt
321      return;      return;
322    }    }
323    
324    if(!context->area->mmpos->valid) {    if(!context->area->appdata->mmpos.valid) {
325      errorf(context->dialog,      errorf(context->dialog,
326             _("No valid position received yet. You need "             _("No valid position received yet. You need "
327               "to scroll or zoom the Maemo Mapper view "               "to scroll or zoom the Maemo Mapper view "
# Line 295  static void callback_fetch_mm_clicked(Gt Line 335  static void callback_fetch_mm_clicked(Gt
335      return;      return;
336    
337    /* maemo mapper pos data ... */    /* maemo mapper pos data ... */
338    pos_float_t center_lat = context->area->mmpos->pos.lat;    pos_float_t center_lat = context->area->appdata->mmpos.pos.lat;
339    pos_float_t center_lon = context->area->mmpos->pos.lon;    pos_float_t center_lon = context->area->appdata->mmpos.pos.lon;
340    int zoom = context->area->mmpos->zoom;    int zoom = context->area->appdata->mmpos.zoom;
341    
342    if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))    if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))
343      return;      return;
# Line 324  static void callback_fetch_mm_clicked(Gt Line 364  static void callback_fetch_mm_clicked(Gt
364  #endif  #endif
365    
366  #ifdef ENABLE_OSM_GPS_MAP  #ifdef ENABLE_OSM_GPS_MAP
 /* the user has changed the map view, update other views accordingly */  
 static void map_has_changed(context_t *context) {  
   coord_t pt1, pt2;  
367    
368    /* get maps bounding box */  static gboolean
369    osm_gps_map_get_bbox(OSM_GPS_MAP(context->map.widget), &pt1, &pt2);  on_map_button_press_event(GtkWidget *widget,
370                              GdkEventButton *event, context_t *context) {
371      if(!context->map.drag_mode) {
372        OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
373    
374        /* remove existing marker */
375        osm_gps_map_clear_tracks(map);
376    
377        /* and remember this location as the start */
378        context->map.start =
379          osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
380    
381    context->min.lat = RAD2DEG(pt2.rlat);      return TRUE;
382    context->max.lat = RAD2DEG(pt1.rlat);    }
383    
384    context->min.lon = RAD2DEG(pt1.rlon);    return FALSE;
385    context->max.lon = RAD2DEG(pt2.rlon);  }
386    
387    area_main_update(context);  static gboolean
388    direct_update(context);  on_map_motion_notify_event(GtkWidget *widget,
389    extent_update(context);                             GdkEventMotion  *event, context_t *context) {
390      if(!context->map.drag_mode &&
391         !isnan(context->map.start.rlon) &&
392         !isnan(context->map.start.rlat)) {
393        OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
394    
395        /* remove existing marker */
396        osm_gps_map_clear_tracks(map);
397    
398        coord_t start = context->map.start, end =
399          osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
400    
401        GSList *box = pos_append_rad(NULL, start.rlat, start.rlon);
402        box = pos_append_rad(box, end.rlat,   start.rlon);
403        box = pos_append_rad(box, end.rlat,   end.rlon);
404        box = pos_append_rad(box, start.rlat, end.rlon);
405        box = pos_append_rad(box, start.rlat, start.rlon);
406    
407        osm_gps_map_add_track(map, box);
408    
409        return TRUE;
410      }
411    
412      return FALSE;
413  }  }
414    
415  static gboolean  static gboolean
416  on_map_button_release_event(GtkWidget *widget,  on_map_button_release_event(GtkWidget *widget,
417                              GdkEventButton *event, context_t *context) {                              GdkEventButton *event, context_t *context) {
418    map_has_changed(context);    if(!context->map.drag_mode &&
419         !isnan(context->map.start.rlon) &&
420         !isnan(context->map.start.rlat)) {
421        OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
422    
423        coord_t start = context->map.start, end =
424          osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
425    
426        GSList *box = pos_append_rad(NULL, start.rlat, start.rlon);
427        box = pos_append_rad(box, end.rlat,   start.rlon);
428        box = pos_append_rad(box, end.rlat,   end.rlon);
429        box = pos_append_rad(box, start.rlat, end.rlon);
430        box = pos_append_rad(box, start.rlat, start.rlon);
431    
432        osm_gps_map_add_track(map, box);
433    
434        if(start.rlat < end.rlat) {
435          context->min.lat = RAD2DEG(start.rlat);
436          context->max.lat = RAD2DEG(end.rlat);
437        } else {
438          context->min.lat = RAD2DEG(end.rlat);
439          context->max.lat = RAD2DEG(start.rlat);
440        }
441    
442        if(start.rlon < end.rlon) {
443          context->min.lon = RAD2DEG(start.rlon);
444          context->max.lon = RAD2DEG(end.rlon);
445        } else {
446          context->min.lon = RAD2DEG(end.rlon);
447          context->max.lon = RAD2DEG(start.rlon);
448        }
449    
450        area_main_update(context);
451        direct_update(context);
452        extent_update(context);
453    
454        context->map.start.rlon = context->map.start.rlat = NAN;
455    
456        return TRUE;
457      }
458    
459    return FALSE;    return FALSE;
460  }  }
461    
# Line 358  static void map_zoom(context_t *context, Line 468  static void map_zoom(context_t *context,
468    /* enable/disable zoom buttons as required */    /* enable/disable zoom buttons as required */
469    gtk_widget_set_sensitive(context->map.zoomin, zoom<17);    gtk_widget_set_sensitive(context->map.zoomin, zoom<17);
470    gtk_widget_set_sensitive(context->map.zoomout, zoom>1);    gtk_widget_set_sensitive(context->map.zoomout, zoom>1);
   
   map_has_changed(context);  
471  }  }
472    
473  static gboolean  static gboolean
# Line 374  cb_map_zoomout(GtkButton *button, contex Line 482  cb_map_zoomout(GtkButton *button, contex
482    return FALSE;    return FALSE;
483  }  }
484    
485    static gboolean
486    cb_map_center(GtkButton *button, context_t *context) {
487      map_update(context, TRUE);
488      return FALSE;
489    }
490    
491    static gboolean
492    cb_map_modesel(GtkButton *button, context_t *context) {
493      /* toggle between "find" icon and "cut" icon */
494      context->map.drag_mode = !context->map.drag_mode;
495      gtk_button_set_image(GTK_BUTTON(context->map.modesel),
496                   gtk_image_new_from_stock(context->map.drag_mode?
497            GTK_STOCK_FIND:GTK_STOCK_CUT, GTK_ICON_SIZE_MENU));
498    
499      return FALSE;
500    }
501    
502    static gboolean
503    cb_map_gps(GtkButton *button, context_t *context) {
504      pos_t pos;
505    
506      /* user clicked "gps" button -> jump to position */
507      gboolean gps_on =
508        context->area->appdata->settings &&
509        context->area->appdata->settings->enable_gps;
510    
511      if(gps_on && gps_get_pos(context->area->appdata, &pos, NULL)) {
512        osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget),
513                               DEG2RAD(pos.lat), DEG2RAD(pos.lon));
514      }
515    
516      return FALSE;
517    }
518    
519  static void on_page_switch(GtkNotebook *notebook, GtkNotebookPage *page,  static void on_page_switch(GtkNotebook *notebook, GtkNotebookPage *page,
520                             guint page_num, context_t *context) {                             guint page_num, context_t *context) {
521    
# Line 384  static void on_page_switch(GtkNotebook * Line 526  static void on_page_switch(GtkNotebook *
526       context->map.needs_redraw)       context->map.needs_redraw)
527      map_update(context, TRUE);      map_update(context, TRUE);
528  }  }
529    
530    static GtkWidget
531    *map_add_button(const gchar *icon, GCallback cb, gpointer data,
532                    char *tooltip) {
533      GtkWidget *button = gtk_button_new();
534      gtk_button_set_image(GTK_BUTTON(button),
535           gtk_image_new_from_stock(icon, GTK_ICON_SIZE_MENU));
536      g_signal_connect(button, "clicked", cb, data);
537    #ifndef USE_HILDON
538      gtk_widget_set_tooltip_text(button, tooltip);
539    #endif
540      return button;
541    }
542    
543    static gboolean map_gps_update(gpointer data) {
544      context_t *context = (context_t*)data;
545    
546      gboolean gps_on =
547        context->area->appdata->settings &&
548        context->area->appdata->settings->enable_gps;
549    
550      gboolean gps_fix = gps_on &&
551        gps_get_pos(context->area->appdata, NULL, NULL);
552    
553      gtk_widget_set_sensitive(context->map.gps, gps_fix);
554    
555      return TRUE;
556    }
557    
558  #endif  #endif
559    
560  gboolean area_edit(area_edit_t *area) {  gboolean area_edit(area_edit_t *area) {
# Line 447  gboolean area_edit(area_edit_t *area) { Line 618  gboolean area_edit(area_edit_t *area) {
618    context.map.widget = g_object_new(OSM_TYPE_GPS_MAP,    context.map.widget = g_object_new(OSM_TYPE_GPS_MAP,
619                  "repo-uri", MAP_SOURCE_OPENSTREETMAP,                  "repo-uri", MAP_SOURCE_OPENSTREETMAP,
620                  "proxy-uri", misc_get_proxy_uri(area->settings),                  "proxy-uri", misc_get_proxy_uri(area->settings),
621                    "tile-cache", NULL,
622                   NULL);                   NULL);
623    
624    g_signal_connect(G_OBJECT(context.map.widget), "configure-event",    g_signal_connect(G_OBJECT(context.map.widget), "configure-event",
625                     G_CALLBACK(on_map_configure), &context);                     G_CALLBACK(on_map_configure), &context);
626      g_signal_connect(G_OBJECT(context.map.widget), "button-press-event",
627                       G_CALLBACK(on_map_button_press_event), &context);
628      g_signal_connect(G_OBJECT(context.map.widget), "motion-notify-event",
629                       G_CALLBACK(on_map_motion_notify_event), &context);
630    g_signal_connect(G_OBJECT(context.map.widget), "button-release-event",    g_signal_connect(G_OBJECT(context.map.widget), "button-release-event",
631                     G_CALLBACK(on_map_button_release_event), &context);                     G_CALLBACK(on_map_button_release_event), &context);
632    
# Line 459  gboolean area_edit(area_edit_t *area) { Line 635  gboolean area_edit(area_edit_t *area) {
635    /* zoom button box */    /* zoom button box */
636    vbox = gtk_vbox_new(FALSE,0);    vbox = gtk_vbox_new(FALSE,0);
637    
638    context.map.zoomin = gtk_button_new();    context.map.zoomin =
639    gtk_button_set_image(GTK_BUTTON(context.map.zoomin),      map_add_button(GTK_STOCK_ZOOM_IN, G_CALLBACK(cb_map_zoomin),
640         gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU));                     &context, _("Zoom in"));
   g_signal_connect(context.map.zoomin, "clicked",  
                    G_CALLBACK(cb_map_zoomin), &context);  
641    gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomin, FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomin, FALSE, FALSE, 0);
642    
643    context.map.zoomout = gtk_button_new();    context.map.zoomout =
644    gtk_button_set_image(GTK_BUTTON(context.map.zoomout),      map_add_button(GTK_STOCK_ZOOM_OUT, G_CALLBACK(cb_map_zoomout),
645         gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_MENU));                     &context, _("Zoom out"));
   g_signal_connect(context.map.zoomout, "clicked",  
                    G_CALLBACK(cb_map_zoomout), &context);  
646    gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomout, FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomout, FALSE, FALSE, 0);
647    
648      context.map.center =
649        map_add_button(GTK_STOCK_HOME, G_CALLBACK(cb_map_center),
650                       &context, _("Center selected area"));
651      gtk_box_pack_start(GTK_BOX(vbox), context.map.center, FALSE, FALSE, 0);
652    
653      context.map.gps =
654        map_add_button(GTK_STOCK_ABOUT, G_CALLBACK(cb_map_gps),
655                       &context, _("Jump to GPS position"));
656      gtk_widget_set_sensitive(context.map.gps, FALSE);
657      /* install handler for timed updates of the gps button */
658      context.map.handler_id = gtk_timeout_add(1000, map_gps_update, &context);
659      gtk_box_pack_start(GTK_BOX(vbox), context.map.gps, FALSE, FALSE, 0);
660    
661      context.map.drag_mode = TRUE;
662      context.map.start.rlon = context.map.start.rlat = NAN;
663      context.map.modesel =
664        map_add_button(GTK_STOCK_FIND, G_CALLBACK(cb_map_modesel),
665                       &context, _("Toggle scroll/select"));
666      gtk_box_pack_start(GTK_BOX(vbox), context.map.modesel, FALSE, FALSE, 0);
667    
668    gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
669    
670    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
# Line 548  gboolean area_edit(area_edit_t *area) { Line 740  gboolean area_edit(area_edit_t *area) {
740    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
741    gtk_table_attach_defaults(GTK_TABLE(table),  label, 0, 1, 2, 3);    gtk_table_attach_defaults(GTK_TABLE(table),  label, 0, 1, 2, 3);
742    context.extent.height = gtk_entry_new();    context.extent.height = gtk_entry_new();
743    gtk_table_attach_defaults(GTK_TABLE(table), context.extent.height, 1, 2, 2, 3);    gtk_table_attach_defaults(GTK_TABLE(table),
744                                context.extent.height, 1, 2, 2, 3);
745    
746    context.extent.mil_km = gtk_combo_box_new_text();    context.extent.mil_km = gtk_combo_box_new_text();
747    gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("mi"));    gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("mi"));
# Line 624  gboolean area_edit(area_edit_t *area) { Line 817  gboolean area_edit(area_edit_t *area) {
817      ok = TRUE;      ok = TRUE;
818    }    }
819    
820    #ifdef ENABLE_OSM_GPS_MAP
821      gtk_timeout_remove(context.map.handler_id);
822    #endif
823    
824    gtk_widget_destroy(context.dialog);    gtk_widget_destroy(context.dialog);
825    
826    return ok;    return ok;

Legend:
Removed from v.209  
changed lines
  Added in v.248