Diff of /trunk/src/map.c

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

src/map.c revision 1 by harbaum, Tue Dec 9 20:06:06 2008 UTC trunk/src/map.c revision 154 by harbaum, Tue Mar 31 06:31:53 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 56  static void map_statusbar(map_t *map, ma Line 62  static void map_statusbar(map_t *map, ma
62      str = g_strdup_printf("%s #%ld", item_str, id);      str = g_strdup_printf("%s #%ld", item_str, id);
63    
64      /* add some tags ... */      /* add some tags ... */
65        /*
66         *  XXX Should we just try to present only the name or the ref (or the
67         *  alt_name, old_name, whatever) here?  Hurling a load of tags in the
68         *  user's face in some unpredictable, uninformative order isn't very
69         *  friendly.
70         *
71         *  Actually, a tag_short_desc() function would be useful in dialogs
72         *  nd user messages too.
73         */
74      while(tag) {      while(tag) {
75        if(!collision && info_tag_key_collision(tags, tag))        if(!collision && info_tag_key_collision(tags, tag))
76          collision = TRUE;          collision = TRUE;
# Line 123  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 137  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 146  static void map_node_select(appdata_t *a Line 161  static void map_node_select(appdata_t *a
161    
162    float radius = map->style->highlight.width + map->style->node.radius;    float radius = map->style->highlight.width + map->style->node.radius;
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      gint w = gdk_pixbuf_get_width(map_item->node->icon_buf);       !appdata->settings->no_icons) {
166      gint h = gdk_pixbuf_get_height(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->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 156  static void map_node_select(appdata_t *a Line 172  static void map_node_select(appdata_t *a
172    
173    map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,    map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,
174                      x, y, radius, map->style->highlight.color);                      x, y, radius, map->style->highlight.color);
175    
176    if(!map_item->item) {    if(!map_item->item) {
177      /* and draw a fake node */      /* and draw a fake node */
178      new_map_item = g_new0(map_item_t, 1);      new_map_item = g_new0(map_item_t, 1);
179      memcpy(new_map_item, map_item, sizeof(map_item_t));      memcpy(new_map_item, map_item, sizeof(map_item_t));
180      new_map_item->highlight = TRUE;      new_map_item->highlight = TRUE;
181      map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,      map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item,
182                        x, y, map->style->node.radius,                        x, y, map->style->node.radius,
183                        map->style->highlight.node_color);                        map->style->highlight.node_color);
184    }    }
# Line 174  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 183  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 208  void map_way_select(appdata_t *appdata, Line 224  void map_way_select(appdata_t *appdata,
224        diff.x = node_chain->node->lpos.x - last->lpos.x;        diff.x = node_chain->node->lpos.x - last->lpos.x;
225        diff.y = node_chain->node->lpos.y - last->lpos.y;        diff.y = node_chain->node->lpos.y - last->lpos.y;
226    
227          /* only draw arrow if there's sufficient space */
228          /* TODO: what if there's not enough space anywhere? */
229        float len = sqrt(pow(diff.x, 2)+pow(diff.y, 2));        float len = sqrt(pow(diff.x, 2)+pow(diff.y, 2));
230        if(len > map->style->highlight.arrow_limit*arrow_width) {        if(len > map->style->highlight.arrow_limit*arrow_width) {
231          len /= arrow_width;          len /= arrow_width;
# Line 222  void map_way_select(appdata_t *appdata, Line 240  void map_way_select(appdata_t *appdata,
240          points->coords[2*2+0] = center.x - diff.y - diff.x;          points->coords[2*2+0] = center.x - diff.y - diff.x;
241          points->coords[2*2+1] = center.y + diff.x - diff.y;          points->coords[2*2+1] = center.y + diff.x - diff.y;
242    
243          map_hl_polygon_new(map, CANVAS_GROUP_NODES_HL, new_map_item,          map_hl_polygon_new(map, CANVAS_GROUP_WAYS_DIR, new_map_item,
244                             points, map->style->highlight.arrow_color);                             points, map->style->highlight.arrow_color);
245    
246          canvas_points_free(points);          canvas_points_free(points);
# Line 233  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;
259        gint y = node_chain->node->lpos.y;        gint y = node_chain->node->lpos.y;
260    
261        map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,        map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item,
262                          x, y, map->style->node.radius,                          x, y, map->style->node.radius,
263                          map->style->highlight.node_color);                          map->style->highlight.node_color);
264      }      }
# Line 257  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 269  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->type) {
322    
323        case NODE: {
324          node_t *node = member->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->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;
382      case WAY:
383        map_way_select(appdata, object->way);
384      break;      break;
385    case MAP_TYPE_WAY:    case RELATION:
386      map_way_select(appdata, map_item->way);      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 296  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 321  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 333  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 363  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_item->item = canvas_circle_new(map, CANVAS_GROUP_NODES,       map->appdata->settings->no_icons)
470        map_item->item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES,
471         node->lpos.x, node->lpos.y, radius, width, fill, border);         node->lpos.x, node->lpos.y, radius, width, fill, border);
472    else    else
473      map_item->item = canvas_image_new(map, CANVAS_GROUP_NODES,      map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES,
474        node->icon_buf,        node->icon_buf,
475        node->lpos.x - map->style->icon.scale/2 *        node->lpos.x - map->style->icon.scale/2 *
476                        gdk_pixbuf_get_width(node->icon_buf),                        gdk_pixbuf_get_width(node->icon_buf),
# Line 400  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_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);
508    
# Line 426  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.opaque)      if(map->style->area.color & 0xff)
534        map_item->item = canvas_polygon_new(map, group, points,        map_item->item = canvas_polygon_new(map->canvas, group, points,
535                                            width, color, fill_color);                                            width, color, fill_color);
536      else      else
537        map_item->item = canvas_polyline_new(map, group, points,        map_item->item = canvas_polyline_new(map->canvas, group, points,
538                                             width, color);                                             width, color);
539    } else {    } else {
540      map_item->item = canvas_polyline_new(map, group, points, width, color);      map_item->item = canvas_polyline_new(map->canvas, group, points, width, color);
541    }    }
542    
543    canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max);    canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max);
544    
545      /* a ways outline itself is never dashed */
546      if (group != CANVAS_GROUP_WAYS_OL)
547        if (way->draw.dashed)
548          canvas_item_set_dashed(map_item->item, width, way->draw.dash_length);
549    
550    /* attach map_item to ways map_item_chain */    /* attach map_item to ways map_item_chain */
551    map_item_chain_t **chain = &way->map_item_chain;    map_item_chain_t **chain = &way->map_item_chain;
552    while(*chain) chain = &(*chain)->next;    while(*chain) chain = &(*chain)->next;
# Line 458  static canvas_item_t *map_way_new(map_t Line 563  static canvas_item_t *map_way_new(map_t
563    
564  void map_show_node(map_t *map, node_t *node) {  void map_show_node(map_t *map, node_t *node) {
565    map_node_new(map, node, map->style->node.radius, 0,    map_node_new(map, node, map->style->node.radius, 0,
566                 RGB2CANVAS(map->style->node.color), 0);                 map->style->node.color, 0);
567  }  }
568    
569  void map_way_draw(map_t *map, way_t *way) {  void map_way_draw(map_t *map, way_t *way) {
# Line 473  void map_way_draw(map_t *map, way_t *way Line 578  void map_way_draw(map_t *map, way_t *way
578    if(nodes == 1) {    if(nodes == 1) {
579      /* draw a single dot where this single node is */      /* draw a single dot where this single node is */
580      map_way_single_new(map, way, map->style->node.radius, 0,      map_way_single_new(map, way, map->style->node.radius, 0,
581                         RGB2CANVAS(map->style->node.color), 0);                         map->style->node.color, 0);
582    } else {    } else {
583      canvas_points_t *points = canvas_points_new(nodes);      canvas_points_t *points = canvas_points_new(nodes);
584    
# Line 489  void map_way_draw(map_t *map, way_t *way Line 594  void map_way_draw(map_t *map, way_t *way
594        map_way_new(map, CANVAS_GROUP_POLYGONS, way, points,        map_way_new(map, CANVAS_GROUP_POLYGONS, way, points,
595                    way->draw.width, way->draw.color, way->draw.area.color);                    way->draw.width, way->draw.color, way->draw.area.color);
596      } else {      } else {
       map_way_new(map, CANVAS_GROUP_WAYS, way, points,  
                   way->draw.width, way->draw.color, NO_COLOR);  
597    
598        if(way->draw.flags & OSM_DRAW_FLAG_BG)        if(way->draw.flags & OSM_DRAW_FLAG_BG) {
599            map_way_new(map, CANVAS_GROUP_WAYS_INT, way, points,
600                        way->draw.width, way->draw.color, NO_COLOR);
601    
602          map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points,          map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points,
603                      way->draw.bg.width, way->draw.bg.color, NO_COLOR);                      way->draw.bg.width, way->draw.bg.color, NO_COLOR);
604    
605          } else
606            map_way_new(map, CANVAS_GROUP_WAYS, way, points,
607                        way->draw.width, way->draw.color, NO_COLOR);
608      }      }
609      canvas_points_free(points);      canvas_points_free(points);
610    }    }
# Line 509  void map_node_draw(map_t *map, node_t *n Line 619  void map_node_draw(map_t *map, node_t *n
619      map_node_new(map, node,      map_node_new(map, node,
620                   map->style->node.radius,                   map->style->node.radius,
621                   map->style->node.border_radius,                   map->style->node.border_radius,
622                   RGBA2CANVAS(map->style->node.fill_color,                   map->style->node.fill_color,
623                               map->style->node.has_fill_color?0xff:0x00),                   map->style->node.color);
                  RGB2CANVAS(map->style->node.color));  
624    
625    else if(map->style->node.show_untagged || osm_node_has_tag(node))    else if(map->style->node.show_untagged || osm_node_has_tag(node))
626      map_node_new(map, node,      map_node_new(map, node,
627                   map->style->node.radius, 0,                   map->style->node.radius, 0,
628                   RGB2CANVAS(map->style->node.color), 0);                   map->style->node.color, 0);
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 570  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 581  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 598  void map_frisket_draw(map_t *map, bounds Line 707  void map_frisket_draw(map_t *map, bounds
707    canvas_points_t *points = canvas_points_new(5);    canvas_points_t *points = canvas_points_new(5);
708    
709    /* don't draw frisket at all if it's completely transparent */    /* don't draw frisket at all if it's completely transparent */
710    if(map->style->frisket.opaque) {    if(map->style->frisket.color & 0xff) {
711      elemstyle_color_t color =      elemstyle_color_t color = map->style->frisket.color;
       (map->style->background.color<<8) | map->style->frisket.opaque;  
712    
713      float mult = map->style->frisket.mult;      float mult = map->style->frisket.mult;
714    
715      /* top rectangle */      /* top rectangle */
716      map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x,      map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x,
717                            mult*bounds->min.y, bounds->min.y);                            mult*bounds->min.y, bounds->min.y);
718      canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color);      canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points,
719                           1, NO_COLOR, color);
720    
721      /* bottom rectangle */      /* bottom rectangle */
722      map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x,      map_frisket_rectangle(points, mult*bounds->min.x, mult*bounds->max.x,
723                            bounds->max.y, mult*bounds->max.y);                            bounds->max.y, mult*bounds->max.y);
724      canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color);      canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points,
725                           1, NO_COLOR, color);
726    
727      /* left rectangle */      /* left rectangle */
728      map_frisket_rectangle(points, mult*bounds->min.x, bounds->min.x,      map_frisket_rectangle(points, mult*bounds->min.x, bounds->min.x,
729                            mult*bounds->min.y, mult*bounds->max.y);                            mult*bounds->min.y, mult*bounds->max.y);
730      canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color);      canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points,
731                           1, NO_COLOR, color);
732    
733      /* right rectangle */      /* right rectangle */
734      map_frisket_rectangle(points, bounds->max.x, mult*bounds->max.x,      map_frisket_rectangle(points, bounds->max.x, mult*bounds->max.x,
735                            mult*bounds->min.y, mult*bounds->max.y);                            mult*bounds->min.y, mult*bounds->max.y);
736      canvas_polygon_new(map, CANVAS_GROUP_NODES, points, 1, NO_COLOR, color);      canvas_polygon_new(map->canvas, CANVAS_GROUP_FRISKET, points,
737                           1, NO_COLOR, color);
738    
739    }    }
740    
# Line 633  void map_frisket_draw(map_t *map, bounds Line 745  void map_frisket_draw(map_t *map, bounds
745                            bounds->min.x-ew2, bounds->max.x+ew2,                            bounds->min.x-ew2, bounds->max.x+ew2,
746                            bounds->min.y-ew2, bounds->max.y+ew2);                            bounds->min.y-ew2, bounds->max.y+ew2);
747    
748      canvas_polyline_new(map, CANVAS_GROUP_NODES, points,      canvas_polyline_new(map->canvas, CANVAS_GROUP_FRISKET, points,
749                          map->style->frisket.border.width,                          map->style->frisket.border.width,
750                          map->style->frisket.border.color);                          map->style->frisket.border.color);
751    
# Line 765  map_item_t *map_item_at(map_t *map, gint Line 877  map_item_t *map_item_at(map_t *map, gint
877      return NULL;      return NULL;
878    }    }
879    
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 784  map_item_t *map_item_at(map_t *map, gint Line 896  map_item_t *map_item_at(map_t *map, gint
896  }  }
897    
898  /* get the real item (no highlight) at x, y */  /* get the real item (no highlight) at x, y */
899  static map_item_t *map_real_item_at(map_t *map, gint x, gint y) {  map_item_t *map_real_item_at(map_t *map, gint x, gint y) {
900    map_item_t *map_item = map_item_at(map, x, y);    map_item_t *map_item = map_item_at(map, x, y);
901    
902    /* no item or already a real one */    /* no item or already a real one */
# Line 792  static map_item_t *map_real_item_at(map_ Line 904  static map_item_t *map_real_item_at(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 824  static map_item_t *map_real_item_at(map_ Line 936  static map_item_t *map_real_item_at(map_
936    return map_item;    return map_item;
937  }  }
938    
   
   
 #ifdef USE_GOOCANVAS  
   
939  /* Limitations on the amount by which we can scroll. Keeps part of the  /* Limitations on the amount by which we can scroll. Keeps part of the
940   * map visible at all times */   * map visible at all times */
941  static void map_limit_scroll(map_t *map, gint *sx, gint *sy) {  static void map_limit_scroll(map_t *map, canvas_unit_t unit,
942      gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas));                               gint *sx, gint *sy) {
   
     gint sx_cu = *sx / zoom;  
     gint sy_cu = *sy / zoom;  
   
     // Canvas viewport dimensions  
     GtkAllocation *a = &GTK_WIDGET(map->canvas)->allocation;  
     gint aw_cu = a->width / zoom;  
     gint ah_cu = a->height / zoom;  
   
     // Data rect minimum and maximum  
     gint min_x, min_y, max_x, max_y;  
     min_x = map->appdata->osm->bounds->min.x;  
     min_y = map->appdata->osm->bounds->min.y;  
     max_x = map->appdata->osm->bounds->max.x;  
     max_y = map->appdata->osm->bounds->max.y;  
943    
944      // limit stops - prevent scrolling beyond these    /* get scale factor for pixel->meter conversion. set to 1 if */
945      gint min_sy_cu = 0.95*(min_y - ah_cu);    /* given coordinates are already in meters */
946      gint min_sx_cu = 0.95*(min_x - aw_cu);    gdouble scale = (unit == CANVAS_UNIT_METER)?1.0:canvas_get_zoom(map->canvas);
947      gint max_sy_cu = 0.95*(max_y);  
948      gint max_sx_cu = 0.95*(max_x);    /* convert pixels to meters if necessary */
949      if (sy_cu < min_sy_cu) { *sy = min_sy_cu*zoom; }    gdouble sx_cu = *sx / scale;
950      if (sx_cu < min_sx_cu) { *sx = min_sx_cu*zoom; }    gdouble sy_cu = *sy / scale;
951      if (sy_cu > max_sy_cu) { *sy = max_sy_cu*zoom; }  
952      if (sx_cu > max_sx_cu) { *sx = max_sx_cu*zoom; }    /* get size of visible area in canvas units (meters) */
953      gint aw_cu = canvas_get_viewport_width(map->canvas, CANVAS_UNIT_METER);
954      gint ah_cu = canvas_get_viewport_height(map->canvas, CANVAS_UNIT_METER);
955    
956      // Data rect minimum and maximum
957      gint min_x, min_y, max_x, max_y;
958      min_x = map->appdata->osm->bounds->min.x;
959      min_y = map->appdata->osm->bounds->min.y;
960      max_x = map->appdata->osm->bounds->max.x;
961      max_y = map->appdata->osm->bounds->max.y;
962    
963      // limit stops - prevent scrolling beyond these
964      gint min_sy_cu = 0.95*(min_y - ah_cu);
965      gint min_sx_cu = 0.95*(min_x - aw_cu);
966      gint max_sy_cu = 0.95*(max_y);
967      gint max_sx_cu = 0.95*(max_x);
968      if (sy_cu < min_sy_cu) { *sy = min_sy_cu * scale; }
969      if (sx_cu < min_sx_cu) { *sx = min_sx_cu * scale; }
970      if (sy_cu > max_sy_cu) { *sy = max_sy_cu * scale; }
971      if (sx_cu > max_sx_cu) { *sx = max_sx_cu * scale; }
972  }  }
973    
974    
# Line 870  static gboolean map_limit_zoom(map_t *ma Line 982  static gboolean map_limit_zoom(map_t *ma
982      max_x = map->appdata->osm->bounds->max.x;      max_x = map->appdata->osm->bounds->max.x;
983      max_y = map->appdata->osm->bounds->max.y;      max_y = map->appdata->osm->bounds->max.y;
984    
985      // Canvas viewport dimensions      /* get size of visible area in pixels and convert to meters of intended */
986      GtkAllocation *a = &GTK_WIDGET(map->canvas)->allocation;      /* zoom by deviding by zoom (which is basically pix/m) */
987      gint ah_cu = a->height / *zoom;      gint aw_cu =
988      gint aw_cu = a->width / *zoom;        canvas_get_viewport_width(map->canvas, CANVAS_UNIT_PIXEL) / *zoom;
989        gint ah_cu =
990          canvas_get_viewport_height(map->canvas, CANVAS_UNIT_PIXEL) / *zoom;
991    
992      gdouble oldzoom = *zoom;      gdouble oldzoom = *zoom;
993      if (ah_cu < aw_cu) {      if (ah_cu < aw_cu) {
# Line 898  static gboolean map_limit_zoom(map_t *ma Line 1012  static gboolean map_limit_zoom(map_t *ma
1012  }  }
1013    
1014    
1015  #if 0  /*
1016  /* Scroll the map a little towards the centre from where it is right now.   * Scroll the map to a point if that point is currently offscreen.
1017   * This is used as a cute recentring trick when the map is at its outer   */
1018   * scroll limit. */  void map_scroll_to_if_offscreen(map_t *map, lpos_t *lpos) {
 static void map_scroll_towards_centre(map_t *map, gdouble amt) {  
     gint sx, sy, sx_orig, sy_orig;  
     canvas_get_scroll_offsets(map->canvas, &sx, &sy);  
     gdouble zoom = goo_canvas_get_scale(GOO_CANVAS(map->canvas));  
     sx_orig=sx;  
     sy_orig=sy;  
   
     // Work in canvas units  
     gdouble sx_cu = sx / zoom;  
     gdouble sy_cu = sy / zoom;  
   
     // Map bounds  
     gdouble bmin_x_cu, bmin_y_cu, bmax_x_cu, bmax_y_cu;  
     bmin_x_cu = map->appdata->osm->bounds->min.x;  
     bmin_y_cu = map->appdata->osm->bounds->min.y;  
     bmax_x_cu = map->appdata->osm->bounds->max.x;  
     bmax_y_cu = map->appdata->osm->bounds->max.y;  
   
     // Canvas viewport dimensions  
     GtkAllocation *a = &GTK_WIDGET(map->canvas)->allocation;  
     gdouble ah_cu = a->height / zoom;  
     gdouble aw_cu = a->width / zoom;  
   
     // Scroll offsets that would recentre the map  
     gdouble centre_sx_cu, centre_sy_cu;  
     centre_sx_cu = - (aw_cu/2);  
     centre_sy_cu = - (ah_cu/2);  
   
     // Move towards centre by a given fraction of the whole map  
     if (sx_cu > centre_sx_cu) {  
         sx_cu -= ((bmax_x_cu - bmin_x_cu) * amt);  
         if (sx_cu < centre_sx_cu) {  
             printf("force-centre-x\n");  
             sx_cu = centre_sx_cu;  
         }  
     }  
     if (sx_cu < centre_sx_cu) {  
         sx_cu += ((bmax_x_cu - bmin_x_cu) * amt);  
         if (sx_cu > centre_sx_cu) {  
             printf("force-centre-x\n");  
             sx_cu = centre_sx_cu;  
         }  
     }  
1019    
1020      if (sy_cu > centre_sy_cu) {    // Ignore anything outside the working area
1021          sy_cu -= ((bmax_y_cu - bmin_y_cu) * amt);    if (!(map && map->appdata && map->appdata->osm)) {
1022          if (sy_cu < centre_sy_cu) {      return;
1023              printf("force-centre-y\n");    }
1024              sy_cu = centre_sy_cu;    gint min_x, min_y, max_x, max_y;
1025          }    min_x = map->appdata->osm->bounds->min.x;
1026      }    min_y = map->appdata->osm->bounds->min.y;
1027      if (sy_cu < centre_sy_cu) {    max_x = map->appdata->osm->bounds->max.x;
1028          sy_cu += ((bmax_y_cu - bmin_y_cu) * amt);    max_y = map->appdata->osm->bounds->max.y;
1029          if (sy_cu > centre_sy_cu) {    if (   (lpos->x > max_x) || (lpos->x < min_x)
1030              printf("force-centre-y\n");        || (lpos->y > max_y) || (lpos->y < min_y)) {
1031              sy_cu = centre_sy_cu;      printf("cannot scroll to (%d, %d): outside the working area\n",
1032          }             lpos->x, lpos->y);
1033      }      return;
1034      }
1035    
1036      // Viewport dimensions in canvas space
1037    
1038      // Back to pixels for setting the scroll    /* get size of visible area in canvas units (meters) */
1039      sx = (gint)(sx_cu * zoom);    gdouble pix_per_meter = canvas_get_zoom(map->canvas);
1040      sy = (gint)(sy_cu * zoom);    gdouble aw = canvas_get_viewport_width(map->canvas, CANVAS_UNIT_METER);
1041      canvas_scroll_to(map->canvas, sx, sy);    gdouble ah = canvas_get_viewport_height(map->canvas, CANVAS_UNIT_METER);
1042      map->state->scroll_offset.x = sx;  
1043      map->state->scroll_offset.y = sy;    // Is the point still onscreen?
1044      gboolean vert_recentre_needed = FALSE;
1045      gboolean horiz_recentre_needed = FALSE;
1046      gint sx, sy;
1047      canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy);
1048      gint viewport_left   = (sx/pix_per_meter);
1049      gint viewport_right  = (sx/pix_per_meter)+aw;
1050      gint viewport_top    = (sy/pix_per_meter);
1051      gint viewport_bottom = (sy/pix_per_meter)+ah;
1052      if (lpos->x > viewport_right) {
1053        printf("** off right edge (%d > %d)\n", lpos->x, viewport_right);
1054        horiz_recentre_needed = TRUE;
1055      }
1056      if (lpos->x < viewport_left) {
1057        printf("** off left edge (%d < %d)\n", lpos->x, viewport_left);
1058        horiz_recentre_needed = TRUE;
1059      }
1060      if (lpos->y > viewport_bottom) {
1061        printf("** off bottom edge (%d > %d)\n", lpos->y, viewport_bottom);
1062        vert_recentre_needed = TRUE;
1063      }
1064      if (lpos->y < viewport_top) {
1065        printf("** off top edge (%d < %d)\n", lpos->y, viewport_top);
1066        vert_recentre_needed = TRUE;
1067      }
1068    
1069      if (horiz_recentre_needed || vert_recentre_needed) {
1070        gint new_sx, new_sy;
1071    
1072        // Just centre both at once
1073        new_sx = pix_per_meter * (lpos->x - (aw/2));
1074        new_sy = pix_per_meter * (lpos->y - (ah/2));
1075    
1076        map_limit_scroll(map, CANVAS_UNIT_PIXEL, &new_sx, &new_sy);
1077        canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, new_sx, new_sy);
1078      }
1079  }  }
 #endif // #if 0  
 #endif // #ifdef USE_GOOCANVAS  
1080    
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 995  void map_deselect_if_zoom_below_zoom_max Line 1102  void map_deselect_if_zoom_below_zoom_max
1102  void map_set_zoom(map_t *map, double zoom,  void map_set_zoom(map_t *map, double zoom,
1103                    gboolean update_scroll_offsets) {                    gboolean update_scroll_offsets) {
1104    gboolean at_zoom_limit = 0;    gboolean at_zoom_limit = 0;
 #ifdef USE_GOOCANVAS  
1105    at_zoom_limit = map_limit_zoom(map, &zoom);    at_zoom_limit = map_limit_zoom(map, &zoom);
1106  #endif  
1107    map->state->zoom = zoom;    map->state->zoom = zoom;
1108    canvas_set_zoom(map->canvas, map->state->zoom);    canvas_set_zoom(map->canvas, map->state->zoom);
1109    
1110    map_deselect_if_zoom_below_zoom_max(map);    map_deselect_if_zoom_below_zoom_max(map);
1111    
1112    if (update_scroll_offsets) {    if(update_scroll_offsets) {
1113      if (!at_zoom_limit) {      if (!at_zoom_limit) {
1114        /* zooming affects the scroll offsets */        /* zooming affects the scroll offsets */
1115        gint sx, sy;        gint sx, sy;
1116        canvas_get_scroll_offsets(map->canvas, &sx, &sy);        canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy);
1117  #ifdef USE_GOOCANVAS        map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy);
1118        map_limit_scroll(map, &sx, &sy);  
1119        canvas_scroll_to(map->canvas, sx, sy);  // keep the map visible        // keep the map visible
1120  #endif        canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy);
       map->state->scroll_offset.x = sx;  
       map->state->scroll_offset.y = sy;  
     }  
 #ifdef USE_GOOCANVAS  
     else {  
       //      map_scroll_towards_centre(map, 0.20);  
1121      }      }
1122  #endif  
1123        canvas_scroll_get(map->canvas, CANVAS_UNIT_METER,
1124                          &map->state->scroll_offset.x,
1125                          &map->state->scroll_offset.y);
1126    }    }
1127  }  }
1128    
# Line 1044  static gboolean map_scroll_event(GtkWidg Line 1147  static gboolean map_scroll_event(GtkWidg
1147  static gboolean distance_above(map_t *map, gint x, gint y, gint limit) {  static gboolean distance_above(map_t *map, gint x, gint y, gint limit) {
1148    gint sx, sy;    gint sx, sy;
1149    
 #ifdef USE_GNOMECANVAS  
   gnome_canvas_get_scroll_offsets(GNOME_CANVAS(map->canvas), &sx, &sy);  
   
   /* add offsets generated by mouse within map and map scrolling */  
   sx = (x-map->pen_down.at.x) + (map->pen_down.so.x-sx);  
   sy = (y-map->pen_down.at.y) + (map->pen_down.so.y-sy);  
 #else  
1150    /* add offsets generated by mouse within map and map scrolling */    /* add offsets generated by mouse within map and map scrolling */
1151    sx = (x-map->pen_down.at.x);    sx = (x-map->pen_down.at.x);
1152    sy = (y-map->pen_down.at.y);    sy = (y-map->pen_down.at.y);
 #endif  
1153    
1154    return(sx*sx + sy*sy > limit*limit);    return(sx*sx + sy*sy > limit*limit);
1155  }  }
# Line 1063  static gboolean distance_above(map_t *ma Line 1158  static gboolean distance_above(map_t *ma
1158  static void map_do_scroll(map_t *map, gint x, gint y) {  static void map_do_scroll(map_t *map, gint x, gint y) {
1159    gint sx, sy;    gint sx, sy;
1160    
1161    canvas_get_scroll_offsets(map->canvas, &sx, &sy);    canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy);
1162    sx -= x-map->pen_down.at.x;    sx -= x-map->pen_down.at.x;
1163    sy -= y-map->pen_down.at.y;    sy -= y-map->pen_down.at.y;
1164  #ifdef USE_GOOCANVAS    map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy);
1165    map_limit_scroll(map, &sx, &sy);    canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy);
1166  #endif  
1167    canvas_scroll_to(map->canvas, sx, sy);    canvas_scroll_get(map->canvas, CANVAS_UNIT_METER,
1168    map->state->scroll_offset.x = sx;                      &map->state->scroll_offset.x,
1169    map->state->scroll_offset.y = sy;                      &map->state->scroll_offset.y);
1170  }  }
1171    
1172    
1173  /* scroll a certain step */  /* scroll a certain step */
1174  static void map_do_scroll_step(map_t *map, gint x, gint y) {  static void map_do_scroll_step(map_t *map, gint x, gint y) {
1175    gint sx, sy;    gint sx, sy;
1176    canvas_get_scroll_offsets(map->canvas, &sx, &sy);    canvas_scroll_get(map->canvas, CANVAS_UNIT_PIXEL, &sx, &sy);
1177    sx += x;    sx += x;
1178    sy += y;    sy += y;
1179  #ifdef USE_GOOCANVAS    map_limit_scroll(map, CANVAS_UNIT_PIXEL, &sx, &sy);
1180    map_limit_scroll(map, &sx, &sy);    canvas_scroll_to(map->canvas, CANVAS_UNIT_PIXEL, sx, sy);
 #endif  
   canvas_scroll_to(map->canvas, sx, sy);  
   map->state->scroll_offset.x = sx;  
   map->state->scroll_offset.y = sy;  
 }  
1181    
1182      canvas_scroll_get(map->canvas, CANVAS_UNIT_METER,
1183                        &map->state->scroll_offset.x,
1184                        &map->state->scroll_offset.y);
1185    }
1186    
1187  gboolean map_item_is_selected_node(map_t *map, map_item_t *map_item) {  gboolean map_item_is_selected_node(map_t *map, map_item_t *map_item) {
1188    printf("check if item is a selected node\n");    printf("check if item is a selected node\n");
# Line 1098  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 1152  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 1181  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 1216  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 1254  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 1307  static void map_button_press(map_t *map, Line 1401  static void map_button_press(map_t *map,
1401    map->pen_down.at.y = y;    map->pen_down.at.y = y;
1402    map->pen_down.drag = FALSE;     // don't assume drag yet    map->pen_down.drag = FALSE;     // don't assume drag yet
1403    
 #ifdef USE_GNOMECANVAS  
   /* save initial scroll offset */  
   gnome_canvas_get_scroll_offsets(GNOME_CANVAS(map->canvas),  
                   &map->pen_down.so.x, &map->pen_down.so.y);  
 #endif  
   
1404    /* determine wether this press was on an item */    /* determine wether this press was on an item */
1405    map->pen_down.on_item = map_real_item_at(map, x, y);    map->pen_down.on_item = map_real_item_at(map, x, y);
1406    
# Line 1384  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 1505  static gboolean map_motion_notify_event( Line 1593  static gboolean map_motion_notify_event(
1593    /* reduce update frequency on hildon to keep screen update fluid */    /* reduce update frequency on hildon to keep screen update fluid */
1594    static guint32 last_time = 0;    static guint32 last_time = 0;
1595    
1596    if(event->time - last_time < 100) return FALSE;    if(event->time - last_time < 250) return FALSE;
1597    last_time = event->time;    last_time = event->time;
1598  #endif  #endif
1599    
1600    if(!map->pen_down.is)    if(!map->pen_down.is)
1601      return FALSE;      return FALSE;
1602    
1603  #ifdef USE_GNOMECANVAS  #ifndef USE_GOOCANVAS
1604    /* handle hints, hints are handled by goocanvas directly */    /* handle hints, hints are handled by goocanvas directly */
1605    if(event->is_hint)    if(event->is_hint)
1606      gdk_window_get_pointer(event->window, &x, &y, &state);      gdk_window_get_pointer(event->window, &x, &y, &state);
# Line 1549  static gboolean map_motion_notify_event( Line 1637  static gboolean map_motion_notify_event(
1637    case MAP_ACTION_NODE_ADD:    case MAP_ACTION_NODE_ADD:
1638      map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius);      map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius);
1639      break;      break;
1640    
1641    case MAP_ACTION_WAY_ADD:    case MAP_ACTION_WAY_ADD:
1642      map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius);      map_hl_cursor_draw(map, x, y, FALSE, map->style->node.radius);
1643      map_touchnode_update(appdata, x, y);      map_touchnode_update(appdata, x, y);
# Line 1654  GtkWidget *map_new(appdata_t *appdata) { Line 1742  GtkWidget *map_new(appdata_t *appdata) {
1742    map_t *map = appdata->map = g_new0(map_t, 1);    map_t *map = appdata->map = g_new0(map_t, 1);
1743    
1744    map->style = style_load(appdata, appdata->settings->style);    map->style = style_load(appdata, appdata->settings->style);
1745      if(!map->style) {
1746        errorf(NULL, _("Unable to load valid style, terminating."));
1747        g_free(map);
1748        return NULL;
1749      }
1750    
1751    if(appdata->project && appdata->project->map_state) {    if(appdata->project && appdata->project->map_state) {
1752      printf("Using projects map state\n");      printf("Using projects map state\n");
# Line 1671  GtkWidget *map_new(appdata_t *appdata) { Line 1764  GtkWidget *map_new(appdata_t *appdata) {
1764    map->appdata = appdata;    map->appdata = appdata;
1765    map->action.type = MAP_ACTION_IDLE;    map->action.type = MAP_ACTION_IDLE;
1766    
1767  #ifdef USE_GNOMECANVAS    map->canvas = canvas_new(map->style->background.color);
1768    map->canvas = gnome_canvas_new_aa();  // _aa    canvas_set_antialias(map->canvas, !appdata->settings->no_antialias);
   
   /* create the groups */  
   canvas_group_t group;  
   for(group = 0; group < CANVAS_GROUPS; group++)  
     map->group[group] = gnome_canvas_item_new(  
                 gnome_canvas_root(GNOME_CANVAS(map->canvas)),  
                 GNOME_TYPE_CANVAS_GROUP,  
                 NULL);  
   
   gtk_widget_modify_bg(map->canvas, GTK_STATE_NORMAL,  
                        &map->canvas->style->white);  
   
 #else  
   map->canvas = goo_canvas_new();  
   
   g_object_set(G_OBJECT(map->canvas), "anchor", GTK_ANCHOR_CENTER, NULL);  
   g_object_set(G_OBJECT(map->canvas), "background-color-rgb",  
                map->style->background.color, NULL);  
   
   GooCanvasItem *root = goo_canvas_get_root_item(GOO_CANVAS(map->canvas));  
   
   /* create the groups */  
   canvas_group_t group;  
   for(group = 0; group < CANVAS_GROUPS; group++)  
     map->group[group] = goo_canvas_group_new(root, NULL);  
1769    
1770  #endif    GtkWidget *canvas_widget = canvas_get_widget(map->canvas);
1771    
1772    gtk_widget_set_events(map->canvas,    gtk_widget_set_events(canvas_widget,
1773                            GDK_BUTTON_PRESS_MASK                            GDK_BUTTON_PRESS_MASK
1774                          | GDK_BUTTON_RELEASE_MASK                          | GDK_BUTTON_RELEASE_MASK
1775                          | GDK_SCROLL_MASK                          | GDK_SCROLL_MASK
1776                          | GDK_POINTER_MOTION_MASK                          | GDK_POINTER_MOTION_MASK
1777                          | GDK_POINTER_MOTION_HINT_MASK);                          | GDK_POINTER_MOTION_HINT_MASK);
1778    
1779    gtk_signal_connect(GTK_OBJECT(map->canvas),    gtk_signal_connect(GTK_OBJECT(canvas_widget),
1780       "button_press_event", G_CALLBACK(map_button_event), appdata);       "button_press_event", G_CALLBACK(map_button_event), appdata);
1781    gtk_signal_connect(GTK_OBJECT(map->canvas),    gtk_signal_connect(GTK_OBJECT(canvas_widget),
1782       "button_release_event", G_CALLBACK(map_button_event), appdata);       "button_release_event", G_CALLBACK(map_button_event), appdata);
1783    gtk_signal_connect(GTK_OBJECT(map->canvas),    gtk_signal_connect(GTK_OBJECT(canvas_widget),
1784       "motion_notify_event", G_CALLBACK(map_motion_notify_event), appdata);       "motion_notify_event", G_CALLBACK(map_motion_notify_event), appdata);
1785    gtk_signal_connect(GTK_OBJECT(map->canvas),    gtk_signal_connect(GTK_OBJECT(canvas_widget),
1786       "scroll_event", G_CALLBACK(map_scroll_event), appdata);       "scroll_event", G_CALLBACK(map_scroll_event), appdata);
1787    
1788    gtk_signal_connect(GTK_OBJECT(map->canvas),    gtk_signal_connect(GTK_OBJECT(canvas_widget),
1789       "destroy", G_CALLBACK(map_destroy_event), appdata);       "destroy", G_CALLBACK(map_destroy_event), appdata);
1790    
1791    return map->canvas;    return canvas_widget;
1792  }  }
1793    
1794  void map_init(appdata_t *appdata) {  void map_init(appdata_t *appdata) {
# Line 1739  void map_init(appdata_t *appdata) { Line 1807  void map_init(appdata_t *appdata) {
1807                      mult*appdata->osm->bounds->max.x,                      mult*appdata->osm->bounds->max.x,
1808                      mult*appdata->osm->bounds->max.y);                      mult*appdata->osm->bounds->max.y);
1809    
1810    printf("restore scroll offsets %d/%d\n",    printf("restore scroll position %d/%d\n",
1811           map->state->scroll_offset.x, map->state->scroll_offset.y);           map->state->scroll_offset.x, map->state->scroll_offset.y);
1812    
1813    canvas_scroll_to(map->canvas,    map_limit_scroll(map, CANVAS_UNIT_METER,
1814                     map->state->scroll_offset.x, map->state->scroll_offset.y);             &map->state->scroll_offset.x, &map->state->scroll_offset.y);
1815      canvas_scroll_to(map->canvas, CANVAS_UNIT_METER,
1816               map->state->scroll_offset.x, map->state->scroll_offset.y);
1817  }  }
1818    
1819    
1820  void map_item_set_flags(map_item_t *map_item, int set, int clr) {  void map_clear(appdata_t *appdata, gint group_mask) {
   
   switch(map_item->type) {  
   case MAP_TYPE_NODE:  
     map_item->node->flags |=  set;  
     map_item->node->flags &= ~clr;  
     break;  
   
   case MAP_TYPE_WAY:  
     map_item->way->flags |=  set;  
     map_item->way->flags &= ~clr;  
     break;  
   
   default:  
     g_assert(0);  
     break;  
   }  
 }  
   
 void map_clear(appdata_t *appdata, gint layer_mask) {  
1821    map_t *map = appdata->map;    map_t *map = appdata->map;
1822    
1823    printf("freeing map contents\n");    printf("freeing map contents\n");
# Line 1776  void map_clear(appdata_t *appdata, gint Line 1827  void map_clear(appdata_t *appdata, gint
1827    /* remove a possibly existing highlight */    /* remove a possibly existing highlight */
1828    map_item_deselect(appdata);    map_item_deselect(appdata);
1829    
1830    canvas_group_t group;    canvas_erase(map->canvas, group_mask);
   for(group=0;group<CANVAS_GROUPS;group++) {  
   
 #ifdef USE_GNOMECANVAS  
     /* destroy the entire group */  
     canvas_item_destroy(map->group[group]);  
   
     /* and create an empty new one */  
     map->group[group] = gnome_canvas_item_new(  
                       gnome_canvas_root(GNOME_CANVAS(map->canvas)),  
                       GNOME_TYPE_CANVAS_GROUP,  
                       NULL);  
 #else  
     if(layer_mask & (1<<group)) {  
       gint children = goo_canvas_item_get_n_children(map->group[group]);  
       printf("Removing %d children from layer %d\n", children, group);  
       while(children--)  
         goo_canvas_item_remove_child(map->group[group], children);  
     }  
 #endif  
   }  
1831  }  }
1832    
1833  void map_paint(appdata_t *appdata) {  void map_paint(appdata_t *appdata) {
1834    map_t *map = appdata->map;    map_t *map = appdata->map;
1835    
1836      /* user may have changed antialias settings */
1837      canvas_set_antialias(map->canvas, !appdata->settings->no_antialias);
1838    
1839    josm_elemstyles_colorize_world(map->style, appdata->osm);    josm_elemstyles_colorize_world(map->style, appdata->osm);
1840    map_draw(map, appdata->osm);    map_draw(map, appdata->osm);
1841  }  }
# Line 1833  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 1933  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    switch(item.type) {    undo_remember_delete(appdata, item.object.type, item.object.ptr);
1971    case MAP_TYPE_NODE:  
1972      printf("request to delete node #%ld\n", item.node->id);    switch(item.object.type) {
1973      case NODE:
1974        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 1965  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 1983  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 1995  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  }  }
# Line 2017  void map_track_draw_seg(map_t *map, trac Line 2053  void map_track_draw_seg(map_t *map, trac
2053    if(pnum == 1) {    if(pnum == 1) {
2054      g_assert(!seg->item);      g_assert(!seg->item);
2055    
2056      seg->item = canvas_circle_new(map, CANVAS_GROUP_TRACK,      seg->item = canvas_circle_new(map->canvas, CANVAS_GROUP_TRACK,
2057            seg->track_point->lpos.x, seg->track_point->lpos.y,            seg->track_point->lpos.x, seg->track_point->lpos.y,
2058            map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR);            map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR);
2059    }    }
# Line 2039  void map_track_draw_seg(map_t *map, trac Line 2075  void map_track_draw_seg(map_t *map, trac
2075      if(seg->item)      if(seg->item)
2076        canvas_item_destroy(seg->item);        canvas_item_destroy(seg->item);
2077    
2078      seg->item = canvas_polyline_new(map, CANVAS_GROUP_TRACK,      seg->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2079            points, map->style->track.width, map->style->track.color);            points, map->style->track.width, map->style->track.color);
2080    
2081      canvas_points_free(points);      canvas_points_free(points);
# Line 2105  void map_track_pos(appdata_t *appdata, l Line 2141  void map_track_pos(appdata_t *appdata, l
2141    }    }
2142    
2143    if(lpos)    if(lpos)
2144      appdata->track.gps_item = canvas_circle_new(appdata->map, CANVAS_GROUP_GPS,      appdata->track.gps_item =
2145          canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,
2146          lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0,          lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0,
2147                          RGB2CANVAS(appdata->map->style->track.gps_color), NO_COLOR);                          appdata->map->style->track.gps_color, NO_COLOR);
2148  }  }
2149    
2150  /* ------------------- map background ------------------ */  /* ------------------- map background ------------------ */
# Line 2148  void map_set_bg_image(map_t *map, char * Line 2185  void map_set_bg_image(map_t *map, char *
2185    map->bg.scale.y = (float)(bounds->max.y - bounds->min.y)/    map->bg.scale.y = (float)(bounds->max.y - bounds->min.y)/
2186      (float)gdk_pixbuf_get_height(map->bg.pix);      (float)gdk_pixbuf_get_height(map->bg.pix);
2187    
2188    map->bg.item = canvas_image_new(map, CANVAS_GROUP_BG, map->bg.pix,    map->bg.item = canvas_image_new(map->canvas, CANVAS_GROUP_BG, map->bg.pix,
2189            bounds->min.x, bounds->min.y, map->bg.scale.x, map->bg.scale.y);            bounds->min.x, bounds->min.y, map->bg.scale.x, map->bg.scale.y);
2190    
2191    canvas_item_destroy_connect(map->bg.item,    canvas_item_destroy_connect(map->bg.item,
# Line 2162  void map_hide_selected(appdata_t *appdat Line 2199  void map_hide_selected(appdata_t *appdat
2199    map_t *map = appdata->map;    map_t *map = appdata->map;
2200    if(!map) return;    if(!map) return;
2201    
2202    if(map->selected.type != MAP_TYPE_WAY) {    if(map->selected.object.type != WAY) {
2203      printf("selected item is not a way\n");      printf("selected item is not a way\n");
2204      return;      return;
2205    }    }
2206    
2207    way_t *way = map->selected.way;    way_t *way = map->selected.object.way;
2208    printf("hiding way #%ld\n", way->id);    printf("hiding way #%ld\n", way->id);
2209    
2210    map_item_deselect(appdata);    map_item_deselect(appdata);
# Line 2193  void map_show_all(appdata_t *appdata) { Line 2230  void map_show_all(appdata_t *appdata) {
2230    
2231    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);
2232  }  }
2233    
2234    // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.1  
changed lines
  Added in v.154