Contents of /trunk/src/area_edit.c

Parent Directory Parent Directory | Revision Log Revision Log


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