[libshumate/tintou/compass] Compass: Add ShumateCompass




commit 1339f34ee974421a0d6b3ea53ad3a2d9a9b8e625
Author: Corentin Noël <corentin noel collabora com>
Date:   Tue Aug 17 12:18:31 2021 +0200

    Compass: Add ShumateCompass
    
    A simple widget to show the north when doing a rotation of the map.

 data/compass.css                        |   8 +
 data/icons/32x32/status/map-compass.svg |  25 +++
 data/libshumate.gresource.xml           |   2 +
 demos/shumate-demo-window.c             |   3 +
 demos/shumate-demo-window.ui            |  13 +-
 shumate/meson.build                     |   2 +
 shumate/shumate-compass.c               | 263 ++++++++++++++++++++++++++++++++
 shumate/shumate-compass.h               |  46 ++++++
 shumate/shumate.h                       |   1 +
 9 files changed, 362 insertions(+), 1 deletion(-)
---
diff --git a/data/compass.css b/data/compass.css
new file mode 100644
index 0000000..1b34d6a
--- /dev/null
+++ b/data/compass.css
@@ -0,0 +1,8 @@
+map-compass image {
+  padding: 3px;
+  -gtk-icon-size: 32px;
+}
+
+map-compass {
+  margin: 6px;
+}
diff --git a/data/icons/32x32/status/map-compass.svg b/data/icons/32x32/status/map-compass.svg
new file mode 100644
index 0000000..eb29863
--- /dev/null
+++ b/data/icons/32x32/status/map-compass.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="32"
+   height="32"
+   viewBox="0 0 8.4666667 8.4666667"
+   version="1.1"
+   id="svg5"
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:svg="http://www.w3.org/2000/svg";>
+  <defs
+     id="defs2" />
+  <g
+     id="layer1">
+    <path
+       
style="fill:#ff0008;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.59953439;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers
 fill stroke"
+       d="M 4.2333333,1.0583333 3.175,3.96536 5.2916667,3.97214 Z"
+       id="path1025" />
+    <path
+       
style="fill:#ffffff;stroke:#000000;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.60000002;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers
 fill stroke"
+       d="M 4.2333333,7.4083334 3.175,4.5013267 5.2916667,4.4945067 Z"
+       id="path1025-3" />
+  </g>
+</svg>
diff --git a/data/libshumate.gresource.xml b/data/libshumate.gresource.xml
index aaad36e..6c26462 100644
--- a/data/libshumate.gresource.xml
+++ b/data/libshumate.gresource.xml
@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/shumate/">
+    <file compressed="true">compass.css</file>
     <file compressed="true">scale.css</file>
     <file compressed="true">license.css</file>
     <file compressed="true">point.css</file>
+    <file preprocess="xml-stripblanks">icons/32x32/status/map-compass.svg</file>
   </gresource>
 </gresources>
diff --git a/demos/shumate-demo-window.c b/demos/shumate-demo-window.c
index ba76af7..88b6e5c 100644
--- a/demos/shumate-demo-window.c
+++ b/demos/shumate-demo-window.c
@@ -28,6 +28,7 @@ struct _ShumateDemoWindow
   GtkOverlay *overlay;
   ShumateScale *scale;
   ShumateLicense *license;
+  ShumateCompass *compass;
   GtkDropDown *layers_dropdown;
   ShumateMapSourceRegistry *registry;
 
@@ -121,6 +122,7 @@ shumate_demo_window_class_init (ShumateDemoWindowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, overlay);
   gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, scale);
   gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, license);
+  gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, compass);
   gtk_widget_class_bind_template_child (widget_class, ShumateDemoWindow, layers_dropdown);
   gtk_widget_class_bind_template_callback (widget_class, on_layers_dropdown_notify_selected);
 }
@@ -153,6 +155,7 @@ shumate_demo_window_init (ShumateDemoWindow *self)
   on_layers_dropdown_notify_selected (self, NULL, self->layers_dropdown);
 
   shumate_scale_set_viewport (self->scale, viewport);
+  shumate_compass_set_viewport (self->compass, viewport);
 
   /* Add the marker layers */
   self->marker_layer = shumate_marker_layer_new (viewport);
diff --git a/demos/shumate-demo-window.ui b/demos/shumate-demo-window.ui
index 96c50a1..d2ee6d0 100644
--- a/demos/shumate-demo-window.ui
+++ b/demos/shumate-demo-window.ui
@@ -29,9 +29,20 @@
           </object>
         </child>
         <child type="overlay">
-          <object class="ShumateLicense" id="license">
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
             <property name="halign">end</property>
             <property name="valign">end</property>
+            <child>
+              <object class="ShumateCompass" id="compass">
+                <property name="halign">end</property>
+              </object>
+            </child>
+            <child>
+              <object class="ShumateLicense" id="license">
+                <property name="halign">end</property>
+              </object>
+            </child>
           </object>
         </child>
       </object>
diff --git a/shumate/meson.build b/shumate/meson.build
index 84eee2b..4c9542a 100644
--- a/shumate/meson.build
+++ b/shumate/meson.build
@@ -1,5 +1,6 @@
 libshumate_public_h = [
   'shumate-coordinate.h',
+  'shumate-compass.h',
   'shumate-file-cache.h',
   'shumate-layer.h',
   'shumate-license.h',
@@ -27,6 +28,7 @@ libshumate_private_h = [
 
 libshumate_sources = [
   'shumate-coordinate.c',
+  'shumate-compass.c',
   'shumate-file-cache.c',
   'shumate-kinetic-scrolling.c',
   'shumate-layer.c',
diff --git a/shumate/shumate-compass.c b/shumate/shumate-compass.c
new file mode 100644
index 0000000..7fdc96c
--- /dev/null
+++ b/shumate/shumate-compass.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2020 Collabora Ltd. (https://www.collabora.com)
+ * Copyright (C) 2020 Corentin Noël <corentin noel collabora 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
+ */
+
+/**
+ * SECTION:shumate-compass
+ * @short_description: A widget displaying a compass.
+ *
+ * A widget displaying a compass.
+ *
+ * # CSS nodes
+ *
+ * |[<!-- language="plain" -->
+ * map-compass
+ * ├── revealer
+ * ├──── image
+ * ]|
+ *
+ * ShumateCompass uses a single CSS node with name map-compass. It also uses an
+ * image named "map-compass".
+ */
+
+#include "config.h"
+
+#include "shumate-compass.h"
+
+struct _ShumateCompass
+{
+  GtkWidget parent_instance;
+
+  ShumateViewport *viewport;
+  GtkWidget *revealer;
+  GtkWidget *image;
+  double rotation;
+};
+
+G_DEFINE_TYPE (ShumateCompass, shumate_compass, GTK_TYPE_WIDGET)
+
+enum
+{
+  PROP_VIEWPORT = 1,
+  N_PROPERTIES,
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+static void
+shumate_compass_on_rotation_changed (ShumateCompass *self)
+{
+  double rotation = shumate_viewport_get_rotation (self->viewport);
+  if (rotation != 0)
+    {
+      self->rotation = rotation;
+      gtk_widget_queue_draw (GTK_WIDGET (self));
+    }
+
+  gtk_revealer_set_reveal_child (GTK_REVEALER (self->revealer), rotation != 0);
+}
+
+static void
+on_viewport_props_changed (ShumateCompass *self,
+                           G_GNUC_UNUSED GParamSpec *pspec,
+                           ShumateViewport *viewport)
+{
+  shumate_compass_on_rotation_changed (self);
+}
+
+static void
+shumate_compass_dispose (GObject *object)
+{
+  ShumateCompass *self = (ShumateCompass *)object;
+
+  g_clear_object (&self->viewport);
+  g_clear_pointer (&self->revealer, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (shumate_compass_parent_class)->dispose (object);
+}
+
+static void
+shumate_compass_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  ShumateCompass *self = SHUMATE_COMPASS (object);
+
+  switch (prop_id)
+    {
+    case PROP_VIEWPORT:
+      g_value_set_object (value, self->viewport);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+shumate_compass_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  ShumateCompass *self = SHUMATE_COMPASS (object);
+
+  switch (prop_id)
+    {
+    case PROP_VIEWPORT:
+      shumate_compass_set_viewport (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+shumate_compass_snapshot (GtkWidget   *widget,
+                          GtkSnapshot *snapshot)
+{
+  ShumateCompass *self = SHUMATE_COMPASS (widget);
+  graphene_point_t p;
+
+  p.x = gtk_widget_get_width (widget) / 2;
+  p.y = gtk_widget_get_height (widget) / 2;
+
+  gtk_snapshot_save (snapshot);
+  gtk_snapshot_translate (snapshot, &p);
+  gtk_snapshot_rotate (snapshot, self->rotation * 180 / G_PI);
+  p.x = -p.x;
+  p.y = -p.y;
+  gtk_snapshot_translate (snapshot, &p);
+  GTK_WIDGET_CLASS (shumate_compass_parent_class)->snapshot (widget, snapshot);
+  gtk_snapshot_restore (snapshot);
+}
+
+static void
+shumate_compass_class_init (ShumateCompassClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GdkDisplay *display;
+
+  object_class->dispose = shumate_compass_dispose;
+  object_class->get_property = shumate_compass_get_property;
+  object_class->set_property = shumate_compass_set_property;
+
+  widget_class->snapshot = shumate_compass_snapshot;
+
+  /**
+   * ShumateCompass:viewport:
+   *
+   * The viewport to use.
+   */
+  obj_properties[PROP_VIEWPORT] =
+    g_param_spec_object ("viewport",
+                         "The viewport",
+                         "The viewport",
+                         SHUMATE_TYPE_VIEWPORT,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
+
+  gtk_widget_class_set_css_name (widget_class, g_intern_static_string ("map-compass"));
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+
+  display = gdk_display_get_default ();
+  if (display)
+    {
+      GtkIconTheme *icon_theme;
+      g_autoptr(GtkCssProvider) provider = gtk_css_provider_new ();
+      gtk_css_provider_load_from_resource (provider, "/org/gnome/shumate/compass.css");
+      gtk_style_context_add_provider_for_display (display,
+                                                  GTK_STYLE_PROVIDER (provider),
+                                                  GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
+      icon_theme = gtk_icon_theme_get_for_display (display);
+      gtk_icon_theme_add_resource_path (icon_theme, "/org/gnome/shumate/icons");
+    }
+}
+
+static void
+shumate_compass_init (ShumateCompass *self)
+{
+  self->revealer = gtk_revealer_new ();
+  gtk_revealer_set_transition_type (GTK_REVEALER (self->revealer), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
+  gtk_widget_insert_after (self->revealer, GTK_WIDGET (self), NULL);
+  self->image = gtk_image_new_from_icon_name ("map-compass");
+  gtk_revealer_set_child (GTK_REVEALER (self->revealer), self->image);
+}
+
+/**
+ * shumate_compass_new:
+ * @viewport: (nullable): a #ShumateViewport
+ *
+ * Creates an instance of #ShumateCompass.
+ *
+ * Returns: a new #ShumateCompass.
+ */
+ShumateCompass *
+shumate_compass_new (ShumateViewport *viewport)
+{
+  return SHUMATE_COMPASS (g_object_new (SHUMATE_TYPE_COMPASS,
+                                        "viewport", viewport,
+                                        NULL));
+}
+
+/**
+ * shumate_compass_set_viewport:
+ * @compass: a #ShumateCompass
+ * @viewport: (nullable): a #ShumateViewport
+ *
+ * Sets the compass viewport.
+ */
+void
+shumate_compass_set_viewport (ShumateCompass  *compass,
+                              ShumateViewport *viewport)
+{
+  g_return_if_fail (SHUMATE_IS_COMPASS (compass));
+
+  if (compass->viewport)
+    g_signal_handlers_disconnect_by_data (compass->viewport, compass);
+
+  if (g_set_object (&compass->viewport, viewport))
+    {
+      g_object_notify_by_pspec(G_OBJECT (compass), obj_properties[PROP_VIEWPORT]);
+      if (compass->viewport)
+        {
+          g_signal_connect_swapped (compass->viewport, "notify::rotation", G_CALLBACK 
(on_viewport_props_changed), compass);
+          shumate_compass_on_rotation_changed (compass);
+        }
+    }
+}
+
+/**
+ * shumate_compass_get_viewport:
+ * @compass: a #ShumateCompass
+ *
+ * Gets the viewport used by the compass.
+ *
+ * Returns: (transfer none) (nullable): The #ShumateViewport used by the compass
+ */
+ShumateViewport *
+shumate_compass_get_viewport (ShumateCompass *compass)
+{
+  g_return_val_if_fail (SHUMATE_IS_COMPASS (compass), NULL);
+
+  return compass->viewport;
+}
diff --git a/shumate/shumate-compass.h b/shumate/shumate-compass.h
new file mode 100644
index 0000000..6765214
--- /dev/null
+++ b/shumate/shumate-compass.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 Collabora Ltd. (https://www.collabora.com)
+ * Copyright (C) 2021 Corentin Noël <corentin noel collabora 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 (__SHUMATE_SHUMATE_H_INSIDE__) && !defined (SHUMATE_COMPILATION)
+#error "Only <shumate/shumate.h> can be included directly."
+#endif
+
+#ifndef SHUMATE_COMPASS_H
+#define SHUMATE_COMPASS_H
+
+#include <shumate/shumate-viewport.h>
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SHUMATE_TYPE_COMPASS (shumate_compass_get_type())
+
+G_DECLARE_FINAL_TYPE (ShumateCompass, shumate_compass, SHUMATE, COMPASS, GtkWidget)
+
+ShumateCompass *shumate_compass_new (ShumateViewport *viewport);
+
+ShumateViewport *shumate_compass_get_viewport (ShumateCompass *compass);
+void shumate_compass_set_viewport (ShumateCompass  *compass,
+                                   ShumateViewport *viewport);
+
+G_END_DECLS
+
+#endif
diff --git a/shumate/shumate.h b/shumate/shumate.h
index dc4d3dc..0486d1a 100644
--- a/shumate/shumate.h
+++ b/shumate/shumate.h
@@ -36,6 +36,7 @@
 #include "shumate/shumate-point.h"
 #include "shumate/shumate-location.h"
 #include "shumate/shumate-coordinate.h"
+#include "shumate/shumate-compass.h"
 #include "shumate/shumate-marker.h"
 #include "shumate/shumate-map.h"
 #include "shumate/shumate-viewport.h"


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