18 |
*/ |
*/ |
19 |
|
|
20 |
#include "appdata.h" |
#include "appdata.h" |
21 |
|
|
22 |
|
#ifdef ENABLE_OSM_GPS_MAP |
23 |
#include "osm-gps-map.h" |
#include "osm-gps-map.h" |
24 |
|
#endif |
25 |
|
|
26 |
|
#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 |
|
/* limit of square kilometers above the warning is enabled */ |
32 |
|
#define WARN_OVER 5.0 |
33 |
|
|
34 |
typedef struct { |
typedef struct { |
35 |
GtkWidget *dialog, *notebook; |
GtkWidget *dialog, *notebook; |
36 |
area_edit_t *area; |
area_edit_t *area; |
37 |
pos_t min, max; /* local copy to work on */ |
pos_t min, max; /* local copy to work on */ |
38 |
GtkWidget *minlat, *maxlat, *minlon, *maxlon; |
GtkWidget *minlat, *maxlat, *minlon, *maxlon; |
39 |
|
GtkWidget *warning; |
40 |
|
|
41 |
struct { |
struct { |
42 |
GtkWidget *minlat, *maxlat, *minlon, *maxlon; |
GtkWidget *minlat, *maxlat, *minlon, *maxlon; |
53 |
} mmapper; |
} mmapper; |
54 |
#endif |
#endif |
55 |
|
|
56 |
|
#ifdef ENABLE_OSM_GPS_MAP |
57 |
struct { |
struct { |
58 |
GtkWidget *widget; |
GtkWidget *widget; |
59 |
GtkWidget *zoomin, *zoomout; |
GtkWidget *zoomin, *zoomout, *center, *modesel, *gps; |
60 |
|
gboolean needs_redraw, drag_mode; |
61 |
|
gint handler_id; |
62 |
|
coord_t start; |
63 |
} map; |
} map; |
64 |
|
#endif |
65 |
} context_t; |
} context_t; |
66 |
|
|
67 |
static void parse_and_set_lat(GtkWidget *src, GtkWidget *dst, pos_float_t *store) { |
static void parse_and_set_lat(GtkWidget *src, pos_float_t *store) { |
68 |
pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(src))); |
pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(src))); |
69 |
if(pos_lat_valid(i)) { |
if(pos_lat_valid(i)) |
70 |
*store = i; |
*store = i; |
|
pos_lat_label_set(dst, i); |
|
|
} |
|
71 |
} |
} |
72 |
|
|
73 |
static void parse_and_set_lon(GtkWidget *src, GtkWidget *dst, pos_float_t *store) { |
static void parse_and_set_lon(GtkWidget *src, pos_float_t *store) { |
74 |
pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(src))); |
pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(src))); |
75 |
if(pos_lon_valid(i)) { |
if(pos_lon_valid(i)) |
76 |
*store = i; |
*store = i; |
|
pos_lon_label_set(dst, i); |
|
|
} |
|
77 |
} |
} |
78 |
|
|
79 |
#define log2(x) (log(x) / log(2)) |
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 |
|
static void on_area_warning_clicked(GtkButton *button, gpointer data) { |
95 |
|
context_t *context = (context_t*)data; |
96 |
|
|
97 |
void get_zoom(context_t *context) { |
/* compute area size */ |
98 |
pos_float_t center_lat = (context->max.lat + context->min.lat)/2; |
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 |
/* we know pixel size, we know the real size, we want the zoom! */ |
double area = vscale * (context->max.lat - context->min.lat) * |
103 |
|
hscale * (context->max.lon - context->min.lon); |
104 |
|
|
105 |
printf("map_update: %d x %d\n", |
warningf(context->dialog, |
106 |
context->map.widget->allocation.width, |
_("The currently selected area is %.02f km² (%.02f mi²) in size. " |
107 |
context->map.widget->allocation.height); |
"This is more than the recommended %.02f km² (%.02f mi²).\n\n" |
108 |
|
"Continuing may result in a big download and low mapping performance " |
109 |
|
"in a densly mapped area (e.g. cities)!"), |
110 |
|
area, area/(KMPMIL*KMPMIL), |
111 |
|
WARN_OVER, WARN_OVER/(KMPMIL*KMPMIL) |
112 |
|
); |
113 |
|
|
114 |
double vscale = DEG2RAD(POS_EQ_RADIUS); |
} |
|
double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS); |
|
115 |
|
|
116 |
printf("scale: %f m/pix %f m/pix\n", hscale*256, vscale*256); |
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 |
// double height = 8 * (1<<zoom) / vscale; // 2^zoom ln2(zoom) |
/* check if area size exceeds recommended values */ |
123 |
// double hzoom = log2(context->map.widget->allocation.height * vscale / 8); |
pos_float_t center_lat = (context->max.lat + context->min.lat)/2; |
124 |
// double width = 16 * (1<<zoom) / hscale; |
double vscale = DEG2RAD(POS_EQ_RADIUS / 1000.0); |
125 |
// double vzoom = log2(context->map.widget->allocation.width * hscale / 8); |
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 |
// printf("zoom: %f %f\n", hzoom, vzoom); |
if(area > WARN_OVER) |
131 |
|
gtk_widget_show(context->warning); |
132 |
|
else |
133 |
|
gtk_widget_hide(context->warning); |
134 |
} |
} |
135 |
|
|
136 |
/* the contents of the map tab have been changed */ |
#ifdef ENABLE_OSM_GPS_MAP |
137 |
static void map_update(context_t *context) { |
#define LOG2(x) (log(x) / log(2)) |
|
pos_float_t center_lat = (context->max.lat + context->min.lat)/2; |
|
|
pos_float_t center_lon = (context->max.lon + context->min.lon)/2; |
|
138 |
|
|
139 |
get_zoom(context); |
static GSList *pos_append_rad(GSList *list, pos_float_t lat, pos_float_t lon) { |
140 |
|
coord_t *coo = g_new0(coord_t, 1); |
141 |
|
coo->rlat = lat; |
142 |
|
coo->rlon = lon; |
143 |
|
list = g_slist_append(list, coo); |
144 |
|
return list; |
145 |
|
} |
146 |
|
|
147 |
osm_gps_map_set_center(OSM_GPS_MAP(context->map.widget), |
static GSList *pos_append(GSList *list, pos_float_t lat, pos_float_t lon) { |
148 |
center_lat, center_lon); |
return pos_append_rad(list, DEG2RAD(lat), DEG2RAD(lon)); |
149 |
|
} |
150 |
|
|
151 |
osm_gps_map_set_zoom(OSM_GPS_MAP(context->map.widget), 14); |
/* the contents of the map tab have been changed */ |
152 |
|
static void map_update(context_t *context, gboolean forced) { |
153 |
|
|
154 |
|
/* map is first tab (page 0) */ |
155 |
|
if(!forced && !current_tab_is(context, -1, TAB_LABEL_MAP)) { |
156 |
|
context->map.needs_redraw = TRUE; |
157 |
|
return; |
158 |
|
} |
159 |
|
|
160 |
|
/* 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 |
|
|
164 |
|
/* 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 |
|
|
168 |
|
osm_gps_map_clear_tracks(OSM_GPS_MAP(context->map.widget)); |
169 |
|
} else { |
170 |
|
|
171 |
|
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 |
|
|
174 |
|
/* 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 |
|
context->map.needs_redraw = FALSE; |
202 |
} |
} |
203 |
|
|
204 |
static gboolean on_map_configure(GtkWidget *widget, |
static gboolean on_map_configure(GtkWidget *widget, |
205 |
GdkEventConfigure *event, |
GdkEventConfigure *event, |
206 |
context_t *context) { |
context_t *context) { |
207 |
|
map_update(context, FALSE); |
|
map_update(context); |
|
208 |
return FALSE; |
return FALSE; |
209 |
} |
} |
210 |
|
#endif |
211 |
|
|
212 |
/* the contents of the direct tab have been changed */ |
/* the contents of the direct tab have been changed */ |
213 |
static void direct_update(context_t *context) { |
static void direct_update(context_t *context) { |
238 |
static void callback_modified_direct(GtkWidget *widget, gpointer data) { |
static void callback_modified_direct(GtkWidget *widget, gpointer data) { |
239 |
context_t *context = (context_t*)data; |
context_t *context = (context_t*)data; |
240 |
|
|
241 |
/* direct is first tab (page 0) */ |
/* direct is second tab (page 1) */ |
242 |
if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 0) |
if(!current_tab_is(context, -1, TAB_LABEL_DIRECT)) |
243 |
return; |
return; |
244 |
|
|
245 |
/* parse the fields from the direct entry pad */ |
/* parse the fields from the direct entry pad */ |
246 |
parse_and_set_lat(context->direct.minlat, context->minlat, &context->min.lat); |
parse_and_set_lat(context->direct.minlat, &context->min.lat); |
247 |
parse_and_set_lon(context->direct.minlon, context->minlon, &context->min.lon); |
parse_and_set_lon(context->direct.minlon, &context->min.lon); |
248 |
parse_and_set_lat(context->direct.maxlat, context->maxlat, &context->max.lat); |
parse_and_set_lat(context->direct.maxlat, &context->max.lat); |
249 |
parse_and_set_lon(context->direct.maxlon, context->maxlon, &context->max.lon); |
parse_and_set_lon(context->direct.maxlon, &context->max.lon); |
250 |
|
|
251 |
|
area_main_update(context); |
252 |
|
|
253 |
/* also adjust other views */ |
/* also adjust other views */ |
254 |
extent_update(context); |
extent_update(context); |
255 |
|
#ifdef ENABLE_OSM_GPS_MAP |
256 |
|
map_update(context, FALSE); |
257 |
|
#endif |
258 |
} |
} |
259 |
|
|
260 |
static void callback_modified_extent(GtkWidget *widget, gpointer data) { |
static void callback_modified_extent(GtkWidget *widget, gpointer data) { |
261 |
context_t *context = (context_t*)data; |
context_t *context = (context_t*)data; |
262 |
|
|
263 |
/* extent is second tab (page 1) */ |
/* extent is third tab (page 2) */ |
264 |
if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 1) |
if(!current_tab_is(context, -1, TAB_LABEL_EXTENT)) |
265 |
return; |
return; |
266 |
|
|
267 |
pos_float_t center_lat = pos_lat_get(context->extent.lat); |
pos_float_t center_lat = pos_lat_get(context->extent.lat); |
278 |
|
|
279 |
height /= 2 * vscale; |
height /= 2 * vscale; |
280 |
context->min.lat = center_lat - height; |
context->min.lat = center_lat - height; |
|
pos_lat_label_set(context->minlat, context->min.lat); |
|
281 |
context->max.lat = center_lat + height; |
context->max.lat = center_lat + height; |
282 |
pos_lat_label_set(context->maxlat, context->max.lat); |
|
|
|
|
283 |
width /= 2 * hscale; |
width /= 2 * hscale; |
284 |
context->min.lon = center_lon - width; |
context->min.lon = center_lon - width; |
|
pos_lon_label_set(context->minlon, context->min.lon); |
|
285 |
context->max.lon = center_lon + width; |
context->max.lon = center_lon + width; |
286 |
pos_lon_label_set(context->maxlon, context->max.lon); |
|
287 |
|
area_main_update(context); |
288 |
|
|
289 |
/* also update other tabs */ |
/* also update other tabs */ |
290 |
direct_update(context); |
direct_update(context); |
291 |
map_update(context); |
#ifdef ENABLE_OSM_GPS_MAP |
292 |
|
map_update(context, FALSE); |
293 |
|
#endif |
294 |
} |
} |
295 |
|
|
296 |
static void callback_modified_unit(GtkWidget *widget, gpointer data) { |
static void callback_modified_unit(GtkWidget *widget, gpointer data) { |
313 |
static void callback_fetch_mm_clicked(GtkButton *button, gpointer data) { |
static void callback_fetch_mm_clicked(GtkButton *button, gpointer data) { |
314 |
context_t *context = (context_t*)data; |
context_t *context = (context_t*)data; |
315 |
|
|
316 |
printf("clicked fetch mm!\n"); |
if(!dbus_mm_set_position(context->area->appdata->osso_context, NULL)) { |
|
|
|
|
if(!dbus_mm_set_position(context->area->osso_context, NULL)) { |
|
317 |
errorf(context->dialog, |
errorf(context->dialog, |
318 |
_("Unable to communicate with Maemo Mapper. " |
_("Unable to communicate with Maemo Mapper. " |
319 |
"You need to have Maemo Mapper installed " |
"You need to have Maemo Mapper installed " |
321 |
return; |
return; |
322 |
} |
} |
323 |
|
|
324 |
if(!context->area->mmpos->valid) { |
if(!context->area->appdata->mmpos.valid) { |
325 |
errorf(context->dialog, |
errorf(context->dialog, |
326 |
_("No valid position received yet. You need " |
_("No valid position received yet. You need " |
327 |
"to scroll or zoom the Maemo Mapper view " |
"to scroll or zoom the Maemo Mapper view " |
330 |
return; |
return; |
331 |
} |
} |
332 |
|
|
333 |
/* maemo mapper is third tab (page 2) */ |
/* maemo mapper is fourth tab (page 3) */ |
334 |
if(gtk_notebook_get_current_page(GTK_NOTEBOOK(context->notebook)) != 2) |
if(!current_tab_is(context, -1, TAB_LABEL_MM)) |
335 |
return; |
return; |
336 |
|
|
337 |
/* maemo mapper pos data ... */ |
/* maemo mapper pos data ... */ |
338 |
pos_float_t center_lat = context->area->mmpos->pos.lat; |
pos_float_t center_lat = context->area->appdata->mmpos.pos.lat; |
339 |
pos_float_t center_lon = context->area->mmpos->pos.lon; |
pos_float_t center_lon = context->area->appdata->mmpos.pos.lon; |
340 |
int zoom = context->area->mmpos->zoom; |
int zoom = context->area->appdata->mmpos.zoom; |
341 |
|
|
342 |
if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon)) |
if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon)) |
343 |
return; |
return; |
345 |
double vscale = DEG2RAD(POS_EQ_RADIUS); |
double vscale = DEG2RAD(POS_EQ_RADIUS); |
346 |
double height = 8 * (1<<zoom) / vscale; |
double height = 8 * (1<<zoom) / vscale; |
347 |
context->min.lat = center_lat - height; |
context->min.lat = center_lat - height; |
|
pos_lat_label_set(context->minlat, context->min.lat); |
|
348 |
context->max.lat = center_lat + height; |
context->max.lat = center_lat + height; |
|
pos_lat_label_set(context->maxlat, context->max.lat); |
|
349 |
|
|
350 |
double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS); |
double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS); |
351 |
double width = 16 * (1<<zoom) / hscale; |
double width = 16 * (1<<zoom) / hscale; |
352 |
context->min.lon = center_lon - width; |
context->min.lon = center_lon - width; |
|
pos_lon_label_set(context->minlon, context->min.lon); |
|
353 |
context->max.lon = center_lon + width; |
context->max.lon = center_lon + width; |
354 |
pos_lon_label_set(context->maxlon, context->max.lon); |
|
355 |
|
area_main_update(context); |
356 |
|
|
357 |
/* also update other tabs */ |
/* also update other tabs */ |
358 |
direct_update(context); |
direct_update(context); |
359 |
extent_update(context); |
extent_update(context); |
360 |
map_update(context); |
#ifdef ENABLE_OSM_GPS_MAP |
361 |
|
map_update(context, FALSE); |
362 |
|
#endif |
363 |
} |
} |
364 |
#endif |
#endif |
365 |
|
|
366 |
|
#ifdef ENABLE_OSM_GPS_MAP |
367 |
|
|
368 |
|
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 |
|
|
374 |
|
/* remove existing marker */ |
375 |
|
osm_gps_map_clear_tracks(map); |
376 |
|
|
377 |
|
/* 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 |
|
|
381 |
|
return TRUE; |
382 |
|
} |
383 |
|
|
384 |
|
return FALSE; |
385 |
|
} |
386 |
|
|
387 |
|
static gboolean |
388 |
|
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 |
|
on_map_button_release_event(GtkWidget *widget, |
417 |
|
GdkEventButton *event, context_t *context) { |
418 |
|
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 |
|
return FALSE; |
460 |
|
} |
461 |
|
|
462 |
static void map_zoom(context_t *context, int step) { |
static void map_zoom(context_t *context, int step) { |
463 |
int zoom; |
int zoom; |
464 |
OsmGpsMap *map = OSM_GPS_MAP(context->map.widget); |
OsmGpsMap *map = OSM_GPS_MAP(context->map.widget); |
465 |
g_object_get(map, "zoom", &zoom, NULL); |
g_object_get(map, "zoom", &zoom, NULL); |
466 |
zoom = osm_gps_map_set_zoom(map, zoom+step); |
zoom = osm_gps_map_set_zoom(map, zoom+step); |
467 |
|
|
|
get_zoom(context); |
|
|
|
|
468 |
/* enable/disable zoom buttons as required */ |
/* enable/disable zoom buttons as required */ |
469 |
gtk_widget_set_sensitive(context->map.zoomin, zoom<17); |
gtk_widget_set_sensitive(context->map.zoomin, zoom<17); |
470 |
gtk_widget_set_sensitive(context->map.zoomout, zoom>1); |
gtk_widget_set_sensitive(context->map.zoomout, zoom>1); |
482 |
return FALSE; |
return FALSE; |
483 |
} |
} |
484 |
|
|
485 |
|
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 |
|
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 |
|
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 |
|
if(current_tab_is(context, page_num, TAB_LABEL_MAP) && |
526 |
|
context->map.needs_redraw) |
527 |
|
map_update(context, TRUE); |
528 |
|
} |
529 |
|
|
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 |
|
#endif |
540 |
|
return button; |
541 |
|
} |
542 |
|
|
543 |
|
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 |
gboolean area_edit(area_edit_t *area) { |
gboolean area_edit(area_edit_t *area) { |
561 |
|
GtkWidget *vbox; |
562 |
gboolean ok = FALSE; |
gboolean ok = FALSE; |
563 |
|
|
564 |
context_t context; |
context_t context; |
576 |
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
577 |
NULL); |
NULL); |
578 |
|
|
579 |
GtkWidget *table = gtk_table_new(4, 2, FALSE); // x, y |
GtkWidget *table = gtk_table_new(5, 2, FALSE); // x, y |
580 |
|
|
581 |
GtkWidget *label = gtk_label_new(_("Latitude:")); |
GtkWidget *label = gtk_label_new(_("Latitude:")); |
582 |
misc_table_attach(table, label, 0, 0); |
misc_table_attach(table, label, 0, 0); |
596 |
context.maxlon = pos_lon_label_new(area->max->lon); |
context.maxlon = pos_lon_label_new(area->max->lon); |
597 |
misc_table_attach(table, context.maxlon, 3, 1); |
misc_table_attach(table, context.maxlon, 3, 1); |
598 |
|
|
599 |
|
context.warning = gtk_button_new(); |
600 |
|
gtk_button_set_image(GTK_BUTTON(context.warning), |
601 |
|
gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING, |
602 |
|
GTK_ICON_SIZE_BUTTON)); |
603 |
|
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 |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context.dialog)->vbox), |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context.dialog)->vbox), |
608 |
table, FALSE, FALSE, 0); |
table, FALSE, FALSE, 0); |
609 |
|
|
610 |
context.notebook = gtk_notebook_new(); |
context.notebook = gtk_notebook_new(); |
611 |
|
|
612 |
|
#ifdef ENABLE_OSM_GPS_MAP |
613 |
/* ------------- fetch from map ------------------------ */ |
/* ------------- fetch from map ------------------------ */ |
614 |
|
|
615 |
GtkWidget *hbox = gtk_hbox_new(FALSE, 0); |
GtkWidget *hbox = gtk_hbox_new(FALSE, 0); |
616 |
|
|
617 |
|
context.map.needs_redraw = FALSE; |
618 |
context.map.widget = g_object_new(OSM_TYPE_GPS_MAP, |
context.map.widget = g_object_new(OSM_TYPE_GPS_MAP, |
619 |
"repo-uri", MAP_SOURCE_OPENSTREETMAP, |
"repo-uri", MAP_SOURCE_OPENSTREETMAP, |
620 |
"proxy-uri", misc_get_proxy_uri(area->settings), |
"proxy-uri", misc_get_proxy_uri(area->settings), |
621 |
|
"tile-cache", NULL, |
622 |
NULL); |
NULL); |
623 |
|
|
624 |
g_signal_connect(G_OBJECT(context.map.widget), "configure-event", |
g_signal_connect(G_OBJECT(context.map.widget), "configure-event", |
625 |
G_CALLBACK(on_map_configure), &context); |
G_CALLBACK(on_map_configure), &context); |
626 |
|
g_signal_connect(G_OBJECT(context.map.widget), "button-press-event", |
627 |
|
G_CALLBACK(on_map_button_press_event), &context); |
628 |
|
g_signal_connect(G_OBJECT(context.map.widget), "motion-notify-event", |
629 |
|
G_CALLBACK(on_map_motion_notify_event), &context); |
630 |
|
g_signal_connect(G_OBJECT(context.map.widget), "button-release-event", |
631 |
|
G_CALLBACK(on_map_button_release_event), &context); |
632 |
|
|
633 |
gtk_box_pack_start_defaults(GTK_BOX(hbox), context.map.widget); |
gtk_box_pack_start_defaults(GTK_BOX(hbox), context.map.widget); |
634 |
|
|
635 |
/* zoom button box */ |
/* zoom button box */ |
636 |
GtkWidget *vbox = gtk_vbox_new(FALSE,0); |
vbox = gtk_vbox_new(FALSE,0); |
637 |
|
|
638 |
context.map.zoomin = gtk_button_new(); |
context.map.zoomin = |
639 |
gtk_button_set_image(GTK_BUTTON(context.map.zoomin), |
map_add_button(GTK_STOCK_ZOOM_IN, G_CALLBACK(cb_map_zoomin), |
640 |
gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_MENU)); |
&context, _("Zoom in")); |
|
g_signal_connect(context.map.zoomin, "clicked", |
|
|
G_CALLBACK(cb_map_zoomin), &context); |
|
641 |
gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomin, FALSE, FALSE, 0); |
gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomin, FALSE, FALSE, 0); |
642 |
|
|
643 |
context.map.zoomout = gtk_button_new(); |
context.map.zoomout = |
644 |
gtk_button_set_image(GTK_BUTTON(context.map.zoomout), |
map_add_button(GTK_STOCK_ZOOM_OUT, G_CALLBACK(cb_map_zoomout), |
645 |
gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT, GTK_ICON_SIZE_MENU)); |
&context, _("Zoom out")); |
|
g_signal_connect(context.map.zoomout, "clicked", |
|
|
G_CALLBACK(cb_map_zoomout), &context); |
|
646 |
gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomout, FALSE, FALSE, 0); |
gtk_box_pack_start(GTK_BOX(vbox), context.map.zoomout, FALSE, FALSE, 0); |
647 |
|
|
648 |
|
context.map.center = |
649 |
|
map_add_button(GTK_STOCK_HOME, G_CALLBACK(cb_map_center), |
650 |
|
&context, _("Center selected area")); |
651 |
|
gtk_box_pack_start(GTK_BOX(vbox), context.map.center, FALSE, FALSE, 0); |
652 |
|
|
653 |
|
context.map.gps = |
654 |
|
map_add_button(GTK_STOCK_ABOUT, G_CALLBACK(cb_map_gps), |
655 |
|
&context, _("Jump to GPS position")); |
656 |
|
gtk_widget_set_sensitive(context.map.gps, FALSE); |
657 |
|
/* install handler for timed updates of the gps button */ |
658 |
|
context.map.handler_id = gtk_timeout_add(1000, map_gps_update, &context); |
659 |
|
gtk_box_pack_start(GTK_BOX(vbox), context.map.gps, FALSE, FALSE, 0); |
660 |
|
|
661 |
|
context.map.drag_mode = TRUE; |
662 |
|
context.map.start.rlon = context.map.start.rlat = NAN; |
663 |
|
context.map.modesel = |
664 |
|
map_add_button(GTK_STOCK_FIND, G_CALLBACK(cb_map_modesel), |
665 |
|
&context, _("Toggle scroll/select")); |
666 |
|
gtk_box_pack_start(GTK_BOX(vbox), context.map.modesel, FALSE, FALSE, 0); |
667 |
|
|
668 |
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0); |
669 |
|
|
670 |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
671 |
hbox, gtk_label_new(_("Map"))); |
hbox, gtk_label_new(_(TAB_LABEL_MAP))); |
672 |
|
#endif |
673 |
|
|
674 |
/* ------------ direct min/max edit --------------- */ |
/* ------------ direct min/max edit --------------- */ |
675 |
|
|
676 |
vbox = gtk_vbox_new(FALSE, 10); |
vbox = gtk_vbox_new(FALSE, 10); |
677 |
table = gtk_table_new(3, 3, FALSE); // x, y |
table = gtk_table_new(3, 3, FALSE); // x, y |
678 |
|
gtk_table_set_col_spacings(GTK_TABLE(table), 10); |
679 |
|
gtk_table_set_row_spacings(GTK_TABLE(table), 5); |
680 |
|
|
681 |
context.direct.minlat = pos_lat_entry_new(0.0); |
context.direct.minlat = pos_lat_entry_new(0.0); |
682 |
misc_table_attach(table, context.direct.minlat, 0, 0); |
misc_table_attach(table, context.direct.minlat, 0, 0); |
711 |
|
|
712 |
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); |
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); |
713 |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
714 |
vbox, gtk_label_new(_("Direct"))); |
vbox, gtk_label_new(_(TAB_LABEL_DIRECT))); |
715 |
|
|
716 |
/* ------------- center/extent edit ------------------------ */ |
/* ------------- center/extent edit ------------------------ */ |
717 |
|
|
718 |
vbox = gtk_vbox_new(FALSE, 10); |
vbox = gtk_vbox_new(FALSE, 10); |
719 |
table = gtk_table_new(3, 4, FALSE); // x, y |
table = gtk_table_new(3, 4, FALSE); // x, y |
720 |
|
gtk_table_set_col_spacings(GTK_TABLE(table), 10); |
721 |
|
gtk_table_set_row_spacings(GTK_TABLE(table), 5); |
722 |
|
|
723 |
label = gtk_label_new(_("Center:")); |
label = gtk_label_new(_("Center:")); |
724 |
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); |
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); |
728 |
context.extent.lon = pos_lon_entry_new(0.0); |
context.extent.lon = pos_lon_entry_new(0.0); |
729 |
gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lon, 2, 3, 0, 1); |
gtk_table_attach_defaults(GTK_TABLE(table), context.extent.lon, 2, 3, 0, 1); |
730 |
|
|
731 |
gtk_table_set_row_spacing(GTK_TABLE(table), 0, 8); |
gtk_table_set_row_spacing(GTK_TABLE(table), 0, 10); |
732 |
|
|
733 |
label = gtk_label_new(_("Width:")); |
label = gtk_label_new(_("Width:")); |
734 |
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); |
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); |
740 |
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); |
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); |
741 |
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); |
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); |
742 |
context.extent.height = gtk_entry_new(); |
context.extent.height = gtk_entry_new(); |
743 |
gtk_table_attach_defaults(GTK_TABLE(table), context.extent.height, 1, 2, 2, 3); |
gtk_table_attach_defaults(GTK_TABLE(table), |
744 |
|
context.extent.height, 1, 2, 2, 3); |
745 |
|
|
746 |
context.extent.mil_km = gtk_combo_box_new_text(); |
context.extent.mil_km = gtk_combo_box_new_text(); |
747 |
gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("mi")); |
gtk_combo_box_append_text(GTK_COMBO_BOX(context.extent.mil_km), _("mi")); |
772 |
|
|
773 |
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); |
gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); |
774 |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
775 |
vbox, gtk_label_new(_("Extent"))); |
vbox, gtk_label_new(_(TAB_LABEL_EXTENT))); |
776 |
|
|
777 |
#ifdef USE_HILDON |
#ifdef USE_HILDON |
778 |
/* ------------- fetch from maemo mapper ------------------------ */ |
/* ------------- fetch from maemo mapper ------------------------ */ |
791 |
|
|
792 |
|
|
793 |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
gtk_notebook_append_page(GTK_NOTEBOOK(context.notebook), |
794 |
vbox, gtk_label_new(_("Maemo Mapper"))); |
vbox, gtk_label_new(_(TAB_LABEL_MM))); |
795 |
#endif |
#endif |
796 |
|
|
797 |
/* ------------------------------------------------------ */ |
/* ------------------------------------------------------ */ |
799 |
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox), |
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox), |
800 |
context.notebook); |
context.notebook); |
801 |
|
|
802 |
|
#ifdef ENABLE_OSM_GPS_MAP |
803 |
|
g_signal_connect(G_OBJECT(context.notebook), "switch-page", |
804 |
|
G_CALLBACK(on_page_switch), &context); |
805 |
|
#endif |
806 |
|
|
807 |
gtk_widget_show_all(context.dialog); |
gtk_widget_show_all(context.dialog); |
808 |
|
|
809 |
|
area_main_update(&context); |
810 |
|
|
811 |
if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) { |
if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) { |
812 |
/* copy modified values back to given storage */ |
/* copy modified values back to given storage */ |
813 |
area->min->lat = context.min.lat; |
area->min->lat = context.min.lat; |
817 |
ok = TRUE; |
ok = TRUE; |
818 |
} |
} |
819 |
|
|
820 |
|
#ifdef ENABLE_OSM_GPS_MAP |
821 |
|
gtk_timeout_remove(context.map.handler_id); |
822 |
|
#endif |
823 |
|
|
824 |
gtk_widget_destroy(context.dialog); |
gtk_widget_destroy(context.dialog); |
825 |
|
|
826 |
return ok; |
return ok; |