Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2020 Collabora Ltd. (https://www.collabora.com)
3 : : * Copyright (C) 2020 Corentin Noël <corentin.noel@collabora.com>
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2.1 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 : : */
19 : :
20 : : /**
21 : : * ShumateCompass:
22 : : *
23 : : * A widget displaying a compass.
24 : : *
25 : : * # CSS nodes
26 : : *
27 : : * ```
28 : : * map-compass
29 : : * ├── revealer
30 : : * ├──── image
31 : : * ```
32 : : *
33 : : * `ShumateCompass` uses a single CSS node with name map-compass. It also uses an
34 : : * image named "map-compass".
35 : : */
36 : :
37 : : #include "shumate-compass.h"
38 : :
39 : : struct _ShumateCompass
40 : : {
41 : : GtkWidget parent_instance;
42 : :
43 : : ShumateViewport *viewport;
44 : : GtkWidget *revealer;
45 : : GtkWidget *image;
46 : : double rotation;
47 : : };
48 : :
49 [ + + + - ]: 4 : G_DEFINE_TYPE (ShumateCompass, shumate_compass, GTK_TYPE_WIDGET)
50 : :
51 : : enum
52 : : {
53 : : PROP_VIEWPORT = 1,
54 : : N_PROPERTIES,
55 : : };
56 : :
57 : : static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
58 : :
59 : : static void
60 : 0 : shumate_compass_on_rotation_changed (ShumateCompass *self)
61 : : {
62 : 0 : double rotation = shumate_viewport_get_rotation (self->viewport);
63 [ # # ]: 0 : if (rotation != 0)
64 : : {
65 : 0 : self->rotation = rotation;
66 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
67 : : }
68 : :
69 : 0 : gtk_revealer_set_reveal_child (GTK_REVEALER (self->revealer), rotation != 0);
70 : 0 : }
71 : :
72 : : static void
73 : 0 : on_viewport_props_changed (ShumateCompass *self,
74 : : G_GNUC_UNUSED GParamSpec *pspec,
75 : : ShumateViewport *viewport)
76 : : {
77 : 0 : shumate_compass_on_rotation_changed (self);
78 : 0 : }
79 : :
80 : : static void
81 : 0 : shumate_compass_dispose (GObject *object)
82 : : {
83 : 0 : ShumateCompass *self = (ShumateCompass *)object;
84 : :
85 [ # # ]: 0 : g_clear_object (&self->viewport);
86 [ # # ]: 0 : g_clear_pointer (&self->revealer, gtk_widget_unparent);
87 : :
88 : 0 : G_OBJECT_CLASS (shumate_compass_parent_class)->dispose (object);
89 : 0 : }
90 : :
91 : : static void
92 : 0 : shumate_compass_get_property (GObject *object,
93 : : guint prop_id,
94 : : GValue *value,
95 : : GParamSpec *pspec)
96 : : {
97 : 0 : ShumateCompass *self = SHUMATE_COMPASS (object);
98 : :
99 [ # # ]: 0 : switch (prop_id)
100 : : {
101 : 0 : case PROP_VIEWPORT:
102 : 0 : g_value_set_object (value, self->viewport);
103 : 0 : break;
104 : :
105 : 0 : default:
106 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
107 : : }
108 : 0 : }
109 : :
110 : : static void
111 : 0 : shumate_compass_set_property (GObject *object,
112 : : guint prop_id,
113 : : const GValue *value,
114 : : GParamSpec *pspec)
115 : : {
116 : 0 : ShumateCompass *self = SHUMATE_COMPASS (object);
117 : :
118 [ # # ]: 0 : switch (prop_id)
119 : : {
120 : 0 : case PROP_VIEWPORT:
121 : 0 : shumate_compass_set_viewport (self, g_value_get_object (value));
122 : 0 : break;
123 : :
124 : 0 : default:
125 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
126 : : }
127 : 0 : }
128 : :
129 : : static void
130 : 0 : shumate_compass_snapshot (GtkWidget *widget,
131 : : GtkSnapshot *snapshot)
132 : : {
133 : 0 : ShumateCompass *self = SHUMATE_COMPASS (widget);
134 : 0 : graphene_point_t p;
135 : :
136 : 0 : p.x = gtk_widget_get_width (widget) / 2;
137 : 0 : p.y = gtk_widget_get_height (widget) / 2;
138 : :
139 : 0 : gtk_snapshot_save (snapshot);
140 : 0 : gtk_snapshot_translate (snapshot, &p);
141 : 0 : gtk_snapshot_rotate (snapshot, self->rotation * 180 / G_PI);
142 : 0 : p.x = -p.x;
143 : 0 : p.y = -p.y;
144 : 0 : gtk_snapshot_translate (snapshot, &p);
145 : 0 : GTK_WIDGET_CLASS (shumate_compass_parent_class)->snapshot (widget, snapshot);
146 : 0 : gtk_snapshot_restore (snapshot);
147 : 0 : }
148 : :
149 : : static void
150 : 1 : shumate_compass_class_init (ShumateCompassClass *klass)
151 : : {
152 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
153 : 1 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
154 : 1 : GdkDisplay *display;
155 : :
156 : 1 : object_class->dispose = shumate_compass_dispose;
157 : 1 : object_class->get_property = shumate_compass_get_property;
158 : 1 : object_class->set_property = shumate_compass_set_property;
159 : :
160 : 1 : widget_class->snapshot = shumate_compass_snapshot;
161 : :
162 : : /**
163 : : * ShumateCompass:viewport:
164 : : *
165 : : * The viewport to use.
166 : : */
167 : 2 : obj_properties[PROP_VIEWPORT] =
168 : 1 : g_param_spec_object ("viewport",
169 : : "The viewport",
170 : : "The viewport",
171 : : SHUMATE_TYPE_VIEWPORT,
172 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
173 : :
174 : 1 : g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
175 : :
176 : 1 : gtk_widget_class_set_css_name (widget_class, "map-compass");
177 : 1 : gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
178 : :
179 : 1 : display = gdk_display_get_default ();
180 [ - + ]: 1 : if (display)
181 : : {
182 : 0 : GtkIconTheme *icon_theme = gtk_icon_theme_get_for_display (display);
183 : 0 : gtk_icon_theme_add_resource_path (icon_theme, "/org/gnome/shumate/icons");
184 : : }
185 : 1 : }
186 : :
187 : : static void
188 : 0 : shumate_compass_init (ShumateCompass *self)
189 : : {
190 : 0 : self->revealer = gtk_revealer_new ();
191 : 0 : gtk_revealer_set_transition_type (GTK_REVEALER (self->revealer), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
192 : 0 : gtk_widget_insert_after (self->revealer, GTK_WIDGET (self), NULL);
193 : 0 : self->image = gtk_image_new_from_icon_name ("map-compass");
194 : 0 : gtk_image_set_icon_size (GTK_IMAGE (self->image), GTK_ICON_SIZE_LARGE);
195 : 0 : gtk_revealer_set_child (GTK_REVEALER (self->revealer), self->image);
196 : 0 : }
197 : :
198 : : /**
199 : : * shumate_compass_new:
200 : : * @viewport: (nullable): a #ShumateViewport
201 : : *
202 : : * Creates an instance of #ShumateCompass.
203 : : *
204 : : * Returns: a new #ShumateCompass.
205 : : */
206 : : ShumateCompass *
207 : 0 : shumate_compass_new (ShumateViewport *viewport)
208 : : {
209 : 0 : return SHUMATE_COMPASS (g_object_new (SHUMATE_TYPE_COMPASS,
210 : : "viewport", viewport,
211 : : NULL));
212 : : }
213 : :
214 : : /**
215 : : * shumate_compass_set_viewport:
216 : : * @compass: a [class@Compass]
217 : : * @viewport: (nullable): a [class@Viewport]
218 : : *
219 : : * Sets the compass viewport.
220 : : */
221 : : void
222 : 0 : shumate_compass_set_viewport (ShumateCompass *compass,
223 : : ShumateViewport *viewport)
224 : : {
225 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_COMPASS (compass));
226 [ # # # # ]: 0 : g_return_if_fail (viewport == NULL || SHUMATE_IS_VIEWPORT (viewport));
227 : :
228 [ # # ]: 0 : if (compass->viewport == viewport)
229 : : return;
230 : :
231 [ # # ]: 0 : if (compass->viewport)
232 : 0 : g_signal_handlers_disconnect_by_data (compass->viewport, compass);
233 : :
234 : 0 : g_set_object (&compass->viewport, viewport);
235 : :
236 [ # # ]: 0 : if (compass->viewport)
237 : : {
238 : 0 : g_signal_connect_swapped (compass->viewport, "notify::rotation", G_CALLBACK (on_viewport_props_changed), compass);
239 : 0 : shumate_compass_on_rotation_changed (compass);
240 : : }
241 : :
242 : 0 : g_object_notify_by_pspec (G_OBJECT (compass), obj_properties[PROP_VIEWPORT]);
243 : : }
244 : :
245 : : /**
246 : : * shumate_compass_get_viewport:
247 : : * @compass: a #ShumateCompass
248 : : *
249 : : * Gets the viewport used by the compass.
250 : : *
251 : : * Returns: (transfer none) (nullable): The #ShumateViewport used by the compass
252 : : */
253 : : ShumateViewport *
254 : 0 : shumate_compass_get_viewport (ShumateCompass *compass)
255 : : {
256 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_COMPASS (compass), NULL);
257 : :
258 : 0 : return compass->viewport;
259 : : }
|