MAP_ZOOMED_IN,
MAP_ZOOMED_OUT,
+ MAP_PANNED,
+
+ MARKER_CLICK,
+
LAST_SIGNAL
};
}
#endif
+priv->buffer=NULL;
+
gtk_widget_set_extension_events(GTK_WIDGET(map), GDK_EXTENSION_EVENTS_ALL);
gtk_widget_add_events(GTK_WIDGET(map), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
+g_return_val_if_fail(priv->buffer, FALSE);
+
style=widget->style;
-gdk_draw_drawable(GDK_DRAWABLE(map->map),
+gdk_draw_drawable(GDK_DRAWABLE(map),
style->fg_gc[GTK_STATE_NORMAL],
priv->buffer,
event->area.x + priv->offsetx,
while ((dest_dim >>= ratio_p2) > 1);
}
+static gboolean
+gtk_map_render_tile(GtkWidget *widget, guint tilex, guint tiley, guint destx, guint desty, gboolean fast_fail)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+GdkPixbuf *pixbuf=NULL;
+gint zoff;
+
+g_return_if_fail(GTK_IS_MAP(widget));
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+g_return_val_if_fail(priv->buffer, FALSE);
+
+if (destx > priv->buf_width_pixels || desty > priv->buf_height_pixels)
+ return FALSE;
+
+if (tilex > priv->world_size_tiles || tiley > priv->world_size_tiles)
+ return FALSE;
+
+/* g_debug("MAP RT: %u %u (%u) %u %u (%u, %u)", tilex, tiley, priv->world_size_tiles, destx, desty, buf_width_tiles, buf_height_tiles); */
+
+/* The tile is possible. */
+for (zoff = (_curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zoff) <= priv->max_zoom && zoff <= TILE_SIZE_P2; zoff += 1) {
+ pixbuf=gtk_map_tile_load(map, tilex, tiley, zoff, !fast_fail);
+ if (!pixbuf) {
+ if (!fast_fail)
+ fast_fail=TRUE;
+ } else {
+ /* Check if we need to blit. */
+ if (zoff) {
+ gtk_map_pixbuf_scale_inplace(pixbuf, zoff,
+ (tilex - ((tilex >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff),
+ (tiley - ((tiley >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff));
+ image_cache_invalidate_by_image(priv->icache, pixbuf);
+ }
+ }
+}
+
+if (pixbuf) {
+ gdk_draw_pixbuf(priv->buffer, _gc[COLORABLE_MARK], pixbuf, 0, 0, destx, desty, TILE_SIZE_PIXELS, TILE_SIZE_PIXELS, GDK_RGB_DITHER_NONE, 0, 0);
+ g_object_unref(pixbuf);
+ return TRUE;
+}
+gdk_draw_rectangle(priv->buffer, map->style->black_gc, TRUE, destx, desty, TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+return TRUE;
+}
+
+gboolean
+gtk_map_set_center(GtkWidget *map, guint new_center_unitx, guint new_center_unity)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+gint new_base_tilex, new_base_tiley;
+guint new_x, new_y;
+guint j, k, base_new_x, base_old_x, old_x, old_y, iox, ioy;
+
+/* Assure that _center.unitx/y are bounded. */
+BOUND(new_center_unitx, priv->min_center.unitx, priv->max_center.unitx);
+BOUND(new_center_unity, priv->min_center.unity, priv->max_center.unity);
+
+priv->center.unitx = new_center_unitx;
+priv->center.unity = new_center_unity;
+
+new_base_tilex = grid2tile((gint) pixel2grid((gint)unit2pixel((gint) priv->center.unitx)) - (gint)priv->screen_grids_halfwidth);
+new_base_tiley = grid2tile(pixel2grid(unit2pixel(priv->center.unity)) - priv->screen_grids_halfheight);
+
+/* Same zoom level, so it's likely that we can reuse some of the old
+ * buffer's pixels. */
+
+if (new_base_tilex != priv->base_tilex || new_base_tiley != priv->base_tiley) {
+ /* If copying from old parts to new parts, we need to make sure we
+ * don't overwrite the old parts when copying, so set up new_x,
+ * new_y, old_x, old_y, iox, and ioy with that in mind. */
+ if (new_base_tiley < priv->base_tiley) {
+ /* New is lower than old - start at bottom and go up. */
+ new_y = buf_height_tiles - 1;
+ ioy = -1;
+ } else {
+ /* New is higher than old - start at top and go down. */
+ new_y = 0;
+ ioy = 1;
+ }
+ if (new_base_tilex < priv->base_tilex) {
+ /* New is righter than old - start at right and go left. */
+ base_new_x = buf_width_tiles - 1;
+ iox = -1;
+ } else {
+ /* New is lefter than old - start at left and go right. */
+ base_new_x = 0;
+ iox = 1;
+ }
+
+ /* Iterate over the y tile values. */
+ old_y = new_y + new_base_tiley - priv->base_tiley;
+ base_old_x = base_new_x + new_base_tilex - priv->base_tilex;
+ priv->base_tilex = new_base_tilex;
+ priv->base_tiley = new_base_tiley;
+
+ for (j = 0; j < buf_height_tiles; ++j, new_y += ioy, old_y += ioy) {
+ new_x = base_new_x;
+ old_x = base_old_x;
+ /* Iterate over the x tile values. */
+ for (k = 0; k < buf_width_tiles; ++k, new_x += iox, old_x += iox) {
+ /* Can we get this grid block from the old buffer?. */
+ if (old_x >= 0 && old_x < buf_width_tiles && old_y >= 0 && old_y < buf_height_tiles) {
+ /* Copy from old buffer to new buffer. */
+ gdk_draw_drawable(priv->buffer,
+ _gc[COLORABLE_MARK],
+ priv->buffer,
+ old_x * TILE_SIZE_PIXELS,
+ old_y * TILE_SIZE_PIXELS,
+ new_x * TILE_SIZE_PIXELS,
+ new_y * TILE_SIZE_PIXELS,
+ TILE_SIZE_PIXELS,
+ TILE_SIZE_PIXELS);
+ } else {
+ gtk_map_render_tile(map, new_base_tilex + new_x,
+ new_base_tiley + new_y,
+ new_x * TILE_SIZE_PIXELS,
+ new_y * TILE_SIZE_PIXELS,
+ map_drag_id!=0 ? TRUE : FALSE);
+ }
+ }
+ }
+ gtk_map_render_data(map);
+}
+
+MACRO_RECALC_OFFSET();
+MACRO_RECALC_FOCUS_BASE(priv->center_ratio);
+
+gtk_map_set_mark(&_gps->data);
+gtk_map_refresh(map);
+}
+
void
gtk_map_refresh(GtkWidget *widget)
{
gtk_widget_queue_draw_area(widget, 0, 0, map->width, map->height);
}
-gint gtk_map_get_zoom(GtkWidget *map)
+gint
+gtk_map_get_zoom(GtkWidget *map)
{
GtkMap *map;
GtkMapPriv *priv;
return priv->zoom;
}
+gboolean
+gtk_map_set_zoom(GtkWidget *map, gint new_zoom)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+if (new_zoom > (priv->max_zoom - 1))
+ return FALSE;
+
+if (new_zoom == priv->zoom)
+ return FALSE;
+
+priv->zoom = new_zoom / _curr_repo->view_zoom_steps * _curr_repo->view_zoom_steps;
+priv->world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
+
+/* If we're leading, update the center to reflect new zoom level. */
+MACRO_RECALC_CENTER(_gps->data, priv->center.unitx, priv->center.unity);
+
+/* Update center bounds to reflect new zoom level. */
+priv->min_center.unitx = pixel2unit(grid2pixel(priv->screen_grids_halfwidth));
+priv->min_center.unity = pixel2unit(grid2pixel(priv->screen_grids_halfheight));
+priv->max_center.unitx = WORLD_SIZE_UNITS - grid2unit(priv->screen_grids_halfwidth) - 1;
+priv->max_center.unity = WORLD_SIZE_UNITS - grid2unit(priv->screen_grids_halfheight) - 1;
+
+BOUND(priv->center.unitx, priv->min_center.unitx, priv->max_center.unitx);
+BOUND(priv->center.unity, priv->min_center.unity, priv->max_center.unity);
+
+priv->base_tilex = grid2tile((gint) pixel2grid((gint) unit2pixel((gint) priv->center.unitx)) - (gint) priv->screen_grids_halfwidth);
+priv->base_tiley = grid2tile(pixel2grid(unit2pixel(priv->center.unity)) - priv->screen_grids_halfheight);
+
+/* New zoom level, so we can't reuse the old buffer's pixels. */
+/* Update state variables. */
+MACRO_RECALC_OFFSET();
+MACRO_RECALC_FOCUS_BASE(priv->center_ratio);
+MACRO_RECALC_FOCUS_SIZE(priv->center_ratio);
+
+gtk_map_set_mark(&_gps->data);
+gtk_map_refresh(map);
+
+return TRUE;
+}
+
+
gint
gtk_map_zoom(GtkWidget *widget, gint zdir)
{