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

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

revision 55 by harbaum, Thu Aug 13 12:01:52 2009 UTC revision 63 by harbaum, Wed Aug 19 12:35:25 2009 UTC
# Line 98  struct _OsmGpsMapPrivate Line 98  struct _OsmGpsMapPrivate
98      coord_t *gps;      coord_t *gps;
99      gboolean gps_valid;      gboolean gps_valid;
100    
101        //a balloon with additional info
102        struct {
103            coord_t *coo;
104            gboolean valid;
105            OsmGpsMapRect_t rect;
106            OsmGpsMapBalloonCallback cb;
107            gpointer data;
108        } balloon;
109    
110    #ifdef ENABLE_OSD
111        //the osd controls
112        struct {
113            GdkPixmap *backup;
114            gint backup_x, backup_y;
115            //        GdkPixbuf *pixbuf;
116        } osd;
117    #endif
118    
119      //additional images or tracks added to the map      //additional images or tracks added to the map
120      GSList *tracks;      GSList *tracks;
121      GSList *images;      GSList *images;
# Line 631  osm_gps_map_draw_gps_point (OsmGpsMap *m Line 649  osm_gps_map_draw_gps_point (OsmGpsMap *m
649                                      (mr*2)+lw+lw);                                      (mr*2)+lw+lw);
650  #endif  #endif
651      }      }
652    }
653    
654    /* most visual effects are hardcoded by now, but may be made */
655    /* available via properties later */
656    #define BALLOON_AREA_WIDTH           290
657    #define BALLOON_AREA_HEIGHT           75
658    
659    #define BALLOON_CORNER_RADIUS         20
660    #define BALLOON_BORDER               (BALLOON_CORNER_RADIUS/4)
661    #define BALLOON_WIDTH                (BALLOON_AREA_WIDTH + 2 * BALLOON_BORDER)
662    #define BALLOON_HEIGHT               (BALLOON_AREA_HEIGHT + 2 * BALLOON_BORDER)
663    #define BALLOON_TRANSPARENCY         0.8
664    #define POINTER_HEIGHT                20
665    #define POINTER_FOOT_WIDTH            20
666    #define POINTER_OFFSET               (BALLOON_CORNER_RADIUS*3/4)
667    #define BALLOON_SHADOW                5
668    #define BALLOON_SHADOW_TRANSPARENCY  0.2
669    
670    #define CLOSE_BUTTON_RADIUS   (BALLOON_CORNER_RADIUS/3)
671    
672    
673    /* draw the bubble shape. this is used twice, once for the shape and once */
674    /* for the shadow */
675    static void
676    osm_gps_map_draw_balloon_shape (cairo_t *cr, int x0, int y0, int x1, int y1,
677           gboolean bottom, int px, int py, int px0, int px1) {
678    
679        cairo_move_to (cr, x0, y0 + BALLOON_CORNER_RADIUS);
680        cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + BALLOON_CORNER_RADIUS, y0);
681        if(!bottom) {
682            /* insert top pointer */
683            cairo_line_to (cr, px1, y0);
684            cairo_line_to (cr, px, py);
685            cairo_line_to (cr, px0, y0);
686        }
687    
688        cairo_line_to (cr, x1 - BALLOON_CORNER_RADIUS, y0);
689        cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + BALLOON_CORNER_RADIUS);
690        cairo_line_to (cr, x1 , y1 - BALLOON_CORNER_RADIUS);
691        cairo_curve_to (cr, x1, y1, x1, y1, x1 - BALLOON_CORNER_RADIUS, y1);
692        if(bottom) {
693            /* insert bottom pointer */
694            cairo_line_to (cr, px0, y1);
695            cairo_line_to (cr, px, py);
696            cairo_line_to (cr, px1, y1);
697        }
698    
699        cairo_line_to (cr, x0 + BALLOON_CORNER_RADIUS, y1);
700        cairo_curve_to (cr, x0, y1, x0, y1, x0, y1 - BALLOON_CORNER_RADIUS);
701    
702        cairo_close_path (cr);
703    }
704    
705    static void
706    osm_gps_map_draw_balloon_int (OsmGpsMap *map)
707    {
708        OsmGpsMapPrivate *priv = map->priv;
709    
710        if (priv->balloon.valid) {
711    
712            /* ------- convert given coordinate into screen position --------- */
713            int x0 = lon2pixel(priv->map_zoom, priv->balloon.coo->rlon) -
714                priv->map_x + EXTRA_BORDER;
715            int y0 = lat2pixel(priv->map_zoom, priv->balloon.coo->rlat) -
716                priv->map_y + EXTRA_BORDER;
717    
718            /* check position of this relative to screen center to determine */
719            /* pointer direction ... */
720            int pointer_x = x0, pointer_x0, pointer_x1;
721            int pointer_y = y0;
722    
723            /* ... and calculate position */
724            if((x0 - EXTRA_BORDER) > GTK_WIDGET(map)->allocation.width/2) {
725                x0 -= BALLOON_WIDTH - POINTER_OFFSET;
726                pointer_x0 = pointer_x - (BALLOON_CORNER_RADIUS - POINTER_OFFSET);
727                pointer_x1 = pointer_x0 - POINTER_FOOT_WIDTH;
728            } else {
729                x0 -= POINTER_OFFSET;
730                pointer_x1 = pointer_x + (BALLOON_CORNER_RADIUS - POINTER_OFFSET);
731                pointer_x0 = pointer_x1 + POINTER_FOOT_WIDTH;
732            }
733    
734            gboolean bottom = FALSE;
735            if((y0 - EXTRA_BORDER) > GTK_WIDGET(map)->allocation.height/2) {
736                bottom = TRUE;
737                y0 -= BALLOON_HEIGHT + POINTER_HEIGHT;
738            } else
739                y0 += POINTER_HEIGHT;
740    
741            /* calculate bottom/right of box */
742            int x1 = x0 + BALLOON_WIDTH, y1 = y0 + BALLOON_HEIGHT;
743    
744            /* save balloon screen coordinates for later use */
745            priv->balloon.rect.x = x0 + BALLOON_BORDER;
746            priv->balloon.rect.y = y0 + BALLOON_BORDER;
747            priv->balloon.rect.w = x1 - x0 - 2*BALLOON_BORDER;
748            priv->balloon.rect.h = y1 - y0 - 2*BALLOON_BORDER;
749    
750    #ifdef USE_CAIRO
751            cairo_t *cr = gdk_cairo_create(priv->pixmap);
752    
753            /* --------- draw shadow --------------- */
754            osm_gps_map_draw_balloon_shape (cr,
755                        x0 + BALLOON_SHADOW, y0 + BALLOON_SHADOW,
756                        x1 + BALLOON_SHADOW, y1 + BALLOON_SHADOW,
757                        bottom, pointer_x, pointer_y,
758                        pointer_x0 + BALLOON_SHADOW, pointer_x1 + BALLOON_SHADOW);
759    
760            cairo_set_source_rgba (cr, 0, 0, 0, BALLOON_SHADOW_TRANSPARENCY);
761            cairo_fill_preserve (cr);
762            cairo_set_source_rgba (cr, 1, 0, 0, 1.0);
763            cairo_set_line_width (cr, 0);
764            cairo_stroke (cr);
765    
766            /* --------- draw main shape ----------- */
767            osm_gps_map_draw_balloon_shape (cr, x0, y0, x1, y1,
768                        bottom, pointer_x, pointer_y, pointer_x0, pointer_x1);
769    
770            cairo_set_source_rgba (cr, 1, 1, 1, BALLOON_TRANSPARENCY);
771            cairo_fill_preserve (cr);
772            cairo_set_source_rgba (cr, 0, 0, 0, BALLOON_TRANSPARENCY);
773            cairo_set_line_width (cr, 1);
774            cairo_stroke (cr);
775    
776    
777            /* ---------- draw close button --------- */
778    
779            int cx = x1 - BALLOON_BORDER - CLOSE_BUTTON_RADIUS;
780            int cy = y0 + BALLOON_BORDER + CLOSE_BUTTON_RADIUS;
781            int crad = CLOSE_BUTTON_RADIUS;
782    
783            cairo_arc (cr, cx, cy, crad, 0, 2 * M_PI);
784            cairo_set_source_rgba (cr, 0.8, 0, 0, 1.0);
785            cairo_fill_preserve (cr);
786            cairo_set_source_rgba (cr, 0.3, 0, 0, 1.0);
787            cairo_set_line_width (cr, 2);
788            cairo_stroke(cr);
789    
790            cairo_set_source_rgba (cr, 1, 1, 1, 1.0);
791            cairo_set_line_width (cr, 3);
792            cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
793            cairo_move_to (cr, cx - crad/2, cy - crad/2);
794            cairo_line_to (cr, cx + crad/2, cy + crad/2);
795            cairo_stroke (cr);
796            cairo_move_to (cr, cx + crad/2, cy - crad/2);
797            cairo_line_to (cr, cx - crad/2, cy + crad/2);
798            cairo_stroke (cr);
799    
800            if (priv->balloon.cb) {
801                /* clip in case application tries to draw in */
802                /* exceed of the balloon */
803                cairo_rectangle (cr, priv->balloon.rect.x, priv->balloon.rect.y,
804                                 priv->balloon.rect.w, priv->balloon.rect.h);
805                cairo_clip (cr);
806                cairo_new_path (cr);  /* current path is not
807                                         consumed by cairo_clip() */
808    
809                priv->balloon.cb(cr, &priv->balloon.rect, priv->balloon.data);
810            }
811    
812            cairo_destroy(cr);
813    
814            gtk_widget_queue_draw_area (GTK_WIDGET(map),
815                                        x0, y0, BALLOON_WIDTH,
816                                        BALLOON_HEIGHT + POINTER_HEIGHT);
817    #else
818    #warning "Balloon display lacks a non-cairo implementation!"
819    #endif
820        }
821    }
822    
823    /* the user clicked into the balloons main area. handle this */
824    static void
825    osm_gps_map_handle_balloon_click(OsmGpsMap *map, gint x, gint y)
826    {
827        OsmGpsMapPrivate *priv = map->priv;
828    
829        if (!priv->balloon.valid)
830            return;
831    
832        /* check if the close button was clicked */
833        if ((x > priv->balloon.rect.w - 2*CLOSE_BUTTON_RADIUS) &&
834            (x < priv->balloon.rect.w) &&
835            (y > 0) && (y < 2*CLOSE_BUTTON_RADIUS)) {
836    
837            priv->balloon.valid = FALSE;
838            osm_gps_map_map_redraw_idle(map);
839        }
840    }
841    
842    /* return true if balloon is being displayed and if */
843    /* the given coordinate is within this balloon */
844    static gboolean
845    osm_gps_map_in_balloon(OsmGpsMapPrivate *priv, gint x, gint y)
846    {
847        return (priv->balloon.valid &&
848                (x > priv->balloon.rect.x) &&
849                (x < priv->balloon.rect.x + priv->balloon.rect.w) &&
850                (y > priv->balloon.rect.y) &&
851                (y < priv->balloon.rect.y + priv->balloon.rect.h));
852  }  }
853    
854  static void  static void
# Line 695  osm_gps_map_tile_download_complete (Soup Line 913  osm_gps_map_tile_download_complete (Soup
913              }              }
914              else              else
915              {              {
916                  g_warning("Error creating tile download directory: %s", dl->folder);                  g_warning("Error creating tile download directory: %s",
917                              dl->folder);
918                    perror("perror:");
919              }              }
920          }          }
921    
# Line 1187  osm_gps_map_purge_cache (OsmGpsMap *map) Line 1407  osm_gps_map_purge_cache (OsmGpsMap *map)
1407     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);
1408  }  }
1409    
1410    #ifdef ENABLE_OSD
1411    /* position and extent of bounding box */
1412    #define OSD_X      (10)
1413    #define OSD_Y      (10)
1414    
1415    #define OSD_COLOR  0.5, 0.5, 1
1416    
1417    /* parameters of the direction shape */
1418    #define D_RAD  (20)         // diameter of dpad
1419    #define D_TIP  (4*D_RAD/5)  // distance of arrow tip from dpad center
1420    #define D_LEN  (D_RAD/4)    // length of arrow
1421    #define D_WID  (D_LEN)      // width of arrow
1422    
1423    /* parameters of the "zoom" pad */
1424    #define Z_STEP   (-D_RAD/8) // distance between dpad and zoom
1425    #define Z_RAD    (D_RAD/2)  // radius of "caps" of zoom bar
1426    
1427    /* shadow also depends on control size */
1428    #define OSD_SHADOW (D_RAD/8)
1429    
1430    /* total width and height of controls incl. shadow */
1431    #define OSD_W    (2*D_RAD + OSD_SHADOW)
1432    #define OSD_H    (2*D_RAD + Z_STEP + 2*Z_RAD + OSD_SHADOW)
1433    
1434    #define OSD_LBL_SHADOW (OSD_SHADOW/2)
1435    
1436    #define Z_TOP    (2 * D_RAD + Z_STEP)
1437    #define Z_MID    (Z_TOP + Z_RAD)
1438    #define Z_BOT    (Z_MID + Z_RAD)
1439    #define Z_LEFT   (Z_RAD)
1440    #define Z_RIGHT  (2 * D_RAD - Z_RAD)
1441    
1442    /* create the cairo shape used for the zoom buttons */
1443    static void
1444    osm_gps_map_osd_zoom_shape(cairo_t *cr, gint x, gint y) {
1445        cairo_move_to (cr, x+Z_LEFT,    y+Z_TOP);
1446        cairo_line_to (cr, x+Z_RIGHT,   y+Z_TOP);
1447        cairo_arc     (cr, x+Z_RIGHT,   y+Z_MID, Z_RAD, -M_PI/2,  M_PI/2);
1448        cairo_line_to (cr, x+Z_LEFT,    y+Z_BOT);
1449        cairo_arc     (cr, x+Z_LEFT,    y+Z_MID, Z_RAD,  M_PI/2, -M_PI/2);
1450    }
1451    
1452    /* create the cairo shape used for the dpad */
1453    static void
1454    osm_gps_map_osd_dpad_shape(cairo_t *cr, gint x, gint y) {
1455        cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI);
1456    }
1457    
1458    typedef enum {
1459        OSD_NONE = 0,
1460        OSD_BG,
1461        OSD_UP,
1462        OSD_DOWN,
1463        OSD_LEFT,
1464        OSD_RIGHT,
1465        OSD_IN,
1466        OSD_OUT,
1467        OSD_GPS
1468    } osd_button_t;
1469    
1470    static gboolean
1471    osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad)
1472    {
1473        return( pow(cx - x, 2) + pow(cy - y, 2) < rad * rad);
1474    }
1475    
1476    /* check whether x/y is within the dpad */
1477    static osd_button_t
1478    osm_gps_map_osd_check_dpad(gint x, gint y)
1479    {
1480        /* within entire dpad circle */
1481        if( osm_gps_map_in_circle(x, y, OSD_X + D_RAD, OSD_Y + D_RAD, D_RAD))
1482        {
1483            /* convert into position relative to dpads centre */
1484            x -= (OSD_X + D_RAD);
1485            y -= (OSD_Y + D_RAD);
1486    
1487            /* check for dpad center goes here! */
1488            if( osm_gps_map_in_circle(x, y, OSD_X + D_RAD, OSD_Y + D_RAD, D_RAD/3))
1489                return OSD_GPS;
1490    
1491            if( y < 0 && abs(x) < abs(y))
1492                return OSD_UP;
1493    
1494            if( y > 0 && abs(x) < abs(y))
1495                return OSD_DOWN;
1496    
1497            if( x < 0 && abs(y) < abs(x))
1498                return OSD_LEFT;
1499    
1500            if( x > 0 && abs(y) < abs(x))
1501                return OSD_RIGHT;
1502    
1503            return OSD_BG;
1504        }
1505        return OSD_NONE;
1506    }
1507    
1508    /* check whether x/y is within the zoom pads */
1509    static osd_button_t
1510    osm_gps_map_osd_check_zoom(gint x, gint y) {
1511        if( x > OSD_X && x < (OSD_X + OSD_W) && y > Z_TOP && y < Z_BOT) {
1512    
1513            /* within circle around (-) label */
1514            if( osm_gps_map_in_circle(x, y, OSD_X + Z_LEFT, OSD_Y + Z_MID, Z_RAD))
1515                return OSD_OUT;
1516    
1517            /* between center of (-) button and center of entire zoom control area */
1518            if(x > OSD_LEFT && x < OSD_X + D_RAD)
1519                return OSD_OUT;
1520    
1521            /* within circle around (+) label */
1522            if( osm_gps_map_in_circle(x, y, OSD_X + Z_RIGHT, OSD_Y + Z_MID, Z_RAD))
1523                return OSD_IN;
1524    
1525            /* between center of (+) button and center of entire zoom control area */
1526            if(x < OSD_RIGHT && x > OSD_X + D_RAD)
1527                return OSD_IN;
1528        }
1529    
1530        return OSD_NONE;
1531    }
1532    
1533    static osd_button_t
1534    osm_gps_map_osd_check(gint x, gint y) {
1535        osd_button_t but = OSD_NONE;
1536    
1537        /* first do a rough test for the OSD area. */
1538        /* this is just to avoid an unnecessary detailed test */
1539        if(x > OSD_X && x < OSD_X + OSD_W &&
1540           y > OSD_Y && y < OSD_Y + OSD_H) {
1541    
1542            but = osm_gps_map_osd_check_dpad(x, y);
1543    
1544            if(but == OSD_NONE)
1545                but = osm_gps_map_osd_check_zoom(x, y);
1546        }
1547    
1548        return but;
1549    }
1550    
1551    static void
1552    osm_gps_map_osd_shape_shadow(cairo_t *cr) {
1553        cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
1554        cairo_fill (cr);
1555        cairo_stroke (cr);
1556    }
1557    
1558    static void
1559    osm_gps_map_osd_shape(cairo_t *cr) {
1560        cairo_set_source_rgb (cr, 1, 1, 1);
1561        cairo_fill_preserve (cr);
1562        cairo_set_source_rgb (cr, OSD_COLOR);
1563        cairo_set_line_width (cr, 1);
1564        cairo_stroke (cr);
1565    }
1566    
1567    static void
1568    osm_gps_map_osd_dpad_labels(cairo_t *cr, gint x, gint y) {
1569        /* move reference to dpad center */
1570        x += D_RAD;
1571        y += D_RAD;
1572    
1573        const static gint offset[][3][2] = {
1574            /* left arrow/triangle */
1575            { { -D_TIP+D_LEN, -D_WID }, { -D_LEN, D_WID }, { +D_LEN, D_WID } },
1576            /* right arrow/triangle */
1577            { { +D_TIP-D_LEN, -D_WID }, { +D_LEN, D_WID }, { -D_LEN, D_WID } },
1578            /* top arrow/triangle */
1579            { { -D_WID, -D_TIP+D_LEN }, { D_WID, -D_LEN }, { D_WID, +D_LEN } },
1580            /* bottom arrow/triangle */
1581            { { -D_WID, +D_TIP-D_LEN }, { D_WID, +D_LEN }, { D_WID, -D_LEN } }
1582        };
1583    
1584        int i;
1585        for(i=0;i<4;i++) {
1586            cairo_move_to (cr, x + offset[i][0][0], y + offset[i][0][1]);
1587            cairo_rel_line_to (cr, offset[i][1][0], offset[i][1][1]);
1588            cairo_rel_line_to (cr, offset[i][2][0], offset[i][2][1]);
1589        }
1590    }
1591    
1592    /* draw the sattelite dish icon in the center of the dpad */
1593    #define GPS_V0  (D_RAD/8)
1594    #define GPS_V1  (D_RAD/10)
1595    #define GPS_V2  (D_RAD/5)
1596    
1597    /* draw a satellite receiver dish */
1598    static void
1599    osm_gps_map_osd_dpad_gps(cairo_t *cr, gint x, gint y) {
1600        /* move reference to dpad center */
1601        x += D_RAD;
1602        y += D_RAD + GPS_V0;
1603    
1604        cairo_move_to (cr, x-GPS_V0, y+GPS_V0);
1605        cairo_rel_line_to (cr, +GPS_V0, -GPS_V0);
1606        cairo_rel_line_to (cr, +GPS_V0, +GPS_V0);
1607        cairo_close_path (cr);
1608    
1609        cairo_move_to (cr, x+GPS_V1-GPS_V2, y-2*GPS_V2);
1610        cairo_curve_to (cr, x-GPS_V2, y, x+GPS_V1, y+GPS_V1, x+GPS_V1+GPS_V2, y);
1611        cairo_close_path (cr);
1612    
1613        x += GPS_V1;
1614        cairo_move_to (cr, x, y-GPS_V2);
1615        cairo_rel_line_to (cr, +GPS_V1, -GPS_V1);
1616    }
1617    
1618    #define Z_LEN  (2*Z_RAD/3)
1619    
1620    static void
1621    osm_gps_map_osd_zoom_labels(cairo_t *cr, gint x, gint y) {
1622        cairo_move_to (cr, x + Z_LEFT  - Z_LEN, y + Z_MID);
1623        cairo_line_to (cr, x + Z_LEFT  + Z_LEN, y + Z_MID);
1624    
1625        cairo_move_to (cr, x + Z_RIGHT,         y + Z_MID - Z_LEN);
1626        cairo_line_to (cr, x + Z_RIGHT,         y + Z_MID + Z_LEN);
1627        cairo_move_to (cr, x + Z_RIGHT - Z_LEN, y + Z_MID);
1628        cairo_line_to (cr, x + Z_RIGHT + Z_LEN, y + Z_MID);
1629    }
1630    
1631    static void
1632    osm_gps_map_osd_labels(cairo_t *cr, gint width) {
1633        cairo_set_source_rgb (cr, OSD_COLOR);
1634        cairo_set_line_width (cr, width);
1635        cairo_stroke (cr);
1636    }
1637    
1638    static void
1639    osm_gps_map_osd_labels_shadow(cairo_t *cr, gint width) {
1640        cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
1641        cairo_set_line_width (cr, width);
1642        cairo_stroke (cr);
1643    }
1644    
1645    static void
1646    osm_gps_map_osd_draw_controls (OsmGpsMap *map, gint xoffset, gint yoffset)
1647    {
1648        OsmGpsMapPrivate *priv = map->priv;
1649    
1650        /* backup previous contents */
1651        if(!priv->osd.backup)
1652            priv->osd.backup = gdk_pixmap_new(priv->pixmap, OSD_W+2, OSD_H+2, -1);
1653    
1654        gint x = OSD_X + EXTRA_BORDER + xoffset;
1655        gint y = OSD_Y + EXTRA_BORDER + yoffset;
1656    
1657        /* create backup of background */
1658        gdk_draw_drawable(priv->osd.backup,
1659            GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],
1660                          priv->pixmap, x-1, y-1, 0, 0, OSD_W+2, OSD_H+2);
1661        priv->osd.backup_x = x-1;
1662        priv->osd.backup_y = y-1;
1663    
1664    #if 0
1665        /* create pixbuf for osd */
1666        if(!priv->osd.pixbuf)
1667            priv->osd.pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
1668                                              TRUE, 8, OSD_W, OSD_H);
1669        cairo_surface_t *surface =
1670            cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_W, OSD_H);
1671    
1672        /* fill with transparency */
1673        {
1674        cairo_t *cr = cairo_create(surface);
1675        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1676        cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.0);
1677        cairo_paint(cr);
1678        cairo_destroy(cr);
1679        }
1680    #endif
1681    
1682    
1683    #ifdef USE_CAIRO
1684        //    cairo_t *cr = cairo_create(surface);
1685        cairo_t *cr = gdk_cairo_create(priv->pixmap);
1686    
1687        /* --------- draw zoom and dpad shape shadow ----------- */
1688    
1689        osm_gps_map_osd_zoom_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);
1690        osm_gps_map_osd_shape_shadow(cr);
1691        osm_gps_map_osd_dpad_shape(cr, x + OSD_SHADOW, y + OSD_SHADOW);
1692        osm_gps_map_osd_shape_shadow(cr);
1693    
1694        /* --------- draw zoom and dpad shape ----------- */
1695    
1696        osm_gps_map_osd_zoom_shape(cr, x, y);
1697        osm_gps_map_osd_shape(cr);
1698        osm_gps_map_osd_dpad_shape(cr, x, y);
1699        osm_gps_map_osd_shape(cr);
1700    
1701        /* --------- draw zoom and dpad labels --------- */
1702    
1703        osm_gps_map_osd_zoom_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
1704        osm_gps_map_osd_dpad_labels(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
1705        osm_gps_map_osd_labels_shadow(cr, Z_RAD/3);
1706        osm_gps_map_osd_dpad_gps(cr, x + OSD_LBL_SHADOW, y + OSD_LBL_SHADOW);
1707        osm_gps_map_osd_labels_shadow(cr, Z_RAD/6);
1708    
1709        osm_gps_map_osd_zoom_labels(cr, x, y);
1710        osm_gps_map_osd_dpad_labels(cr, x, y);
1711        osm_gps_map_osd_labels(cr, Z_RAD/3);
1712        osm_gps_map_osd_dpad_gps(cr, x, y);
1713        osm_gps_map_osd_labels(cr, Z_RAD/6);
1714    
1715        cairo_destroy(cr);
1716    
1717    #else
1718    #warning "OSD control display lacks a non-cairo implementation!"
1719    #endif
1720    }
1721    
1722    static void
1723    osm_gps_map_osd_restore (OsmGpsMap *map)
1724    {
1725        OsmGpsMapPrivate *priv = map->priv;
1726    
1727        /* restore backup of previous contents */
1728        if(priv->osd.backup) {
1729            /* create backup of background */
1730            gdk_draw_drawable(priv->pixmap,
1731                GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(map))],
1732                          priv->osd.backup, 0, 0,
1733                          priv->osd.backup_x, priv->osd.backup_y, OSD_W+2, OSD_H+2);
1734        }
1735    }
1736    
1737    #endif
1738    
1739  static gboolean  static gboolean
1740  osm_gps_map_map_redraw (OsmGpsMap *map)  osm_gps_map_map_redraw (OsmGpsMap *map)
1741  {  {
# Line 1217  osm_gps_map_map_redraw (OsmGpsMap *map) Line 1766  osm_gps_map_map_redraw (OsmGpsMap *map)
1766      osm_gps_map_print_tracks(map);      osm_gps_map_print_tracks(map);
1767      osm_gps_map_draw_gps_point(map);      osm_gps_map_draw_gps_point(map);
1768      osm_gps_map_print_images(map);      osm_gps_map_print_images(map);
1769        osm_gps_map_draw_balloon_int(map);
1770    #ifdef ENABLE_OSD
1771        osm_gps_map_osd_draw_controls(map, 0, 0);
1772    #endif
1773    
1774      //osm_gps_map_osd_speed(map, 1.5);      //osm_gps_map_osd_speed(map, 1.5);
1775      osm_gps_map_purge_cache(map);      osm_gps_map_purge_cache(map);
# Line 1248  osm_gps_map_init (OsmGpsMap *object) Line 1801  osm_gps_map_init (OsmGpsMap *object)
1801      priv->gps = g_new0(coord_t, 1);      priv->gps = g_new0(coord_t, 1);
1802      priv->gps_valid = FALSE;      priv->gps_valid = FALSE;
1803    
1804        priv->balloon.coo = g_new0(coord_t, 1);
1805        priv->balloon.valid = FALSE;
1806        priv->balloon.cb = NULL;
1807    
1808    #ifdef ENABLE_OSD
1809        priv->osd.backup = NULL;
1810    #endif
1811    
1812      priv->tracks = NULL;      priv->tracks = NULL;
1813      priv->images = NULL;      priv->images = NULL;
1814    
# Line 1405  osm_gps_map_dispose (GObject *object) Line 1966  osm_gps_map_dispose (GObject *object)
1966      if (priv->idle_map_redraw != 0)      if (priv->idle_map_redraw != 0)
1967          g_source_remove (priv->idle_map_redraw);          g_source_remove (priv->idle_map_redraw);
1968    
1969        g_free(priv->gps);
1970        g_free(priv->balloon.coo);
1971    
1972    #ifdef ENABLE_OSD
1973        if (priv->osd.backup)
1974            g_object_unref(priv->osd.backup);
1975    #endif
1976    
1977      G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);      G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
1978  }  }
1979    
# Line 1620  osm_gps_map_button_press (GtkWidget *wid Line 2189  osm_gps_map_button_press (GtkWidget *wid
2189  {  {
2190      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
2191    
2192        /* don't drag if the user clicked within the balloon */
2193        if (osm_gps_map_in_balloon(priv,
2194                       event->x + EXTRA_BORDER,
2195                       event->y + EXTRA_BORDER))
2196        {
2197            priv->drag_counter = -1;
2198            return FALSE;
2199        }
2200    
2201    #ifdef ENABLE_OSD
2202        /* also don't drag on clicks into the control OSD */
2203        if(osm_gps_map_osd_check(event->x, event->y) != OSD_NONE)
2204        {
2205            priv->drag_counter = -1;
2206            return FALSE;
2207        }
2208    #endif
2209    
2210      priv->drag_counter = 0;      priv->drag_counter = 0;
2211      priv->drag_start_mouse_x = (int) event->x;      priv->drag_start_mouse_x = (int) event->x;
2212      priv->drag_start_mouse_y = (int) event->y;      priv->drag_start_mouse_y = (int) event->y;
# Line 1634  osm_gps_map_button_release (GtkWidget *w Line 2221  osm_gps_map_button_release (GtkWidget *w
2221  {  {
2222      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);      OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
2223    
2224    #ifdef ENABLE_OSD
2225        /* released inside OSD control? */
2226        osd_button_t but = osm_gps_map_osd_check(event->x, event->y);
2227        if(but != OSD_NONE)
2228        {
2229            switch(but) {
2230            case OSD_UP:
2231                priv->map_y -= GTK_WIDGET(widget)->allocation.height/4;
2232                priv->center_coord_set = FALSE;
2233                break;
2234    
2235            case OSD_DOWN:
2236                priv->map_y += GTK_WIDGET(widget)->allocation.height/4;
2237                priv->center_coord_set = FALSE;
2238                break;
2239    
2240            case OSD_LEFT:
2241                priv->map_x -= GTK_WIDGET(widget)->allocation.width/4;
2242                priv->center_coord_set = FALSE;
2243                break;
2244    
2245            case OSD_RIGHT:
2246                priv->map_x += GTK_WIDGET(widget)->allocation.width/4;
2247                priv->center_coord_set = FALSE;
2248                break;
2249    
2250            case OSD_IN:
2251                osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom+1);
2252                break;
2253    
2254            case OSD_OUT:
2255                osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom-1);
2256                break;
2257    
2258            default:
2259                break;
2260            }
2261    
2262            osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
2263    
2264            return FALSE;
2265        }
2266    #endif
2267    
2268        /* released inside the balloon? */
2269        if (osm_gps_map_in_balloon(priv,
2270                       event->x + EXTRA_BORDER,
2271                       event->y + EXTRA_BORDER))
2272        {
2273            osm_gps_map_handle_balloon_click(OSM_GPS_MAP(widget),
2274                 event->x - priv->balloon.rect.x + EXTRA_BORDER,
2275                 event->y - priv->balloon.rect.y + EXTRA_BORDER);
2276        }
2277    
2278      if (priv->dragging)      if (priv->dragging)
2279      {      {
2280          priv->dragging = FALSE;          priv->dragging = FALSE;
# Line 1651  osm_gps_map_button_release (GtkWidget *w Line 2292  osm_gps_map_button_release (GtkWidget *w
2292    
2293      priv->drag_mouse_dx = 0;      priv->drag_mouse_dx = 0;
2294      priv->drag_mouse_dy = 0;      priv->drag_mouse_dy = 0;
2295      priv->drag_counter = 0;      priv->drag_counter = -1;
2296    
2297      return FALSE;      return FALSE;
2298  }  }
# Line 1676  osm_gps_map_motion_notify (GtkWidget *wi Line 2317  osm_gps_map_motion_notify (GtkWidget *wi
2317      if (!(state & GDK_BUTTON1_MASK))      if (!(state & GDK_BUTTON1_MASK))
2318          return FALSE;          return FALSE;
2319    
2320        if (priv->drag_counter < 0)
2321            return FALSE;
2322    
2323      priv->drag_counter++;      priv->drag_counter++;
2324    
2325      // we havent dragged more than 6 pixels      // we havent dragged more than 6 pixels
# Line 1690  osm_gps_map_motion_notify (GtkWidget *wi Line 2334  osm_gps_map_motion_notify (GtkWidget *wi
2334      priv->drag_mouse_dx = x - priv->drag_start_mouse_x;      priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
2335      priv->drag_mouse_dy = y - priv->drag_start_mouse_y;      priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
2336    
2337    #ifdef ENABLE_OSD
2338        /* undo OSD */
2339        osm_gps_map_osd_restore (OSM_GPS_MAP(widget));
2340    
2341        /* draw new OSD */
2342        osm_gps_map_osd_draw_controls (OSM_GPS_MAP(widget),
2343                                       -priv->drag_mouse_dx,
2344                                       -priv->drag_mouse_dy);
2345    #endif
2346    
2347      gdk_draw_drawable (      gdk_draw_drawable (
2348                         widget->window,                         widget->window,
2349                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
# Line 1778  osm_gps_map_expose (GtkWidget *widget, G Line 2432  osm_gps_map_expose (GtkWidget *widget, G
2432                         widget->window,                         widget->window,
2433                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2434                         priv->pixmap,                         priv->pixmap,
2435                         event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,                         event->area.x + EXTRA_BORDER,
2436                           event->area.y + EXTRA_BORDER,
2437                         event->area.x, event->area.y,                         event->area.x, event->area.y,
2438                         event->area.width, event->area.height);                         event->area.width, event->area.height);
2439    
2440    #ifdef ENABLE_OSD_OVL
2441        /* TODO: intersect with area */
2442        if (priv->osd.pixbuf)
2443        {
2444            //        gdk_draw_drawable (widget->window,
2445            //            widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2446            //            priv->osd.pixbuf, 0, 0,
2447            //            OSD_X, OSD_Y, OSD_W, OSD_H);
2448        }
2449    #endif
2450    
2451      return FALSE;      return FALSE;
2452  }  }
2453    
# Line 2553  osm_gps_map_get_scale(OsmGpsMap *map) Line 3219  osm_gps_map_get_scale(OsmGpsMap *map)
3219      return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);      return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);
3220  }  }
3221    
3222    void
3223    osm_gps_map_draw_balloon (OsmGpsMap *map, float latitude, float longitude,
3224                              OsmGpsMapBalloonCallback cb, gpointer data)
3225    {
3226        OsmGpsMapPrivate *priv;
3227    
3228        /* remove and previously installed balloon */
3229        osm_gps_map_clear_balloon (map);
3230    
3231        g_return_if_fail (OSM_IS_GPS_MAP (map));
3232        priv = map->priv;
3233    
3234        priv->balloon.coo->rlat = deg2rad(latitude);
3235        priv->balloon.coo->rlon = deg2rad(longitude);
3236        priv->balloon.valid = TRUE;
3237    
3238        priv->balloon.cb = cb;
3239        priv->balloon.data = data;
3240    
3241        // this redraws the map
3242        osm_gps_map_map_redraw_idle(map);
3243    }
3244    
3245    void
3246    osm_gps_map_clear_balloon (OsmGpsMap *map)
3247    {
3248        OsmGpsMapPrivate *priv;
3249    
3250        g_return_if_fail (OSM_IS_GPS_MAP (map));
3251        priv = map->priv;
3252    
3253        priv->balloon.valid = FALSE;
3254    
3255        osm_gps_map_map_redraw_idle(map);
3256    }

Legend:
Removed from v.55  
changed lines
  Added in v.63