/*
* Copyright (C) 2008 Pierre-Luc Beaudoin <pierre-luc@pierlux.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <champlain/champlain.h>
#include <math.h>
#define MARKER_SIZE 10
static gboolean
draw_center (ClutterCanvas *canvas,
cairo_t *cr,
int width,
int height)
{
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
/* Draw the circle */
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_arc (cr, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, 0, 2 * M_PI);
cairo_close_path (cr);
/* Fill the circle */
cairo_set_source_rgba (cr, 0.1, 0.1, 0.9, 1.0);
cairo_fill (cr);
return TRUE;
}
static gboolean
draw_circle (ClutterCanvas *canvas,
cairo_t *cr,
int width,
int height)
{
/* Draw the circle */
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_arc (cr, MARKER_SIZE, MARKER_SIZE, 0.9 * MARKER_SIZE, 0, 2 * M_PI);
cairo_close_path (cr);
/* Stroke the circle */
cairo_set_line_width (cr, 2.0);
cairo_set_source_rgba (cr, 0.1, 0.1, 0.7, 1.0);
cairo_stroke (cr);
return TRUE;
}
/* The marker is drawn with cairo. It is composed of 1 static filled circle
* and 1 stroked circle animated as an echo.
*/
static ClutterActor *
create_marker ()
{
ClutterActor *marker;
ClutterActor *bg;
ClutterContent *canvas;
ClutterTransition *transition;
/* Create the marker */
marker = champlain_custom_marker_new ();
/* Static filled circle ----------------------------------------------- */
canvas = clutter_canvas_new ();
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), MARKER_SIZE, MARKER_SIZE);
g_signal_connect (canvas, "draw", G_CALLBACK (draw_center), NULL);
bg = clutter_actor_new ();
clutter_actor_set_size (bg, MARKER_SIZE, MARKER_SIZE);
clutter_actor_set_content (bg, canvas);
clutter_content_invalidate (canvas);
g_object_unref (canvas);
/* Add the circle to the marker */
clutter_actor_add_child (marker, bg);
clutter_actor_set_position (bg, -0.5 * MARKER_SIZE, -0.5 * MARKER_SIZE);
/* Echo circle -------------------------------------------------------- */
canvas = clutter_canvas_new ();
clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 2 * MARKER_SIZE, 2 * MARKER_SIZE);
g_signal_connect (canvas, "draw", G_CALLBACK (draw_circle), NULL);
bg = clutter_actor_new ();
clutter_actor_set_size (bg, 2 * MARKER_SIZE, 2 * MARKER_SIZE);
clutter_actor_set_content (bg, canvas);
clutter_content_invalidate (canvas);
g_object_unref (canvas);
/* Add the circle to the marker */
clutter_actor_add_child (marker, bg);
clutter_actor_set_pivot_point (bg, 0.5, 0.5);
clutter_actor_set_position (bg, -MARKER_SIZE, -MARKER_SIZE);
transition = clutter_property_transition_new ("opacity");
clutter_actor_set_easing_mode (bg, CLUTTER_EASE_OUT_SINE);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 1000);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_transition_set_from (transition, G_TYPE_UINT, 255);
clutter_transition_set_to (transition, G_TYPE_UINT, 0);
clutter_actor_add_transition (bg, "animate-opacity", transition);
transition = clutter_property_transition_new ("scale-x");
clutter_actor_set_easing_mode (bg, CLUTTER_EASE_OUT_SINE);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 1000);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_transition_set_from (transition, G_TYPE_FLOAT, 0.5);
clutter_transition_set_to (transition, G_TYPE_FLOAT, 2.0);
clutter_actor_add_transition (bg, "animate-scale-x", transition);
transition = clutter_property_transition_new ("scale-y");
clutter_actor_set_easing_mode (bg, CLUTTER_EASE_OUT_SINE);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 1000);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_transition_set_from (transition, G_TYPE_FLOAT, 0.5);
clutter_transition_set_to (transition, G_TYPE_FLOAT, 2.0);
clutter_actor_add_transition (bg, "animate-scale-y", transition);
return marker;
}
double lat = 45.466;
double lon = -73.75;
typedef struct
{
ChamplainView *view;
ChamplainMarker *marker;
} GpsCallbackData;
static gboolean
gps_callback (GpsCallbackData *data)
{
lat += 0.005;
lon += 0.005;
champlain_view_center_on (data->view, lat, lon);
champlain_location_set_location (CHAMPLAIN_LOCATION (data->marker), lat, lon);
return TRUE;
}
int
main (int argc, char *argv[])
{
ClutterActor *actor, *marker, *stage;
ChamplainMarkerLayer *layer;
GpsCallbackData callback_data;
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_actor_set_size (stage, 800, 600);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* Create the map view */
actor = champlain_view_new ();
clutter_actor_set_size (CLUTTER_ACTOR (actor), 800, 600);
clutter_actor_add_child (stage, actor);
/* Create the marker layer */
layer = champlain_marker_layer_new_full (CHAMPLAIN_SELECTION_SINGLE);
clutter_actor_show (CLUTTER_ACTOR (layer));
champlain_view_add_layer (CHAMPLAIN_VIEW (actor), CHAMPLAIN_LAYER (layer));
/* Create a marker */
marker = create_marker ();
champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER (marker));
/* Finish initialising the map view */
g_object_set (G_OBJECT (actor), "zoom-level", 12,
"kinetic-mode", TRUE, NULL);
champlain_view_center_on (CHAMPLAIN_VIEW (actor), lat, lon);
/* Create callback that updates the map periodically */
callback_data.view = CHAMPLAIN_VIEW (actor);
callback_data.marker = CHAMPLAIN_MARKER (marker);
g_timeout_add (1000, (GSourceFunc) gps_callback, &callback_data);
clutter_actor_show (stage);
clutter_main ();
return 0;
}