Contents of /trunk/src/area_edit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 200 - (hide annotations)
Thu Jul 9 11:44:27 2009 UTC (14 years, 10 months ago) by harbaum
File MIME type: text/plain
File size: 16399 byte(s)
Added osm-gps-map
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 200 #include "osm-gps-map.h"
22 harbaum 1
23     typedef struct {
24     GtkWidget *dialog, *notebook;
25     area_edit_t *area;
26     pos_t min, max; /* local copy to work on */
27     GtkWidget *minlat, *maxlat, *minlon, *maxlon;
28    
29     struct {
30     GtkWidget *minlat, *maxlat, *minlon, *maxlon;
31     } direct;
32    
33     struct {
34     GtkWidget *lat, *lon, *height, *width, *mil_km;
35     gboolean is_mil;
36     } extent;
37    
38 harbaum 200 #ifdef USE_HILDON
39 harbaum 1 struct {
40     GtkWidget *fetch;
41     } mmapper;
42 harbaum 200 #endif
43 harbaum 1
44 harbaum 200 struct {
45     GtkWidget *widget;
46     GtkWidget *zoomin, *zoomout;
47     } map;
48    
49 harbaum 1 } context_t;
50    
51 harbaum 9 static void parse_and_set_lat(GtkWidget *src, GtkWidget *dst, pos_float_t *store) {
52     pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(src)));
53 harbaum 1 if(pos_lat_valid(i)) {
54     *store = i;
55     pos_lat_label_set(dst, i);
56     }
57     }
58    
59 harbaum 9 static void parse_and_set_lon(GtkWidget *src, GtkWidget *dst, pos_float_t *store) {
60     pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(src)));
61 harbaum 1 if(pos_lon_valid(i)) {
62     *store = i;
63     pos_lon_label_set(dst, i);
64     }
65     }
66    
67     /* the contents of the direct tab have been changed */
68     static void direct_update(context_t *context) {
69     pos_lat_entry_set(context->direct.minlat, context->min.lat);
70     pos_lon_entry_set(context->direct.minlon, context->min.lon);
71     pos_lat_entry_set(context->direct.maxlat, context->max.lat);
72     pos_lon_entry_set(context->direct.maxlon, context->max.lon);
73     }
74    
75     /* update the contents of the extent tab */
76     static void extent_update(context_t *context) {
77 harbaum 9 pos_float_t center_lat = (context->max.lat + context->min.lat)/2;
78     pos_float_t center_lon = (context->max.lon + context->min.lon)/2;
79 harbaum 1
80     pos_lat_entry_set(context->extent.lat, center_lat);
81     pos_lat_entry_set(context->extent.lon, center_lon);
82    
83     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
84     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
85    
86     double height = vscale * (context->max.lat - context->min.lat);
87     double width = hscale * (context->max.lon - context->min.lon);
88    
89     pos_dist_entry_set(context->extent.width, width, context->extent.is_mil);
90     pos_dist_entry_set(context->extent.height, height, context->extent.is_mil);
91     }
92    
93     static void callback_modified_direct(GtkWidget *widget, gpointer data) {
94     context_t *context = (context_t*)data;
95    
96     /* direct is first tab (page 0) */
97     if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 0)
98     return;
99    
100     /* parse the fields from the direct entry pad */
101     parse_and_set_lat(context->direct.minlat, context->minlat, &context->min.lat);
102     parse_and_set_lon(context->direct.minlon, context->minlon, &context->min.lon);
103     parse_and_set_lat(context->direct.maxlat, context->maxlat, &context->max.lat);
104     parse_and_set_lon(context->direct.maxlon, context->maxlon, &context->max.lon);
105    
106     /* also adjust other views */
107     extent_update(context);
108     }
109    
110     static void callback_modified_extent(GtkWidget *widget, gpointer data) {
111     context_t *context = (context_t*)data;
112    
113     /* extent is second tab (page 1) */
114     if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 1)
115     return;
116    
117 harbaum 9 pos_float_t center_lat = pos_lat_get(context->extent.lat);
118     pos_float_t center_lon = pos_lon_get(context->extent.lon);
119 harbaum 1
120     if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))
121     return;
122    
123     double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0);
124     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS / 1000.0);
125    
126     double height = pos_dist_get(context->extent.height, context->extent.is_mil);
127     double width = pos_dist_get(context->extent.width, context->extent.is_mil);
128    
129     height /= 2 * vscale;
130     context->min.lat = center_lat - height;
131     pos_lat_label_set(context->minlat, context->min.lat);
132     context->max.lat = center_lat + height;
133     pos_lat_label_set(context->maxlat, context->max.lat);
134    
135     width /= 2 * hscale;
136     context->min.lon = center_lon - width;
137     pos_lon_label_set(context->minlon, context->min.lon);
138     context->max.lon = center_lon + width;
139     pos_lon_label_set(context->maxlon, context->max.lon);
140    
141     /* also update other tabs */
142     direct_update(context);
143     }
144    
145     static void callback_modified_unit(GtkWidget *widget, gpointer data) {
146     context_t *context = (context_t*)data;
147    
148     /* get current values */
149     double height = pos_dist_get(context->extent.height, context->extent.is_mil);
150     double width = pos_dist_get(context->extent.width, context->extent.is_mil);
151    
152     /* adjust unit flag */
153     context->extent.is_mil = gtk_combo_box_get_active(
154     GTK_COMBO_BOX(context->extent.mil_km)) == 0;
155    
156     /* save values */
157     pos_dist_entry_set(context->extent.width, width, context->extent.is_mil);
158     pos_dist_entry_set(context->extent.height, height, context->extent.is_mil);
159     }
160    
161     #ifdef USE_HILDON
162     static void callback_fetch_mm_clicked(GtkButton *button, gpointer data) {
163     context_t *context = (context_t*)data;
164    
165     printf("clicked fetch mm!\n");
166    
167     if(!dbus_mm_set_position(context->area->osso_context, NULL)) {
168     errorf(context->dialog,
169     _("Unable to communicate with Maemo Mapper. "
170     "You need to have Maemo Mapper installed "
171     "to use this feature."));
172     return;
173     }
174    
175     if(!context->area->mmpos->valid) {
176     errorf(context->dialog,
177     _("No valid position received yet. You need "
178     "to scroll or zoom the Maemo Mapper view "
179     "in order to force it to send its current "
180     "view position to osm2go."));
181     return;
182     }
183    
184     /* maemo mapper is third tab (page 2) */
185     if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 2)
186     return;
187    
188     /* maemo mapper pos data ... */
189 harbaum 9 pos_float_t center_lat = context->area->mmpos->pos.lat;
190     pos_float_t center_lon = context->area->mmpos->pos.lon;
191 harbaum 1 int zoom = context->area->mmpos->zoom;
192    
193     if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))
194     return;
195    
196     double vscale = DEG2RAD(POS_EQ_RADIUS);
197     double height = 8 * (1<<zoom) / vscale;
198     context->min.lat = center_lat - height;
199     pos_lat_label_set(context->minlat, context->min.lat);
200     context->max.lat = center_lat + height;
201     pos_lat_label_set(context->maxlat, context->max.lat);
202    
203     double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS);
204     double width = 16 * (1<<zoom) / hscale;
205     context->min.lon = center_lon - width;
206     pos_lon_label_set(context->minlon, context->min.lon);
207     context->max.lon = center_lon + width;
208     pos_lon_label_set(context->maxlon, context->max.lon);
209    
210     /* also update other tabs */
211     direct_update(context);
212     extent_update(context);
213     }
214     #endif
215    
216 harbaum 200 static void map_zoom(context_t *context, int step) {
217     int zoom;
218     OsmGpsMap *map = OSM_GPS_MAP(context->map.widget);
219     g_object_get(map, "zoom", &zoom, NULL);
220     zoom = osm_gps_map_set_zoom(map, zoom+step);
221    
222     /* enable/disable zoom buttons as required */
223     gtk_widget_set_sensitive(context->map.zoomin, zoom<17);
224     gtk_widget_set_sensitive(context->map.zoomout, zoom>1);
225     }
226    
227     static gboolean
228     cb_map_zoomin(GtkButton *button, context_t *context) {
229     map_zoom(context, +1);
230     return FALSE;
231     }
232    
233     static gboolean
234     cb_map_zoomout(GtkButton *button, context_t *context) {
235     map_zoom(context, -1);
236     return FALSE;
237     }
238    
239 harbaum 1 gboolean area_edit(area_edit_t *area) {
240     gboolean ok = FALSE;
241    
242     context_t context;
243     memset(&context, 0, sizeof(context_t));
244     context.area = area;
245     context.min.lat = area->min->lat;
246     context.min.lon = area->min->lon;
247     context.max.lat = area->max->lat;
248     context.max.lon = area->max->lon;
249    
250 harbaum 167 context.dialog =
251 harbaum 200 misc_dialog_new(MISC_DIALOG_HIGH, _("Area editor"),
252 harbaum 167 GTK_WINDOW(area->parent),
253 harbaum 1 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
254     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
255     NULL);
256    
257     GtkWidget *table = gtk_table_new(3, 3, FALSE); // x, y
258    
259     GtkWidget *label = gtk_label_new(_("Latitude"));
260     gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 0, 1);
261     label = gtk_label_new(_("Longitude"));
262     gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 0, 1);
263    
264     label = gtk_label_new(_("Min:"));
265     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
266     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
267     context.minlat = pos_lat_label_new(area->min->lat);
268     gtk_table_attach_defaults(GTK_TABLE(table), context.minlat, 1, 2, 1, 2);
269     context.minlon = pos_lon_label_new(area->min->lon);
270     gtk_table_attach_defaults(GTK_TABLE(table), context.minlon, 2, 3, 1, 2);
271    
272     label = gtk_label_new(_("Max:"));
273     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
274     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
275     context.maxlat = pos_lat_label_new(area->max->lat);
276     gtk_table_attach_defaults(GTK_TABLE(table), context.maxlat, 1, 2, 2, 3);
277     context.maxlon = pos_lon_label_new(area->max->lon);
278     gtk_table_attach_defaults(GTK_TABLE(table), context.maxlon, 2, 3, 2, 3);
279    
280 harbaum 200 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),
281     table, FALSE, FALSE, 0);
282 harbaum 1
283     context.notebook = gtk_notebook_new();
284    
285     /* ------------ direct min/max edit --------------- */
286    
287 harbaum 200 GtkWidget *vbox = gtk_vbox_new(FALSE, 10);
288 harbaum 1 table = gtk_table_new(3, 3, FALSE); // x, y
289    
290     label = gtk_label_new(_("Min:"));
291     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
292     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
293     context.direct.minlat = pos_lat_entry_new(0.);
294     gtk_table_attach_defaults(GTK_TABLE(table), context.direct.minlat, 1, 2, 0, 1);
295     context.direct.minlon = pos_lon_entry_new(area->min->lon);
296     gtk_table_attach_defaults(GTK_TABLE(table), context.direct.minlon, 2, 3, 0, 1);
297    
298     label = gtk_label_new(_("Max:"));
299     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
300     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
301     context.direct.maxlat = pos_lat_entry_new(0.0);
302     gtk_table_attach_defaults(GTK_TABLE(table), context.direct.maxlat, 1, 2, 1, 2);
303     context.direct.maxlon = pos_lon_entry_new(0.0);
304     gtk_table_attach_defaults(GTK_TABLE(table), context.direct.maxlon, 2, 3, 1, 2);
305    
306     /* setup this page */
307     direct_update(&context);
308    
309     g_signal_connect(G_OBJECT(context.direct.minlat), "changed",
310     G_CALLBACK(callback_modified_direct), &context);
311     g_signal_connect(G_OBJECT(context.direct.minlon), "changed",
312     G_CALLBACK(callback_modified_direct), &context);
313     g_signal_connect(G_OBJECT(context.direct.maxlat), "changed",
314     G_CALLBACK(callback_modified_direct), &context);
315     g_signal_connect(G_OBJECT(context.direct.maxlon), "changed",
316     G_CALLBACK(callback_modified_direct), &context);
317    
318    
319     /* --- hint --- */
320     label = gtk_label_new(_("(recommended min/max diff <0.03 degrees)"));
321     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 2, 3);
322    
323 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
324 harbaum 1 gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
325 harbaum 200 vbox, gtk_label_new(_("Direct")));
326 harbaum 1
327     /* ------------- center/extent edit ------------------------ */
328    
329 harbaum 200 vbox = gtk_vbox_new(FALSE, 10);
330 harbaum 1 table = gtk_table_new(3, 4, FALSE); // x, y
331    
332     label = gtk_label_new(_("Center:"));
333     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
334     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
335     context.extent.lat = pos_lat_entry_new(0.0);
336     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lat, 1, 2, 0, 1);
337     context.extent.lon = pos_lon_entry_new(0.0);
338     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lon, 2, 3, 0, 1);
339    
340     gtk_table_set_row_spacing(GTK_TABLE(table), 0, 8);
341    
342     label = gtk_label_new(_("Width:"));
343     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
344     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
345     context.extent.width = gtk_entry_new();
346     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.width, 1, 2, 1, 2);
347    
348     label = gtk_label_new(_("Height:"));
349     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
350     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
351     context.extent.height = gtk_entry_new();
352     gtk_table_attach_defaults(GTK_TABLE(table), context.extent.height, 1, 2, 2, 3);
353    
354     context.extent.mil_km = gtk_combo_box_new_text();
355     gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("mi"));
356     gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("km"));
357     gtk_combo_box_set_active(GTK_COMBO_BOX(context.extent.mil_km), 1); // km
358    
359     gtk_table_attach(GTK_TABLE(table), context.extent.mil_km, 2, 3, 1, 3,
360     0, 0, 0, 0);
361    
362     /* setup this page */
363     extent_update(&context);
364    
365     /* connect signals after inital update to avoid confusion */
366     g_signal_connect(G_OBJECT(context.extent.lat), "changed",
367     G_CALLBACK(callback_modified_extent), &context);
368     g_signal_connect(G_OBJECT(context.extent.lon), "changed",
369     G_CALLBACK(callback_modified_extent), &context);
370     g_signal_connect(G_OBJECT(context.extent.width), "changed",
371     G_CALLBACK(callback_modified_extent), &context);
372     g_signal_connect(G_OBJECT(context.extent.height), "changed",
373     G_CALLBACK(callback_modified_extent), &context);
374     g_signal_connect(G_OBJECT(context.extent.mil_km), "changed",
375     G_CALLBACK(callback_modified_unit), &context);
376    
377     /* --- hint --- */
378     label = gtk_label_new(_("(recommended width/height < 2km/1.25mi)"));
379     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 3, 4);
380    
381 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
382 harbaum 1 gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
383 harbaum 200 vbox, gtk_label_new(_("Extent")));
384 harbaum 1
385     #ifdef USE_HILDON
386     /* ------------- fetch from maemo mapper ------------------------ */
387    
388 harbaum 200 vbox = gtk_vbox_new(FALSE, 8);
389 harbaum 1 context.mmapper.fetch =
390     gtk_button_new_with_label(_("Get from Maemo Mapper"));
391 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), context.mmapper.fetch, FALSE, FALSE, 0);
392 harbaum 1
393     g_signal_connect(G_OBJECT(context.mmapper.fetch), "clicked",
394     G_CALLBACK(callback_fetch_mm_clicked), &context);
395    
396     /* --- hint --- */
397     label = gtk_label_new(_("(recommended MM zoom level < 7)"));
398 harbaum 200 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
399 harbaum 1
400    
401     gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
402     vbox, gtk_label_new(_("Maemo Mapper")));
403     #endif
404    
405 harbaum 200 /* ------------- fetch from map ------------------------ */
406    
407     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
408    
409     context.map.widget = g_object_new(OSM_TYPE_GPS_MAP,
410     "repo-uri", MAP_SOURCE_OPENSTREETMAP,
411     "proxy-uri", misc_get_proxy_uri(area->settings),
412     NULL);
413    
414     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.map.widget);
415    
416     /* zoom button box */
417     vbox = gtk_vbox_new(FALSE,0);
418    
419     context.map.zoomin = gtk_button_new();
420     gtk_button_set_image(GTK_BUTTON(context.map.zoomin),
421     gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU));
422     g_signal_connect(context.map.zoomin, "clicked",
423     G_CALLBACK(cb_map_zoomin), &context);
424     gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomin, FALSE, FALSE, 0);
425    
426     context.map.zoomout = gtk_button_new();
427     gtk_button_set_image(GTK_BUTTON(context.map.zoomout),
428     gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_MENU));
429     g_signal_connect(context.map.zoomout, "clicked",
430     G_CALLBACK(cb_map_zoomout), &context);
431     gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomout, FALSE, FALSE, 0);
432    
433     gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
434    
435     gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook),
436     hbox, gtk_label_new(_("Map")));
437    
438     /* ------------------------------------------------------ */
439    
440 harbaum 1 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox),
441     context.notebook);
442    
443    
444     gtk_widget_show_all(context.dialog);
445    
446     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) {
447     /* copy modified values back to given storage */
448     area->min->lat = context.min.lat;
449     area->min->lon = context.min.lon;
450     area->max->lat = context.max.lat;
451     area->max->lon = context.max.lon;
452     ok = TRUE;
453     }
454    
455     gtk_widget_destroy(context.dialog);
456    
457     return ok;
458     }