Contents of /trunk/src/area_edit.c

Parent Directory Parent Directory | Revision Log Revision Log


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