Contents of /trunk/src/area_edit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 270 - (hide annotations)
Thu Aug 20 19:15:45 2009 UTC (14 years, 9 months ago) by harbaum
File MIME type: text/plain
File size: 26006 byte(s)
Released 0.7.16
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of OSM2Go.
5     *
6     * OSM2Go is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * OSM2Go is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with OSM2Go. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include "appdata.h"
21 harbaum 209
22     #ifdef ENABLE_OSM_GPS_MAP
23 harbaum 200 #include "osm-gps-map.h"
24 harbaum 209 #endif
25 harbaum 1
26 harbaum 209 #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 harbaum 205 /* limit of square kilometers above the warning is enabled */
32     #define WARN_OVER 5.0
33    
34 harbaum 1 typedef struct {
35     GtkWidget *dialog, *notebook;
36     area_edit_t *area;
37     pos_t min, max; /* local copy to work on */
38     GtkWidget *minlat, *maxlat, *minlon, *maxlon;
39 harbaum 205 GtkWidget *warning;
40 harbaum 1
41     struct {
42     GtkWidget *minlat, *maxlat, *minlon, *maxlon;
43     } direct;
44    
45     struct {
46     GtkWidget *lat, *lon, *height, *width, *mil_km;
47     gboolean is_mil;
48     } extent;
49    
50 harbaum 200 #ifdef USE_HILDON
51 harbaum 1 struct {
52     GtkWidget *fetch;
53     } mmapper;
54 harbaum 200 #endif
55 harbaum 1
56 harbaum 224 #ifdef ENABLE_OSM_GPS_MAP
57 harbaum 200 struct {
58     GtkWidget *widget;
59 harbaum 270 gboolean needs_redraw;
60 harbaum 224 gint handler_id;
61 harbaum 217 coord_t start;
62 harbaum 200 } map;
63 harbaum 224 #endif
64 harbaum 1 } context_t;
65    
66 harbaum 205 static void parse_and_set_lat(GtkWidget *src, pos_float_t *store) {
67 harbaum 9 pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(src)));
68 harbaum 205 if(pos_lat_valid(i))
69 harbaum 1 *store = i;
70     }
71    
72 harbaum 205 static void parse_and_set_lon(GtkWidget *src, pos_float_t *store) {
73 harbaum 9 pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(src)));
74 harbaum 205 if(pos_lon_valid(i))
75 harbaum 1 *store = i;
76     }
77    
78 harbaum 209 static gboolean current_tab_is(context_t *context, gint page_num, char *str) {
79     if(page_num < 0)
80     page_num =
81     gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook));
82    
83     if(page_num < 0) return FALSE;
84    
85     GtkWidget *w =
86     gtk_notebook_get_nth_page(GTK_NOTEBOOK(context->notebook), page_num);
87     const char *name =
88     gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(context->notebook), w);
89    
90     return(strcasecmp(name, _(str)) == 0);
91     }
92    
93 harbaum 249 static char *warn_text(context_t *context) {
94     /* compute area size */
95     pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
96     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
97     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
98    
99     double area = vscale * (context->max.lat - context->min.lat) *
100     hscale * (context->max.lon - context->min.lon);
101    
102     return g_strdup_printf(
103     _("The currently selected area is %.02f km² (%.02f mi²) in size. "
104     "This is more than the recommended %.02f km² (%.02f mi²).\n\n"
105     "Continuing may result in a big or failing download and low "
106     "mapping performance in a densly mapped area (e.g. cities)!"),
107     area, area/(KMPMIL*KMPMIL),
108     WARN_OVER, WARN_OVER/(KMPMIL*KMPMIL)
109     );
110     }
111    
112 harbaum 205 static void on_area_warning_clicked(GtkButton *button, gpointer data) {
113     context_t *context = (context_t*)data;
114    
115 harbaum 249 char *wtext = warn_text(context);
116     warningf(context->dialog, wtext);
117     g_free(wtext);
118     }
119    
120     static gboolean area_warning(context_t *context) {
121     gboolean ret = TRUE;
122    
123     /* check if area size exceeds recommended values */
124 harbaum 205 pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
125     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
126     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
127    
128     double area = vscale * (context->max.lat - context->min.lat) *
129     hscale * (context->max.lon - context->min.lon);
130    
131 harbaum 249 if(area > WARN_OVER) {
132     char *wtext = warn_text(context);
133 harbaum 205
134 harbaum 249 ret = yes_no_f(context->dialog, context->area->appdata,
135     MISC_AGAIN_ID_AREA_TOO_BIG, MISC_AGAIN_FLAG_DONT_SAVE_NO,
136     _("Area size warning!"),
137     _("%s Do you really want to continue?"), wtext);
138    
139     g_free(wtext);
140     }
141    
142     return ret;
143 harbaum 205 }
144    
145     static void area_main_update(context_t *context) {
146     pos_lat_label_set(context->minlat, context->min.lat);
147     pos_lat_label_set(context->maxlat, context->max.lat);
148     pos_lon_label_set(context->minlon, context->min.lon);
149     pos_lon_label_set(context->maxlon, context->max.lon);
150    
151     /* check if area size exceeds recommended values */
152     pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
153     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
154     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
155    
156     double area = vscale * (context->max.lat - context->min.lat) *
157     hscale * (context->max.lon - context->min.lon);
158    
159     if(area > WARN_OVER)
160     gtk_widget_show(context->warning);
161     else
162     gtk_widget_hide(context->warning);
163     }
164    
165 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
166 harbaum 224 #define LOG2(x) (log(x) / log(2))
167    
168 harbaum 217 static GSList *pos_append_rad(GSList *list, pos_float_t lat, pos_float_t lon) {
169 harbaum 215 coord_t *coo = g_new0(coord_t, 1);
170 harbaum 217 coo->rlat = lat;
171     coo->rlon = lon;
172 harbaum 215 list = g_slist_append(list, coo);
173     return list;
174     }
175    
176 harbaum 217 static GSList *pos_append(GSList *list, pos_float_t lat, pos_float_t lon) {
177     return pos_append_rad(list, DEG2RAD(lat), DEG2RAD(lon));
178     }
179    
180 harbaum 204 /* the contents of the map tab have been changed */
181     static void map_update(context_t *context, gboolean forced) {
182 harbaum 203
183 harbaum 204 /* map is first tab (page 0) */
184 harbaum 209 if(!forced && !current_tab_is(context, -1, TAB_LABEL_MAP)) {
185 harbaum 204 context->map.needs_redraw = TRUE;
186     return;
187     }
188 harbaum 203
189 harbaum 221 /* check if the position is invalid */
190     if(isnan(context->min.lat) || isnan(context->min.lon) ||
191     isnan(context->min.lat) || isnan(context->min.lon)) {
192 harbaum 203
193 harbaum 221 /* no coordinates given: display the entire world */
194     osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->map.widget),
195     0.0, 0.0, 1);
196 harbaum 203
197 harbaum 221 osm_gps_map_clear_tracks(OSM_GPS_MAP(context->map.widget));
198     } else {
199 harbaum 204
200 harbaum 221 pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
201     pos_float_t center_lon = (context->max.lon + context->min.lon)/2;
202 harbaum 203
203 harbaum 221 /* we know the widgets pixel size, we know the required real size, */
204     /* we want the zoom! */
205     double vzoom = LOG2((45.0 * context->map.widget->allocation.height)/
206 harbaum 270 ((context->max.lat - context->min.lat)*32.0)) -1;
207 harbaum 221
208     double hzoom = LOG2((45.0 * context->map.widget->allocation.width)/
209 harbaum 270 ((context->max.lon - context->min.lon)*32.0)) -1;
210 harbaum 221
211     osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget),
212     center_lat, center_lon);
213    
214     /* use smallest zoom, so everything fits on screen */
215     osm_gps_map_set_zoom(OSM_GPS_MAP(context->map.widget),
216     (vzoom < hzoom)?vzoom:hzoom);
217    
218     /* ---------- draw border (as a gps track) -------------- */
219     osm_gps_map_clear_tracks(OSM_GPS_MAP(context->map.widget));
220    
221     GSList *box = pos_append(NULL, context->min.lat, context->min.lon);
222     box = pos_append(box, context->max.lat, context->min.lon);
223     box = pos_append(box, context->max.lat, context->max.lon);
224     box = pos_append(box, context->min.lat, context->max.lon);
225     box = pos_append(box, context->min.lat, context->min.lon);
226    
227     osm_gps_map_add_track(OSM_GPS_MAP(context->map.widget), box);
228     }
229    
230 harbaum 204 context->map.needs_redraw = FALSE;
231 harbaum 203 }
232    
233     static gboolean on_map_configure(GtkWidget *widget,
234     GdkEventConfigure *event,
235     context_t *context) {
236 harbaum 204 map_update(context, FALSE);
237 harbaum 203 return FALSE;
238     }
239 harbaum 209 #endif
240 harbaum 203
241 harbaum 1 /* the contents of the direct tab have been changed */
242     static void direct_update(context_t *context) {
243     pos_lat_entry_set(context->direct.minlat, context->min.lat);
244     pos_lon_entry_set(context->direct.minlon, context->min.lon);
245     pos_lat_entry_set(context->direct.maxlat, context->max.lat);
246     pos_lon_entry_set(context->direct.maxlon, context->max.lon);
247     }
248    
249     /* update the contents of the extent tab */
250     static void extent_update(context_t *context) {
251 harbaum 9 pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
252     pos_float_t center_lon = (context->max.lon + context->min.lon)/2;
253 harbaum 1
254     pos_lat_entry_set(context->extent.lat, center_lat);
255     pos_lat_entry_set(context->extent.lon, center_lon);
256    
257     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
258     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
259    
260     double height = vscale * (context->max.lat - context->min.lat);
261     double width = hscale * (context->max.lon - context->min.lon);
262    
263     pos_dist_entry_set(context->extent.width, width, context->extent.is_mil);
264     pos_dist_entry_set(context->extent.height, height, context->extent.is_mil);
265     }
266    
267     static void callback_modified_direct(GtkWidget *widget, gpointer data) {
268     context_t *context = (context_t*)data;
269    
270 harbaum 204 /* direct is second tab (page 1) */
271 harbaum 209 if(!current_tab_is(context, -1, TAB_LABEL_DIRECT))
272 harbaum 1 return;
273    
274     /* parse the fields from the direct entry pad */
275 harbaum 205 parse_and_set_lat(context->direct.minlat, &context->min.lat);
276     parse_and_set_lon(context->direct.minlon, &context->min.lon);
277     parse_and_set_lat(context->direct.maxlat, &context->max.lat);
278     parse_and_set_lon(context->direct.maxlon, &context->max.lon);
279 harbaum 1
280 harbaum 205 area_main_update(context);
281    
282 harbaum 1 /* also adjust other views */
283     extent_update(context);
284 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
285     map_update(context, FALSE);
286     #endif
287 harbaum 1 }
288    
289     static void callback_modified_extent(GtkWidget *widget, gpointer data) {
290     context_t *context = (context_t*)data;
291    
292 harbaum 204 /* extent is third tab (page 2) */
293 harbaum 209 if(!current_tab_is(context, -1, TAB_LABEL_EXTENT))
294 harbaum 1 return;
295    
296 harbaum 9 pos_float_t center_lat = pos_lat_get(context->extent.lat);
297     pos_float_t center_lon = pos_lon_get(context->extent.lon);
298 harbaum 1
299     if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))
300     return;
301    
302     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
303     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
304    
305     double height = pos_dist_get(context->extent.height, context->extent.is_mil);
306     double width = pos_dist_get(context->extent.width, context->extent.is_mil);
307    
308     height /= 2 * vscale;
309     context->min.lat = center_lat - height;
310     context->max.lat = center_lat + height;
311 harbaum 205
312 harbaum 1 width /= 2 * hscale;
313     context->min.lon = center_lon - width;
314     context->max.lon = center_lon + width;
315 harbaum 205
316     area_main_update(context);
317 harbaum 1
318     /* also update other tabs */
319     direct_update(context);
320 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
321 harbaum 204 map_update(context, FALSE);
322 harbaum 209 #endif
323 harbaum 1 }
324    
325     static void callback_modified_unit(GtkWidget *widget, gpointer data) {
326     context_t *context = (context_t*)data;
327    
328     /* get current values */
329     double height = pos_dist_get(context->extent.height, context->extent.is_mil);
330     double width = pos_dist_get(context->extent.width, context->extent.is_mil);
331    
332     /* adjust unit flag */
333     context->extent.is_mil = gtk_combo_box_get_active(
334     GTK_COMBO_BOX(context->extent.mil_km)) == 0;
335    
336     /* save values */
337     pos_dist_entry_set(context->extent.width, width, context->extent.is_mil);
338     pos_dist_entry_set(context->extent.height, height, context->extent.is_mil);
339     }
340    
341     #ifdef USE_HILDON
342     static void callback_fetch_mm_clicked(GtkButton *button, gpointer data) {
343     context_t *context = (context_t*)data;
344    
345 harbaum 224 if(!dbus_mm_set_position(context->area->appdata->osso_context, NULL)) {
346 harbaum 1 errorf(context->dialog,
347     _("Unable to communicate with Maemo Mapper. "
348     "You need to have Maemo Mapper installed "
349     "to use this feature."));
350     return;
351     }
352    
353 harbaum 224 if(!context->area->appdata->mmpos.valid) {
354 harbaum 1 errorf(context->dialog,
355     _("No valid position received yet. You need "
356     "to scroll or zoom the Maemo Mapper view "
357     "in order to force it to send its current "
358     "view position to osm2go."));
359     return;
360     }
361    
362 harbaum 204 /* maemo mapper is fourth tab (page 3) */
363 harbaum 209 if(!current_tab_is(context, -1, TAB_LABEL_MM))
364 harbaum 1 return;
365    
366     /* maemo mapper pos data ... */
367 harbaum 224 pos_float_t center_lat = context->area->appdata->mmpos.pos.lat;
368     pos_float_t center_lon = context->area->appdata->mmpos.pos.lon;
369     int zoom = context->area->appdata->mmpos.zoom;
370 harbaum 1
371     if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))
372     return;
373    
374     double vscale = DEG2RAD(POS_EQ_RADIUS);
375     double height = 8 * (1<<zoom) / vscale;
376     context->min.lat = center_lat - height;
377     context->max.lat = center_lat + height;
378    
379     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS);
380     double width = 16 * (1<<zoom) / hscale;
381     context->min.lon = center_lon - width;
382     context->max.lon = center_lon + width;
383    
384 harbaum 205 area_main_update(context);
385    
386 harbaum 1 /* also update other tabs */
387     direct_update(context);
388     extent_update(context);
389 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
390 harbaum 204 map_update(context, FALSE);
391 harbaum 209 #endif
392 harbaum 1 }
393     #endif
394    
395 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
396 harbaum 204
397 harbaum 217 static gboolean
398     on_map_button_press_event(GtkWidget *widget,
399     GdkEventButton *event, context_t *context) {
400 harbaum 270 OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
401 harbaum 204
402 harbaum 270 /* osm-gps-map needs this event to handle the OSD */
403     if(osm_gps_map_osd_check((int)event->x, (int)event->y))
404     return FALSE;
405 harbaum 204
406 harbaum 270 /* remove existing marker */
407     osm_gps_map_clear_tracks(map);
408 harbaum 204
409 harbaum 270 /* and remember this location as the start */
410     context->map.start =
411     osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
412 harbaum 217
413 harbaum 270 return TRUE;
414 harbaum 204 }
415    
416     static gboolean
417 harbaum 217 on_map_motion_notify_event(GtkWidget *widget,
418     GdkEventMotion *event, context_t *context) {
419 harbaum 270 if(!isnan(context->map.start.rlon) &&
420 harbaum 217 !isnan(context->map.start.rlat)) {
421     OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
422    
423     /* remove existing marker */
424     osm_gps_map_clear_tracks(map);
425    
426     coord_t start = context->map.start, end =
427     osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
428    
429     GSList *box = pos_append_rad(NULL, start.rlat, start.rlon);
430     box = pos_append_rad(box, end.rlat, start.rlon);
431     box = pos_append_rad(box, end.rlat, end.rlon);
432     box = pos_append_rad(box, start.rlat, end.rlon);
433     box = pos_append_rad(box, start.rlat, start.rlon);
434    
435     osm_gps_map_add_track(map, box);
436     }
437    
438 harbaum 270 /* always returning true here disables dragging in osm-gps-map */
439     return TRUE;
440 harbaum 217 }
441    
442     static gboolean
443 harbaum 204 on_map_button_release_event(GtkWidget *widget,
444     GdkEventButton *event, context_t *context) {
445 harbaum 270
446     if(!isnan(context->map.start.rlon) &&
447 harbaum 217 !isnan(context->map.start.rlat)) {
448     OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
449    
450     coord_t start = context->map.start, end =
451     osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
452    
453     GSList *box = pos_append_rad(NULL, start.rlat, start.rlon);
454     box = pos_append_rad(box, end.rlat, start.rlon);
455     box = pos_append_rad(box, end.rlat, end.rlon);
456     box = pos_append_rad(box, start.rlat, end.rlon);
457     box = pos_append_rad(box, start.rlat, start.rlon);
458    
459     osm_gps_map_add_track(map, box);
460    
461     if(start.rlat < end.rlat) {
462     context->min.lat = RAD2DEG(start.rlat);
463     context->max.lat = RAD2DEG(end.rlat);
464     } else {
465     context->min.lat = RAD2DEG(end.rlat);
466     context->max.lat = RAD2DEG(start.rlat);
467     }
468    
469     if(start.rlon < end.rlon) {
470     context->min.lon = RAD2DEG(start.rlon);
471     context->max.lon = RAD2DEG(end.rlon);
472     } else {
473     context->min.lon = RAD2DEG(end.rlon);
474     context->max.lon = RAD2DEG(start.rlon);
475     }
476    
477     area_main_update(context);
478     direct_update(context);
479     extent_update(context);
480    
481     context->map.start.rlon = context->map.start.rlat = NAN;
482     }
483    
484 harbaum 270 /* osm-gps-map needs this event to handle the OSD */
485     if(osm_gps_map_osd_check((int)event->x, (int)event->y))
486     return FALSE;
487    
488     return TRUE;
489 harbaum 204 }
490    
491 harbaum 270 #if 0
492 harbaum 200 static void map_zoom(context_t *context, int step) {
493     int zoom;
494     OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
495     g_object_get(map, "zoom", &zoom, NULL);
496     zoom = osm_gps_map_set_zoom(map, zoom+step);
497     }
498 harbaum 270 #endif
499 harbaum 200
500 harbaum 270 static void
501     cb_map_gps(context_t *context) {
502 harbaum 224 pos_t pos;
503    
504     /* user clicked "gps" button -> jump to position */
505     gboolean gps_on =
506     context->area->appdata->settings &&
507     context->area->appdata->settings->enable_gps;
508    
509     if(gps_on && gps_get_pos(context->area->appdata, &pos, NULL)) {
510     osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget),
511 harbaum 258 pos.lat, pos.lon);
512 harbaum 224 }
513     }
514    
515 harbaum 204 static void on_page_switch(GtkNotebook *notebook, GtkNotebookPage *page,
516     guint page_num, context_t *context) {
517    
518     /* updating the map while the user manually changes some coordinates */
519     /* may confuse the map. so we delay those updates until the map tab */
520     /* is becoming visible */
521 harbaum 209 if(current_tab_is(context, page_num, TAB_LABEL_MAP) &&
522     context->map.needs_redraw)
523 harbaum 204 map_update(context, TRUE);
524     }
525 harbaum 224
526     static gboolean map_gps_update(gpointer data) {
527     context_t *context = (context_t*)data;
528    
529     gboolean gps_on =
530     context->area->appdata->settings &&
531     context->area->appdata->settings->enable_gps;
532    
533     gboolean gps_fix = gps_on &&
534     gps_get_pos(context->area->appdata, NULL, NULL);
535    
536 harbaum 270 /* ... and enable "goto" button if it's valid */
537     osm_gps_map_osd_enable_gps(OSM_GPS_MAP(context->map.widget),
538     OSM_GPS_MAP_OSD_GPS_CALLBACK(gps_fix?cb_map_gps:NULL), context);
539 harbaum 224
540 harbaum 270
541 harbaum 224 return TRUE;
542     }
543    
544     #endif
545    
546 harbaum 1 gboolean area_edit(area_edit_t *area) {
547 harbaum 209 GtkWidget *vbox;
548 harbaum 1
549     context_t context;
550     memset(&context, 0, sizeof(context_t));
551     context.area = area;
552     context.min.lat = area->min->lat;
553     context.min.lon = area->min->lon;
554     context.max.lat = area->max->lat;
555     context.max.lon = area->max->lon;
556    
557 harbaum 167 context.dialog =
558 harbaum 200 misc_dialog_new(MISC_DIALOG_HIGH, _("Area editor"),
559 harbaum 167 GTK_WINDOW(area->parent),
560 harbaum 1 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
561     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
562     NULL);
563    
564 harbaum 205 GtkWidget *table = gtk_table_new(5, 2, FALSE); // x, y
565 harbaum 1
566 harbaum 203 GtkWidget *label = gtk_label_new(_("Latitude:"));
567     misc_table_attach(table, label, 0, 0);
568     context.minlat = pos_lat_label_new(area->min->lat);
569     misc_table_attach(table, context.minlat, 1, 0);
570     label = gtk_label_new(_("to"));
571     misc_table_attach(table, label, 2, 0);
572     context.maxlat = pos_lat_label_new(area->max->lat);
573     misc_table_attach(table, context.maxlat, 3, 0);
574 harbaum 1
575 harbaum 203 label = gtk_label_new(_("Longitude:"));
576     misc_table_attach(table, label, 0, 1);
577 harbaum 1 context.minlon = pos_lon_label_new(area->min->lon);
578 harbaum 203 misc_table_attach(table, context.minlon, 1, 1);
579     label = gtk_label_new(_("to"));
580     misc_table_attach(table, label, 2, 1);
581 harbaum 1 context.maxlon = pos_lon_label_new(area->max->lon);
582 harbaum 203 misc_table_attach(table, context.maxlon, 3, 1);
583 harbaum 1
584 harbaum 205 context.warning = gtk_button_new();
585     gtk_button_set_image(GTK_BUTTON(context.warning),
586 harbaum 206 gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
587     GTK_ICON_SIZE_BUTTON));
588 harbaum 205 g_signal_connect(context.warning, "clicked",
589     G_CALLBACK(on_area_warning_clicked), &context);
590     gtk_table_attach_defaults(GTK_TABLE(table), context.warning, 4, 5, 0, 2);
591    
592 harbaum 200 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),
593     table, FALSE, FALSE, 0);
594 harbaum 1
595     context.notebook = gtk_notebook_new();
596    
597 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
598 harbaum 203 /* ------------- fetch from map ------------------------ */
599    
600 harbaum 204 context.map.needs_redraw = FALSE;
601 harbaum 203 context.map.widget = g_object_new(OSM_TYPE_GPS_MAP,
602 harbaum 268 "map-source", OSM_GPS_MAP_SOURCE_OPENSTREETMAP,
603 harbaum 203 "proxy-uri", misc_get_proxy_uri(area->settings),
604 harbaum 248 "tile-cache", NULL,
605 harbaum 203 NULL);
606    
607     g_signal_connect(G_OBJECT(context.map.widget), "configure-event",
608     G_CALLBACK(on_map_configure), &context);
609 harbaum 217 g_signal_connect(G_OBJECT(context.map.widget), "button-press-event",
610     G_CALLBACK(on_map_button_press_event), &context);
611     g_signal_connect(G_OBJECT(context.map.widget), "motion-notify-event",
612     G_CALLBACK(on_map_motion_notify_event), &context);
613 harbaum 204 g_signal_connect(G_OBJECT(context.map.widget), "button-release-event",
614     G_CALLBACK(on_map_button_release_event), &context);
615 harbaum 203
616 harbaum 224 /* install handler for timed updates of the gps button */
617     context.map.handler_id = gtk_timeout_add(1000, map_gps_update, &context);
618 harbaum 217 context.map.start.rlon = context.map.start.rlat = NAN;
619    
620 harbaum 203 gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
621 harbaum 270 context.map.widget, gtk_label_new(_(TAB_LABEL_MAP)));
622 harbaum 209 #endif
623 harbaum 203
624 harbaum 1 /* ------------ direct min/max edit --------------- */
625    
626 harbaum 203 vbox = gtk_vbox_new(FALSE, 10);
627 harbaum 1 table = gtk_table_new(3, 3, FALSE); // x, y
628 harbaum 204 gtk_table_set_col_spacings(GTK_TABLE(table), 10);
629     gtk_table_set_row_spacings(GTK_TABLE(table), 5);
630 harbaum 1
631 harbaum 203 context.direct.minlat = pos_lat_entry_new(0.0);
632     misc_table_attach(table, context.direct.minlat, 0, 0);
633     label = gtk_label_new(_("to"));
634     misc_table_attach(table, label, 1, 0);
635     context.direct.maxlat = pos_lat_entry_new(0.0);
636     misc_table_attach(table, context.direct.maxlat, 2, 0);
637    
638 harbaum 1 context.direct.minlon = pos_lon_entry_new(area->min->lon);
639 harbaum 203 misc_table_attach(table, context.direct.minlon, 0, 1);
640     label = gtk_label_new(_("to"));
641     misc_table_attach(table, label, 1, 1);
642 harbaum 1 context.direct.maxlon = pos_lon_entry_new(0.0);
643 harbaum 203 misc_table_attach(table, context.direct.maxlon, 2, 1);
644 harbaum 1
645     /* setup this page */
646     direct_update(&context);
647    
648     g_signal_connect(G_OBJECT(context.direct.minlat), "changed",
649     G_CALLBACK(callback_modified_direct), &context);
650     g_signal_connect(G_OBJECT(context.direct.minlon), "changed",
651     G_CALLBACK(callback_modified_direct), &context);
652     g_signal_connect(G_OBJECT(context.direct.maxlat), "changed",
653     G_CALLBACK(callback_modified_direct), &context);
654     g_signal_connect(G_OBJECT(context.direct.maxlon), "changed",
655     G_CALLBACK(callback_modified_direct), &context);
656    
657    
658     /* --- hint --- */
659     label = gtk_label_new(_("(recommended min/max diff <0.03 degrees)"));
660     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 2, 3);
661    
662 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
663 harbaum 1 gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
664 harbaum 209 vbox, gtk_label_new(_(TAB_LABEL_DIRECT)));
665 harbaum 1
666     /* ------------- center/extent edit ------------------------ */
667    
668 harbaum 200 vbox = gtk_vbox_new(FALSE, 10);
669 harbaum 1 table = gtk_table_new(3, 4, FALSE); // x, y
670 harbaum 204 gtk_table_set_col_spacings(GTK_TABLE(table), 10);
671     gtk_table_set_row_spacings(GTK_TABLE(table), 5);
672 harbaum 1
673     label = gtk_label_new(_("Center:"));
674     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
675     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
676     context.extent.lat = pos_lat_entry_new(0.0);
677     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lat, 1, 2, 0, 1);
678     context.extent.lon = pos_lon_entry_new(0.0);
679     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lon, 2, 3, 0, 1);
680    
681 harbaum 204 gtk_table_set_row_spacing(GTK_TABLE(table), 0, 10);
682 harbaum 1
683     label = gtk_label_new(_("Width:"));
684     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
685     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
686     context.extent.width = gtk_entry_new();
687     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.width, 1, 2, 1, 2);
688    
689     label = gtk_label_new(_("Height:"));
690     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
691     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
692     context.extent.height = gtk_entry_new();
693 harbaum 218 gtk_table_attach_defaults(GTK_TABLE(table),
694     context.extent.height, 1, 2, 2, 3);
695 harbaum 1
696     context.extent.mil_km = gtk_combo_box_new_text();
697     gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("mi"));
698     gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("km"));
699     gtk_combo_box_set_active(GTK_COMBO_BOX(context.extent.mil_km), 1); // km
700    
701     gtk_table_attach(GTK_TABLE(table), context.extent.mil_km, 2, 3, 1, 3,
702     0, 0, 0, 0);
703    
704     /* setup this page */
705     extent_update(&context);
706    
707     /* connect signals after inital update to avoid confusion */
708     g_signal_connect(G_OBJECT(context.extent.lat), "changed",
709     G_CALLBACK(callback_modified_extent), &context);
710     g_signal_connect(G_OBJECT(context.extent.lon), "changed",
711     G_CALLBACK(callback_modified_extent), &context);
712     g_signal_connect(G_OBJECT(context.extent.width), "changed",
713     G_CALLBACK(callback_modified_extent), &context);
714     g_signal_connect(G_OBJECT(context.extent.height), "changed",
715     G_CALLBACK(callback_modified_extent), &context);
716     g_signal_connect(G_OBJECT(context.extent.mil_km), "changed",
717     G_CALLBACK(callback_modified_unit), &context);
718    
719     /* --- hint --- */
720     label = gtk_label_new(_("(recommended width/height < 2km/1.25mi)"));
721     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 3, 4);
722    
723 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
724 harbaum 1 gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
725 harbaum 209 vbox, gtk_label_new(_(TAB_LABEL_EXTENT)));
726 harbaum 1
727     #ifdef USE_HILDON
728     /* ------------- fetch from maemo mapper ------------------------ */
729    
730 harbaum 200 vbox = gtk_vbox_new(FALSE, 8);
731 harbaum 1 context.mmapper.fetch =
732     gtk_button_new_with_label(_("Get from Maemo Mapper"));
733 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), context.mmapper.fetch, FALSE, FALSE, 0);
734 harbaum 1
735     g_signal_connect(G_OBJECT(context.mmapper.fetch), "clicked",
736     G_CALLBACK(callback_fetch_mm_clicked), &context);
737    
738     /* --- hint --- */
739     label = gtk_label_new(_("(recommended MM zoom level < 7)"));
740 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
741 harbaum 1
742    
743     gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
744 harbaum 209 vbox, gtk_label_new(_(TAB_LABEL_MM)));
745 harbaum 1 #endif
746    
747 harbaum 200 /* ------------------------------------------------------ */
748    
749 harbaum 1 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),
750     context.notebook);
751    
752 harbaum 209 #ifdef ENABLE_OSM_GPS_MAP
753 harbaum 204 g_signal_connect(G_OBJECT(context.notebook), "switch-page",
754     G_CALLBACK(on_page_switch), &context);
755 harbaum 209 #endif
756 harbaum 1
757     gtk_widget_show_all(context.dialog);
758    
759 harbaum 205 area_main_update(&context);
760    
761 harbaum 249 gboolean leave = FALSE, ok = FALSE;
762     do {
763     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) {
764     if(area_warning(&context)) {
765     leave = TRUE;
766     ok = TRUE;
767     }
768     } else
769     leave = TRUE;
770     } while(!leave);
771    
772     if(ok) {
773 harbaum 1 /* copy modified values back to given storage */
774     area->min->lat = context.min.lat;
775     area->min->lon = context.min.lon;
776     area->max->lat = context.max.lat;
777     area->max->lon = context.max.lon;
778     }
779    
780 harbaum 224 #ifdef ENABLE_OSM_GPS_MAP
781     gtk_timeout_remove(context.map.handler_id);
782     #endif
783    
784 harbaum 1 gtk_widget_destroy(context.dialog);
785    
786     return ok;
787     }