Contents of /trunk/src/area_edit.c

Parent Directory Parent Directory | Revision Log Revision Log


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