Diff of /trunk/src/map.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 153 by harbaum, Mon Mar 30 11:14:20 2009 UTC revision 180 by harbaum, Thu Jun 18 18:40:44 2009 UTC
# Line 30  static void map_statusbar(map_t *map, ma Line 30  static void map_statusbar(map_t *map, ma
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;      break;
45    
46    case MAP_TYPE_RELATION:    case RELATION:
47      item_str = "Relation";      item_str = "Relation";
48      id = map_item->relation->id;      id = map_item->object.relation->id;
49      tag = map_item->relation->tag;      tag = map_item->object.relation->tag;
50      break;      break;
51    
52    default:    default:
# Line 59  static void map_statusbar(map_t *map, ma Line 59  static void map_statusbar(map_t *map, ma
59    if(id == ID_ILLEGAL)    if(id == ID_ILLEGAL)
60      str = g_strdup_printf(_("Unknown item"));      str = g_strdup_printf(_("Unknown item"));
61    else {    else {
62      str = g_strdup_printf("%s #%ld", item_str, id);      str = g_strdup_printf("%s #" ITEM_ID_FORMAT, item_str, id);
63    
64      /* add some tags ... */      /* add some tags ... */
65      /*      /*
# Line 138  static void map_node_select(appdata_t *a Line 138  static void map_node_select(appdata_t *a
138    
139    g_assert(!map->highlight);    g_assert(!map->highlight);
140    
141    map_item->type      = MAP_TYPE_NODE;    map_item->object.type      = NODE;
142    map_item->node      = node;    map_item->object.node      = node;
143    map_item->highlight = FALSE;    map_item->highlight = FALSE;
144    
145    /* node may not have any visible representation at all */    /* node may not have any visible representation at all */
# Line 152  static void map_node_select(appdata_t *a Line 152  static void map_node_select(appdata_t *a
152    icon_bar_map_item_selected(appdata, map_item, TRUE);    icon_bar_map_item_selected(appdata, map_item, TRUE);
153    
154    /* highlight node */    /* highlight node */
155    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;
156    
157    /* 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 */
158    map_item_t *new_map_item = g_new0(map_item_t, 1);    map_item_t *new_map_item = g_new0(map_item_t, 1);
# Line 163  static void map_node_select(appdata_t *a Line 163  static void map_node_select(appdata_t *a
163    if(!node->ways) radius += map->style->node.border_radius;    if(!node->ways) radius += map->style->node.border_radius;
164    if(node->icon_buf && map->style->icon.enable &&    if(node->icon_buf && map->style->icon.enable &&
165       !appdata->settings->no_icons) {       !appdata->settings->no_icons) {
166      gint w = gdk_pixbuf_get_width(map_item->node->icon_buf);      gint w = gdk_pixbuf_get_width(map_item->object.node->icon_buf);
167      gint h = gdk_pixbuf_get_height(map_item->node->icon_buf);      gint h = gdk_pixbuf_get_height(map_item->object.node->icon_buf);
168      /* icons are technically square, so a radius slightly bigger */      /* icons are technically square, so a radius slightly bigger */
169      /* than sqrt(2)*MAX(w,h) should fit nicely */      /* than sqrt(2)*MAX(w,h) should fit nicely */
170      radius =  0.75 * map->style->icon.scale * ((w>h)?w:h);      radius = 0.75 * map->style->icon.scale * ((w>h)?w:h);
171    }    }
172    
173      radius *= map->state->detail;
174    map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,    map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,
175                      x, y, radius, map->style->highlight.color);                      x, y, radius, map->style->highlight.color);
176    
# Line 190  void map_way_select(appdata_t *appdata, Line 191  void map_way_select(appdata_t *appdata,
191    
192    g_assert(!map->highlight);    g_assert(!map->highlight);
193    
194    map_item->type      = MAP_TYPE_WAY;    map_item->object.type      = WAY;
195    map_item->way       = way;    map_item->object.way       = way;
196    map_item->highlight = FALSE;    map_item->highlight = FALSE;
197    map_item->item      = way->map_item_chain->map_item->item;    map_item->item      = way->map_item_chain->map_item->item;
198    
199    map_statusbar(map, map_item);    map_statusbar(map, map_item);
200    icon_bar_map_item_selected(appdata, map_item, TRUE);    icon_bar_map_item_selected(appdata, map_item, TRUE);
201    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;  
202    
203    node_chain_t *node_chain = map_item->way->node_chain;    gint arrow_width = ((map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?
204                          map->style->highlight.width + map_item->object.way->draw.bg.width/2:
205                          map->style->highlight.width + map_item->object.way->draw.width/2)
206        * map->state->detail;
207    
208      node_chain_t *node_chain = map_item->object.way->node_chain;
209    node_t *last = NULL;    node_t *last = NULL;
210    while(node_chain) {    while(node_chain) {
211      map_item_t item;      map_item_t item;
212      item.type = MAP_TYPE_NODE;      item.object.type = NODE;
213      item.node = node_chain->node;      item.object.node = node_chain->node;
214    
215      /* draw an arrow between every two nodes */      /* draw an arrow between every two nodes */
216      if(last) {      if(last) {
217        /* create a new map item for every arrow */        /* create a new map item for every arrow */
218        map_item_t *new_map_item = g_new0(map_item_t, 1);        map_item_t *new_map_item = g_new0(map_item_t, 1);
219        new_map_item->type = MAP_TYPE_WAY;        new_map_item->object.type = WAY;
220        new_map_item->way = way;        new_map_item->object.way = way;
221        new_map_item->highlight = TRUE;        new_map_item->highlight = TRUE;
222    
223        struct { float x, y;} center, diff;        struct { float x, y;} center, diff;
# Line 251  void map_way_select(appdata_t *appdata, Line 253  void map_way_select(appdata_t *appdata,
253    
254        /* create a new map item for every node */        /* create a new map item for every node */
255        map_item_t *new_map_item = g_new0(map_item_t, 1);        map_item_t *new_map_item = g_new0(map_item_t, 1);
256        new_map_item->type = MAP_TYPE_NODE;        new_map_item->object.type = NODE;
257        new_map_item->node = node_chain->node;        new_map_item->object.node = node_chain->node;
258        new_map_item->highlight = TRUE;        new_map_item->highlight = TRUE;
259    
260        gint x = node_chain->node->lpos.x;        gint x = node_chain->node->lpos.x;
261        gint y = node_chain->node->lpos.y;        gint y = node_chain->node->lpos.y;
262    
263        map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item,        map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item,
264                          x, y, map->style->node.radius,                          x, y, map->style->node.radius * map->state->detail,
265                          map->style->highlight.node_color);                          map->style->highlight.node_color);
266      }      }
267    
# Line 275  void map_way_select(appdata_t *appdata, Line 277  void map_way_select(appdata_t *appdata,
277      canvas_points_t *points = canvas_points_new(nodes);      canvas_points_t *points = canvas_points_new(nodes);
278    
279      int node = 0;      int node = 0;
280      node_chain = map_item->way->node_chain;      node_chain = map_item->object.way->node_chain;
281      while(node_chain) {      while(node_chain) {
282        canvas_point_set_pos(points, node++, &node_chain->node->lpos);        canvas_point_set_pos(points, node++, &node_chain->node->lpos);
283        node_chain = node_chain->next;        node_chain = node_chain->next;
# Line 287  void map_way_select(appdata_t *appdata, Line 289  void map_way_select(appdata_t *appdata,
289      new_map_item->highlight = TRUE;      new_map_item->highlight = TRUE;
290    
291      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,
292                  (map_item->way->draw.flags & OSM_DRAW_FLAG_BG)?                   ((map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?
293                  2*map->style->highlight.width + map_item->way->draw.bg.width:                   2*map->style->highlight.width + map_item->object.way->draw.bg.width:
294                  2*map->style->highlight.width + map_item->way->draw.width,                   2*map->style->highlight.width + map_item->object.way->draw.width)
295                  map->style->highlight.color);                  * map->state->detail, map->style->highlight.color);
296    
297      canvas_points_free(points);      canvas_points_free(points);
298    }    }
299  }  }
# Line 299  void map_way_select(appdata_t *appdata, Line 301  void map_way_select(appdata_t *appdata,
301  void map_relation_select(appdata_t *appdata, relation_t *relation) {  void map_relation_select(appdata_t *appdata, relation_t *relation) {
302    map_t *map = appdata->map;    map_t *map = appdata->map;
303    
304    printf("highlighting relation %ld\n", relation->id);    printf("highlighting relation "ITEM_ID_FORMAT"\n", relation->id);
305    
306    g_assert(!map->highlight);    g_assert(!map->highlight);
307    map_highlight_t **hl = &map->highlight;    map_highlight_t **hl = &map->highlight;
308    
309    map_item_t *map_item = &map->selected;    map_item_t *map_item = &map->selected;
310    map_item->type      = MAP_TYPE_RELATION;    map_item->object.type      = RELATION;
311    map_item->relation  = relation;    map_item->object.relation  = relation;
312    map_item->highlight = FALSE;    map_item->highlight = FALSE;
313    map_item->item      = NULL;    map_item->item      = NULL;
314    
# Line 318  void map_relation_select(appdata_t *appd Line 320  void map_relation_select(appdata_t *appd
320    while(member) {    while(member) {
321      canvas_item_t *item = NULL;      canvas_item_t *item = NULL;
322    
323      switch(member->type) {      switch(member->object.type) {
324    
325      case NODE: {      case NODE: {
326        node_t *node = member->node;        node_t *node = member->object.node;
327        printf("  -> node %ld\n", node->id);        printf("  -> node "ITEM_ID_FORMAT"\n", node->id);
328    
329        item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES_HL,        item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES_HL,
330                          node->lpos.x, node->lpos.y,                          node->lpos.x, node->lpos.y,
# Line 331  void map_relation_select(appdata_t *appd Line 333  void map_relation_select(appdata_t *appd
333        } break;        } break;
334    
335      case WAY: {      case WAY: {
336        way_t *way = member->way;        way_t *way = member->object.way;
337        /* a way needs at least 2 points to be drawn */        /* a way needs at least 2 points to be drawn */
338        guint nodes = osm_way_number_of_nodes(way);        guint nodes = osm_way_number_of_nodes(way);
339        if(nodes > 1) {        if(nodes > 1) {
# Line 374  void map_relation_select(appdata_t *appd Line 376  void map_relation_select(appdata_t *appd
376    }    }
377  }  }
378    
379  static void map_item_select(appdata_t *appdata, map_item_t *map_item) {  static void map_object_select(appdata_t *appdata, object_t *object) {
380    switch(map_item->type) {    switch(object->type) {
381    case MAP_TYPE_NODE:    case NODE:
382      map_node_select(appdata, map_item->node);      map_node_select(appdata, object->node);
383        break;
384      case WAY:
385        map_way_select(appdata, object->way);
386      break;      break;
387    case MAP_TYPE_WAY:    case RELATION:
388      map_way_select(appdata, map_item->way);      map_relation_select(appdata, object->relation);
389      break;      break;
390    default:    default:
391      g_assert((map_item->type == MAP_TYPE_NODE)||      g_assert((object->type == NODE)||(object->type == RELATION)||
392               (map_item->type == MAP_TYPE_WAY));               (object->type == WAY));
393      break;      break;
394    }    }
395  }  }
# Line 392  static void map_item_select(appdata_t *a Line 397  static void map_item_select(appdata_t *a
397  void map_item_deselect(appdata_t *appdata) {  void map_item_deselect(appdata_t *appdata) {
398    
399    /* save tags for "last" function in info dialog */    /* save tags for "last" function in info dialog */
400    if(appdata->map->selected.type == MAP_TYPE_NODE) {    if(appdata->map->selected.object.type == NODE) {
401      if(appdata->map->last_node_tags)      if(appdata->map->last_node_tags)
402        osm_tags_free(appdata->map->last_node_tags);        osm_tags_free(appdata->map->last_node_tags);
403    
404      appdata->map->last_node_tags =      appdata->map->last_node_tags =
405        osm_tags_copy(appdata->map->selected.node->tag, FALSE);        osm_tags_copy(appdata->map->selected.object.node->tag, FALSE);
406    } else if(appdata->map->selected.type == MAP_TYPE_WAY) {    } else if(appdata->map->selected.object.type == WAY) {
407      if(appdata->map->last_way_tags)      if(appdata->map->last_way_tags)
408        osm_tags_free(appdata->map->last_way_tags);        osm_tags_free(appdata->map->last_way_tags);
409    
410      appdata->map->last_way_tags =      appdata->map->last_way_tags =
411        osm_tags_copy(appdata->map->selected.way->tag, FALSE);        osm_tags_copy(appdata->map->selected.object.way->tag, FALSE);
412    }    }
413    
414    /* remove statusbar message */    /* remove statusbar message */
# Line 417  void map_item_deselect(appdata_t *appdat Line 422  void map_item_deselect(appdata_t *appdat
422    map_hl_remove(appdata);    map_hl_remove(appdata);
423    
424    /* forget about selection */    /* forget about selection */
425    appdata->map->selected.type = MAP_TYPE_ILLEGAL;    appdata->map->selected.object.type = ILLEGAL;
426  }  }
427    
428  /* called whenever a map item is to be destroyed */  /* called whenever a map item is to be destroyed */
# Line 429  static gint map_item_destroy_event(GtkWi Line 434  static gint map_item_destroy_event(GtkWi
434  #ifdef DESTROY_WAIT_FOR_GTK  #ifdef DESTROY_WAIT_FOR_GTK
435    /* remove item from nodes/ways map_item_chain */    /* remove item from nodes/ways map_item_chain */
436    map_item_chain_t **chain = NULL;    map_item_chain_t **chain = NULL;
437    if(map_item->type == MAP_TYPE_NODE)    if(map_item->object.type == NODE)
438      chain = &map_item->node->map_item_chain;      chain = &map_item->object.node->map_item_chain;
439    else if(map_item->type == MAP_TYPE_WAY)    else if(map_item->object.type == WAY)
440      chain = &map_item->way->map_item_chain;      chain = &map_item->object.way->map_item_chain;
441    
442    /* there must be a chain with content, otherwise things are broken */    /* there must be a chain with content, otherwise things are broken */
443    g_assert(chain);    g_assert(chain);
# Line 459  static canvas_item_t *map_node_new(map_t Line 464  static canvas_item_t *map_node_new(map_t
464                     gint width, canvas_color_t fill, canvas_color_t border) {                     gint width, canvas_color_t fill, canvas_color_t border) {
465    
466    map_item_t *map_item = g_new0(map_item_t, 1);    map_item_t *map_item = g_new0(map_item_t, 1);
467    map_item->type = MAP_TYPE_NODE;    map_item->object.type = NODE;
468    map_item->node = node;    map_item->object.node = node;
469    
470    if(!node->icon_buf || !map->style->icon.enable ||    if(!node->icon_buf || !map->style->icon.enable ||
471       map->appdata->settings->no_icons)       map->appdata->settings->no_icons)
# Line 469  static canvas_item_t *map_node_new(map_t Line 474  static canvas_item_t *map_node_new(map_t
474    else    else
475      map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES,      map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES,
476        node->icon_buf,        node->icon_buf,
477        node->lpos.x - map->style->icon.scale/2 *        node->lpos.x - map->style->icon.scale/2 * map->state->detail *
478                        gdk_pixbuf_get_width(node->icon_buf),                        gdk_pixbuf_get_width(node->icon_buf),
479        node->lpos.y - map->style->icon.scale/2 *        node->lpos.y - map->style->icon.scale/2 * map->state->detail *
480                        gdk_pixbuf_get_height(node->icon_buf),                        gdk_pixbuf_get_height(node->icon_buf),
481                map->style->icon.scale,map->style->icon.scale);                        map->state->detail * map->style->icon.scale,
482                          map->state->detail * map->style->icon.scale);
483    
484    canvas_item_set_zoom_max(map_item->item, node->zoom_max);    canvas_item_set_zoom_max(map_item->item,
485                               node->zoom_max / (2 * map->state->detail));
486    
487    /* attach map_item to nodes map_item_chain */    /* attach map_item to nodes map_item_chain */
488    map_item_chain_t **chain = &node->map_item_chain;    map_item_chain_t **chain = &node->map_item_chain;
# Line 497  static canvas_item_t *map_way_single_new Line 504  static canvas_item_t *map_way_single_new
504                     gint width, canvas_color_t fill, canvas_color_t border) {                     gint width, canvas_color_t fill, canvas_color_t border) {
505    
506    map_item_t *map_item = g_new0(map_item_t, 1);    map_item_t *map_item = g_new0(map_item_t, 1);
507    map_item->type = MAP_TYPE_WAY;    map_item->object.type = WAY;
508    map_item->way = way;    map_item->object.way = way;
509    map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_WAYS,    map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_WAYS,
510            way->node_chain->node->lpos.x, way->node_chain->node->lpos.y,            way->node_chain->node->lpos.x, way->node_chain->node->lpos.y,
511                                       radius, width, fill, border);                                       radius, width, fill, border);
# Line 523  static canvas_item_t *map_way_new(map_t Line 530  static canvas_item_t *map_way_new(map_t
530            way_t *way, canvas_points_t *points, gint width,            way_t *way, canvas_points_t *points, gint width,
531            canvas_color_t color, canvas_color_t fill_color) {            canvas_color_t color, canvas_color_t fill_color) {
532    map_item_t *map_item = g_new0(map_item_t, 1);    map_item_t *map_item = g_new0(map_item_t, 1);
533    map_item->type = MAP_TYPE_WAY;    map_item->object.type = WAY;
534    map_item->way = way;    map_item->object.way = way;
535    
536    if(way->draw.flags & OSM_DRAW_FLAG_AREA) {    if(way->draw.flags & OSM_DRAW_FLAG_AREA) {
537      if(map->style->area.color & 0xff)      if(map->style->area.color & 0xff)
# Line 537  static canvas_item_t *map_way_new(map_t Line 544  static canvas_item_t *map_way_new(map_t
544      map_item->item = canvas_polyline_new(map->canvas, group, points, width, color);      map_item->item = canvas_polyline_new(map->canvas, group, points, width, color);
545    }    }
546    
547    canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max);    canvas_item_set_zoom_max(map_item->item,
548                               way->draw.zoom_max / (2 * map->state->detail));
549    
550    /* a ways outline itself is never dashed */    /* a ways outline itself is never dashed */
551    if (group != CANVAS_GROUP_WAYS_OL)    if (group != CANVAS_GROUP_WAYS_OL)
# Line 587  void map_way_draw(map_t *map, way_t *way Line 595  void map_way_draw(map_t *map, way_t *way
595      }      }
596    
597      /* draw way */      /* draw way */
598        float width = way->draw.width * map->state->detail;
599    
600      if(way->draw.flags & OSM_DRAW_FLAG_AREA) {      if(way->draw.flags & OSM_DRAW_FLAG_AREA) {
601        map_way_new(map, CANVAS_GROUP_POLYGONS, way, points,        map_way_new(map, CANVAS_GROUP_POLYGONS, way, points,
602                    way->draw.width, way->draw.color, way->draw.area.color);                    width, way->draw.color, way->draw.area.color);
603      } else {      } else {
604    
605        if(way->draw.flags & OSM_DRAW_FLAG_BG) {        if(way->draw.flags & OSM_DRAW_FLAG_BG) {
606          map_way_new(map, CANVAS_GROUP_WAYS_INT, way, points,          map_way_new(map, CANVAS_GROUP_WAYS_INT, way, points,
607                      way->draw.width, way->draw.color, NO_COLOR);                      width, way->draw.color, NO_COLOR);
608    
609          map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points,          map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points,
610                      way->draw.bg.width, way->draw.bg.color, NO_COLOR);                      way->draw.bg.width * map->state->detail,
611                        way->draw.bg.color, NO_COLOR);
612    
613        } else        } else
614          map_way_new(map, CANVAS_GROUP_WAYS, way, points,          map_way_new(map, CANVAS_GROUP_WAYS, way, points,
615                      way->draw.width, way->draw.color, NO_COLOR);                      width, way->draw.color, NO_COLOR);
616      }      }
617      canvas_points_free(points);      canvas_points_free(points);
618    }    }
# Line 614  void map_node_draw(map_t *map, node_t *n Line 625  void map_node_draw(map_t *map, node_t *n
625    
626    if(!node->ways)    if(!node->ways)
627      map_node_new(map, node,      map_node_new(map, node,
628                   map->style->node.radius,                   map->style->node.radius * map->state->detail,
629                   map->style->node.border_radius,                   map->style->node.border_radius * map->state->detail,
630                   map->style->node.fill_color,                   map->style->node.fill_color,
631                   map->style->node.color);                   map->style->node.color);
632    
633    else if(map->style->node.show_untagged || osm_node_has_tag(node))    else if(map->style->node.show_untagged || osm_node_has_tag(node))
634      map_node_new(map, node,      map_node_new(map, node,
635                   map->style->node.radius, 0,                   map->style->node.radius * map->state->detail, 0,
636                   map->style->node.color, 0);                   map->style->node.color, 0);
637  }  }
638    
639  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) {
640    switch(map_item->type) {    switch(map_item->object.type) {
641    case MAP_TYPE_NODE:    case NODE:
642      map_node_draw(map, map_item->node);      map_node_draw(map, map_item->object.node);
643      break;      break;
644    case MAP_TYPE_WAY:    case WAY:
645      map_way_draw(map, map_item->way);      map_way_draw(map, map_item->object.way);
646      break;      break;
647    default:    default:
648      g_assert((map_item->type == MAP_TYPE_NODE) ||      g_assert((map_item->object.type == NODE) ||
649               (map_item->type == MAP_TYPE_WAY));               (map_item->object.type == WAY));
650    }    }
651  }  }
652    
653  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) {
654    map_item_chain_t **chainP = NULL;    map_item_chain_t **chainP = NULL;
655    
656    switch(map_item->type) {    switch(map_item->object.type) {
657    case MAP_TYPE_NODE:    case NODE:
658      chainP = &map_item->node->map_item_chain;      chainP = &map_item->object.node->map_item_chain;
659      break;      break;
660    case MAP_TYPE_WAY:    case WAY:
661      chainP = &map_item->way->map_item_chain;      chainP = &map_item->object.way->map_item_chain;
662      break;      break;
663    default:    default:
664      g_assert((map_item->type == MAP_TYPE_NODE) ||      g_assert((map_item->object.type == NODE) ||
665               (map_item->type == MAP_TYPE_WAY));               (map_item->object.type == WAY));
666    }    }
667    
668    map_item_chain_destroy(chainP);    map_item_chain_destroy(chainP);
669  }  }
670    
671  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) {
672    switch (map_item->type){    switch (map_item->object.type){
673      case MAP_TYPE_WAY:      case WAY:
674        josm_elemstyles_colorize_way(style, map_item->way);        josm_elemstyles_colorize_way(style, map_item->object.way);
675        break;        break;
676      case MAP_TYPE_NODE:      case NODE:
677        josm_elemstyles_colorize_node(style, map_item->node);        josm_elemstyles_colorize_node(style, map_item->object.node);
678        break;        break;
679      default:      default:
680        g_assert((map_item->type == MAP_TYPE_NODE) ||        g_assert((map_item->object.type == NODE) ||
681                     (map_item->type == MAP_TYPE_WAY));                     (map_item->object.type == WAY));
682    }    }
683  }  }
684    
# Line 676  void map_item_redraw(appdata_t *appdata, Line 687  void map_item_redraw(appdata_t *appdata,
687    
688    /* check if the item to be redrawn is the selected one */    /* check if the item to be redrawn is the selected one */
689    gboolean is_selected = FALSE;    gboolean is_selected = FALSE;
690    if(map_item->ptr == appdata->map->selected.ptr) {    if(map_item->object.ptr == appdata->map->selected.object.ptr) {
691      map_item_deselect(appdata);      map_item_deselect(appdata);
692      is_selected = TRUE;      is_selected = TRUE;
693    }    }
# Line 687  void map_item_redraw(appdata_t *appdata, Line 698  void map_item_redraw(appdata_t *appdata,
698    
699    /* restore selection if there was one */    /* restore selection if there was one */
700    if(is_selected)    if(is_selected)
701      map_item_select(appdata, &item);      map_object_select(appdata, &item.object);
702  }  }
703    
704  static void map_frisket_rectangle(canvas_points_t *points,  static void map_frisket_rectangle(canvas_points_t *points,
# Line 877  map_item_t *map_item_at(map_t *map, gint Line 888  map_item_t *map_item_at(map_t *map, gint
888    if(map_item->highlight)    if(map_item->highlight)
889      printf("  item is highlight\n");      printf("  item is highlight\n");
890    
891    switch(map_item->type) {    switch(map_item->object.type) {
892    case MAP_TYPE_NODE:    case NODE:
893      printf("  item is node #%ld\n", map_item->node->id);      printf("  item is node #"ITEM_ID_FORMAT"\n", map_item->object.node->id);
894      break;      break;
895    case MAP_TYPE_WAY:    case WAY:
896      printf("  item is way #%ld\n", map_item->way->id);      printf("  item is way #"ITEM_ID_FORMAT"\n", map_item->object.way->id);
897      break;      break;
898    default:    default:
899      printf("  unknown item\n");      printf("  unknown item\n");
# Line 901  map_item_t *map_real_item_at(map_t *map, Line 912  map_item_t *map_real_item_at(map_t *map,
912    
913    /* get the item (parent) this item is the highlight of */    /* get the item (parent) this item is the highlight of */
914    map_item_t *parent = NULL;    map_item_t *parent = NULL;
915    switch(map_item->type) {    switch(map_item->object.type) {
916    
917    case MAP_TYPE_NODE:    case NODE:
918      if(map_item->node->map_item_chain)      if(map_item->object.node->map_item_chain)
919        parent = map_item->node->map_item_chain->map_item;        parent = map_item->object.node->map_item_chain->map_item;
920    
921      if(parent)      if(parent)
922        printf("  using parent item node #%ld\n", parent->node->id);        printf("  using parent item node #" ITEM_ID_FORMAT "\n",
923                 parent->object.node->id);
924      break;      break;
925    
926    case MAP_TYPE_WAY:    case WAY:
927      if(map_item->way->map_item_chain)      if(map_item->object.way->map_item_chain)
928        parent = map_item->way->map_item_chain->map_item;        parent = map_item->object.way->map_item_chain->map_item;
929    
930      if(parent)      if(parent)
931        printf("  using parent item way #%ld\n", parent->way->id);        printf("  using parent item way #" ITEM_ID_FORMAT "\n",
932                 parent->object.way->id);
933      break;      break;
934    
935    default:    default:
936      g_assert((map_item->type == MAP_TYPE_NODE) ||      g_assert((map_item->object.type == NODE) ||
937               (map_item->type == MAP_TYPE_WAY));               (map_item->object.type == WAY));
938      break;      break;
939    }    }
940    
# Line 1078  void map_scroll_to_if_offscreen(map_t *m Line 1091  void map_scroll_to_if_offscreen(map_t *m
1091  /* Deselects the current way or node if its zoom_max  /* Deselects the current way or node if its zoom_max
1092   * 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. */
1093  void map_deselect_if_zoom_below_zoom_max(map_t *map) {  void map_deselect_if_zoom_below_zoom_max(map_t *map) {
1094      if (map->selected.type == MAP_TYPE_WAY) {      if (map->selected.object.type == WAY) {
1095          printf("will deselect way if zoomed below %f\n",          printf("will deselect way if zoomed below %f\n",
1096                 map->selected.way->draw.zoom_max);                 map->selected.object.way->draw.zoom_max);
1097          if (map->state->zoom < map->selected.way->draw.zoom_max) {          if (map->state->zoom < map->selected.object.way->draw.zoom_max) {
1098              printf("  deselecting way!\n");              printf("  deselecting way!\n");
1099              map_item_deselect(map->appdata);              map_item_deselect(map->appdata);
1100          }          }
1101      }      }
1102      else if (map->selected.type == MAP_TYPE_NODE) {      else if (map->selected.object.type == NODE) {
1103          printf("will deselect node if zoomed below %f\n",          printf("will deselect node if zoomed below %f\n",
1104                 map->selected.node->zoom_max);                 map->selected.object.node->zoom_max);
1105          if (map->state->zoom < map->selected.node->zoom_max) {          if (map->state->zoom < map->selected.object.node->zoom_max) {
1106              printf("  deselecting node!\n");              printf("  deselecting node!\n");
1107              map_item_deselect(map->appdata);              map_item_deselect(map->appdata);
1108          }          }
# Line 1189  gboolean map_item_is_selected_node(map_t Line 1202  gboolean map_item_is_selected_node(map_t
1202      return FALSE;      return FALSE;
1203    }    }
1204    
1205    if(map->selected.type == MAP_TYPE_ILLEGAL) {    if(map->selected.object.type == ILLEGAL) {
1206      printf("  nothing is selected\n");      printf("  nothing is selected\n");
1207      return FALSE;      return FALSE;
1208    }    }
1209    
1210    /* clicked the highlight directly */    /* clicked the highlight directly */
1211    if(map_item->type != MAP_TYPE_NODE) {    if(map_item->object.type != NODE) {
1212      printf("  didn't click node\n");      printf("  didn't click node\n");
1213      return FALSE;      return FALSE;
1214    }    }
1215    
1216    if(map->selected.type == MAP_TYPE_NODE) {    if(map->selected.object.type == NODE) {
1217      printf("  selected item is a node\n");      printf("  selected item is a node\n");
1218    
1219      if(map_item->node == map->selected.node) {      if(map_item->object.node == map->selected.object.node) {
1220        printf("  requested item is a selected node\n");        printf("  requested item is a selected node\n");
1221        return TRUE;        return TRUE;
1222      }      }
1223      printf("  but it's not the requested one\n");      printf("  but it's not the requested one\n");
1224      return FALSE;      return FALSE;
1225    
1226    } else if(map->selected.type == MAP_TYPE_WAY) {    } else if(map->selected.object.type == WAY) {
1227      printf("  selected item is a way\n");      printf("  selected item is a way\n");
1228    
1229      node_chain_t *node_chain = map->selected.way->node_chain;      node_chain_t *node_chain = map->selected.object.way->node_chain;
1230      while(node_chain) {      while(node_chain) {
1231        if(node_chain->node == map_item->node) {        if(node_chain->node == map_item->object.node) {
1232          printf("  requested item is part of selected way\n");          printf("  requested item is part of selected way\n");
1233          return TRUE;          return TRUE;
1234        }        }
# Line 1243  gboolean map_item_is_selected_way(map_t Line 1256  gboolean map_item_is_selected_way(map_t
1256      return FALSE;      return FALSE;
1257    }    }
1258    
1259    if(map->selected.type == MAP_TYPE_ILLEGAL) {    if(map->selected.object.type == ILLEGAL) {
1260      printf("  nothing is selected\n");      printf("  nothing is selected\n");
1261      return FALSE;      return FALSE;
1262    }    }
1263    
1264    /* clicked the highlight directly */    /* clicked the highlight directly */
1265    if(map_item->type != MAP_TYPE_WAY) {    if(map_item->object.type != WAY) {
1266      printf("  didn't click way\n");      printf("  didn't click way\n");
1267      return FALSE;      return FALSE;
1268    }    }
1269    
1270    if(map->selected.type == MAP_TYPE_WAY) {    if(map->selected.object.type == WAY) {
1271      printf("  selected item is a way\n");      printf("  selected item is a way\n");
1272    
1273      if(map_item->way == map->selected.way) {      if(map_item->object.way == map->selected.object.way) {
1274        printf("  requested item is a selected way\n");        printf("  requested item is a selected way\n");
1275        return TRUE;        return TRUE;
1276      }      }
# Line 1272  gboolean map_item_is_selected_way(map_t Line 1285  gboolean map_item_is_selected_way(map_t
1285    
1286  void map_highlight_refresh(appdata_t *appdata) {  void map_highlight_refresh(appdata_t *appdata) {
1287    map_t *map = appdata->map;    map_t *map = appdata->map;
1288    map_item_t old = map->selected;    object_t old = map->selected.object;
1289    
1290    printf("type to refresh is %d\n", old.type);    printf("type to refresh is %d\n", old.type);
1291    if(old.type == MAP_TYPE_ILLEGAL)    if(old.type == ILLEGAL)
1292      return;      return;
1293    
1294    map_item_deselect(appdata);    map_item_deselect(appdata);
1295    map_item_select(appdata, &old);    map_object_select(appdata, &old);
1296  }  }
1297    
1298  void map_way_delete(appdata_t *appdata, way_t *way) {  void map_way_delete(appdata_t *appdata, way_t *way) {
1299    printf("deleting way #%ld from map and osm\n", way->id);    printf("deleting way #" ITEM_ID_FORMAT " from map and osm\n", way->id);
1300    
1301    /* remove it visually from the screen */    /* remove it visually from the screen */
1302    map_item_chain_destroy(&way->map_item_chain);    map_item_chain_destroy(&way->map_item_chain);
# Line 1307  static void map_handle_click(appdata_t * Line 1320  static void map_handle_click(appdata_t *
1320    /* problem: on_item may be the highlight itself! So store it! */    /* problem: on_item may be the highlight itself! So store it! */
1321    map_item_t map_item;    map_item_t map_item;
1322    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;
1323    else                      map_item.type = MAP_TYPE_ILLEGAL;    else                      map_item.object.type = ILLEGAL;
1324    
1325    /* if we aready have something selected, then de-select it */    /* if we aready have something selected, then de-select it */
1326    map_item_deselect(appdata);    map_item_deselect(appdata);
1327    
1328    /* select the clicked item (if there was one) */    /* select the clicked item (if there was one) */
1329    if(map_item.type != MAP_TYPE_ILLEGAL) {    if(map_item.object.type != ILLEGAL) {
1330      switch(map_item.type) {      switch(map_item.object.type) {
1331      case MAP_TYPE_NODE:      case NODE:
1332        map_node_select(appdata, map_item.node);        map_node_select(appdata, map_item.object.node);
1333        break;        break;
1334    
1335      case MAP_TYPE_WAY:      case WAY:
1336        map_way_select(appdata, map_item.way);        map_way_select(appdata, map_item.object.way);
1337        break;        break;
1338    
1339      default:      default:
1340        g_assert((map_item.type == MAP_TYPE_NODE) ||        g_assert((map_item.object.type == NODE) ||
1341                 (map_item.type == MAP_TYPE_WAY));                 (map_item.object.type == WAY));
1342        break;        break;
1343      }      }
1344    }    }
# Line 1345  static void map_touchnode_update(appdata Line 1358  static void map_touchnode_update(appdata
1358      /* in idle mode the dragged node is not highlighted */      /* in idle mode the dragged node is not highlighted */
1359    case MAP_ACTION_IDLE:    case MAP_ACTION_IDLE:
1360      g_assert(map->pen_down.on_item);      g_assert(map->pen_down.on_item);
1361      g_assert(map->pen_down.on_item->type == MAP_TYPE_NODE);      g_assert(map->pen_down.on_item->object.type == NODE);
1362      cur_node = map->pen_down.on_item->node;      cur_node = map->pen_down.on_item->object.node;
1363      break;      break;
1364    
1365    default:    default:
# Line 1361  static void map_touchnode_update(appdata Line 1374  static void map_touchnode_update(appdata
1374      /* don't highlight the dragged node itself and don't highlight */      /* don't highlight the dragged node itself and don't highlight */
1375      /* deleted ones */      /* deleted ones */
1376      if((node != cur_node) && (!(node->flags & OSM_FLAG_DELETED))) {      if((node != cur_node) && (!(node->flags & OSM_FLAG_DELETED))) {
1377        gint nx = x - node->lpos.x;        gint nx = abs(x - node->lpos.x);
1378        gint ny = y - node->lpos.y;        gint ny = abs(y - node->lpos.y);
1379    
1380        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&
1381           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))
# Line 1376  static void map_touchnode_update(appdata Line 1389  static void map_touchnode_update(appdata
1389    if(!map->touchnode && map->action.way) {    if(!map->touchnode && map->action.way) {
1390      node_chain_t *chain = map->action.way->node_chain;      node_chain_t *chain = map->action.way->node_chain;
1391      while(!map->touchnode && chain && chain->next) {      while(!map->touchnode && chain && chain->next) {
1392        gint nx = x - chain->node->lpos.x;        gint nx = abs(x - chain->node->lpos.x);
1393        gint ny = y - chain->node->lpos.y;        gint ny = abs(y - chain->node->lpos.y);
1394    
1395        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&
1396           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))
# Line 1469  static void map_button_release(map_t *ma Line 1482  static void map_button_release(map_t *ma
1482        map_item_t old_sel = map->selected;        map_item_t old_sel = map->selected;
1483        map_handle_click(map->appdata, map);        map_handle_click(map->appdata, map);
1484    
1485        if((old_sel.type != MAP_TYPE_ILLEGAL) &&        if((old_sel.object.type != ILLEGAL) &&
1486           (old_sel.type == map->selected.type) &&           (old_sel.object.type == map->selected.object.type) &&
1487           (old_sel.ptr == map->selected.ptr)) {           (old_sel.object.ptr == map->selected.object.ptr)) {
1488          printf("re-selected same item of type %d, "          printf("re-selected same item of type %d, "
1489                 "pushing it to the bottom\n", old_sel.type);                 "pushing it to the bottom\n", old_sel.object.type);
1490    
1491          if(!map->selected.item) {          if(!map->selected.item) {
1492            printf("  item has no visible representation to push\n");            printf("  item has no visible representation to push\n");
# Line 1735  gboolean map_key_press_event(appdata_t * Line 1748  gboolean map_key_press_event(appdata_t *
1748    return FALSE;    return FALSE;
1749  }  }
1750    
1751    void map_state_reset(map_state_t *state) {
1752      if(!state) return;
1753    
1754      state->zoom = 0.25;
1755      state->detail = 1.0;
1756    
1757      /* todo: try to scroll to center of screen */
1758      state->scroll_offset.x = 0;
1759      state->scroll_offset.y = 0;
1760    }
1761    
1762    map_state_t *map_state_new(void) {
1763      map_state_t *state = g_new0(map_state_t, 1);
1764      map_state_reset(state);
1765      return state;
1766    }
1767    
1768  GtkWidget *map_new(appdata_t *appdata) {  GtkWidget *map_new(appdata_t *appdata) {
1769    map_t *map = appdata->map = g_new0(map_t, 1);    map_t *map = appdata->map = g_new0(map_t, 1);
1770    
# Line 1750  GtkWidget *map_new(appdata_t *appdata) { Line 1780  GtkWidget *map_new(appdata_t *appdata) {
1780      map->state = appdata->project->map_state;      map->state = appdata->project->map_state;
1781    } else {    } else {
1782      printf("Creating new map state\n");      printf("Creating new map state\n");
1783      map->state = g_new0(map_state_t, 1);      map->state = map_state_new();
     map->state->zoom = 0.25;  
1784    }    }
1785    
1786    map->state->refcount++;    map->state->refcount++;
# Line 1814  void map_init(appdata_t *appdata) { Line 1843  void map_init(appdata_t *appdata) {
1843  }  }
1844    
1845    
 void map_item_set_flags(map_item_t *map_item, int set, int clr) {  
   
   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;  
   
   case MAP_TYPE_RELATION:  
     map_item->relation->flags |=  set;  
     map_item->relation->flags &= ~clr;  
     break;  
   
   default:  
     g_assert(0);  
     break;  
   }  
 }  
   
1846  void map_clear(appdata_t *appdata, gint group_mask) {  void map_clear(appdata_t *appdata, gint group_mask) {
1847    map_t *map = appdata->map;    map_t *map = appdata->map;
1848    
# Line 1888  void map_action_set(appdata_t *appdata, Line 1893  void map_action_set(appdata_t *appdata,
1893    
1894      /* remember if there was a way selected */      /* remember if there was a way selected */
1895      way_t *way_sel = NULL;      way_t *way_sel = NULL;
1896      if(appdata->map->selected.type == MAP_TYPE_WAY)      if(appdata->map->selected.object.type == WAY)
1897        way_sel = appdata->map->selected.way;        way_sel = appdata->map->selected.object.way;
1898    
1899      map_item_deselect(appdata);      map_item_deselect(appdata);
1900      map_edit_way_add_begin(appdata->map, way_sel);      map_edit_way_add_begin(appdata->map, way_sel);
# Line 1964  void map_action_ok(appdata_t *appdata) { Line 1969  void map_action_ok(appdata_t *appdata) {
1969      /* save changes to bg_offset in project */      /* save changes to bg_offset in project */
1970      appdata->project->wms_offset.x = map->bg.offset.x;      appdata->project->wms_offset.x = map->bg.offset.x;
1971      appdata->project->wms_offset.y = map->bg.offset.y;      appdata->project->wms_offset.y = map->bg.offset.y;
     appdata->project->dirty = TRUE;  
1972      break;      break;
1973    
1974    default:    default:
# Line 1988  void map_delete_selected(appdata_t *appd Line 1992  void map_delete_selected(appdata_t *appd
1992    /* deleting the selected item de-selects it ... */    /* deleting the selected item de-selects it ... */
1993    map_item_deselect(appdata);    map_item_deselect(appdata);
1994    
1995    undo_remember_delete(appdata, item.type, item.ptr);    undo_remember_delete(appdata, &item.object);
1996    
1997    switch(item.type) {    switch(item.object.type) {
1998    case MAP_TYPE_NODE:    case NODE:
1999      printf("request to delete node #%ld\n", item.node->id);      printf("request to delete node #" ITEM_ID_FORMAT "\n",
2000               item.object.node->id);
2001    
2002      /* 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. */
2003      /* we cannot delete this as this would also delete the way */      /* we cannot delete this as this would also delete the way */
2004      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);
2005      if(way_chain) {      if(way_chain) {
2006        gboolean short_way = FALSE;        gboolean short_way = FALSE;
2007    
# Line 2022  void map_delete_selected(appdata_t *appd Line 2027  void map_delete_selected(appdata_t *appd
2027      }      }
2028    
2029      /* remove it visually from the screen */      /* remove it visually from the screen */
2030      map_item_chain_destroy(&item.node->map_item_chain);      map_item_chain_destroy(&item.object.node->map_item_chain);
2031    
2032      /* and mark it "deleted" in the database */      /* and mark it "deleted" in the database */
2033      osm_node_remove_from_relation(appdata->osm, item.node);      osm_node_remove_from_relation(appdata->osm, item.object.node);
2034      way_chain_t *chain = osm_node_delete(appdata->osm,      way_chain_t *chain = osm_node_delete(appdata->osm,
2035                           &appdata->icon, item.node, FALSE, TRUE);                           &appdata->icon, item.object.node, FALSE, TRUE);
2036    
2037      /* redraw all affected ways */      /* redraw all affected ways */
2038      while(chain) {      while(chain) {
# Line 2040  void map_delete_selected(appdata_t *appd Line 2045  void map_delete_selected(appdata_t *appd
2045          map_way_delete(appdata, chain->way);          map_way_delete(appdata, chain->way);
2046        } else {        } else {
2047          map_item_t item;          map_item_t item;
2048          item.type = MAP_TYPE_WAY;          item.object.type = WAY;
2049          item.way = chain->way;          item.object.way = chain->way;
2050          map_item_redraw(appdata, &item);          map_item_redraw(appdata, &item);
2051        }        }
2052    
# Line 2052  void map_delete_selected(appdata_t *appd Line 2057  void map_delete_selected(appdata_t *appd
2057    
2058      break;      break;
2059    
2060    case MAP_TYPE_WAY:    case WAY:
2061      printf("request to delete way #%ld\n", item.way->id);      printf("request to delete way #" ITEM_ID_FORMAT "\n", item.object.way->id);
2062      map_way_delete(appdata, item.way);      map_way_delete(appdata, item.object.way);
2063      break;      break;
2064    
2065    default:    default:
2066      g_assert((item.type == MAP_TYPE_NODE) ||      g_assert((item.object.type == NODE) ||
2067               (item.type == MAP_TYPE_WAY));               (item.object.type == WAY));
2068      break;      break;
2069    }    }
2070  }  }
2071    
2072  /* ----------------------- track related stuff ----------------------- */  /* ----------------------- track related stuff ----------------------- */
2073    
2074    static gboolean track_pos2lpos(bounds_t *bounds, pos_t *pos, lpos_t *lpos) {
2075      pos2lpos(bounds, pos, lpos);
2076    
2077      /* check if point is within bounds */
2078      return ((lpos->x >= bounds->min.x) && (lpos->x <= bounds->max.x) &&
2079              (lpos->y >= bounds->min.y) && (lpos->y <= bounds->max.y));
2080    }
2081    
2082  void map_track_draw_seg(map_t *map, track_seg_t *seg) {  void map_track_draw_seg(map_t *map, track_seg_t *seg) {
2083      bounds_t *bounds = map->appdata->osm->bounds;
2084    
2085    /* a track_seg needs at least 2 points to be drawn */    /* a track_seg needs at least 2 points to be drawn */
2086    guint pnum = track_seg_points(seg);    guint pnum = track_seg_points(seg);
2087    printf("seg of length %d\n", pnum);    printf("seg of length %d\n", pnum);
2088    
2089    if(pnum == 1) {    if(!pnum)
2090      g_assert(!seg->item);      return;
2091    
2092      seg->item = canvas_circle_new(map->canvas, CANVAS_GROUP_TRACK,    /* nothing should have been drawn by now ... */
2093            seg->track_point->lpos.x, seg->track_point->lpos.y,    g_assert(!seg->item_chain);
2094            map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR);  
2095    }    track_item_chain_t **itemP = &seg->item_chain;
2096      track_point_t *track_point = seg->track_point;
2097      while(track_point) {
2098        lpos_t lpos;
2099    
2100        /* skip all points not on screen */
2101        track_point_t *last = NULL;
2102        while(track_point && !track_pos2lpos(bounds, &track_point->pos, &lpos)) {
2103          last = track_point;
2104          track_point = track_point->next;
2105        }
2106    
2107        int visible = 0;
2108    
2109        /* count nodes that _are_ on screen */
2110        track_point_t *tmp = track_point;
2111        while(tmp && track_pos2lpos(bounds, &tmp->pos, &lpos)) {
2112          tmp = tmp->next;
2113          visible++;
2114        }
2115    
2116        /* actually start drawing with the last position that was offscreen */
2117        /* so the track nicely enters the viewing area */
2118        if(last) {
2119          track_point = last;
2120          visible++;
2121        }
2122    
2123        /* also use last one that's offscreen to nicely leave the visible area */
2124        if(tmp && tmp->next)
2125          visible++;
2126    
   if(pnum > 1) {  
   
2127      /* allocate space for nodes */      /* allocate space for nodes */
2128      canvas_points_t *points = canvas_points_new(pnum);      canvas_points_t *points = canvas_points_new(visible);
2129    
2130      int point = 0;      printf("visible are %d\n", visible);
2131      track_point_t *track_point = seg->track_point;      int point;
2132      while(track_point) {      for(point=0;point<visible;point++) {
2133        points->coords[point++] = track_point->lpos.x;        track_pos2lpos(bounds, &track_point->pos, &lpos);
2134        points->coords[point++] = track_point->lpos.y;  
2135          points->coords[2*point+0] = lpos.x;
2136          points->coords[2*point+1] = lpos.y;
2137        track_point = track_point->next;        track_point = track_point->next;
2138      }      }
   
     /* there may be a circle (one point line) */  
     if(seg->item)  
       canvas_item_destroy(seg->item);  
2139    
2140      seg->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,      *itemP = g_new0(track_item_chain_t, 1);
2141            points, map->style->track.width, map->style->track.color);      (*itemP)->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2142                     points, map->style->track.width, map->style->track.color);
2143        itemP = &(*itemP)->next;
2144    
2145      canvas_points_free(points);      canvas_points_free(points);
2146    }    }
2147  }  }
2148    
2149    /* update the last visible fragment of this segment since a */
2150    /* gps position may have been added */
2151  void map_track_update_seg(map_t *map, track_seg_t *seg) {  void map_track_update_seg(map_t *map, track_seg_t *seg) {
2152      bounds_t *bounds = map->appdata->osm->bounds;
2153    
2154      printf("-- APPENDING TO TRACK --\n");
2155    
2156    /* a track_seg needs at least 2 points to be drawn */    /* a track_seg needs at least 2 points to be drawn */
2157    guint pnum = track_seg_points(seg);    guint pnum = track_seg_points(seg);
2158    printf("seg of length %d\n", pnum);    printf("seg of length %d\n", pnum);
2159    
2160    if(pnum > 1) {    /* there are two cases: either the second last point was on screen */
2161      /* or it wasn't. We'll have to start a new screen item if the latter */
2162      /* is the case */
2163    
2164      /* search last point */
2165      track_point_t *begin = seg->track_point, *second_last = seg->track_point;
2166      lpos_t lpos;
2167      while(second_last && second_last->next && second_last->next->next) {
2168        if(!track_pos2lpos(bounds, &second_last->pos, &lpos))
2169          begin = second_last;
2170    
2171        second_last = second_last->next;
2172      }
2173      track_point_t *last = second_last->next;
2174    
2175      /* since we are updating an existing track, it sure has at least two */
2176      /* points, second_last must be valid and its "next" (last) also */
2177      g_assert(second_last);
2178      g_assert(last);
2179    
2180      /* check if the last and second_last points are visible */
2181      gboolean last_is_visible =
2182        track_pos2lpos(bounds, &last->pos, &lpos);
2183      gboolean second_last_is_visible =
2184        track_pos2lpos(bounds, &second_last->pos, &lpos);
2185    
2186      /* if both are invisible, then nothing has changed on screen */
2187      if(!last_is_visible && !second_last_is_visible) {
2188        printf("second_last and last entry are invisible -> doing nothing\n");
2189        return;
2190      }
2191    
2192      /* search last element in item chain */
2193      track_item_chain_t *item = seg->item_chain;
2194      while(item && item->next)
2195        item = item->next;
2196    
2197      if(second_last_is_visible) {
2198        /* there must be something already on the screen and there must */
2199        /* be visible nodes in the chain */
2200        g_assert(item);
2201        g_assert(begin);
2202    
2203        printf("second_last is visible -> append\n");
2204    
2205      /* allocate space for nodes */      /* count points to be placed */
2206      canvas_points_t *points = canvas_points_new(pnum);      int npoints = 0;
2207        track_point_t *tmp = begin;
2208        while(tmp) {
2209          tmp = tmp->next;
2210          npoints++;
2211        }
2212    
2213        printf("updating last segment to %d points\n", npoints);
2214    
2215        canvas_points_t *points = canvas_points_new(npoints);
2216    
2217        gint point = 0;
2218        while(begin) {
2219          track_pos2lpos(bounds, &begin->pos, &lpos);
2220          canvas_point_set_pos(points, point++, &lpos);
2221          begin = begin->next;
2222        }
2223    
2224      int point = 0;      canvas_item_set_points(item->item, points);
2225      track_point_t *track_point = seg->track_point;      canvas_points_free(points);
2226      while(track_point) {  
2227        canvas_point_set_pos(points, point++, &track_point->lpos);    } else {
2228        track_point = track_point->next;      printf("second last is invisible -> start new screen segment\n");
2229    
2230        /* the search for the "begin" ends with the second_last item */
2231        /* verify the last one also */
2232        if(begin->next && !track_pos2lpos(bounds, &begin->next->pos, &lpos))
2233          begin = begin->next;
2234    
2235        item->next = g_new0(track_item_chain_t, 1);
2236        item = item->next;
2237    
2238        /* count points to be placed */
2239        int npoints = 0;
2240        track_point_t *tmp = begin;
2241        while(tmp) {
2242          tmp = tmp->next;
2243          npoints++;
2244        }
2245    
2246        printf("attaching new segment with %d points\n", npoints);
2247    
2248        canvas_points_t *points = canvas_points_new(npoints);
2249    
2250        gint point = 0;
2251        while(begin) {
2252          track_pos2lpos(bounds, &begin->pos, &lpos);
2253          canvas_point_set_pos(points, point++, &lpos);
2254          begin = begin->next;
2255      }      }
2256    
2257      g_assert(seg->item);      item->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2258      canvas_item_set_points(seg->item, points);                   points, map->style->track.width, map->style->track.color);
2259    
2260      canvas_points_free(points);      canvas_points_free(points);
2261    }    }
2262    
2263  }  }
2264    
2265  void map_track_draw(map_t *map, track_t *track) {  void map_track_draw(map_t *map, track_t *track) {
# Line 2146  void map_track_remove(appdata_t *appdata Line 2282  void map_track_remove(appdata_t *appdata
2282    /* remove all segments */    /* remove all segments */
2283    track_seg_t *seg = track->track_seg;    track_seg_t *seg = track->track_seg;
2284    while(seg) {    while(seg) {
2285      if(seg->item) {      track_item_chain_t *item = seg->item_chain;
2286        canvas_item_destroy(seg->item);      while(item) {
2287        seg->item = NULL;        track_item_chain_t *next = item->next;
2288          canvas_item_destroy(item->item);
2289          item = next;
2290      }      }
2291    
2292        seg->item_chain = NULL;
2293      seg = seg->next;      seg = seg->next;
2294    }    }
2295  }  }
2296    
2297  void map_track_pos(appdata_t *appdata, lpos_t *lpos) {  void map_track_pos(appdata_t *appdata, pos_t *pos) {
2298    if(appdata->track.gps_item) {    if(appdata->track.gps_item) {
2299      canvas_item_destroy(appdata->track.gps_item);      canvas_item_destroy(appdata->track.gps_item);
2300      appdata->track.gps_item = NULL;      appdata->track.gps_item = NULL;
2301    }    }
2302    
2303    if(lpos)    if(pos) {
2304        lpos_t lpos;
2305        pos2lpos(appdata->osm->bounds, pos, &lpos);
2306    
2307      appdata->track.gps_item =      appdata->track.gps_item =
2308        canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,        canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,
2309          lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0,          lpos.x, lpos.y, appdata->map->style->track.width/2.0, 0,
2310                          appdata->map->style->track.gps_color, NO_COLOR);                          appdata->map->style->track.gps_color, NO_COLOR);
2311      }
2312  }  }
2313    
2314  /* ------------------- map background ------------------ */  /* ------------------- map background ------------------ */
# Line 2220  void map_hide_selected(appdata_t *appdat Line 2363  void map_hide_selected(appdata_t *appdat
2363    map_t *map = appdata->map;    map_t *map = appdata->map;
2364    if(!map) return;    if(!map) return;
2365    
2366    if(map->selected.type != MAP_TYPE_WAY) {    if(map->selected.object.type != WAY) {
2367      printf("selected item is not a way\n");      printf("selected item is not a way\n");
2368      return;      return;
2369    }    }
2370    
2371    way_t *way = map->selected.way;    way_t *way = map->selected.object.way;
2372    printf("hiding way #%ld\n", way->id);    printf("hiding way #" ITEM_ID_FORMAT "\n", way->id);
2373    
2374    map_item_deselect(appdata);    map_item_deselect(appdata);
2375    way->flags |= OSM_FLAG_HIDDEN;    way->flags |= OSM_FLAG_HIDDEN;
# Line 2252  void map_show_all(appdata_t *appdata) { Line 2395  void map_show_all(appdata_t *appdata) {
2395    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);
2396  }  }
2397    
2398    static void map_detail_change(map_t *map, float detail) {
2399      appdata_t *appdata = map->appdata;
2400    
2401      /* deselecting anything allows us not to care about automatic deselection */
2402      /* as well as items becoming invisible by the detail change */
2403      map_item_deselect(appdata);
2404    
2405      map->state->detail = detail;
2406      printf("changing detail factor to %f\n", map->state->detail);
2407    
2408      banner_busy_start(appdata, 1, _("Redrawing"));
2409      map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
2410      map_paint(appdata);
2411      banner_busy_stop(appdata);
2412    }
2413    
2414    #define DETAIL_STEP 1.5
2415    
2416    void map_detail_increase(map_t *map) {
2417      if(!map) return;
2418      map_detail_change(map, map->state->detail * DETAIL_STEP);
2419    }
2420    
2421    void map_detail_decrease(map_t *map) {
2422      if(!map) return;
2423      map_detail_change(map, map->state->detail / DETAIL_STEP);
2424    }
2425    
2426    void map_detail_normal(map_t *map) {
2427      if(!map) return;
2428      map_detail_change(map, 1.0);
2429    }
2430    
2431  // vim:et:ts=8:sw=2:sts=2:ai  // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.153  
changed lines
  Added in v.180