30 |
tag_t *tag = NULL; |
tag_t *tag = NULL; |
31 |
char *str = NULL; |
char *str = NULL; |
32 |
|
|
33 |
switch(map_item->type) { |
switch(map_item->object.type) { |
34 |
case MAP_TYPE_NODE: |
case NODE: |
35 |
item_str = "Node"; |
item_str = "Node"; |
36 |
id = map_item->node->id; |
id = map_item->object.node->id; |
37 |
tag = map_item->node->tag; |
tag = map_item->object.node->tag; |
38 |
break; |
break; |
39 |
|
|
40 |
case MAP_TYPE_WAY: |
case WAY: |
41 |
item_str = "Way"; |
item_str = "Way"; |
42 |
id = map_item->way->id; |
id = map_item->object.way->id; |
43 |
tag = map_item->way->tag; |
tag = map_item->object.way->tag; |
44 |
|
break; |
45 |
|
|
46 |
|
case RELATION: |
47 |
|
item_str = "Relation"; |
48 |
|
id = map_item->object.relation->id; |
49 |
|
tag = map_item->object.relation->tag; |
50 |
break; |
break; |
51 |
|
|
52 |
default: |
default: |
55 |
|
|
56 |
gboolean collision = FALSE; |
gboolean collision = FALSE; |
57 |
tag_t *tags = tag; |
tag_t *tags = tag; |
58 |
|
while(tag) { |
59 |
if(id == ID_ILLEGAL) |
if(!collision && info_tag_key_collision(tags, tag)) |
60 |
str = g_strdup_printf(_("Unknown item")); |
collision = TRUE; |
61 |
else { |
tag = tag->next; |
|
str = g_strdup_printf("%s #%ld", item_str, id); |
|
|
|
|
|
/* add some tags ... */ |
|
|
while(tag) { |
|
|
if(!collision && info_tag_key_collision(tags, tag)) |
|
|
collision = TRUE; |
|
|
|
|
|
/* we don't have much space, so ignore created_by tag */ |
|
|
if(!osm_is_creator_tag(tag)) { |
|
|
char *old = str; |
|
|
str = g_strdup_printf("%s, %s=%s", old, tag->key, tag->value); |
|
|
g_free(old); |
|
|
} |
|
|
tag = tag->next; |
|
|
} |
|
62 |
} |
} |
63 |
|
|
64 |
|
str = osm_object_get_speaking_name(&map_item->object); |
65 |
statusbar_set(map->appdata, str, collision); |
statusbar_set(map->appdata, str, collision); |
66 |
g_free(str); |
g_free(str); |
67 |
} |
} |
115 |
|
|
116 |
g_assert(!map->highlight); |
g_assert(!map->highlight); |
117 |
|
|
118 |
map_item->type = MAP_TYPE_NODE; |
map_item->object.type = NODE; |
119 |
map_item->node = node; |
map_item->object.node = node; |
120 |
map_item->highlight = FALSE; |
map_item->highlight = FALSE; |
121 |
|
|
122 |
/* node may not have any visible representation at all */ |
/* node may not have any visible representation at all */ |
129 |
icon_bar_map_item_selected(appdata, map_item, TRUE); |
icon_bar_map_item_selected(appdata, map_item, TRUE); |
130 |
|
|
131 |
/* highlight node */ |
/* highlight node */ |
132 |
gint x = map_item->node->lpos.x, y = map_item->node->lpos.y; |
gint x = map_item->object.node->lpos.x, y = map_item->object.node->lpos.y; |
133 |
|
|
134 |
/* create a copy of this map item and mark it as being a highlight */ |
/* create a copy of this map item and mark it as being a highlight */ |
135 |
map_item_t *new_map_item = g_new0(map_item_t, 1); |
map_item_t *new_map_item = g_new0(map_item_t, 1); |
140 |
if(!node->ways) radius += map->style->node.border_radius; |
if(!node->ways) radius += map->style->node.border_radius; |
141 |
if(node->icon_buf && map->style->icon.enable && |
if(node->icon_buf && map->style->icon.enable && |
142 |
!appdata->settings->no_icons) { |
!appdata->settings->no_icons) { |
143 |
gint w = gdk_pixbuf_get_width(map_item->node->icon_buf); |
gint w = gdk_pixbuf_get_width(map_item->object.node->icon_buf); |
144 |
gint h = gdk_pixbuf_get_height(map_item->node->icon_buf); |
gint h = gdk_pixbuf_get_height(map_item->object.node->icon_buf); |
145 |
/* icons are technically square, so a radius slightly bigger */ |
/* icons are technically square, so a radius slightly bigger */ |
146 |
/* than sqrt(2)*MAX(w,h) should fit nicely */ |
/* than sqrt(2)*MAX(w,h) should fit nicely */ |
147 |
radius = 0.75 * map->style->icon.scale * ((w>h)?w:h); |
radius = 0.75 * map->style->icon.scale * ((w>h)?w:h); |
148 |
} |
} |
149 |
|
|
150 |
|
radius *= map->state->detail; |
151 |
map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
152 |
x, y, radius, map->style->highlight.color); |
x, y, radius, map->style->highlight.color); |
153 |
|
|
154 |
if(!map_item->item) { |
if(!map_item->item) { |
155 |
/* and draw a fake node */ |
/* and draw a fake node */ |
156 |
new_map_item = g_new0(map_item_t, 1); |
new_map_item = g_new0(map_item_t, 1); |
157 |
memcpy(new_map_item, map_item, sizeof(map_item_t)); |
memcpy(new_map_item, map_item, sizeof(map_item_t)); |
158 |
new_map_item->highlight = TRUE; |
new_map_item->highlight = TRUE; |
159 |
map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item, |
160 |
x, y, map->style->node.radius, |
x, y, map->style->node.radius, |
161 |
map->style->highlight.node_color); |
map->style->highlight.node_color); |
162 |
} |
} |
168 |
|
|
169 |
g_assert(!map->highlight); |
g_assert(!map->highlight); |
170 |
|
|
171 |
map_item->type = MAP_TYPE_WAY; |
map_item->object.type = WAY; |
172 |
map_item->way = way; |
map_item->object.way = way; |
173 |
map_item->highlight = FALSE; |
map_item->highlight = FALSE; |
174 |
map_item->item = way->map_item_chain->map_item->item; |
map_item->item = way->map_item_chain->map_item->item; |
175 |
|
|
176 |
map_statusbar(map, map_item); |
map_statusbar(map, map_item); |
177 |
icon_bar_map_item_selected(appdata, map_item, TRUE); |
icon_bar_map_item_selected(appdata, map_item, TRUE); |
178 |
gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, TRUE); |
gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, TRUE); |
|
|
|
|
gint arrow_width = (map_item->way->draw.flags & OSM_DRAW_FLAG_BG)? |
|
|
map->style->highlight.width + map_item->way->draw.bg.width/2: |
|
|
map->style->highlight.width + map_item->way->draw.width/2; |
|
179 |
|
|
180 |
node_chain_t *node_chain = map_item->way->node_chain; |
gint arrow_width = ((map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)? |
181 |
|
map->style->highlight.width + map_item->object.way->draw.bg.width/2: |
182 |
|
map->style->highlight.width + map_item->object.way->draw.width/2) |
183 |
|
* map->state->detail; |
184 |
|
|
185 |
|
node_chain_t *node_chain = map_item->object.way->node_chain; |
186 |
node_t *last = NULL; |
node_t *last = NULL; |
187 |
while(node_chain) { |
while(node_chain) { |
188 |
map_item_t item; |
map_item_t item; |
189 |
item.type = MAP_TYPE_NODE; |
item.object.type = NODE; |
190 |
item.node = node_chain->node; |
item.object.node = node_chain->node; |
191 |
|
|
192 |
/* draw an arrow between every two nodes */ |
/* draw an arrow between every two nodes */ |
193 |
if(last) { |
if(last) { |
194 |
/* create a new map item for every arrow */ |
/* create a new map item for every arrow */ |
195 |
map_item_t *new_map_item = g_new0(map_item_t, 1); |
map_item_t *new_map_item = g_new0(map_item_t, 1); |
196 |
new_map_item->type = MAP_TYPE_WAY; |
new_map_item->object.type = WAY; |
197 |
new_map_item->way = way; |
new_map_item->object.way = way; |
198 |
new_map_item->highlight = TRUE; |
new_map_item->highlight = TRUE; |
199 |
|
|
200 |
struct { float x, y;} center, diff; |
struct { float x, y;} center, diff; |
219 |
points->coords[2*2+0] = center.x - diff.y - diff.x; |
points->coords[2*2+0] = center.x - diff.y - diff.x; |
220 |
points->coords[2*2+1] = center.y + diff.x - diff.y; |
points->coords[2*2+1] = center.y + diff.x - diff.y; |
221 |
|
|
222 |
map_hl_polygon_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
map_hl_polygon_new(map, CANVAS_GROUP_WAYS_DIR, new_map_item, |
223 |
points, map->style->highlight.arrow_color); |
points, map->style->highlight.arrow_color); |
224 |
|
|
225 |
canvas_points_free(points); |
canvas_points_free(points); |
230 |
|
|
231 |
/* create a new map item for every node */ |
/* create a new map item for every node */ |
232 |
map_item_t *new_map_item = g_new0(map_item_t, 1); |
map_item_t *new_map_item = g_new0(map_item_t, 1); |
233 |
new_map_item->type = MAP_TYPE_NODE; |
new_map_item->object.type = NODE; |
234 |
new_map_item->node = node_chain->node; |
new_map_item->object.node = node_chain->node; |
235 |
new_map_item->highlight = TRUE; |
new_map_item->highlight = TRUE; |
236 |
|
|
237 |
gint x = node_chain->node->lpos.x; |
gint x = node_chain->node->lpos.x; |
238 |
gint y = node_chain->node->lpos.y; |
gint y = node_chain->node->lpos.y; |
239 |
|
|
240 |
map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item, |
map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item, |
241 |
x, y, map->style->node.radius, |
x, y, map->style->node.radius * map->state->detail, |
242 |
map->style->highlight.node_color); |
map->style->highlight.node_color); |
243 |
} |
} |
244 |
|
|
254 |
canvas_points_t *points = canvas_points_new(nodes); |
canvas_points_t *points = canvas_points_new(nodes); |
255 |
|
|
256 |
int node = 0; |
int node = 0; |
257 |
node_chain = map_item->way->node_chain; |
node_chain = map_item->object.way->node_chain; |
258 |
while(node_chain) { |
while(node_chain) { |
259 |
canvas_point_set_pos(points, node++, &node_chain->node->lpos); |
canvas_point_set_pos(points, node++, &node_chain->node->lpos); |
260 |
node_chain = node_chain->next; |
node_chain = node_chain->next; |
266 |
new_map_item->highlight = TRUE; |
new_map_item->highlight = TRUE; |
267 |
|
|
268 |
map_hl_polyline_new(map, CANVAS_GROUP_WAYS_HL, new_map_item, points, |
map_hl_polyline_new(map, CANVAS_GROUP_WAYS_HL, new_map_item, points, |
269 |
(map_item->way->draw.flags & OSM_DRAW_FLAG_BG)? |
((map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)? |
270 |
2*map->style->highlight.width + map_item->way->draw.bg.width: |
2*map->style->highlight.width + map_item->object.way->draw.bg.width: |
271 |
2*map->style->highlight.width + map_item->way->draw.width, |
2*map->style->highlight.width + map_item->object.way->draw.width) |
272 |
map->style->highlight.color); |
* map->state->detail, map->style->highlight.color); |
273 |
|
|
274 |
canvas_points_free(points); |
canvas_points_free(points); |
275 |
} |
} |
276 |
} |
} |
277 |
|
|
278 |
static void map_item_select(appdata_t *appdata, map_item_t *map_item) { |
void map_relation_select(appdata_t *appdata, relation_t *relation) { |
279 |
switch(map_item->type) { |
map_t *map = appdata->map; |
280 |
case MAP_TYPE_NODE: |
|
281 |
map_node_select(appdata, map_item->node); |
printf("highlighting relation "ITEM_ID_FORMAT"\n", relation->id); |
282 |
|
|
283 |
|
g_assert(!map->highlight); |
284 |
|
map_highlight_t **hl = &map->highlight; |
285 |
|
|
286 |
|
map_item_t *map_item = &map->selected; |
287 |
|
map_item->object.type = RELATION; |
288 |
|
map_item->object.relation = relation; |
289 |
|
map_item->highlight = FALSE; |
290 |
|
map_item->item = NULL; |
291 |
|
|
292 |
|
map_statusbar(map, map_item); |
293 |
|
icon_bar_map_item_selected(appdata, map_item, TRUE); |
294 |
|
|
295 |
|
/* process all members */ |
296 |
|
member_t *member = relation->member; |
297 |
|
while(member) { |
298 |
|
canvas_item_t *item = NULL; |
299 |
|
|
300 |
|
switch(member->object.type) { |
301 |
|
|
302 |
|
case NODE: { |
303 |
|
node_t *node = member->object.node; |
304 |
|
printf(" -> node "ITEM_ID_FORMAT"\n", node->id); |
305 |
|
|
306 |
|
item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES_HL, |
307 |
|
node->lpos.x, node->lpos.y, |
308 |
|
map->style->highlight.width + map->style->node.radius, |
309 |
|
0, map->style->highlight.color, NO_COLOR); |
310 |
|
} break; |
311 |
|
|
312 |
|
case WAY: { |
313 |
|
way_t *way = member->object.way; |
314 |
|
/* a way needs at least 2 points to be drawn */ |
315 |
|
guint nodes = osm_way_number_of_nodes(way); |
316 |
|
if(nodes > 1) { |
317 |
|
|
318 |
|
/* allocate space for nodes */ |
319 |
|
canvas_points_t *points = canvas_points_new(nodes); |
320 |
|
|
321 |
|
int node = 0; |
322 |
|
node_chain_t *node_chain = way->node_chain; |
323 |
|
while(node_chain) { |
324 |
|
canvas_point_set_pos(points, node++, &node_chain->node->lpos); |
325 |
|
node_chain = node_chain->next; |
326 |
|
} |
327 |
|
|
328 |
|
if(way->draw.flags & OSM_DRAW_FLAG_AREA) |
329 |
|
item = canvas_polygon_new(map->canvas, CANVAS_GROUP_WAYS_HL, points, 0, 0, |
330 |
|
map->style->highlight.color); |
331 |
|
else |
332 |
|
item = canvas_polyline_new(map->canvas, CANVAS_GROUP_WAYS_HL, points, |
333 |
|
(way->draw.flags & OSM_DRAW_FLAG_BG)? |
334 |
|
2*map->style->highlight.width + way->draw.bg.width: |
335 |
|
2*map->style->highlight.width + way->draw.width, |
336 |
|
map->style->highlight.color); |
337 |
|
|
338 |
|
canvas_points_free(points); |
339 |
|
} } break; |
340 |
|
|
341 |
|
default: |
342 |
|
break; |
343 |
|
} |
344 |
|
|
345 |
|
/* attach item to item chain */ |
346 |
|
if(item) { |
347 |
|
*hl = g_new0(map_highlight_t, 1); |
348 |
|
(*hl)->item = item; |
349 |
|
hl = &(*hl)->next; |
350 |
|
} |
351 |
|
|
352 |
|
member = member->next; |
353 |
|
} |
354 |
|
} |
355 |
|
|
356 |
|
static void map_object_select(appdata_t *appdata, object_t *object) { |
357 |
|
switch(object->type) { |
358 |
|
case NODE: |
359 |
|
map_node_select(appdata, object->node); |
360 |
|
break; |
361 |
|
case WAY: |
362 |
|
map_way_select(appdata, object->way); |
363 |
break; |
break; |
364 |
case MAP_TYPE_WAY: |
case RELATION: |
365 |
map_way_select(appdata, map_item->way); |
map_relation_select(appdata, object->relation); |
366 |
break; |
break; |
367 |
default: |
default: |
368 |
g_assert((map_item->type == MAP_TYPE_NODE)|| |
g_assert((object->type == NODE)||(object->type == RELATION)|| |
369 |
(map_item->type == MAP_TYPE_WAY)); |
(object->type == WAY)); |
370 |
break; |
break; |
371 |
} |
} |
372 |
} |
} |
374 |
void map_item_deselect(appdata_t *appdata) { |
void map_item_deselect(appdata_t *appdata) { |
375 |
|
|
376 |
/* save tags for "last" function in info dialog */ |
/* save tags for "last" function in info dialog */ |
377 |
if(appdata->map->selected.type == MAP_TYPE_NODE) { |
if(appdata->map->selected.object.type == NODE) { |
378 |
if(appdata->map->last_node_tags) |
if(appdata->map->last_node_tags) |
379 |
osm_tags_free(appdata->map->last_node_tags); |
osm_tags_free(appdata->map->last_node_tags); |
380 |
|
|
381 |
appdata->map->last_node_tags = |
appdata->map->last_node_tags = |
382 |
osm_tags_copy(appdata->map->selected.node->tag, FALSE); |
osm_tags_copy(appdata->map->selected.object.node->tag, FALSE); |
383 |
} else if(appdata->map->selected.type == MAP_TYPE_WAY) { |
} else if(appdata->map->selected.object.type == WAY) { |
384 |
if(appdata->map->last_way_tags) |
if(appdata->map->last_way_tags) |
385 |
osm_tags_free(appdata->map->last_way_tags); |
osm_tags_free(appdata->map->last_way_tags); |
386 |
|
|
387 |
appdata->map->last_way_tags = |
appdata->map->last_way_tags = |
388 |
osm_tags_copy(appdata->map->selected.way->tag, FALSE); |
osm_tags_copy(appdata->map->selected.object.way->tag, FALSE); |
389 |
} |
} |
390 |
|
|
391 |
/* remove statusbar message */ |
/* remove statusbar message */ |
399 |
map_hl_remove(appdata); |
map_hl_remove(appdata); |
400 |
|
|
401 |
/* forget about selection */ |
/* forget about selection */ |
402 |
appdata->map->selected.type = MAP_TYPE_ILLEGAL; |
appdata->map->selected.object.type = ILLEGAL; |
403 |
} |
} |
404 |
|
|
405 |
/* called whenever a map item is to be destroyed */ |
/* called whenever a map item is to be destroyed */ |
411 |
#ifdef DESTROY_WAIT_FOR_GTK |
#ifdef DESTROY_WAIT_FOR_GTK |
412 |
/* remove item from nodes/ways map_item_chain */ |
/* remove item from nodes/ways map_item_chain */ |
413 |
map_item_chain_t **chain = NULL; |
map_item_chain_t **chain = NULL; |
414 |
if(map_item->type == MAP_TYPE_NODE) |
if(map_item->object.type == NODE) |
415 |
chain = &map_item->node->map_item_chain; |
chain = &map_item->object.node->map_item_chain; |
416 |
else if(map_item->type == MAP_TYPE_WAY) |
else if(map_item->object.type == WAY) |
417 |
chain = &map_item->way->map_item_chain; |
chain = &map_item->object.way->map_item_chain; |
418 |
|
|
419 |
/* there must be a chain with content, otherwise things are broken */ |
/* there must be a chain with content, otherwise things are broken */ |
420 |
g_assert(chain); |
g_assert(chain); |
441 |
gint width, canvas_color_t fill, canvas_color_t border) { |
gint width, canvas_color_t fill, canvas_color_t border) { |
442 |
|
|
443 |
map_item_t *map_item = g_new0(map_item_t, 1); |
map_item_t *map_item = g_new0(map_item_t, 1); |
444 |
map_item->type = MAP_TYPE_NODE; |
map_item->object.type = NODE; |
445 |
map_item->node = node; |
map_item->object.node = node; |
446 |
|
|
447 |
if(!node->icon_buf || !map->style->icon.enable || |
if(!node->icon_buf || !map->style->icon.enable || |
448 |
map->appdata->settings->no_icons) |
map->appdata->settings->no_icons) |
449 |
map_item->item = canvas_circle_new(map, CANVAS_GROUP_NODES, |
map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES, |
450 |
node->lpos.x, node->lpos.y, radius, width, fill, border); |
node->lpos.x, node->lpos.y, radius, width, fill, border); |
451 |
else |
else |
452 |
map_item->item = canvas_image_new(map, CANVAS_GROUP_NODES, |
map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES, |
453 |
node->icon_buf, |
node->icon_buf, |
454 |
node->lpos.x - map->style->icon.scale/2 * |
node->lpos.x - map->style->icon.scale/2 * map->state->detail * |
455 |
gdk_pixbuf_get_width(node->icon_buf), |
gdk_pixbuf_get_width(node->icon_buf), |
456 |
node->lpos.y - map->style->icon.scale/2 * |
node->lpos.y - map->style->icon.scale/2 * map->state->detail * |
457 |
gdk_pixbuf_get_height(node->icon_buf), |
gdk_pixbuf_get_height(node->icon_buf), |
458 |
map->style->icon.scale,map->style->icon.scale); |
map->state->detail * map->style->icon.scale, |
459 |
|
map->state->detail * map->style->icon.scale); |
460 |
|
|
461 |
canvas_item_set_zoom_max(map_item->item, node->zoom_max); |
canvas_item_set_zoom_max(map_item->item, |
462 |
|
node->zoom_max / (2 * map->state->detail)); |
463 |
|
|
464 |
/* attach map_item to nodes map_item_chain */ |
/* attach map_item to nodes map_item_chain */ |
465 |
map_item_chain_t **chain = &node->map_item_chain; |
map_item_chain_t **chain = &node->map_item_chain; |
481 |
gint width, canvas_color_t fill, canvas_color_t border) { |
gint width, canvas_color_t fill, canvas_color_t border) { |
482 |
|
|
483 |
map_item_t *map_item = g_new0(map_item_t, 1); |
map_item_t *map_item = g_new0(map_item_t, 1); |
484 |
map_item->type = MAP_TYPE_WAY; |
map_item->object.type = WAY; |
485 |
map_item->way = way; |
map_item->object.way = way; |
486 |
map_item->item = canvas_circle_new(map, CANVAS_GROUP_WAYS, |
map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_WAYS, |
487 |
way->node_chain->node->lpos.x, way->node_chain->node->lpos.y, |
way->node_chain->node->lpos.x, way->node_chain->node->lpos.y, |
488 |
radius, width, fill, border); |
radius, width, fill, border); |
489 |
|
|
507 |
way_t *way, canvas_points_t *points, gint width, |
way_t *way, canvas_points_t *points, gint width, |
508 |
canvas_color_t color, canvas_color_t fill_color) { |
canvas_color_t color, canvas_color_t fill_color) { |
509 |
map_item_t *map_item = g_new0(map_item_t, 1); |
map_item_t *map_item = g_new0(map_item_t, 1); |
510 |
map_item->type = MAP_TYPE_WAY; |
map_item->object.type = WAY; |
511 |
map_item->way = way; |
map_item->object.way = way; |
512 |
|
|
513 |
if(way->draw.flags & OSM_DRAW_FLAG_AREA) { |
if(way->draw.flags & OSM_DRAW_FLAG_AREA) { |
514 |
if(map->style->area.color & 0xff) |
if(map->style->area.color & 0xff) |
515 |
map_item->item = canvas_polygon_new(map, group, points, |
map_item->item = canvas_polygon_new(map->canvas, group, points, |
516 |
width, color, fill_color); |
width, color, fill_color); |
517 |
else |
else |
518 |
map_item->item = canvas_polyline_new(map, group, points, |
map_item->item = canvas_polyline_new(map->canvas, group, points, |
519 |
width, color); |
width, color); |
520 |
} else { |
} else { |
521 |
map_item->item = canvas_polyline_new(map, group, points, width, color); |
map_item->item = canvas_polyline_new(map->canvas, group, points, width, color); |
522 |
} |
} |
523 |
|
|
524 |
canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max); |
canvas_item_set_zoom_max(map_item->item, |
525 |
|
way->draw.zoom_max / (2 * map->state->detail)); |
526 |
|
|
527 |
|
/* a ways outline itself is never dashed */ |
528 |
if (group != CANVAS_GROUP_WAYS_OL) |
if (group != CANVAS_GROUP_WAYS_OL) |
529 |
if (way->draw.dashed) |
if (way->draw.dashed) |
530 |
canvas_item_set_dashed(map_item->item); |
canvas_item_set_dashed(map_item->item, width, way->draw.dash_length); |
531 |
|
|
532 |
/* attach map_item to ways map_item_chain */ |
/* attach map_item to ways map_item_chain */ |
533 |
map_item_chain_t **chain = &way->map_item_chain; |
map_item_chain_t **chain = &way->map_item_chain; |
572 |
} |
} |
573 |
|
|
574 |
/* draw way */ |
/* draw way */ |
575 |
|
float width = way->draw.width * map->state->detail; |
576 |
|
|
577 |
if(way->draw.flags & OSM_DRAW_FLAG_AREA) { |
if(way->draw.flags & OSM_DRAW_FLAG_AREA) { |
578 |
map_way_new(map, CANVAS_GROUP_POLYGONS, way, points, |
map_way_new(map, CANVAS_GROUP_POLYGONS, way, points, |
579 |
way->draw.width, way->draw.color, way->draw.area.color); |
width, way->draw.color, way->draw.area.color); |
580 |
} else { |
} else { |
581 |
map_way_new(map, CANVAS_GROUP_WAYS, way, points, |
|
582 |
way->draw.width, way->draw.color, NO_COLOR); |
if(way->draw.flags & OSM_DRAW_FLAG_BG) { |
583 |
|
map_way_new(map, CANVAS_GROUP_WAYS_INT, way, points, |
584 |
if(way->draw.flags & OSM_DRAW_FLAG_BG) |
width, way->draw.color, NO_COLOR); |
585 |
|
|
586 |
map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points, |
map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points, |
587 |
way->draw.bg.width, way->draw.bg.color, NO_COLOR); |
way->draw.bg.width * map->state->detail, |
588 |
|
way->draw.bg.color, NO_COLOR); |
589 |
|
|
590 |
|
} else |
591 |
|
map_way_new(map, CANVAS_GROUP_WAYS, way, points, |
592 |
|
width, way->draw.color, NO_COLOR); |
593 |
} |
} |
594 |
canvas_points_free(points); |
canvas_points_free(points); |
595 |
} |
} |
602 |
|
|
603 |
if(!node->ways) |
if(!node->ways) |
604 |
map_node_new(map, node, |
map_node_new(map, node, |
605 |
map->style->node.radius, |
map->style->node.radius * map->state->detail, |
606 |
map->style->node.border_radius, |
map->style->node.border_radius * map->state->detail, |
607 |
map->style->node.fill_color, |
map->style->node.fill_color, |
608 |
map->style->node.color); |
map->style->node.color); |
609 |
|
|
610 |
else if(map->style->node.show_untagged || osm_node_has_tag(node)) |
else if(map->style->node.show_untagged || osm_node_has_tag(node)) |
611 |
map_node_new(map, node, |
map_node_new(map, node, |
612 |
map->style->node.radius, 0, |
map->style->node.radius * map->state->detail, 0, |
613 |
map->style->node.color, 0); |
map->style->node.color, 0); |
614 |
} |
} |
615 |
|
|
616 |
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) { |
617 |
switch(map_item->type) { |
switch(map_item->object.type) { |
618 |
case MAP_TYPE_NODE: |
case NODE: |
619 |
map_node_draw(map, map_item->node); |
map_node_draw(map, map_item->object.node); |
620 |
break; |
break; |
621 |
case MAP_TYPE_WAY: |
case WAY: |
622 |
map_way_draw(map, map_item->way); |
map_way_draw(map, map_item->object.way); |
623 |
break; |
break; |
624 |
default: |
default: |
625 |
g_assert((map_item->type == MAP_TYPE_NODE) || |
g_assert((map_item->object.type == NODE) || |
626 |
(map_item->type == MAP_TYPE_WAY)); |
(map_item->object.type == WAY)); |
627 |
} |
} |
628 |
} |
} |
629 |
|
|
630 |
static void map_item_remove(map_t *map, map_item_t *map_item) { |
static void map_item_remove(map_t *map, map_item_t *map_item) { |
631 |
map_item_chain_t **chainP = NULL; |
map_item_chain_t **chainP = NULL; |
632 |
|
|
633 |
switch(map_item->type) { |
switch(map_item->object.type) { |
634 |
case MAP_TYPE_NODE: |
case NODE: |
635 |
chainP = &map_item->node->map_item_chain; |
chainP = &map_item->object.node->map_item_chain; |
636 |
break; |
break; |
637 |
case MAP_TYPE_WAY: |
case WAY: |
638 |
chainP = &map_item->way->map_item_chain; |
chainP = &map_item->object.way->map_item_chain; |
639 |
break; |
break; |
640 |
default: |
default: |
641 |
g_assert((map_item->type == MAP_TYPE_NODE) || |
g_assert((map_item->object.type == NODE) || |
642 |
(map_item->type == MAP_TYPE_WAY)); |
(map_item->object.type == WAY)); |
643 |
} |
} |
644 |
|
|
645 |
map_item_chain_destroy(chainP); |
map_item_chain_destroy(chainP); |
646 |
} |
} |
647 |
|
|
648 |
static void map_item_init(style_t *style, map_item_t *map_item) { |
static void map_item_init(style_t *style, map_item_t *map_item) { |
649 |
switch (map_item->type){ |
switch (map_item->object.type){ |
650 |
case MAP_TYPE_WAY: |
case WAY: |
651 |
josm_elemstyles_colorize_way(style, map_item->way); |
josm_elemstyles_colorize_way(style, map_item->object.way); |
652 |
break; |
break; |
653 |
case MAP_TYPE_NODE: |
case NODE: |
654 |
josm_elemstyles_colorize_node(style, map_item->node); |
josm_elemstyles_colorize_node(style, map_item->object.node); |
655 |
break; |
break; |
656 |
default: |
default: |
657 |
g_assert((map_item->type == MAP_TYPE_NODE) || |
g_assert((map_item->object.type == NODE) || |
658 |
(map_item->type == MAP_TYPE_WAY)); |
(map_item->object.type == WAY)); |
659 |
} |
} |
660 |
} |
} |
661 |
|
|
662 |
void map_item_redraw(appdata_t *appdata, map_item_t *map_item) { |
void map_item_redraw(appdata_t *appdata, map_item_t *map_item) { |
663 |
map_item_t item = *map_item; |
map_item_t item = *map_item; |
664 |
|
|
665 |
|
/* a relation cannot be redraws as it doesn't have a visual */ |
666 |
|
/* representation */ |
667 |
|
if(map_item->object.type == RELATION) |
668 |
|
return; |
669 |
|
|
670 |
/* check if the item to be redrawn is the selected one */ |
/* check if the item to be redrawn is the selected one */ |
671 |
gboolean is_selected = FALSE; |
gboolean is_selected = FALSE; |
672 |
if(map_item->ptr == appdata->map->selected.ptr) { |
if(map_item->object.ptr == appdata->map->selected.object.ptr) { |
673 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
674 |
is_selected = TRUE; |
is_selected = TRUE; |
675 |
} |
} |
680 |
|
|
681 |
/* restore selection if there was one */ |
/* restore selection if there was one */ |
682 |
if(is_selected) |
if(is_selected) |
683 |
map_item_select(appdata, &item); |
map_object_select(appdata, &item.object); |
684 |
} |
} |
685 |
|
|
686 |
static void map_frisket_rectangle(canvas_points_t *points, |
static void map_frisket_rectangle(canvas_points_t *points, |
705 |
/* top rectangle */ |
/* top rectangle */ |
706 |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
707 |
mult*bounds->min.y, bounds->min.y); |
mult*bounds->min.y, bounds->min.y); |
708 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
709 |
|
1, NO_COLOR, color); |
710 |
|
|
711 |
/* bottom rectangle */ |
/* bottom rectangle */ |
712 |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x, |
713 |
bounds->max.y, mult*bounds->max.y); |
bounds->max.y, mult*bounds->max.y); |
714 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
715 |
|
1, NO_COLOR, color); |
716 |
|
|
717 |
/* left rectangle */ |
/* left rectangle */ |
718 |
map_frisket_rectangle(points, mult*bounds->min.x, bounds->min.x, |
map_frisket_rectangle(points, mult*bounds->min.x, bounds->min.x, |
719 |
mult*bounds->min.y, mult*bounds->max.y); |
mult*bounds->min.y, mult*bounds->max.y); |
720 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
721 |
|
1, NO_COLOR, color); |
722 |
|
|
723 |
/* right rectangle */ |
/* right rectangle */ |
724 |
map_frisket_rectangle(points, bounds->max.x, mult*bounds->max.x, |
map_frisket_rectangle(points, bounds->max.x, mult*bounds->max.x, |
725 |
mult*bounds->min.y, mult*bounds->max.y); |
mult*bounds->min.y, mult*bounds->max.y); |
726 |
canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color); |
canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
727 |
|
1, NO_COLOR, color); |
728 |
|
|
729 |
} |
} |
730 |
|
|
735 |
bounds->min.x-ew2, bounds->max.x+ew2, |
bounds->min.x-ew2, bounds->max.x+ew2, |
736 |
bounds->min.y-ew2, bounds->max.y+ew2); |
bounds->min.y-ew2, bounds->max.y+ew2); |
737 |
|
|
738 |
canvas_polyline_new(map, CANVAS_GROUP_NODES, points, |
canvas_polyline_new(map->canvas, CANVAS_GROUP_FRISKET, points, |
739 |
map->style->frisket.border.width, |
map->style->frisket.border.width, |
740 |
map->style->frisket.border.color); |
map->style->frisket.border.color); |
741 |
|
|
870 |
if(map_item->highlight) |
if(map_item->highlight) |
871 |
printf(" item is highlight\n"); |
printf(" item is highlight\n"); |
872 |
|
|
873 |
switch(map_item->type) { |
switch(map_item->object.type) { |
874 |
case MAP_TYPE_NODE: |
case NODE: |
875 |
printf(" item is node #%ld\n", map_item->node->id); |
printf(" item is node #"ITEM_ID_FORMAT"\n", map_item->object.node->id); |
876 |
break; |
break; |
877 |
case MAP_TYPE_WAY: |
case WAY: |
878 |
printf(" item is way #%ld\n", map_item->way->id); |
printf(" item is way #"ITEM_ID_FORMAT"\n", map_item->object.way->id); |
879 |
break; |
break; |
880 |
default: |
default: |
881 |
printf(" unknown item\n"); |
printf(" unknown item\n"); |
894 |
|
|
895 |
/* get the item (parent) this item is the highlight of */ |
/* get the item (parent) this item is the highlight of */ |
896 |
map_item_t *parent = NULL; |
map_item_t *parent = NULL; |
897 |
switch(map_item->type) { |
switch(map_item->object.type) { |
898 |
|
|
899 |
case MAP_TYPE_NODE: |
case NODE: |
900 |
if(map_item->node->map_item_chain) |
if(map_item->object.node->map_item_chain) |
901 |
parent = map_item->node->map_item_chain->map_item; |
parent = map_item->object.node->map_item_chain->map_item; |
902 |
|
|
903 |
if(parent) |
if(parent) |
904 |
printf(" using parent item node #%ld\n", parent->node->id); |
printf(" using parent item node #" ITEM_ID_FORMAT "\n", |
905 |
|
parent->object.node->id); |
906 |
break; |
break; |
907 |
|
|
908 |
case MAP_TYPE_WAY: |
case WAY: |
909 |
if(map_item->way->map_item_chain) |
if(map_item->object.way->map_item_chain) |
910 |
parent = map_item->way->map_item_chain->map_item; |
parent = map_item->object.way->map_item_chain->map_item; |
911 |
|
|
912 |
if(parent) |
if(parent) |
913 |
printf(" using parent item way #%ld\n", parent->way->id); |
printf(" using parent item way #" ITEM_ID_FORMAT "\n", |
914 |
|
parent->object.way->id); |
915 |
break; |
break; |
916 |
|
|
917 |
default: |
default: |
918 |
g_assert((map_item->type == MAP_TYPE_NODE) || |
g_assert((map_item->object.type == NODE) || |
919 |
(map_item->type == MAP_TYPE_WAY)); |
(map_item->object.type == WAY)); |
920 |
break; |
break; |
921 |
} |
} |
922 |
|
|
928 |
return map_item; |
return map_item; |
929 |
} |
} |
930 |
|
|
|
|
|
|
|
|
|
#ifdef USE_GOOCANVAS |
|
|
|
|
931 |
/* 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 |
932 |
* map visible at all times */ |
* map visible at all times */ |
933 |
static void map_limit_scroll(map_t *map, gint *sx, gint *sy) { |
static void map_limit_scroll(map_t *map, canvas_unit_t unit, |
934 |
gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas)); |
gint *sx, gint *sy) { |
|
|
|
|
gint sx_cu = *sx / zoom; |
|
|
gint sy_cu = *sy / zoom; |
|
935 |
|
|
936 |
// Canvas viewport dimensions |
/* get scale factor for pixel->meter conversion. set to 1 if */ |
937 |
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
/* given coordinates are already in meters */ |
938 |
gint aw_cu = a->width / zoom; |
gdouble scale = (unit == CANVAS_UNIT_METER)?1.0:canvas_get_zoom(map->canvas); |
939 |
gint ah_cu = a->height / zoom; |
|
940 |
|
/* convert pixels to meters if necessary */ |
941 |
// Data rect minimum and maximum |
gdouble sx_cu = *sx / scale; |
942 |
gint min_x, min_y, max_x, max_y; |
gdouble sy_cu = *sy / scale; |
943 |
min_x = map->appdata->osm->bounds->min.x; |
|
944 |
min_y = map->appdata->osm->bounds->min.y; |
/* get size of visible area in canvas units (meters) */ |
945 |
max_x = map->appdata->osm->bounds->max.x; |
gint aw_cu = canvas_get_viewport_width(map->canvas, CANVAS_UNIT_METER); |
946 |
max_y = map->appdata->osm->bounds->max.y; |
gint ah_cu = canvas_get_viewport_height(map->canvas, CANVAS_UNIT_METER); |
947 |
|
|
948 |
// limit stops - prevent scrolling beyond these |
// Data rect minimum and maximum |
949 |
gint min_sy_cu = 0.95*(min_y - ah_cu); |
gint min_x, min_y, max_x, max_y; |
950 |
gint min_sx_cu = 0.95*(min_x - aw_cu); |
min_x = map->appdata->osm->bounds->min.x; |
951 |
gint max_sy_cu = 0.95*(max_y); |
min_y = map->appdata->osm->bounds->min.y; |
952 |
gint max_sx_cu = 0.95*(max_x); |
max_x = map->appdata->osm->bounds->max.x; |
953 |
if (sy_cu < min_sy_cu) { *sy = min_sy_cu*zoom; } |
max_y = map->appdata->osm->bounds->max.y; |
954 |
if (sx_cu < min_sx_cu) { *sx = min_sx_cu*zoom; } |
|
955 |
if (sy_cu > max_sy_cu) { *sy = max_sy_cu*zoom; } |
// limit stops - prevent scrolling beyond these |
956 |
if (sx_cu > max_sx_cu) { *sx = max_sx_cu*zoom; } |
gint min_sy_cu = 0.95*(min_y - ah_cu); |
957 |
|
gint min_sx_cu = 0.95*(min_x - aw_cu); |
958 |
|
gint max_sy_cu = 0.95*(max_y); |
959 |
|
gint max_sx_cu = 0.95*(max_x); |
960 |
|
if (sy_cu < min_sy_cu) { *sy = min_sy_cu * scale; } |
961 |
|
if (sx_cu < min_sx_cu) { *sx = min_sx_cu * scale; } |
962 |
|
if (sy_cu > max_sy_cu) { *sy = max_sy_cu * scale; } |
963 |
|
if (sx_cu > max_sx_cu) { *sx = max_sx_cu * scale; } |
964 |
} |
} |
965 |
|
|
966 |
|
|
974 |
max_x = map->appdata->osm->bounds->max.x; |
max_x = map->appdata->osm->bounds->max.x; |
975 |
max_y = map->appdata->osm->bounds->max.y; |
max_y = map->appdata->osm->bounds->max.y; |
976 |
|
|
977 |
// Canvas viewport dimensions |
/* get size of visible area in pixels and convert to meters of intended */ |
978 |
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
/* zoom by deviding by zoom (which is basically pix/m) */ |
979 |
gint ah_cu = a->height / *zoom; |
gint aw_cu = |
980 |
gint aw_cu = a->width / *zoom; |
canvas_get_viewport_width(map->canvas, CANVAS_UNIT_PIXEL) / *zoom; |
981 |
|
gint ah_cu = |
982 |
|
canvas_get_viewport_height(map->canvas, CANVAS_UNIT_PIXEL) / *zoom; |
983 |
|
|
984 |
gdouble oldzoom = *zoom; |
gdouble oldzoom = *zoom; |
985 |
if (ah_cu < aw_cu) { |
if (ah_cu < aw_cu) { |
997 |
} |
} |
998 |
} |
} |
999 |
if (*zoom != oldzoom) { |
if (*zoom != oldzoom) { |
1000 |
printf("Can't zoom further out\n"); |
printf("Can't zoom further out (%f)\n", *zoom); |
1001 |
return 1; |
return 1; |
1002 |
} |
} |
1003 |
return 0; |
return 0; |
1004 |
} |
} |
1005 |
|
|
1006 |
|
|
|
#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 |
|
|
|
|
1007 |
/* |
/* |
1008 |
* Scroll the map to a point if that point is currently offscreen. |
* Scroll the map to a point if that point is currently offscreen. |
1009 |
*/ |
*/ |
1026 |
} |
} |
1027 |
|
|
1028 |
// Viewport dimensions in canvas space |
// Viewport dimensions in canvas space |
1029 |
gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas)); |
|
1030 |
GtkAllocation *a = >K_WIDGET(map->canvas)->allocation; |
/* get size of visible area in canvas units (meters) */ |
1031 |
gdouble aw = a->width / zoom; |
gdouble pix_per_meter = canvas_get_zoom(map->canvas); |
1032 |
gdouble ah = a->height / zoom; |
gdouble aw = canvas_get_viewport_width(map->canvas, CANVAS_UNIT_METER); |
1033 |
|
gdouble ah = canvas_get_viewport_height(map->canvas, CANVAS_UNIT_METER); |
1034 |
|
|
1035 |
// Is the point still onscreen? |
// Is the point still onscreen? |
1036 |
gboolean vert_recentre_needed = FALSE; |
gboolean vert_recentre_needed = FALSE; |
1037 |
gboolean horiz_recentre_needed = FALSE; |
gboolean horiz_recentre_needed = FALSE; |
1038 |
gint sx, sy; |
gint sx, sy; |
1039 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1040 |
gint viewport_left = (sx/zoom); |
gint viewport_left = (sx/pix_per_meter); |
1041 |
gint viewport_right = (sx/zoom)+aw; |
gint viewport_right = (sx/pix_per_meter)+aw; |
1042 |
gint viewport_top = (sy/zoom); |
gint viewport_top = (sy/pix_per_meter); |
1043 |
gint viewport_bottom = (sy/zoom)+ah; |
gint viewport_bottom = (sy/pix_per_meter)+ah; |
1044 |
if (lpos->x > viewport_right) { |
if (lpos->x > viewport_right) { |
1045 |
printf("** off right edge (%d > %d)\n", lpos->x, viewport_right); |
printf("** off right edge (%d > %d)\n", lpos->x, viewport_right); |
1046 |
horiz_recentre_needed = TRUE; |
horiz_recentre_needed = TRUE; |
1060 |
|
|
1061 |
if (horiz_recentre_needed || vert_recentre_needed) { |
if (horiz_recentre_needed || vert_recentre_needed) { |
1062 |
gint new_sx, new_sy; |
gint new_sx, new_sy; |
1063 |
#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 |
|
1064 |
// Just centre both at once |
// Just centre both at once |
1065 |
new_sx = zoom * (lpos->x - (aw/2)); |
new_sx = pix_per_meter * (lpos->x - (aw/2)); |
1066 |
new_sy = zoom * (lpos->y - (ah/2)); |
new_sy = pix_per_meter * (lpos->y - (ah/2)); |
1067 |
#endif |
|
1068 |
map_limit_scroll(map, &new_sx, &new_sy); |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &new_sx, &new_sy); |
1069 |
canvas_scroll_to(map->canvas, new_sx, new_sy); |
canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, new_sx, new_sy); |
1070 |
} |
} |
1071 |
} |
} |
1072 |
|
|
|
#endif // #ifdef USE_GOOCANVAS |
|
|
|
|
1073 |
/* Deselects the current way or node if its zoom_max |
/* Deselects the current way or node if its zoom_max |
1074 |
* 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. */ |
1075 |
void map_deselect_if_zoom_below_zoom_max(map_t *map) { |
void map_deselect_if_zoom_below_zoom_max(map_t *map) { |
1076 |
if (map->selected.type == MAP_TYPE_WAY) { |
if (map->selected.object.type == WAY) { |
1077 |
printf("will deselect way if zoomed below %f\n", |
printf("will deselect way if zoomed below %f\n", |
1078 |
map->selected.way->draw.zoom_max); |
map->selected.object.way->draw.zoom_max); |
1079 |
if (map->state->zoom < map->selected.way->draw.zoom_max) { |
if (map->state->zoom < map->selected.object.way->draw.zoom_max) { |
1080 |
printf(" deselecting way!\n"); |
printf(" deselecting way!\n"); |
1081 |
map_item_deselect(map->appdata); |
map_item_deselect(map->appdata); |
1082 |
} |
} |
1083 |
} |
} |
1084 |
else if (map->selected.type == MAP_TYPE_NODE) { |
else if (map->selected.object.type == NODE) { |
1085 |
printf("will deselect node if zoomed below %f\n", |
printf("will deselect node if zoomed below %f\n", |
1086 |
map->selected.node->zoom_max); |
map->selected.object.node->zoom_max); |
1087 |
if (map->state->zoom < map->selected.node->zoom_max) { |
if (map->state->zoom < map->selected.object.node->zoom_max) { |
1088 |
printf(" deselecting node!\n"); |
printf(" deselecting node!\n"); |
1089 |
map_item_deselect(map->appdata); |
map_item_deselect(map->appdata); |
1090 |
} |
} |
1094 |
void map_set_zoom(map_t *map, double zoom, |
void map_set_zoom(map_t *map, double zoom, |
1095 |
gboolean update_scroll_offsets) { |
gboolean update_scroll_offsets) { |
1096 |
gboolean at_zoom_limit = 0; |
gboolean at_zoom_limit = 0; |
|
#ifdef USE_GOOCANVAS |
|
1097 |
at_zoom_limit = map_limit_zoom(map, &zoom); |
at_zoom_limit = map_limit_zoom(map, &zoom); |
1098 |
#endif |
|
1099 |
map->state->zoom = zoom; |
map->state->zoom = zoom; |
1100 |
canvas_set_zoom(map->canvas, map->state->zoom); |
canvas_set_zoom(map->canvas, map->state->zoom); |
1101 |
|
|
1102 |
map_deselect_if_zoom_below_zoom_max(map); |
map_deselect_if_zoom_below_zoom_max(map); |
1103 |
|
|
1104 |
if (update_scroll_offsets) { |
if(update_scroll_offsets) { |
1105 |
if (!at_zoom_limit) { |
if (!at_zoom_limit) { |
1106 |
/* zooming affects the scroll offsets */ |
/* zooming affects the scroll offsets */ |
1107 |
gint sx, sy; |
gint sx, sy; |
1108 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1109 |
#ifdef USE_GOOCANVAS |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy); |
1110 |
map_limit_scroll(map, &sx, &sy); |
|
1111 |
canvas_scroll_to(map->canvas, sx, sy); // keep the map visible |
// keep the map visible |
1112 |
#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); |
|
1113 |
} |
} |
1114 |
#endif |
|
1115 |
|
canvas_scroll_get(map->canvas, CANVAS_UNIT_METER, |
1116 |
|
&map->state->scroll_offset.x, |
1117 |
|
&map->state->scroll_offset.y); |
1118 |
} |
} |
1119 |
} |
} |
1120 |
|
|
1139 |
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) { |
1140 |
gint sx, sy; |
gint sx, sy; |
1141 |
|
|
|
#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 |
|
1142 |
/* add offsets generated by mouse within map and map scrolling */ |
/* add offsets generated by mouse within map and map scrolling */ |
1143 |
sx = (x-map->pen_down.at.x); |
sx = (x-map->pen_down.at.x); |
1144 |
sy = (y-map->pen_down.at.y); |
sy = (y-map->pen_down.at.y); |
|
#endif |
|
1145 |
|
|
1146 |
return(sx*sx + sy*sy > limit*limit); |
return(sx*sx + sy*sy > limit*limit); |
1147 |
} |
} |
1150 |
static void map_do_scroll(map_t *map, gint x, gint y) { |
static void map_do_scroll(map_t *map, gint x, gint y) { |
1151 |
gint sx, sy; |
gint sx, sy; |
1152 |
|
|
1153 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1154 |
sx -= x-map->pen_down.at.x; |
sx -= x-map->pen_down.at.x; |
1155 |
sy -= y-map->pen_down.at.y; |
sy -= y-map->pen_down.at.y; |
1156 |
#ifdef USE_GOOCANVAS |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy); |
1157 |
map_limit_scroll(map, &sx, &sy); |
canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy); |
1158 |
#endif |
|
1159 |
canvas_scroll_to(map->canvas, sx, sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_METER, |
1160 |
map->state->scroll_offset.x = sx; |
&map->state->scroll_offset.x, |
1161 |
map->state->scroll_offset.y = sy; |
&map->state->scroll_offset.y); |
1162 |
} |
} |
1163 |
|
|
1164 |
|
|
1165 |
/* scroll a certain step */ |
/* scroll a certain step */ |
1166 |
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) { |
1167 |
gint sx, sy; |
gint sx, sy; |
1168 |
canvas_get_scroll_offsets(map->canvas, &sx, &sy); |
canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy); |
1169 |
sx += x; |
sx += x; |
1170 |
sy += y; |
sy += y; |
1171 |
#ifdef USE_GOOCANVAS |
map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy); |
1172 |
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; |
|
|
} |
|
1173 |
|
|
1174 |
|
canvas_scroll_get(map->canvas, CANVAS_UNIT_METER, |
1175 |
|
&map->state->scroll_offset.x, |
1176 |
|
&map->state->scroll_offset.y); |
1177 |
|
} |
1178 |
|
|
1179 |
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) { |
1180 |
printf("check if item is a selected node\n"); |
printf("check if item is a selected node\n"); |
1184 |
return FALSE; |
return FALSE; |
1185 |
} |
} |
1186 |
|
|
1187 |
if(map->selected.type == MAP_TYPE_ILLEGAL) { |
if(map->selected.object.type == ILLEGAL) { |
1188 |
printf(" nothing is selected\n"); |
printf(" nothing is selected\n"); |
1189 |
return FALSE; |
return FALSE; |
1190 |
} |
} |
1191 |
|
|
1192 |
/* clicked the highlight directly */ |
/* clicked the highlight directly */ |
1193 |
if(map_item->type != MAP_TYPE_NODE) { |
if(map_item->object.type != NODE) { |
1194 |
printf(" didn't click node\n"); |
printf(" didn't click node\n"); |
1195 |
return FALSE; |
return FALSE; |
1196 |
} |
} |
1197 |
|
|
1198 |
if(map->selected.type == MAP_TYPE_NODE) { |
if(map->selected.object.type == NODE) { |
1199 |
printf(" selected item is a node\n"); |
printf(" selected item is a node\n"); |
1200 |
|
|
1201 |
if(map_item->node == map->selected.node) { |
if(map_item->object.node == map->selected.object.node) { |
1202 |
printf(" requested item is a selected node\n"); |
printf(" requested item is a selected node\n"); |
1203 |
return TRUE; |
return TRUE; |
1204 |
} |
} |
1205 |
printf(" but it's not the requested one\n"); |
printf(" but it's not the requested one\n"); |
1206 |
return FALSE; |
return FALSE; |
1207 |
|
|
1208 |
} else if(map->selected.type == MAP_TYPE_WAY) { |
} else if(map->selected.object.type == WAY) { |
1209 |
printf(" selected item is a way\n"); |
printf(" selected item is a way\n"); |
1210 |
|
|
1211 |
node_chain_t *node_chain = map->selected.way->node_chain; |
node_chain_t *node_chain = map->selected.object.way->node_chain; |
1212 |
while(node_chain) { |
while(node_chain) { |
1213 |
if(node_chain->node == map_item->node) { |
if(node_chain->node == map_item->object.node) { |
1214 |
printf(" requested item is part of selected way\n"); |
printf(" requested item is part of selected way\n"); |
1215 |
return TRUE; |
return TRUE; |
1216 |
} |
} |
1238 |
return FALSE; |
return FALSE; |
1239 |
} |
} |
1240 |
|
|
1241 |
if(map->selected.type == MAP_TYPE_ILLEGAL) { |
if(map->selected.object.type == ILLEGAL) { |
1242 |
printf(" nothing is selected\n"); |
printf(" nothing is selected\n"); |
1243 |
return FALSE; |
return FALSE; |
1244 |
} |
} |
1245 |
|
|
1246 |
/* clicked the highlight directly */ |
/* clicked the highlight directly */ |
1247 |
if(map_item->type != MAP_TYPE_WAY) { |
if(map_item->object.type != WAY) { |
1248 |
printf(" didn't click way\n"); |
printf(" didn't click way\n"); |
1249 |
return FALSE; |
return FALSE; |
1250 |
} |
} |
1251 |
|
|
1252 |
if(map->selected.type == MAP_TYPE_WAY) { |
if(map->selected.object.type == WAY) { |
1253 |
printf(" selected item is a way\n"); |
printf(" selected item is a way\n"); |
1254 |
|
|
1255 |
if(map_item->way == map->selected.way) { |
if(map_item->object.way == map->selected.object.way) { |
1256 |
printf(" requested item is a selected way\n"); |
printf(" requested item is a selected way\n"); |
1257 |
return TRUE; |
return TRUE; |
1258 |
} |
} |
1267 |
|
|
1268 |
void map_highlight_refresh(appdata_t *appdata) { |
void map_highlight_refresh(appdata_t *appdata) { |
1269 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
1270 |
map_item_t old = map->selected; |
object_t old = map->selected.object; |
1271 |
|
|
1272 |
printf("type to refresh is %d\n", old.type); |
printf("type to refresh is %d\n", old.type); |
1273 |
if(old.type == MAP_TYPE_ILLEGAL) |
if(old.type == ILLEGAL) |
1274 |
return; |
return; |
1275 |
|
|
1276 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1277 |
map_item_select(appdata, &old); |
map_object_select(appdata, &old); |
1278 |
} |
} |
1279 |
|
|
1280 |
void map_way_delete(appdata_t *appdata, way_t *way) { |
void map_way_delete(appdata_t *appdata, way_t *way) { |
1281 |
printf("deleting way #%ld from map and osm\n", way->id); |
printf("deleting way #" ITEM_ID_FORMAT " from map and osm\n", way->id); |
1282 |
|
|
1283 |
/* remove it visually from the screen */ |
/* remove it visually from the screen */ |
1284 |
map_item_chain_destroy(&way->map_item_chain); |
map_item_chain_destroy(&way->map_item_chain); |
1302 |
/* problem: on_item may be the highlight itself! So store it! */ |
/* problem: on_item may be the highlight itself! So store it! */ |
1303 |
map_item_t map_item; |
map_item_t map_item; |
1304 |
if(map->pen_down.on_item) map_item = *map->pen_down.on_item; |
if(map->pen_down.on_item) map_item = *map->pen_down.on_item; |
1305 |
else map_item.type = MAP_TYPE_ILLEGAL; |
else map_item.object.type = ILLEGAL; |
1306 |
|
|
1307 |
/* if we aready have something selected, then de-select it */ |
/* if we aready have something selected, then de-select it */ |
1308 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1309 |
|
|
1310 |
/* select the clicked item (if there was one) */ |
/* select the clicked item (if there was one) */ |
1311 |
if(map_item.type != MAP_TYPE_ILLEGAL) { |
if(map_item.object.type != ILLEGAL) { |
1312 |
switch(map_item.type) { |
switch(map_item.object.type) { |
1313 |
case MAP_TYPE_NODE: |
case NODE: |
1314 |
map_node_select(appdata, map_item.node); |
map_node_select(appdata, map_item.object.node); |
1315 |
break; |
break; |
1316 |
|
|
1317 |
case MAP_TYPE_WAY: |
case WAY: |
1318 |
map_way_select(appdata, map_item.way); |
map_way_select(appdata, map_item.object.way); |
1319 |
break; |
break; |
1320 |
|
|
1321 |
default: |
default: |
1322 |
g_assert((map_item.type == MAP_TYPE_NODE) || |
g_assert((map_item.object.type == NODE) || |
1323 |
(map_item.type == MAP_TYPE_WAY)); |
(map_item.object.type == WAY)); |
1324 |
break; |
break; |
1325 |
} |
} |
1326 |
} |
} |
1340 |
/* in idle mode the dragged node is not highlighted */ |
/* in idle mode the dragged node is not highlighted */ |
1341 |
case MAP_ACTION_IDLE: |
case MAP_ACTION_IDLE: |
1342 |
g_assert(map->pen_down.on_item); |
g_assert(map->pen_down.on_item); |
1343 |
g_assert(map->pen_down.on_item->type == MAP_TYPE_NODE); |
g_assert(map->pen_down.on_item->object.type == NODE); |
1344 |
cur_node = map->pen_down.on_item->node; |
cur_node = map->pen_down.on_item->object.node; |
1345 |
break; |
break; |
1346 |
|
|
1347 |
default: |
default: |
1356 |
/* don't highlight the dragged node itself and don't highlight */ |
/* don't highlight the dragged node itself and don't highlight */ |
1357 |
/* deleted ones */ |
/* deleted ones */ |
1358 |
if((node != cur_node) && (!(node->flags & OSM_FLAG_DELETED))) { |
if((node != cur_node) && (!(node->flags & OSM_FLAG_DELETED))) { |
1359 |
gint nx = x - node->lpos.x; |
gint nx = abs(x - node->lpos.x); |
1360 |
gint ny = y - node->lpos.y; |
gint ny = abs(y - node->lpos.y); |
1361 |
|
|
1362 |
if((nx < map->style->node.radius) && (ny < map->style->node.radius) && |
if((nx < map->style->node.radius) && (ny < map->style->node.radius) && |
1363 |
(nx*nx + ny*ny < map->style->node.radius * map->style->node.radius)) |
(nx*nx + ny*ny < map->style->node.radius * map->style->node.radius)) |
1371 |
if(!map->touchnode && map->action.way) { |
if(!map->touchnode && map->action.way) { |
1372 |
node_chain_t *chain = map->action.way->node_chain; |
node_chain_t *chain = map->action.way->node_chain; |
1373 |
while(!map->touchnode && chain && chain->next) { |
while(!map->touchnode && chain && chain->next) { |
1374 |
gint nx = x - chain->node->lpos.x; |
gint nx = abs(x - chain->node->lpos.x); |
1375 |
gint ny = y - chain->node->lpos.y; |
gint ny = abs(y - chain->node->lpos.y); |
1376 |
|
|
1377 |
if((nx < map->style->node.radius) && (ny < map->style->node.radius) && |
if((nx < map->style->node.radius) && (ny < map->style->node.radius) && |
1378 |
(nx*nx + ny*ny < map->style->node.radius * map->style->node.radius)) |
(nx*nx + ny*ny < map->style->node.radius * map->style->node.radius)) |
1393 |
map->pen_down.at.y = y; |
map->pen_down.at.y = y; |
1394 |
map->pen_down.drag = FALSE; // don't assume drag yet |
map->pen_down.drag = FALSE; // don't assume drag yet |
1395 |
|
|
|
#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 |
|
|
|
|
1396 |
/* determine wether this press was on an item */ |
/* determine wether this press was on an item */ |
1397 |
map->pen_down.on_item = map_real_item_at(map, x, y); |
map->pen_down.on_item = map_real_item_at(map, x, y); |
1398 |
|
|
1464 |
map_item_t old_sel = map->selected; |
map_item_t old_sel = map->selected; |
1465 |
map_handle_click(map->appdata, map); |
map_handle_click(map->appdata, map); |
1466 |
|
|
1467 |
if((old_sel.type != MAP_TYPE_ILLEGAL) && |
if((old_sel.object.type != ILLEGAL) && |
1468 |
(old_sel.type == map->selected.type) && |
(old_sel.object.type == map->selected.object.type) && |
1469 |
(old_sel.ptr == map->selected.ptr)) { |
(old_sel.object.ptr == map->selected.object.ptr)) { |
1470 |
printf("re-selected same item of type %d, " |
printf("re-selected same item of type %d, " |
1471 |
"pushing it to the bottom\n", old_sel.type); |
"pushing it to the bottom\n", old_sel.object.type); |
1472 |
|
|
1473 |
if(!map->selected.item) { |
if(!map->selected.item) { |
1474 |
printf(" item has no visible representation to push\n"); |
printf(" item has no visible representation to push\n"); |
1585 |
/* reduce update frequency on hildon to keep screen update fluid */ |
/* reduce update frequency on hildon to keep screen update fluid */ |
1586 |
static guint32 last_time = 0; |
static guint32 last_time = 0; |
1587 |
|
|
1588 |
if(event->time - last_time < 100) return FALSE; |
if(event->time - last_time < 250) return FALSE; |
1589 |
last_time = event->time; |
last_time = event->time; |
1590 |
#endif |
#endif |
1591 |
|
|
1592 |
if(!map->pen_down.is) |
if(!map->pen_down.is) |
1593 |
return FALSE; |
return FALSE; |
1594 |
|
|
1595 |
#ifdef USE_GNOMECANVAS |
#ifndef USE_GOOCANVAS |
1596 |
/* handle hints, hints are handled by goocanvas directly */ |
/* handle hints, hints are handled by goocanvas directly */ |
1597 |
if(event->is_hint) |
if(event->is_hint) |
1598 |
gdk_window_get_pointer(event->window, &x, &y, &state); |
gdk_window_get_pointer(event->window, &x, &y, &state); |
1637 |
|
|
1638 |
case MAP_ACTION_WAY_NODE_ADD: |
case MAP_ACTION_WAY_NODE_ADD: |
1639 |
map_hl_cursor_clear(map); |
map_hl_cursor_clear(map); |
1640 |
map_item_t *item = map_real_item_at(map, x, y); |
map_item_t *item = map_item_at(map, x, y); |
1641 |
if(item) map_edit_way_node_add_highlight(map, item, x, y); |
if(item) map_edit_way_node_add_highlight(map, item, x, y); |
1642 |
break; |
break; |
1643 |
|
|
1644 |
case MAP_ACTION_WAY_CUT: |
case MAP_ACTION_WAY_CUT: |
1645 |
map_hl_cursor_clear(map); |
map_hl_cursor_clear(map); |
1646 |
item = map_real_item_at(map, x, y); |
item = map_item_at(map, x, y); |
1647 |
if(item) map_edit_way_cut_highlight(map, item, x, y); |
if(item) map_edit_way_cut_highlight(map, item, x, y); |
1648 |
break; |
break; |
1649 |
|
|
1730 |
return FALSE; |
return FALSE; |
1731 |
} |
} |
1732 |
|
|
1733 |
|
void map_state_reset(map_state_t *state) { |
1734 |
|
if(!state) return; |
1735 |
|
|
1736 |
|
state->zoom = 0.25; |
1737 |
|
state->detail = 1.0; |
1738 |
|
|
1739 |
|
/* todo: try to scroll to center of screen */ |
1740 |
|
state->scroll_offset.x = 0; |
1741 |
|
state->scroll_offset.y = 0; |
1742 |
|
} |
1743 |
|
|
1744 |
|
map_state_t *map_state_new(void) { |
1745 |
|
map_state_t *state = g_new0(map_state_t, 1); |
1746 |
|
map_state_reset(state); |
1747 |
|
return state; |
1748 |
|
} |
1749 |
|
|
1750 |
GtkWidget *map_new(appdata_t *appdata) { |
GtkWidget *map_new(appdata_t *appdata) { |
1751 |
map_t *map = appdata->map = g_new0(map_t, 1); |
map_t *map = appdata->map = g_new0(map_t, 1); |
1752 |
|
|
1762 |
map->state = appdata->project->map_state; |
map->state = appdata->project->map_state; |
1763 |
} else { |
} else { |
1764 |
printf("Creating new map state\n"); |
printf("Creating new map state\n"); |
1765 |
map->state = g_new0(map_state_t, 1); |
map->state = map_state_new(); |
|
map->state->zoom = 0.25; |
|
1766 |
} |
} |
1767 |
|
|
1768 |
map->state->refcount++; |
map->state->refcount++; |
1772 |
map->appdata = appdata; |
map->appdata = appdata; |
1773 |
map->action.type = MAP_ACTION_IDLE; |
map->action.type = MAP_ACTION_IDLE; |
1774 |
|
|
1775 |
#ifdef USE_GNOMECANVAS |
map->canvas = canvas_new(); |
|
map->canvas = gnome_canvas_new_aa(); // _aa |
|
|
|
|
|
/* 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); |
|
1776 |
|
|
1777 |
gtk_widget_modify_bg(map->canvas, GTK_STATE_NORMAL, |
GtkWidget *canvas_widget = canvas_get_widget(map->canvas); |
|
&map->canvas->style->white); |
|
1778 |
|
|
1779 |
#else |
gtk_widget_set_events(canvas_widget, |
|
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 >> 8, 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); |
|
|
|
|
|
#endif |
|
|
|
|
|
gtk_widget_set_events(map->canvas, |
|
1780 |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_PRESS_MASK |
1781 |
| GDK_BUTTON_RELEASE_MASK |
| GDK_BUTTON_RELEASE_MASK |
1782 |
| GDK_SCROLL_MASK |
| GDK_SCROLL_MASK |
1783 |
| GDK_POINTER_MOTION_MASK |
| GDK_POINTER_MOTION_MASK |
1784 |
| GDK_POINTER_MOTION_HINT_MASK); |
| GDK_POINTER_MOTION_HINT_MASK); |
1785 |
|
|
1786 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1787 |
"button_press_event", G_CALLBACK(map_button_event), appdata); |
"button_press_event", G_CALLBACK(map_button_event), appdata); |
1788 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1789 |
"button_release_event", G_CALLBACK(map_button_event), appdata); |
"button_release_event", G_CALLBACK(map_button_event), appdata); |
1790 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1791 |
"motion_notify_event", G_CALLBACK(map_motion_notify_event), appdata); |
"motion_notify_event", G_CALLBACK(map_motion_notify_event), appdata); |
1792 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1793 |
"scroll_event", G_CALLBACK(map_scroll_event), appdata); |
"scroll_event", G_CALLBACK(map_scroll_event), appdata); |
1794 |
|
|
1795 |
gtk_signal_connect(GTK_OBJECT(map->canvas), |
gtk_signal_connect(GTK_OBJECT(canvas_widget), |
1796 |
"destroy", G_CALLBACK(map_destroy_event), appdata); |
"destroy", G_CALLBACK(map_destroy_event), appdata); |
1797 |
|
|
1798 |
return map->canvas; |
return canvas_widget; |
1799 |
} |
} |
1800 |
|
|
1801 |
void map_init(appdata_t *appdata) { |
void map_init(appdata_t *appdata) { |
1802 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
1803 |
|
|
1804 |
|
/* update canvas background color */ |
1805 |
|
canvas_set_background(map->canvas, map->style->background.color); |
1806 |
|
|
1807 |
/* set initial zoom */ |
/* set initial zoom */ |
1808 |
map_set_zoom(map, map->state->zoom, FALSE); |
map_set_zoom(map, map->state->zoom, FALSE); |
1809 |
josm_elemstyles_colorize_world(map->style, appdata->osm); |
josm_elemstyles_colorize_world(map->style, appdata->osm); |
1817 |
mult*appdata->osm->bounds->max.x, |
mult*appdata->osm->bounds->max.x, |
1818 |
mult*appdata->osm->bounds->max.y); |
mult*appdata->osm->bounds->max.y); |
1819 |
|
|
1820 |
printf("restore scroll offsets %d/%d\n", |
printf("restore scroll position %d/%d\n", |
1821 |
map->state->scroll_offset.x, map->state->scroll_offset.y); |
map->state->scroll_offset.x, map->state->scroll_offset.y); |
1822 |
|
|
1823 |
canvas_scroll_to(map->canvas, |
map_limit_scroll(map, CANVAS_UNIT_METER, |
1824 |
map->state->scroll_offset.x, map->state->scroll_offset.y); |
&map->state->scroll_offset.x, &map->state->scroll_offset.y); |
1825 |
|
canvas_scroll_to(map->canvas, CANVAS_UNIT_METER, |
1826 |
|
map->state->scroll_offset.x, map->state->scroll_offset.y); |
1827 |
} |
} |
1828 |
|
|
1829 |
|
|
1830 |
void map_item_set_flags(map_item_t *map_item, int set, int clr) { |
void map_clear(appdata_t *appdata, gint group_mask) { |
|
|
|
|
switch(map_item->type) { |
|
|
case MAP_TYPE_NODE: |
|
|
map_item->node->flags |= set; |
|
|
map_item->node->flags &= ~clr; |
|
|
break; |
|
|
|
|
|
case MAP_TYPE_WAY: |
|
|
map_item->way->flags |= set; |
|
|
map_item->way->flags &= ~clr; |
|
|
break; |
|
|
|
|
|
default: |
|
|
g_assert(0); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
void map_clear(appdata_t *appdata, gint layer_mask) { |
|
1831 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
1832 |
|
|
1833 |
printf("freeing map contents\n"); |
printf("freeing map contents\n"); |
1837 |
/* remove a possibly existing highlight */ |
/* remove a possibly existing highlight */ |
1838 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1839 |
|
|
1840 |
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 |
|
|
} |
|
1841 |
} |
} |
1842 |
|
|
1843 |
void map_paint(appdata_t *appdata) { |
void map_paint(appdata_t *appdata) { |
1874 |
|
|
1875 |
/* remember if there was a way selected */ |
/* remember if there was a way selected */ |
1876 |
way_t *way_sel = NULL; |
way_t *way_sel = NULL; |
1877 |
if(appdata->map->selected.type == MAP_TYPE_WAY) |
if(appdata->map->selected.object.type == WAY) |
1878 |
way_sel = appdata->map->selected.way; |
way_sel = appdata->map->selected.object.way; |
1879 |
|
|
1880 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1881 |
map_edit_way_add_begin(appdata->map, way_sel); |
map_edit_way_add_begin(appdata->map, way_sel); |
1950 |
/* save changes to bg_offset in project */ |
/* save changes to bg_offset in project */ |
1951 |
appdata->project->wms_offset.x = map->bg.offset.x; |
appdata->project->wms_offset.x = map->bg.offset.x; |
1952 |
appdata->project->wms_offset.y = map->bg.offset.y; |
appdata->project->wms_offset.y = map->bg.offset.y; |
|
appdata->project->dirty = TRUE; |
|
1953 |
break; |
break; |
1954 |
|
|
1955 |
default: |
default: |
1973 |
/* deleting the selected item de-selects it ... */ |
/* deleting the selected item de-selects it ... */ |
1974 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
1975 |
|
|
1976 |
switch(item.type) { |
undo_remember_delete(appdata, &item.object); |
1977 |
case MAP_TYPE_NODE: |
|
1978 |
printf("request to delete node #%ld\n", item.node->id); |
switch(item.object.type) { |
1979 |
|
case NODE: |
1980 |
|
printf("request to delete node #" ITEM_ID_FORMAT "\n", |
1981 |
|
item.object.node->id); |
1982 |
|
|
1983 |
/* check if this node is part of a way with two nodes only. */ |
/* check if this node is part of a way with two nodes only. */ |
1984 |
/* we cannot delete this as this would also delete the way */ |
/* we cannot delete this as this would also delete the way */ |
1985 |
way_chain_t *way_chain = osm_node_to_way(appdata->osm, item.node); |
way_chain_t *way_chain = osm_node_to_way(appdata->osm, item.object.node); |
1986 |
if(way_chain) { |
if(way_chain) { |
1987 |
gboolean short_way = FALSE; |
gboolean short_way = FALSE; |
1988 |
|
|
2008 |
} |
} |
2009 |
|
|
2010 |
/* remove it visually from the screen */ |
/* remove it visually from the screen */ |
2011 |
map_item_chain_destroy(&item.node->map_item_chain); |
map_item_chain_destroy(&item.object.node->map_item_chain); |
2012 |
|
|
2013 |
/* and mark it "deleted" in the database */ |
/* and mark it "deleted" in the database */ |
2014 |
osm_node_remove_from_relation(appdata->osm, item.node); |
osm_node_remove_from_relation(appdata->osm, item.object.node); |
2015 |
way_chain_t *chain = osm_node_delete(appdata->osm, |
way_chain_t *chain = osm_node_delete(appdata->osm, |
2016 |
&appdata->icon, item.node, FALSE, TRUE); |
&appdata->icon, item.object.node, FALSE, TRUE); |
2017 |
|
|
2018 |
/* redraw all affected ways */ |
/* redraw all affected ways */ |
2019 |
while(chain) { |
while(chain) { |
2026 |
map_way_delete(appdata, chain->way); |
map_way_delete(appdata, chain->way); |
2027 |
} else { |
} else { |
2028 |
map_item_t item; |
map_item_t item; |
2029 |
item.type = MAP_TYPE_WAY; |
item.object.type = WAY; |
2030 |
item.way = chain->way; |
item.object.way = chain->way; |
2031 |
map_item_redraw(appdata, &item); |
map_item_redraw(appdata, &item); |
2032 |
} |
} |
2033 |
|
|
2038 |
|
|
2039 |
break; |
break; |
2040 |
|
|
2041 |
case MAP_TYPE_WAY: |
case WAY: |
2042 |
printf("request to delete way #%ld\n", item.way->id); |
printf("request to delete way #" ITEM_ID_FORMAT "\n", item.object.way->id); |
2043 |
map_way_delete(appdata, item.way); |
map_way_delete(appdata, item.object.way); |
2044 |
break; |
break; |
2045 |
|
|
2046 |
default: |
default: |
2047 |
g_assert((item.type == MAP_TYPE_NODE) || |
g_assert((item.object.type == NODE) || |
2048 |
(item.type == MAP_TYPE_WAY)); |
(item.object.type == WAY)); |
2049 |
break; |
break; |
2050 |
} |
} |
2051 |
} |
} |
2052 |
|
|
2053 |
/* ----------------------- track related stuff ----------------------- */ |
/* ----------------------- track related stuff ----------------------- */ |
2054 |
|
|
2055 |
|
static gboolean track_pos2lpos(bounds_t *bounds, pos_t *pos, lpos_t *lpos) { |
2056 |
|
pos2lpos(bounds, pos, lpos); |
2057 |
|
|
2058 |
|
/* check if point is within bounds */ |
2059 |
|
return ((lpos->x >= bounds->min.x) && (lpos->x <= bounds->max.x) && |
2060 |
|
(lpos->y >= bounds->min.y) && (lpos->y <= bounds->max.y)); |
2061 |
|
} |
2062 |
|
|
2063 |
void map_track_draw_seg(map_t *map, track_seg_t *seg) { |
void map_track_draw_seg(map_t *map, track_seg_t *seg) { |
2064 |
|
bounds_t *bounds = map->appdata->osm->bounds; |
2065 |
|
|
2066 |
/* a track_seg needs at least 2 points to be drawn */ |
/* a track_seg needs at least 2 points to be drawn */ |
2067 |
guint pnum = track_seg_points(seg); |
guint pnum = track_seg_points(seg); |
2068 |
printf("seg of length %d\n", pnum); |
printf("seg of length %d\n", pnum); |
2069 |
|
|
2070 |
if(pnum == 1) { |
if(!pnum) |
2071 |
g_assert(!seg->item); |
return; |
2072 |
|
|
2073 |
seg->item = canvas_circle_new(map, CANVAS_GROUP_TRACK, |
/* nothing should have been drawn by now ... */ |
2074 |
seg->track_point->lpos.x, seg->track_point->lpos.y, |
g_assert(!seg->item_chain); |
2075 |
map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR); |
|
2076 |
} |
track_item_chain_t **itemP = &seg->item_chain; |
2077 |
|
track_point_t *track_point = seg->track_point; |
2078 |
|
while(track_point) { |
2079 |
|
lpos_t lpos; |
2080 |
|
|
2081 |
|
/* skip all points not on screen */ |
2082 |
|
track_point_t *last = NULL; |
2083 |
|
while(track_point && !track_pos2lpos(bounds, &track_point->pos, &lpos)) { |
2084 |
|
last = track_point; |
2085 |
|
track_point = track_point->next; |
2086 |
|
} |
2087 |
|
|
2088 |
|
int visible = 0; |
2089 |
|
|
2090 |
|
/* count nodes that _are_ on screen */ |
2091 |
|
track_point_t *tmp = track_point; |
2092 |
|
while(tmp && track_pos2lpos(bounds, &tmp->pos, &lpos)) { |
2093 |
|
tmp = tmp->next; |
2094 |
|
visible++; |
2095 |
|
} |
2096 |
|
|
2097 |
|
/* actually start drawing with the last position that was offscreen */ |
2098 |
|
/* so the track nicely enters the viewing area */ |
2099 |
|
if(last) { |
2100 |
|
track_point = last; |
2101 |
|
visible++; |
2102 |
|
} |
2103 |
|
|
2104 |
|
/* also use last one that's offscreen to nicely leave the visible area */ |
2105 |
|
if(tmp && tmp->next) |
2106 |
|
visible++; |
2107 |
|
|
|
if(pnum > 1) { |
|
|
|
|
2108 |
/* allocate space for nodes */ |
/* allocate space for nodes */ |
2109 |
canvas_points_t *points = canvas_points_new(pnum); |
canvas_points_t *points = canvas_points_new(visible); |
2110 |
|
|
2111 |
int point = 0; |
printf("visible are %d\n", visible); |
2112 |
track_point_t *track_point = seg->track_point; |
int point; |
2113 |
while(track_point) { |
for(point=0;point<visible;point++) { |
2114 |
points->coords[point++] = track_point->lpos.x; |
track_pos2lpos(bounds, &track_point->pos, &lpos); |
2115 |
points->coords[point++] = track_point->lpos.y; |
|
2116 |
|
points->coords[2*point+0] = lpos.x; |
2117 |
|
points->coords[2*point+1] = lpos.y; |
2118 |
track_point = track_point->next; |
track_point = track_point->next; |
2119 |
} |
} |
|
|
|
|
/* there may be a circle (one point line) */ |
|
|
if(seg->item) |
|
|
canvas_item_destroy(seg->item); |
|
2120 |
|
|
2121 |
seg->item = canvas_polyline_new(map, CANVAS_GROUP_TRACK, |
*itemP = g_new0(track_item_chain_t, 1); |
2122 |
points, map->style->track.width, map->style->track.color); |
(*itemP)->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK, |
2123 |
|
points, map->style->track.width, map->style->track.color); |
2124 |
|
itemP = &(*itemP)->next; |
2125 |
|
|
2126 |
canvas_points_free(points); |
canvas_points_free(points); |
2127 |
} |
} |
2128 |
} |
} |
2129 |
|
|
2130 |
|
/* update the last visible fragment of this segment since a */ |
2131 |
|
/* gps position may have been added */ |
2132 |
void map_track_update_seg(map_t *map, track_seg_t *seg) { |
void map_track_update_seg(map_t *map, track_seg_t *seg) { |
2133 |
|
bounds_t *bounds = map->appdata->osm->bounds; |
2134 |
|
|
2135 |
|
printf("-- APPENDING TO TRACK --\n"); |
2136 |
|
|
2137 |
/* a track_seg needs at least 2 points to be drawn */ |
/* a track_seg needs at least 2 points to be drawn */ |
2138 |
guint pnum = track_seg_points(seg); |
guint pnum = track_seg_points(seg); |
2139 |
printf("seg of length %d\n", pnum); |
printf("seg of length %d\n", pnum); |
2140 |
|
|
2141 |
if(pnum > 1) { |
/* there are two cases: either the second last point was on screen */ |
2142 |
|
/* or it wasn't. We'll have to start a new screen item if the latter */ |
2143 |
|
/* is the case */ |
2144 |
|
|
2145 |
|
/* search last point */ |
2146 |
|
track_point_t *begin = seg->track_point, *second_last = seg->track_point; |
2147 |
|
lpos_t lpos; |
2148 |
|
while(second_last && second_last->next && second_last->next->next) { |
2149 |
|
if(!track_pos2lpos(bounds, &second_last->pos, &lpos)) |
2150 |
|
begin = second_last; |
2151 |
|
|
2152 |
|
second_last = second_last->next; |
2153 |
|
} |
2154 |
|
track_point_t *last = second_last->next; |
2155 |
|
|
2156 |
|
/* since we are updating an existing track, it sure has at least two */ |
2157 |
|
/* points, second_last must be valid and its "next" (last) also */ |
2158 |
|
g_assert(second_last); |
2159 |
|
g_assert(last); |
2160 |
|
|
2161 |
|
/* check if the last and second_last points are visible */ |
2162 |
|
gboolean last_is_visible = |
2163 |
|
track_pos2lpos(bounds, &last->pos, &lpos); |
2164 |
|
gboolean second_last_is_visible = |
2165 |
|
track_pos2lpos(bounds, &second_last->pos, &lpos); |
2166 |
|
|
2167 |
|
/* if both are invisible, then nothing has changed on screen */ |
2168 |
|
if(!last_is_visible && !second_last_is_visible) { |
2169 |
|
printf("second_last and last entry are invisible -> doing nothing\n"); |
2170 |
|
return; |
2171 |
|
} |
2172 |
|
|
2173 |
|
/* search last element in item chain */ |
2174 |
|
track_item_chain_t *item = seg->item_chain; |
2175 |
|
while(item && item->next) |
2176 |
|
item = item->next; |
2177 |
|
|
2178 |
|
if(second_last_is_visible) { |
2179 |
|
/* there must be something already on the screen and there must */ |
2180 |
|
/* be visible nodes in the chain */ |
2181 |
|
g_assert(item); |
2182 |
|
g_assert(begin); |
2183 |
|
|
2184 |
|
printf("second_last is visible -> append\n"); |
2185 |
|
|
2186 |
/* allocate space for nodes */ |
/* count points to be placed */ |
2187 |
canvas_points_t *points = canvas_points_new(pnum); |
int npoints = 0; |
2188 |
|
track_point_t *tmp = begin; |
2189 |
|
while(tmp) { |
2190 |
|
tmp = tmp->next; |
2191 |
|
npoints++; |
2192 |
|
} |
2193 |
|
|
2194 |
|
printf("updating last segment to %d points\n", npoints); |
2195 |
|
|
2196 |
|
canvas_points_t *points = canvas_points_new(npoints); |
2197 |
|
|
2198 |
|
gint point = 0; |
2199 |
|
while(begin) { |
2200 |
|
track_pos2lpos(bounds, &begin->pos, &lpos); |
2201 |
|
canvas_point_set_pos(points, point++, &lpos); |
2202 |
|
begin = begin->next; |
2203 |
|
} |
2204 |
|
|
2205 |
int point = 0; |
canvas_item_set_points(item->item, points); |
2206 |
track_point_t *track_point = seg->track_point; |
canvas_points_free(points); |
2207 |
while(track_point) { |
|
2208 |
canvas_point_set_pos(points, point++, &track_point->lpos); |
} else { |
2209 |
track_point = track_point->next; |
printf("second last is invisible -> start new screen segment\n"); |
2210 |
|
|
2211 |
|
/* the search for the "begin" ends with the second_last item */ |
2212 |
|
/* verify the last one also */ |
2213 |
|
if(begin->next && !track_pos2lpos(bounds, &begin->next->pos, &lpos)) |
2214 |
|
begin = begin->next; |
2215 |
|
|
2216 |
|
item->next = g_new0(track_item_chain_t, 1); |
2217 |
|
item = item->next; |
2218 |
|
|
2219 |
|
/* count points to be placed */ |
2220 |
|
int npoints = 0; |
2221 |
|
track_point_t *tmp = begin; |
2222 |
|
while(tmp) { |
2223 |
|
tmp = tmp->next; |
2224 |
|
npoints++; |
2225 |
} |
} |
2226 |
|
|
2227 |
|
printf("attaching new segment with %d points\n", npoints); |
2228 |
|
|
2229 |
|
canvas_points_t *points = canvas_points_new(npoints); |
2230 |
|
|
2231 |
|
gint point = 0; |
2232 |
|
while(begin) { |
2233 |
|
track_pos2lpos(bounds, &begin->pos, &lpos); |
2234 |
|
canvas_point_set_pos(points, point++, &lpos); |
2235 |
|
begin = begin->next; |
2236 |
|
} |
2237 |
|
|
2238 |
|
item->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK, |
2239 |
|
points, map->style->track.width, map->style->track.color); |
2240 |
|
|
|
g_assert(seg->item); |
|
|
canvas_item_set_points(seg->item, points); |
|
2241 |
canvas_points_free(points); |
canvas_points_free(points); |
2242 |
} |
} |
2243 |
|
|
2244 |
} |
} |
2245 |
|
|
2246 |
void map_track_draw(map_t *map, track_t *track) { |
void map_track_draw(map_t *map, track_t *track) { |
2263 |
/* remove all segments */ |
/* remove all segments */ |
2264 |
track_seg_t *seg = track->track_seg; |
track_seg_t *seg = track->track_seg; |
2265 |
while(seg) { |
while(seg) { |
2266 |
if(seg->item) { |
track_item_chain_t *item = seg->item_chain; |
2267 |
canvas_item_destroy(seg->item); |
while(item) { |
2268 |
seg->item = NULL; |
track_item_chain_t *next = item->next; |
2269 |
|
canvas_item_destroy(item->item); |
2270 |
|
item = next; |
2271 |
} |
} |
2272 |
|
|
2273 |
|
seg->item_chain = NULL; |
2274 |
seg = seg->next; |
seg = seg->next; |
2275 |
} |
} |
2276 |
} |
} |
2277 |
|
|
2278 |
void map_track_pos(appdata_t *appdata, lpos_t *lpos) { |
void map_track_pos(appdata_t *appdata, pos_t *pos) { |
2279 |
if(appdata->track.gps_item) { |
if(appdata->track.gps_item) { |
2280 |
canvas_item_destroy(appdata->track.gps_item); |
canvas_item_destroy(appdata->track.gps_item); |
2281 |
appdata->track.gps_item = NULL; |
appdata->track.gps_item = NULL; |
2282 |
} |
} |
2283 |
|
|
2284 |
if(lpos) |
if(pos) { |
2285 |
appdata->track.gps_item = canvas_circle_new(appdata->map, CANVAS_GROUP_GPS, |
lpos_t lpos; |
2286 |
lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0, |
pos2lpos(appdata->osm->bounds, pos, &lpos); |
2287 |
|
|
2288 |
|
appdata->track.gps_item = |
2289 |
|
canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS, |
2290 |
|
lpos.x, lpos.y, appdata->map->style->track.width/2.0, 0, |
2291 |
appdata->map->style->track.gps_color, NO_COLOR); |
appdata->map->style->track.gps_color, NO_COLOR); |
2292 |
|
} |
2293 |
} |
} |
2294 |
|
|
2295 |
/* ------------------- map background ------------------ */ |
/* ------------------- map background ------------------ */ |
2330 |
map->bg.scale.y = (float)(bounds->max.y - bounds->min.y)/ |
map->bg.scale.y = (float)(bounds->max.y - bounds->min.y)/ |
2331 |
(float)gdk_pixbuf_get_height(map->bg.pix); |
(float)gdk_pixbuf_get_height(map->bg.pix); |
2332 |
|
|
2333 |
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, |
2334 |
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); |
2335 |
|
|
2336 |
canvas_item_destroy_connect(map->bg.item, |
canvas_item_destroy_connect(map->bg.item, |
2344 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
2345 |
if(!map) return; |
if(!map) return; |
2346 |
|
|
2347 |
if(map->selected.type != MAP_TYPE_WAY) { |
if(map->selected.object.type != WAY) { |
2348 |
printf("selected item is not a way\n"); |
printf("selected item is not a way\n"); |
2349 |
return; |
return; |
2350 |
} |
} |
2351 |
|
|
2352 |
way_t *way = map->selected.way; |
way_t *way = map->selected.object.way; |
2353 |
printf("hiding way #%ld\n", way->id); |
printf("hiding way #" ITEM_ID_FORMAT "\n", way->id); |
2354 |
|
|
2355 |
map_item_deselect(appdata); |
map_item_deselect(appdata); |
2356 |
way->flags |= OSM_FLAG_HIDDEN; |
way->flags |= OSM_FLAG_HIDDEN; |
2375 |
|
|
2376 |
gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE); |
gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE); |
2377 |
} |
} |
2378 |
|
|
2379 |
|
static void map_detail_change(map_t *map, float detail) { |
2380 |
|
appdata_t *appdata = map->appdata; |
2381 |
|
|
2382 |
|
/* deselecting anything allows us not to care about automatic deselection */ |
2383 |
|
/* as well as items becoming invisible by the detail change */ |
2384 |
|
map_item_deselect(appdata); |
2385 |
|
|
2386 |
|
map->state->detail = detail; |
2387 |
|
printf("changing detail factor to %f\n", map->state->detail); |
2388 |
|
|
2389 |
|
banner_busy_start(appdata, 1, _("Redrawing")); |
2390 |
|
map_clear(appdata, MAP_LAYER_OBJECTS_ONLY); |
2391 |
|
map_paint(appdata); |
2392 |
|
banner_busy_stop(appdata); |
2393 |
|
} |
2394 |
|
|
2395 |
|
#define DETAIL_STEP 1.5 |
2396 |
|
|
2397 |
|
void map_detail_increase(map_t *map) { |
2398 |
|
if(!map) return; |
2399 |
|
map_detail_change(map, map->state->detail * DETAIL_STEP); |
2400 |
|
} |
2401 |
|
|
2402 |
|
void map_detail_decrease(map_t *map) { |
2403 |
|
if(!map) return; |
2404 |
|
map_detail_change(map, map->state->detail / DETAIL_STEP); |
2405 |
|
} |
2406 |
|
|
2407 |
|
void map_detail_normal(map_t *map) { |
2408 |
|
if(!map) return; |
2409 |
|
map_detail_change(map, 1.0); |
2410 |
|
} |
2411 |
|
|
2412 |
// vim:et:ts=8:sw=2:sts=2:ai |
// vim:et:ts=8:sw=2:sts=2:ai |