Commit 2b2e1870 authored by Corentin Noël's avatar Corentin Noël Committed by Marcus Lundblad
Browse files

compass: Add ShumateCompass

A simple widget to show the north when doing a rotation of the map.
parent b4e96a2e
Pipeline #309373 passed with stages
in 2 minutes and 40 seconds
map-compass image {
padding: 3px;
-gtk-icon-size: 32px;
}
map-compass {
margin: 6px;
}
<?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>
<?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>
......@@ -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);
......
......@@ -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>
......
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',
......
/*
* 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;
}
/*
* 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
......@@ -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"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment