| 1 |
/* |
| 2 |
* Copyright (C) 2008 Pierre-Luc Beaudoin <pierre-luc@pierlux.com> |
| 3 |
* |
| 4 |
* This library is free software; you can redistribute it and/or |
| 5 |
* modify it under the terms of the GNU Lesser General Public |
| 6 |
* License as published by the Free Software Foundation; either |
| 7 |
* version 2.1 of the License, or (at your option) any later version. |
| 8 |
* |
| 9 |
* This library is distributed in the hope that it will be useful, |
| 10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 |
* Lesser General Public License for more details. |
| 13 |
* |
| 14 |
* You should have received a copy of the GNU Lesser General Public |
| 15 |
* License along with this library; if not, write to the Free Software |
| 16 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 |
*/ |
| 18 |
|
| 19 |
#include <champlain/champlain.h> |
| 20 |
#include <math.h> |
| 21 |
|
| 22 |
#define MARKER_SIZE 10 |
| 23 |
|
| 24 |
/* The marker is drawn with cairo. It is composed of 1 static filled circle |
| 25 |
* and 1 stroked circle animated as an echo. |
| 26 |
*/ |
| 27 |
static ClutterActor * |
| 28 |
create_marker () |
| 29 |
{ |
| 30 |
ClutterActor *marker; |
| 31 |
ClutterActor *bg; |
| 32 |
ClutterTimeline *timeline; |
| 33 |
cairo_t *cr; |
| 34 |
|
| 35 |
/* Create the marker */ |
| 36 |
marker = champlain_custom_marker_new (); |
| 37 |
|
| 38 |
/* Static filled circle ----------------------------------------------- */ |
| 39 |
bg = clutter_cairo_texture_new (MARKER_SIZE, MARKER_SIZE); |
| 40 |
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg)); |
| 41 |
|
| 42 |
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); |
| 43 |
cairo_paint(cr); |
| 44 |
cairo_set_operator (cr, CAIRO_OPERATOR_OVER); |
| 45 |
|
| 46 |
/* Draw the circle */ |
| 47 |
cairo_set_source_rgb (cr, 0, 0, 0); |
| 48 |
cairo_arc (cr, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, 0, 2 * M_PI); |
| 49 |
cairo_close_path (cr); |
| 50 |
|
| 51 |
/* Fill the circle */ |
| 52 |
cairo_set_source_rgba (cr, 0.1, 0.1, 0.9, 1.0); |
| 53 |
cairo_fill (cr); |
| 54 |
|
| 55 |
cairo_destroy (cr); |
| 56 |
|
| 57 |
/* Add the circle to the marker */ |
| 58 |
clutter_container_add_actor (CLUTTER_CONTAINER (marker), bg); |
| 59 |
clutter_actor_set_anchor_point_from_gravity (bg, CLUTTER_GRAVITY_CENTER); |
| 60 |
clutter_actor_set_position (bg, 0, 0); |
| 61 |
|
| 62 |
/* Echo circle -------------------------------------------------------- */ |
| 63 |
bg = clutter_cairo_texture_new (2 * MARKER_SIZE, 2 * MARKER_SIZE); |
| 64 |
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg)); |
| 65 |
|
| 66 |
/* Draw the circle */ |
| 67 |
cairo_set_source_rgb (cr, 0, 0, 0); |
| 68 |
cairo_arc (cr, MARKER_SIZE, MARKER_SIZE, 0.9 * MARKER_SIZE, 0, 2 * M_PI); |
| 69 |
cairo_close_path (cr); |
| 70 |
|
| 71 |
/* Stroke the circle */ |
| 72 |
cairo_set_line_width (cr, 2.0); |
| 73 |
cairo_set_source_rgba (cr, 0.1, 0.1, 0.7, 1.0); |
| 74 |
cairo_stroke (cr); |
| 75 |
|
| 76 |
cairo_destroy (cr); |
| 77 |
|
| 78 |
/* Add the circle to the marker */ |
| 79 |
clutter_container_add_actor (CLUTTER_CONTAINER (marker), bg); |
| 80 |
clutter_actor_lower_bottom (bg); /* Ensure it is under the previous circle */ |
| 81 |
clutter_actor_set_position (bg, 0, 0); |
| 82 |
clutter_actor_set_anchor_point_from_gravity (bg, CLUTTER_GRAVITY_CENTER); |
| 83 |
|
| 84 |
/* Animate the echo circle */ |
| 85 |
timeline = clutter_timeline_new (1000); |
| 86 |
clutter_timeline_set_loop (timeline, TRUE); |
| 87 |
clutter_actor_set_opacity (CLUTTER_ACTOR (bg), 255); |
| 88 |
clutter_actor_set_scale (CLUTTER_ACTOR (bg), 0.5, 0.5); |
| 89 |
clutter_actor_animate_with_timeline (CLUTTER_ACTOR (bg), |
| 90 |
CLUTTER_EASE_OUT_SINE, |
| 91 |
timeline, |
| 92 |
"opacity", 0, |
| 93 |
"scale-x", 2.0, |
| 94 |
"scale-y", 2.0, |
| 95 |
NULL); |
| 96 |
|
| 97 |
clutter_timeline_start (timeline); |
| 98 |
|
| 99 |
return marker; |
| 100 |
} |
| 101 |
|
| 102 |
|
| 103 |
double lat = 45.466; |
| 104 |
double lon = -73.75; |
| 105 |
|
| 106 |
typedef struct |
| 107 |
{ |
| 108 |
ChamplainView *view; |
| 109 |
ChamplainMarker *marker; |
| 110 |
} GpsCallbackData; |
| 111 |
|
| 112 |
static gboolean |
| 113 |
gps_callback (GpsCallbackData *data) |
| 114 |
{ |
| 115 |
lat += 0.005; |
| 116 |
lon += 0.005; |
| 117 |
champlain_view_center_on (data->view, lat, lon); |
| 118 |
champlain_location_set_location (CHAMPLAIN_LOCATION (data->marker), lat, lon); |
| 119 |
return TRUE; |
| 120 |
} |
| 121 |
|
| 122 |
|
| 123 |
int |
| 124 |
main (int argc, char *argv[]) |
| 125 |
{ |
| 126 |
ClutterActor *actor, *marker, *stage; |
| 127 |
ChamplainMarkerLayer *layer; |
| 128 |
GpsCallbackData callback_data; |
| 129 |
|
| 130 |
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) |
| 131 |
return 1; |
| 132 |
|
| 133 |
stage = clutter_stage_new (); |
| 134 |
clutter_actor_set_size (stage, 800, 600); |
| 135 |
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); |
| 136 |
|
| 137 |
/* Create the map view */ |
| 138 |
actor = champlain_view_new (); |
| 139 |
clutter_actor_set_size (CLUTTER_ACTOR (actor), 800, 600); |
| 140 |
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); |
| 141 |
|
| 142 |
/* Create the marker layer */ |
| 143 |
layer = champlain_marker_layer_new_full (CHAMPLAIN_SELECTION_SINGLE); |
| 144 |
clutter_actor_show (CLUTTER_ACTOR (layer)); |
| 145 |
champlain_view_add_layer (CHAMPLAIN_VIEW (actor), CHAMPLAIN_LAYER (layer)); |
| 146 |
|
| 147 |
/* Create a marker */ |
| 148 |
marker = create_marker (); |
| 149 |
champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER (marker)); |
| 150 |
|
| 151 |
/* Finish initialising the map view */ |
| 152 |
g_object_set (G_OBJECT (actor), "zoom-level", 12, |
| 153 |
"kinetic-mode", TRUE, NULL); |
| 154 |
champlain_view_center_on (CHAMPLAIN_VIEW (actor), lat, lon); |
| 155 |
|
| 156 |
/* Create callback that updates the map periodically */ |
| 157 |
callback_data.view = CHAMPLAIN_VIEW (actor); |
| 158 |
callback_data.marker = CHAMPLAIN_MARKER (marker); |
| 159 |
|
| 160 |
g_timeout_add (1000, (GSourceFunc) gps_callback, &callback_data); |
| 161 |
|
| 162 |
clutter_actor_show (stage); |
| 163 |
clutter_main (); |
| 164 |
|
| 165 |
return 0; |
| 166 |
} |