21 |
#include <string.h> |
#include <string.h> |
22 |
#include <ctype.h> |
#include <ctype.h> |
23 |
|
|
24 |
|
#include <glib.h> |
25 |
|
#include <glib/gstdio.h> |
26 |
|
|
27 |
#include "gpxview.h" |
#include "gpxview.h" |
28 |
|
|
29 |
|
#if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5) |
30 |
|
#include <hildon/hildon-entry.h> |
31 |
|
#include <hildon/hildon-touch-selector.h> |
32 |
|
#include <hildon/hildon-picker-button.h> |
33 |
|
#include <hildon/hildon-picker-dialog.h> |
34 |
|
#endif |
35 |
|
|
36 |
|
float roundf(float x); |
37 |
|
|
38 |
|
/* TODO: make coordinate picker support "changed" signal */ |
39 |
|
|
40 |
|
#ifdef FREMANTLE |
41 |
|
#define PRESET_PICKER_DIALOG |
42 |
|
#define COORDINATE_PICKER |
43 |
|
#endif |
44 |
|
|
45 |
char strlastchr(char *str) { |
char strlastchr(char *str) { |
46 |
return str[strlen(str)]-1; |
return str[strlen(str)]-1; |
47 |
} |
} |
167 |
|
|
168 |
const char *pos_get_bearing_str(pos_t from, pos_t to) { |
const char *pos_get_bearing_str(pos_t from, pos_t to) { |
169 |
static const char *bear_str[]={ |
static const char *bear_str[]={ |
170 |
"N", "NE", "E", "SE", "S", "SW", "W", "NW" }; |
"N", "NE", "E", "SE", "S", "SW", "W", "NW", "" }; |
171 |
int idx = (gpx_pos_get_bearing(from, to)+22.5)/45.0; |
|
172 |
/* make sure we stay in icon bounds */ |
float bearing = gpx_pos_get_bearing(from, to); |
173 |
while(idx < 0) idx += 8; |
if(!isnan(bearing)) { |
174 |
while(idx > 7) idx -= 8; |
int idx = (bearing+22.5)/45.0; |
175 |
return _(bear_str[idx]); |
/* make sure we stay in icon bounds */ |
176 |
|
while(idx < 0) idx += 8; |
177 |
|
while(idx > 7) idx -= 8; |
178 |
|
return _(bear_str[idx]); |
179 |
|
} |
180 |
|
|
181 |
|
return bear_str[8]; // empty string |
182 |
} |
} |
183 |
|
|
184 |
/* the maemo font size is quite huge, so we adjust some fonts */ |
/* the maemo font size is quite huge, so we adjust some fonts */ |
266 |
} |
} |
267 |
|
|
268 |
void distance_str(char *str, int len, float dist, gboolean imperial) { |
void distance_str(char *str, int len, float dist, gboolean imperial) { |
269 |
if(imperial) { |
if(isnan(dist)) |
270 |
|
snprintf(str, len, "---"); |
271 |
|
else if(imperial) { |
272 |
/* 1 mil = 1760 yd = 5280 ft ... */ |
/* 1 mil = 1760 yd = 5280 ft ... */ |
273 |
if(dist<0.018) snprintf(str, len, "%.1f ft", dist*5280.0); |
if(dist<0.018) snprintf(str, len, "%.1f ft", dist*5280.0); |
274 |
else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0); |
else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0); |
309 |
return val; |
return val; |
310 |
} |
} |
311 |
|
|
312 |
|
/* ------------------ coordinate picker tool --------------------------- */ |
313 |
|
|
314 |
static gboolean mark(GtkWidget *widget, gboolean valid) { |
static gboolean mark(GtkWidget *widget, gboolean valid) { |
315 |
gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE); |
gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE); |
316 |
return valid; |
return valid; |
317 |
} |
} |
318 |
|
|
319 |
|
#ifndef COORDINATE_PICKER |
320 |
static void callback_modified_lat(GtkWidget *widget, gpointer data ) { |
static void callback_modified_lat(GtkWidget *widget, gpointer data ) { |
321 |
float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget))); |
float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget))); |
322 |
mark(widget, !isnan(i)); |
mark(widget, !isnan(i)); |
323 |
} |
} |
324 |
|
#else |
325 |
|
static GtkWidget *letter_picker_create(char *a, char *b, int sel) { |
326 |
|
#ifndef FREMANTLE |
327 |
|
GtkWidget *view = gtk_tree_view_new(); |
328 |
|
#else |
329 |
|
GtkWidget *view = hildon_gtk_tree_view_new(HILDON_UI_MODE_EDIT); |
330 |
|
#endif |
331 |
|
|
332 |
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); |
333 |
|
GtkTreeSelection *selection = |
334 |
|
gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); |
335 |
|
|
336 |
|
/* --- "char" column --- */ |
337 |
|
GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
338 |
|
g_object_set(renderer, "xalign", 0.5, NULL ); |
339 |
|
gtk_tree_view_insert_column_with_attributes( |
340 |
|
GTK_TREE_VIEW(view), -1, "char", renderer, "text", 0, NULL); |
341 |
|
|
342 |
|
GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); |
343 |
|
|
344 |
|
/* add digits */ |
345 |
|
GtkTreeIter iter_a, iter_b; |
346 |
|
gtk_list_store_append (store, &iter_a); |
347 |
|
gtk_list_store_set(store, &iter_a, 0, _(a), 1, 0, -1); |
348 |
|
gtk_list_store_append (store, &iter_b); |
349 |
|
gtk_list_store_set(store, &iter_b, 0, _(b), 1, 1, -1); |
350 |
|
|
351 |
|
gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); |
352 |
|
g_object_unref(store); |
353 |
|
|
354 |
|
/* select right character */ |
355 |
|
GtkTreeIter iter = (!sel)?iter_a:iter_b; |
356 |
|
gtk_tree_selection_select_iter(selection, &iter); |
357 |
|
GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); |
358 |
|
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view), |
359 |
|
path, NULL, TRUE, 0.5, 0.5); |
360 |
|
gtk_tree_path_free(path); |
361 |
|
|
362 |
|
/* put this inside a scrolled view */ |
363 |
|
#ifndef USE_PANNABLE_AREA |
364 |
|
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); |
365 |
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
366 |
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
367 |
|
gtk_container_add(GTK_CONTAINER(scrolled_window), view); |
368 |
|
return scrolled_window; |
369 |
|
#else |
370 |
|
GtkWidget *pannable_area = hildon_pannable_area_new(); |
371 |
|
gtk_container_add(GTK_CONTAINER(pannable_area), view); |
372 |
|
return pannable_area; |
373 |
|
#endif |
374 |
|
} |
375 |
|
|
376 |
|
static int picker_get(GtkWidget *widget) { |
377 |
|
GtkWidget *view = gtk_bin_get_child(GTK_BIN(widget)); |
378 |
|
|
379 |
|
GtkTreeSelection *sel = |
380 |
|
gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); |
381 |
|
|
382 |
|
GtkTreeModel *model; |
383 |
|
GtkTreeIter iter; |
384 |
|
|
385 |
|
/* there should never be an unseletced column. But if */ |
386 |
|
/* it is, we count it as zero */ |
387 |
|
if(!gtk_tree_selection_get_selected(sel, &model, &iter)) |
388 |
|
return 0; |
389 |
|
|
390 |
|
int retval = 0; |
391 |
|
gtk_tree_model_get(model, &iter, 1, &retval, -1); |
392 |
|
return retval; |
393 |
|
} |
394 |
|
|
395 |
|
|
396 |
|
static GtkWidget *digit_picker_create(int min, int max, int sel) { |
397 |
|
#ifndef FREMANTLE |
398 |
|
GtkWidget *view = gtk_tree_view_new(); |
399 |
|
#else |
400 |
|
GtkWidget *view = hildon_gtk_tree_view_new(HILDON_UI_MODE_EDIT); |
401 |
|
#endif |
402 |
|
|
403 |
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); |
404 |
|
GtkTreeSelection *selection = |
405 |
|
gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); |
406 |
|
|
407 |
|
/* --- "digit" column --- */ |
408 |
|
GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
409 |
|
g_object_set(renderer, "xalign", 0.5, NULL ); |
410 |
|
gtk_tree_view_insert_column_with_attributes( |
411 |
|
GTK_TREE_VIEW(view), -1, "digit", renderer, "text", 0, NULL); |
412 |
|
|
413 |
|
GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); |
414 |
|
|
415 |
|
/* add digits */ |
416 |
|
int i; |
417 |
|
GtkTreeIter siter; |
418 |
|
for(i=min;i<=max;i++) { |
419 |
|
char str[2] = { '0'+i, 0 }; |
420 |
|
GtkTreeIter iter; |
421 |
|
/* Append a row and fill in some data */ |
422 |
|
gtk_list_store_append (store, &iter); |
423 |
|
gtk_list_store_set(store, &iter, 0, str, 1, i, -1); |
424 |
|
|
425 |
|
if(i == sel) siter = iter; |
426 |
|
} |
427 |
|
|
428 |
|
gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); |
429 |
|
g_object_unref(store); |
430 |
|
|
431 |
|
gtk_tree_selection_select_iter(selection, &siter); |
432 |
|
GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &siter); |
433 |
|
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view), |
434 |
|
path, NULL, TRUE, 0.5, 0.5); |
435 |
|
gtk_tree_path_free(path); |
436 |
|
|
437 |
|
/* put this inside a scrolled view */ |
438 |
|
#ifndef USE_PANNABLE_AREA |
439 |
|
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); |
440 |
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
441 |
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
442 |
|
gtk_container_add(GTK_CONTAINER(scrolled_window), view); |
443 |
|
return scrolled_window; |
444 |
|
#else |
445 |
|
GtkWidget *pannable_area = hildon_pannable_area_new(); |
446 |
|
gtk_container_add(GTK_CONTAINER(pannable_area), view); |
447 |
|
return pannable_area; |
448 |
|
#endif |
449 |
|
} |
450 |
|
|
451 |
|
static gint on_lat_picker_button_press(GtkWidget *button, |
452 |
|
GdkEventButton *event, gpointer data) { |
453 |
|
|
454 |
|
if(event->type == GDK_BUTTON_PRESS) { |
455 |
|
GtkWidget *dialog = |
456 |
|
gtk_dialog_new_with_buttons(_("Latitude"), |
457 |
|
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), |
458 |
|
GTK_DIALOG_MODAL, |
459 |
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
460 |
|
_("Done"), GTK_RESPONSE_ACCEPT, |
461 |
|
NULL); |
462 |
|
|
463 |
|
gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200); |
464 |
|
|
465 |
|
int i, lat = (int)g_object_get_data(G_OBJECT(button), "latitude"); |
466 |
|
|
467 |
|
/* parse latitude into components */ |
468 |
|
int sign = (lat>=0)?0:1; |
469 |
|
lat = abs(lat); |
470 |
|
int deg = lat / 60000; |
471 |
|
int min = (lat /1000)%60; |
472 |
|
int minfrac = lat % 1000; |
473 |
|
|
474 |
|
GtkWidget *signw, *degw[2], *minw[2], *minfracw[3]; |
475 |
|
|
476 |
|
|
477 |
|
/* create N/S 89° 99.999 */ |
478 |
|
GtkWidget *hbox = gtk_hbox_new(FALSE, 0); |
479 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
480 |
|
signw = letter_picker_create("N","S", sign)); |
481 |
|
|
482 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
483 |
|
degw[0] = digit_picker_create(0,8, deg/10)); |
484 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
485 |
|
degw[1] = digit_picker_create(0,9, deg%10)); |
486 |
|
gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("°"), FALSE, FALSE, 0); |
487 |
|
|
488 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
489 |
|
minw[0] = digit_picker_create(0,5, min/10)); |
490 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
491 |
|
minw[1] = digit_picker_create(0,9, min%10)); |
492 |
|
gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("."), FALSE, FALSE, 0); |
493 |
|
|
494 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
495 |
|
minfracw[0] = digit_picker_create(0,9, minfrac/100)); |
496 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
497 |
|
minfracw[1] = digit_picker_create(0,9, (minfrac/10)%10)); |
498 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
499 |
|
minfracw[2] = digit_picker_create(0,9, minfrac%10)); |
500 |
|
|
501 |
|
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox); |
502 |
|
|
503 |
|
gtk_widget_show_all(dialog); |
504 |
|
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { |
505 |
|
|
506 |
|
/* parse N/S */ |
507 |
|
sign = picker_get(signw)?-1:1; |
508 |
|
|
509 |
|
/* parse degrees ... */ |
510 |
|
for(deg=0,i=0;i<2;i++) |
511 |
|
deg = 10 * deg + picker_get(degw[i]); |
512 |
|
|
513 |
|
/* ... minutes ... */ |
514 |
|
for(min=0,i=0;i<2;i++) |
515 |
|
min = 10 * min + picker_get(minw[i]); |
516 |
|
|
517 |
|
/* ... and fractions of minutes */ |
518 |
|
for(minfrac=0,i=0;i<3;i++) |
519 |
|
minfrac = 10 * minfrac + picker_get(minfracw[i]); |
520 |
|
|
521 |
|
float latitude = sign * (deg + min/60.0 + minfrac/60000.0); |
522 |
|
lat_entry_set(button, latitude); |
523 |
|
} |
524 |
|
|
525 |
|
gtk_widget_destroy(dialog); |
526 |
|
|
527 |
|
return TRUE; |
528 |
|
} |
529 |
|
return FALSE; |
530 |
|
} |
531 |
|
#endif |
532 |
|
|
533 |
/* a entry that is colored red when being "active" */ |
/* a entry that is colored red when being "active" */ |
534 |
GtkWidget *lat_entry_new(float lat) { |
GtkWidget *lat_entry_new(float lat) { |
535 |
|
char str[32]; |
536 |
|
pos_lat_str(str, sizeof(str), lat); |
537 |
|
|
538 |
|
#ifndef COORDINATE_PICKER |
539 |
GdkColor color; |
GdkColor color; |
540 |
GtkWidget *widget = gtk_entry_new(); |
|
541 |
|
GtkWidget *widget = entry_new(); |
542 |
gdk_color_parse("#ff0000", &color); |
gdk_color_parse("#ff0000", &color); |
543 |
gtk_widget_modify_text(widget, TAG_STATE, &color); |
gtk_widget_modify_text(widget, TAG_STATE, &color); |
544 |
|
|
|
char str[32]; |
|
|
pos_lat_str(str, sizeof(str), lat); |
|
545 |
gtk_entry_set_text(GTK_ENTRY(widget), str); |
gtk_entry_set_text(GTK_ENTRY(widget), str); |
546 |
|
|
547 |
g_signal_connect(G_OBJECT(widget), "changed", |
g_signal_connect(G_OBJECT(widget), "changed", |
548 |
G_CALLBACK(callback_modified_lat), NULL); |
G_CALLBACK(callback_modified_lat), NULL); |
549 |
|
|
550 |
|
#else |
551 |
|
GtkWidget *widget = gtk_button_new_with_label(str); |
552 |
|
|
553 |
|
#ifdef FREMANTLE |
554 |
|
hildon_gtk_widget_set_theme_size(widget, |
555 |
|
(HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); |
556 |
|
#endif |
557 |
|
int lat_int = (int)roundf(lat * 60000); |
558 |
|
g_object_set_data(G_OBJECT(widget), "latitude", (gpointer)lat_int); |
559 |
|
gtk_signal_connect(GTK_OBJECT(widget), "button-press-event", |
560 |
|
(GtkSignalFunc)on_lat_picker_button_press, NULL); |
561 |
|
#endif |
562 |
|
|
563 |
return widget; |
return widget; |
564 |
} |
} |
565 |
|
|
566 |
|
#ifndef COORDINATE_PICKER |
567 |
static void callback_modified_lon(GtkWidget *widget, gpointer data ) { |
static void callback_modified_lon(GtkWidget *widget, gpointer data ) { |
568 |
float i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget))); |
float i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget))); |
569 |
mark(widget, !isnan(i)); |
mark(widget, !isnan(i)); |
570 |
} |
} |
571 |
|
#else |
572 |
|
static gint on_lon_picker_button_press(GtkWidget *button, |
573 |
|
GdkEventButton *event, gpointer data) { |
574 |
|
|
575 |
|
if(event->type == GDK_BUTTON_PRESS) { |
576 |
|
GtkWidget *dialog = |
577 |
|
gtk_dialog_new_with_buttons(_("Longitude"), |
578 |
|
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), |
579 |
|
GTK_DIALOG_MODAL, |
580 |
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
581 |
|
_("Done"), GTK_RESPONSE_ACCEPT, |
582 |
|
NULL); |
583 |
|
|
584 |
|
gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200); |
585 |
|
|
586 |
|
int i, lat = (int)g_object_get_data(G_OBJECT(button), "longitude"); |
587 |
|
|
588 |
|
/* parse latitude into components */ |
589 |
|
int sign = (lat>=0)?0:1; |
590 |
|
lat = abs(lat); |
591 |
|
int deg = lat / 60000; |
592 |
|
int min = (lat /1000)%60; |
593 |
|
int minfrac = lat % 1000; |
594 |
|
|
595 |
|
GtkWidget *signw, *degw[3], *minw[2], *minfracw[3]; |
596 |
|
|
597 |
|
/* create E/W 179° 99.999 */ |
598 |
|
GtkWidget *hbox = gtk_hbox_new(FALSE, 0); |
599 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
600 |
|
signw = letter_picker_create("E","W", sign)); |
601 |
|
|
602 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
603 |
|
degw[0] = digit_picker_create(0,1, deg/100)); |
604 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
605 |
|
degw[1] = digit_picker_create(0,9, (deg/10)%10)); |
606 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
607 |
|
degw[2] = digit_picker_create(0,9, deg%10)); |
608 |
|
gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("°"), FALSE, FALSE, 0); |
609 |
|
|
610 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
611 |
|
minw[0] = digit_picker_create(0,5, min/10)); |
612 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
613 |
|
minw[1] = digit_picker_create(0,9, min%10)); |
614 |
|
gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new("."), FALSE, FALSE, 0); |
615 |
|
|
616 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
617 |
|
minfracw[0] = digit_picker_create(0,9, minfrac/100)); |
618 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
619 |
|
minfracw[1] = digit_picker_create(0,9, (minfrac/10)%10)); |
620 |
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), |
621 |
|
minfracw[2] = digit_picker_create(0,9, minfrac%10)); |
622 |
|
|
623 |
|
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox); |
624 |
|
|
625 |
|
gtk_widget_show_all(dialog); |
626 |
|
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { |
627 |
|
|
628 |
|
/* parse E/W */ |
629 |
|
sign = picker_get(signw)?-1:1; |
630 |
|
|
631 |
|
/* parse degrees ... */ |
632 |
|
for(deg=0,i=0;i<3;i++) |
633 |
|
deg = 10 * deg + picker_get(degw[i]); |
634 |
|
|
635 |
|
/* ... minutes ... */ |
636 |
|
for(min=0,i=0;i<2;i++) |
637 |
|
min = 10 * min + picker_get(minw[i]); |
638 |
|
|
639 |
|
/* ... and fractions of minutes */ |
640 |
|
for(minfrac=0,i=0;i<3;i++) |
641 |
|
minfrac = 10 * minfrac + picker_get(minfracw[i]); |
642 |
|
|
643 |
|
float longitude = sign * (deg + min/60.0 + minfrac/60000.0); |
644 |
|
lon_entry_set(button, longitude); |
645 |
|
} |
646 |
|
|
647 |
|
gtk_widget_destroy(dialog); |
648 |
|
|
649 |
|
return TRUE; |
650 |
|
} |
651 |
|
return FALSE; |
652 |
|
} |
653 |
|
#endif |
654 |
|
|
655 |
/* a entry that is colored red when filled with invalid coordinate */ |
/* a entry that is colored red when filled with invalid coordinate */ |
656 |
GtkWidget *lon_entry_new(float lon) { |
GtkWidget *lon_entry_new(float lon) { |
657 |
|
char str[32]; |
658 |
|
pos_lon_str(str, sizeof(str), lon); |
659 |
|
|
660 |
|
#ifndef COORDINATE_PICKER |
661 |
GdkColor color; |
GdkColor color; |
662 |
GtkWidget *widget = gtk_entry_new(); |
|
663 |
|
GtkWidget *widget = entry_new(); |
664 |
gdk_color_parse("#ff0000", &color); |
gdk_color_parse("#ff0000", &color); |
665 |
gtk_widget_modify_text(widget, TAG_STATE, &color); |
gtk_widget_modify_text(widget, TAG_STATE, &color); |
666 |
|
|
|
char str[32]; |
|
|
pos_lon_str(str, sizeof(str), lon); |
|
667 |
gtk_entry_set_text(GTK_ENTRY(widget), str); |
gtk_entry_set_text(GTK_ENTRY(widget), str); |
668 |
|
|
669 |
g_signal_connect(G_OBJECT(widget), "changed", |
g_signal_connect(G_OBJECT(widget), "changed", |
670 |
G_CALLBACK(callback_modified_lon), NULL); |
G_CALLBACK(callback_modified_lon), NULL); |
671 |
|
|
672 |
|
#else |
673 |
|
GtkWidget *widget = gtk_button_new_with_label(str); |
674 |
|
|
675 |
|
#ifdef FREMANTLE |
676 |
|
hildon_gtk_widget_set_theme_size(widget, |
677 |
|
(HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); |
678 |
|
#endif |
679 |
|
int lon_int = (int)roundf(lon * 60000); |
680 |
|
g_object_set_data(G_OBJECT(widget), "longitude", (gpointer)lon_int); |
681 |
|
gtk_signal_connect(GTK_OBJECT(widget), "button-press-event", |
682 |
|
(GtkSignalFunc)on_lon_picker_button_press, NULL); |
683 |
|
#endif |
684 |
|
|
685 |
return widget; |
return widget; |
686 |
} |
} |
687 |
|
|
688 |
|
float lat_entry_get(GtkWidget *widget) { |
689 |
float lat_get(GtkWidget *widget) { |
#ifndef COORDINATE_PICKER |
690 |
char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget)); |
char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget)); |
691 |
|
#else |
692 |
|
char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget)); |
693 |
|
#endif |
694 |
return pos_parse_lat(p); |
return pos_parse_lat(p); |
695 |
} |
} |
696 |
|
|
697 |
float lon_get(GtkWidget *widget) { |
float lon_entry_get(GtkWidget *widget) { |
698 |
|
#ifndef COORDINATE_PICKER |
699 |
char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget)); |
char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget)); |
700 |
|
#else |
701 |
|
char *p = (char*)gtk_button_get_label(GTK_BUTTON(widget)); |
702 |
|
#endif |
703 |
return pos_parse_lon(p); |
return pos_parse_lon(p); |
704 |
} |
} |
705 |
|
|
706 |
|
void lat_entry_set(GtkWidget *widget, float lat) { |
707 |
|
char str[32]; |
708 |
|
pos_lat_str(str, sizeof(str)-1, lat); |
709 |
|
#ifndef COORDINATE_PICKER |
710 |
|
gtk_entry_set_text(GTK_ENTRY(widget), str); |
711 |
|
#else |
712 |
|
gtk_button_set_label(GTK_BUTTON(widget), str); |
713 |
|
int lat_int = (int)roundf(lat * 60000); |
714 |
|
g_object_set_data(G_OBJECT(widget), "latitude", (gpointer)lat_int); |
715 |
|
#endif |
716 |
|
} |
717 |
|
|
718 |
|
void lon_entry_set(GtkWidget *widget, float lon) { |
719 |
|
char str[32]; |
720 |
|
pos_lon_str(str, sizeof(str)-1, lon); |
721 |
|
#ifndef COORDINATE_PICKER |
722 |
|
gtk_entry_set_text(GTK_ENTRY(widget), str); |
723 |
|
#else |
724 |
|
gtk_button_set_label(GTK_BUTTON(widget), str); |
725 |
|
int lon_int = (int)roundf(lon * 60000); |
726 |
|
g_object_set_data(G_OBJECT(widget), "longitude", (gpointer)lon_int); |
727 |
|
#endif |
728 |
|
} |
729 |
|
|
730 |
|
void lat_label_set(GtkWidget *widget, float lat) { |
731 |
|
char str[32]; |
732 |
|
pos_lat_str(str, sizeof(str)-1, lat); |
733 |
|
gtk_label_set(GTK_LABEL(widget), str); |
734 |
|
} |
735 |
|
|
736 |
|
void lon_label_set(GtkWidget *widget, float lon) { |
737 |
|
char str[32]; |
738 |
|
pos_lon_str(str, sizeof(str)-1, lon); |
739 |
|
gtk_label_set(GTK_LABEL(widget), str); |
740 |
|
} |
741 |
|
|
742 |
|
void lat_label_attrib_set(GtkWidget *widget, float lat, |
743 |
|
int size, int strikethrough) { |
744 |
|
char str[32]; |
745 |
|
pos_lat_str(str, sizeof(str)-1, lat); |
746 |
|
gtk_label_attrib_set(widget, str, size, strikethrough); |
747 |
|
} |
748 |
|
|
749 |
|
void lon_label_attrib_set(GtkWidget *widget, float lon, |
750 |
|
int size, int strikethrough) { |
751 |
|
char str[32]; |
752 |
|
pos_lon_str(str, sizeof(str)-1, lon); |
753 |
|
gtk_label_attrib_set(widget, str, size, strikethrough); |
754 |
|
} |
755 |
|
|
756 |
static void callback_modified_dist(GtkWidget *widget, gpointer data ) { |
static void callback_modified_dist(GtkWidget *widget, gpointer data ) { |
757 |
/* don't care for metric/imperial since we only want to know if this */ |
/* don't care for metric/imperial since we only want to know if this */ |
758 |
/* is parseable at all */ |
/* is parseable at all */ |
763 |
/* a entry that is colored red when filled with invalid distance */ |
/* a entry that is colored red when filled with invalid distance */ |
764 |
GtkWidget *dist_entry_new(float dist, gboolean mil) { |
GtkWidget *dist_entry_new(float dist, gboolean mil) { |
765 |
GdkColor color; |
GdkColor color; |
766 |
GtkWidget *widget = gtk_entry_new(); |
GtkWidget *widget = entry_new(); |
767 |
gdk_color_parse("#ff0000", &color); |
gdk_color_parse("#ff0000", &color); |
768 |
gtk_widget_modify_text(widget, TAG_STATE, &color); |
gtk_widget_modify_text(widget, TAG_STATE, &color); |
769 |
|
|
794 |
} |
} |
795 |
#endif |
#endif |
796 |
#endif |
#endif |
797 |
|
|
798 |
|
/* recursively remove an entire file system */ |
799 |
|
void rmdir_recursive(char *path) { |
800 |
|
GDir *dir = g_dir_open(path, 0, NULL); |
801 |
|
if(dir) { |
802 |
|
const char *name = g_dir_read_name(dir); |
803 |
|
while(name) { |
804 |
|
char *fullname = g_strdup_printf("%s/%s", path, name); |
805 |
|
// printf("deleting %s\n", fullname); |
806 |
|
|
807 |
|
if(g_file_test(fullname, G_FILE_TEST_IS_DIR)) |
808 |
|
rmdir_recursive(fullname); |
809 |
|
else if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR)) |
810 |
|
g_remove(fullname); |
811 |
|
|
812 |
|
g_free(fullname); |
813 |
|
name = g_dir_read_name(dir); |
814 |
|
} |
815 |
|
|
816 |
|
g_dir_close(dir); |
817 |
|
} |
818 |
|
g_rmdir(path); |
819 |
|
} |
820 |
|
|
821 |
|
#ifdef ENABLE_BROWSER_INTERFACE |
822 |
|
static void on_link_clicked(GtkButton *button, gpointer data) { |
823 |
|
appdata_t *appdata = (appdata_t*)data; |
824 |
|
char *url = g_object_get_data(G_OBJECT(button), "url"); |
825 |
|
if(url) browser_url(appdata, url); |
826 |
|
} |
827 |
|
#endif |
828 |
|
|
829 |
|
/* a button containing a weblink */ |
830 |
|
GtkWidget *link_button_attrib(appdata_t *appdata, char *str, char *url, |
831 |
|
int size, int strikethrough) { |
832 |
|
|
833 |
|
#ifdef ENABLE_BROWSER_INTERFACE |
834 |
|
if(url) { |
835 |
|
GtkWidget *button = gtk_button_attrib(str, size, strikethrough); |
836 |
|
g_object_set_data(G_OBJECT(button), "url", url); |
837 |
|
gtk_signal_connect(GTK_OBJECT(button), "clicked", |
838 |
|
(GtkSignalFunc)on_link_clicked, appdata); |
839 |
|
|
840 |
|
return button; |
841 |
|
} |
842 |
|
#endif |
843 |
|
return gtk_label_attrib(str, size, strikethrough); |
844 |
|
} |
845 |
|
|
846 |
|
#ifdef ENABLE_BROWSER_INTERFACE |
847 |
|
static void on_link_id_clicked(GtkButton *button, gpointer data) { |
848 |
|
appdata_t *appdata = (appdata_t*)data; |
849 |
|
|
850 |
|
unsigned int id = (unsigned int)g_object_get_data(G_OBJECT(button), "id"); |
851 |
|
char *type = g_object_get_data(G_OBJECT(button), "type"); |
852 |
|
|
853 |
|
char *url = g_strdup_printf("http://www.geocaching.com/%s?id=%u", |
854 |
|
type, id); |
855 |
|
|
856 |
|
if(url) { |
857 |
|
browser_url(appdata, url); |
858 |
|
g_free(url); |
859 |
|
} |
860 |
|
} |
861 |
|
#endif |
862 |
|
|
863 |
|
GtkWidget *link_button_by_id(appdata_t *appdata, char *str, |
864 |
|
const char *type, int id) { |
865 |
|
|
866 |
|
#ifdef ENABLE_BROWSER_INTERFACE |
867 |
|
if(id) { |
868 |
|
GtkWidget *ref = gtk_button_new_with_label(str); |
869 |
|
#if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5) |
870 |
|
// hildon_gtk_widget_set_theme_size(ref, |
871 |
|
// (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); |
872 |
|
#endif |
873 |
|
g_object_set_data(G_OBJECT(ref), "id", (gpointer)id); |
874 |
|
g_object_set_data(G_OBJECT(ref), "type", (gpointer)type); |
875 |
|
gtk_signal_connect(GTK_OBJECT(ref), "clicked", |
876 |
|
GTK_SIGNAL_FUNC(on_link_id_clicked), appdata); |
877 |
|
|
878 |
|
return ref; |
879 |
|
} |
880 |
|
#endif |
881 |
|
return gtk_label_new(str); |
882 |
|
} |
883 |
|
|
884 |
|
|
885 |
|
GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon, |
886 |
|
const char *type, int id) { |
887 |
|
|
888 |
|
#ifdef ENABLE_BROWSER_INTERFACE |
889 |
|
if(id) { |
890 |
|
GtkWidget *ref = gtk_button_new(); |
891 |
|
gtk_button_set_image(GTK_BUTTON(ref), icon); |
892 |
|
|
893 |
|
#if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5) |
894 |
|
// hildon_gtk_widget_set_theme_size(ref, |
895 |
|
// (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); |
896 |
|
#endif |
897 |
|
g_object_set_data(G_OBJECT(ref), "id", (gpointer)id); |
898 |
|
g_object_set_data(G_OBJECT(ref), "type", (gpointer)type); |
899 |
|
gtk_signal_connect(GTK_OBJECT(ref), "clicked", |
900 |
|
GTK_SIGNAL_FUNC(on_link_id_clicked), appdata); |
901 |
|
|
902 |
|
return ref; |
903 |
|
} |
904 |
|
#endif |
905 |
|
return icon; |
906 |
|
} |
907 |
|
|
908 |
|
/* left aligned, word wrapped multiline widget */ |
909 |
|
GtkWidget *simple_text_widget(char *text) { |
910 |
|
GtkWidget *label = gtk_label_new(text); |
911 |
|
|
912 |
|
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
913 |
|
gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD); |
914 |
|
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); |
915 |
|
|
916 |
|
return label; |
917 |
|
} |
918 |
|
|
919 |
|
|
920 |
|
/* a label that is left aligned */ |
921 |
|
GtkWidget *left_label_new(char *str) { |
922 |
|
GtkWidget *widget = gtk_label_new(str); |
923 |
|
gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f); |
924 |
|
return widget; |
925 |
|
} |
926 |
|
|
927 |
|
/* ------------- preset coordinate picker tool ----------------- */ |
928 |
|
|
929 |
|
static void pos_set(GtkWidget *item, float lat, float lon) { |
930 |
|
|
931 |
|
GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry"); |
932 |
|
lat_entry_set(lat_entry, lat); |
933 |
|
|
934 |
|
GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry"); |
935 |
|
lon_entry_set(lon_entry, lon); |
936 |
|
} |
937 |
|
|
938 |
|
static void cb_gps(GtkWidget *item, gpointer data) { |
939 |
|
appdata_t *appdata = (appdata_t*)data; |
940 |
|
gint id = (gint)g_object_get_data(G_OBJECT(item), "id"); |
941 |
|
pos_t *pos = NULL; |
942 |
|
|
943 |
|
if(!id) |
944 |
|
pos = gps_get_pos(appdata); |
945 |
|
else if(id == 1) |
946 |
|
pos = &appdata->home; |
947 |
|
else { |
948 |
|
location_t *location = appdata->location; |
949 |
|
while(location && id > 2) { |
950 |
|
location = location->next; |
951 |
|
id--; |
952 |
|
} |
953 |
|
|
954 |
|
if(id == 2) |
955 |
|
pos = &location->pos; |
956 |
|
} |
957 |
|
|
958 |
|
if(!pos) pos_set(item, NAN, NAN); |
959 |
|
else pos_set(item, pos->lat, pos->lon); |
960 |
|
} |
961 |
|
|
962 |
|
static void cb_geomath(GtkWidget *item, gpointer data) { |
963 |
|
appdata_t *appdata = (appdata_t*)data; |
964 |
|
|
965 |
|
pos_set(item, appdata->geomath.lat, appdata->geomath.lon); |
966 |
|
} |
967 |
|
|
968 |
|
#ifdef ENABLE_OSM_GPS_MAP |
969 |
|
static void cb_map(GtkWidget *item, gpointer data) { |
970 |
|
appdata_t *appdata = (appdata_t*)data; |
971 |
|
|
972 |
|
pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon); |
973 |
|
} |
974 |
|
#endif |
975 |
|
|
976 |
|
static void cb_cache(GtkWidget *item, gpointer data) { |
977 |
|
appdata_t *appdata = (appdata_t*)data; |
978 |
|
|
979 |
|
cache_t *cache = appdata->cur_cache; |
980 |
|
g_assert(cache); |
981 |
|
|
982 |
|
gint id = (gint)g_object_get_data(G_OBJECT(item), "id"); |
983 |
|
|
984 |
|
if(!id) |
985 |
|
pos_set(item, cache->pos.lat, cache->pos.lon); |
986 |
|
else if(id == 1) |
987 |
|
pos_set(item, cache->notes->pos.lat, cache->notes->pos.lon); |
988 |
|
else { |
989 |
|
wpt_t *wpt = cache->wpt; |
990 |
|
while(wpt && id > 2) { |
991 |
|
wpt = wpt->next; |
992 |
|
id--; |
993 |
|
} |
994 |
|
|
995 |
|
if(id == 2) |
996 |
|
pos_set(item, wpt->pos.lat, wpt->pos.lon); |
997 |
|
} |
998 |
|
} |
999 |
|
|
1000 |
|
#ifndef PRESET_PICKER_DIALOG |
1001 |
|
static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata, |
1002 |
|
GtkWidget *icon, char *menu_str, |
1003 |
|
void(*func)(GtkWidget*, gpointer), gint id, |
1004 |
|
GtkWidget *lon_entry, GtkWidget *lat_entry) { |
1005 |
|
|
1006 |
|
GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str); |
1007 |
|
|
1008 |
|
if(icon) |
1009 |
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon); |
1010 |
|
|
1011 |
|
g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry); |
1012 |
|
g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry); |
1013 |
|
g_object_set_data(G_OBJECT(item), "id", (gpointer)id); |
1014 |
|
|
1015 |
|
if(func) |
1016 |
|
gtk_signal_connect(GTK_OBJECT(item), "activate", |
1017 |
|
(GtkSignalFunc)func, appdata); |
1018 |
|
|
1019 |
|
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
1020 |
|
|
1021 |
|
return item; |
1022 |
|
} |
1023 |
|
|
1024 |
|
static GtkWidget *popup_menu_create(appdata_t *appdata, |
1025 |
|
GtkWidget *lat_entry, GtkWidget *lon_entry) { |
1026 |
|
GtkWidget *menu = gtk_menu_new(); |
1027 |
|
|
1028 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, 18), |
1029 |
|
_("GPS position"), cb_gps, 0, lon_entry, lat_entry); |
1030 |
|
|
1031 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, 21), |
1032 |
|
_("Home"), cb_gps, 1, lon_entry, lat_entry); |
1033 |
|
|
1034 |
|
location_t *location = appdata->location; |
1035 |
|
gint id = 2; |
1036 |
|
while(location) { |
1037 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, 21), |
1038 |
|
location->name, cb_gps, id++, lon_entry, lat_entry); |
1039 |
|
|
1040 |
|
location = location->next; |
1041 |
|
} |
1042 |
|
|
1043 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, 19), |
1044 |
|
_("Geomath projection"), cb_geomath, 0, lon_entry, lat_entry); |
1045 |
|
#ifdef ENABLE_OSM_GPS_MAP |
1046 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, 20), |
1047 |
|
_("Map position"), cb_map, 0, lon_entry, lat_entry); |
1048 |
|
#endif |
1049 |
|
|
1050 |
|
if(appdata->cur_cache) { |
1051 |
|
cache_t *cache = appdata->cur_cache; |
1052 |
|
|
1053 |
|
char *name = cache->name; |
1054 |
|
if(!name) name = cache->id; |
1055 |
|
|
1056 |
|
/* original cache position */ |
1057 |
|
if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) { |
1058 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6), |
1059 |
|
name, cb_cache, 0, lon_entry, lat_entry); |
1060 |
|
} |
1061 |
|
|
1062 |
|
/* overwritten cache position */ |
1063 |
|
if(cache->notes && |
1064 |
|
!isnan(cache->notes->pos.lat) && !isnan(cache->notes->pos.lon)) { |
1065 |
|
menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6), |
1066 |
|
_("Modified coordinate"), cb_cache, 1, lon_entry, lat_entry); |
1067 |
|
} |
1068 |
|
|
1069 |
|
wpt_t *wpt = cache->wpt; |
1070 |
|
gint id = 2; |
1071 |
|
while(wpt) { |
1072 |
|
GtkWidget *icon = NULL; |
1073 |
|
if(wpt->sym != WPT_SYM_UNKNOWN) |
1074 |
|
icon = icon_get_widget(ICON_POS, wpt->sym); |
1075 |
|
|
1076 |
|
char *name = wpt->desc; |
1077 |
|
if(!name) name = wpt->cmt; |
1078 |
|
if(!name) name = wpt->id; |
1079 |
|
|
1080 |
|
menu_add(menu, appdata, icon, name, cb_cache, id++, |
1081 |
|
lon_entry, lat_entry); |
1082 |
|
|
1083 |
|
wpt = wpt->next; |
1084 |
|
} |
1085 |
|
} |
1086 |
|
|
1087 |
|
gtk_widget_show_all(menu); |
1088 |
|
|
1089 |
|
return menu; |
1090 |
|
} |
1091 |
|
|
1092 |
|
static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event, |
1093 |
|
gpointer data) { |
1094 |
|
|
1095 |
|
if(event->type == GDK_BUTTON_PRESS) { |
1096 |
|
GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu"); |
1097 |
|
|
1098 |
|
/* draw a popup menu */ |
1099 |
|
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, |
1100 |
|
event->button, event->time); |
1101 |
|
return TRUE; |
1102 |
|
} |
1103 |
|
return FALSE; |
1104 |
|
} |
1105 |
|
|
1106 |
|
static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) { |
1107 |
|
GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu"); |
1108 |
|
gtk_widget_destroy(menu); |
1109 |
|
} |
1110 |
|
#endif |
1111 |
|
|
1112 |
|
#ifdef PRESET_PICKER_DIALOG |
1113 |
|
|
1114 |
|
enum { |
1115 |
|
PRESET_PICKER_COL_ICON = 0, |
1116 |
|
PRESET_PICKER_COL_NAME, |
1117 |
|
PRESET_PICKER_COL_ID, |
1118 |
|
PRESET_PICKER_COL_CB, |
1119 |
|
PRESET_PICKER_NUM_COLS |
1120 |
|
}; |
1121 |
|
|
1122 |
|
static void preset_picker_add(GtkListStore *store, appdata_t *appdata, |
1123 |
|
GdkPixbuf *icon, char *menu_str, |
1124 |
|
void(*func)(GtkWidget*, gpointer), gint id) { |
1125 |
|
GtkTreeIter iter; |
1126 |
|
|
1127 |
|
/* Append a row and fill in some data */ |
1128 |
|
gtk_list_store_append (store, &iter); |
1129 |
|
|
1130 |
|
gtk_list_store_set(store, &iter, |
1131 |
|
PRESET_PICKER_COL_ICON, icon, |
1132 |
|
PRESET_PICKER_COL_NAME, menu_str, |
1133 |
|
PRESET_PICKER_COL_ID, id, |
1134 |
|
PRESET_PICKER_COL_CB, func, |
1135 |
|
-1); |
1136 |
|
} |
1137 |
|
|
1138 |
|
static void on_preset_picker_activated(GtkTreeView *treeview, |
1139 |
|
GtkTreePath *path, |
1140 |
|
GtkTreeViewColumn *col, |
1141 |
|
gpointer userdata) { |
1142 |
|
GtkTreeIter iter; |
1143 |
|
GtkTreeModel *model = gtk_tree_view_get_model(treeview); |
1144 |
|
|
1145 |
|
if(gtk_tree_model_get_iter(model, &iter, path)) { |
1146 |
|
gint id; |
1147 |
|
void(*func)(GtkWidget*, gpointer); |
1148 |
|
gtk_tree_model_get(model, &iter, |
1149 |
|
PRESET_PICKER_COL_ID, &id, |
1150 |
|
PRESET_PICKER_COL_CB, &func, |
1151 |
|
-1); |
1152 |
|
|
1153 |
|
/* set id on widget as callbacks expect it this way */ |
1154 |
|
g_object_set_data(G_OBJECT(treeview), "id", (gpointer)id); |
1155 |
|
func(GTK_WIDGET(treeview), userdata); |
1156 |
|
|
1157 |
|
gtk_dialog_response(GTK_DIALOG(gtk_widget_get_toplevel( |
1158 |
|
GTK_WIDGET(treeview))), GTK_RESPONSE_ACCEPT); |
1159 |
|
|
1160 |
|
} |
1161 |
|
} |
1162 |
|
|
1163 |
|
static GtkWidget *preset_picker_create(appdata_t *appdata, |
1164 |
|
GtkWidget *lat_entry, GtkWidget *lon_entry) { |
1165 |
|
GtkCellRenderer *renderer; |
1166 |
|
GtkListStore *store; |
1167 |
|
|
1168 |
|
GtkWidget *view = gtk_tree_view_new(); |
1169 |
|
|
1170 |
|
g_object_set_data(G_OBJECT(view), "lat_entry", (gpointer)lat_entry); |
1171 |
|
g_object_set_data(G_OBJECT(view), "lon_entry", (gpointer)lon_entry); |
1172 |
|
|
1173 |
|
/* --- "Icon" column --- */ |
1174 |
|
renderer = gtk_cell_renderer_pixbuf_new(); |
1175 |
|
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), |
1176 |
|
-1, "Icon", renderer, "pixbuf", PRESET_PICKER_COL_ICON, NULL); |
1177 |
|
|
1178 |
|
/* --- "Name" column --- */ |
1179 |
|
renderer = gtk_cell_renderer_text_new(); |
1180 |
|
g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL ); |
1181 |
|
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes( |
1182 |
|
"Name", renderer, "text", PRESET_PICKER_COL_NAME, NULL); |
1183 |
|
gtk_tree_view_column_set_expand(column, TRUE); |
1184 |
|
gtk_tree_view_insert_column(GTK_TREE_VIEW(view), column, -1); |
1185 |
|
|
1186 |
|
store = gtk_list_store_new(PRESET_PICKER_NUM_COLS, |
1187 |
|
GDK_TYPE_PIXBUF, |
1188 |
|
G_TYPE_STRING, |
1189 |
|
G_TYPE_INT, |
1190 |
|
G_TYPE_POINTER); |
1191 |
|
|
1192 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, 18), |
1193 |
|
_("GPS position"), cb_gps, 0); |
1194 |
|
|
1195 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, 21), |
1196 |
|
_("Home"), cb_gps, 1); |
1197 |
|
|
1198 |
|
location_t *location = appdata->location; |
1199 |
|
gint id = 2; |
1200 |
|
while(location) { |
1201 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, 21), |
1202 |
|
location->name, cb_gps, id++); |
1203 |
|
|
1204 |
|
location = location->next; |
1205 |
|
} |
1206 |
|
|
1207 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, 19), |
1208 |
|
_("Geomath projection"), cb_geomath, 0); |
1209 |
|
#ifdef ENABLE_OSM_GPS_MAP |
1210 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, 20), |
1211 |
|
_("Map position"), cb_map, 0); |
1212 |
|
#endif |
1213 |
|
|
1214 |
|
if(appdata->cur_cache) { |
1215 |
|
cache_t *cache = appdata->cur_cache; |
1216 |
|
|
1217 |
|
char *name = cache->name; |
1218 |
|
if(!name) name = cache->id; |
1219 |
|
|
1220 |
|
/* original cache position */ |
1221 |
|
if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) { |
1222 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6), |
1223 |
|
name, cb_cache, 0); |
1224 |
|
} |
1225 |
|
|
1226 |
|
/* overwritten cache position */ |
1227 |
|
if(cache->notes && |
1228 |
|
!isnan(cache->notes->pos.lat) && !isnan(cache->notes->pos.lon)) { |
1229 |
|
preset_picker_add(store, appdata, icon_get(ICON_POS, cache->type + 6), |
1230 |
|
_("Modified coordinate"), cb_cache, 1); |
1231 |
|
} |
1232 |
|
|
1233 |
|
wpt_t *wpt = cache->wpt; |
1234 |
|
gint id = 2; |
1235 |
|
while(wpt) { |
1236 |
|
GdkPixbuf *icon = NULL; |
1237 |
|
if(wpt->sym != WPT_SYM_UNKNOWN) |
1238 |
|
icon = icon_get(ICON_POS, wpt->sym); |
1239 |
|
|
1240 |
|
char *name = wpt->desc; |
1241 |
|
if(!name) name = wpt->cmt; |
1242 |
|
if(!name) name = wpt->id; |
1243 |
|
|
1244 |
|
preset_picker_add(store, appdata, icon, name, cb_cache, id++); |
1245 |
|
wpt = wpt->next; |
1246 |
|
} |
1247 |
|
} |
1248 |
|
|
1249 |
|
|
1250 |
|
gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); |
1251 |
|
g_object_unref(store); |
1252 |
|
|
1253 |
|
/* make list react on clicks */ |
1254 |
|
g_signal_connect(view, "row-activated", |
1255 |
|
(GCallback)on_preset_picker_activated, appdata); |
1256 |
|
|
1257 |
|
/* put this inside a scrolled view */ |
1258 |
|
#ifndef USE_PANNABLE_AREA |
1259 |
|
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); |
1260 |
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
1261 |
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
1262 |
|
gtk_container_add(GTK_CONTAINER(scrolled_window), view); |
1263 |
|
return scrolled_window; |
1264 |
|
#else |
1265 |
|
GtkWidget *pannable_area = hildon_pannable_area_new(); |
1266 |
|
gtk_container_add(GTK_CONTAINER(pannable_area), view); |
1267 |
|
return pannable_area; |
1268 |
|
#endif |
1269 |
|
} |
1270 |
|
|
1271 |
|
static gint on_preset_picker_button_press(GtkWidget *button, |
1272 |
|
GdkEventButton *event, gpointer data) { |
1273 |
|
appdata_t *appdata = (appdata_t*)data; |
1274 |
|
|
1275 |
|
gpointer lat_entry = g_object_get_data(G_OBJECT(button), "lat_entry"); |
1276 |
|
gpointer lon_entry = g_object_get_data(G_OBJECT(button), "lon_entry"); |
1277 |
|
|
1278 |
|
if(event->type == GDK_BUTTON_PRESS) { |
1279 |
|
GtkWidget *dialog = |
1280 |
|
gtk_dialog_new_with_buttons(_("Preset coordinates"), |
1281 |
|
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), |
1282 |
|
GTK_DIALOG_MODAL, |
1283 |
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
1284 |
|
NULL); |
1285 |
|
|
1286 |
|
gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 200); |
1287 |
|
|
1288 |
|
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), |
1289 |
|
preset_picker_create(appdata, lat_entry, lon_entry)); |
1290 |
|
|
1291 |
|
gtk_widget_show_all(dialog); |
1292 |
|
gtk_dialog_run(GTK_DIALOG(dialog)); |
1293 |
|
gtk_widget_destroy(dialog); |
1294 |
|
|
1295 |
|
return TRUE; |
1296 |
|
} |
1297 |
|
return FALSE; |
1298 |
|
} |
1299 |
|
#endif |
1300 |
|
|
1301 |
|
void preset_coordinate_picker_update(appdata_t *appdata, GtkWidget *widget) { |
1302 |
|
#ifndef PRESET_PICKER_DIALOG |
1303 |
|
printf("updating popup menu\n"); |
1304 |
|
|
1305 |
|
GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu"); |
1306 |
|
g_assert(menu); |
1307 |
|
gtk_widget_destroy(menu); |
1308 |
|
|
1309 |
|
gpointer lat_entry = g_object_get_data(G_OBJECT(widget), "lat_entry"); |
1310 |
|
g_assert(lat_entry); |
1311 |
|
gpointer lon_entry = g_object_get_data(G_OBJECT(widget), "lon_entry"); |
1312 |
|
g_assert(lon_entry); |
1313 |
|
|
1314 |
|
menu = popup_menu_create(appdata, lat_entry, lon_entry); |
1315 |
|
g_object_set_data(G_OBJECT(widget), "menu", (gpointer)menu); |
1316 |
|
#endif |
1317 |
|
} |
1318 |
|
|
1319 |
|
GtkWidget *preset_coordinate_picker(appdata_t *appdata, |
1320 |
|
GtkWidget *lat_entry, GtkWidget *lon_entry) { |
1321 |
|
|
1322 |
|
GtkWidget *button = gtk_button_new(); |
1323 |
|
|
1324 |
|
gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17)); |
1325 |
|
|
1326 |
|
gtk_widget_set_tooltip_text(button, _("Preset coordinates")); |
1327 |
|
|
1328 |
|
g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry); |
1329 |
|
g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry); |
1330 |
|
|
1331 |
|
g_object_set_data(G_OBJECT(button), "lat_entry", (gpointer)lat_entry); |
1332 |
|
g_object_set_data(G_OBJECT(button), "lon_entry", (gpointer)lon_entry); |
1333 |
|
|
1334 |
|
#ifndef PRESET_PICKER_DIALOG |
1335 |
|
gtk_signal_connect(GTK_OBJECT(button), "button-press-event", |
1336 |
|
(GtkSignalFunc)on_popup_button_press, appdata); |
1337 |
|
|
1338 |
|
gtk_signal_connect(GTK_OBJECT(button), "destroy", |
1339 |
|
(GtkSignalFunc)on_popup_destroy, appdata); |
1340 |
|
|
1341 |
|
g_object_set_data(G_OBJECT(button), "menu", |
1342 |
|
popup_menu_create(appdata, lat_entry, lon_entry)); |
1343 |
|
#else |
1344 |
|
#ifdef FREMANTLE |
1345 |
|
hildon_gtk_widget_set_theme_size(button, |
1346 |
|
(HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); |
1347 |
|
#endif |
1348 |
|
|
1349 |
|
gtk_signal_connect(GTK_OBJECT(button), "button-press-event", |
1350 |
|
(GtkSignalFunc)on_preset_picker_button_press, appdata); |
1351 |
|
#endif |
1352 |
|
|
1353 |
|
return button; |
1354 |
|
} |
1355 |
|
|
1356 |
|
GtkWidget *entry_new(void) { |
1357 |
|
#if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5) |
1358 |
|
return gtk_entry_new(); |
1359 |
|
#else |
1360 |
|
return hildon_entry_new(HILDON_SIZE_AUTO); |
1361 |
|
#endif |
1362 |
|
} |
1363 |
|
|
1364 |
|
gboolean pos_differ(pos_t *pos1, pos_t *pos2) { |
1365 |
|
int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5; |
1366 |
|
int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5; |
1367 |
|
|
1368 |
|
return((lat1 != lat2) || (lon1 != lon2)); |
1369 |
|
} |
1370 |
|
|