* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "config.h"
+
#include <stdlib.h>
#include <glib/gstdio.h>
#include <glib-object.h>
#define BUF_WIDTH_PIXELS (1024)
#define BUF_HEIGHT_PIXELS (768)
-#define SCALE_WIDTH (300)
+/* Filename buffer */
+#define BUFFER_SIZE (2048)
+
+#define SCALE_WIDTH (256)
#define MAP_CACHE_DEFAULT (64)
cairo_t *ct;
#endif
+ GtkMenu *menu;
+
PangoContext *context;
PangoLayout *layout;
PangoFontDescription *fontdesc;
PangoLayout *scale_layout;
PangoFontDescription *scale_font;
- GdkGC *gc_h;
- GdkGC *gc_w;
- GdkGC *gc_d;
+ GdkGC *gc_track;
+ GdkGC *gc_route;
+ GdkGC *gc_waypoint;
+ GdkGC *gc_break;
+
+ GdkGC *gc_mark;
+ GdkGC *gc_velvec;
GdkGC *speed_gc1;
GdkGC *speed_gc2;
GdkGC *speed_gc;
+ /* OpenGL data */
+#ifdef WITH_GL
+ GdkGLConfig* gl_config;
+#endif
+ gboolean gl;
+
GdkRectangle scale_rect;
RepoData *curr_repo;
GTimer *timer;
ImageCache *icache;
- GList *markers;
- /* OpenGL data */
-#ifdef WITH_GL
- GdkGLConfig* gl_config;
-#endif
- gboolean gl;
-
- GdkGC *gc_mark;
- GdkGC *gc_velvec;
+ GSList *markers;
/* Cached Location dot x,y values */
gint mark_x1;
GdkRectangle mark_rect;
GtkMapCenterMode center_mode;
-
Point center;
Point min_center;
Point max_center;
gint zoom;
gint max_zoom;
gint min_zoom;
+ gboolean zoom_to_mouse;
gfloat units_conv;
gchar *units_str;
gboolean show_location;
gboolean show_velvec;
gboolean show_markers;
+ gboolean show_speed;
+ gboolean click_to_center;
+ gboolean zoom_in_on_2button;
+ gboolean rotate_view;
+ gfloat rotate_angle;
guint draw_width;
+ gboolean button_down;
+ gint mouse_x;
+ gint mouse_y;
+ gdouble mouse_lat;
+ gdouble mouse_lon;
+
gboolean fast_render;
guint key_zoom_new;
guint key_zoom_timeout_sid;
+
+ /* Paths */
+ GSList *paths; /* A list with paths to draw (tracks, routes, friends) */
+ Path *current_track; /* Pointer to main track */
+ Path *current_route; /* Pointer to main route */
};
#define tile2grid(tile) ((tile) << 3)
#define grid2tile(grid) ((grid) >> 3)
+
#define tile2pixel(tile) ((tile) << 8)
#define pixel2tile(pixel) ((pixel) >> 8)
+
#define tile2unit(tile) ((tile) << (8 + priv->zoom))
#define unit2tile(unit) ((unit) >> (8 + priv->zoom))
+
#define tile2zunit(tile, zoom) ((tile) << (8 + zoom))
#define unit2ztile(unit, zoom) ((unit) >> (8 + zoom))
#define grid2pixel(grid) ((grid) << 5)
#define pixel2grid(pixel) ((pixel) >> 5)
+
#define grid2unit(grid) ((grid) << (5 + priv->zoom))
#define unit2grid(unit) ((unit) >> (5 + priv->zoom))
/* #define GTK_MAP_WORLD_SIZE_UNITS(max_zoom) (2 << (max_zoom + GTK_MAP_TILE_SIZE_P2)) */
-#define GTK_MAP_WORLD_SIZE_UNITS (1<<31)
+#define GTK_MAP_WORLD_SIZE_UNITS (2<<26)
#define WORLD_SIZE_UNITS GTK_MAP_WORLD_SIZE_UNITS
/* Pans are done two "grids" at a time, or 64 pixels. */
static void gtk_map_size_allocate(GtkWidget *widget, GtkAllocation *allocate);
static void gtk_map_realize(GtkWidget *widget);
static gboolean gtk_map_expose(GtkWidget *widget, GdkEventExpose *event);
-static gboolean gtk_map_configure(GtkWidget *widget, GdkEventConfigure *event);
static void gtk_map_scale_draw(GtkWidget *widget, GdkEventExpose *event);
static void gtk_map_mark_draw(GtkWidget *widget, GdkEventExpose *event);
+static void gtk_map_speed_draw(GtkWidget *widget, GdkEventExpose *event);
+
+static void gtk_map_render_buffer(GtkWidget *widget, GdkEventExpose *event);
+static void gtk_map_render_markers(GtkWidget *widget, GdkEventExpose *event);
+static void gtk_map_render_paths(GtkWidget *widget, GdkEventExpose *event);
static gboolean gtk_map_update_buffer_size(GtkWidget *widget, gint new_width, gint new_height);
static void gtk_map_update_size(GtkWidget *widget, gint width, gint height);
static void gtk_map_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gtk_map_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static gboolean gtk_map_button_press_cb(GtkWidget *widget, GdkEventButton *event);
+static gboolean gtk_map_button_release_cb(GtkWidget *widget, GdkEventButton *event);
+static gboolean gtk_map_scroll_event_cb(GtkWidget *widget, GdkEventScroll *event);
+static gboolean gtk_map_motion_notify_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data);
+
+
/* Signal IDs */
enum {
MAP_LOCATION_CHANGED,
-
- MAP_ZOOMED_IN,
- MAP_ZOOMED_OUT,
-
+ MAP_ZOOM_CHANGED,
MAP_PANNED,
-
+ MAP_CENTER_MODE_CHANGED,
MARKER_CLICK,
-
LAST_SIGNAL
};
widget_class->size_request = gtk_map_size_request;
widget_class->expose_event = gtk_map_expose;
-/* widget_class->configure_event = gtk_map_configure; */
widget_class->realize = gtk_map_realize;
widget_class->size_allocate = gtk_map_size_allocate;
g_type_class_add_private (object_class, sizeof(GtkMapPriv));
+
+gtk_map_signals[MAP_ZOOM_CHANGED]=g_signal_new("zoom-changed", G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(GtkMapClass, zoom_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
+gtk_map_signals[MAP_LOCATION_CHANGED]=g_signal_new("location-changed", G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(GtkMapClass, location_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
+gtk_map_signals[MAP_LOCATION_CHANGED]=g_signal_new("center-mode-changed", G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(GtkMapClass, center_mode_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
}
static inline void
priv->center.unitx = priv->location.unitx;
priv->center.unity = priv->location.unity;
break;
+ case CENTER_MANUAL:
default:
-#if 0
- priv->center.unitx = center->unitx;
- priv->center.unity = center->unity;
-#endif
+ /* Do nothing, use priv->center.* */
break;
}
}
g_debug("GTKMAP: %s", __PRETTY_FUNCTION__);
priv=GTK_MAP_GET_PRIVATE(map);
-#ifdef WITH_CAIRO
-priv->ct=gdk_cairo_create(GTK_WIDGET(map)->window);
-#endif
-
-priv->zoom=3;
-priv->center_mode=CENTER_LATLON;
priv->base_tilex=-5;
priv->base_tiley=-5;
+
priv->draw_width=4;
+priv->zoom=3;
+priv->min_zoom=0;
+priv->max_zoom=17;
+priv->zoom_to_mouse=TRUE;
+
+priv->center_mode=CENTER_LATLON;
+priv->center.unitx=0;
+priv->center.unity=0;
+
priv->speed=-1;
priv->speed_gc=priv->speed_gc1;
priv->show_markers=TRUE;
priv->show_location=TRUE;
-priv->gl=FALSE;
+priv->button_down=FALSE;
+priv->click_to_center=FALSE;
+priv->zoom_in_on_2button=FALSE;
-#ifdef WITH_GL
-priv->gl_config=gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH);
-if (priv->gl_config) {
- g_print("OpenGL version: %s\n", glGetString (GL_VERSION));
- g_print("OpenGL vendor: %s\n", glGetString (GL_VENDOR));
- g_print("OpenGL renderer: %s\n", glGetString (GL_RENDERER));
- gtk_widget_set_gl_capability(map->widget, priv->gl_config, NULL, TRUE, GDK_GL_RGBA_TYPE);
- priv->gl=TRUE;
-}
-#endif
+priv->rotate_angle=M_PI;
+priv->rotate_view=FALSE;
+priv->gl=FALSE;
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
- | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
-
-#if 0
-g_signal_connect(G_OBJECT(map), "button_press_event", G_CALLBACK(gtk_map_cb_button_press), NULL);
-#endif
-
}
-static gboolean
-gtk_map_configure(GtkWidget *widget, GdkEventConfigure *event)
-{
-GtkMap *map;
-GtkMapPriv *priv;
-
-g_return_val_if_fail(GTK_IS_MAP(widget), TRUE);
-map=GTK_MAP(widget);
-priv=GTK_MAP_GET_PRIVATE(map);
-
-g_debug("GTKMAP: %s", __PRETTY_FUNCTION__);
-
-return TRUE;
-}
-
-
static void
-gtk_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+gtk_map_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
GtkMap *map;
g_return_if_fail(GTK_IS_MAP(object));
gtk_map_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
GtkMap *map;
+
g_return_if_fail(GTK_IS_MAP(object));
map=GTK_MAP(object);
switch (prop_id) {
gtk_map_finalize(GObject *object)
{
GtkMap *map;
+GtkMapPriv *priv;
g_return_if_fail(GTK_IS_MAP(object));
map=GTK_MAP(object);
+priv=GTK_MAP_GET_PRIVATE(map);
g_debug("GTKMAP: %s", __PRETTY_FUNCTION__);
+#ifdef WITH_CAIRO
+if (priv->ct)
+ cairo_destroy(priv->ct);
+#endif
+
if (GTK_WIDGET(object)->parent && GTK_WIDGET_MAPPED(object)) {
gtk_widget_unmap(GTK_WIDGET(object));
}
tw=GTK_MAP_TILE_SIZE_PIXELS*((width/GTK_MAP_TILE_SIZE_PIXELS)+2);
th=GTK_MAP_TILE_SIZE_PIXELS*((height/GTK_MAP_TILE_SIZE_PIXELS)+2);
-gtk_map_update_buffer_size(GTK_MAP(widget), tw, th);
+gtk_map_update_buffer_size(widget, tw, th);
if (!priv->buffer) {
return;
}
-map->width=width;
-map->height=height;
-
-priv->buf_width_pixels=tw;
-priv->buf_height_pixels=th;
-priv->buf_width_tiles=priv->buf_width_pixels/GTK_MAP_TILE_SIZE_PIXELS;
-priv->buf_height_tiles=priv->buf_height_pixels/GTK_MAP_TILE_SIZE_PIXELS;
-
priv->screen_width_pixels = width;
priv->screen_height_pixels = height;
priv->screen_grids_halfwidth = pixel2grid(priv->screen_width_pixels) / 2;
g_debug("GTKMAP: Size allocate (%d, %d)", widget->allocation.width, widget->allocation.height);
-if (GTK_WIDGET_REALIZED(widget))
+if (GTK_WIDGET_REALIZED(widget)) {
gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height);
+ gtk_map_update_size(widget, allocation->width, allocation->height);
+ gtk_map_refresh(widget);
+}
-gtk_map_update_size(widget, allocation->width, allocation->height);
}
static void
map=GTK_MAP(widget);
-g_debug("GTKMAP: Size request");
-
requisition->width=GTK_MAP_TILE_SIZE_PIXELS/2;
requisition->height=GTK_MAP_TILE_SIZE_PIXELS/2;
-gtk_map_update_size(widget, requisition->width, requisition->height);
}
static gboolean
g_debug("GTKMAP: %s (%d, %d)", __PRETTY_FUNCTION__, new_width, new_height);
-if (priv->buffer==NULL) {
- priv->buffer=gdk_pixmap_new(widget->window,
- new_width<GTK_MAP_TILE_SIZE_PIXELS ? GTK_MAP_TILE_SIZE_PIXELS : new_width,
- new_height<GTK_MAP_TILE_SIZE_PIXELS ? GTK_MAP_TILE_SIZE_PIXELS : new_height, -1);
- return TRUE;
-} else if (new_width>priv->buf_width_pixels || new_height>priv->buf_height_pixels ||
- new_width<priv->buf_width_pixels-(GTK_MAP_TILE_SIZE_PIXELS*2) || new_height<priv->buf_height_pixels-(GTK_MAP_TILE_SIZE_PIXELS*2) ) {
- g_object_unref(priv->buffer);
- priv->buffer=gdk_pixmap_new(widget->window, new_width, new_height, -1);
+if ( (priv->buffer==NULL) || (new_width>priv->buf_width_pixels || new_height>priv->buf_height_pixels || new_width<priv->buf_width_pixels-(GTK_MAP_TILE_SIZE_PIXELS*2) || new_height<priv->buf_height_pixels-(GTK_MAP_TILE_SIZE_PIXELS*2) )) {
+ priv->buf_width_pixels=new_width<GTK_MAP_TILE_SIZE_PIXELS ? GTK_MAP_TILE_SIZE_PIXELS : new_width;
+ priv->buf_height_pixels=new_height<GTK_MAP_TILE_SIZE_PIXELS ? GTK_MAP_TILE_SIZE_PIXELS : new_height;
+ priv->buf_width_tiles=priv->buf_width_pixels/GTK_MAP_TILE_SIZE_PIXELS;
+ priv->buf_height_tiles=priv->buf_height_pixels/GTK_MAP_TILE_SIZE_PIXELS;
+ if (priv->buffer)
+ g_object_unref(priv->buffer);
+ priv->buffer=gdk_pixmap_new(widget->window, priv->buf_width_pixels, priv->buf_height_pixels, -1);
+ if (priv->buffer)
+ gdk_draw_rectangle(priv->buffer, widget->style->black_gc, TRUE, 0, 0, priv->buf_width_pixels, priv->buf_height_pixels);
return TRUE;
}
return FALSE;
attributes.height=widget->allocation.height;
attributes.wclass=GDK_INPUT_OUTPUT;
-attributes.event_mask=gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
+attributes.event_mask=gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
attributes_mask=GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
attributes.visual=gtk_widget_get_visual(widget);
widget->style=gtk_style_attach(widget->style, widget->window);
gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
+gtk_widget_set_extension_events(widget, GDK_EXTENSION_EVENTS_ALL);
+
+#ifdef WITH_GL
+priv->gl_config=gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH);
+if (priv->gl_config) {
+ g_print("OpenGL version: %s\n", glGetString (GL_VERSION));
+ g_print("OpenGL vendor: %s\n", glGetString (GL_VENDOR));
+ g_print("OpenGL renderer: %s\n", glGetString (GL_RENDERER));
+ gtk_widget_set_gl_capability(widget, priv->gl_config, NULL, TRUE, GDK_GL_RGBA_TYPE);
+ priv->gl=TRUE;
+}
+#endif
+
priv->scale_context=gtk_widget_get_pango_context(widget);
priv->scale_layout=pango_layout_new(priv->scale_context);
priv->scale_font=pango_font_description_new();
color.blue=0;
gdk_gc_set_rgb_fg_color(priv->speed_gc2, &color);
+priv->gc_track=gdk_gc_new(widget->window);
+color.red=0xffff;
+color.green=0;
+color.blue=0;
+gdk_gc_set_rgb_fg_color(priv->gc_track, &color);
+
+priv->gc_route=gdk_gc_new(widget->window);
+color.red=0;
+color.green=0xffff;
+color.blue=0;
+gdk_gc_set_rgb_fg_color(priv->gc_route, &color);
+
+priv->gc_waypoint=gdk_gc_new(widget->window);
+color.red=0xffff;
+color.green=0xffff;
+color.blue=0;
+gdk_gc_set_rgb_fg_color(priv->gc_waypoint, &color);
+
+priv->gc_break=gdk_gc_new(widget->window);
+color.red=0xffff;
+color.green=0;
+color.blue=0xffff;
+gdk_gc_set_rgb_fg_color(priv->gc_break, &color);
+
priv->speed_context=gtk_widget_get_pango_context(widget);
priv->speed_layout=pango_layout_new(priv->speed_context);
priv->speed_font=pango_font_description_new();
pango_font_description_set_size(priv->speed_font, 48 * PANGO_SCALE);
pango_layout_set_font_description(priv->speed_layout, priv->speed_font);
pango_layout_set_alignment(priv->speed_layout, PANGO_ALIGN_LEFT);
+
+g_signal_connect(G_OBJECT(map), "button_press_event", G_CALLBACK(gtk_map_button_press_cb), NULL);
+g_signal_connect(G_OBJECT(map), "button_release_event",G_CALLBACK(gtk_map_button_release_cb), NULL);
+g_signal_connect(G_OBJECT(map), "scroll_event", G_CALLBACK(gtk_map_scroll_event_cb), NULL);
+g_signal_connect(G_OBJECT(map), "motion_notify_event", G_CALLBACK(gtk_map_motion_notify_cb), NULL);
+
+gtk_widget_queue_resize(widget);
+}
+
+static void
+gtk_map_render_buffer(GtkWidget *widget, GdkEventExpose *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_if_fail(GTK_IS_MAP(widget));
+g_return_if_fail(event != NULL);
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+if (!priv->buffer)
+ return
+
+g_debug("GTKMAP: expose (%d, %d)-(%d, %d)", event->area.x, event->area.y, event->area.width, event->area.height);
+g_debug("GTKMAP: expose (%d, %d)", event->area.x + priv->offsetx, event->area.y + priv->offsety);
+g_debug("GTKMAP: expose (%d, %d)", unit2x(priv->center.unitx), unit2y(priv->center.unity));
+
+#ifdef WITH_CAIROa
+cairo_save(priv->ct);
+cairo_rectangle(priv->ct, event->area.x, event->area.y, event->area.width, event->area.height);
+cairo_clip(priv->ct);
+#if 0
+if (priv->rotate_view) {
+ cairo_translate(priv->ct, (gdouble)-unit2x(priv->center.unitx), (gdouble)-unit2y(priv->center.unity) );
+ cairo_rotate(priv->ct, (gdouble)priv->rotate_angle);
+ cairo_translate(priv->ct, (gdouble)unit2x(priv->center.unitx), (gdouble)unit2y(priv->center.unity) );
+}
+#endif
+cairo_translate(priv->ct, -(event->area.x+priv->offsetx), -(event->area.y+priv->offsety));
+gdk_cairo_set_source_pixmap(priv->ct, priv->buffer, event->area.x, event->area.y);
+cairo_set_operator (priv->ct, CAIRO_OPERATOR_SOURCE);
+cairo_paint(priv->ct);
+cairo_restore(priv->ct);
+#else
+gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], priv->buffer,
+ event->area.x + priv->offsetx, event->area.y + priv->offsety,
+ event->area.x, event->area.y, event->area.width, event->area.height);
+#endif
}
static gboolean
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
-g_debug("GTKMAP: expose (%d, %d)-(%d, %d)", event->area.x, event->area.y, event->area.width, event->area.height);
+#ifdef WITH_CAIRO
+priv->ct=gdk_cairo_create(widget->window);
+#endif
-if (priv->buffer)
- gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], priv->buffer,
- event->area.x + priv->offsetx, event->area.y + priv->offsety,
- event->area.x, event->area.y, event->area.width, event->area.height);
+gtk_map_render_buffer(widget, event);
-#if 0
-gtk_map_paths_draw(widget, event);
+if (priv->show_paths!=0)
+ gtk_map_render_paths(widget, event);
if (priv->show_markers)
- gtk_map_markers_draw(widget, event);
+ gtk_map_render_markers(widget, event);
if (priv->show_speed)
gtk_map_speed_draw(widget, event);
-#endif
if (priv->show_location)
gtk_map_mark_draw(widget, event);
if (priv->show_scale)
gtk_map_scale_draw(widget, event);
+#ifdef WITH_CAIRO
+cairo_destroy(priv->ct);
+priv->ct=NULL;
+#endif
+
+return TRUE;
+}
+
+static void
+gtk_map_render_markers(GtkWidget *widget, GdkEventExpose *event)
+{
+
+}
+
+static void
+gtk_map_render_waypoint(GtkWidget *widget, guint x1, guint y1)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+GdkGC *gc;
+
+g_return_if_fail(GTK_IS_MAP(widget));
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+gc=priv->gc_waypoint;
+
+if ((x1 > priv->buf_width_pixels) || (y1 > priv->buf_height_pixels))
+ return;
+gdk_draw_arc(widget->window, gc, FALSE, x1 - priv->draw_width, y1 - priv->draw_width, 2 * priv->draw_width, 2 * priv->draw_width, 0, 360 * 64);
+}
+
+static void
+gtk_map_render_path_segment(GtkWidget *widget, guint unitx1, guint unity1, guint unitx2, guint unity2)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+GdkGC *gc;
+gint x1, y1, x2, y2;
+
+g_return_if_fail(GTK_IS_MAP(widget));
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+x1=unit2bufx(unitx1);
+y1=unit2bufy(unity1);
+x2=unit2bufx(unitx2);
+y2=unit2bufy(unity2);
+
+/* Make sure this line could possibly be visible. */
+if (!((x1 > priv->buf_width_pixels && x2 > priv->buf_width_pixels) || (x1 < 0 && x2 < 0)
+ || (y1 > priv->buf_height_pixels && y2 > priv->buf_height_pixels) || (y1 < 0 && y2 < 0))) {
+ gc=priv->gc_track;
+ gdk_draw_line(widget->window, gc, x1, y1, x2, y2);
+}
+}
+
+static void
+gtk_map_render_path(GtkWidget *widget, Path *path, GdkEventExpose *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+Point *curr;
+WayPoint *wcurr;
+
+g_return_if_fail(path);
+
+if (path->head==path->tail)
+ return;
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+for (curr = path->head, wcurr = path->whead; curr++ != path->tail;) {
+ /* Draw the line from (curr - 1) to (curr). */
+
+ gtk_map_render_path_segment(widget, curr[-1].unitx, curr[-1].unity, curr->unitx, curr->unity);
+ /* Now, check if curr is a waypoint. */
+ if (wcurr && wcurr <= path->wtail && wcurr->point == curr) {
+ guint x1 = unit2bufx(wcurr->point->unitx);
+ guint y1 = unit2bufy(wcurr->point->unity);
+
+ gtk_map_render_waypoint(widget, x1, y1);
+ wcurr++;
+ }
+}
+#if 0
+if (path->type==PATH_TYPE_ROUTE)
+ gtk_map_render_next_waypoint(widget, path);
+#endif
+}
+
+static void
+gtk_map_render_paths(GtkWidget *widget, GdkEventExpose *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+GSList *iter;
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+/* No paths defined so return */
+if (!priv->paths)
+ return;
+
+for (iter=priv->paths; iter!=NULL; iter=iter->next) {
+ Path *p=(Path *)iter->data;
+
+ if ( (!(priv->show_paths & ROUTES_MASK) && p->type==PATH_TYPE_ROUTE) ||
+ (!(priv->show_paths & TRACKS_MASK) && p->type==PATH_TYPE_ROUTE) )
+ continue;
+
+ gtk_map_render_path(widget, p, event);
+}
+}
+
+gboolean
+gtk_map_add_path(GtkWidget *widget, Path *path)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+g_return_val_if_fail(path, FALSE);
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+/* Don't allow duplicates */
+if (g_slist_find(priv->paths, path)!=NULL)
+ return FALSE;
+priv->paths=g_slist_append(priv->paths, path);
+return TRUE;
+}
+
+gboolean
+gtk_map_remove_path(GtkWidget *widget, Path *path)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+g_return_val_if_fail(path, FALSE);
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+priv->paths=g_slist_remove(priv->paths, path);
return TRUE;
}
if (!gdk_rectangle_intersect(&event->area, &priv->mark_rect, NULL))
return;
+return;
+
#ifdef WITH_CAIRO
-cairo_arc(priv->ct, priv->mark_x1, priv->marky1, priv->draw_width*2, 0, 2 * M_PI);
+cairo_save(priv->ct);
+cairo_arc(priv->ct, priv->mark_x1, priv->mark_y1, priv->draw_width*2, 0, 2 * M_PI);
cairo_set_source_rgb(priv->ct, 1, 1, 1);
cairo_fill_preserve(priv->ct);
-cairo_set_source_rgb(priv->ct, 0, 0, 0);
+cairo_set_source_rgba(priv->ct, 0.2, 0.2, 0.8, 0.7);
if (priv->show_velvec) {
cairo_save(priv->ct);
cairo_set_line_width(priv->ct, priv->draw_width);
- cairo_move_to(priv->ct, priv->mark_x1, priv->marky1);
- cairo_line_to(priv->ct, priv->mark_x2, priv->marky2);
+ cairo_move_to(priv->ct, priv->mark_x1, priv->mark_y1);
+ cairo_line_to(priv->ct, priv->mark_x2, priv->mark_y2);
cairo_restore(priv->ct);
}
cairo_stroke(priv->ct);
+cairo_restore(priv->ct);
#else
-gdk_draw_arc(widget->window,
- priv->gc_mark,
- FALSE,
+gdk_draw_arc(widget->window, priv->gc_mark, FALSE,
priv->mark_x1 - priv->draw_width,
priv->mark_y1 - priv->draw_width,
- 2 * priv->draw_width,
- 2 * priv->draw_width,
+ 2 * priv->draw_width, 2 * priv->draw_width,
0, 360 * 64);
if (priv->show_velvec)
- gdk_draw_line(widget->window,
- priv->gc_velvec,
+ gdk_draw_line(widget->window, priv->gc_velvec,
priv->mark_x1, priv->mark_y1,
priv->mark_x2, priv->mark_y2);
#endif
priv->mark_rect.height = abs(priv->mark_y1 - priv->mark_y2) + (4 * priv->draw_width);
}
+#define SCALE_PADDING (4)
+
static void
gtk_map_scale_draw(GtkWidget *widget, GdkEventExpose *event)
{
if (!gdk_rectangle_intersect(&event->area, &priv->scale_rect, NULL))
return;
-gdk_draw_rectangle(widget->window, widget->style->bg_gc[GTK_WIDGET_STATE(widget)],
- TRUE, priv->scale_rect.x, priv->scale_rect.y,
- priv->scale_rect.width, priv->scale_rect.height);
-
-gdk_draw_rectangle(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- FALSE, priv->scale_rect.x, priv->scale_rect.y,
- priv->scale_rect.width, priv->scale_rect.height);
-
/* Now calculate and draw the distance. */
-unit2latlon(priv->center.unitx - pixel2unit(SCALE_WIDTH / 2 - 4), priv->center.unity, lat1, lon1);
-unit2latlon(priv->center.unitx + pixel2unit(SCALE_WIDTH / 2 - 4), priv->center.unity, lat2, lon2);
+unit2latlon(priv->center.unitx - pixel2unit(SCALE_WIDTH / 2 - SCALE_PADDING), priv->center.unity, lat1, lon1);
+unit2latlon(priv->center.unitx + pixel2unit(SCALE_WIDTH / 2 - SCALE_PADDING), priv->center.unity, lat2, lon2);
distance=calculate_distance(lat1, lon1, lat2, lon2) * priv->units_conv;
if (distance < 1.f)
g_debug("SCALE: %s", buffer);
+#ifdef WITH_CAIRO
+cairo_save(priv->ct);
+cairo_rectangle(priv->ct, priv->scale_rect.x, priv->scale_rect.y, priv->scale_rect.width, priv->scale_rect.height);
+cairo_set_source_rgba(priv->ct, 1, 1, 1, 0.65);
+cairo_fill_preserve(priv->ct);
+cairo_set_source_rgba(priv->ct, 0, 0, 0, 0.81);
+#else
+gdk_draw_rectangle(widget->window, widget->style->bg_gc[GTK_WIDGET_STATE(widget)],
+ TRUE, priv->scale_rect.x, priv->scale_rect.y, priv->scale_rect.width, priv->scale_rect.height);
+gdk_draw_rectangle(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ FALSE, priv->scale_rect.x, priv->scale_rect.y, priv->scale_rect.width, priv->scale_rect.height);
+#endif
+
pango_layout_set_text(priv->scale_layout, buffer, -1);
pango_layout_get_pixel_size(priv->scale_layout, &width, NULL);
+/* Draw little hashes on the ends. */
+#ifdef WITH_CAIRO
+cairo_set_source_rgb(priv->ct, 0, 0, 0);
+cairo_move_to(priv->ct, priv->scale_rect.x + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 - SCALE_PADDING);
+cairo_line_to(priv->ct, priv->scale_rect.x + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 + SCALE_PADDING);
+
+cairo_move_to(priv->ct, priv->scale_rect.x + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2);
+cairo_line_to(priv->ct, priv->scale_rect.x + (priv->scale_rect.width - width) / 2 - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2);
+
+cairo_move_to(priv->ct, priv->scale_rect.x + priv->scale_rect.width - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 - SCALE_PADDING);
+cairo_line_to(priv->ct, priv->scale_rect.x + priv->scale_rect.width - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 + SCALE_PADDING);
+
+cairo_move_to(priv->ct, priv->scale_rect.x + priv->scale_rect.width - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2);
+cairo_line_to(priv->ct, priv->scale_rect.x + (priv->scale_rect.width + width) / 2 + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2);
+
+cairo_stroke(priv->ct);
+cairo_restore(priv->ct);
+#else
+gdk_draw_line(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ priv->scale_rect.x + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 - SCALE_PADDING,
+ priv->scale_rect.x + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 + SCALE_PADDING);
+gdk_draw_line(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ priv->scale_rect.x + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2,
+ priv->scale_rect.x + (priv->scale_rect.width - width) / 2 - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2);
+gdk_draw_line(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ priv->scale_rect.x + priv->scale_rect.width - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 - SCALE_PADDING,
+ priv->scale_rect.x + priv->scale_rect.width - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2 + SCALE_PADDING);
+gdk_draw_line(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ priv->scale_rect.x + priv->scale_rect.width - SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2,
+ priv->scale_rect.x + (priv->scale_rect.width + width) / 2 + SCALE_PADDING, priv->scale_rect.y + priv->scale_rect.height / 2);
+#endif
+
/* Draw the layout itself. */
-gdk_draw_layout(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- priv->scale_rect.x + (priv->scale_rect.width - width) / 2,
- priv->scale_rect.y, priv->scale_layout);
+gdk_draw_layout(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ priv->scale_rect.x + (priv->scale_rect.width - width) / 2, priv->scale_rect.y, priv->scale_layout);
-/* Draw little hashes on the ends. */
-gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- priv->scale_rect.x + 4,
- priv->scale_rect.y + priv->scale_rect.height / 2 - 4,
- priv->scale_rect.x + 4,
- priv->scale_rect.y + priv->scale_rect.height / 2 + 4);
-gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- priv->scale_rect.x + 4,
- priv->scale_rect.y + priv->scale_rect.height / 2,
- priv->scale_rect.x + (priv->scale_rect.width - width) / 2 - 4,
- priv->scale_rect.y + priv->scale_rect.height / 2);
-gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- priv->scale_rect.x + priv->scale_rect.width - 4,
- priv->scale_rect.y + priv->scale_rect.height / 2 - 4,
- priv->scale_rect.x + priv->scale_rect.width - 4,
- priv->scale_rect.y + priv->scale_rect.height / 2 + 4);
-gdk_draw_line(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
- priv->scale_rect.x + priv->scale_rect.width - 4,
- priv->scale_rect.y + priv->scale_rect.height / 2,
- priv->scale_rect.x + (priv->scale_rect.width + width) / 2 + 4,
- priv->scale_rect.y + priv->scale_rect.height / 2);
}
static void
return;
g_snprintf(buffer, sizeof(buffer), "%0.0f %s", priv->speed * priv->units_conv, priv->units_str);
-map_information_text(10, 10, priv->speed_gc, buffer);
+gtk_map_information_text(widget, 10, 10, priv->speed_gc, buffer);
}
void
{
GtkMap *map;
GtkMapPriv *priv;
+GdkPixbuf *pixbuf;
+GError *error = NULL;
+gchar buffer[BUFFER_SIZE];
+gchar key[BUFFER_SIZE];
+struct stat tstat;
+gint se;
g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
-return NULL;
+g_snprintf(buffer, sizeof(buffer), "%s/%u/%u/%u.jpg", priv->curr_repo->cache_dir, priv->zoom + zoff, (tilex >> zoff), (tiley >> zoff));
+g_snprintf(key, sizeof(key), "%s/%u/%u/%u", priv->curr_repo->cache_dir, priv->zoom + zoff, (tilex >> zoff), (tiley >> zoff));
+
+g_debug("LOAD: %u, %u @ (%d+%d): %s", tilex, tiley, priv->zoom, zoff, buffer);
+
+pixbuf=image_cache_get(priv->icache, key, buffer);
+if (!pixbuf) {
+#if 0
+ g_unlink(buffer);
+
+ if (_auto_download && _curr_repo->type != REPOTYPE_NONE && !((_zoom + zoff - (_curr_repo->double_size ? 1 : 0)) % _curr_repo->dl_zoom_steps)) {
+ if (download)
+ map_initiate_download(tilex >> zoff, tiley >> zoff, _zoom + zoff, -INITIAL_DOWNLOAD_RETRIES);
+ }
+#endif
+ return NULL;
+}
+
+g_object_ref(pixbuf);
+
+#if 0
+/* Check if we need to trim. */
+if (gdk_pixbuf_get_width(pixbuf) != TILE_SIZE_PIXELS || gdk_pixbuf_get_height(pixbuf) != TILE_SIZE_PIXELS)
+ pixbuf=pixbuf_trim(pixbuf);
+#endif
+
+#if 0
+/* Check tile age, if file date is ower a week old, redownload if autodownload enabled */
+se=stat(buffer, &tstat);
+if (se==0) {
+ time_t t;
+ t=time(NULL);
+ if (t-tstat.st_mtime>TILE_MAX_AGE) {
+ if (_auto_download && _curr_repo->type != REPOTYPE_NONE && !((_zoom + zoff - (_curr_repo->double_size ? 1 : 0)) % _curr_repo->dl_zoom_steps)) {
+ if (download) {
+ g_debug("Tile: %s is old, re-downloading\n", buffer);
+ map_initiate_download(tilex >> zoff, tiley >> zoff, _zoom + zoff, -INITIAL_DOWNLOAD_RETRIES);
+ image_cache_invalidate(map_ic, key);
+ }
+ }
+ }
+}
+#endif
+
+return pixbuf;
+}
+
+void
+gtk_map_set_tile_repository(GtkWidget *widget, RepoData *rd)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_if_fail(GTK_IS_MAP(widget));
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+priv->curr_repo=rd;
}
static gboolean
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
+g_debug("RT: %u %u (%u) %u %u (%u, %u)", tilex, tiley,
+ priv->world_size_tiles, destx, desty, priv->buf_width_tiles, priv->buf_height_tiles);
+
g_return_val_if_fail(priv->buffer, FALSE);
g_return_val_if_fail(priv->curr_repo, 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); */
-
for (zoff = (priv->curr_repo->double_size ? 1 : 0); !pixbuf && (priv->zoom + zoff) <= priv->max_zoom && zoff <= GTK_MAP_TILE_SIZE_P2; zoff += 1) {
pixbuf=gtk_map_tile_load(map, tilex, tiley, zoff, !fast_fail);
if (!pixbuf) {
return TRUE;
}
-gboolean
-gtk_map_set_center(GtkWidget *widget, guint new_center_unitx, guint new_center_unity)
+void
+gtk_map_set_center(GtkWidget *widget, guint unitx, guint unity)
{
GtkMap *map;
GtkMapPriv *priv;
GtkStyle *style;
+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;
g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
priv=GTK_MAP_GET_PRIVATE(map);
style=widget->style;
-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;
+priv->center_mode=CENTER_MANUAL;
/* 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);
+BOUND(unitx, priv->min_center.unitx, priv->max_center.unitx);
+BOUND(unity, priv->min_center.unity, priv->max_center.unity);
-priv->center.unitx = new_center_unitx;
-priv->center.unity = new_center_unity;
+priv->center.unitx = unitx;
+priv->center.unity = 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);
gtk_map_recalc_offset(priv);
gtk_map_recalc_focus_base(priv);
+gtk_map_refresh(widget);
+g_signal_emit(widget, gtk_map_signals[MAP_LOCATION_CHANGED], 0, priv->zoom);
+}
+
+void
+gtk_map_set_center_latlon(GtkWidget *widget, gdouble lat, gdouble lon)
+{
+guint unitx, unity;
-gtk_map_refresh(map);
+latlon2unit(lat, lon, unitx, unity);
+gtk_map_set_center(widget, unitx, unity);
}
void
-gtk_map_refresh(GtkWidget *widget)
+gtk_map_pan(GtkWidget *widget, gint delta_x, gint delta_y)
{
GtkMap *map;
+GtkMapPriv *priv;
g_return_if_fail(GTK_IS_MAP(widget));
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+gtk_map_set_center(widget, priv->center.unitx + delta_x*GTK_MAP_PAN_UNITS, priv->center.unity + delta_y*GTK_MAP_PAN_UNITS);
+}
+
+void
+gtk_map_refresh(GtkWidget *widget)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+guint x, y;
+
+g_return_if_fail(GTK_IS_MAP(widget));
map=GTK_MAP(widget);
-gtk_widget_queue_draw_area(widget, 0, 0, map->width, map->height);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+for (y = 0; y < priv->buf_height_tiles; ++y)
+ for (x = 0; x < priv->buf_width_tiles; ++x)
+ gtk_map_render_tile(map, priv->base_tilex + x, priv->base_tiley + y, x * GTK_MAP_TILE_SIZE_PIXELS, y * GTK_MAP_TILE_SIZE_PIXELS, FALSE);
+
+gtk_widget_queue_draw(widget);
}
gint
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
+g_debug("GTKMAP: zoom %d", new_zoom);
+
if (new_zoom > (priv->max_zoom - 1))
return FALSE;
if (new_zoom == priv->zoom)
return FALSE;
-priv->zoom = new_zoom / priv->curr_repo->view_zoom_steps * priv->curr_repo->view_zoom_steps;
+if (priv->curr_repo)
+ priv->zoom = new_zoom / priv->curr_repo->view_zoom_steps * priv->curr_repo->view_zoom_steps;
+else
+ priv->zoom = new_zoom;
+
priv->world_size_tiles = unit2tile(GTK_MAP_WORLD_SIZE_UNITS);
/* If we're leading, update the center to reflect new zoom level. */
gtk_map_recalc_focus_base(priv);
gtk_map_recalc_focus_size(priv);
-gtk_map_refresh(GTK_WIDGET(map));
+gtk_map_refresh(widget);
+g_signal_emit(widget, gtk_map_signals[MAP_ZOOM_CHANGED], 0, priv->zoom);
return TRUE;
}
cache_size=512;
image_cache_set_size(priv->icache, cache_size);
}
+
+/******************************************************************************/
+/* Internal widget callback handlers */
+/******************************************************************************/
+
+/**
+ * Mouse scroller zoom in/out callback
+ */
+static gboolean
+gtk_map_scroll_event_cb(GtkWidget *widget, GdkEventScroll *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+gtk_map_zoom(widget, event->direction==GDK_SCROLL_UP ? -1 : 1);
+if (priv->zoom_to_mouse)
+ gtk_map_set_center(widget, x2unit((gint) (event->x + 0.5)), y2unit((gint) (event->y + 0.5)));
+return FALSE;
+}
+
+static gboolean
+gtk_map_motion_notify_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+priv->mouse_x=(gint)event->x;
+priv->mouse_y=(gint)event->y;
+unit2latlon(x2unit((gint) (event->x+0.5)), y2unit((gint) (event->y+0.5)), priv->mouse_lat, priv->mouse_lon);
+
+g_debug("MOUSE: %d,%d (%f,%f)", priv->mouse_x, priv->mouse_y, priv->mouse_lat, priv->mouse_lon);
+
+return FALSE;
+}
+
+static gboolean
+gtk_map_button_press_cb(GtkWidget *widget, GdkEventButton *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+switch (event->button) {
+case 1:
+ priv->button_down=TRUE;
+ if (priv->click_to_center) {
+ gtk_map_set_center(widget, x2unit((gint) (event->x+0.5)), y2unit((gint) (event->y+0.5)));
+ return FALSE;
+ } else if (event->type==GDK_2BUTTON_PRESS) {
+ gtk_map_set_center(widget, x2unit((gint) (event->x+0.5)), y2unit((gint) (event->y+0.5)));
+ if (priv->zoom_in_on_2button)
+ gtk_map_zoom_in(widget);
+ return FALSE;
+ }
+break;
+case 2:
+
+break;
+case 3:
+ if (priv->menu)
+ gtk_menu_popup(GTK_MENU(priv->menu), NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time());
+break;
+}
+return FALSE;
+}
+
+static gboolean
+gtk_map_button_release_cb(GtkWidget *widget, GdkEventButton *event)
+{
+GtkMap *map;
+GtkMapPriv *priv;
+
+g_return_val_if_fail(GTK_IS_MAP(widget), FALSE);
+map=GTK_MAP(widget);
+priv=GTK_MAP_GET_PRIVATE(map);
+
+switch (event->button) {
+case 1:
+ priv->button_down=FALSE;
+break;
+case 2:
+
+break;
+case 3:
+
+break;
+}
+return FALSE;
+}