Contents of /trunk/src/area_edit.c

Parent Directory Parent Directory | Revision Log Revision Log


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