56 |
str = g_strdup_printf("%s #%ld", item_str, id); |
str = g_strdup_printf("%s #%ld", item_str, id); |
57 |
|
|
58 |
/* add some tags ... */ |
/* add some tags ... */ |
59 |
|
/* |
60 |
|
* XXX Should we just try to present only the name or the ref (or the |
61 |
|
* alt_name, old_name, whatever) here? Hurling a load of tags in the |
62 |
|
* user's face in some unpredictable, uninformative order isn't very |
63 |
|
* friendly. |
64 |
|
* |
65 |
|
* Actually, a tag_short_desc() function would be useful in dialogs |
66 |
|
* nd user messages too. |
67 |
|
*/ |
68 |
while(tag) { |
while(tag) { |
69 |
if(!collision && info_tag_key_collision(tags, tag)) |
if(!collision && info_tag_key_collision(tags, tag)) |
70 |
collision = TRUE; |
collision = TRUE; |
155 |
|
|
156 |
float radius = map->style->highlight.width + map->style->node.radius; |
float radius = map->style->highlight.width + map->style->node.radius; |
157 |
if(!node->ways) radius += map->style->node.border_radius; |
if(!node->ways) radius += map->style->node.border_radius; |
158 |
if(node->icon_buf && map->style->icon.enable) { |
if(node->icon_buf && map->style->icon.enable && |
159 |
|
!appdata->settings->no_icons) { |
160 |
gint w = gdk_pixbuf_get_width(map_item->node->icon_buf); |
gint w = gdk_pixbuf_get_width(map_item->node->icon_buf); |
161 |
gint h = gdk_pixbuf_get_height(map_item->node->icon_buf); |
gint h = gdk_pixbuf_get_height(map_item->node->icon_buf); |
162 |
/* icons are technically square, so a radius slightly bigger */ |
/* icons are technically square, so a radius slightly bigger */ |
166 |
|
|
167 |
map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
168 |
x, y, radius, map->style->highlight.color); |
x, y, radius, map->style->highlight.color); |
169 |
|
|
170 |
if(!map_item->item) { |
if(!map_item->item) { |
171 |
/* and draw a fake node */ |
/* and draw a fake node */ |
172 |
new_map_item = g_new0(map_item_t, 1); |
new_map_item = g_new0(map_item_t, 1); |
218 |
diff.x = node_chain->node->lpos.x - last->lpos.x; |
diff.x = node_chain->node->lpos.x - last->lpos.x; |
219 |
diff.y = node_chain->node->lpos.y - last->lpos.y; |
diff.y = node_chain->node->lpos.y - last->lpos.y; |
220 |
|
|
221 |
|
/* only draw arrow if there's sufficient space */ |
222 |
|
/* TODO: what if there's not enough space anywhere? */ |
223 |
float len = sqrt(pow(diff.x, 2)+pow(diff.y, 2)); |
float len = sqrt(pow(diff.x, 2)+pow(diff.y, 2)); |
224 |
if(len > map->style->highlight.arrow_limit*arrow_width) { |
if(len > map->style->highlight.arrow_limit*arrow_width) { |
225 |
len /= arrow_width; |
len /= arrow_width; |
234 |
points->coords[2*2+0] = center.x - diff.y - diff.x; |
points->coords[2*2+0] = center.x - diff.y - diff.x; |
235 |
points->coords[2*2+1] = center.y + diff.x - diff.y; |
points->coords[2*2+1] = center.y + diff.x - diff.y; |
236 |
|
|
237 |
map_hl_polygon_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
map_hl_polygon_new(map, CANVAS_GROUP_WAYS_DIR, new_map_item, |
238 |
points, map->style->highlight.arrow_color); |
points, map->style->highlight.arrow_color); |
239 |
|
|
240 |
canvas_points_free(points); |
canvas_points_free(points); |
378 |
map_item->type = MAP_TYPE_NODE; |
map_item->type = MAP_TYPE_NODE; |
379 |
map_item->node = node; |
map_item->node = node; |
380 |
|
|
381 |
if(!node->icon_buf || !map->style->icon.enable) |
if(!node->icon_buf || !map->style->icon.enable || |
382 |
map_item->item = canvas_circle_new(map, CANVAS_GROUP_NODES, |
map->appdata->settings->no_icons) |
383 |
|
map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES, |
384 |
node->lpos.x, node->lpos.y, radius, width, fill, border); |
node->lpos.x, node->lpos.y, radius, width, fill, border); |
385 |
else |
else |
386 |
map_item->item = canvas_image_new(map, CANVAS_GROUP_NODES, |
map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES, |
387 |
node->icon_buf, |
node->icon_buf, |
388 |
node->lpos.x - map->style->icon.scale/2 * |
node->lpos.x - map->style->icon.scale/2 * |
389 |
gdk_pixbuf_get_width(node->icon_buf), |
gdk_pixbuf_get_width(node->icon_buf), |
415 |
map_item_t *map_item = g_new0(map_item_t, 1); |
map_item_t *map_item = g_new0(map_item_t, 1); |
416 |
map_item->type = MAP_TYPE_WAY; |
map_item->type = MAP_TYPE_WAY; |
417 |
map_item->way = way; |
map_item->way = way; |
418 |
map_item->item = canvas_circle_new(map, CANVAS_GROUP_WAYS, |
map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_WAYS, |
419 |
way->node_chain->node->lpos.x, way->node_chain->node->lpos.y, |
way->node_chain->node->lpos.x, way->node_chain->node->lpos.y, |
420 |
radius, width, fill, border); |
radius, width, fill, border); |
421 |
|
|
443 |
map_item->way = way; |
map_item->way = way; |
444 |
|
|
445 |
if(way->draw.flags & OSM_DRAW_FLAG_AREA) { |
if(way->draw.flags & OSM_DRAW_FLAG_AREA) { |
446 |
if(map->style->area.opaque) |
if(map->style->area.color & 0xff) |
447 |
map_item->item = canvas_polygon_new(map, group, points, |
map_item->item = canvas_polygon_new(map->canvas, group, points, |
448 |
width, color, fill_color); |
width, color, fill_color); |
449 |
else |
else |
450 |
map_item->item = canvas_polyline_new(map, group, points, |
map_item->item = canvas_polyline_new(map->canvas, group, points, |
451 |
width, color); |
width, color); |
452 |
} else { |
} else { |
453 |
map_item->item = canvas_polyline_new(map, group, points, width, color); |
map_item->item = canvas_polyline_new(map->canvas, group, points, width, color); |
454 |
} |
} |
455 |
|
|
456 |
canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max); |
canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max); |
457 |
|
|
458 |
if (group != CANVAS_GROUP_WAYS_OL) |
if (group != CANVAS_GROUP_WAYS_OL) |
459 |
if (way->draw.dashed) |
if (way->draw.dashed) |
460 |
canvas_item_set_dashed(map_item->item); |
canvas_item_set_dashed(map_item->item, width, way->draw.dash_length); |
461 |
|
|
462 |
/* attach map_item to ways map_item_chain */ |
/* attach map_item to ways map_item_chain */ |
463 |
map_item_chain_t **chain = &way->map_item_chain; |
map_item_chain_t **chain = &way->map_item_chain; |
475 |
|
|
476 |
void map_show_node(map_t *map, node_t *node) { |
void map_show_node(map_t *map, node_t *node) { |
477 |
map_node_new(map, node, map->style->node.radius, 0, |
map_node_new(map, node, map->style->node.radius, 0, |
478 |
RGB2CANVAS(map->style->node.color), 0); |
map->style->node.color, 0); |
479 |
} |
} |
480 |
|
|
481 |
void map_way_draw(map_t *map, way_t *way) { |
void map_way_draw(map_t *map, way_t *way) { |
490 |
if(nodes == 1) { |
if(nodes == 1) { |
491 |
/* draw a single dot where this single node is */ |
/* draw a single dot where this single node is */ |
492 |
map_way_single_new(map, way, map->style->node.radius, 0, |
map_way_single_new(map, way, map->style->node.radius, 0, |
493 |
RGB2CANVAS(map->style->node.color), 0); |
map->style->node.color, 0); |
494 |
} else { |
} else { |
495 |
canvas_points_t *points = canvas_points_new(nodes); |
canvas_points_t *points = canvas_points_new(nodes); |
496 |
|
|
526 |
map_node_new(map, node, |
map_node_new(map, node, |
527 |
map->style->node.radius, |
map->style->node.radius, |
528 |
map->style->node.border_radius, |
map->style->node.border_radius, |
529 |
RGBA2CANVAS(map->style->node.fill_color, |
map->style->node.fill_color, |
530 |
map->style->node.has_fill_color?0xff:0x00), |
map->style->node.color); |
|
RGB2CANVAS(map->style->node.color)); |
|
531 |
|
|
532 |
else if(map->style->node.show_untagged || osm_node_has_tag(node)) |
else if(map->style->node.show_untagged || osm_node_has_tag(node)) |
533 |
map_node_new(map, node, |
map_node_new(map, node, |
534 |
map->style->node.radius, 0, |
map->style->node.radius, 0, |
535 |
RGB2CANVAS(map->style->node.color), 0); |
map->style->node.color, 0); |
536 |
} |
} |
537 |
|
|
538 |
static void map_item_draw(map_t *map, map_item_t *map_item) { |
static void map_item_draw(map_t *map, map_item_t *map_item) { |
614 |
canvas_points_t *points = canvas_points_new(5); |
canvas_points_t *points = canvas_points_new(5); |
615 |
|
|
616 |
/* don't draw frisket at all if it's completely transparent */ |
/* don't draw frisket at all if it's completely transparent */ |
617 |
if(map->style->frisket.opaque) { |
if(map->style->frisket.color & 0xff) { |
618 |
elemstyle_color_t color = |
elemstyle_color_t color = map->style->frisket.color; |
|
(map->style->background.color<<8) | map->style->frisket.opaque; |
|
619 |
|
|
620 |
float mult = map->style->frisket.mult; |
float mult = map->style->frisket.mult; |
621 |
|
|
622 |
/* top rectangle */ |
/* top rectangle */ |
623 |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
624 |
mult*bounds->min.y, bounds->min.y); |
mult*bounds->min.y, bounds->min.y); |
625 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
626 |
|
1, NO_COLOR, color); |
627 |
|
|
628 |
/* bottom rectangle */ |
/* bottom rectangle */ |
629 |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
630 |
bounds->max.y, mult*bounds->max.y); |
bounds->max.y, mult*bounds->max.y); |
631 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
632 |
|
1, NO_COLOR, color); |
633 |
|
|
634 |
/* left rectangle */ |
/* left rectangle */ |
635 |
map_frisket_rectangle(points, mult*bounds->min.x, bounds->min.x, |
map_frisket_rectangle(points, mult*bounds->min.x, bounds->min.x, |
636 |
mult*bounds->min.y, mult*bounds->max.y); |
mult*bounds->min.y, mult*bounds->max.y); |
637 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
638 |
|
1, NO_COLOR, color); |
639 |
|
|
640 |
/* right rectangle */ |
/* right rectangle */ |
641 |
map_frisket_rectangle(points, bounds->max.x, mult*bounds->max.x, |
map_frisket_rectangle(points, bounds->max.x, mult*bounds->max.x, |
642 |
mult*bounds->min.y, mult*bounds->max.y); |
mult*bounds->min.y, mult*bounds->max.y); |
643 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
644 |
|
1, NO_COLOR, color); |
645 |
|
|
646 |
} |
} |
647 |
|
|
652 |
bounds->min.x-ew2, bounds->max.x+ew2, |
bounds->min.x-ew2, bounds->max.x+ew2, |
653 |
bounds->min.y-ew2, bounds->max.y+ew2); |
bounds->min.y-ew2, bounds->max.y+ew2); |
654 |
|
|
655 |
canvas_polyline_new(map, CANVAS_GROUP_NODES, points, |
canvas_polyline_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
656 |
map->style->frisket.border.width, |
map->style->frisket.border.width, |
657 |
map->style->frisket.border.color); |
map->style->frisket.border.color); |
658 |
|
|
784 |
return NULL; |
return NULL; |
785 |
} |
} |
786 |
|
|
787 |
if(map_item->highlight) |
if(map_item->highlight) |
788 |
printf(" item is highlight\n"); |
printf(" item is highlight\n"); |
789 |
|
|
790 |
switch(map_item->type) { |
switch(map_item->type) { |
803 |
} |
} |
804 |
|
|
805 |
/* get the real item (no highlight) at x, y */ |
/* get the real item (no highlight) at x, y */ |
806 |
static map_item_t *map_real_item_at(map_t *map, gint x, gint y) { |
map_item_t *map_real_item_at(map_t *map, gint x, gint y) { |
807 |
map_item_t *map_item = map_item_at(map, x, y); |
map_item_t *map_item = map_item_at(map, x, y); |
808 |
|
|
809 |
/* no item or already a real one */ |
/* no item or already a real one */ |
843 |
return map_item; |
return map_item; |
844 |
} |
} |
845 |
|
|
|
|
|
|
|
|
|
#ifdef USE_GOOCANVAS |
|
|
|
|
846 |
/* Limitations on the amount by which we can scroll. Keeps part of the |
/* Limitations on the amount by which we can scroll. Keeps part of the |
847 |
* map visible at all times */ |
* map visible at all times */ |
848 |
static void map_limit_scroll(map_t *map, gint *sx, gint *sy) { |
static void map_limit_scroll(map_t *map, canvas_unit_t unit, |
849 |
gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas)); |
gint *sx, gint *sy) { |
850 |
|
|
851 |
gint sx_cu = *sx / zoom; |
/* get scale factor for pixel->meter conversion. set to 1 if */ |
852 |
gint sy_cu = *sy / zoom; |
/* given coordinates are already in meters */ |
853 |
|
gdouble scale = (unit == CANVAS_UNIT_METER)?1.0:canvas_get_zoom(map->canvas); |
854 |
// Canvas viewport dimensions |
|
855 |
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
/* convert pixels to meters if necessary */ |
856 |
gint aw_cu = a->width / zoom; |
gdouble sx_cu = *sx / scale; |
857 |
gint ah_cu = a->height / zoom; |
gdouble sy_cu = *sy / scale; |
858 |
|
|
859 |
// Data rect minimum and maximum |
/* get size of visible area in canvas units (meters) */ |
860 |
gint min_x, min_y, max_x, max_y; |
gint aw_cu = canvas_get_viewport_width(map->canvas, CANVAS_UNIT_METER); |
861 |
min_x = map->appdata->osm->bounds->min.x; |
gint ah_cu = canvas_get_viewport_height(map->canvas, CANVAS_UNIT_METER); |
862 |
min_y = map->appdata->osm->bounds->min.y; |
|
863 |
max_x = map->appdata->osm->bounds->max.x; |
// Data rect minimum and maximum |
864 |
max_y = map->appdata->osm->bounds->max.y; |
gint min_x, min_y, max_x, max_y; |
865 |
|
min_x = map->appdata->osm->bounds->min.x; |
866 |
// limit stops - prevent scrolling beyond these |
min_y = map->appdata->osm->bounds->min.y; |
867 |
gint min_sy_cu = 0.95*(min_y - ah_cu); |
max_x = map->appdata->osm->bounds->max.x; |
868 |
gint min_sx_cu = 0.95*(min_x - aw_cu); |
max_y = map->appdata->osm->bounds->max.y; |
869 |
gint max_sy_cu = 0.95*(max_y); |
|
870 |
gint max_sx_cu = 0.95*(max_x); |
// limit stops - prevent scrolling beyond these |
871 |
if (sy_cu < min_sy_cu) { *sy = min_sy_cu*zoom; } |
gint min_sy_cu = 0.95*(min_y - ah_cu); |
872 |
if (sx_cu < min_sx_cu) { *sx = min_sx_cu*zoom; } |
gint min_sx_cu = 0.95*(min_x - aw_cu); |
873 |
if (sy_cu > max_sy_cu) { *sy = max_sy_cu*zoom; } |
gint max_sy_cu = 0.95*(max_y); |
874 |
if (sx_cu > max_sx_cu) { *sx = max_sx_cu*zoom; } |
gint max_sx_cu = 0.95*(max_x); |
875 |
|
if (sy_cu < min_sy_cu) { *sy = min_sy_cu * scale; } |
876 |
|
if (sx_cu < min_sx_cu) { *sx = min_sx_cu * scale; } |
877 |
|
if (sy_cu > max_sy_cu) { *sy = max_sy_cu * scale; } |
878 |
|
if (sx_cu > max_sx_cu) { *sx = max_sx_cu * scale; } |
879 |
} |
} |
880 |
|
|
881 |
|
|
889 |
max_x = map->appdata->osm->bounds->max.x; |
max_x = map->appdata->osm->bounds->max.x; |
890 |
max_y = map->appdata->osm->bounds->max.y; |
max_y = map->appdata->osm->bounds->max.y; |
891 |
|
|
892 |
// Canvas viewport dimensions |
/* get size of visible area in pixels and convert to meters of intended */ |
893 |
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
/* zoom by deviding by zoom (which is basically pix/m) */ |
894 |
gint ah_cu = a->height / *zoom; |
gint aw_cu = |
895 |
gint aw_cu = a->width / *zoom; |
canvas_get_viewport_width(map->canvas, CANVAS_UNIT_PIXEL) / *zoom; |
896 |
|
gint ah_cu = |
897 |
|
canvas_get_viewport_height(map->canvas, CANVAS_UNIT_PIXEL) / *zoom; |
898 |
|
|
899 |
gdouble oldzoom = *zoom; |
gdouble oldzoom = *zoom; |
900 |
if (ah_cu < aw_cu) { |
if (ah_cu < aw_cu) { |
919 |
} |
} |
920 |
|
|
921 |
|
|
|
#if 0 |
|
|
/* Scroll the map a little towards the centre from where it is right now. |
|
|
* This is used as a cute recentring trick when the map is at its outer |
|
|
* scroll limit. */ |
|
|
static void map_scroll_towards_centre(map_t *map, gdouble amt) { |
|
|
gint sx, sy, sx_orig, sy_orig; |
|
|
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
|
|
gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas)); |
|
|
sx_orig=sx; |
|
|
sy_orig=sy; |
|
|
|
|
|
// Work in canvas units |
|
|
gdouble sx_cu = sx / zoom; |
|
|
gdouble sy_cu = sy / zoom; |
|
|
|
|
|
// Map bounds |
|
|
gdouble bmin_x_cu, bmin_y_cu, bmax_x_cu, bmax_y_cu; |
|
|
bmin_x_cu = map->appdata->osm->bounds->min.x; |
|
|
bmin_y_cu = map->appdata->osm->bounds->min.y; |
|
|
bmax_x_cu = map->appdata->osm->bounds->max.x; |
|
|
bmax_y_cu = map->appdata->osm->bounds->max.y; |
|
|
|
|
|
// Canvas viewport dimensions |
|
|
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
|
|
gdouble ah_cu = a->height / zoom; |
|
|
gdouble aw_cu = a->width / zoom; |
|
|
|
|
|
// Scroll offsets that would recentre the map |
|
|
gdouble centre_sx_cu, centre_sy_cu; |
|
|
centre_sx_cu = - (aw_cu/2); |
|
|
centre_sy_cu = - (ah_cu/2); |
|
|
|
|
|
// Move towards centre by a given fraction of the whole map |
|
|
if (sx_cu > centre_sx_cu) { |
|
|
sx_cu -= ((bmax_x_cu - bmin_x_cu) * amt); |
|
|
if (sx_cu < centre_sx_cu) { |
|
|
printf("force-centre-x\n"); |
|
|
sx_cu = centre_sx_cu; |
|
|
} |
|
|
} |
|
|
if (sx_cu < centre_sx_cu) { |
|
|
sx_cu += ((bmax_x_cu - bmin_x_cu) * amt); |
|
|
if (sx_cu > centre_sx_cu) { |
|
|
printf("force-centre-x\n"); |
|
|
sx_cu = centre_sx_cu; |
|
|
} |
|
|
} |
|
|
|
|
|
if (sy_cu > centre_sy_cu) { |
|
|
sy_cu -= ((bmax_y_cu - bmin_y_cu) * amt); |
|
|
if (sy_cu < centre_sy_cu) { |
|
|
printf("force-centre-y\n"); |
|
|
sy_cu = centre_sy_cu; |
|
|
} |
|
|
} |
|
|
if (sy_cu < centre_sy_cu) { |
|
|
sy_cu += ((bmax_y_cu - bmin_y_cu) * amt); |
|
|
if (sy_cu > centre_sy_cu) { |
|
|
printf("force-centre-y\n"); |
|
|
sy_cu = centre_sy_cu; |
|
|
} |
|
|
} |
|
|
|
|
|
// Back to pixels for setting the scroll |
|
|
sx = (gint)(sx_cu * zoom); |
|
|
sy = (gint)(sy_cu * zoom); |
|
|
canvas_scroll_to(map->canvas, sx, sy); |
|
|
map->state->scroll_offset.x = sx; |
|
|
map->state->scroll_offset.y = sy; |
|
|
} |
|
|
#endif // #if 0 |
|
|
|
|
922 |
/* |
/* |
923 |
* Scroll the map to a point if that point is currently offscreen. |
* Scroll the map to a point if that point is currently offscreen. |
924 |
*/ |
*/ |
935 |
max_y = map->appdata->osm->bounds->max.y; |
max_y = map->appdata->osm->bounds->max.y; |
936 |
if ( (lpos->x > max_x) || (lpos->x < min_x) |
if ( (lpos->x > max_x) || (lpos->x < min_x) |
937 |
|| (lpos->y > max_y) || (lpos->y < min_y)) { |
|| (lpos->y > max_y) || (lpos->y < min_y)) { |
938 |
printf("cannot scroll to (%d, %d): outside the working area\n"); |
printf("cannot scroll to (%d, %d): outside the working area\n", |
939 |
|
lpos->x, lpos->y); |
940 |
return; |
return; |
941 |
} |
} |
942 |
|
|
943 |
// Viewport dimensions in canvas space |
// Viewport dimensions in canvas space |
944 |
gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas)); |
|
945 |
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
/* get size of visible area in canvas units (meters) */ |
946 |
gdouble aw = a->width / zoom; |
gdouble pix_per_meter = canvas_get_zoom(map->canvas); |
947 |
gdouble ah = a->height / zoom; |
gdouble aw = canvas_get_viewport_width(map->canvas, CANVAS_UNIT_METER); |
948 |
|
gdouble ah = canvas_get_viewport_height(map->canvas, CANVAS_UNIT_METER); |
949 |
|
|
950 |
// Is the point still onscreen? |
// Is the point still onscreen? |
951 |
gboolean vert_recentre_needed = FALSE; |
gboolean vert_recentre_needed = FALSE; |
952 |
gboolean horiz_recentre_needed = FALSE; |
gboolean horiz_recentre_needed = FALSE; |
953 |
gint sx, sy; |
gint sx, sy; |
954 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
955 |
gint viewport_left = (sx/zoom); |
gint viewport_left = (sx/pix_per_meter); |
956 |
gint viewport_right = (sx/zoom)+aw; |
gint viewport_right = (sx/pix_per_meter)+aw; |
957 |
gint viewport_top = (sy/zoom); |
gint viewport_top = (sy/pix_per_meter); |
958 |
gint viewport_bottom = (sy/zoom)+ah; |
gint viewport_bottom = (sy/pix_per_meter)+ah; |
959 |
if (lpos->x > viewport_right) { |
if (lpos->x > viewport_right) { |
960 |
printf("** off right edge (%d > %d)\n", lpos->x, viewport_right); |
printf("** off right edge (%d > %d)\n", lpos->x, viewport_right); |
961 |
horiz_recentre_needed = TRUE; |
horiz_recentre_needed = TRUE; |
975 |
|
|
976 |
if (horiz_recentre_needed || vert_recentre_needed) { |
if (horiz_recentre_needed || vert_recentre_needed) { |
977 |
gint new_sx, new_sy; |
gint new_sx, new_sy; |
978 |
#if 0 |
|
|
// Only recentre the drifting axis. |
|
|
new_sx = horiz_recentre_needed ? zoom*(lpos->x - (aw/2)) : sx; |
|
|
new_sy = vert_recentre_needed ? zoom*(lpos->y - (ah/2)) : sy; |
|
|
// Not sure about this. I don't think it really buys us anything. |
|
|
#else |
|
979 |
// Just centre both at once |
// Just centre both at once |
980 |
new_sx = zoom * (lpos->x - (aw/2)); |
new_sx = pix_per_meter * (lpos->x - (aw/2)); |
981 |
new_sy = zoom * (lpos->y - (ah/2)); |
new_sy = pix_per_meter * (lpos->y - (ah/2)); |
982 |
#endif |
|
983 |
map_limit_scroll(map, &new_sx, &new_sy); |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &new_sx, &new_sy); |
984 |
canvas_scroll_to(map->canvas, new_sx, new_sy); |
canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, new_sx, new_sy); |
985 |
} |
} |
986 |
} |
} |
987 |
|
|
|
#endif // #ifdef USE_GOOCANVAS |
|
|
|
|
988 |
/* Deselects the current way or node if its zoom_max |
/* Deselects the current way or node if its zoom_max |
989 |
* means that it's not going to render at the current map zoom. */ |
* means that it's not going to render at the current map zoom. */ |
990 |
void map_deselect_if_zoom_below_zoom_max(map_t *map) { |
void map_deselect_if_zoom_below_zoom_max(map_t *map) { |
1009 |
void map_set_zoom(map_t *map, double zoom, |
void map_set_zoom(map_t *map, double zoom, |
1010 |
gboolean update_scroll_offsets) { |
gboolean update_scroll_offsets) { |
1011 |
gboolean at_zoom_limit = 0; |
gboolean at_zoom_limit = 0; |
|
#ifdef USE_GOOCANVAS |
|
1012 |
at_zoom_limit = map_limit_zoom(map, &zoom); |
at_zoom_limit = map_limit_zoom(map, &zoom); |
1013 |
#endif |
|
1014 |
map->state->zoom = zoom; |
map->state->zoom = zoom; |
1015 |
canvas_set_zoom(map->canvas, map->state->zoom); |
canvas_set_zoom(map->canvas, map->state->zoom); |
1016 |
|
|
1017 |
map_deselect_if_zoom_below_zoom_max(map); |
map_deselect_if_zoom_below_zoom_max(map); |
1018 |
|
|
1019 |
if (update_scroll_offsets) { |
if(update_scroll_offsets) { |
1020 |
if (!at_zoom_limit) { |
if (!at_zoom_limit) { |
1021 |
/* zooming affects the scroll offsets */ |
/* zooming affects the scroll offsets */ |
1022 |
gint sx, sy; |
gint sx, sy; |
1023 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1024 |
#ifdef USE_GOOCANVAS |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy); |
1025 |
map_limit_scroll(map, &sx, &sy); |
|
1026 |
canvas_scroll_to(map->canvas, sx, sy); // keep the map visible |
// keep the map visible |
1027 |
#endif |
canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy); |
|
map->state->scroll_offset.x = sx; |
|
|
map->state->scroll_offset.y = sy; |
|
|
} |
|
|
#ifdef USE_GOOCANVAS |
|
|
else { |
|
|
// map_scroll_towards_centre(map, 0.20); |
|
1028 |
} |
} |
1029 |
#endif |
|
1030 |
|
canvas_scroll_get(map->canvas, CANVAS_UNIT_METER, |
1031 |
|
&map->state->scroll_offset.x, |
1032 |
|
&map->state->scroll_offset.y); |
1033 |
} |
} |
1034 |
} |
} |
1035 |
|
|
1054 |
static gboolean distance_above(map_t *map, gint x, gint y, gint limit) { |
static gboolean distance_above(map_t *map, gint x, gint y, gint limit) { |
1055 |
gint sx, sy; |
gint sx, sy; |
1056 |
|
|
|
#ifdef USE_GNOMECANVAS |
|
|
gnome_canvas_get_scroll_offsets(GNOME_CANVAS(map->canvas), &sx, &sy); |
|
|
|
|
|
/* add offsets generated by mouse within map and map scrolling */ |
|
|
sx = (x-map->pen_down.at.x) + (map->pen_down.so.x-sx); |
|
|
sy = (y-map->pen_down.at.y) + (map->pen_down.so.y-sy); |
|
|
#else |
|
1057 |
/* add offsets generated by mouse within map and map scrolling */ |
/* add offsets generated by mouse within map and map scrolling */ |
1058 |
sx = (x-map->pen_down.at.x); |
sx = (x-map->pen_down.at.x); |
1059 |
sy = (y-map->pen_down.at.y); |
sy = (y-map->pen_down.at.y); |
|
#endif |
|
1060 |
|
|
1061 |
return(sx*sx + sy*sy > limit*limit); |
return(sx*sx + sy*sy > limit*limit); |
1062 |
} |
} |
1065 |
static void map_do_scroll(map_t *map, gint x, gint y) { |
static void map_do_scroll(map_t *map, gint x, gint y) { |
1066 |
gint sx, sy; |
gint sx, sy; |
1067 |
|
|
1068 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1069 |
sx -= x-map->pen_down.at.x; |
sx -= x-map->pen_down.at.x; |
1070 |
sy -= y-map->pen_down.at.y; |
sy -= y-map->pen_down.at.y; |
1071 |
#ifdef USE_GOOCANVAS |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy); |
1072 |
map_limit_scroll(map, &sx, &sy); |
canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy); |
1073 |
#endif |
|
1074 |
canvas_scroll_to(map->canvas, sx, sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_METER, |
1075 |
map->state->scroll_offset.x = sx; |
&map->state->scroll_offset.x, |
1076 |
map->state->scroll_offset.y = sy; |
&map->state->scroll_offset.y); |
1077 |
} |
} |
1078 |
|
|
1079 |
|
|
1080 |
/* scroll a certain step */ |
/* scroll a certain step */ |
1081 |
static void map_do_scroll_step(map_t *map, gint x, gint y) { |
static void map_do_scroll_step(map_t *map, gint x, gint y) { |
1082 |
gint sx, sy; |
gint sx, sy; |
1083 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1084 |
sx += x; |
sx += x; |
1085 |
sy += y; |
sy += y; |
1086 |
#ifdef USE_GOOCANVAS |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy); |
1087 |
map_limit_scroll(map, &sx, &sy); |
canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy); |
|
#endif |
|
|
canvas_scroll_to(map->canvas, sx, sy); |
|
|
map->state->scroll_offset.x = sx; |
|
|
map->state->scroll_offset.y = sy; |
|
|
} |
|
1088 |
|
|
1089 |
|
canvas_scroll_get(map->canvas, CANVAS_UNIT_METER, |
1090 |
|
&map->state->scroll_offset.x, |
1091 |
|
&map->state->scroll_offset.y); |
1092 |
|
} |
1093 |
|
|
1094 |
gboolean map_item_is_selected_node(map_t *map, map_item_t *map_item) { |
gboolean map_item_is_selected_node(map_t *map, map_item_t *map_item) { |
1095 |
printf("check if item is a selected node\n"); |
printf("check if item is a selected node\n"); |
1308 |
map->pen_down.at.y = y; |
map->pen_down.at.y = y; |
1309 |
map->pen_down.drag = FALSE; // don't assume drag yet |
map->pen_down.drag = FALSE; // don't assume drag yet |
1310 |
|
|
|
#ifdef USE_GNOMECANVAS |
|
|
/* save initial scroll offset */ |
|
|
gnome_canvas_get_scroll_offsets(GNOME_CANVAS(map->canvas), |
|
|
&map->pen_down.so.x, &map->pen_down.so.y); |
|
|
#endif |
|
|
|
|
1311 |
/* determine wether this press was on an item */ |
/* determine wether this press was on an item */ |
1312 |
map->pen_down.on_item = map_real_item_at(map, x, y); |
map->pen_down.on_item = map_real_item_at(map, x, y); |
1313 |
|
|
1500 |
/* reduce update frequency on hildon to keep screen update fluid */ |
/* reduce update frequency on hildon to keep screen update fluid */ |
1501 |
static guint32 last_time = 0; |
static guint32 last_time = 0; |
1502 |
|
|
1503 |
if(event->time - last_time < 100) return FALSE; |
if(event->time - last_time < 250) return FALSE; |
1504 |
last_time = event->time; |
last_time = event->time; |
1505 |
#endif |
#endif |
1506 |
|
|
1507 |
if(!map->pen_down.is) |
if(!map->pen_down.is) |
1508 |
return FALSE; |
return FALSE; |
1509 |
|
|
1510 |
#ifdef USE_GNOMECANVAS |
#ifndef USE_GOOCANVAS |
1511 |
/* handle hints, hints are handled by goocanvas directly */ |
/* handle hints, hints are handled by goocanvas directly */ |
1512 |
if(event->is_hint) |
if(event->is_hint) |
1513 |
gdk_window_get_pointer(event->window, &x, &y, &state); |
gdk_window_get_pointer(event->window, &x, &y, &state); |
1544 |
case MAP_ACTION_NODE_ADD: |
case MAP_ACTION_NODE_ADD: |
1545 |
map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius); |
map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius); |
1546 |
break; |
break; |
1547 |
|
|
1548 |
case MAP_ACTION_WAY_ADD: |
case MAP_ACTION_WAY_ADD: |
1549 |
map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius); |
map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius); |
1550 |
map_touchnode_update(appdata, x, y); |
map_touchnode_update(appdata, x, y); |
1649 |
map_t *map = appdata->map = g_new0(map_t, 1); |
map_t *map = appdata->map = g_new0(map_t, 1); |
1650 |
|
|
1651 |
map->style = style_load(appdata, appdata->settings->style); |
map->style = style_load(appdata, appdata->settings->style); |
1652 |
|
if(!map->style) { |
1653 |
|
errorf(NULL, _("Unable to load valid style, terminating.")); |
1654 |
|
g_free(map); |
1655 |
|
return NULL; |
1656 |
|
} |
1657 |
|
|
1658 |
if(appdata->project && appdata->project->map_state) { |
if(appdata->project && appdata->project->map_state) { |
1659 |
printf("Using projects map state\n"); |
printf("Using projects map state\n"); |
1671 |
map->appdata = appdata; |
map->appdata = appdata; |
1672 |
map->action.type = MAP_ACTION_IDLE; |
map->action.type = MAP_ACTION_IDLE; |
1673 |
|
|
1674 |
#ifdef USE_GNOMECANVAS |
map->canvas = canvas_new(map->style->background.color); |
1675 |
map->canvas = gnome_canvas_new_aa(); // _aa |
canvas_set_antialias(map->canvas, !appdata->settings->no_antialias); |
|
|
|
|
/* create the groups */ |
|
|
canvas_group_t group; |
|
|
for(group = 0; group < CANVAS_GROUPS; group++) |
|
|
map->group[group] = gnome_canvas_item_new( |
|
|
gnome_canvas_root(GNOME_CANVAS(map->canvas)), |
|
|
GNOME_TYPE_CANVAS_GROUP, |
|
|
NULL); |
|
|
|
|
|
gtk_widget_modify_bg(map->canvas, GTK_STATE_NORMAL, |
|
|
&map->canvas->style->white); |
|
|
|
|
|
#else |
|
|
map->canvas = goo_canvas_new(); |
|
|
|
|
|
g_object_set(G_OBJECT(map->canvas), "anchor", GTK_ANCHOR_CENTER, NULL); |
|
|
g_object_set(G_OBJECT(map->canvas), "background-color-rgb", |
|
|
map->style->background.color, NULL); |
|
|
|
|
|
GooCanvasItem *root = goo_canvas_get_root_item(GOO_CANVAS(map->canvas)); |
|
|
|
|
|
/* create the groups */ |
|
|
canvas_group_t group; |
|
|
for(group = 0; group < CANVAS_GROUPS; group++) |
|
|
map->group[group] = goo_canvas_group_new(root, NULL); |
|
1676 |
|
|
1677 |
#endif |
GtkWidget *canvas_widget = canvas_get_widget(map->canvas); |
1678 |
|
|
1679 |
gtk_widget_set_events(map->canvas, |
gtk_widget_set_events(canvas_widget, |
1680 |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_PRESS_MASK |
1681 |
| GDK_BUTTON_RELEASE_MASK |
| GDK_BUTTON_RELEASE_MASK |
1682 |
| GDK_SCROLL_MASK |
| GDK_SCROLL_MASK |
1683 |
| GDK_POINTER_MOTION_MASK |
| GDK_POINTER_MOTION_MASK |
1684 |
| GDK_POINTER_MOTION_HINT_MASK); |
| GDK_POINTER_MOTION_HINT_MASK); |
1685 |
|
|
1686 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1687 |
"button_press_event", G_CALLBACK(map_button_event), appdata); |
"button_press_event", G_CALLBACK(map_button_event), appdata); |
1688 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1689 |
"button_release_event", G_CALLBACK(map_button_event), appdata); |
"button_release_event", G_CALLBACK(map_button_event), appdata); |
1690 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1691 |
"motion_notify_event", G_CALLBACK(map_motion_notify_event), appdata); |
"motion_notify_event", G_CALLBACK(map_motion_notify_event), appdata); |
1692 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1693 |
"scroll_event", G_CALLBACK(map_scroll_event), appdata); |
"scroll_event", G_CALLBACK(map_scroll_event), appdata); |
1694 |
|
|
1695 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1696 |
"destroy", G_CALLBACK(map_destroy_event), appdata); |
"destroy", G_CALLBACK(map_destroy_event), appdata); |
1697 |
|
|
1698 |
return map->canvas; |
return canvas_widget; |
1699 |
} |
} |
1700 |
|
|
1701 |
void map_init(appdata_t *appdata) { |
void map_init(appdata_t *appdata) { |
1714 |
mult*appdata->osm->bounds->max.x, |
mult*appdata->osm->bounds->max.x, |
1715 |
mult*appdata->osm->bounds->max.y); |
mult*appdata->osm->bounds->max.y); |
1716 |
|
|
1717 |
printf("restore scroll offsets %d/%d\n", |
printf("restore scroll position %d/%d\n", |
1718 |
map->state->scroll_offset.x, map->state->scroll_offset.y); |
map->state->scroll_offset.x, map->state->scroll_offset.y); |
1719 |
|
|
1720 |
canvas_scroll_to(map->canvas, |
map_limit_scroll(map, CANVAS_UNIT_METER, |
1721 |
map->state->scroll_offset.x, map->state->scroll_offset.y); |
&map->state->scroll_offset.x, &map->state->scroll_offset.y); |
1722 |
|
canvas_scroll_to(map->canvas, CANVAS_UNIT_METER, |
1723 |
|
map->state->scroll_offset.x, map->state->scroll_offset.y); |
1724 |
} |
} |
1725 |
|
|
1726 |
|
|
1743 |
} |
} |
1744 |
} |
} |
1745 |
|
|
1746 |
void map_clear(appdata_t *appdata, gint layer_mask) { |
void map_clear(appdata_t *appdata, gint group_mask) { |
1747 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
1748 |
|
|
1749 |
printf("freeing map contents\n"); |
printf("freeing map contents\n"); |
1753 |
/* remove a possibly existing highlight */ |
/* remove a possibly existing highlight */ |
1754 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1755 |
|
|
1756 |
canvas_group_t group; |
canvas_erase(map->canvas, group_mask); |
|
for(group=0;group<CANVAS_GROUPS;group++) { |
|
|
|
|
|
#ifdef USE_GNOMECANVAS |
|
|
/* destroy the entire group */ |
|
|
canvas_item_destroy(map->group[group]); |
|
|
|
|
|
/* and create an empty new one */ |
|
|
map->group[group] = gnome_canvas_item_new( |
|
|
gnome_canvas_root(GNOME_CANVAS(map->canvas)), |
|
|
GNOME_TYPE_CANVAS_GROUP, |
|
|
NULL); |
|
|
#else |
|
|
if(layer_mask & (1<<group)) { |
|
|
gint children = goo_canvas_item_get_n_children(map->group[group]); |
|
|
printf("Removing %d children from layer %d\n", children, group); |
|
|
while(children--) |
|
|
goo_canvas_item_remove_child(map->group[group], children); |
|
|
} |
|
|
#endif |
|
|
} |
|
1757 |
} |
} |
1758 |
|
|
1759 |
void map_paint(appdata_t *appdata) { |
void map_paint(appdata_t *appdata) { |
1760 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
1761 |
|
|
1762 |
|
/* user may have changed antialias settings */ |
1763 |
|
canvas_set_antialias(map->canvas, !appdata->settings->no_antialias); |
1764 |
|
|
1765 |
josm_elemstyles_colorize_world(map->style, appdata->osm); |
josm_elemstyles_colorize_world(map->style, appdata->osm); |
1766 |
map_draw(map, appdata->osm); |
map_draw(map, appdata->osm); |
1767 |
} |
} |
1893 |
/* deleting the selected item de-selects it ... */ |
/* deleting the selected item de-selects it ... */ |
1894 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1895 |
|
|
1896 |
|
undo_remember_delete(appdata, item.type, item.ptr); |
1897 |
|
|
1898 |
switch(item.type) { |
switch(item.type) { |
1899 |
case MAP_TYPE_NODE: |
case MAP_TYPE_NODE: |
1900 |
printf("request to delete node #%ld\n", item.node->id); |
printf("request to delete node #%ld\n", item.node->id); |
1979 |
if(pnum == 1) { |
if(pnum == 1) { |
1980 |
g_assert(!seg->item); |
g_assert(!seg->item); |
1981 |
|
|
1982 |
seg->item = canvas_circle_new(map, CANVAS_GROUP_TRACK, |
seg->item = canvas_circle_new(map->canvas, CANVAS_GROUP_TRACK, |
1983 |
seg->track_point->lpos.x, seg->track_point->lpos.y, |
seg->track_point->lpos.x, seg->track_point->lpos.y, |
1984 |
map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR); |
map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR); |
1985 |
} |
} |
2001 |
if(seg->item) |
if(seg->item) |
2002 |
canvas_item_destroy(seg->item); |
canvas_item_destroy(seg->item); |
2003 |
|
|
2004 |
seg->item = canvas_polyline_new(map, CANVAS_GROUP_TRACK, |
seg->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK, |
2005 |
points, map->style->track.width, map->style->track.color); |
points, map->style->track.width, map->style->track.color); |
2006 |
|
|
2007 |
canvas_points_free(points); |
canvas_points_free(points); |
2067 |
} |
} |
2068 |
|
|
2069 |
if(lpos) |
if(lpos) |
2070 |
appdata->track.gps_item = canvas_circle_new(appdata->map, CANVAS_GROUP_GPS, |
appdata->track.gps_item = |
2071 |
|
canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS, |
2072 |
lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0, |
lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0, |
2073 |
RGB2CANVAS(appdata->map->style->track.gps_color), NO_COLOR); |
appdata->map->style->track.gps_color, NO_COLOR); |
2074 |
} |
} |
2075 |
|
|
2076 |
/* ------------------- map background ------------------ */ |
/* ------------------- map background ------------------ */ |
2111 |
map->bg.scale.y = (float)(bounds->max.y - bounds->min.y)/ |
map->bg.scale.y = (float)(bounds->max.y - bounds->min.y)/ |
2112 |
(float)gdk_pixbuf_get_height(map->bg.pix); |
(float)gdk_pixbuf_get_height(map->bg.pix); |
2113 |
|
|
2114 |
map->bg.item = canvas_image_new(map, CANVAS_GROUP_BG, map->bg.pix, |
map->bg.item = canvas_image_new(map->canvas, CANVAS_GROUP_BG, map->bg.pix, |
2115 |
bounds->min.x, bounds->min.y, map->bg.scale.x, map->bg.scale.y); |
bounds->min.x, bounds->min.y, map->bg.scale.x, map->bg.scale.y); |
2116 |
|
|
2117 |
canvas_item_destroy_connect(map->bg.item, |
canvas_item_destroy_connect(map->bg.item, |