[libchamplain] Move license and scale actors out of the view



commit 0257079a681bb8903b1ae4b05f8f2e65c67fe477
Author: JiÅ?í Techet <techet gmail com>
Date:   Tue Feb 1 22:52:14 2011 +0100

    Move license and scale actors out of the view

 champlain/Makefile.am         |    4 +
 champlain/champlain-license.c |  290 ++++++++++++++++++
 champlain/champlain-license.h |   83 ++++++
 champlain/champlain-scale.c   |  480 ++++++++++++++++++++++++++++++
 champlain/champlain-scale.h   |   98 ++++++
 champlain/champlain-view.c    |  654 +++--------------------------------------
 champlain/champlain-view.h    |   33 +--
 champlain/champlain.h         |    1 +
 demos/launcher-gtk.c          |   18 +-
 9 files changed, 1011 insertions(+), 650 deletions(-)
---
diff --git a/champlain/Makefile.am b/champlain/Makefile.am
index c573d1e..0d4b72b 100644
--- a/champlain/Makefile.am
+++ b/champlain/Makefile.am
@@ -20,6 +20,8 @@ libchamplain_headers_public = 				\
 	$(srcdir)/champlain-marker-layer.h 			\
 	$(srcdir)/champlain-marker.h		\
 	$(srcdir)/champlain-label.h			\
+	$(srcdir)/champlain-scale.h			\
+	$(srcdir)/champlain-license.h			\
 	$(srcdir)/champlain-tile.h			\
 	$(srcdir)/champlain-map-source.h		\
 	$(srcdir)/champlain-map-source-chain.h		\
@@ -56,6 +58,8 @@ libchamplain_sources =					\
 	$(srcdir)/champlain-marker-layer.c 			\
 	$(srcdir)/champlain-marker.c 		\
 	$(srcdir)/champlain-label.c 			\
+	$(srcdir)/champlain-scale.c			\
+	$(srcdir)/champlain-license.c			\
 	$(srcdir)/champlain-tile.c			\
 	$(srcdir)/champlain-map-source.c		\
 	$(srcdir)/champlain-map-source-chain.c		\
diff --git a/champlain/champlain-license.c b/champlain/champlain-license.c
new file mode 100644
index 0000000..0d33826
--- /dev/null
+++ b/champlain/champlain-license.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2011 Jiri Techet <techet gmail 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 "config.h"
+
+#include "champlain-license.h"
+#include "champlain-defines.h"
+#include "champlain-marshal.h"
+#include "champlain-private.h"
+#include "champlain-enum-types.h"
+#include "champlain-view.h"
+
+#include <clutter/clutter.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <cairo.h>
+#include <math.h>
+#include <string.h>
+
+
+enum
+{
+  /* normal signals */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_LICENSE_EXTRA,
+};
+
+/* static guint champlain_license_signals[LAST_SIGNAL] = { 0, }; */
+
+struct _ChamplainLicensePrivate
+{
+  gchar *license_text; /* Extra license text */
+  ClutterActor *license_actor;
+  
+  ChamplainView *view;
+};
+
+G_DEFINE_TYPE (ChamplainLicense, champlain_license, CLUTTER_TYPE_GROUP);
+
+#define GET_PRIVATE(obj) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CHAMPLAIN_TYPE_LICENSE, ChamplainLicensePrivate))
+
+#define WIDTH_PADDING 10
+#define HEIGHT_PADDING 7
+
+static void
+champlain_license_get_property (GObject *object,
+    guint prop_id,
+    GValue *value,
+    GParamSpec *pspec)
+{
+  ChamplainLicensePrivate *priv = CHAMPLAIN_LICENSE (object)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_LICENSE_EXTRA:
+      g_value_set_string (value, priv->license_text);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+static void
+champlain_license_set_property (GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec)
+{
+  ChamplainLicense *license = CHAMPLAIN_LICENSE (object);
+
+  switch (prop_id)
+    {
+    case PROP_LICENSE_EXTRA:
+      champlain_license_set_text (license, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+static void
+champlain_license_dispose (GObject *object)
+{
+//  ChamplainLicensePrivate *priv = CHAMPLAIN_LICENSE (object)->priv;
+
+  G_OBJECT_CLASS (champlain_license_parent_class)->dispose (object);
+}
+
+
+static void
+champlain_license_finalize (GObject *object)
+{
+  ChamplainLicensePrivate *priv = CHAMPLAIN_LICENSE (object)->priv;
+
+  g_free (priv->license_text);
+
+  G_OBJECT_CLASS (champlain_license_parent_class)->finalize (object);
+}
+
+
+static void
+champlain_license_class_init (ChamplainLicenseClass *license_class)
+{
+  g_type_class_add_private (license_class, sizeof (ChamplainLicensePrivate));
+
+  GObjectClass *object_class = G_OBJECT_CLASS (license_class);
+  object_class->finalize = champlain_license_finalize;
+  object_class->dispose = champlain_license_dispose;
+  object_class->get_property = champlain_license_get_property;
+  object_class->set_property = champlain_license_set_property;
+
+  /**
+   * ChamplainView:license-text:
+   *
+   * Sets additional text to be displayed in the license area.  The map's
+   * license will be added below it. Your text can have multiple line, just use
+   * "\n" in between.
+   *
+   * Since: 0.4.3
+   */
+  g_object_class_install_property (object_class,
+      PROP_LICENSE_EXTRA,
+      g_param_spec_string ("license-text",
+          "Additional license",
+          "Additional license text",
+          "",
+          CHAMPLAIN_PARAM_READWRITE));
+}
+
+
+static void
+redraw_license (ChamplainLicense *license)
+{
+  ChamplainLicensePrivate *priv = license->priv;
+  gchar *text;
+  gfloat width, height;
+  
+  if (!priv->view)
+    return;
+
+  if (priv->license_text)
+    text = g_strjoin ("\n",
+          priv->license_text,
+          champlain_view_get_license_text (priv->view),
+          NULL);
+  else
+    text = g_strdup (champlain_view_get_license_text (priv->view));
+
+  clutter_text_set_text (CLUTTER_TEXT (priv->license_actor), text);
+  clutter_actor_get_size (priv->license_actor, &width, &height);
+  clutter_actor_set_size (CLUTTER_ACTOR (license), width + 2 * WIDTH_PADDING, height + 2 * HEIGHT_PADDING);
+  clutter_actor_set_position (priv->license_actor, WIDTH_PADDING, HEIGHT_PADDING);
+
+  g_free (text);
+}
+
+
+static void
+create_license (ChamplainLicense *license)
+{
+  ChamplainLicensePrivate *priv = license->priv;
+
+  if (priv->license_actor)
+    {
+      g_object_unref (priv->license_actor);
+      clutter_container_remove_actor (CLUTTER_CONTAINER (license), priv->license_actor);
+    }
+
+  priv->license_actor = g_object_ref (clutter_text_new ());
+  clutter_text_set_font_name (CLUTTER_TEXT (priv->license_actor), "sans 8");
+  clutter_text_set_line_alignment (CLUTTER_TEXT (priv->license_actor), PANGO_ALIGN_RIGHT);
+  clutter_actor_set_opacity (priv->license_actor, 128);
+  clutter_container_add_actor (CLUTTER_CONTAINER (license), priv->license_actor);
+//  clutter_actor_set_anchor_point_from_gravity (priv->license_actor, CLUTTER_GRAVITY_SOUTH_EAST);
+}
+
+
+static void
+champlain_license_init (ChamplainLicense *license)
+{
+  ChamplainLicensePrivate *priv = GET_PRIVATE (license);
+
+  license->priv = priv;
+  priv->license_text = NULL;
+  priv->view = NULL;
+  priv->license_actor = NULL;
+  
+  create_license (license);
+}
+
+
+ClutterActor *
+champlain_license_new (void)
+{
+  return CLUTTER_ACTOR (g_object_new (CHAMPLAIN_TYPE_LICENSE, NULL));
+}
+
+
+static void
+redraw_license_cb (G_GNUC_UNUSED GObject *gobject,
+    G_GNUC_UNUSED GParamSpec *arg1,
+    ChamplainLicense *license)
+{
+  redraw_license (license);
+}
+
+
+void 
+champlain_license_connect_view (ChamplainLicense *license,
+    ChamplainView *view)
+{
+  g_return_if_fail (CHAMPLAIN_IS_LICENSE (license));
+  
+  license->priv->view = view;
+
+  g_signal_connect (view, "notify::map-source",
+      G_CALLBACK (redraw_license_cb), license);
+  redraw_license (license);
+}
+
+/**
+ * champlain_view_set_license_text:
+ * @view: a #ChamplainView
+ * @text: a license
+ *
+ * Show the additional license text on the map view.  The text will preceed the
+ * map's licence when displayed. Use "\n" to separate the lines.
+ *
+ * Since: 0.4.3
+ */
+void
+champlain_license_set_text (ChamplainLicense *license,
+    const gchar *text)
+{
+  g_return_if_fail (CHAMPLAIN_IS_LICENSE (license));
+
+  ChamplainLicensePrivate *priv = license->priv;
+
+  if (priv->license_text)
+    g_free (priv->license_text);
+
+  priv->license_text = g_strdup (text);
+  redraw_license (license);
+}
+
+/**
+ * champlain_view_get_license_text:
+ * @view: The view
+ *
+ * Gets the additional license text.
+ *
+ * Returns: the additional license text
+ *
+ * Since: 0.4.3
+ */
+const gchar *
+champlain_license_get_text (ChamplainLicense *license)
+{
+  g_return_val_if_fail (CHAMPLAIN_IS_LICENSE (license), FALSE);
+
+  return license->priv->license_text;
+}
+
+
diff --git a/champlain/champlain-license.h b/champlain/champlain-license.h
new file mode 100644
index 0000000..dd355c3
--- /dev/null
+++ b/champlain/champlain-license.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 Jiri Techet <techet gmail 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
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef CHAMPLAIN_LICENSE_H
+#define CHAMPLAIN_LICENSE_H
+
+#include <champlain/champlain-defines.h>
+
+#include <glib-object.h>
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_LICENSE champlain_license_get_type ()
+
+#define CHAMPLAIN_LICENSE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_LICENSE, ChamplainLicense))
+
+#define CHAMPLAIN_LICENSE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_LICENSE, ChamplainLicenseClass))
+
+#define CHAMPLAIN_IS_LICENSE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_LICENSE))
+
+#define CHAMPLAIN_IS_LICENSE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_LICENSE))
+
+#define CHAMPLAIN_LICENSE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_LICENSE, ChamplainLicenseClass))
+
+typedef struct _ChamplainLicensePrivate ChamplainLicensePrivate;
+
+typedef struct _ChamplainLicense ChamplainLicense;
+typedef struct _ChamplainLicenseClass ChamplainLicenseClass;
+
+
+struct _ChamplainLicense
+{
+  ClutterGroup parent;
+
+  ChamplainLicensePrivate *priv;
+};
+
+struct _ChamplainLicenseClass
+{
+  ClutterGroupClass parent_class;
+};
+
+GType champlain_license_get_type (void);
+
+ClutterActor *champlain_license_new (void);
+
+void champlain_license_set_text (ChamplainLicense *license,
+    const gchar *text);
+
+const gchar *champlain_license_get_text (ChamplainLicense *license);
+
+void 
+champlain_license_connect_view (ChamplainLicense *license,
+    ChamplainView *view);
+
+G_END_DECLS
+
+#endif
diff --git a/champlain/champlain-scale.c b/champlain/champlain-scale.c
new file mode 100644
index 0000000..64c5c66
--- /dev/null
+++ b/champlain/champlain-scale.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2011 Jiri Techet <techet gmail 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 "config.h"
+
+#include "champlain-scale.h"
+#include "champlain-defines.h"
+#include "champlain-marshal.h"
+#include "champlain-private.h"
+#include "champlain-enum-types.h"
+#include "champlain-view.h"
+
+#include <clutter/clutter.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <cairo.h>
+#include <math.h>
+#include <string.h>
+
+
+enum
+{
+  /* normal signals */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_SCALE_UNIT,
+  PROP_MAX_SCALE_WIDTH,
+};
+
+/* static guint champlain_scale_signals[LAST_SIGNAL] = { 0, }; */
+
+struct _ChamplainScalePrivate
+{
+  ChamplainUnit scale_unit;
+  guint max_scale_width;
+  gfloat text_height;
+  
+  ChamplainView *view;
+};
+
+G_DEFINE_TYPE (ChamplainScale, champlain_scale, CLUTTER_TYPE_GROUP);
+
+#define GET_PRIVATE(obj) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CHAMPLAIN_TYPE_SCALE, ChamplainScalePrivate))
+
+
+#define SCALE_HEIGHT  5
+#define GAP_SIZE 2
+#define SCALE_INSIDE_PADDING 10
+#define SCALE_LINE_WIDTH 2
+
+
+
+static void
+champlain_scale_get_property (GObject *object,
+    guint prop_id,
+    GValue *value,
+    GParamSpec *pspec)
+{
+  ChamplainScalePrivate *priv = CHAMPLAIN_SCALE (object)->priv;
+
+  switch (prop_id)
+    {
+    case PROP_MAX_SCALE_WIDTH:
+      g_value_set_uint (value, priv->max_scale_width);
+      break;
+
+    case PROP_SCALE_UNIT:
+      g_value_set_enum (value, priv->scale_unit);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+
+static void
+champlain_scale_set_property (GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec)
+{
+  ChamplainScale *scale = CHAMPLAIN_SCALE (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAX_SCALE_WIDTH:
+      champlain_scale_set_max_width (scale, g_value_get_uint (value));
+      break;
+
+    case PROP_SCALE_UNIT:
+      champlain_scale_set_unit (scale, g_value_get_enum (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+static void
+champlain_scale_dispose (GObject *object)
+{
+//  ChamplainScalePrivate *priv = CHAMPLAIN_SCALE (object)->priv;
+
+  G_OBJECT_CLASS (champlain_scale_parent_class)->dispose (object);
+}
+
+
+static void
+champlain_scale_finalize (GObject *object)
+{
+//  ChamplainScalePrivate *priv = CHAMPLAIN_SCALE (object)->priv;
+
+  G_OBJECT_CLASS (champlain_scale_parent_class)->finalize (object);
+}
+
+
+static void
+champlain_scale_class_init (ChamplainScaleClass *scale_class)
+{
+  g_type_class_add_private (scale_class, sizeof (ChamplainScalePrivate));
+
+  GObjectClass *object_class = G_OBJECT_CLASS (scale_class);
+  object_class->finalize = champlain_scale_finalize;
+  object_class->dispose = champlain_scale_dispose;
+  object_class->get_property = champlain_scale_get_property;
+  object_class->set_property = champlain_scale_set_property;
+
+  /**
+   * ChamplainScale:max-width:
+   *
+   * The size of the map scale on screen in pixels.
+   *
+   * Since: 0.4.3
+   */
+  g_object_class_install_property (object_class,
+      PROP_MAX_SCALE_WIDTH,
+      g_param_spec_uint ("max-width",
+          "The width of the scale",
+          "The max width of the scale"
+          "on screen",
+          1,
+          2000,
+          100,
+          G_PARAM_READWRITE));
+
+  /**
+   * ChamplainScale:unit:
+   *
+   * The scale's units.
+   *
+   * Since: 0.4.3
+   */
+  g_object_class_install_property (object_class,
+      PROP_SCALE_UNIT,
+      g_param_spec_enum ("scale-unit",
+          "The scale's unit",
+          "The map scale's unit",
+          CHAMPLAIN_TYPE_UNIT,
+          CHAMPLAIN_UNIT_KM,
+          G_PARAM_READWRITE));
+
+}
+
+
+static void
+redraw_scale (ChamplainScale *scale)
+{
+  static gfloat previous_m_per_pixel = 0.0;
+  static gint previous_zoom_level = 0.0;
+
+  gboolean is_small_unit = TRUE;  /* indicates if using meters */
+  ClutterActor *text, *line;
+  gfloat width, height;
+  ChamplainScalePrivate *priv = scale->priv;
+  gfloat m_per_pixel;
+  gfloat scale_width = priv->max_scale_width;
+  gchar *label;
+  cairo_t *cr;
+  gfloat base;
+  gfloat factor;
+  gboolean final_unit = FALSE;
+  gint zoom_level;
+  gdouble lat, lon;
+  gfloat offset;
+  ChamplainMapSource *map_source;
+
+  if (!priv->view)
+    return;
+
+  zoom_level = champlain_view_get_zoom_level (priv->view);
+  map_source = champlain_view_get_map_source (priv->view);
+  g_object_get (G_OBJECT (priv->view), "latitude", &lat, "longitude", &lon, NULL);
+  m_per_pixel = champlain_map_source_get_meters_per_pixel (map_source,
+      zoom_level, lat, lon);
+
+  /* Don't redraw too often, 1 meters difference is a good value
+   * since at low levels the value changes alot, and not at high levels */
+  if (fabs (m_per_pixel - previous_m_per_pixel) < 10 &&
+      previous_zoom_level == zoom_level)
+    return;
+
+  previous_m_per_pixel = m_per_pixel;
+  previous_zoom_level = zoom_level;
+
+  if (priv->scale_unit == CHAMPLAIN_UNIT_MILES)
+    m_per_pixel *= 3.28;  /* m_per_pixel is now in ft */
+
+  /* This loop will find the pretty value to display on the scale.
+   * It will be run once for metric units, and twice for imperials
+   * so that both feet and miles have pretty numbers.
+   */
+  do
+    {
+      /* Keep the previous power of 10 */
+      base = floor (log (m_per_pixel * scale_width) / log (10));
+      base = pow (10, base);
+
+      /* How many times can it be fitted in our max scale width */
+      g_assert (base > 0);
+      g_assert (m_per_pixel * scale_width / base > 0);
+      scale_width /= m_per_pixel * scale_width / base;
+      g_assert (scale_width > 0);
+      factor = floor (priv->max_scale_width / scale_width);
+      base *= factor;
+      scale_width *= factor;
+
+      if (priv->scale_unit == CHAMPLAIN_UNIT_KM)
+        {
+          if (base / 1000.0 >= 1)
+            {
+              base /= 1000.0; /* base is now in km */
+              is_small_unit = FALSE;
+            }
+          final_unit = TRUE; /* Don't need to recompute */
+        }
+      else if (priv->scale_unit == CHAMPLAIN_UNIT_MILES)
+        {
+          if (is_small_unit && base / 5280.0 >= 1)
+            {
+              m_per_pixel /= 5280.0; /* m_per_pixel is now in miles */
+              is_small_unit = FALSE;
+              /* we need to recompute the base because 1000 ft != 1 mile */
+            }
+          else
+            final_unit = TRUE;
+        }
+    } while (!final_unit);
+
+  text = clutter_container_find_child_by_name (CLUTTER_CONTAINER (scale), "scale-far-label");
+  label = g_strdup_printf ("%g", base);
+  /* Get only digits width for centering */
+  clutter_text_set_text (CLUTTER_TEXT (text), label);
+  g_free (label);
+  clutter_actor_get_size (text, &width, NULL);
+  /* actual label with unit */
+  label = g_strdup_printf ("%g %s", base,
+        priv->scale_unit == CHAMPLAIN_UNIT_KM ?
+        (is_small_unit ? "m" : "km") :
+        (is_small_unit ? "ft" : "miles"));
+  clutter_text_set_text (CLUTTER_TEXT (text), label);
+  g_free (label);
+  clutter_actor_set_position (text, (scale_width - width / 2) + SCALE_INSIDE_PADDING, SCALE_INSIDE_PADDING);
+
+  text = clutter_container_find_child_by_name (CLUTTER_CONTAINER (scale), "scale-mid-label");
+  label = g_strdup_printf ("%g", base / 2.0);
+  clutter_text_set_text (CLUTTER_TEXT (text), label);
+  clutter_actor_get_size (text, &width, &height);
+  clutter_actor_set_position (text, (scale_width - width) / 2 + SCALE_INSIDE_PADDING, SCALE_INSIDE_PADDING);
+  g_free (label);
+
+  /* Draw the line */
+  line = clutter_container_find_child_by_name (CLUTTER_CONTAINER (scale), "scale-line");
+  clutter_cairo_texture_clear (CLUTTER_CAIRO_TEXTURE (line));
+  cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (line));
+
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+  cairo_set_line_width (cr, SCALE_LINE_WIDTH);
+
+  offset = SCALE_INSIDE_PADDING + priv->text_height + GAP_SIZE;
+
+  /* First tick */
+  cairo_move_to (cr, SCALE_INSIDE_PADDING, offset);
+  cairo_line_to (cr, SCALE_INSIDE_PADDING, offset + SCALE_HEIGHT);
+  cairo_stroke (cr);
+
+  /* Line */
+  cairo_move_to (cr, SCALE_INSIDE_PADDING, offset + SCALE_HEIGHT);
+  cairo_line_to (cr, scale_width + SCALE_INSIDE_PADDING, offset + SCALE_HEIGHT);
+  cairo_stroke (cr);
+
+  /* Middle tick */
+  cairo_move_to (cr, scale_width / 2 + SCALE_INSIDE_PADDING, offset);
+  cairo_line_to (cr, scale_width / 2 + SCALE_INSIDE_PADDING, offset + SCALE_HEIGHT);
+  cairo_stroke (cr);
+
+  /* Last tick */
+  cairo_move_to (cr, scale_width + SCALE_INSIDE_PADDING, offset);
+  cairo_line_to (cr, scale_width + SCALE_INSIDE_PADDING, offset + SCALE_HEIGHT);
+  cairo_stroke (cr);
+
+  cairo_destroy (cr);
+}
+
+
+static void
+create_scale (ChamplainScale *scale)
+{
+  ClutterActor *scale_actor, *text;
+  gfloat width;
+  ChamplainScalePrivate *priv = scale->priv;
+
+  text = clutter_text_new_with_text ("Sans 9", "X km");
+  clutter_actor_set_name (text, "scale-far-label");
+  clutter_container_add_actor (CLUTTER_CONTAINER (scale), text);
+
+  text = clutter_text_new_with_text ("Sans 9", "X km");
+  clutter_actor_set_name (text, "scale-mid-label");
+  clutter_container_add_actor (CLUTTER_CONTAINER (scale), text);
+
+  text = clutter_text_new_with_text ("Sans 9", "0");
+  clutter_container_add_actor (CLUTTER_CONTAINER (scale), text);
+  clutter_actor_get_size (text, &width, &priv->text_height);
+  clutter_actor_set_position (text, SCALE_INSIDE_PADDING - width / 2, SCALE_INSIDE_PADDING);
+
+  scale_actor = clutter_cairo_texture_new (priv->max_scale_width + 2 * SCALE_INSIDE_PADDING, SCALE_HEIGHT + priv->text_height + GAP_SIZE + 2*SCALE_INSIDE_PADDING);
+  clutter_actor_set_name (scale_actor, "scale-line");
+  clutter_container_add_actor (CLUTTER_CONTAINER (scale), scale_actor);
+//  clutter_actor_set_position (CLUTTER_ACTOR (scale_actor), 0, 2*SCALE_INSIDE_PADDING);
+//      priv->viewport_size.height - SCALE_HEIGHT - SCALE_PADDING - SCALE_INSIDE_PADDING);
+
+  clutter_actor_set_opacity (CLUTTER_ACTOR (scale), 200);
+//  clutter_actor_raise_top (scale);
+}
+
+
+static void
+champlain_scale_init (ChamplainScale *scale)
+{
+  ChamplainScalePrivate *priv = GET_PRIVATE (scale);
+
+  scale->priv = priv;
+
+  priv->scale_unit = CHAMPLAIN_UNIT_KM;
+  priv->max_scale_width = 100;
+  priv->view = NULL;
+  
+  create_scale (scale);
+}
+
+
+ClutterActor *
+champlain_scale_new (void)
+{
+  return CLUTTER_ACTOR (g_object_new (CHAMPLAIN_TYPE_SCALE, NULL));
+}
+
+/**
+ * champlain_scale_set_max_width:
+ * @scale: a #ChamplainScale
+ * @value: a #guint in pixels
+ *
+ * Sets the maximum width of the scale on the screen in pixels
+ *
+ * Since: 0.4.3
+ */
+void
+champlain_scale_set_max_width (ChamplainScale *scale,
+    guint value)
+{
+  g_return_if_fail (CHAMPLAIN_IS_SCALE (scale));
+
+  scale->priv->max_scale_width = value;
+  create_scale (scale);
+  redraw_scale (scale);
+}
+
+
+/**
+ * champlain_scale_set_unit:
+ * @scale: a #ChamplainScale
+ * @unit: a #ChamplainUnit
+ *
+ * Sets the scales unit.
+ *
+ * Since: 0.4.3
+ */
+void
+champlain_scale_set_unit (ChamplainScale *scale,
+    ChamplainUnit unit)
+{
+  g_return_if_fail (CHAMPLAIN_IS_SCALE (scale));
+
+  scale->priv->scale_unit = unit;
+  redraw_scale (scale);
+}
+
+
+/**
+ * champlain_scale_get_max_width:
+ * @scale: The scale
+ *
+ * Gets the maximal scale width.
+ *
+ * Returns: The max scale width in pixels.
+ *
+ * Since: 0.4.3
+ */
+guint
+champlain_scale_get_max_width (ChamplainScale *scale)
+{
+  g_return_val_if_fail (CHAMPLAIN_IS_SCALE (scale), FALSE);
+
+  return scale->priv->max_scale_width;
+}
+
+
+/**
+ * champlain_scale_get_unit:
+ * @scale: The scale
+ *
+ * Gets the unit used by the scale.
+ *
+ * Returns: The unit used by the scale
+ *
+ * Since: 0.4.3
+ */
+ChamplainUnit
+champlain_scale_get_unit (ChamplainScale *scale)
+{
+  g_return_val_if_fail (CHAMPLAIN_IS_SCALE (scale), FALSE);
+
+  return scale->priv->scale_unit;
+}
+
+
+static void
+redraw_scale_cb (G_GNUC_UNUSED GObject *gobject,
+    G_GNUC_UNUSED GParamSpec *arg1,
+    ChamplainScale *scale)
+{
+  redraw_scale (scale);
+}
+
+
+void 
+champlain_scale_connect_view (ChamplainScale *scale,
+    ChamplainView *view)
+{
+  g_return_if_fail (CHAMPLAIN_IS_SCALE (scale));
+  
+  scale->priv->view = view;
+  g_signal_connect (view, "notify::latitude",
+      G_CALLBACK (redraw_scale_cb), scale);
+  redraw_scale (scale);
+}
diff --git a/champlain/champlain-scale.h b/champlain/champlain-scale.h
new file mode 100644
index 0000000..cfd6e7c
--- /dev/null
+++ b/champlain/champlain-scale.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 Jiri Techet <techet gmail 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
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef CHAMPLAIN_SCALE_H
+#define CHAMPLAIN_SCALE_H
+
+#include <champlain/champlain-defines.h>
+
+#include <glib-object.h>
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define CHAMPLAIN_TYPE_SCALE champlain_scale_get_type ()
+
+#define CHAMPLAIN_SCALE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHAMPLAIN_TYPE_SCALE, ChamplainScale))
+
+#define CHAMPLAIN_SCALE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), CHAMPLAIN_TYPE_SCALE, ChamplainScaleClass))
+
+#define CHAMPLAIN_IS_SCALE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHAMPLAIN_TYPE_SCALE))
+
+#define CHAMPLAIN_IS_SCALE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), CHAMPLAIN_TYPE_SCALE))
+
+#define CHAMPLAIN_SCALE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), CHAMPLAIN_TYPE_SCALE, ChamplainScaleClass))
+
+typedef struct _ChamplainScalePrivate ChamplainScalePrivate;
+
+typedef struct _ChamplainScale ChamplainScale;
+typedef struct _ChamplainScaleClass ChamplainScaleClass;
+
+/**
+ * ChamplainUnit:
+ * @CHAMPLAIN_UNIT_KM: kilometers
+ * @CHAMPLAIN_UNIT_MILES: miles
+ *
+ * Units used by the scale.
+ */
+typedef enum
+{
+  CHAMPLAIN_UNIT_KM,
+  CHAMPLAIN_UNIT_MILES,
+} ChamplainUnit;
+
+struct _ChamplainScale
+{
+  ClutterGroup parent;
+
+  ChamplainScalePrivate *priv;
+};
+
+struct _ChamplainScaleClass
+{
+  ClutterGroupClass parent_class;
+};
+
+GType champlain_scale_get_type (void);
+
+ClutterActor *champlain_scale_new (void);
+
+
+void champlain_scale_set_max_width (ChamplainScale *scale,
+    guint value);
+void champlain_scale_set_unit (ChamplainScale *scale,
+    ChamplainUnit unit);
+    
+guint champlain_scale_get_max_width (ChamplainScale *scale);
+ChamplainUnit champlain_scale_get_unit (ChamplainScale *scale);
+
+void champlain_scale_connect_view (ChamplainScale *scale,
+    ChamplainView *view);
+
+G_END_DECLS
+
+#endif
diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c
index c1f8974..b740e8f 100644
--- a/champlain/champlain-view.c
+++ b/champlain/champlain-view.c
@@ -60,6 +60,7 @@
 #include "champlain-map-source-factory.h"
 #include "champlain-private.h"
 #include "champlain-tile.h"
+#include "champlain-license.h"
 
 #include <clutter/clutter.h>
 #include <glib.h>
@@ -97,13 +98,8 @@ enum
   PROP_DECEL_RATE,
   PROP_SCROLL_MODE,
   PROP_KEEP_CENTER_ON_RESIZE,
-  PROP_SHOW_LICENSE,
-  PROP_LICENSE_EXTRA,
   PROP_ZOOM_ON_DOUBLE_CLICK,
   PROP_STATE,
-  PROP_SHOW_SCALE,
-  PROP_SCALE_UNIT,
-  PROP_MAX_SCALE_WIDTH,
 };
 
 #define PADDING 10
@@ -177,14 +173,7 @@ struct _ChamplainViewPrivate
 
   gboolean zoom_on_double_click;
 
-  gboolean show_license;
   ClutterActor *license_actor; /* Contains the license info */
-  gchar *license_text; /* Extra license text */
-
-  ClutterActor *scale_actor;
-  gboolean show_scale;
-  ChamplainUnit scale_unit;
-  guint max_scale_width;
 
   ChamplainState state; /* View's global state */
 
@@ -192,6 +181,7 @@ struct _ChamplainViewPrivate
   GoToContext *goto_context;
 
   gint tiles_loading;
+  ClutterLayoutManager *layout_manager;
 };
 
 G_DEFINE_TYPE (ChamplainView, champlain_view, CLUTTER_TYPE_GROUP);
@@ -217,8 +207,6 @@ static void viewport_pos_changed_cb (GObject *gobject,
 static gboolean finger_scroll_button_press_cb (ClutterActor *actor,
     ClutterButtonEvent *event,
     ChamplainView *view);
-static void update_license (ChamplainView *view);
-static void update_scale (ChamplainView *view);
 static void view_load_visible_tiles (ChamplainView *view);
 static void view_position_tile (ChamplainView *view,
     ChamplainTile *tile);
@@ -241,11 +229,6 @@ static void champlain_view_go_to_with_duration (ChamplainView *view,
     guint duration);
 static gboolean fill_tile_cb (FillTileCallbackData *data);
 
-#define SCALE_HEIGHT  20
-#define SCALE_PADDING 10
-#define SCALE_INSIDE_PADDING 10
-#define SCALE_LINE_WIDTH 2
-
 
 /* Updates the internals after the viewport changed */
 static void
@@ -283,7 +266,6 @@ update_viewport (ChamplainView *view,
       y);
 
   view_load_visible_tiles (view);
-  update_scale (view);
 
   g_object_notify (G_OBJECT (view), "longitude");
   g_object_notify (G_OBJECT (view), "latitude");
@@ -418,18 +400,6 @@ champlain_view_get_property (GObject *object,
       g_value_set_enum (value, priv->scroll_mode);
       break;
 
-    case PROP_SHOW_SCALE:
-      g_value_set_boolean (value, priv->show_scale);
-      break;
-
-    case PROP_MAX_SCALE_WIDTH:
-      g_value_set_uint (value, priv->max_scale_width);
-      break;
-
-    case PROP_SCALE_UNIT:
-      g_value_set_enum (value, priv->scale_unit);
-      break;
-
     case PROP_DECEL_RATE:
       {
         gdouble decel = 0.0;
@@ -442,14 +412,6 @@ champlain_view_get_property (GObject *object,
       g_value_set_boolean (value, priv->keep_center_on_resize);
       break;
 
-    case PROP_SHOW_LICENSE:
-      g_value_set_boolean (value, priv->show_license);
-      break;
-
-    case PROP_LICENSE_EXTRA:
-      g_value_set_string (value, priv->license_text);
-      break;
-
     case PROP_ZOOM_ON_DOUBLE_CLICK:
       g_value_set_boolean (value, priv->zoom_on_double_click);
       break;
@@ -507,18 +469,6 @@ champlain_view_set_property (GObject *object,
       champlain_view_set_scroll_mode (view, g_value_get_enum (value));
       break;
 
-    case PROP_SHOW_SCALE:
-      champlain_view_set_show_scale (view, g_value_get_boolean (value));
-      break;
-
-    case PROP_MAX_SCALE_WIDTH:
-      champlain_view_set_max_scale_width (view, g_value_get_uint (value));
-      break;
-
-    case PROP_SCALE_UNIT:
-      champlain_view_set_scale_unit (view, g_value_get_enum (value));
-      break;
-
     case PROP_DECEL_RATE:
       champlain_view_set_decel_rate (view, g_value_get_double (value));
       break;
@@ -527,14 +477,6 @@ champlain_view_set_property (GObject *object,
       champlain_view_set_keep_center_on_resize (view, g_value_get_boolean (value));
       break;
 
-    case PROP_SHOW_LICENSE:
-      champlain_view_set_show_license (view, g_value_get_boolean (value));
-      break;
-
-    case PROP_LICENSE_EXTRA:
-      champlain_view_set_license_text (view, g_value_get_string (value));
-      break;
-
     case PROP_ZOOM_ON_DOUBLE_CLICK:
       champlain_view_set_zoom_on_double_click (view, g_value_get_boolean (value));
       break;
@@ -577,12 +519,6 @@ champlain_view_dispose (GObject *object)
       priv->license_actor = NULL;
     }
 
-  if (priv->scale_actor != NULL)
-    {
-      g_object_unref (priv->scale_actor);
-      priv->scale_actor = NULL;
-    }
-
   if (priv->finger_scroll != NULL)
     {
       mx_kinetic_scroll_view_stop (MX_KINETIC_SCROLL_VIEW (priv->finger_scroll));
@@ -624,9 +560,7 @@ champlain_view_finalize (GObject *object)
 {
   DEBUG_LOG ()
 
-  ChamplainViewPrivate *priv = CHAMPLAIN_VIEW (object)->priv;
-
-  g_free (priv->license_text);
+//  ChamplainViewPrivate *priv = CHAMPLAIN_VIEW (object)->priv;
 
   G_OBJECT_CLASS (champlain_view_parent_class)->finalize (object);
 }
@@ -645,13 +579,6 @@ _update_idle_cb (ChamplainView *view)
 
   resize_viewport (view);
 
-  clutter_actor_set_position (priv->license_actor,
-      priv->viewport_size.width - PADDING,
-      priv->viewport_size.height - PADDING);
-  clutter_actor_set_position (priv->scale_actor,
-      SCALE_PADDING,
-      priv->viewport_size.height - SCALE_HEIGHT - SCALE_PADDING);
-
   if (priv->keep_center_on_resize)
     champlain_view_center_on (view, priv->latitude, priv->longitude);
   else
@@ -714,9 +641,6 @@ champlain_view_realize (ClutterActor *actor)
 
   /* this call will launch the tiles loading */
   champlain_view_center_on (view, priv->latitude, priv->longitude);
-
-  update_scale (view);
-  update_license (view);
 }
 
 
@@ -912,39 +836,6 @@ champlain_view_class_init (ChamplainViewClass *champlainViewClass)
           TRUE, CHAMPLAIN_PARAM_READWRITE));
 
   /**
-   * ChamplainView:show-license:
-   *
-   * Show the license on the map view.  The license information should always be
-   * available in a way or another in your application.  You can have it in
-   * About, or on the map.
-   *
-   * Since: 0.2.8
-   */
-  g_object_class_install_property (object_class,
-      PROP_SHOW_LICENSE,
-      g_param_spec_boolean ("show-license",
-          "Show the map data license",
-          "Show the map data license on the map view",
-          TRUE, CHAMPLAIN_PARAM_READWRITE));
-
-  /**
-   * ChamplainView:license-text:
-   *
-   * Sets additional text to be displayed in the license area.  The map's
-   * license will be added below it. Your text can have multiple line, just use
-   * "\n" in between.
-   *
-   * Since: 0.4.3
-   */
-  g_object_class_install_property (object_class,
-      PROP_LICENSE_EXTRA,
-      g_param_spec_string ("license-text",
-          "Additional license",
-          "Additional license text",
-          "",
-          CHAMPLAIN_PARAM_READWRITE));
-
-  /**
    * ChamplainView:zoom-on-double-click:
    *
    * Should the view zoom in and recenter when the user double click on the map.
@@ -976,56 +867,6 @@ champlain_view_class_init (ChamplainViewClass *champlainViewClass)
           G_PARAM_READABLE));
 
   /**
-   * ChamplainView:show-scale:
-   *
-   * Display the map scale.
-   *
-   * Since: 0.4.3
-   */
-  g_object_class_install_property (object_class,
-      PROP_SHOW_SCALE,
-      g_param_spec_boolean ("show-scale",
-          "Show the map scale",
-          "Show the map scale "
-          "on the screen",
-          FALSE,
-          G_PARAM_READWRITE));
-
-  /**
-   * ChamplainView:max-scale-width:
-   *
-   * The size of the map scale on screen in pixels.
-   *
-   * Since: 0.4.3
-   */
-  g_object_class_install_property (object_class,
-      PROP_MAX_SCALE_WIDTH,
-      g_param_spec_uint ("max-scale-width",
-          "The width of the scale",
-          "The max width of the scale"
-          "on screen",
-          1,
-          2000,
-          100,
-          G_PARAM_READWRITE));
-
-  /**
-   * ChamplainView:scale-unit:
-   *
-   * The scale's units.
-   *
-   * Since: 0.4.3
-   */
-  g_object_class_install_property (object_class,
-      PROP_SCALE_UNIT,
-      g_param_spec_enum ("scale-unit",
-          "The scale's unit",
-          "The map scale's unit",
-          CHAMPLAIN_TYPE_UNIT,
-          CHAMPLAIN_UNIT_KM,
-          G_PARAM_READWRITE));
-
-  /**
    * ChamplainView::animation-completed:
    *
    * The #ChamplainView::animation-completed signal is emitted when any animation in the view
@@ -1049,214 +890,6 @@ champlain_view_class_init (ChamplainViewClass *champlainViewClass)
 
 
 static void
-create_license (ChamplainView *view)
-{
-  DEBUG_LOG ()
-
-  ChamplainViewPrivate *priv = view->priv;
-
-  if (priv->license_actor)
-    {
-      g_object_unref (priv->license_actor);
-      clutter_container_remove_actor (CLUTTER_CONTAINER (priv->stage), priv->license_actor);
-    }
-
-  priv->license_actor = g_object_ref (clutter_text_new ());
-  clutter_text_set_font_name (CLUTTER_TEXT (priv->license_actor), "sans 8");
-  clutter_text_set_line_alignment (CLUTTER_TEXT (priv->license_actor), PANGO_ALIGN_RIGHT);
-  clutter_actor_set_opacity (priv->license_actor, 128);
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->stage),
-      priv->license_actor);
-  clutter_actor_set_anchor_point_from_gravity (priv->license_actor, CLUTTER_GRAVITY_SOUTH_EAST);
-  clutter_actor_raise_top (priv->license_actor);
-}
-
-
-static void
-update_scale (ChamplainView *view)
-{
-  DEBUG_LOG ()
-
-  static gfloat previous_m_per_pixel = 0.0;
-  static gint previous_zoom_level = 0.0;
-
-  gboolean is_small_unit = TRUE;  /* indicates if using meters */
-  ClutterActor *text, *line;
-  gfloat width;
-  ChamplainViewPrivate *priv = view->priv;
-  gfloat m_per_pixel;
-  gfloat scale_width = priv->max_scale_width;
-  gchar *label;
-  cairo_t *cr;
-  gfloat base;
-  gfloat factor;
-  gboolean final_unit = FALSE;
-
-  if (priv->show_scale)
-    {
-      clutter_actor_show (priv->scale_actor);
-    }
-  else
-    {
-      clutter_actor_hide (priv->scale_actor);
-      return;
-    }
-
-  m_per_pixel = champlain_map_source_get_meters_per_pixel (priv->map_source,
-        priv->zoom_level, priv->latitude, priv->longitude);
-
-  /* Don't redraw too often, 1 meters difference is a good value
-   * since at low levels the value changes alot, and not at high levels */
-  if (fabs (m_per_pixel - previous_m_per_pixel) < 10 &&
-      previous_zoom_level == priv->zoom_level)
-    return;
-
-  previous_m_per_pixel = m_per_pixel;
-  previous_zoom_level = priv->zoom_level;
-
-  if (priv->scale_unit == CHAMPLAIN_UNIT_MILES)
-    m_per_pixel *= 3.28;  /* m_per_pixel is now in ft */
-
-  /* This loop will find the pretty value to display on the scale.
-   * It will be run once for metric units, and twice for imperials
-   * so that both feet and miles have pretty numbers.
-   */
-  do
-    {
-      /* Keep the previous power of 10 */
-      base = floor (log (m_per_pixel * scale_width) / log (10));
-      base = pow (10, base);
-
-      /* How many times can it be fitted in our max scale width */
-      g_assert (base > 0);
-      g_assert (m_per_pixel * scale_width / base > 0);
-      scale_width /= m_per_pixel * scale_width / base;
-      g_assert (scale_width > 0);
-      factor = floor (priv->max_scale_width / scale_width);
-      base *= factor;
-      scale_width *= factor;
-
-      if (priv->scale_unit == CHAMPLAIN_UNIT_KM)
-        {
-          if (base / 1000.0 >= 1)
-            {
-              base /= 1000.0; /* base is now in km */
-              is_small_unit = FALSE;
-            }
-          final_unit = TRUE; /* Don't need to recompute */
-        }
-      else if (priv->scale_unit == CHAMPLAIN_UNIT_MILES)
-        {
-          if (is_small_unit && base / 5280.0 >= 1)
-            {
-              m_per_pixel /= 5280.0; /* m_per_pixel is now in miles */
-              is_small_unit = FALSE;
-              /* we need to recompute the base because 1000 ft != 1 mile */
-            }
-          else
-            final_unit = TRUE;
-        }
-    } while (!final_unit);
-
-  text = clutter_container_find_child_by_name (CLUTTER_CONTAINER (priv->scale_actor), "scale-far-label");
-  label = g_strdup_printf ("%g", base);
-  /* Get only digits width for centering */
-  clutter_text_set_text (CLUTTER_TEXT (text), label);
-  g_free (label);
-  clutter_actor_get_size (text, &width, NULL);
-  /* actual label with unit */
-  label = g_strdup_printf ("%g %s", base,
-        priv->scale_unit == CHAMPLAIN_UNIT_KM ?
-        (is_small_unit ? "m" : "km") :
-        (is_small_unit ? "ft" : "miles"));
-  clutter_text_set_text (CLUTTER_TEXT (text), label);
-  g_free (label);
-  clutter_actor_set_position (text, (scale_width - width / 2) + SCALE_INSIDE_PADDING, -SCALE_INSIDE_PADDING);
-
-  text = clutter_container_find_child_by_name (CLUTTER_CONTAINER (priv->scale_actor), "scale-mid-label");
-  label = g_strdup_printf ("%g", base / 2.0);
-  clutter_text_set_text (CLUTTER_TEXT (text), label);
-  clutter_actor_get_size (text, &width, NULL);
-  clutter_actor_set_position (text, (scale_width - width) / 2 + SCALE_INSIDE_PADDING, -SCALE_INSIDE_PADDING);
-  g_free (label);
-
-  /* Draw the line */
-  line = clutter_container_find_child_by_name (CLUTTER_CONTAINER (priv->scale_actor), "scale-line");
-  clutter_cairo_texture_clear (CLUTTER_CAIRO_TEXTURE (line));
-  cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (line));
-
-  cairo_set_source_rgb (cr, 0, 0, 0);
-  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
-  cairo_set_line_width (cr, SCALE_LINE_WIDTH);
-
-  /* First tick */
-  cairo_move_to (cr, SCALE_INSIDE_PADDING, SCALE_HEIGHT / 4);
-  cairo_line_to (cr, SCALE_INSIDE_PADDING, SCALE_HEIGHT / 2);
-  cairo_stroke (cr);
-
-  /* Line */
-  cairo_move_to (cr, SCALE_INSIDE_PADDING, SCALE_HEIGHT / 2);
-  cairo_line_to (cr, scale_width + SCALE_INSIDE_PADDING, SCALE_HEIGHT / 2);
-  cairo_stroke (cr);
-
-  /* Middle tick */
-  cairo_move_to (cr, scale_width / 2 + SCALE_INSIDE_PADDING, SCALE_HEIGHT / 4);
-  cairo_line_to (cr, scale_width / 2 + SCALE_INSIDE_PADDING, SCALE_HEIGHT / 2);
-  cairo_stroke (cr);
-
-  /* Last tick */
-  cairo_move_to (cr, scale_width + SCALE_INSIDE_PADDING, SCALE_HEIGHT / 4);
-  cairo_line_to (cr, scale_width + SCALE_INSIDE_PADDING, SCALE_HEIGHT / 2);
-  cairo_stroke (cr);
-
-  cairo_destroy (cr);
-}
-
-
-static void
-create_scale (ChamplainView *view)
-{
-  DEBUG_LOG ()
-
-  ClutterActor *scale, *text;
-  gfloat width;
-  ChamplainViewPrivate *priv = view->priv;
-
-  if (priv->scale_actor)
-    {
-      g_object_unref (priv->scale_actor);
-      clutter_container_remove_actor (CLUTTER_CONTAINER (priv->stage), priv->scale_actor);
-    }
-
-  priv->scale_actor = g_object_ref (clutter_group_new ());
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->stage), priv->scale_actor);
-
-  scale = clutter_cairo_texture_new (priv->max_scale_width + 2 * SCALE_INSIDE_PADDING, SCALE_HEIGHT + 2 * SCALE_INSIDE_PADDING);
-  clutter_actor_set_name (scale, "scale-line");
-
-  text = clutter_text_new_with_text ("Sans 9", "X km");
-  clutter_actor_set_name (text, "scale-far-label");
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->scale_actor), text);
-
-  text = clutter_text_new_with_text ("Sans 9", "X km");
-  clutter_actor_set_name (text, "scale-mid-label");
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->scale_actor), text);
-
-  text = clutter_text_new_with_text ("Sans 9", "0");
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->scale_actor), text);
-  clutter_actor_get_size (text, &width, NULL);
-  clutter_actor_set_position (text, SCALE_INSIDE_PADDING - width / 2, -SCALE_INSIDE_PADDING);
-
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->scale_actor), scale);
-  clutter_actor_set_position (priv->scale_actor, SCALE_PADDING - SCALE_INSIDE_PADDING,
-      priv->viewport_size.height - SCALE_HEIGHT - SCALE_PADDING - SCALE_INSIDE_PADDING);
-
-  clutter_actor_set_opacity (priv->scale_actor, 200);
-  clutter_actor_raise_top (priv->scale_actor);
-}
-
-
-static void
 champlain_view_init (ChamplainView *view)
 {
   DEBUG_LOG ()
@@ -1278,9 +911,7 @@ champlain_view_init (ChamplainView *view)
   priv->max_zoom_level = champlain_map_source_get_max_zoom_level (priv->map_source);
   priv->keep_center_on_resize = TRUE;
   priv->zoom_on_double_click = TRUE;
-  priv->show_license = TRUE;
   priv->license_actor = NULL;
-  priv->license_text = NULL;
   priv->stage = NULL;
   priv->scroll_mode = CHAMPLAIN_SCROLL_MODE_PUSH;
   priv->viewport_size.x = 0;
@@ -1294,9 +925,6 @@ champlain_view_init (ChamplainView *view)
   priv->latitude = 0.0f;
   priv->longitude = 0.0f;
   priv->goto_context = NULL;
-  priv->show_scale = FALSE;
-  priv->scale_unit = CHAMPLAIN_UNIT_KM;
-  priv->max_scale_width = 100;
   priv->tiles_loading = 0;
   priv->update_viewport_timer = g_timer_new();
 
@@ -1349,20 +977,24 @@ champlain_view_init (ChamplainView *view)
       priv->viewport);
 
   /* Setup stage */
-  priv->stage = g_object_ref (clutter_group_new ());
+  priv->layout_manager = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
+                                  CLUTTER_BIN_ALIGNMENT_CENTER);
+  priv->stage = g_object_ref (clutter_box_new (priv->layout_manager));
 
-  clutter_container_add_actor (CLUTTER_CONTAINER (priv->stage),
-      priv->finger_scroll);
+  clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (priv->layout_manager), priv->finger_scroll,
+                          CLUTTER_BIN_ALIGNMENT_FILL,
+                          CLUTTER_BIN_ALIGNMENT_FILL);
 
   clutter_container_add_actor (CLUTTER_CONTAINER (view), priv->stage);
 
   resize_viewport (view);
 
-  /* Setup scale */
-  create_scale (view);
-
   /* Setup license */
-  create_license (view);
+  priv->license_actor = g_object_ref (champlain_license_new ());
+  champlain_license_connect_view (CHAMPLAIN_LICENSE (priv->license_actor), view);
+  clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (priv->layout_manager), priv->license_actor,
+                          CLUTTER_BIN_ALIGNMENT_END,
+                          CLUTTER_BIN_ALIGNMENT_END);
 
   priv->state = CHAMPLAIN_STATE_DONE;
   g_object_notify (G_OBJECT (view), "state");
@@ -1397,33 +1029,6 @@ viewport_pos_changed_cb (G_GNUC_UNUSED GObject *gobject,
 }
 
 
-static void
-update_license (ChamplainView *view)
-{
-  DEBUG_LOG ()
-
-  ChamplainViewPrivate *priv = view->priv;
-  gchar *license;
-
-  if (priv->license_text)
-    license = g_strjoin ("\n",
-          priv->license_text,
-          champlain_map_source_get_license (priv->map_source),
-          NULL);
-  else
-    license = g_strdup (champlain_map_source_get_license (priv->map_source));
-
-  clutter_text_set_text (CLUTTER_TEXT (priv->license_actor), license);
-
-  if (priv->show_license)
-    clutter_actor_show (priv->license_actor);
-  else
-    clutter_actor_hide (priv->license_actor);
-
-  g_free (license);
-}
-
-
 static gboolean
 finger_scroll_button_press_cb (G_GNUC_UNUSED ClutterActor *actor,
     ClutterButtonEvent *event,
@@ -2418,7 +2023,6 @@ champlain_view_set_map_source (ChamplainView *view,
 
   remove_all_tiles (view);
 
-  update_license (view);
   champlain_view_center_on (view, priv->latitude, priv->longitude);
 
   g_object_notify (G_OBJECT (view), "map-source");
@@ -2495,125 +2099,6 @@ champlain_view_set_keep_center_on_resize (ChamplainView *view,
 
 
 /**
- * champlain_view_set_license_text:
- * @view: a #ChamplainView
- * @text: a license
- *
- * Show the additional license text on the map view.  The text will preceed the
- * map's licence when displayed. Use "\n" to separate the lines.
- *
- * Since: 0.4.3
- */
-void
-champlain_view_set_license_text (ChamplainView *view,
-    const gchar *text)
-{
-  DEBUG_LOG ()
-
-  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
-
-  ChamplainViewPrivate *priv = view->priv;
-
-  if (priv->license_text)
-    g_free (priv->license_text);
-
-  priv->license_text = g_strdup (text);
-  update_license (view);
-}
-
-
-/**
- * champlain_view_set_show_license:
- * @view: a #ChamplainView
- * @value: a #gboolean
- *
- * Show the license on the map view.  The license information should always be
- * available in a way or another in your application.  You can have it in
- * About, or on the map.
- *
- * Since: 0.4
- */
-void
-champlain_view_set_show_license (ChamplainView *view,
-    gboolean value)
-{
-  DEBUG_LOG ()
-
-  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
-
-  view->priv->show_license = value;
-  update_license (view);
-}
-
-
-/**
- * champlain_view_set_show_scale:
- * @view: a #ChamplainView
- * @value: a #gboolean
- *
- * Show the scale on the map view.
- *
- * Since: 0.4.3
- */
-void
-champlain_view_set_show_scale (ChamplainView *view,
-    gboolean value)
-{
-  DEBUG_LOG ()
-
-  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
-
-  view->priv->show_scale = value;
-  update_scale (view);
-}
-
-
-/**
- * champlain_view_set_max_scale_width:
- * @view: a #ChamplainView
- * @value: a #guint in pixels
- *
- * Sets the maximum width of the scale on the screen in pixels
- *
- * Since: 0.4.3
- */
-void
-champlain_view_set_max_scale_width (ChamplainView *view,
-    guint value)
-{
-  DEBUG_LOG ()
-
-  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
-
-  view->priv->max_scale_width = value;
-  create_scale (view);
-  update_scale (view);
-}
-
-
-/**
- * champlain_view_set_scale_unit:
- * @view: a #ChamplainView
- * @unit: a #ChamplainUnit
- *
- * Sets the scales unit.
- *
- * Since: 0.4.3
- */
-void
-champlain_view_set_scale_unit (ChamplainView *view,
-    ChamplainUnit unit)
-{
-  DEBUG_LOG ()
-
-  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
-
-  view->priv->scale_unit = unit;
-  update_scale (view);
-}
-
-
-/**
  * champlain_view_set_zoom_on_double_click:
  * @view: a #ChamplainView
  * @value: a #gboolean
@@ -2929,126 +2414,57 @@ champlain_view_get_keep_center_on_resize (ChamplainView *view)
 
 
 /**
- * champlain_view_get_show_license:
+ * champlain_view_get_zoom_on_double_click:
  * @view: The view
  *
- * Checks whether the view displays the license.
+ * Checks whether the view zooms on double click.
  *
- * Returns: TRUE if the view displays the license, FALSE otherwise.
+ * Returns: TRUE if the view zooms on double click, FALSE otherwise.
  *
  * Since: 0.4
  */
 gboolean
-champlain_view_get_show_license (ChamplainView *view)
+champlain_view_get_zoom_on_double_click (ChamplainView *view)
 {
   DEBUG_LOG ()
 
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
 
-  return view->priv->show_license;
+  return view->priv->zoom_on_double_click;
 }
 
 
-/**
- * champlain_view_get_license_text:
- * @view: The view
- *
- * Gets the additional license text.
- *
- * Returns: the additional license text
- *
- * Since: 0.4.3
- */
-const gchar *
-champlain_view_get_license_text (ChamplainView *view)
+ClutterBinLayout *
+champlain_view_get_layout_manager (ChamplainView *view)
 {
   DEBUG_LOG ()
 
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
-
-  return view->priv->license_text;
-}
-
-
-/**
- * champlain_view_get_show_scale:
- * @view: The view
- *
- * Checks whether the view displays the scale.
- *
- * Returns: TRUE if the view displays the scale, FALSE otherwise.
- *
- * Since: 0.4.3
- */
-gboolean
-champlain_view_get_show_scale (ChamplainView *view)
-{
-  DEBUG_LOG ()
-
-  g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
-
-  return view->priv->show_scale;
-}
-
-
-/**
- * champlain_view_get_max_scale_width:
- * @view: The view
- *
- * Gets the maximal scale width.
- *
- * Returns: The max scale width in pixels.
- *
- * Since: 0.4.3
- */
-guint
-champlain_view_get_max_scale_width (ChamplainView *view)
-{
-  DEBUG_LOG ()
-
-  g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
-
-  return view->priv->max_scale_width;
+  
+  ChamplainViewPrivate *priv = view->priv;
+  
+  return CLUTTER_BIN_LAYOUT (priv->layout_manager);
 }
 
 
-/**
- * champlain_view_get_scale_unit:
- * @view: The view
- *
- * Gets the unit used by the scale.
- *
- * Returns: The unit used by the scale
- *
- * Since: 0.4.3
- */
-ChamplainUnit
-champlain_view_get_scale_unit (ChamplainView *view)
+const gchar *
+champlain_view_get_license_text (ChamplainView *view)
 {
   DEBUG_LOG ()
 
   g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
-
-  return view->priv->scale_unit;
+  
+  ChamplainViewPrivate *priv = view->priv;
+  
+  return champlain_map_source_get_license (priv->map_source);  
 }
 
 
-/**
- * champlain_view_get_zoom_on_double_click:
- * @view: The view
- *
- * Checks whether the view zooms on double click.
- *
- * Returns: TRUE if the view zooms on double click, FALSE otherwise.
- *
- * Since: 0.4
- */
-gboolean
-champlain_view_get_zoom_on_double_click (ChamplainView *view)
+ChamplainLicense *champlain_view_get_license_actor (ChamplainView *view)
 {
   DEBUG_LOG ()
 
-  g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), FALSE);
-
-  return view->priv->zoom_on_double_click;
+  g_return_val_if_fail (CHAMPLAIN_IS_VIEW (view), NULL);
+  
+  return CHAMPLAIN_LICENSE (view->priv->license_actor);      
 }
diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h
index 4b0d98c..9aa538f 100644
--- a/champlain/champlain-view.h
+++ b/champlain/champlain-view.h
@@ -27,6 +27,7 @@
 #include <champlain/champlain-defines.h>
 #include <champlain/champlain-layer.h>
 #include <champlain/champlain-map-source.h>
+#include <champlain/champlain-license.h>
 
 #include <glib.h>
 #include <glib-object.h>
@@ -67,19 +68,6 @@ typedef enum
 } ChamplainScrollMode;
 
 
-/**
- * ChamplainUnit:
- * @CHAMPLAIN_UNIT_KM: kilometers
- * @CHAMPLAIN_UNIT_MILES: miles
- *
- * Units used by the scale.
- */
-typedef enum
-{
-  CHAMPLAIN_UNIT_KM,
-  CHAMPLAIN_UNIT_MILES,
-} ChamplainUnit;
-
 struct _ChamplainView
 {
   ClutterGroup group;
@@ -128,16 +116,6 @@ void champlain_view_set_scroll_mode (ChamplainView *view,
     ChamplainScrollMode mode);
 void champlain_view_set_keep_center_on_resize (ChamplainView *view,
     gboolean value);
-void champlain_view_set_show_license (ChamplainView *view,
-    gboolean value);
-void champlain_view_set_license_text (ChamplainView *view,
-    const gchar *text);
-void champlain_view_set_show_scale (ChamplainView *view,
-    gboolean value);
-void champlain_view_set_scale_unit (ChamplainView *view,
-    ChamplainUnit unit);
-void champlain_view_set_max_scale_width (ChamplainView *view,
-    guint value);
 void champlain_view_set_zoom_on_double_click (ChamplainView *view,
     gboolean value);
 
@@ -146,7 +124,6 @@ void champlain_view_add_layer (ChamplainView *view,
 void champlain_view_remove_layer (ChamplainView *view,
     ChamplainLayer *layer);
 
-
 gint champlain_view_get_zoom_level (ChamplainView *view);
 gint champlain_view_get_min_zoom_level (ChamplainView *view);
 gint champlain_view_get_max_zoom_level (ChamplainView *view);
@@ -154,16 +131,11 @@ ChamplainMapSource *champlain_view_get_map_source (ChamplainView *view);
 gdouble champlain_view_get_decel_rate (ChamplainView *view);
 ChamplainScrollMode champlain_view_get_scroll_mode (ChamplainView *view);
 gboolean champlain_view_get_keep_center_on_resize (ChamplainView *view);
-gboolean champlain_view_get_show_license (ChamplainView *view);
 const gchar *champlain_view_get_license_text (ChamplainView *view);
-gboolean champlain_view_get_show_scale (ChamplainView *view);
-guint champlain_view_get_max_scale_width (ChamplainView *view);
-ChamplainUnit champlain_view_get_scale_unit (ChamplainView *view);
 gboolean champlain_view_get_zoom_on_double_click (ChamplainView *view);
 
 void champlain_view_reload_tiles (ChamplainView *view);
 
-
 gdouble champlain_view_x_to_longitude (ChamplainView *view,
     gdouble x);
 gdouble champlain_view_y_to_latitude (ChamplainView *view,
@@ -176,6 +148,9 @@ gdouble champlain_view_latitude_to_y (ChamplainView *view,
 double champlain_view_get_viewport_x (ChamplainView *view);
 double champlain_view_get_viewport_y (ChamplainView *view);
 
+ClutterBinLayout *champlain_view_get_layout_manager (ChamplainView *view); 
+
+ChamplainLicense *champlain_view_get_license_actor (ChamplainView *view);
 
 G_END_DECLS
 
diff --git a/champlain/champlain.h b/champlain/champlain.h
index d4a9324..ffdff63 100644
--- a/champlain/champlain.h
+++ b/champlain/champlain.h
@@ -36,6 +36,7 @@
 #include "champlain/champlain-label.h"
 #include "champlain/champlain-view.h"
 #include "champlain/champlain-bounding-box.h"
+#include "champlain/champlain-scale.h"
 
 #include "champlain/champlain-map-source.h"
 #include "champlain/champlain-tile-source.h"
diff --git a/demos/launcher-gtk.c b/demos/launcher-gtk.c
index e2f8b24..32250a9 100644
--- a/demos/launcher-gtk.c
+++ b/demos/launcher-gtk.c
@@ -221,6 +221,9 @@ main (int argc,
   GtkWidget *widget, *vbox, *bbox, *button, *viewport;
   ChamplainView *view;
   ChamplainMarkerLayer *layer;
+  ClutterActor *scale;
+  ClutterBinLayout *layout_manager;
+  ChamplainLicense *license_actor;
 
   g_thread_init (NULL);
   gtk_clutter_init (&argc, &argv);
@@ -252,9 +255,20 @@ main (int argc,
   g_object_set (G_OBJECT (view),
       "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC,
       "zoom-level", 5,
-      "license-text", "Don't eat cereals with orange juice\nIt tastes bad",
-      "show-scale", TRUE,
       NULL);
+      
+  scale = champlain_scale_new ();
+  champlain_scale_connect_view (CHAMPLAIN_SCALE (scale), view);
+  
+  /* align to the bottom left */
+  layout_manager = champlain_view_get_layout_manager (view);
+  clutter_bin_layout_add (layout_manager, scale,
+                          CLUTTER_BIN_ALIGNMENT_START,
+                          CLUTTER_BIN_ALIGNMENT_END);
+  
+  license_actor = champlain_view_get_license_actor (view);
+  champlain_license_set_text (license_actor, "Don't eat cereals with orange juice\nIt tastes bad");
+  
   champlain_view_center_on (CHAMPLAIN_VIEW (view), 45.466, -73.75);
 
   layer = create_marker_layer (view);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]