* 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)
+/* Filename buffer */
+#define BUFFER_SIZE (2048)
+
#define SCALE_WIDTH (256)
#define MAP_CACHE_DEFAULT (64)
/* #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. */
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_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->base_tilex=-5;
priv->base_tiley=-5;
priv->show_location=TRUE;
priv->gl=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->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));
}
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);
}
static void
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->window, 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();
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);
+
+#if 0
+g_signal_connect(G_OBJECT(widget), "button_press_event", G_CALLBACK(gtk_map_press_cb), NULL);
+#endif
+
+}
+
+static void
+draw (GtkWidget *clock, cairo_t *cr)
+{
+ double x, y;
+ double radius;
+ int i;
+
+ x = clock->allocation.x + clock->allocation.width / 2;
+ y = clock->allocation.y + clock->allocation.height / 2;
+ radius = MIN (clock->allocation.width / 2, clock->allocation.height / 2) - 5;
+
+ /* clock back */
+ cairo_arc (cr, x, y, radius, 0, 2 * M_PI);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_fill_preserve (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_stroke (cr);
}
static gboolean
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
+#ifdef WITH_CAIRO
+priv->ct=gdk_cairo_create(widget->window);
+#endif
+
g_debug("GTKMAP: expose (%d, %d)-(%d, %d)", event->area.x, event->area.y, event->area.width, event->area.height);
if (priv->buffer)
if (priv->show_scale)
gtk_map_scale_draw(widget, event);
+#ifdef WITH_CAIRO
+cairo_destroy(priv->ct);
+priv->ct=NULL;
+#endif
+
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_restore(priv->ct);
cairo_stroke(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
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);
g_debug("SCALE: %s", buffer);
+#ifdef WITH_CAIRO
+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.8);
+cairo_fill_preserve(priv->ct);
+cairo_set_source_rgb(priv->ct, 0, 0, 0);
+cairo_stroke(priv->ct);
+#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);
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)],
+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)],
+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)],
+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)],
+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,
{
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);
-g_debug("LOAD: %u, %u @ (%d+%d)", tilex, tiley, priv->zoom, zoff);
+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 NULL;
+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
gtk_map_recalc_offset(priv);
gtk_map_recalc_focus_base(priv);
-
-gtk_map_refresh(map);
+gtk_map_refresh(widget);
}
void
map=GTK_MAP(widget);
priv=GTK_MAP_GET_PRIVATE(map);
-gtk_map_set_center(widget, priv->center.unitx + delta_x, priv->center.unity + delta_y);
+gtk_map_set_center(widget, priv->center.unitx + delta_x*GTK_MAP_PAN_UNITS, priv->center.unity + delta_y*GTK_MAP_PAN_UNITS);
}
-void
+static 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);
+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_area(widget, 0, 0, widget->allocation.width, widget->allocation.height);
}
gtk_map_recalc_focus_base(priv);
gtk_map_recalc_focus_size(priv);
-gtk_map_refresh(GTK_WIDGET(map));
+gtk_map_refresh(widget);
return TRUE;
}