Diff of /trunk/src/osm-gps-map.c

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

revision 66 by harbaum, Wed Aug 19 20:03:28 2009 UTC revision 77 by harbaum, Tue Aug 25 12:49:03 2009 UTC
# Line 49  Line 49 
49    
50  #define EXTRA_BORDER (TILESIZE / 2)  #define EXTRA_BORDER (TILESIZE / 2)
51    
52    #define OSM_GPS_MAP_SCROLL_STEP 10
53    
54    /* any defined key enables key support */
55    #if (defined(OSM_GPS_MAP_KEY_FULLSCREEN) || \
56         defined(OSM_GPS_MAP_KEY_ZOOMIN) || \
57         defined(OSM_GPS_MAP_KEY_ZOOMOUT) || \
58         defined(OSM_GPS_MAP_KEY_UP) || \
59         defined(OSM_GPS_MAP_KEY_DOWN) || \
60         defined(OSM_GPS_MAP_KEY_LEFT) || \
61         defined(OSM_GPS_MAP_KEY_RIGHT))
62    #define OSM_GPS_MAP_KEYS
63    #endif
64    
65    #ifdef OSM_GPS_MAP_KEYS
66    #include <gdk/gdkkeysyms.h>
67    #endif
68    
69  struct _OsmGpsMapPrivate  struct _OsmGpsMapPrivate
70  {  {
71      GHashTable *tile_queue;      GHashTable *tile_queue;
# Line 110  struct _OsmGpsMapPrivate Line 127  struct _OsmGpsMapPrivate
127  #endif  #endif
128    
129  #ifdef ENABLE_OSD  #ifdef ENABLE_OSD
130      //the osd controls      //the osd controls (if present)
131      struct {      osm_gps_map_osd_t *osd;
132          GdkPixmap *backup;  #ifdef OSD_DOUBLE_BUFFER
133          gint backup_x, backup_y;      GdkPixmap *dbuf_pixmap;
134          OsmGpsMapOsdGpsCallback cb;  #endif
         gpointer data;  
     } osd;  
135  #endif  #endif
136    
137    #ifdef OSM_GPS_MAP_KEY_FULLSCREEN
138        gboolean fullscreen;
139    #endif
140    
141      //additional images or tracks added to the map      //additional images or tracks added to the map
142      GSList *tracks;      GSList *tracks;
143      GSList *images;      GSList *images;
# Line 1422  osm_gps_map_purge_cache (OsmGpsMap *map) Line 1441  osm_gps_map_purge_cache (OsmGpsMap *map)
1441     g_hash_table_foreach_remove(priv->tile_cache, osm_gps_map_purge_cache_check, priv);     g_hash_table_foreach_remove(priv->tile_cache, osm_gps_map_purge_cache_check, priv);
1442  }  }
1443    
 #ifdef ENABLE_OSD  
 /* position and extent of bounding box */  
 #define OSD_X      (10)  
 #define OSD_Y      (10)  
   
 #define OSD_COLOR            0.5, 0.5, 1  
 #define OSD_COLOR_DISABLED   0.8, 0.8, 0.8  
   
 /* parameters of the direction shape */  
 #ifndef OSM_GPS_MAP_OSD_DIAMETER  
 #define D_RAD  (30)         // diameter of dpad  
 #else  
 #define D_RAD  (OSM_GPS_MAP_OSD_DIAMETER)  
 #endif  
 #define D_TIP  (4*D_RAD/5)  // distance of arrow tip from dpad center  
 #define D_LEN  (D_RAD/4)    // length of arrow  
 #define D_WID  (D_LEN)      // width of arrow  
   
 /* parameters of the "zoom" pad */  
 #define Z_STEP   (D_RAD/4)  // distance between dpad and zoom  
 #define Z_RAD    (D_RAD/2)  // radius of "caps" of zoom bar  
   
 /* shadow also depends on control size */  
 #define OSD_SHADOW (D_RAD/6)  
   
 /* total width and height of controls incl. shadow */  
 #define OSD_W    (2*D_RAD + OSD_SHADOW)  
 #define OSD_H    (2*D_RAD + Z_STEP + 2*Z_RAD + OSD_SHADOW)  
   
 #define OSD_LBL_SHADOW (OSD_SHADOW/2)  
   
 #define Z_TOP    (2 * D_RAD + Z_STEP)  
 #define Z_MID    (Z_TOP + Z_RAD)  
 #define Z_BOT    (Z_MID + Z_RAD)  
 #define Z_LEFT   (Z_RAD)  
 #define Z_RIGHT  (2 * D_RAD - Z_RAD)  
   
 /* create the cairo shape used for the zoom buttons */  
 static void  
 osm_gps_map_osd_zoom_shape(cairo_t *cr, gint x, gint y) {  
     cairo_move_to (cr, x+Z_LEFT,    y+Z_TOP);  
     cairo_line_to (cr, x+Z_RIGHT,   y+Z_TOP);  
     cairo_arc     (cr, x+Z_RIGHT,   y+Z_MID, Z_RAD, -M_PI/2,  M_PI/2);  
     cairo_line_to (cr, x+Z_LEFT,    y+Z_BOT);  
     cairo_arc     (cr, x+Z_LEFT,    y+Z_MID, Z_RAD,  M_PI/2, -M_PI/2);  
 }  
   
 /* create the cairo shape used for the dpad */  
 static void  
 osm_gps_map_osd_dpad_shape(cairo_t *cr, gint x, gint y) {  
     cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI);  
 }  
   
 typedef enum {  
     OSD_NONE = 0,  
     OSD_BG,  
     OSD_UP,  
     OSD_DOWN,  
     OSD_LEFT,  
     OSD_RIGHT,  
     OSD_IN,  
     OSD_OUT,  
     OSD_GPS  
 } osd_button_t;  
   
 static gboolean  
 osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad)  
 {  
     return( pow(cx - x, 2) + pow(cy - y, 2) < rad * rad);  
 }  
   
 /* check whether x/y is within the dpad */  
 static osd_button_t  
 osm_gps_map_osd_check_dpad(gint x, gint y)  
 {  
     /* within entire dpad circle */  
     if( osm_gps_map_in_circle(x, y, OSD_X + D_RAD, OSD_Y + D_RAD, D_RAD))  
     {  
         /* convert into position relative to dpads centre */  
         x -= (OSD_X + D_RAD);  
         y -= (OSD_Y + D_RAD);  
   
         /* check for dpad center goes here! */  
         if( osm_gps_map_in_circle(x, y, 0, 0, D_RAD/3))  
             return OSD_GPS;  
   
         if( y < 0 && abs(x) < abs(y))  
             return OSD_UP;  
   
         if( y > 0 && abs(x) < abs(y))  
             return OSD_DOWN;  
   
         if( x < 0 && abs(y) < abs(x))  
             return OSD_LEFT;  
   
         if( x > 0 && abs(y) < abs(x))  
             return OSD_RIGHT;  
   
         return OSD_BG;  
     }  
     return OSD_NONE;  
 }  
   
 /* check whether x/y is within the zoom pads */  
 static osd_button_t  
 osm_gps_map_osd_check_zoom(gint x, gint y) {  
     if( x > OSD_X && x < (OSD_X + OSD_W) && y > Z_TOP && y < (OSD_Y+Z_BOT)) {  
   
         /* within circle around (-) label */  
         if( osm_gps_map_in_circle(x, y, OSD_X + Z_LEFT, OSD_Y + Z_MID, Z_RAD))  
             return OSD_OUT;  
   
         /* between center of (-) button and center of entire zoom control area */  
         if(x > OSD_LEFT && x < OSD_X + D_RAD)  
             return OSD_OUT;  
   
         /* within circle around (+) label */  
         if( osm_gps_map_in_circle(x, y, OSD_X + Z_RIGHT, OSD_Y + Z_MID, Z_RAD))  
             return OSD_IN;  
   
         /* between center of (+) button and center of entire zoom control area */  
         if(x < OSD_RIGHT && x > OSD_X + D_RAD)  
             return OSD_IN;  
     }  
   
     return OSD_NONE;  
 }  
   
 static osd_button_t  
 osm_gps_map_osd_check(gint x, gint y) {  
     osd_button_t but = OSD_NONE;  
   
     /* first do a rough test for the OSD area. */  
     /* this is just to avoid an unnecessary detailed test */  
     if(x > OSD_X && x < OSD_X + OSD_W &&  
        y > OSD_Y && y < OSD_Y + OSD_H) {  
         but = osm_gps_map_osd_check_dpad(x, y);  
   
         if(but == OSD_NONE)  
             but = osm_gps_map_osd_check_zoom(x, y);  
     }  
   
     return but;  
 }  
   
 static void  
 osm_gps_map_osd_shape_shadow(cairo_t *cr) {  
     cairo_set_source_rgba (cr, 0, 0, 0, 0.2);  
     cairo_fill (cr);  
     cairo_stroke (cr);  
 }  
   
 static void  
 osm_gps_map_osd_shape(cairo_t *cr) {  
     cairo_set_source_rgb (cr, 1, 1, 1);  
     cairo_fill_preserve (cr);  
     cairo_set_source_rgb (cr, OSD_COLOR);  
     cairo_set_line_width (cr, 1);  
     cairo_stroke (cr);  
 }  
   
 static void  
 osm_gps_map_osd_dpad_labels(cairo_t *cr, gint x, gint y) {  
     /* move reference to dpad center */  
     x += D_RAD;  
     y += D_RAD;  
   
     const static gint offset[][3][2] = {  
         /* left arrow/triangle */  
         { { -D_TIP+D_LEN, -D_WID }, { -D_LEN, D_WID }, { +D_LEN, D_WID } },  
         /* right arrow/triangle */  
         { { +D_TIP-D_LEN, -D_WID }, { +D_LEN, D_WID }, { -D_LEN, D_WID } },  
         /* top arrow/triangle */  
         { { -D_WID, -D_TIP+D_LEN }, { D_WID, -D_LEN }, { D_WID, +D_LEN } },  
         /* bottom arrow/triangle */  
         { { -D_WID, +D_TIP-D_LEN }, { D_WID, +D_LEN }, { D_WID, -D_LEN } }  
     };  
   
     int i;  
     for(i=0;i<4;i++) {  
         cairo_move_to (cr, x + offset[i][0][0], y + offset[i][0][1]);  
         cairo_rel_line_to (cr, offset[i][1][0], offset[i][1][1]);  
         cairo_rel_line_to (cr, offset[i][2][0], offset[i][2][1]);  
     }  
 }  
   
 /* draw the sattelite dish icon in the center of the dpad */  
 #define GPS_V0  (D_RAD/8)  
 #define GPS_V1  (D_RAD/10)  
 #define GPS_V2  (D_RAD/5)  
   
 /* draw a satellite receiver dish */  
 static void  
 osm_gps_map_osd_dpad_gps(cairo_t *cr, gint x, gint y) {  
     /* move reference to dpad center */  
     x += D_RAD;  
     y += D_RAD + GPS_V0;  
   
     cairo_move_to (cr, x-GPS_V0, y+GPS_V0);  
     cairo_rel_line_to (cr, +GPS_V0, -GPS_V0);  
     cairo_rel_line_to (cr, +GPS_V0, +GPS_V0);  
     cairo_close_path (cr);  
   
     cairo_move_to (cr, x+GPS_V1-GPS_V2, y-2*GPS_V2);  
     cairo_curve_to (cr, x-GPS_V2, y, x+GPS_V1, y+GPS_V1, x+GPS_V1+GPS_V2, y);  
     cairo_close_path (cr);  
   
     x += GPS_V1;  
     cairo_move_to (cr, x, y-GPS_V2);  
     cairo_rel_line_to (cr, +GPS_V1, -GPS_V1);  
 }  
   
 #define Z_LEN  (2*Z_RAD/3)  
   
 static void  
 osm_gps_map_osd_zoom_labels(cairo_t *cr, gint x, gint y) {  
     cairo_move_to (cr, x + Z_LEFT  - Z_LEN, y + Z_MID);  
     cairo_line_to (cr, x + Z_LEFT  + Z_LEN, y + Z_MID);  
   
     cairo_move_to (cr, x + Z_RIGHT,         y + Z_MID - Z_LEN);  
     cairo_line_to (cr, x + Z_RIGHT,         y + Z_MID + Z_LEN);  
     cairo_move_to (cr, x + Z_RIGHT - Z_LEN, y + Z_MID);  
     cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);  
 }  
   
 static void  
 osm_gps_map_osd_labels(cairo_t *cr, gint width, gboolean enabled) {  
     if(enabled)  cairo_set_source_rgb (cr, OSD_COLOR);  
     else         cairo_set_source_rgb (cr, OSD_COLOR_DISABLED);  
     cairo_set_line_width (cr, width);  
     cairo_stroke (cr);  
 }  
   
 static void  
 osm_gps_map_osd_labels_shadow(cairo_t *cr, gint width, gboolean enabled) {  
     cairo_set_source_rgba (cr, 0, 0, 0, enabled?0.3:0.15);  
     cairo_set_line_width (cr, width);  
     cairo_stroke (cr);  
 }  
   
 static void  
 osm_gps_map_osd_draw_controls (OsmGpsMap *map, gint xoffset, gint yoffset)  
 {  
     OsmGpsMapPrivate *priv = map->priv;  
   
     /* backup previous contents */  
     if(!priv->osd.backup)  
         priv->osd.backup = gdk_pixmap_new(priv->pixmap, OSD_W+2, OSD_H+2, -1);  
   
     gint x = OSD_X + EXTRA_BORDER + xoffset;  
     gint y = OSD_Y + EXTRA_BORDER + yoffset;  
   
     /* create backup of background */  
     gdk_draw_drawable(priv->osd.backup,  
         GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],  
                       priv->pixmap, x-1, y-1, 0, 0, OSD_W+2, OSD_H+2);  
     priv->osd.backup_x = x-1;  
     priv->osd.backup_y = y-1;  
   
 #if 0  
     /* create pixbuf for osd */  
     if(!priv->osd.pixbuf)  
         priv->osd.pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,  
                                           TRUE, 8, OSD_W, OSD_H);  
     cairo_surface_t *surface =  
         cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);  
   
     /* fill with transparency */  
     {  
     cairo_t *cr = cairo_create(surface);  
     cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);  
     cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);  
     cairo_paint(cr);  
     cairo_destroy(cr);  
     }  
 #endif  
   
   
 #ifdef USE_CAIRO  
     //    cairo_t *cr = cairo_create(surface);  
     cairo_t *cr = gdk_cairo_create(priv->pixmap);  
   
     /* --------- draw zoom and dpad shape shadow ----------- */  
   
     osm_gps_map_osd_zoom_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);  
     osm_gps_map_osd_shape_shadow(cr);  
     osm_gps_map_osd_dpad_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);  
     osm_gps_map_osd_shape_shadow(cr);  
   
     /* --------- draw zoom and dpad shape ----------- */  
   
     osm_gps_map_osd_zoom_shape(cr, x, y);  
     osm_gps_map_osd_shape(cr);  
     osm_gps_map_osd_dpad_shape(cr, x, y);  
     osm_gps_map_osd_shape(cr);  
   
     /* --------- draw zoom and dpad labels --------- */  
   
     osm_gps_map_osd_zoom_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);  
     osm_gps_map_osd_dpad_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);  
     osm_gps_map_osd_labels_shadow(cr, Z_RAD/3, TRUE);  
     osm_gps_map_osd_dpad_gps(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);  
     osm_gps_map_osd_labels_shadow(cr, Z_RAD/6, priv->osd.cb != NULL);  
   
     osm_gps_map_osd_zoom_labels(cr, x, y);  
     osm_gps_map_osd_dpad_labels(cr, x, y);  
     osm_gps_map_osd_labels(cr, Z_RAD/3, TRUE);  
     osm_gps_map_osd_dpad_gps(cr, x, y);  
     osm_gps_map_osd_labels(cr, Z_RAD/6, priv->osd.cb != NULL);  
   
     cairo_destroy(cr);  
   
 #else  
 #warning "OSD control display lacks a non-cairo implementation!"  
 #endif  
 }  
   
 static void  
 osm_gps_map_osd_restore (OsmGpsMap *map)  
 {  
     OsmGpsMapPrivate *priv = map->priv;  
   
     /* restore backup of previous contents */  
     if(priv->osd.backup) {  
         /* create backup of background */  
         gdk_draw_drawable(priv->pixmap,  
             GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],  
                       priv->osd.backup, 0, 0,  
                       priv->osd.backup_x, priv->osd.backup_y, OSD_W+2, OSD_H+2);  
     }  
 }  
   
 #endif  
   
1444  static gboolean  static gboolean
1445  osm_gps_map_map_redraw (OsmGpsMap *map)  osm_gps_map_map_redraw (OsmGpsMap *map)
1446  {  {
# Line 1789  osm_gps_map_map_redraw (OsmGpsMap *map) Line 1474  osm_gps_map_map_redraw (OsmGpsMap *map)
1474  #ifdef ENABLE_BALLOON  #ifdef ENABLE_BALLOON
1475      osm_gps_map_draw_balloon_int(map);      osm_gps_map_draw_balloon_int(map);
1476  #endif  #endif
 #ifdef ENABLE_OSD  
     osm_gps_map_osd_draw_controls(map, 0, 0);  
 #endif  
1477    
1478      //osm_gps_map_osd_speed(map, 1.5);      //osm_gps_map_osd_speed(map, 1.5);
1479      osm_gps_map_purge_cache(map);      osm_gps_map_purge_cache(map);
# Line 1809  osm_gps_map_map_redraw_idle (OsmGpsMap * Line 1491  osm_gps_map_map_redraw_idle (OsmGpsMap *
1491          priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map);          priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map);
1492  }  }
1493    
1494    #ifdef OSM_GPS_MAP_KEYS
1495    static gboolean
1496    on_window_key_press(GtkWidget *widget,
1497                             GdkEventKey *event, OsmGpsMapPrivate *priv) {
1498      gboolean handled = FALSE;
1499      int step = GTK_WIDGET(widget)->allocation.width/OSM_GPS_MAP_SCROLL_STEP;
1500    
1501      printf("key event with keyval %x\n", event->keyval);
1502    
1503      // the map handles some keys on its own ...
1504      switch(event->keyval) {
1505    #ifdef OSM_GPS_MAP_KEY_FULLSCREEN
1506      case OSM_GPS_MAP_KEY_FULLSCREEN: {
1507          GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget));
1508          if(!priv->fullscreen)
1509              gtk_window_fullscreen(GTK_WINDOW(toplevel));
1510          else
1511              gtk_window_unfullscreen(GTK_WINDOW(toplevel));
1512    
1513          priv->fullscreen = !priv->fullscreen;
1514          handled = TRUE;
1515          } break;
1516    #endif
1517    
1518    #ifdef OSM_GPS_MAP_KEY_ZOOMIN
1519      case OSM_GPS_MAP_KEY_ZOOMIN:
1520          osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom+1);
1521          handled = TRUE;
1522          break;
1523    #endif
1524    
1525    #ifdef OSM_GPS_MAP_KEY_ZOOMOUT
1526      case OSM_GPS_MAP_KEY_ZOOMOUT:
1527          osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom-1);
1528          handled = TRUE;
1529          break;
1530    #endif
1531    
1532    #ifdef OSM_GPS_MAP_KEY_UP
1533      case OSM_GPS_MAP_KEY_UP:
1534          priv->map_y -= step;
1535          priv->center_coord_set = FALSE;
1536          osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1537          handled = TRUE;
1538          break;
1539    #endif
1540    
1541    #ifdef OSM_GPS_MAP_KEY_DOWN
1542      case OSM_GPS_MAP_KEY_DOWN:
1543          priv->map_y += step;
1544          priv->center_coord_set = FALSE;
1545          osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1546          handled = TRUE;
1547          break;
1548    #endif
1549    
1550    #ifdef OSM_GPS_MAP_KEY_LEFT
1551      case OSM_GPS_MAP_KEY_LEFT:
1552          priv->map_x -= step;
1553          priv->center_coord_set = FALSE;
1554          osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1555          handled = TRUE;
1556          break;
1557    #endif
1558    
1559    #ifdef OSM_GPS_MAP_KEY_RIGHT
1560      case OSM_GPS_MAP_KEY_RIGHT:
1561          priv->map_x += step;
1562          priv->center_coord_set = FALSE;
1563          osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1564          handled = TRUE;
1565          break;
1566    #endif
1567    
1568      default:
1569          printf("unhandled key event with keyval %x\n", event->keyval);
1570          break;
1571      }
1572    
1573      return handled;
1574    }
1575    #endif
1576    
1577  static void  static void
1578  osm_gps_map_init (OsmGpsMap *object)  osm_gps_map_init (OsmGpsMap *object)
1579  {  {
# Line 1830  osm_gps_map_init (OsmGpsMap *object) Line 1595  osm_gps_map_init (OsmGpsMap *object)
1595  #endif  #endif
1596    
1597  #ifdef ENABLE_OSD  #ifdef ENABLE_OSD
1598      priv->osd.backup = NULL;      priv->osd = NULL;
1599      priv->osd.cb = NULL;  #endif
1600    
1601    #ifdef OSM_GPS_MAP_BUTTON_FULLSCREEN
1602        priv->fullscreen = FALSE;
1603  #endif  #endif
1604    
1605      priv->tracks = NULL;      priv->tracks = NULL;
# Line 1878  osm_gps_map_init (OsmGpsMap *object) Line 1646  osm_gps_map_init (OsmGpsMap *object)
1646      GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);      GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);
1647    
1648      g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);      g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
 }  
1649    
1650  #ifndef G_CHECKSUM_MD5  #ifdef OSM_GPS_MAP_KEYS
1651  /* simple hash algorithm hack if md5 is not present */      //    GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(object));
1652  static char *simple_hash(char *str) {      g_signal_connect(G_OBJECT(object), "key_press_event",
1653      union {                       G_CALLBACK(on_window_key_press), priv);
         char str[4];  
         gulong val;  
     } hash = { .val = 0x55555555 };  
   
     while(*str) {  
         hash.str[(int)str & 3] ^= *str;  
         str++;  
     }  
     return g_strdup_printf("%08lX", hash.val);  
 }  
1654  #endif  #endif
1655    }
1656    
1657  static GObject *  static GObject *
1658  osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)  osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
# Line 1934  osm_gps_map_constructor (GType gtype, gu Line 1692  osm_gps_map_constructor (GType gtype, gu
1692      }      }
1693    
1694      if (!priv->cache_dir_is_full_path) {      if (!priv->cache_dir_is_full_path) {
1695  #ifdef G_CHECKSUM_MD5          const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source);
1696          char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);          if(!fname) fname = "_unknown_";
 #else  
         char *md5 = simple_hash(priv->repo_uri);  
 #endif  
1697    
1698          if (priv->cache_dir) {          if (priv->cache_dir) {
1699              char *old = priv->cache_dir;              char *old = priv->cache_dir;
1700              //the new cachedir is the given cache dir + the md5 of the repo_uri              //the new cachedir is the given cache dir + the md5 of the repo_uri
1701              priv->cache_dir = g_strdup_printf("%s%c%s", old, G_DIR_SEPARATOR, md5);              priv->cache_dir = g_strdup_printf("%s%c%s", old, G_DIR_SEPARATOR, fname);
1702              g_debug("Adjusting cache dir %s -> %s", old, priv->cache_dir);              g_debug("Adjusting cache dir %s -> %s", old, priv->cache_dir);
1703              g_free(old);              g_free(old);
1704          } else {          } else {
1705              //the new cachedir is the current dir + the md5 of the repo_uri              //the new cachedir is the current dir + the md5 of the repo_uri
1706              priv->cache_dir = g_strdup(md5);              priv->cache_dir = g_strdup(fname);
1707          }          }
   
         g_free(md5);  
1708      }      }
1709    
1710      inspect_map_uri(map);      inspect_map_uri(map);
# Line 1998  osm_gps_map_dispose (GObject *object) Line 1751  osm_gps_map_dispose (GObject *object)
1751  #endif  #endif
1752    
1753  #ifdef ENABLE_OSD  #ifdef ENABLE_OSD
1754      if (priv->osd.backup)      if(priv->osd)
1755          g_object_unref(priv->osd.backup);          priv->osd->free(priv->osd);
1756    
1757    #ifdef OSD_DOUBLE_BUFFER
1758        if(priv->dbuf_pixmap)
1759            g_object_unref (priv->dbuf_pixmap);
1760    #endif
1761  #endif  #endif
1762    
1763      G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);      G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
# Line 2229  osm_gps_map_button_press (GtkWidget *wid Line 1987  osm_gps_map_button_press (GtkWidget *wid
1987  #endif  #endif
1988    
1989  #ifdef ENABLE_OSD  #ifdef ENABLE_OSD
     #define SCROLL_STEP 10  
   
1990      /* pressed inside OSD control? */      /* pressed inside OSD control? */
1991      osd_button_t but = osm_gps_map_osd_check(event->x, event->y);      if(priv->osd) {
1992      if(but != OSD_NONE)          osd_button_t but = priv->osd->check(priv->osd, event->x, event->y);
1993      {          if(but != OSD_NONE)
1994          priv->drag_counter = -1;          {
1995                int step = GTK_WIDGET(widget)->allocation.width/OSM_GPS_MAP_SCROLL_STEP;
1996          switch(but) {              priv->drag_counter = -1;
1997          case OSD_GPS:  
1998              priv->osd.cb(priv->osd.data);              switch(but) {
1999              break;              case OSD_UP:
2000                    priv->map_y -= step;
2001          case OSD_UP:                  priv->center_coord_set = FALSE;
2002              priv->map_y -= GTK_WIDGET(widget)->allocation.height/SCROLL_STEP;                  osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
2003              priv->center_coord_set = FALSE;                  break;
             break;  
   
         case OSD_DOWN:  
             priv->map_y += GTK_WIDGET(widget)->allocation.height/SCROLL_STEP;  
             priv->center_coord_set = FALSE;  
             break;  
   
         case OSD_LEFT:  
             priv->map_x -= GTK_WIDGET(widget)->allocation.width/SCROLL_STEP;  
             priv->center_coord_set = FALSE;  
             break;  
   
         case OSD_RIGHT:  
             priv->map_x += GTK_WIDGET(widget)->allocation.width/SCROLL_STEP;  
             priv->center_coord_set = FALSE;  
             break;  
   
         case OSD_IN:  
             osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom+1);  
             break;  
2004    
2005          case OSD_OUT:              case OSD_DOWN:
2006              osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom-1);                  priv->map_y += step;
2007              break;                  priv->center_coord_set = FALSE;
2008                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
2009                    break;
2010    
2011          default:              case OSD_LEFT:
2012              break;                  priv->map_x -= step;
2013                    priv->center_coord_set = FALSE;
2014                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
2015                    break;
2016    
2017                case OSD_RIGHT:
2018                    priv->map_x += step;
2019                    priv->center_coord_set = FALSE;
2020                    osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
2021                    break;
2022    
2023                case OSD_IN:
2024                    osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom+1);
2025                    break;
2026    
2027                case OSD_OUT:
2028                    osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom-1);
2029                    break;
2030    
2031                default:
2032                    /* all custom buttons are forwarded to the application */
2033                    if(priv->osd->cb)
2034                        priv->osd->cb(but, priv->osd->data);
2035                    break;
2036                }
2037    
2038                return FALSE;
2039          }          }
   
         osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));  
   
         return FALSE;  
2040      }      }
2041  #endif  #endif
2042    
# Line 2329  osm_gps_map_button_release (GtkWidget *w Line 2089  osm_gps_map_button_release (GtkWidget *w
2089  }  }
2090    
2091  static gboolean  static gboolean
2092    osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event);
2093    
2094    static gboolean
2095  osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)  osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
2096  {  {
2097      int x, y;      int x, y;
# Line 2357  osm_gps_map_motion_notify (GtkWidget *wi Line 2120  osm_gps_map_motion_notify (GtkWidget *wi
2120      if (priv->drag_counter < 6)      if (priv->drag_counter < 6)
2121          return FALSE;          return FALSE;
2122    
2123    #ifdef OSM_GPS_MAP_REFRESH
2124        /* reduce update frequency on maemo to keep screen update fluid */
2125        static guint32 last_time = 0;
2126    
2127        if(event->time - last_time < (1000/OSM_GPS_MAP_REFRESH)) return FALSE;
2128        last_time = event->time;
2129    #endif
2130    
2131      priv->dragging = TRUE;      priv->dragging = TRUE;
2132    
2133      if (priv->map_auto_center)      if (priv->map_auto_center)
# Line 2365  osm_gps_map_motion_notify (GtkWidget *wi Line 2136  osm_gps_map_motion_notify (GtkWidget *wi
2136      priv->drag_mouse_dx = x - priv->drag_start_mouse_x;      priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
2137      priv->drag_mouse_dy = y - priv->drag_start_mouse_y;      priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
2138    
2139        osm_gps_map_expose (widget, NULL);
2140    
2141        return FALSE;
2142    }
2143    
2144    static gboolean
2145    osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
2146    {
2147        OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
2148    
2149        /* create pixmap */
2150        if (priv->pixmap)
2151            g_object_unref (priv->pixmap);
2152    
2153        priv->pixmap = gdk_pixmap_new (
2154                            widget->window,
2155                            widget->allocation.width + EXTRA_BORDER * 2,
2156                            widget->allocation.height + EXTRA_BORDER * 2,
2157                            -1);
2158    
2159  #ifdef ENABLE_OSD  #ifdef ENABLE_OSD
     /* undo OSD */  
     osm_gps_map_osd_restore (OSM_GPS_MAP(widget));  
2160    
2161      /* draw new OSD */  #ifdef OSD_DOUBLE_BUFFER
2162      osm_gps_map_osd_draw_controls (OSM_GPS_MAP(widget),      if (priv->dbuf_pixmap)
2163                                     -priv->drag_mouse_dx,          g_object_unref (priv->dbuf_pixmap);
2164                                     -priv->drag_mouse_dy);  
2165        priv->dbuf_pixmap = gdk_pixmap_new (
2166                            widget->window,
2167                            widget->allocation.width,
2168                            widget->allocation.height,
2169                            -1);
2170    #endif
2171    
2172        /* the osd needs some references to map internal objects */
2173        if(priv->osd)
2174            priv->osd->widget = widget;
2175    #endif
2176    
2177        /* and gc, used for clipping (I think......) */
2178        if(priv->gc_map)
2179            g_object_unref(priv->gc_map);
2180    
2181        priv->gc_map = gdk_gc_new(priv->pixmap);
2182    
2183        osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
2184    
2185        return FALSE;
2186    }
2187    
2188    static gboolean
2189    osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event)
2190    {
2191        OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
2192    
2193    #if defined(ENABLE_OSD) && defined(OSD_DOUBLE_BUFFER)
2194        GdkDrawable *drawable = priv->dbuf_pixmap;
2195    #else
2196        GdkDrawable *drawable = widget->window;
2197  #endif  #endif
2198    
2199      gdk_draw_drawable (      gdk_draw_drawable (drawable,
                        widget->window,  
2200                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2201                         priv->pixmap,                         priv->pixmap,
2202                         0,0,                         0,0,
2203                         priv->drag_mouse_dx - EXTRA_BORDER, priv->drag_mouse_dy - EXTRA_BORDER,                         priv->drag_mouse_dx - EXTRA_BORDER,
2204                           priv->drag_mouse_dy - EXTRA_BORDER,
2205                         -1,-1);                         -1,-1);
2206    
2207      //Paint white outside of the map if dragging. Its less      //Paint white outside of the map if dragging. Its less
2208      //ugly than painting the corrupted map      //ugly than painting the corrupted map
2209      if(priv->drag_mouse_dx>EXTRA_BORDER) {      if(priv->drag_mouse_dx>EXTRA_BORDER) {
2210          gdk_draw_rectangle (          gdk_draw_rectangle (drawable,
                             widget->window,  
2211                              widget->style->white_gc,                              widget->style->white_gc,
2212                              TRUE,                              TRUE,
2213                              0, 0,                              0, 0,
# Line 2396  osm_gps_map_motion_notify (GtkWidget *wi Line 2216  osm_gps_map_motion_notify (GtkWidget *wi
2216      }      }
2217      else if (-priv->drag_mouse_dx > EXTRA_BORDER)      else if (-priv->drag_mouse_dx > EXTRA_BORDER)
2218      {      {
2219          gdk_draw_rectangle (          gdk_draw_rectangle (drawable,
                             widget->window,  
2220                              widget->style->white_gc,                              widget->style->white_gc,
2221                              TRUE,                              TRUE,
2222                              priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,                              priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,
# Line 2406  osm_gps_map_motion_notify (GtkWidget *wi Line 2225  osm_gps_map_motion_notify (GtkWidget *wi
2225      }      }
2226    
2227      if (priv->drag_mouse_dy>EXTRA_BORDER) {      if (priv->drag_mouse_dy>EXTRA_BORDER) {
2228          gdk_draw_rectangle (          gdk_draw_rectangle (drawable,
                             widget->window,  
2229                              widget->style->white_gc,                              widget->style->white_gc,
2230                              TRUE,                              TRUE,
2231                              0, 0,                              0, 0,
# Line 2416  osm_gps_map_motion_notify (GtkWidget *wi Line 2234  osm_gps_map_motion_notify (GtkWidget *wi
2234      }      }
2235      else if (-priv->drag_mouse_dy > EXTRA_BORDER)      else if (-priv->drag_mouse_dy > EXTRA_BORDER)
2236      {      {
2237          gdk_draw_rectangle (          gdk_draw_rectangle (drawable,
                             widget->window,  
2238                              widget->style->white_gc,                              widget->style->white_gc,
2239                              TRUE,                              TRUE,
2240                              0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,                              0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,
# Line 2425  osm_gps_map_motion_notify (GtkWidget *wi Line 2242  osm_gps_map_motion_notify (GtkWidget *wi
2242                              -priv->drag_mouse_dy - EXTRA_BORDER);                              -priv->drag_mouse_dy - EXTRA_BORDER);
2243      }      }
2244    
2245      return FALSE;  #ifdef ENABLE_OSD
2246  }      /* draw new OSD */
2247        if(priv->osd)
2248  static gboolean          priv->osd->draw (priv->osd, drawable);
 osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)  
 {  
     OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);  
   
     /* create pixmap */  
     if (priv->pixmap)  
         g_object_unref (priv->pixmap);  
   
     priv->pixmap = gdk_pixmap_new (  
                                    widget->window,  
                                    widget->allocation.width + EXTRA_BORDER * 2,  
                                    widget->allocation.height + EXTRA_BORDER * 2,  
                                    -1);  
   
     /* and gc, used for clipping (I think......) */  
     if(priv->gc_map)  
         g_object_unref(priv->gc_map);  
   
     priv->gc_map = gdk_gc_new(priv->pixmap);  
   
     osm_gps_map_map_redraw(OSM_GPS_MAP(widget));  
   
     return FALSE;  
 }  
   
 static gboolean  
 osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event)  
 {  
     OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);  
2249    
2250      gdk_draw_drawable (  #ifdef OSD_DOUBLE_BUFFER
2251                         widget->window,      gdk_draw_drawable (widget->window,
2252                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2253                         priv->pixmap,                         priv->dbuf_pixmap,
2254                         event->area.x + EXTRA_BORDER,                         0,0,0,0,-1,-1);
                        event->area.y + EXTRA_BORDER,  
                        event->area.x, event->area.y,  
                        event->area.width, event->area.height);  
   
 #ifdef ENABLE_OSD_OVL  
     /* TODO: intersect with area */  
     if (priv->osd.pixbuf)  
     {  
         //        gdk_draw_drawable (widget->window,  
         //            widget->style->fg_gc[GTK_WIDGET_STATE (widget)],  
         //            priv->osd.pixbuf, 0, 0,  
         //            OSD_X, OSD_Y, OSD_W, OSD_H);  
     }  
2255  #endif  #endif
2256    
2257    #endif
2258    
2259      return FALSE;      return FALSE;
2260  }  }
2261    
# Line 3058  osm_gps_map_clear_images (OsmGpsMap *map Line 2835  osm_gps_map_clear_images (OsmGpsMap *map
2835  }  }
2836    
2837  void  void
 osm_gps_map_osd_speed (OsmGpsMap *map, float speed)  
 {  
     OsmGpsMapPrivate *priv;  
   
     PangoContext        *context = NULL;  
     PangoLayout     *layout  = NULL;  
     PangoFontDescription    *desc    = NULL;  
   
     GdkColor color;  
     GdkGC *gc;  
   
     gchar *buffer;  
     //static int x = 10, y = 10;  
     static int width = 0, height = 0;  
   
     g_return_if_fail (OSM_IS_GPS_MAP (map));  
     priv = map->priv;  
   
     buffer = g_strdup_printf("%.0f", speed);  
   
     /* pango initialisation */  
     context = gtk_widget_get_pango_context (GTK_WIDGET(map));  
     layout  = pango_layout_new (context);  
     desc    = pango_font_description_new();  
   
     pango_font_description_set_size (desc, 40 * PANGO_SCALE);  
     pango_layout_set_font_description (layout, desc);  
     pango_layout_set_text (layout, buffer, strlen(buffer));  
   
     gc = gdk_gc_new (GTK_WIDGET(map)->window);  
   
     color.red = (0 > 50) ? 0xffff : 0;  
     color.green = 0;  
     color.blue = 0;  
   
     gdk_gc_set_rgb_fg_color (gc, &color);  
   
     /* faster / less flicker alternative:*/  
     gdk_draw_drawable (  
                        GTK_WIDGET(map)->window,  
                        GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(map)],  
                        priv->pixmap,  
                        0,0,  
                        0,0,  
                        width+10,width+10);  
   
     gdk_draw_layout(GTK_WIDGET(map)->window,  
                     gc,  
                     0, 0,  
                     layout);  
   
     /* set width and height */  
     pango_layout_get_pixel_size(layout, &width, &height);  
   
     g_free(buffer);  
     pango_font_description_free (desc);  
     g_object_unref (layout);  
     g_object_unref (gc);  
 }  
   
 void  
2838  osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)  osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)
2839  {  {
2840      int pixel_x, pixel_y;      int pixel_x, pixel_y;
# Line 3289  osm_gps_map_clear_balloon (OsmGpsMap *ma Line 3005  osm_gps_map_clear_balloon (OsmGpsMap *ma
3005  #endif  #endif
3006    
3007  #ifdef ENABLE_OSD  #ifdef ENABLE_OSD
3008  void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdGpsCallback cb, gpointer data) {  
3009    void
3010    osm_gps_map_redraw (OsmGpsMap *map)
3011    {
3012        osm_gps_map_map_redraw_idle(map);
3013    }
3014    
3015    osm_gps_map_osd_t *osm_gps_map_osd_get(OsmGpsMap *map) {
3016        g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL);
3017        return map->priv->osd;
3018    }
3019    
3020    void osm_gps_map_register_osd(OsmGpsMap *map, osm_gps_map_osd_t *osd) {
3021      OsmGpsMapPrivate *priv;      OsmGpsMapPrivate *priv;
3022    
3023      g_return_if_fail (OSM_IS_GPS_MAP (map));      g_return_if_fail (OSM_IS_GPS_MAP (map));
     priv = map->priv;  
3024    
3025      priv->osd.cb = cb;      priv = map->priv;
3026      priv->osd.data = data;      g_return_if_fail (!priv->osd);
3027    
3028      osm_gps_map_map_redraw_idle(map);      priv->osd = osd;
3029  }  }
3030    
3031  #endif  #endif

Legend:
Removed from v.66  
changed lines
  Added in v.77