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
}