From f1d0cd196826a3eb23bfc91eff1a9f9c4db8b8a6 Mon Sep 17 00:00:00 2001 From: Pierre-Luc Beaudoin Date: Wed, 3 Jun 2009 17:01:07 -0400 Subject: [PATCH] Introduce the API for route drawing --- champlain/Makefile.am | 12 ++- champlain/champlain-defines.h | 6 ++ champlain/champlain-line.c | 156 ++++++++++++++++++++++++++++++++++ champlain/champlain-line.h | 72 ++++++++++++++++ champlain/champlain-private.h | 2 +- champlain/champlain-view.c | 48 ++++++++++- champlain/champlain-view.h | 6 +- demos/Makefile.am | 5 +- demos/lines.c | 126 +++++++++++++++++++++++++++ 9 files changed, 423 insertions(+), 10 deletions(-) create mode 100644 champlain/champlain-line.c create mode 100644 champlain/champlain-line.h create mode 100644 demos/lines.c diff --git a/champlain/Makefile.am b/champlain/Makefile.am index 9898dde..67cdcee 100644 --- a/champlain/Makefile.am +++ b/champlain/Makefile.am @@ -28,6 +28,7 @@ libchamplain_headers = \ champlain-network-map-source.h \ champlain-map-source-factory.h \ champlain-map-source-desc.h \ + champlain-line.h \ champlain-version.h @@ -45,7 +46,8 @@ libchamplain_0_3_la_SOURCES = \ champlain-map-source.c \ champlain-network-map-source.c \ champlain-map-source-factory.c \ - champlain-cache.c + champlain-cache.c \ + champlain-line.c noinst_HEADERS = \ champlain-debug.h \ @@ -62,7 +64,9 @@ noinst_HEADERS = \ champlain-map-source-factory.h \ champlain-map-source-desc.h \ champlain-version.h \ - champlain-cache.h + champlain-cache.h \ + champlain-line.h \ + champlain-version.h libchamplain_include_HEADERS = \ champlain.h \ @@ -79,7 +83,9 @@ libchamplain_include_HEADERS = \ champlain-base-marker.h \ champlain-marker.h \ champlain-version.h \ - champlain-cache.h + champlain-cache.h \ + champlain-line.h \ + champlain-version.h libchamplain_0_3_la_LIBADD = $(DEPS_LIBS) $(SOUP_LIBS) ../tidy/libtidy-1.0.la diff --git a/champlain/champlain-defines.h b/champlain/champlain-defines.h index 54056b7..1f98d31 100644 --- a/champlain/champlain-defines.h +++ b/champlain/champlain-defines.h @@ -47,4 +47,10 @@ typedef enum CHAMPLAIN_STATE_DONE } ChamplainState; +typedef struct +{ + double lat; + double lon; +} ChamplainPoint; + #endif diff --git a/champlain/champlain-line.c b/champlain/champlain-line.c new file mode 100644 index 0000000..2eeb5cb --- /dev/null +++ b/champlain/champlain-line.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2009 Pierre-Luc Beaudoin + * + * 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 + */ + +/** + * SECTION:champlain-line + * @short_description: A container for #ChamplainMarker + * + * A ChamplainLine is little more than a #ClutterContainer. It keeps the + * markers ordered so that they display correctly. + * + * Use #clutter_container_add to add markers to the line and + * #clutter_container_remove to remove them. + */ + +#include "config.h" + +#include "champlain-line.h" + +#include "champlain-defines.h" + +#include +#include + +G_DEFINE_TYPE (ChamplainLine, champlain_line, G_TYPE_OBJECT) + +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHAMPLAIN_TYPE_LINE, ChamplainLinePrivate)) + +enum +{ + PROP_0 +}; + +struct _ChamplainLinePrivate { + GList *points; +}; + +static void +champlain_line_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + //ChamplainLine *self = CHAMPLAIN_LINE (object); + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +champlain_line_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + //ChamplainLine *self = CHAMPLAIN_LINE (object); + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +champlain_line_dispose (GObject *object) +{ + //ChamplainLinePrivate *priv = GET_PRIVATE (object); + + G_OBJECT_CLASS (champlain_line_parent_class)->dispose (object); +} + +static void +champlain_line_finalize (GObject *object) +{ + G_OBJECT_CLASS (champlain_line_parent_class)->finalize (object); +} + +static void +champlain_line_class_init (ChamplainLineClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (ChamplainLinePrivate)); + + object_class->get_property = champlain_line_get_property; + object_class->set_property = champlain_line_set_property; + object_class->dispose = champlain_line_dispose; + object_class->finalize = champlain_line_finalize; +} + +static void +champlain_line_init (ChamplainLine *self) +{ + self->priv = GET_PRIVATE (self); + + self->priv->points = NULL; +} + +/** + * champlain_line_new: + * + * Returns a new #ChamplainLine ready to be to draw lines on the map + * + * Since: 0.4 + */ +ChamplainLine * +champlain_line_new () +{ + return g_object_new (CHAMPLAIN_TYPE_LINE, NULL); +} + +void +champlain_line_add_point (ChamplainLine *self, + gdouble lat, + gdouble lon) +{ + g_return_if_fail (CHAMPLAIN_IS_LINE (self)); + + ChamplainPoint *point = g_new0 (ChamplainPoint, 1); + point->lat = lat; + point->lon = lon; + + self->priv->points = g_list_append (self->priv->points, point); +} + +void +champlain_line_clear_points (ChamplainLine *self) +{ + g_return_if_fail (CHAMPLAIN_IS_LINE (self)); + + GList *next = self->priv->points; + while (next != NULL) + { + g_free (next->data); + next = g_list_next (next); + } + g_list_free (self->priv->points); +} + diff --git a/champlain/champlain-line.h b/champlain/champlain-line.h new file mode 100644 index 0000000..a2879ea --- /dev/null +++ b/champlain/champlain-line.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 Pierre-Luc Beaudoin + * + * 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 + */ + +#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef CHAMPLAIN_LINE_H +#define CHAMPLAIN_LINE_H + +#include + +#include + +G_BEGIN_DECLS + +#define CHAMPLAIN_TYPE_LINE champlain_line_get_type() + +#define CHAMPLAIN_LINE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_LINE, ChamplainLine)) + +#define CHAMPLAIN_LINE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_LINE, ChamplainLineClass)) + +#define CHAMPLAIN_IS_LINE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_LINE)) + +#define CHAMPLAIN_IS_LINE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_LINE)) + +#define CHAMPLAIN_LINE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_LINE, ChamplainLineClass)) + +typedef struct _ChamplainLinePrivate ChamplainLinePrivate; + +typedef struct { + GObject parent; + ChamplainLinePrivate *priv; +} ChamplainLine; + +typedef struct { + GObjectClass parent_class; +} ChamplainLineClass; + +GType champlain_line_get_type (void); + +ChamplainLine* champlain_line_new (void); + +void champlain_line_add_point (ChamplainLine *line, + gdouble lat, + gdouble lon); + +void champlain_line_clear_points (ChamplainLine *line); + +G_END_DECLS + +#endif diff --git a/champlain/champlain-private.h b/champlain/champlain-private.h index 9af67e0..d27e705 100644 --- a/champlain/champlain-private.h +++ b/champlain/champlain-private.h @@ -29,7 +29,7 @@ typedef struct gint x; gint y; gint z; -} ChamplainPoint; +} ChamplainIntPoint; struct _ChamplainBaseMarkerPrivate { diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c index c601333..1406a1d 100644 --- a/champlain/champlain-view.c +++ b/champlain/champlain-view.c @@ -64,6 +64,7 @@ #include "champlain-zoom-level.h" #include +#include #include #include #include @@ -129,7 +130,7 @@ struct _ChamplainViewPrivate gdouble latitude; /* Hack to get smaller x,y coordinates as the clutter limit is G_MAXINT16 */ - ChamplainPoint anchor; + ChamplainIntPoint anchor; gdouble anchor_zoom_level; /* the zoom_level for which the current anchor has been computed for */ @@ -141,6 +142,7 @@ struct _ChamplainViewPrivate ChamplainRectangle viewport_size; ClutterActor *user_layers; /* Contains the markers */ + ClutterActor *line_layer; /* Contains the lines */ gboolean keep_center_on_resize; @@ -153,6 +155,8 @@ struct _ChamplainViewPrivate /* champlain_view_go_to's context, kept for stop_go_to */ GoToContext *goto_context; + + ChamplainLine *line; }; G_DEFINE_TYPE (ChamplainView, champlain_view, CLUTTER_TYPE_GROUP); @@ -199,6 +203,7 @@ static gboolean view_set_zoom_level_at (ChamplainView *view, static void tile_state_notify (GObject *gobject, GParamSpec *pspec, gpointer data); +static void view_update_lines (ChamplainView *view); static gdouble viewport_get_longitude_at (ChamplainViewPrivate *priv, gint x) @@ -850,6 +855,14 @@ champlain_view_init (ChamplainView *view) priv->user_layers); clutter_actor_raise (priv->user_layers, priv->map_layer); + /* Setup user_layers */ + priv->line_layer = g_object_ref (clutter_cairo_new (800, 600)); + clutter_actor_show (priv->line_layer); + clutter_container_add_actor (CLUTTER_CONTAINER (priv->viewport), + priv->line_layer); + clutter_actor_raise (priv->line_layer, priv->map_layer); + clutter_actor_set_position (priv->line_layer, 0, 0); + champlain_view_set_size (view, priv->viewport_size.width, priv->viewport_size.height); @@ -866,8 +879,8 @@ viewport_x_changed_cb (GObject *gobject, { ChamplainViewPrivate *priv = view->priv; - ChamplainPoint rect; - ChamplainPoint old_anchor; + ChamplainIntPoint rect; + ChamplainIntPoint old_anchor; tidy_viewport_get_origin (TIDY_VIEWPORT (priv->viewport), &rect.x, &rect.y, NULL); @@ -885,7 +898,7 @@ viewport_x_changed_cb (GObject *gobject, if (priv->anchor.x - old_anchor.x != 0) { - ChamplainPoint diff; + ChamplainIntPoint diff; diff.x = priv->anchor.x - old_anchor.x; diff.y = priv->anchor.y - old_anchor.y; @@ -902,6 +915,7 @@ viewport_x_changed_cb (GObject *gobject, view_load_visible_tiles (view); view_tiles_reposition (view); marker_reposition (view); + view_update_lines (view); priv->longitude = viewport_get_current_longitude (priv); priv->latitude = viewport_get_current_latitude (priv); @@ -2158,3 +2172,29 @@ champlain_view_get_zoom_on_double_click (ChamplainView *view) return priv->zoom_on_double_click; } +void +champlain_view_add_line (ChamplainView *view, + ChamplainLine *line) +{ + g_return_if_fail (CHAMPLAIN_IS_VIEW (view)); + g_return_if_fail (CHAMPLAIN_IS_LINE (line)); + + view->priv->line = g_object_ref (line); +} + +static void +view_update_lines (ChamplainView *view) +{ + cairo_t *cr; + cr = clutter_cairo_create (CLUTTER_CAIRO (view->priv->line_layer)); + + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, 100, 0); + cairo_line_to (cr, 100, 200); + cairo_line_to (cr, 100, 100); + cairo_line_to (cr, 0, 100); + + cairo_stroke (cr); + cairo_destroy (cr); + +} diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h index c998b60..1645cdc 100644 --- a/champlain/champlain-view.h +++ b/champlain/champlain-view.h @@ -24,8 +24,9 @@ #define CHAMPLAIN_VIEW_H #include -#include #include +#include +#include #include #include @@ -139,6 +140,9 @@ gboolean champlain_view_get_keep_center_on_resize (ChamplainView *view); gboolean champlain_view_get_show_license (ChamplainView *view); gboolean champlain_view_get_zoom_on_double_click (ChamplainView *view); +void champlain_view_add_line (ChamplainView *view, + ChamplainLine *line); + G_END_DECLS #endif diff --git a/demos/Makefile.am b/demos/Makefile.am index 51263c1..5d9e6b4 100644 --- a/demos/Makefile.am +++ b/demos/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = launcher animated-marker +noinst_PROGRAMS = launcher animated-marker lines INCLUDES = -I$(top_srcdir) @@ -11,6 +11,9 @@ launcher_LDADD = $(DEPS_LIBS) ../champlain/libchamplain-0.3.la animated_marker_SOURCES = animated-marker.c animated_marker_LDADD = $(DEPS_LIBS) ../champlain/libchamplain-0.3.la +lines_SOURCES = lines.c +lines_LDADD = $(DEPS_LIBS) ../champlain/libchamplain-0.3.la + if ENABLE_GTK noinst_PROGRAMS += launcher-gtk launcher_gtk_SOURCES = launcher-gtk.c markers.c diff --git a/demos/lines.c b/demos/lines.c new file mode 100644 index 0000000..f47b66b --- /dev/null +++ b/demos/lines.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2008 Pierre-Luc Beaudoin + * + * 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 + +#define PADDING 10 + +static gboolean +zoom_in (ClutterActor *actor, + ClutterButtonEvent *event, + ChamplainView * view) +{ + champlain_view_zoom_in (view); + return TRUE; +} + +static gboolean +zoom_out (ClutterActor *actor, + ClutterButtonEvent *event, + ChamplainView * view) +{ + champlain_view_zoom_out (view); + return TRUE; +} + +static ClutterActor * +make_button (char *text) +{ + ClutterActor *button, *button_bg, *button_text; + ClutterColor white = { 0xff, 0xff, 0xff, 0xff }; + ClutterColor black = { 0x00, 0x00, 0x00, 0xff }; + guint width, height; + + button = clutter_group_new (); + + button_bg = clutter_rectangle_new_with_color (&white); + clutter_container_add_actor (CLUTTER_CONTAINER (button), button_bg); + clutter_actor_set_opacity (button_bg, 0xcc); + + button_text = clutter_label_new_full ("Sans 10", text, &black); + clutter_container_add_actor (CLUTTER_CONTAINER (button), button_text); + clutter_actor_get_size (button_text, &width, &height); + + clutter_actor_set_size (button_bg, width + PADDING * 2, height + PADDING * 2); + clutter_actor_set_position (button_bg, 0, 0); + clutter_actor_set_position (button_text, PADDING, PADDING); + + return button; +} + +int +main (int argc, + char *argv[]) +{ + ClutterActor* actor, *stage, *buttons, *button; + ChamplainLine *line; + guint width, total_width = 0;; + + g_thread_init (NULL); + clutter_init (&argc, &argv); + + stage = clutter_stage_get_default (); + clutter_actor_set_size (stage, 800, 600); + + /* Create the map view */ + actor = champlain_view_new (); + champlain_view_set_size (CHAMPLAIN_VIEW (actor), 800, 600); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); + + /* Create the buttons */ + buttons = clutter_group_new (); + clutter_actor_set_position (buttons, PADDING, PADDING); + + button = make_button ("Zoom in"); + clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); + clutter_actor_set_reactive (button, TRUE); + clutter_actor_get_size (button, &width, NULL); + total_width += width + PADDING; + g_signal_connect (button, "button-release-event", + G_CALLBACK (zoom_in), + actor); + + button = make_button ("Zoom out"); + clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); + clutter_actor_set_reactive (button, TRUE); + clutter_actor_set_position (button, total_width, 0); + clutter_actor_get_size (button, &width, NULL); + total_width += width + PADDING; + g_signal_connect (button, "button-release-event", + G_CALLBACK (zoom_out), + actor); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), buttons); + + /* draw a line */ + line = champlain_line_new (); + champlain_line_add_point (line, -40, -70); + champlain_line_add_point (line, -45, -75); + champlain_view_add_line (CHAMPLAIN_VIEW (actor), line); + + + /* Finish initialising the map view */ + g_object_set (G_OBJECT (actor), "zoom-level", 12, + "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC, NULL); + champlain_view_center_on(CHAMPLAIN_VIEW(actor), 45.466, -73.75); + + clutter_actor_show (stage); + clutter_main (); + + return 0; +} -- 2.39.5