99 |
gboolean gps_valid; |
gboolean gps_valid; |
100 |
|
|
101 |
//a balloon with additional info |
//a balloon with additional info |
102 |
coord_t *balloon; |
struct { |
103 |
gboolean balloon_valid; |
coord_t *coo; |
104 |
|
gboolean valid; |
105 |
|
OsmGpsMapRect_t rect; |
106 |
|
OsmGpsMapBalloonCallback cb; |
107 |
|
gpointer data; |
108 |
|
} balloon; |
109 |
|
|
110 |
//additional images or tracks added to the map |
//additional images or tracks added to the map |
111 |
GSList *tracks; |
GSList *tracks; |
644 |
|
|
645 |
/* most visual effects are hardcoded by now, but may be made */ |
/* most visual effects are hardcoded by now, but may be made */ |
646 |
/* available via properties later */ |
/* available via properties later */ |
647 |
|
#define BALLOON_AREA_WIDTH 250 |
648 |
|
#define BALLOON_AREA_HEIGHT 75 |
649 |
|
|
650 |
#define BALLOON_CORNER_RADIUS 20 |
#define BALLOON_CORNER_RADIUS 20 |
651 |
#define BALLOON_WIDTH 150 |
#define BALLOON_BORDER (BALLOON_CORNER_RADIUS/4) |
652 |
#define BALLOON_HEIGHT 75 |
#define BALLOON_WIDTH (BALLOON_AREA_WIDTH + 2 * BALLOON_BORDER) |
653 |
|
#define BALLOON_HEIGHT (BALLOON_AREA_HEIGHT + 2 * BALLOON_BORDER) |
654 |
#define BALLOON_TRANSPARENCY 0.8 |
#define BALLOON_TRANSPARENCY 0.8 |
655 |
#define POINTER_HEIGHT 20 |
#define POINTER_HEIGHT 20 |
656 |
#define POINTER_FOOT_WIDTH 20 |
#define POINTER_FOOT_WIDTH 20 |
658 |
#define BALLOON_SHADOW 5 |
#define BALLOON_SHADOW 5 |
659 |
#define BALLOON_SHADOW_TRANSPARENCY 0.2 |
#define BALLOON_SHADOW_TRANSPARENCY 0.2 |
660 |
|
|
661 |
|
#define CLOSE_BUTTON_RADIUS (BALLOON_CORNER_RADIUS/3) |
662 |
|
|
663 |
|
|
664 |
/* draw the bubble shape. this is used twice, once for the shape and once */ |
/* draw the bubble shape. this is used twice, once for the shape and once */ |
665 |
/* for the shadow */ |
/* for the shadow */ |
666 |
static void |
static void |
670 |
cairo_move_to (cr, x0, y0 + BALLOON_CORNER_RADIUS); |
cairo_move_to (cr, x0, y0 + BALLOON_CORNER_RADIUS); |
671 |
cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + BALLOON_CORNER_RADIUS, y0); |
cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + BALLOON_CORNER_RADIUS, y0); |
672 |
if(!bottom) { |
if(!bottom) { |
673 |
/* insert bottom/left pointer */ |
/* insert top pointer */ |
674 |
cairo_line_to (cr, px1, y0); |
cairo_line_to (cr, px1, y0); |
675 |
cairo_line_to (cr, px, py); |
cairo_line_to (cr, px, py); |
676 |
cairo_line_to (cr, px0, y0); |
cairo_line_to (cr, px0, y0); |
681 |
cairo_line_to (cr, x1 , y1 - BALLOON_CORNER_RADIUS); |
cairo_line_to (cr, x1 , y1 - BALLOON_CORNER_RADIUS); |
682 |
cairo_curve_to (cr, x1, y1, x1, y1, x1 - BALLOON_CORNER_RADIUS, y1); |
cairo_curve_to (cr, x1, y1, x1, y1, x1 - BALLOON_CORNER_RADIUS, y1); |
683 |
if(bottom) { |
if(bottom) { |
684 |
/* insert bottom/left pointer */ |
/* insert bottom pointer */ |
685 |
cairo_line_to (cr, px0, y1); |
cairo_line_to (cr, px0, y1); |
686 |
cairo_line_to (cr, px, py); |
cairo_line_to (cr, px, py); |
687 |
cairo_line_to (cr, px1, y1); |
cairo_line_to (cr, px1, y1); |
699 |
{ |
{ |
700 |
OsmGpsMapPrivate *priv = map->priv; |
OsmGpsMapPrivate *priv = map->priv; |
701 |
|
|
702 |
if (priv->balloon_valid) { |
if (priv->balloon.valid) { |
703 |
|
|
704 |
/* ------- convert given coordinate into screen position --------- */ |
/* ------- convert given coordinate into screen position --------- */ |
705 |
int x0 = lon2pixel(priv->map_zoom, priv->balloon->rlon) - |
int x0 = lon2pixel(priv->map_zoom, priv->balloon.coo->rlon) - |
706 |
priv->map_x + EXTRA_BORDER; |
priv->map_x + EXTRA_BORDER; |
707 |
int y0 = lat2pixel(priv->map_zoom, priv->balloon->rlat) - |
int y0 = lat2pixel(priv->map_zoom, priv->balloon.coo->rlat) - |
708 |
priv->map_y + EXTRA_BORDER; |
priv->map_y + EXTRA_BORDER; |
709 |
|
|
710 |
/* check position of this relative to screen center to determine */ |
/* check position of this relative to screen center to determine */ |
733 |
/* calculate bottom/right of box */ |
/* calculate bottom/right of box */ |
734 |
int x1 = x0 + BALLOON_WIDTH, y1 = y0 + BALLOON_HEIGHT; |
int x1 = x0 + BALLOON_WIDTH, y1 = y0 + BALLOON_HEIGHT; |
735 |
|
|
736 |
|
/* save balloon screen coordinates for later use */ |
737 |
|
priv->balloon.rect.x = x0 + BALLOON_BORDER; |
738 |
|
priv->balloon.rect.y = y0 + BALLOON_BORDER; |
739 |
|
priv->balloon.rect.w = x1 - x0 - 2*BALLOON_BORDER; |
740 |
|
priv->balloon.rect.h = y1 - y0 - 2*BALLOON_BORDER; |
741 |
|
|
742 |
#ifdef USE_CAIRO |
#ifdef USE_CAIRO |
743 |
cairo_t *cr = gdk_cairo_create(priv->pixmap); |
cairo_t *cr = gdk_cairo_create(priv->pixmap); |
744 |
|
|
768 |
|
|
769 |
/* ---------- draw close button --------- */ |
/* ---------- draw close button --------- */ |
770 |
|
|
771 |
int cx = x1 - BALLOON_CORNER_RADIUS*3/4; |
int cx = x1 - BALLOON_BORDER - CLOSE_BUTTON_RADIUS; |
772 |
int cy = y0 + BALLOON_CORNER_RADIUS*3/4; |
int cy = y0 + BALLOON_BORDER + CLOSE_BUTTON_RADIUS; |
773 |
int crad = BALLOON_CORNER_RADIUS/3; |
int crad = CLOSE_BUTTON_RADIUS; |
774 |
|
|
775 |
cairo_arc (cr, cx, cy, crad, 0, 2 * M_PI); |
cairo_arc (cr, cx, cy, crad, 0, 2 * M_PI); |
776 |
cairo_set_source_rgba (cr, 0.8, 0, 0, 1.0); |
cairo_set_source_rgba (cr, 0.8, 0, 0, 1.0); |
777 |
cairo_fill_preserve (cr); |
cairo_fill_preserve (cr); |
778 |
cairo_set_source_rgba (cr, 0.3, 0, 0, 1.0); |
cairo_set_source_rgba (cr, 0.3, 0, 0, 1.0); |
779 |
cairo_set_line_width (cr, 1); |
cairo_set_line_width (cr, 2); |
780 |
cairo_stroke(cr); |
cairo_stroke(cr); |
781 |
|
|
|
int cs = crad/2; |
|
782 |
cairo_set_source_rgba (cr, 1, 1, 1, 1.0); |
cairo_set_source_rgba (cr, 1, 1, 1, 1.0); |
783 |
cairo_set_line_width (cr, 3); |
cairo_set_line_width (cr, 3); |
784 |
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); |
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); |
785 |
cairo_move_to (cr, cx - cs, cy - cs); |
cairo_move_to (cr, cx - crad/2, cy - crad/2); |
786 |
cairo_line_to (cr, cx + cs, cy + cs); |
cairo_line_to (cr, cx + crad/2, cy + crad/2); |
787 |
cairo_stroke (cr); |
cairo_stroke (cr); |
788 |
cairo_move_to (cr, cx + cs, cy - cs); |
cairo_move_to (cr, cx + crad/2, cy - crad/2); |
789 |
cairo_line_to (cr, cx - cs, cy + cs); |
cairo_line_to (cr, cx - crad/2, cy + crad/2); |
790 |
cairo_stroke (cr); |
cairo_stroke (cr); |
791 |
|
|
792 |
|
if (priv->balloon.cb) { |
793 |
|
/* clip in case application tries to draw in */ |
794 |
|
/* exceed of the balloon */ |
795 |
|
cairo_rectangle (cr, priv->balloon.rect.x, priv->balloon.rect.y, |
796 |
|
priv->balloon.rect.w, priv->balloon.rect.h); |
797 |
|
cairo_clip (cr); |
798 |
|
cairo_new_path (cr); /* current path is not |
799 |
|
consumed by cairo_clip() */ |
800 |
|
|
801 |
|
priv->balloon.cb(cr, &priv->balloon.rect, priv->balloon.data); |
802 |
|
} |
803 |
|
|
804 |
gtk_widget_queue_draw_area (GTK_WIDGET(map), |
gtk_widget_queue_draw_area (GTK_WIDGET(map), |
805 |
x0, y0, BALLOON_WIDTH, |
x0, y0, BALLOON_WIDTH, |
810 |
} |
} |
811 |
} |
} |
812 |
|
|
813 |
|
/* the user clicked into the balloons main area. handle this */ |
814 |
|
static void |
815 |
|
osm_gps_map_handle_balloon_click(OsmGpsMap *map, gint x, gint y) |
816 |
|
{ |
817 |
|
OsmGpsMapPrivate *priv = map->priv; |
818 |
|
|
819 |
|
printf("clocked at %d %d\n", x, y); |
820 |
|
|
821 |
|
if (!priv->balloon.valid) |
822 |
|
return; |
823 |
|
|
824 |
|
/* check if the close button was clicked */ |
825 |
|
if ((x > priv->balloon.rect.w - 2*CLOSE_BUTTON_RADIUS) && |
826 |
|
(x < priv->balloon.rect.w) && |
827 |
|
(y > 0) && (y < 2*CLOSE_BUTTON_RADIUS)) { |
828 |
|
|
829 |
|
priv->balloon.valid = FALSE; |
830 |
|
osm_gps_map_map_redraw_idle(map); |
831 |
|
} |
832 |
|
} |
833 |
|
|
834 |
|
/* return true if balloon is being displayed and if */ |
835 |
|
/* the given coordinate is within this balloon */ |
836 |
|
static gboolean |
837 |
|
osm_gps_map_in_balloon(OsmGpsMapPrivate *priv, gint x, gint y) |
838 |
|
{ |
839 |
|
return (priv->balloon.valid && |
840 |
|
(x > priv->balloon.rect.x) && |
841 |
|
(x < priv->balloon.rect.x + priv->balloon.rect.w) && |
842 |
|
(y > priv->balloon.rect.y) && |
843 |
|
(y < priv->balloon.rect.y + priv->balloon.rect.h)); |
844 |
|
} |
845 |
|
|
846 |
static void |
static void |
847 |
osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y) |
osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y) |
848 |
{ |
{ |
1459 |
priv->gps = g_new0(coord_t, 1); |
priv->gps = g_new0(coord_t, 1); |
1460 |
priv->gps_valid = FALSE; |
priv->gps_valid = FALSE; |
1461 |
|
|
1462 |
priv->balloon = g_new0(coord_t, 1); |
priv->balloon.coo = g_new0(coord_t, 1); |
1463 |
priv->balloon_valid = FALSE; |
priv->balloon.valid = FALSE; |
1464 |
|
priv->balloon.cb = NULL; |
1465 |
|
|
1466 |
priv->tracks = NULL; |
priv->tracks = NULL; |
1467 |
priv->images = NULL; |
priv->images = NULL; |
1621 |
g_source_remove (priv->idle_map_redraw); |
g_source_remove (priv->idle_map_redraw); |
1622 |
|
|
1623 |
g_free(priv->gps); |
g_free(priv->gps); |
1624 |
g_free(priv->balloon); |
g_free(priv->balloon.coo); |
1625 |
|
|
1626 |
G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object); |
G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object); |
1627 |
} |
} |
1838 |
{ |
{ |
1839 |
OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); |
OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); |
1840 |
|
|
1841 |
|
/* don't drag if the user clicked within the balloon */ |
1842 |
|
if (osm_gps_map_in_balloon(priv, |
1843 |
|
event->x + EXTRA_BORDER, |
1844 |
|
event->y + EXTRA_BORDER)) |
1845 |
|
{ |
1846 |
|
priv->drag_counter = -1; |
1847 |
|
return FALSE; |
1848 |
|
} |
1849 |
|
|
1850 |
priv->drag_counter = 0; |
priv->drag_counter = 0; |
1851 |
priv->drag_start_mouse_x = (int) event->x; |
priv->drag_start_mouse_x = (int) event->x; |
1852 |
priv->drag_start_mouse_y = (int) event->y; |
priv->drag_start_mouse_y = (int) event->y; |
1861 |
{ |
{ |
1862 |
OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); |
OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); |
1863 |
|
|
1864 |
|
/* released inside the balloon? */ |
1865 |
|
if (osm_gps_map_in_balloon(priv, |
1866 |
|
event->x + EXTRA_BORDER, |
1867 |
|
event->y + EXTRA_BORDER)) |
1868 |
|
{ |
1869 |
|
osm_gps_map_handle_balloon_click(OSM_GPS_MAP(widget), |
1870 |
|
event->x - priv->balloon.rect.x + EXTRA_BORDER, |
1871 |
|
event->y - priv->balloon.rect.y + EXTRA_BORDER); |
1872 |
|
return FALSE; |
1873 |
|
} |
1874 |
|
|
1875 |
|
if (priv->drag_counter < 0) |
1876 |
|
return FALSE; |
1877 |
|
|
1878 |
if (priv->dragging) |
if (priv->dragging) |
1879 |
{ |
{ |
1880 |
priv->dragging = FALSE; |
priv->dragging = FALSE; |
1892 |
|
|
1893 |
priv->drag_mouse_dx = 0; |
priv->drag_mouse_dx = 0; |
1894 |
priv->drag_mouse_dy = 0; |
priv->drag_mouse_dy = 0; |
1895 |
priv->drag_counter = 0; |
priv->drag_counter = -1; |
1896 |
|
|
1897 |
return FALSE; |
return FALSE; |
1898 |
} |
} |
1917 |
if (!(state & GDK_BUTTON1_MASK)) |
if (!(state & GDK_BUTTON1_MASK)) |
1918 |
return FALSE; |
return FALSE; |
1919 |
|
|
1920 |
|
if (priv->drag_counter < 0) |
1921 |
|
return FALSE; |
1922 |
|
|
1923 |
priv->drag_counter++; |
priv->drag_counter++; |
1924 |
|
|
1925 |
// we havent dragged more than 6 pixels |
// we havent dragged more than 6 pixels |
2022 |
widget->window, |
widget->window, |
2023 |
widget->style->fg_gc[GTK_WIDGET_STATE (widget)], |
widget->style->fg_gc[GTK_WIDGET_STATE (widget)], |
2024 |
priv->pixmap, |
priv->pixmap, |
2025 |
event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER, |
event->area.x + EXTRA_BORDER, |
2026 |
|
event->area.y + EXTRA_BORDER, |
2027 |
event->area.x, event->area.y, |
event->area.x, event->area.y, |
2028 |
event->area.width, event->area.height); |
event->area.width, event->area.height); |
2029 |
|
|
2799 |
} |
} |
2800 |
|
|
2801 |
void |
void |
2802 |
osm_gps_map_draw_balloon (OsmGpsMap *map, float latitude, float longitude) |
osm_gps_map_draw_balloon (OsmGpsMap *map, float latitude, float longitude, |
2803 |
|
OsmGpsMapBalloonCallback cb, gpointer data) |
2804 |
{ |
{ |
2805 |
OsmGpsMapPrivate *priv; |
OsmGpsMapPrivate *priv; |
2806 |
|
|
2810 |
g_return_if_fail (OSM_IS_GPS_MAP (map)); |
g_return_if_fail (OSM_IS_GPS_MAP (map)); |
2811 |
priv = map->priv; |
priv = map->priv; |
2812 |
|
|
2813 |
priv->balloon->rlat = deg2rad(latitude); |
priv->balloon.coo->rlat = deg2rad(latitude); |
2814 |
priv->balloon->rlon = deg2rad(longitude); |
priv->balloon.coo->rlon = deg2rad(longitude); |
2815 |
priv->balloon_valid = TRUE; |
priv->balloon.valid = TRUE; |
2816 |
|
|
2817 |
|
priv->balloon.cb = cb; |
2818 |
|
priv->balloon.data = data; |
2819 |
|
|
2820 |
// this redraws the map |
// this redraws the map |
2821 |
osm_gps_map_map_redraw_idle(map); |
osm_gps_map_map_redraw_idle(map); |
2829 |
g_return_if_fail (OSM_IS_GPS_MAP (map)); |
g_return_if_fail (OSM_IS_GPS_MAP (map)); |
2830 |
priv = map->priv; |
priv = map->priv; |
2831 |
|
|
2832 |
priv->balloon_valid = FALSE; |
priv->balloon.valid = FALSE; |
2833 |
|
|
2834 |
osm_gps_map_map_redraw_idle(map); |
osm_gps_map_map_redraw_idle(map); |
2835 |
} |
} |