Diff of /trunk/src/map.c

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

revision 151 by harbaum, Sat Mar 28 12:42:18 2009 UTC revision 156 by harbaum, Wed Apr 1 12:47:35 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;
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:
# Line 132  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 146  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 157  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);
# Line 184  void map_way_select(appdata_t *appdata, Line 190  void map_way_select(appdata_t *appdata,
190    
191    g_assert(!map->highlight);    g_assert(!map->highlight);
192    
193    map_item->type      = MAP_TYPE_WAY;    map_item->object.type      = WAY;
194    map_item->way       = way;    map_item->object.way       = way;
195    map_item->highlight = FALSE;    map_item->highlight = FALSE;
196    map_item->item      = way->map_item_chain->map_item->item;    map_item->item      = way->map_item_chain->map_item->item;
197    
# Line 193  void map_way_select(appdata_t *appdata, Line 199  void map_way_select(appdata_t *appdata,
199    icon_bar_map_item_selected(appdata, map_item, TRUE);    icon_bar_map_item_selected(appdata, map_item, TRUE);
200    gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, TRUE);    gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, TRUE);
201    
202    gint arrow_width = (map_item->way->draw.flags & OSM_DRAW_FLAG_BG)?    gint arrow_width = (map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?
203      map->style->highlight.width + map_item->way->draw.bg.width/2:      map->style->highlight.width + map_item->object.way->draw.bg.width/2:
204      map->style->highlight.width + map_item->way->draw.width/2;      map->style->highlight.width + map_item->object.way->draw.width/2;
205    
206    node_chain_t *node_chain = map_item->way->node_chain;    node_chain_t *node_chain = map_item->object.way->node_chain;
207    node_t *last = NULL;    node_t *last = NULL;
208    while(node_chain) {    while(node_chain) {
209      map_item_t item;      map_item_t item;
210      item.type = MAP_TYPE_NODE;      item.object.type = NODE;
211      item.node = node_chain->node;      item.object.node = node_chain->node;
212    
213      /* draw an arrow between every two nodes */      /* draw an arrow between every two nodes */
214      if(last) {      if(last) {
215        /* create a new map item for every arrow */        /* create a new map item for every arrow */
216        map_item_t *new_map_item = g_new0(map_item_t, 1);        map_item_t *new_map_item = g_new0(map_item_t, 1);
217        new_map_item->type = MAP_TYPE_WAY;        new_map_item->object.type = WAY;
218        new_map_item->way = way;        new_map_item->object.way = way;
219        new_map_item->highlight = TRUE;        new_map_item->highlight = TRUE;
220    
221        struct { float x, y;} center, diff;        struct { float x, y;} center, diff;
# Line 245  void map_way_select(appdata_t *appdata, Line 251  void map_way_select(appdata_t *appdata,
251    
252        /* create a new map item for every node */        /* create a new map item for every node */
253        map_item_t *new_map_item = g_new0(map_item_t, 1);        map_item_t *new_map_item = g_new0(map_item_t, 1);
254        new_map_item->type = MAP_TYPE_NODE;        new_map_item->object.type = NODE;
255        new_map_item->node = node_chain->node;        new_map_item->object.node = node_chain->node;
256        new_map_item->highlight = TRUE;        new_map_item->highlight = TRUE;
257    
258        gint x = node_chain->node->lpos.x;        gint x = node_chain->node->lpos.x;
# Line 269  void map_way_select(appdata_t *appdata, Line 275  void map_way_select(appdata_t *appdata,
275      canvas_points_t *points = canvas_points_new(nodes);      canvas_points_t *points = canvas_points_new(nodes);
276    
277      int node = 0;      int node = 0;
278      node_chain = map_item->way->node_chain;      node_chain = map_item->object.way->node_chain;
279      while(node_chain) {      while(node_chain) {
280        canvas_point_set_pos(points, node++, &node_chain->node->lpos);        canvas_point_set_pos(points, node++, &node_chain->node->lpos);
281        node_chain = node_chain->next;        node_chain = node_chain->next;
# Line 281  void map_way_select(appdata_t *appdata, Line 287  void map_way_select(appdata_t *appdata,
287      new_map_item->highlight = TRUE;      new_map_item->highlight = TRUE;
288    
289      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,
290                  (map_item->way->draw.flags & OSM_DRAW_FLAG_BG)?                  (map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?
291                  2*map->style->highlight.width + map_item->way->draw.bg.width:                  2*map->style->highlight.width + map_item->object.way->draw.bg.width:
292                  2*map->style->highlight.width + map_item->way->draw.width,                  2*map->style->highlight.width + map_item->object.way->draw.width,
293                  map->style->highlight.color);                  map->style->highlight.color);
294    
295      canvas_points_free(points);      canvas_points_free(points);
296    }    }
297  }  }
298    
299  static void map_item_select(appdata_t *appdata, map_item_t *map_item) {  void map_relation_select(appdata_t *appdata, relation_t *relation) {
300    switch(map_item->type) {    map_t *map = appdata->map;
301    case MAP_TYPE_NODE:  
302      map_node_select(appdata, map_item->node);    printf("highlighting relation %ld\n", relation->id);
303    
304      g_assert(!map->highlight);
305      map_highlight_t **hl = &map->highlight;
306    
307      map_item_t *map_item = &map->selected;
308      map_item->object.type      = RELATION;
309      map_item->object.relation  = relation;
310      map_item->highlight = FALSE;
311      map_item->item      = NULL;
312    
313      map_statusbar(map, map_item);
314      icon_bar_map_item_selected(appdata, map_item, TRUE);
315    
316      /* process all members */
317      member_t *member = relation->member;
318      while(member) {
319        canvas_item_t *item = NULL;
320    
321        switch(member->object.type) {
322    
323        case NODE: {
324          node_t *node = member->object.node;
325          printf("  -> node %ld\n", node->id);
326    
327          item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES_HL,
328                            node->lpos.x, node->lpos.y,
329                            map->style->highlight.width + map->style->node.radius,
330                            0, map->style->highlight.color, NO_COLOR);
331          } break;
332    
333        case WAY: {
334          way_t *way = member->object.way;
335          /* a way needs at least 2 points to be drawn */
336          guint nodes = osm_way_number_of_nodes(way);
337          if(nodes > 1) {
338    
339            /* allocate space for nodes */
340            canvas_points_t *points = canvas_points_new(nodes);
341    
342            int node = 0;
343            node_chain_t *node_chain = way->node_chain;
344            while(node_chain) {
345              canvas_point_set_pos(points, node++, &node_chain->node->lpos);
346              node_chain = node_chain->next;
347            }
348    
349            if(way->draw.flags & OSM_DRAW_FLAG_AREA)
350              item = canvas_polygon_new(map->canvas, CANVAS_GROUP_WAYS_HL, points, 0, 0,
351                                        map->style->highlight.color);
352            else
353              item = canvas_polyline_new(map->canvas, CANVAS_GROUP_WAYS_HL, points,
354                                  (way->draw.flags & OSM_DRAW_FLAG_BG)?
355                                  2*map->style->highlight.width + way->draw.bg.width:
356                                  2*map->style->highlight.width + way->draw.width,
357                                  map->style->highlight.color);
358    
359            canvas_points_free(points);
360          } } break;
361    
362        default:
363          break;
364        }
365    
366        /* attach item to item chain */
367        if(item) {
368          *hl = g_new0(map_highlight_t, 1);
369          (*hl)->item = item;
370          hl = &(*hl)->next;
371        }
372    
373        member = member->next;
374      }
375    }
376    
377    static void map_object_select(appdata_t *appdata, object_t *object) {
378      switch(object->type) {
379      case NODE:
380        map_node_select(appdata, object->node);
381      break;      break;
382    case MAP_TYPE_WAY:    case WAY:
383      map_way_select(appdata, map_item->way);      map_way_select(appdata, object->way);
384        break;
385      case RELATION:
386        map_relation_select(appdata, object->relation);
387      break;      break;
388    default:    default:
389      g_assert((map_item->type == MAP_TYPE_NODE)||      g_assert((object->type == NODE)||(object->type == RELATION)||
390               (map_item->type == MAP_TYPE_WAY));               (object->type == WAY));
391      break;      break;
392    }    }
393  }  }
# Line 308  static void map_item_select(appdata_t *a Line 395  static void map_item_select(appdata_t *a
395  void map_item_deselect(appdata_t *appdata) {  void map_item_deselect(appdata_t *appdata) {
396    
397    /* save tags for "last" function in info dialog */    /* save tags for "last" function in info dialog */
398    if(appdata->map->selected.type == MAP_TYPE_NODE) {    if(appdata->map->selected.object.type == NODE) {
399      if(appdata->map->last_node_tags)      if(appdata->map->last_node_tags)
400        osm_tags_free(appdata->map->last_node_tags);        osm_tags_free(appdata->map->last_node_tags);
401    
402      appdata->map->last_node_tags =      appdata->map->last_node_tags =
403        osm_tags_copy(appdata->map->selected.node->tag, FALSE);        osm_tags_copy(appdata->map->selected.object.node->tag, FALSE);
404    } else if(appdata->map->selected.type == MAP_TYPE_WAY) {    } else if(appdata->map->selected.object.type == WAY) {
405      if(appdata->map->last_way_tags)      if(appdata->map->last_way_tags)
406        osm_tags_free(appdata->map->last_way_tags);        osm_tags_free(appdata->map->last_way_tags);
407    
408      appdata->map->last_way_tags =      appdata->map->last_way_tags =
409        osm_tags_copy(appdata->map->selected.way->tag, FALSE);        osm_tags_copy(appdata->map->selected.object.way->tag, FALSE);
410    }    }
411    
412    /* remove statusbar message */    /* remove statusbar message */
# Line 333  void map_item_deselect(appdata_t *appdat Line 420  void map_item_deselect(appdata_t *appdat
420    map_hl_remove(appdata);    map_hl_remove(appdata);
421    
422    /* forget about selection */    /* forget about selection */
423    appdata->map->selected.type = MAP_TYPE_ILLEGAL;    appdata->map->selected.object.type = ILLEGAL;
424  }  }
425    
426  /* called whenever a map item is to be destroyed */  /* called whenever a map item is to be destroyed */
# Line 345  static gint map_item_destroy_event(GtkWi Line 432  static gint map_item_destroy_event(GtkWi
432  #ifdef DESTROY_WAIT_FOR_GTK  #ifdef DESTROY_WAIT_FOR_GTK
433    /* remove item from nodes/ways map_item_chain */    /* remove item from nodes/ways map_item_chain */
434    map_item_chain_t **chain = NULL;    map_item_chain_t **chain = NULL;
435    if(map_item->type == MAP_TYPE_NODE)    if(map_item->object.type == NODE)
436      chain = &map_item->node->map_item_chain;      chain = &map_item->object.node->map_item_chain;
437    else if(map_item->type == MAP_TYPE_WAY)    else if(map_item->object.type == WAY)
438      chain = &map_item->way->map_item_chain;      chain = &map_item->object.way->map_item_chain;
439    
440    /* there must be a chain with content, otherwise things are broken */    /* there must be a chain with content, otherwise things are broken */
441    g_assert(chain);    g_assert(chain);
# Line 375  static canvas_item_t *map_node_new(map_t Line 462  static canvas_item_t *map_node_new(map_t
462                     gint width, canvas_color_t fill, canvas_color_t border) {                     gint width, canvas_color_t fill, canvas_color_t border) {
463    
464    map_item_t *map_item = g_new0(map_item_t, 1);    map_item_t *map_item = g_new0(map_item_t, 1);
465    map_item->type = MAP_TYPE_NODE;    map_item->object.type = NODE;
466    map_item->node = node;    map_item->object.node = node;
467    
468    if(!node->icon_buf || !map->style->icon.enable ||    if(!node->icon_buf || !map->style->icon.enable ||
469       map->appdata->settings->no_icons)       map->appdata->settings->no_icons)
# Line 413  static canvas_item_t *map_way_single_new Line 500  static canvas_item_t *map_way_single_new
500                     gint width, canvas_color_t fill, canvas_color_t border) {                     gint width, canvas_color_t fill, canvas_color_t border) {
501    
502    map_item_t *map_item = g_new0(map_item_t, 1);    map_item_t *map_item = g_new0(map_item_t, 1);
503    map_item->type = MAP_TYPE_WAY;    map_item->object.type = WAY;
504    map_item->way = way;    map_item->object.way = way;
505    map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_WAYS,    map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_WAYS,
506            way->node_chain->node->lpos.x, way->node_chain->node->lpos.y,            way->node_chain->node->lpos.x, way->node_chain->node->lpos.y,
507                                       radius, width, fill, border);                                       radius, width, fill, border);
# Line 439  static canvas_item_t *map_way_new(map_t Line 526  static canvas_item_t *map_way_new(map_t
526            way_t *way, canvas_points_t *points, gint width,            way_t *way, canvas_points_t *points, gint width,
527            canvas_color_t color, canvas_color_t fill_color) {            canvas_color_t color, canvas_color_t fill_color) {
528    map_item_t *map_item = g_new0(map_item_t, 1);    map_item_t *map_item = g_new0(map_item_t, 1);
529    map_item->type = MAP_TYPE_WAY;    map_item->object.type = WAY;
530    map_item->way = way;    map_item->object.way = way;
531    
532    if(way->draw.flags & OSM_DRAW_FLAG_AREA) {    if(way->draw.flags & OSM_DRAW_FLAG_AREA) {
533      if(map->style->area.color & 0xff)      if(map->style->area.color & 0xff)
# Line 542  void map_node_draw(map_t *map, node_t *n Line 629  void map_node_draw(map_t *map, node_t *n
629  }  }
630    
631  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) {
632    switch(map_item->type) {    switch(map_item->object.type) {
633    case MAP_TYPE_NODE:    case NODE:
634      map_node_draw(map, map_item->node);      map_node_draw(map, map_item->object.node);
635      break;      break;
636    case MAP_TYPE_WAY:    case WAY:
637      map_way_draw(map, map_item->way);      map_way_draw(map, map_item->object.way);
638      break;      break;
639    default:    default:
640      g_assert((map_item->type == MAP_TYPE_NODE) ||      g_assert((map_item->object.type == NODE) ||
641               (map_item->type == MAP_TYPE_WAY));               (map_item->object.type == WAY));
642    }    }
643  }  }
644    
645  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) {
646    map_item_chain_t **chainP = NULL;    map_item_chain_t **chainP = NULL;
647    
648    switch(map_item->type) {    switch(map_item->object.type) {
649    case MAP_TYPE_NODE:    case NODE:
650      chainP = &map_item->node->map_item_chain;      chainP = &map_item->object.node->map_item_chain;
651      break;      break;
652    case MAP_TYPE_WAY:    case WAY:
653      chainP = &map_item->way->map_item_chain;      chainP = &map_item->object.way->map_item_chain;
654      break;      break;
655    default:    default:
656      g_assert((map_item->type == MAP_TYPE_NODE) ||      g_assert((map_item->object.type == NODE) ||
657               (map_item->type == MAP_TYPE_WAY));               (map_item->object.type == WAY));
658    }    }
659    
660    map_item_chain_destroy(chainP);    map_item_chain_destroy(chainP);
661  }  }
662    
663  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) {
664    switch (map_item->type){    switch (map_item->object.type){
665      case MAP_TYPE_WAY:      case WAY:
666        josm_elemstyles_colorize_way(style, map_item->way);        josm_elemstyles_colorize_way(style, map_item->object.way);
667        break;        break;
668      case MAP_TYPE_NODE:      case NODE:
669        josm_elemstyles_colorize_node(style, map_item->node);        josm_elemstyles_colorize_node(style, map_item->object.node);
670        break;        break;
671      default:      default:
672        g_assert((map_item->type == MAP_TYPE_NODE) ||        g_assert((map_item->object.type == NODE) ||
673                     (map_item->type == MAP_TYPE_WAY));                     (map_item->object.type == WAY));
674    }    }
675  }  }
676    
# Line 592  void map_item_redraw(appdata_t *appdata, Line 679  void map_item_redraw(appdata_t *appdata,
679    
680    /* check if the item to be redrawn is the selected one */    /* check if the item to be redrawn is the selected one */
681    gboolean is_selected = FALSE;    gboolean is_selected = FALSE;
682    if(map_item->ptr == appdata->map->selected.ptr) {    if(map_item->object.ptr == appdata->map->selected.object.ptr) {
683      map_item_deselect(appdata);      map_item_deselect(appdata);
684      is_selected = TRUE;      is_selected = TRUE;
685    }    }
# Line 603  void map_item_redraw(appdata_t *appdata, Line 690  void map_item_redraw(appdata_t *appdata,
690    
691    /* restore selection if there was one */    /* restore selection if there was one */
692    if(is_selected)    if(is_selected)
693      map_item_select(appdata, &item);      map_object_select(appdata, &item.object);
694  }  }
695    
696  static void map_frisket_rectangle(canvas_points_t *points,  static void map_frisket_rectangle(canvas_points_t *points,
# Line 793  map_item_t *map_item_at(map_t *map, gint Line 880  map_item_t *map_item_at(map_t *map, gint
880    if(map_item->highlight)    if(map_item->highlight)
881      printf("  item is highlight\n");      printf("  item is highlight\n");
882    
883    switch(map_item->type) {    switch(map_item->object.type) {
884    case MAP_TYPE_NODE:    case NODE:
885      printf("  item is node #%ld\n", map_item->node->id);      printf("  item is node #%ld\n", map_item->object.node->id);
886      break;      break;
887    case MAP_TYPE_WAY:    case WAY:
888      printf("  item is way #%ld\n", map_item->way->id);      printf("  item is way #%ld\n", map_item->object.way->id);
889      break;      break;
890    default:    default:
891      printf("  unknown item\n");      printf("  unknown item\n");
# Line 817  map_item_t *map_real_item_at(map_t *map, Line 904  map_item_t *map_real_item_at(map_t *map,
904    
905    /* get the item (parent) this item is the highlight of */    /* get the item (parent) this item is the highlight of */
906    map_item_t *parent = NULL;    map_item_t *parent = NULL;
907    switch(map_item->type) {    switch(map_item->object.type) {
908    
909    case MAP_TYPE_NODE:    case NODE:
910      if(map_item->node->map_item_chain)      if(map_item->object.node->map_item_chain)
911        parent = map_item->node->map_item_chain->map_item;        parent = map_item->object.node->map_item_chain->map_item;
912    
913      if(parent)      if(parent)
914        printf("  using parent item node #%ld\n", parent->node->id);        printf("  using parent item node #%ld\n", parent->object.node->id);
915      break;      break;
916    
917    case MAP_TYPE_WAY:    case WAY:
918      if(map_item->way->map_item_chain)      if(map_item->object.way->map_item_chain)
919        parent = map_item->way->map_item_chain->map_item;        parent = map_item->object.way->map_item_chain->map_item;
920    
921      if(parent)      if(parent)
922        printf("  using parent item way #%ld\n", parent->way->id);        printf("  using parent item way #%ld\n", parent->object.way->id);
923      break;      break;
924    
925    default:    default:
926      g_assert((map_item->type == MAP_TYPE_NODE) ||      g_assert((map_item->object.type == NODE) ||
927               (map_item->type == MAP_TYPE_WAY));               (map_item->object.type == WAY));
928      break;      break;
929    }    }
930    
# Line 994  void map_scroll_to_if_offscreen(map_t *m Line 1081  void map_scroll_to_if_offscreen(map_t *m
1081  /* Deselects the current way or node if its zoom_max  /* Deselects the current way or node if its zoom_max
1082   * 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. */
1083  void map_deselect_if_zoom_below_zoom_max(map_t *map) {  void map_deselect_if_zoom_below_zoom_max(map_t *map) {
1084      if (map->selected.type == MAP_TYPE_WAY) {      if (map->selected.object.type == WAY) {
1085          printf("will deselect way if zoomed below %f\n",          printf("will deselect way if zoomed below %f\n",
1086                 map->selected.way->draw.zoom_max);                 map->selected.object.way->draw.zoom_max);
1087          if (map->state->zoom < map->selected.way->draw.zoom_max) {          if (map->state->zoom < map->selected.object.way->draw.zoom_max) {
1088              printf("  deselecting way!\n");              printf("  deselecting way!\n");
1089              map_item_deselect(map->appdata);              map_item_deselect(map->appdata);
1090          }          }
1091      }      }
1092      else if (map->selected.type == MAP_TYPE_NODE) {      else if (map->selected.object.type == NODE) {
1093          printf("will deselect node if zoomed below %f\n",          printf("will deselect node if zoomed below %f\n",
1094                 map->selected.node->zoom_max);                 map->selected.object.node->zoom_max);
1095          if (map->state->zoom < map->selected.node->zoom_max) {          if (map->state->zoom < map->selected.object.node->zoom_max) {
1096              printf("  deselecting node!\n");              printf("  deselecting node!\n");
1097              map_item_deselect(map->appdata);              map_item_deselect(map->appdata);
1098          }          }
# Line 1105  gboolean map_item_is_selected_node(map_t Line 1192  gboolean map_item_is_selected_node(map_t
1192      return FALSE;      return FALSE;
1193    }    }
1194    
1195    if(map->selected.type == MAP_TYPE_ILLEGAL) {    if(map->selected.object.type == ILLEGAL) {
1196      printf("  nothing is selected\n");      printf("  nothing is selected\n");
1197      return FALSE;      return FALSE;
1198    }    }
1199    
1200    /* clicked the highlight directly */    /* clicked the highlight directly */
1201    if(map_item->type != MAP_TYPE_NODE) {    if(map_item->object.type != NODE) {
1202      printf("  didn't click node\n");      printf("  didn't click node\n");
1203      return FALSE;      return FALSE;
1204    }    }
1205    
1206    if(map->selected.type == MAP_TYPE_NODE) {    if(map->selected.object.type == NODE) {
1207      printf("  selected item is a node\n");      printf("  selected item is a node\n");
1208    
1209      if(map_item->node == map->selected.node) {      if(map_item->object.node == map->selected.object.node) {
1210        printf("  requested item is a selected node\n");        printf("  requested item is a selected node\n");
1211        return TRUE;        return TRUE;
1212      }      }
1213      printf("  but it's not the requested one\n");      printf("  but it's not the requested one\n");
1214      return FALSE;      return FALSE;
1215    
1216    } else if(map->selected.type == MAP_TYPE_WAY) {    } else if(map->selected.object.type == WAY) {
1217      printf("  selected item is a way\n");      printf("  selected item is a way\n");
1218    
1219      node_chain_t *node_chain = map->selected.way->node_chain;      node_chain_t *node_chain = map->selected.object.way->node_chain;
1220      while(node_chain) {      while(node_chain) {
1221        if(node_chain->node == map_item->node) {        if(node_chain->node == map_item->object.node) {
1222          printf("  requested item is part of selected way\n");          printf("  requested item is part of selected way\n");
1223          return TRUE;          return TRUE;
1224        }        }
# Line 1159  gboolean map_item_is_selected_way(map_t Line 1246  gboolean map_item_is_selected_way(map_t
1246      return FALSE;      return FALSE;
1247    }    }
1248    
1249    if(map->selected.type == MAP_TYPE_ILLEGAL) {    if(map->selected.object.type == ILLEGAL) {
1250      printf("  nothing is selected\n");      printf("  nothing is selected\n");
1251      return FALSE;      return FALSE;
1252    }    }
1253    
1254    /* clicked the highlight directly */    /* clicked the highlight directly */
1255    if(map_item->type != MAP_TYPE_WAY) {    if(map_item->object.type != WAY) {
1256      printf("  didn't click way\n");      printf("  didn't click way\n");
1257      return FALSE;      return FALSE;
1258    }    }
1259    
1260    if(map->selected.type == MAP_TYPE_WAY) {    if(map->selected.object.type == WAY) {
1261      printf("  selected item is a way\n");      printf("  selected item is a way\n");
1262    
1263      if(map_item->way == map->selected.way) {      if(map_item->object.way == map->selected.object.way) {
1264        printf("  requested item is a selected way\n");        printf("  requested item is a selected way\n");
1265        return TRUE;        return TRUE;
1266      }      }
# Line 1188  gboolean map_item_is_selected_way(map_t Line 1275  gboolean map_item_is_selected_way(map_t
1275    
1276  void map_highlight_refresh(appdata_t *appdata) {  void map_highlight_refresh(appdata_t *appdata) {
1277    map_t *map = appdata->map;    map_t *map = appdata->map;
1278    map_item_t old = map->selected;    object_t old = map->selected.object;
1279    
1280    printf("type to refresh is %d\n", old.type);    printf("type to refresh is %d\n", old.type);
1281    if(old.type == MAP_TYPE_ILLEGAL)    if(old.type == ILLEGAL)
1282      return;      return;
1283    
1284    map_item_deselect(appdata);    map_item_deselect(appdata);
1285    map_item_select(appdata, &old);    map_object_select(appdata, &old);
1286  }  }
1287    
1288  void map_way_delete(appdata_t *appdata, way_t *way) {  void map_way_delete(appdata_t *appdata, way_t *way) {
# Line 1223  static void map_handle_click(appdata_t * Line 1310  static void map_handle_click(appdata_t *
1310    /* problem: on_item may be the highlight itself! So store it! */    /* problem: on_item may be the highlight itself! So store it! */
1311    map_item_t map_item;    map_item_t map_item;
1312    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;
1313    else                      map_item.type = MAP_TYPE_ILLEGAL;    else                      map_item.object.type = ILLEGAL;
1314    
1315    /* if we aready have something selected, then de-select it */    /* if we aready have something selected, then de-select it */
1316    map_item_deselect(appdata);    map_item_deselect(appdata);
1317    
1318    /* select the clicked item (if there was one) */    /* select the clicked item (if there was one) */
1319    if(map_item.type != MAP_TYPE_ILLEGAL) {    if(map_item.object.type != ILLEGAL) {
1320      switch(map_item.type) {      switch(map_item.object.type) {
1321      case MAP_TYPE_NODE:      case NODE:
1322        map_node_select(appdata, map_item.node);        map_node_select(appdata, map_item.object.node);
1323        break;        break;
1324    
1325      case MAP_TYPE_WAY:      case WAY:
1326        map_way_select(appdata, map_item.way);        map_way_select(appdata, map_item.object.way);
1327        break;        break;
1328    
1329      default:      default:
1330        g_assert((map_item.type == MAP_TYPE_NODE) ||        g_assert((map_item.object.type == NODE) ||
1331                 (map_item.type == MAP_TYPE_WAY));                 (map_item.object.type == WAY));
1332        break;        break;
1333      }      }
1334    }    }
# Line 1261  static void map_touchnode_update(appdata Line 1348  static void map_touchnode_update(appdata
1348      /* in idle mode the dragged node is not highlighted */      /* in idle mode the dragged node is not highlighted */
1349    case MAP_ACTION_IDLE:    case MAP_ACTION_IDLE:
1350      g_assert(map->pen_down.on_item);      g_assert(map->pen_down.on_item);
1351      g_assert(map->pen_down.on_item->type == MAP_TYPE_NODE);      g_assert(map->pen_down.on_item->object.type == NODE);
1352      cur_node = map->pen_down.on_item->node;      cur_node = map->pen_down.on_item->object.node;
1353      break;      break;
1354    
1355    default:    default:
# Line 1385  static void map_button_release(map_t *ma Line 1472  static void map_button_release(map_t *ma
1472        map_item_t old_sel = map->selected;        map_item_t old_sel = map->selected;
1473        map_handle_click(map->appdata, map);        map_handle_click(map->appdata, map);
1474    
1475        if((old_sel.type != MAP_TYPE_ILLEGAL) &&        if((old_sel.object.type != ILLEGAL) &&
1476           (old_sel.type == map->selected.type) &&           (old_sel.object.type == map->selected.object.type) &&
1477           (old_sel.ptr == map->selected.ptr)) {           (old_sel.object.ptr == map->selected.object.ptr)) {
1478          printf("re-selected same item of type %d, "          printf("re-selected same item of type %d, "
1479                 "pushing it to the bottom\n", old_sel.type);                 "pushing it to the bottom\n", old_sel.object.type);
1480    
1481          if(!map->selected.item) {          if(!map->selected.item) {
1482            printf("  item has no visible representation to push\n");            printf("  item has no visible representation to push\n");
# Line 1730  void map_init(appdata_t *appdata) { Line 1817  void map_init(appdata_t *appdata) {
1817  }  }
1818    
1819    
 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;  
   
   default:  
     g_assert(0);  
     break;  
   }  
 }  
   
1820  void map_clear(appdata_t *appdata, gint group_mask) {  void map_clear(appdata_t *appdata, gint group_mask) {
1821    map_t *map = appdata->map;    map_t *map = appdata->map;
1822    
# Line 1799  void map_action_set(appdata_t *appdata, Line 1867  void map_action_set(appdata_t *appdata,
1867    
1868      /* remember if there was a way selected */      /* remember if there was a way selected */
1869      way_t *way_sel = NULL;      way_t *way_sel = NULL;
1870      if(appdata->map->selected.type == MAP_TYPE_WAY)      if(appdata->map->selected.object.type == WAY)
1871        way_sel = appdata->map->selected.way;        way_sel = appdata->map->selected.object.way;
1872    
1873      map_item_deselect(appdata);      map_item_deselect(appdata);
1874      map_edit_way_add_begin(appdata->map, way_sel);      map_edit_way_add_begin(appdata->map, way_sel);
# Line 1899  void map_delete_selected(appdata_t *appd Line 1967  void map_delete_selected(appdata_t *appd
1967    /* deleting the selected item de-selects it ... */    /* deleting the selected item de-selects it ... */
1968    map_item_deselect(appdata);    map_item_deselect(appdata);
1969    
1970    undo_remember_delete(appdata, item.type, item.ptr);    undo_remember_delete(appdata, &item.object);
1971    
1972    switch(item.type) {    switch(item.object.type) {
1973    case MAP_TYPE_NODE:    case NODE:
1974      printf("request to delete node #%ld\n", item.node->id);      printf("request to delete node #%ld\n", item.object.node->id);
1975    
1976      /* 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. */
1977      /* we cannot delete this as this would also delete the way */      /* we cannot delete this as this would also delete the way */
1978      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);
1979      if(way_chain) {      if(way_chain) {
1980        gboolean short_way = FALSE;        gboolean short_way = FALSE;
1981    
# Line 1933  void map_delete_selected(appdata_t *appd Line 2001  void map_delete_selected(appdata_t *appd
2001      }      }
2002    
2003      /* remove it visually from the screen */      /* remove it visually from the screen */
2004      map_item_chain_destroy(&item.node->map_item_chain);      map_item_chain_destroy(&item.object.node->map_item_chain);
2005    
2006      /* and mark it "deleted" in the database */      /* and mark it "deleted" in the database */
2007      osm_node_remove_from_relation(appdata->osm, item.node);      osm_node_remove_from_relation(appdata->osm, item.object.node);
2008      way_chain_t *chain = osm_node_delete(appdata->osm,      way_chain_t *chain = osm_node_delete(appdata->osm,
2009                           &appdata->icon, item.node, FALSE, TRUE);                           &appdata->icon, item.object.node, FALSE, TRUE);
2010    
2011      /* redraw all affected ways */      /* redraw all affected ways */
2012      while(chain) {      while(chain) {
# Line 1951  void map_delete_selected(appdata_t *appd Line 2019  void map_delete_selected(appdata_t *appd
2019          map_way_delete(appdata, chain->way);          map_way_delete(appdata, chain->way);
2020        } else {        } else {
2021          map_item_t item;          map_item_t item;
2022          item.type = MAP_TYPE_WAY;          item.object.type = WAY;
2023          item.way = chain->way;          item.object.way = chain->way;
2024          map_item_redraw(appdata, &item);          map_item_redraw(appdata, &item);
2025        }        }
2026    
# Line 1963  void map_delete_selected(appdata_t *appd Line 2031  void map_delete_selected(appdata_t *appd
2031    
2032      break;      break;
2033    
2034    case MAP_TYPE_WAY:    case WAY:
2035      printf("request to delete way #%ld\n", item.way->id);      printf("request to delete way #%ld\n", item.object.way->id);
2036      map_way_delete(appdata, item.way);      map_way_delete(appdata, item.object.way);
2037      break;      break;
2038    
2039    default:    default:
2040      g_assert((item.type == MAP_TYPE_NODE) ||      g_assert((item.object.type == NODE) ||
2041               (item.type == MAP_TYPE_WAY));               (item.object.type == WAY));
2042      break;      break;
2043    }    }
2044  }  }
2045    
2046  /* ----------------------- track related stuff ----------------------- */  /* ----------------------- track related stuff ----------------------- */
2047    
2048    static gboolean track_pos2lpos(bounds_t *bounds, pos_t *pos, lpos_t *lpos) {
2049      pos2lpos(bounds, pos, lpos);
2050    
2051      /* check if point is within bounds */
2052      return ((lpos->x >= bounds->min.x) && (lpos->x <= bounds->max.x) &&
2053              (lpos->y >= bounds->min.y) && (lpos->y <= bounds->max.y));
2054    }
2055    
2056  void map_track_draw_seg(map_t *map, track_seg_t *seg) {  void map_track_draw_seg(map_t *map, track_seg_t *seg) {
2057      bounds_t *bounds = map->appdata->osm->bounds;
2058    
2059    /* a track_seg needs at least 2 points to be drawn */    /* a track_seg needs at least 2 points to be drawn */
2060    guint pnum = track_seg_points(seg);    guint pnum = track_seg_points(seg);
2061    printf("seg of length %d\n", pnum);    printf("seg of length %d\n", pnum);
2062    
2063    if(pnum == 1) {    if(!pnum)
2064      g_assert(!seg->item);      return;
2065    
2066      seg->item = canvas_circle_new(map->canvas, CANVAS_GROUP_TRACK,    /* nothing should have been drawn by now ... */
2067            seg->track_point->lpos.x, seg->track_point->lpos.y,    g_assert(!seg->item_chain);
2068            map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR);  
2069    }    track_item_chain_t **itemP = &seg->item_chain;
2070      track_point_t *track_point = seg->track_point;
2071      while(track_point) {
2072        lpos_t lpos;
2073    
2074        /* skip all points not on screen */
2075        track_point_t *last = NULL;
2076        while(track_point && !track_pos2lpos(bounds, &track_point->pos, &lpos)) {
2077          last = track_point;
2078          track_point = track_point->next;
2079        }
2080    
2081        int visible = 0;
2082    
2083        /* count nodes that _are_ on screen */
2084        track_point_t *tmp = track_point;
2085        while(tmp && track_pos2lpos(bounds, &tmp->pos, &lpos)) {
2086          tmp = tmp->next;
2087          visible++;
2088        }
2089    
2090        /* actually start drawing with the last position that was offscreen */
2091        /* so the track nicely enters the viewing area */
2092        if(last) {
2093          track_point = last;
2094          visible++;
2095        }
2096    
2097        /* also use last one that's offscreen to nicely leave the visible area */
2098        if(tmp && tmp->next)
2099          visible++;
2100    
   if(pnum > 1) {  
   
2101      /* allocate space for nodes */      /* allocate space for nodes */
2102      canvas_points_t *points = canvas_points_new(pnum);      canvas_points_t *points = canvas_points_new(visible);
2103    
2104      int point = 0;      printf("visible are %d\n", visible);
2105      track_point_t *track_point = seg->track_point;      int point;
2106      while(track_point) {      for(point=0;point<visible;point++) {
2107        points->coords[point++] = track_point->lpos.x;        track_pos2lpos(bounds, &track_point->pos, &lpos);
2108        points->coords[point++] = track_point->lpos.y;  
2109          points->coords[2*point+0] = lpos.x;
2110          points->coords[2*point+1] = lpos.y;
2111        track_point = track_point->next;        track_point = track_point->next;
2112      }      }
   
     /* there may be a circle (one point line) */  
     if(seg->item)  
       canvas_item_destroy(seg->item);  
2113    
2114      seg->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,      *itemP = g_new0(track_item_chain_t, 1);
2115            points, map->style->track.width, map->style->track.color);      (*itemP)->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2116                     points, map->style->track.width, map->style->track.color);
2117        itemP = &(*itemP)->next;
2118    
2119      canvas_points_free(points);      canvas_points_free(points);
2120    }    }
2121  }  }
2122    
2123    /* update the last visible fragment of this segment since a */
2124    /* gps position may have been added */
2125  void map_track_update_seg(map_t *map, track_seg_t *seg) {  void map_track_update_seg(map_t *map, track_seg_t *seg) {
2126      bounds_t *bounds = map->appdata->osm->bounds;
2127    
2128      printf("-- APPENDING TO TRACK --\n");
2129    
2130    /* a track_seg needs at least 2 points to be drawn */    /* a track_seg needs at least 2 points to be drawn */
2131    guint pnum = track_seg_points(seg);    guint pnum = track_seg_points(seg);
2132    printf("seg of length %d\n", pnum);    printf("seg of length %d\n", pnum);
2133    
2134    if(pnum > 1) {    /* there are two cases: either the second last point was on screen */
2135      /* or it wasn't. We'll have to start a new screen item if the latter */
2136      /* is the case */
2137    
2138      /* search last point */
2139      track_point_t *begin = seg->track_point, *second_last = seg->track_point;
2140      lpos_t lpos;
2141      while(second_last && second_last->next && second_last->next->next) {
2142        if(!track_pos2lpos(bounds, &second_last->pos, &lpos))
2143          begin = second_last;
2144    
2145        second_last = second_last->next;
2146      }
2147      track_point_t *last = second_last->next;
2148    
2149      /* since we are updating an existing track, it sure has at least two */
2150      /* points, second_last must be valid and its "next" (last) also */
2151      g_assert(second_last);
2152      g_assert(last);
2153    
2154      /* check if the last and second_last points are visible */
2155      gboolean last_is_visible =
2156        track_pos2lpos(bounds, &last->pos, &lpos);
2157      gboolean second_last_is_visible =
2158        track_pos2lpos(bounds, &second_last->pos, &lpos);
2159    
2160      /* if both are invisible, then nothing has changed on screen */
2161      if(!last_is_visible && !second_last_is_visible) {
2162        printf("second_last and last entry are invisible -> doing nothing\n");
2163        return;
2164      }
2165    
2166      /* search last element in item chain */
2167      track_item_chain_t *item = seg->item_chain;
2168      while(item && item->next)
2169        item = item->next;
2170    
2171      if(second_last_is_visible) {
2172        /* there must be something already on the screen and there must */
2173        /* be visible nodes in the chain */
2174        g_assert(item);
2175        g_assert(begin);
2176    
2177        printf("second_last is visible -> append\n");
2178    
2179      /* allocate space for nodes */      /* count points to be placed */
2180      canvas_points_t *points = canvas_points_new(pnum);      int npoints = 0;
2181        track_point_t *tmp = begin;
2182        while(tmp) {
2183          tmp = tmp->next;
2184          npoints++;
2185        }
2186    
2187        printf("updating last segment to %d points\n", npoints);
2188    
2189        canvas_points_t *points = canvas_points_new(npoints);
2190    
2191        gint point = 0;
2192        while(begin) {
2193          track_pos2lpos(bounds, &begin->pos, &lpos);
2194          canvas_point_set_pos(points, point++, &lpos);
2195          begin = begin->next;
2196        }
2197    
2198      int point = 0;      canvas_item_set_points(item->item, points);
2199      track_point_t *track_point = seg->track_point;      canvas_points_free(points);
2200      while(track_point) {  
2201        canvas_point_set_pos(points, point++, &track_point->lpos);    } else {
2202        track_point = track_point->next;      printf("second last is invisible -> start new screen segment\n");
2203    
2204        /* the search for the "begin" ends with the second_last item */
2205        /* verify the last one also */
2206        if(begin->next && !track_pos2lpos(bounds, &begin->next->pos, &lpos))
2207          begin = begin->next;
2208    
2209        item->next = g_new0(track_item_chain_t, 1);
2210        item = item->next;
2211    
2212        /* count points to be placed */
2213        int npoints = 0;
2214        track_point_t *tmp = begin;
2215        while(tmp) {
2216          tmp = tmp->next;
2217          npoints++;
2218      }      }
2219    
2220        printf("attaching new segment with %d points\n", npoints);
2221    
2222        canvas_points_t *points = canvas_points_new(npoints);
2223    
2224        gint point = 0;
2225        while(begin) {
2226          track_pos2lpos(bounds, &begin->pos, &lpos);
2227          canvas_point_set_pos(points, point++, &lpos);
2228          begin = begin->next;
2229        }
2230    
2231        item->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2232                     points, map->style->track.width, map->style->track.color);
2233    
     g_assert(seg->item);  
     canvas_item_set_points(seg->item, points);  
2234      canvas_points_free(points);      canvas_points_free(points);
2235    }    }
2236    
2237  }  }
2238    
2239  void map_track_draw(map_t *map, track_t *track) {  void map_track_draw(map_t *map, track_t *track) {
# Line 2057  void map_track_remove(appdata_t *appdata Line 2256  void map_track_remove(appdata_t *appdata
2256    /* remove all segments */    /* remove all segments */
2257    track_seg_t *seg = track->track_seg;    track_seg_t *seg = track->track_seg;
2258    while(seg) {    while(seg) {
2259      if(seg->item) {      track_item_chain_t *item = seg->item_chain;
2260        canvas_item_destroy(seg->item);      while(item) {
2261        seg->item = NULL;        track_item_chain_t *next = item->next;
2262          canvas_item_destroy(item->item);
2263          item = next;
2264      }      }
2265    
2266        seg->item_chain = NULL;
2267      seg = seg->next;      seg = seg->next;
2268    }    }
2269  }  }
2270    
2271  void map_track_pos(appdata_t *appdata, lpos_t *lpos) {  void map_track_pos(appdata_t *appdata, pos_t *pos) {
2272    if(appdata->track.gps_item) {    if(appdata->track.gps_item) {
2273      canvas_item_destroy(appdata->track.gps_item);      canvas_item_destroy(appdata->track.gps_item);
2274      appdata->track.gps_item = NULL;      appdata->track.gps_item = NULL;
2275    }    }
2276    
2277    if(lpos)    if(pos) {
2278        lpos_t lpos;
2279        pos2lpos(appdata->osm->bounds, pos, &lpos);
2280    
2281      appdata->track.gps_item =      appdata->track.gps_item =
2282        canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,        canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,
2283          lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0,          lpos.x, lpos.y, appdata->map->style->track.width/2.0, 0,
2284                          appdata->map->style->track.gps_color, NO_COLOR);                          appdata->map->style->track.gps_color, NO_COLOR);
2285      }
2286  }  }
2287    
2288  /* ------------------- map background ------------------ */  /* ------------------- map background ------------------ */
# Line 2131  void map_hide_selected(appdata_t *appdat Line 2337  void map_hide_selected(appdata_t *appdat
2337    map_t *map = appdata->map;    map_t *map = appdata->map;
2338    if(!map) return;    if(!map) return;
2339    
2340    if(map->selected.type != MAP_TYPE_WAY) {    if(map->selected.object.type != WAY) {
2341      printf("selected item is not a way\n");      printf("selected item is not a way\n");
2342      return;      return;
2343    }    }
2344    
2345    way_t *way = map->selected.way;    way_t *way = map->selected.object.way;
2346    printf("hiding way #%ld\n", way->id);    printf("hiding way #%ld\n", way->id);
2347    
2348    map_item_deselect(appdata);    map_item_deselect(appdata);
# Line 2162  void map_show_all(appdata_t *appdata) { Line 2368  void map_show_all(appdata_t *appdata) {
2368    
2369    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);
2370  }  }
2371    
2372  // vim:et:ts=8:sw=2:sts=2:ai  // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.151  
changed lines
  Added in v.156