Diff of /trunk/src/area_edit.c

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

revision 203 by harbaum, Thu Jul 9 18:39:42 2009 UTC revision 248 by harbaum, Tue Jul 28 06:27:25 2009 UTC
# Line 18  Line 18 
18   */   */
19    
20  #include "appdata.h"  #include "appdata.h"
21    
22    #ifdef ENABLE_OSM_GPS_MAP
23  #include "osm-gps-map.h"  #include "osm-gps-map.h"
24    #endif
25    
26    #define TAB_LABEL_MAP    "Map"
27    #define TAB_LABEL_DIRECT "Direct"
28    #define TAB_LABEL_EXTENT "Extent"
29    #define TAB_LABEL_MM     "Maemo Mapper"
30    
31    /* limit of square kilometers above the warning is enabled */
32    #define WARN_OVER  5.0
33    
34  typedef struct {  typedef struct {
35    GtkWidget *dialog, *notebook;    GtkWidget *dialog, *notebook;
36    area_edit_t *area;    area_edit_t *area;
37    pos_t min, max;      /* local copy to work on */    pos_t min, max;      /* local copy to work on */
38    GtkWidget *minlat, *maxlat, *minlon, *maxlon;    GtkWidget *minlat, *maxlat, *minlon, *maxlon;
39      GtkWidget *warning;
40    
41    struct {    struct {
42      GtkWidget *minlat, *maxlat, *minlon, *maxlon;      GtkWidget *minlat, *maxlat, *minlon, *maxlon;
# Line 41  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, 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, GtkWidget *dst, pos_float_t *store) {  static void parse_and_set_lat(GtkWidget *src, pos_float_t *store) {
68    pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(src)));    pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(src)));
69    if(pos_lat_valid(i)) {    if(pos_lat_valid(i))
70      *store = i;      *store = i;
     pos_lat_label_set(dst, i);  
   }  
71  }  }
72    
73  static void parse_and_set_lon(GtkWidget *src, GtkWidget *dst, pos_float_t *store) {  static void parse_and_set_lon(GtkWidget *src, pos_float_t *store) {
74    pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(src)));    pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(src)));
75    if(pos_lon_valid(i)) {    if(pos_lon_valid(i))
76      *store = i;      *store = i;
     pos_lon_label_set(dst, i);  
   }  
77  }  }
78    
79  #define log2(x) (log(x) / log(2))  static gboolean current_tab_is(context_t *context, gint page_num, char *str) {
80      if(page_num < 0)
81        page_num =
82          gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook));
83    
84      if(page_num < 0) return FALSE;
85    
86      GtkWidget *w =
87        gtk_notebook_get_nth_page(GTK_NOTEBOOK(context->notebook), page_num);
88      const char *name =
89        gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(context->notebook), w);
90    
91      return(strcasecmp(name, _(str)) == 0);
92    }
93    
94    static void on_area_warning_clicked(GtkButton *button, gpointer data) {
95      context_t *context = (context_t*)data;
96    
97  void get_zoom(context_t *context) {    /* compute area size */
98    pos_float_t center_lat = (context->max.lat + context->min.lat)/2;    pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
99      double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
100      double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
101    
102    /* we know pixel size, we know the real size, we want the zoom! */    double area = vscale * (context->max.lat - context->min.lat) *
103        hscale * (context->max.lon - context->min.lon);
104    
105    printf("map_update: %d x %d\n",    warningf(context->dialog,
106           context->map.widget->allocation.width,     _("The currently selected area is %.02f km² (%.02f mi²) in size. "
107           context->map.widget->allocation.height);       "This is more than the recommended %.02f km² (%.02f mi²).\n\n"
108         "Continuing may result in a big download and low mapping performance "
109         "in a densly mapped area (e.g. cities)!"),
110               area, area/(KMPMIL*KMPMIL),
111               WARN_OVER, WARN_OVER/(KMPMIL*KMPMIL)
112               );
113    
114    double vscale = DEG2RAD(POS_EQ_RADIUS);  }
   double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS);  
115    
116    printf("scale: %f m/pix %f m/pix\n", hscale*256, vscale*256);  static void area_main_update(context_t *context) {
117      pos_lat_label_set(context->minlat, context->min.lat);
118      pos_lat_label_set(context->maxlat, context->max.lat);
119      pos_lon_label_set(context->minlon, context->min.lon);
120      pos_lon_label_set(context->maxlon, context->max.lon);
121    
122    //  double height = 8 * (1<<zoom) / vscale;   // 2^zoom  ln2(zoom)    /* check if area size exceeds recommended values */
123    //  double hzoom = log2(context->map.widget->allocation.height * vscale / 8);    pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
124    //  double width  = 16 * (1<<zoom) / hscale;    double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
125    //  double vzoom = log2(context->map.widget->allocation.width * hscale / 8);    double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
126    
127      double area = vscale * (context->max.lat - context->min.lat) *
128        hscale * (context->max.lon - context->min.lon);
129    
130    //  printf("zoom: %f %f\n", hzoom, vzoom);    if(area > WARN_OVER)
131        gtk_widget_show(context->warning);
132      else
133        gtk_widget_hide(context->warning);
134  }  }
135    
136  /* the contents of the map tab have been changed */  #ifdef ENABLE_OSM_GPS_MAP
137  static void map_update(context_t *context) {  #define LOG2(x) (log(x) / log(2))
   pos_float_t center_lat = (context->max.lat + context->min.lat)/2;  
   pos_float_t center_lon = (context->max.lon + context->min.lon)/2;  
138    
139    get_zoom(context);  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    osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget),  static GSList *pos_append(GSList *list, pos_float_t lat, pos_float_t lon) {
148                           center_lat, center_lon);    return pos_append_rad(list, DEG2RAD(lat), DEG2RAD(lon));
149    }
150    
151    osm_gps_map_set_zoom(OSM_GPS_MAP(context->map.widget), 14);  /* the contents of the map tab have been changed */
152    static void map_update(context_t *context, gboolean forced) {
153    
154      /* map is first tab (page 0) */
155      if(!forced && !current_tab_is(context, -1, TAB_LABEL_MAP)) {
156        context->map.needs_redraw = TRUE;
157        return;
158      }
159    
160      /* check if the position is invalid */
161      if(isnan(context->min.lat) || isnan(context->min.lon) ||
162         isnan(context->min.lat) || isnan(context->min.lon)) {
163    
164        /* no coordinates given: display the entire world */
165        osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->map.widget),
166                                  0.0, 0.0, 1);
167    
168        osm_gps_map_clear_tracks(OSM_GPS_MAP(context->map.widget));
169      } else {
170    
171        pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
172        pos_float_t center_lon = (context->max.lon + context->min.lon)/2;
173    
174        /* 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;
202  }  }
203    
204  static gboolean on_map_configure(GtkWidget *widget,  static gboolean on_map_configure(GtkWidget *widget,
205                                   GdkEventConfigure *event,                                   GdkEventConfigure *event,
206                                   context_t *context) {                                   context_t *context) {
207      map_update(context, FALSE);
   map_update(context);  
208    return FALSE;    return FALSE;
209  }  }
210    #endif
211    
212  /* the contents of the direct tab have been changed */  /* the contents of the direct tab have been changed */
213  static void direct_update(context_t *context) {  static void direct_update(context_t *context) {
# Line 138  static void extent_update(context_t *con Line 238  static void extent_update(context_t *con
238  static void callback_modified_direct(GtkWidget *widget, gpointer data) {  static void callback_modified_direct(GtkWidget *widget, gpointer data) {
239    context_t *context = (context_t*)data;    context_t *context = (context_t*)data;
240    
241    /* direct is first tab (page 0) */    /* direct is second tab (page 1) */
242    if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 0)    if(!current_tab_is(context, -1, TAB_LABEL_DIRECT))
243      return;      return;
244    
245    /* parse the fields from the direct entry pad */    /* parse the fields from the direct entry pad */
246    parse_and_set_lat(context->direct.minlat, context->minlat, &context->min.lat);    parse_and_set_lat(context->direct.minlat, &context->min.lat);
247    parse_and_set_lon(context->direct.minlon, context->minlon, &context->min.lon);    parse_and_set_lon(context->direct.minlon, &context->min.lon);
248    parse_and_set_lat(context->direct.maxlat, context->maxlat, &context->max.lat);    parse_and_set_lat(context->direct.maxlat, &context->max.lat);
249    parse_and_set_lon(context->direct.maxlon, context->maxlon, &context->max.lon);    parse_and_set_lon(context->direct.maxlon, &context->max.lon);
250    
251      area_main_update(context);
252    
253    /* also adjust other views */    /* also adjust other views */
254    extent_update(context);    extent_update(context);
255    #ifdef ENABLE_OSM_GPS_MAP
256      map_update(context, FALSE);
257    #endif
258  }  }
259    
260  static void callback_modified_extent(GtkWidget *widget, gpointer data) {  static void callback_modified_extent(GtkWidget *widget, gpointer data) {
261    context_t *context = (context_t*)data;    context_t *context = (context_t*)data;
262    
263    /* extent is second tab (page 1) */    /* extent is third tab (page 2) */
264    if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 1)    if(!current_tab_is(context, -1, TAB_LABEL_EXTENT))
265      return;      return;
266    
267    pos_float_t center_lat = pos_lat_get(context->extent.lat);    pos_float_t center_lat = pos_lat_get(context->extent.lat);
# Line 173  static void callback_modified_extent(Gtk Line 278  static void callback_modified_extent(Gtk
278    
279    height /= 2 * vscale;    height /= 2 * vscale;
280    context->min.lat = center_lat - height;    context->min.lat = center_lat - height;
   pos_lat_label_set(context->minlat, context->min.lat);  
281    context->max.lat = center_lat + height;    context->max.lat = center_lat + height;
282    pos_lat_label_set(context->maxlat, context->max.lat);  
   
283    width /= 2 * hscale;    width /= 2 * hscale;
284    context->min.lon = center_lon - width;    context->min.lon = center_lon - width;
   pos_lon_label_set(context->minlon, context->min.lon);  
285    context->max.lon = center_lon + width;    context->max.lon = center_lon + width;
286    pos_lon_label_set(context->maxlon, context->max.lon);  
287      area_main_update(context);
288    
289    /* also update other tabs */    /* also update other tabs */
290    direct_update(context);    direct_update(context);
291    map_update(context);  #ifdef ENABLE_OSM_GPS_MAP
292      map_update(context, FALSE);
293    #endif
294  }  }
295    
296  static void callback_modified_unit(GtkWidget *widget, gpointer data) {  static void callback_modified_unit(GtkWidget *widget, gpointer data) {
# Line 208  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    printf("clicked fetch mm!\n");    if(!dbus_mm_set_position(context->area->appdata->osso_context, NULL)) {
   
   if(!dbus_mm_set_position(context->area->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 218  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 227  static void callback_fetch_mm_clicked(Gt Line 330  static void callback_fetch_mm_clicked(Gt
330      return;      return;
331    }    }
332    
333    /* maemo mapper is third tab (page 2) */    /* maemo mapper is fourth tab (page 3) */
334    if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 2)    if(!current_tab_is(context, -1, TAB_LABEL_MM))
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 242  static void callback_fetch_mm_clicked(Gt Line 345  static void callback_fetch_mm_clicked(Gt
345    double vscale = DEG2RAD(POS_EQ_RADIUS);    double vscale = DEG2RAD(POS_EQ_RADIUS);
346    double height = 8 * (1<<zoom) / vscale;    double height = 8 * (1<<zoom) / vscale;
347    context->min.lat = center_lat - height;    context->min.lat = center_lat - height;
   pos_lat_label_set(context->minlat, context->min.lat);  
348    context->max.lat = center_lat + height;    context->max.lat = center_lat + height;
   pos_lat_label_set(context->maxlat, context->max.lat);  
349    
350    double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS);    double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS);
351    double width  = 16 * (1<<zoom) / hscale;    double width  = 16 * (1<<zoom) / hscale;
352    context->min.lon = center_lon - width;    context->min.lon = center_lon - width;
   pos_lon_label_set(context->minlon, context->min.lon);  
353    context->max.lon = center_lon + width;    context->max.lon = center_lon + width;
354    pos_lon_label_set(context->maxlon, context->max.lon);  
355      area_main_update(context);
356    
357    /* also update other tabs */    /* also update other tabs */
358    direct_update(context);    direct_update(context);
359    extent_update(context);    extent_update(context);
360    map_update(context);  #ifdef ENABLE_OSM_GPS_MAP
361      map_update(context, FALSE);
362    #endif
363  }  }
364  #endif  #endif
365    
366    #ifdef ENABLE_OSM_GPS_MAP
367    
368    static gboolean
369    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        return TRUE;
382      }
383    
384      return FALSE;
385    }
386    
387    static gboolean
388    on_map_motion_notify_event(GtkWidget *widget,
389                               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
416    on_map_button_release_event(GtkWidget *widget,
417                                GdkEventButton *event, context_t *context) {
418      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;
460    }
461    
462  static void map_zoom(context_t *context, int step) {  static void map_zoom(context_t *context, int step) {
463    int zoom;    int zoom;
464    OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);    OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
465    g_object_get(map, "zoom", &zoom, NULL);    g_object_get(map, "zoom", &zoom, NULL);
466    zoom = osm_gps_map_set_zoom(map, zoom+step);    zoom = osm_gps_map_set_zoom(map, zoom+step);
467    
   get_zoom(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);
# Line 285  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,
520                               guint page_num, context_t *context) {
521    
522      /* updating the map while the user manually changes some coordinates */
523      /* may confuse the map. so we delay those updates until the map tab */
524      /* is becoming visible */
525      if(current_tab_is(context, page_num, TAB_LABEL_MAP) &&
526         context->map.needs_redraw)
527        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
559    
560  gboolean area_edit(area_edit_t *area) {  gboolean area_edit(area_edit_t *area) {
561      GtkWidget *vbox;
562    gboolean ok = FALSE;    gboolean ok = FALSE;
563    
564    context_t context;    context_t context;
# Line 303  gboolean area_edit(area_edit_t *area) { Line 576  gboolean area_edit(area_edit_t *area) {
576            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
577            NULL);            NULL);
578    
579    GtkWidget *table = gtk_table_new(4, 2, FALSE);  // x, y    GtkWidget *table = gtk_table_new(5, 2, FALSE);  // x, y
580    
581    GtkWidget *label = gtk_label_new(_("Latitude:"));    GtkWidget *label = gtk_label_new(_("Latitude:"));
582    misc_table_attach(table, label, 0, 0);    misc_table_attach(table, label, 0, 0);
# Line 323  gboolean area_edit(area_edit_t *area) { Line 596  gboolean area_edit(area_edit_t *area) {
596    context.maxlon = pos_lon_label_new(area->max->lon);    context.maxlon = pos_lon_label_new(area->max->lon);
597    misc_table_attach(table, context.maxlon, 3, 1);    misc_table_attach(table, context.maxlon, 3, 1);
598    
599      context.warning = gtk_button_new();
600      gtk_button_set_image(GTK_BUTTON(context.warning),
601                           gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
602                                                    GTK_ICON_SIZE_BUTTON));
603      g_signal_connect(context.warning, "clicked",
604                       G_CALLBACK(on_area_warning_clicked), &context);
605      gtk_table_attach_defaults(GTK_TABLE(table), context.warning, 4, 5, 0, 2);
606    
607    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),
608                                table, FALSE, FALSE, 0);                                table, FALSE, FALSE, 0);
609    
610    context.notebook = gtk_notebook_new();    context.notebook = gtk_notebook_new();
611    
612    #ifdef ENABLE_OSM_GPS_MAP
613    /* ------------- fetch from map ------------------------ */    /* ------------- fetch from map ------------------------ */
614    
615    GtkWidget *hbox = gtk_hbox_new(FALSE, 0);    GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
616    
617      context.map.needs_redraw = FALSE;
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",
631                       G_CALLBACK(on_map_button_release_event), &context);
632    
633    gtk_box_pack_start_defaults(GTK_BOX(hbox), context.map.widget);    gtk_box_pack_start_defaults(GTK_BOX(hbox), context.map.widget);
634    
635    /* zoom button box */    /* zoom button box */
636    GtkWidget *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),
671                     hbox, gtk_label_new(_("Map")));                     hbox, gtk_label_new(_(TAB_LABEL_MAP)));
672    #endif
673    
674    /* ------------ direct min/max edit --------------- */    /* ------------ direct min/max edit --------------- */
675    
676    vbox = gtk_vbox_new(FALSE, 10);    vbox = gtk_vbox_new(FALSE, 10);
677    table = gtk_table_new(3, 3, FALSE);  // x, y    table = gtk_table_new(3, 3, FALSE);  // x, y
678      gtk_table_set_col_spacings(GTK_TABLE(table), 10);
679      gtk_table_set_row_spacings(GTK_TABLE(table), 5);
680    
681    context.direct.minlat = pos_lat_entry_new(0.0);    context.direct.minlat = pos_lat_entry_new(0.0);
682    misc_table_attach(table, context.direct.minlat, 0, 0);    misc_table_attach(table, context.direct.minlat, 0, 0);
# Line 402  gboolean area_edit(area_edit_t *area) { Line 711  gboolean area_edit(area_edit_t *area) {
711    
712    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
713    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
714                   vbox, gtk_label_new(_("Direct")));             vbox, gtk_label_new(_(TAB_LABEL_DIRECT)));
715    
716    /* ------------- center/extent edit ------------------------ */    /* ------------- center/extent edit ------------------------ */
717    
718    vbox = gtk_vbox_new(FALSE, 10);    vbox = gtk_vbox_new(FALSE, 10);
719    table = gtk_table_new(3, 4, FALSE);  // x, y    table = gtk_table_new(3, 4, FALSE);  // x, y
720      gtk_table_set_col_spacings(GTK_TABLE(table), 10);
721      gtk_table_set_row_spacings(GTK_TABLE(table), 5);
722    
723    label = gtk_label_new(_("Center:"));    label = gtk_label_new(_("Center:"));
724    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
# Line 417  gboolean area_edit(area_edit_t *area) { Line 728  gboolean area_edit(area_edit_t *area) {
728    context.extent.lon = pos_lon_entry_new(0.0);    context.extent.lon = pos_lon_entry_new(0.0);
729    gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lon, 2, 3, 0, 1);    gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lon, 2, 3, 0, 1);
730    
731    gtk_table_set_row_spacing(GTK_TABLE(table), 0, 8);    gtk_table_set_row_spacing(GTK_TABLE(table), 0, 10);
732    
733    label = gtk_label_new(_("Width:"));    label = gtk_label_new(_("Width:"));
734    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
# Line 429  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 460  gboolean area_edit(area_edit_t *area) { Line 772  gboolean area_edit(area_edit_t *area) {
772    
773    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);    gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
774    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
775                     vbox, gtk_label_new(_("Extent")));                     vbox, gtk_label_new(_(TAB_LABEL_EXTENT)));
776    
777  #ifdef USE_HILDON  #ifdef USE_HILDON
778    /* ------------- fetch from maemo mapper ------------------------ */    /* ------------- fetch from maemo mapper ------------------------ */
# Line 479  gboolean area_edit(area_edit_t *area) { Line 791  gboolean area_edit(area_edit_t *area) {
791    
792    
793    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),    gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
794                     vbox, gtk_label_new(_("Maemo Mapper")));                     vbox, gtk_label_new(_(TAB_LABEL_MM)));
795  #endif  #endif
796    
797    /* ------------------------------------------------------ */    /* ------------------------------------------------------ */
# Line 487  gboolean area_edit(area_edit_t *area) { Line 799  gboolean area_edit(area_edit_t *area) {
799    gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),    gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),
800                                context.notebook);                                context.notebook);
801    
802    #ifdef ENABLE_OSM_GPS_MAP
803      g_signal_connect(G_OBJECT(context.notebook), "switch-page",
804                       G_CALLBACK(on_page_switch), &context);
805    #endif
806    
807    gtk_widget_show_all(context.dialog);    gtk_widget_show_all(context.dialog);
808    
809      area_main_update(&context);
810    
811    if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) {    if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) {
812      /* copy modified values back to given storage */      /* copy modified values back to given storage */
813      area->min->lat = context.min.lat;      area->min->lat = context.min.lat;
# Line 499  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.203  
changed lines
  Added in v.248