1 /* dzl-shortcuts-shortcut.c
2 *
3 * Copyright (C) 2015 Christian Hergert <christian@hergert.me>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * 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 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <glib/gi18n.h>
20
21 #include "config.h"
22
23 #include "shortcuts/dzl-shortcut-label.h"
24 #include "shortcuts/dzl-shortcuts-shortcut.h"
25 #include "shortcuts/dzl-shortcuts-window-private.h"
26
27 /**
28 * SECTION:dzl-shortcuts-shortcut
29 * @Title: DzlShortcutsShortcut
30 * @Short_description: Represents a keyboard shortcut in a DzlShortcutsWindow
31 *
32 * A DzlShortcutsShortcut represents a single keyboard shortcut or gesture
33 * with a short text. This widget is only meant to be used with #DzlShortcutsWindow.
34 */
35
36 struct _DzlShortcutsShortcut
37 {
38 GtkBox parent_instance;
39
40 GtkImage *image;
41 DzlShortcutLabel *accelerator;
42 GtkLabel *title;
43 GtkLabel *subtitle;
44 GtkLabel *title_box;
45
46 GtkSizeGroup *accel_size_group;
47 GtkSizeGroup *title_size_group;
48
49 gboolean subtitle_set;
50 gboolean icon_set;
51 GtkTextDirection direction;
52 gchar *action_name;
53 GtkShortcutType shortcut_type;
54 };
55
56 struct _DzlShortcutsShortcutClass
57 {
58 GtkBoxClass parent_class;
59 };
60
61 G_DEFINE_TYPE (DzlShortcutsShortcut, dzl_shortcuts_shortcut, GTK_TYPE_BOX)
62
63 enum {
64 PROP_0,
65 PROP_ACCELERATOR,
66 PROP_ICON,
67 PROP_ICON_SET,
68 PROP_TITLE,
69 PROP_SUBTITLE,
70 PROP_SUBTITLE_SET,
71 PROP_ACCEL_SIZE_GROUP,
72 PROP_TITLE_SIZE_GROUP,
73 PROP_DIRECTION,
74 PROP_SHORTCUT_TYPE,
75 PROP_ACTION_NAME,
76 LAST_PROP
77 };
78
79 static GParamSpec *properties[LAST_PROP];
80
81 static void
dzl_shortcuts_shortcut_set_accelerator(DzlShortcutsShortcut * self,const gchar * accelerator)82 dzl_shortcuts_shortcut_set_accelerator (DzlShortcutsShortcut *self,
83 const gchar *accelerator)
84 {
85 dzl_shortcut_label_set_accelerator (self->accelerator, accelerator);
86 }
87
88 static void
dzl_shortcuts_shortcut_set_accel_size_group(DzlShortcutsShortcut * self,GtkSizeGroup * group)89 dzl_shortcuts_shortcut_set_accel_size_group (DzlShortcutsShortcut *self,
90 GtkSizeGroup *group)
91 {
92 if (self->accel_size_group)
93 {
94 gtk_size_group_remove_widget (self->accel_size_group, GTK_WIDGET (self->accelerator));
95 gtk_size_group_remove_widget (self->accel_size_group, GTK_WIDGET (self->image));
96 }
97
98 if (group)
99 {
100 gtk_size_group_add_widget (group, GTK_WIDGET (self->accelerator));
101 gtk_size_group_add_widget (group, GTK_WIDGET (self->image));
102 }
103
104 g_set_object (&self->accel_size_group, group);
105 }
106
107 static void
dzl_shortcuts_shortcut_set_title_size_group(DzlShortcutsShortcut * self,GtkSizeGroup * group)108 dzl_shortcuts_shortcut_set_title_size_group (DzlShortcutsShortcut *self,
109 GtkSizeGroup *group)
110 {
111 if (self->title_size_group)
112 gtk_size_group_remove_widget (self->title_size_group, GTK_WIDGET (self->title_box));
113 if (group)
114 gtk_size_group_add_widget (group, GTK_WIDGET (self->title_box));
115
116 g_set_object (&self->title_size_group, group);
117 }
118
119 static void
update_subtitle_from_type(DzlShortcutsShortcut * self)120 update_subtitle_from_type (DzlShortcutsShortcut *self)
121 {
122 const gchar *subtitle;
123
124 if (self->subtitle_set)
125 return;
126
127 switch (self->shortcut_type)
128 {
129 case GTK_SHORTCUT_ACCELERATOR:
130 case GTK_SHORTCUT_GESTURE:
131 subtitle = NULL;
132 break;
133
134 case GTK_SHORTCUT_GESTURE_PINCH:
135 subtitle = _("Two finger pinch");
136 break;
137
138 case GTK_SHORTCUT_GESTURE_STRETCH:
139 subtitle = _("Two finger stretch");
140 break;
141
142 case GTK_SHORTCUT_GESTURE_ROTATE_CLOCKWISE:
143 subtitle = _("Rotate clockwise");
144 break;
145
146 case GTK_SHORTCUT_GESTURE_ROTATE_COUNTERCLOCKWISE:
147 subtitle = _("Rotate counterclockwise");
148 break;
149
150 case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_LEFT:
151 subtitle = _("Two finger swipe left");
152 break;
153
154 case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_RIGHT:
155 subtitle = _("Two finger swipe right");
156 break;
157
158 default:
159 subtitle = NULL;
160 break;
161 }
162
163 gtk_label_set_label (self->subtitle, subtitle);
164 gtk_widget_set_visible (GTK_WIDGET (self->subtitle), subtitle != NULL);
165 g_object_notify (G_OBJECT (self), "subtitle");
166 }
167
168 static void
dzl_shortcuts_shortcut_set_subtitle_set(DzlShortcutsShortcut * self,gboolean subtitle_set)169 dzl_shortcuts_shortcut_set_subtitle_set (DzlShortcutsShortcut *self,
170 gboolean subtitle_set)
171 {
172 if (self->subtitle_set != subtitle_set)
173 {
174 self->subtitle_set = subtitle_set;
175 g_object_notify (G_OBJECT (self), "subtitle-set");
176 }
177 update_subtitle_from_type (self);
178 }
179
180 static void
dzl_shortcuts_shortcut_set_subtitle(DzlShortcutsShortcut * self,const gchar * subtitle)181 dzl_shortcuts_shortcut_set_subtitle (DzlShortcutsShortcut *self,
182 const gchar *subtitle)
183 {
184 gtk_label_set_label (self->subtitle, subtitle);
185 gtk_widget_set_visible (GTK_WIDGET (self->subtitle), subtitle && subtitle[0]);
186 dzl_shortcuts_shortcut_set_subtitle_set (self, subtitle && subtitle[0]);
187
188 g_object_notify (G_OBJECT (self), "subtitle");
189 }
190
191 static void
update_icon_from_type(DzlShortcutsShortcut * self)192 update_icon_from_type (DzlShortcutsShortcut *self)
193 {
194 GIcon *icon;
195
196 if (self->icon_set)
197 return;
198
199 switch (self->shortcut_type)
200 {
201 case GTK_SHORTCUT_GESTURE_PINCH:
202 icon = g_themed_icon_new ("gesture-pinch-symbolic");
203 break;
204
205 case GTK_SHORTCUT_GESTURE_STRETCH:
206 icon = g_themed_icon_new ("gesture-stretch-symbolic");
207 break;
208
209 case GTK_SHORTCUT_GESTURE_ROTATE_CLOCKWISE:
210 icon = g_themed_icon_new ("gesture-rotate-clockwise-symbolic");
211 break;
212
213 case GTK_SHORTCUT_GESTURE_ROTATE_COUNTERCLOCKWISE:
214 icon = g_themed_icon_new ("gesture-rotate-anticlockwise-symbolic");
215 break;
216
217 case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_LEFT:
218 icon = g_themed_icon_new ("gesture-two-finger-swipe-left-symbolic");
219 break;
220
221 case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_RIGHT:
222 icon = g_themed_icon_new ("gesture-two-finger-swipe-right-symbolic");
223 break;
224
225 case GTK_SHORTCUT_ACCELERATOR:
226 case GTK_SHORTCUT_GESTURE:
227 default: ;
228 icon = NULL;
229 break;
230 }
231
232 if (icon)
233 {
234 gtk_image_set_from_gicon (self->image, icon, GTK_ICON_SIZE_DIALOG);
235 gtk_image_set_pixel_size (self->image, 64);
236 g_object_unref (icon);
237 }
238 }
239
240 static void
dzl_shortcuts_shortcut_set_icon_set(DzlShortcutsShortcut * self,gboolean icon_set)241 dzl_shortcuts_shortcut_set_icon_set (DzlShortcutsShortcut *self,
242 gboolean icon_set)
243 {
244 if (self->icon_set != icon_set)
245 {
246 self->icon_set = icon_set;
247 g_object_notify (G_OBJECT (self), "icon-set");
248 }
249 update_icon_from_type (self);
250 }
251
252 static void
dzl_shortcuts_shortcut_set_icon(DzlShortcutsShortcut * self,GIcon * gicon)253 dzl_shortcuts_shortcut_set_icon (DzlShortcutsShortcut *self,
254 GIcon *gicon)
255 {
256 gtk_image_set_from_gicon (self->image, gicon, GTK_ICON_SIZE_DIALOG);
257 dzl_shortcuts_shortcut_set_icon_set (self, gicon != NULL);
258 g_object_notify (G_OBJECT (self), "icon");
259 }
260
261 static void
update_visible_from_direction(DzlShortcutsShortcut * self)262 update_visible_from_direction (DzlShortcutsShortcut *self)
263 {
264 if (self->direction == GTK_TEXT_DIR_NONE ||
265 self->direction == gtk_widget_get_direction (GTK_WIDGET (self)))
266 {
267 gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
268 /* When porting to gtk4, we'll have to update all this
269 * code anyway, so fine to disable warnings.
270 */
271 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
272 gtk_widget_set_no_show_all (GTK_WIDGET (self), FALSE);
273 G_GNUC_END_IGNORE_DEPRECATIONS;
274 }
275 else
276 {
277 gtk_widget_set_visible (GTK_WIDGET (self), FALSE);
278 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
279 gtk_widget_set_no_show_all (GTK_WIDGET (self), TRUE);
280 G_GNUC_END_IGNORE_DEPRECATIONS;
281 }
282 }
283
284 static void
dzl_shortcuts_shortcut_set_direction(DzlShortcutsShortcut * self,GtkTextDirection direction)285 dzl_shortcuts_shortcut_set_direction (DzlShortcutsShortcut *self,
286 GtkTextDirection direction)
287 {
288 if (self->direction == direction)
289 return;
290
291 self->direction = direction;
292
293 update_visible_from_direction (self);
294
295 g_object_notify (G_OBJECT (self), "direction");
296 }
297
298 static void
dzl_shortcuts_shortcut_direction_changed(GtkWidget * widget,GtkTextDirection previous_dir)299 dzl_shortcuts_shortcut_direction_changed (GtkWidget *widget,
300 GtkTextDirection previous_dir)
301 {
302 update_visible_from_direction (DZL_SHORTCUTS_SHORTCUT (widget));
303
304 GTK_WIDGET_CLASS (dzl_shortcuts_shortcut_parent_class)->direction_changed (widget, previous_dir);
305 }
306
307 static void
dzl_shortcuts_shortcut_set_type(DzlShortcutsShortcut * self,GtkShortcutType type)308 dzl_shortcuts_shortcut_set_type (DzlShortcutsShortcut *self,
309 GtkShortcutType type)
310 {
311 if (self->shortcut_type == type)
312 return;
313
314 self->shortcut_type = type;
315
316 update_subtitle_from_type (self);
317 update_icon_from_type (self);
318
319 gtk_widget_set_visible (GTK_WIDGET (self->accelerator), type == GTK_SHORTCUT_ACCELERATOR);
320 gtk_widget_set_visible (GTK_WIDGET (self->image), type != GTK_SHORTCUT_ACCELERATOR);
321
322
323 g_object_notify (G_OBJECT (self), "shortcut-type");
324 }
325
326 static void
dzl_shortcuts_shortcut_set_action_name(DzlShortcutsShortcut * self,const gchar * action_name)327 dzl_shortcuts_shortcut_set_action_name (DzlShortcutsShortcut *self,
328 const gchar *action_name)
329 {
330 g_free (self->action_name);
331 self->action_name = g_strdup (action_name);
332
333 g_object_notify (G_OBJECT (self), "action-name");
334 }
335
336 static void
dzl_shortcuts_shortcut_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)337 dzl_shortcuts_shortcut_get_property (GObject *object,
338 guint prop_id,
339 GValue *value,
340 GParamSpec *pspec)
341 {
342 DzlShortcutsShortcut *self = DZL_SHORTCUTS_SHORTCUT (object);
343
344 switch (prop_id)
345 {
346 case PROP_TITLE:
347 g_value_set_string (value, gtk_label_get_label (self->title));
348 break;
349
350 case PROP_SUBTITLE:
351 g_value_set_string (value, gtk_label_get_label (self->subtitle));
352 break;
353
354 case PROP_SUBTITLE_SET:
355 g_value_set_boolean (value, self->subtitle_set);
356 break;
357
358 case PROP_ACCELERATOR:
359 g_value_set_string (value, dzl_shortcut_label_get_accelerator (self->accelerator));
360 break;
361
362 case PROP_ICON:
363 {
364 GIcon *icon;
365
366 gtk_image_get_gicon (self->image, &icon, NULL);
367 g_value_set_object (value, icon);
368 }
369 break;
370
371 case PROP_ICON_SET:
372 g_value_set_boolean (value, self->icon_set);
373 break;
374
375 case PROP_DIRECTION:
376 g_value_set_enum (value, self->direction);
377 break;
378
379 case PROP_SHORTCUT_TYPE:
380 g_value_set_enum (value, self->shortcut_type);
381 break;
382
383 case PROP_ACTION_NAME:
384 g_value_set_string (value, self->action_name);
385 break;
386
387 default:
388 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
389 }
390 }
391
392 static void
dzl_shortcuts_shortcut_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)393 dzl_shortcuts_shortcut_set_property (GObject *object,
394 guint prop_id,
395 const GValue *value,
396 GParamSpec *pspec)
397 {
398 DzlShortcutsShortcut *self = DZL_SHORTCUTS_SHORTCUT (object);
399
400 switch (prop_id)
401 {
402 case PROP_ACCELERATOR:
403 dzl_shortcuts_shortcut_set_accelerator (self, g_value_get_string (value));
404 break;
405
406 case PROP_ICON:
407 dzl_shortcuts_shortcut_set_icon (self, g_value_get_object (value));
408 break;
409
410 case PROP_ICON_SET:
411 dzl_shortcuts_shortcut_set_icon_set (self, g_value_get_boolean (value));
412 break;
413
414 case PROP_ACCEL_SIZE_GROUP:
415 dzl_shortcuts_shortcut_set_accel_size_group (self, GTK_SIZE_GROUP (g_value_get_object (value)));
416 break;
417
418 case PROP_TITLE:
419 gtk_label_set_label (self->title, g_value_get_string (value));
420 break;
421
422 case PROP_SUBTITLE:
423 dzl_shortcuts_shortcut_set_subtitle (self, g_value_get_string (value));
424 break;
425
426 case PROP_SUBTITLE_SET:
427 dzl_shortcuts_shortcut_set_subtitle_set (self, g_value_get_boolean (value));
428 break;
429
430 case PROP_TITLE_SIZE_GROUP:
431 dzl_shortcuts_shortcut_set_title_size_group (self, GTK_SIZE_GROUP (g_value_get_object (value)));
432 break;
433
434 case PROP_DIRECTION:
435 dzl_shortcuts_shortcut_set_direction (self, g_value_get_enum (value));
436 break;
437
438 case PROP_SHORTCUT_TYPE:
439 dzl_shortcuts_shortcut_set_type (self, g_value_get_enum (value));
440 break;
441
442 case PROP_ACTION_NAME:
443 dzl_shortcuts_shortcut_set_action_name (self, g_value_get_string (value));
444 break;
445
446 default:
447 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
448 break;
449 }
450 }
451
452 static void
dzl_shortcuts_shortcut_finalize(GObject * object)453 dzl_shortcuts_shortcut_finalize (GObject *object)
454 {
455 DzlShortcutsShortcut *self = DZL_SHORTCUTS_SHORTCUT (object);
456
457 g_clear_object (&self->accel_size_group);
458 g_clear_object (&self->title_size_group);
459 g_free (self->action_name);
460
461 G_OBJECT_CLASS (dzl_shortcuts_shortcut_parent_class)->finalize (object);
462 }
463
464 static void
dzl_shortcuts_shortcut_add(GtkContainer * container,GtkWidget * widget)465 dzl_shortcuts_shortcut_add (GtkContainer *container,
466 GtkWidget *widget)
467 {
468 g_warning ("Can't add children to %s", G_OBJECT_TYPE_NAME (container));
469 }
470
471 static GType
dzl_shortcuts_shortcut_child_type(GtkContainer * container)472 dzl_shortcuts_shortcut_child_type (GtkContainer *container)
473 {
474 return G_TYPE_NONE;
475 }
476
477 void
dzl_shortcuts_shortcut_update_accel(DzlShortcutsShortcut * self,GtkWindow * window)478 dzl_shortcuts_shortcut_update_accel (DzlShortcutsShortcut *self,
479 GtkWindow *window)
480 {
481 GtkApplication *app;
482 gchar **accels;
483 gchar *str;
484
485 if (self->action_name == NULL)
486 return;
487
488 app = gtk_window_get_application (window);
489 if (app == NULL)
490 return;
491
492 accels = gtk_application_get_accels_for_action (app, self->action_name);
493 str = g_strjoinv (" ", accels);
494
495 dzl_shortcuts_shortcut_set_accelerator (self, str);
496
497 g_free (str);
498 g_strfreev (accels);
499 }
500
501 static void
dzl_shortcuts_shortcut_class_init(DzlShortcutsShortcutClass * klass)502 dzl_shortcuts_shortcut_class_init (DzlShortcutsShortcutClass *klass)
503 {
504 GObjectClass *object_class = G_OBJECT_CLASS (klass);
505 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
506 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
507
508 object_class->finalize = dzl_shortcuts_shortcut_finalize;
509 object_class->get_property = dzl_shortcuts_shortcut_get_property;
510 object_class->set_property = dzl_shortcuts_shortcut_set_property;
511
512 widget_class->direction_changed = dzl_shortcuts_shortcut_direction_changed;
513
514 container_class->add = dzl_shortcuts_shortcut_add;
515 container_class->child_type = dzl_shortcuts_shortcut_child_type;
516
517 /**
518 * DzlShortcutsShortcut:accelerator:
519 *
520 * The accelerator(s) represented by this object. This property is used
521 * if #DzlShortcutsShortcut:shortcut-type is set to #GTK_SHORTCUT_ACCELERATOR.
522 *
523 * The syntax of this property is (an extension of) the syntax understood by
524 * gtk_accelerator_parse(). Multiple accelerators can be specified by separating
525 * them with a space, but keep in mind that the available width is limited.
526 * It is also possible to specify ranges of shortcuts, using ... between the keys.
527 * Sequences of keys can be specified using a + or & between the keys.
528 *
529 * Examples:
530 * - A single shortcut: <ctl><alt>delete
531 * - Two alternative shortcuts: <shift>a Home
532 * - A range of shortcuts: <alt>1...<alt>9
533 * - Several keys pressed together: Control_L&Control_R
534 * - A sequence of shortcuts or keys: <ctl>c+<ctl>x
535 *
536 * Use + instead of & when the keys may (or have to be) pressed sequentially (e.g
537 * use t+t for 'press the t key twice').
538 *
539 * Note that <, > and & need to be escaped as <, > and & when used
540 * in .ui files.
541 */
542 properties[PROP_ACCELERATOR] =
543 g_param_spec_string ("accelerator",
544 "Accelerator",
545 "The accelerator keys for shortcuts of type 'Accelerator'",
546 NULL,
547 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
548
549 /**
550 * DzlShortcutsShortcut:icon:
551 *
552 * An icon to represent the shortcut or gesture. This property is used if
553 * #DzlShortcutsShortcut:shortcut-type is set to #GTK_SHORTCUT_GESTURE.
554 * For the other predefined gesture types, GTK+ provides an icon on its own.
555 */
556 properties[PROP_ICON] =
557 g_param_spec_object ("icon",
558 "Icon",
559 "The icon to show for shortcuts of type 'Other Gesture'",
560 G_TYPE_ICON,
561 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
562
563 /**
564 * DzlShortcutsShortcut:icon-set:
565 *
566 * %TRUE if an icon has been set.
567 */
568 properties[PROP_ICON_SET] =
569 g_param_spec_boolean ("icon-set",
570 "Icon Set",
571 "Whether an icon has been set",
572 FALSE,
573 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
574
575 /**
576 * DzlShortcutsShortcut:title:
577 *
578 * The textual description for the shortcut or gesture represented by
579 * this object. This should be a short string that can fit in a single line.
580 */
581 properties[PROP_TITLE] =
582 g_param_spec_string ("title",
583 "Title",
584 "A short description for the shortcut",
585 "",
586 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
587
588 /**
589 * DzlShortcutsShortcut:subtitle:
590 *
591 * The subtitle for the shortcut or gesture.
592 *
593 * This is typically used for gestures and should be a short, one-line
594 * text that describes the gesture itself. For the predefined gesture
595 * types, GTK+ provides a subtitle on its own.
596 */
597 properties[PROP_SUBTITLE] =
598 g_param_spec_string ("subtitle",
599 "Subtitle",
600 "A short description for the gesture",
601 "",
602 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
603
604 /**
605 * DzlShortcutsShortcut:subtitle-set:
606 *
607 * %TRUE if a subtitle has been set.
608 */
609 properties[PROP_SUBTITLE_SET] =
610 g_param_spec_boolean ("subtitle-set",
611 "Subtitle Set",
612 "Whether a subtitle has been set",
613 FALSE,
614 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
615
616 /**
617 * DzlShortcutsShortcut:accel-size-group:
618 *
619 * The size group for the accelerator portion of this shortcut.
620 *
621 * This is used internally by GTK+, and must not be modified by applications.
622 */
623 properties[PROP_ACCEL_SIZE_GROUP] =
624 g_param_spec_object ("accel-size-group",
625 "Accelerator Size Group",
626 "Accelerator Size Group",
627 GTK_TYPE_SIZE_GROUP,
628 (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
629
630 /**
631 * DzlShortcutsShortcut:title-size-group:
632 *
633 * The size group for the textual portion of this shortcut.
634 *
635 * This is used internally by GTK+, and must not be modified by applications.
636 */
637 properties[PROP_TITLE_SIZE_GROUP] =
638 g_param_spec_object ("title-size-group",
639 "Title Size Group",
640 "Title Size Group",
641 GTK_TYPE_SIZE_GROUP,
642 (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
643
644 /**
645 * DzlShortcutsShortcut:direction:
646 *
647 * The text direction for which this shortcut is active. If the shortcut
648 * is used regardless of the text direction, set this property to
649 * #GTK_TEXT_DIR_NONE.
650 */
651 properties[PROP_DIRECTION] =
652 g_param_spec_enum ("direction",
653 "Direction",
654 "Text direction for which this shortcut is active",
655 GTK_TYPE_TEXT_DIRECTION,
656 GTK_TEXT_DIR_NONE,
657 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
658
659 /**
660 * DzlShortcutsShortcut:shortcut-type:
661 *
662 * The type of shortcut that is represented.
663 */
664 properties[PROP_SHORTCUT_TYPE] =
665 g_param_spec_enum ("shortcut-type",
666 "Shortcut Type",
667 "The type of shortcut that is represented",
668 GTK_TYPE_SHORTCUT_TYPE,
669 GTK_SHORTCUT_ACCELERATOR,
670 (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
671
672 /**
673 * DzlShortcutsShortcut:action-name:
674 *
675 * A detailed action name. If this is set for a shortcut
676 * of type %GTK_SHORTCUT_ACCELERATOR, then GTK+ will use
677 * the accelerators that are associated with the action
678 * via gtk_application_set_accels_for_action(), and setting
679 * #DzlShortcutsShortcut::accelerator is not necessary.
680 *
681 * Since: 3.22
682 */
683 properties[PROP_ACTION_NAME] =
684 g_param_spec_string ("action-name",
685 "Action Name",
686 "The name of the action",
687 NULL,
688 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
689
690 g_object_class_install_properties (object_class, LAST_PROP, properties);
691 gtk_widget_class_set_css_name (widget_class, "shortcut");
692 }
693
694 static void
dzl_shortcuts_shortcut_init(DzlShortcutsShortcut * self)695 dzl_shortcuts_shortcut_init (DzlShortcutsShortcut *self)
696 {
697 gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL);
698 gtk_box_set_spacing (GTK_BOX (self), 12);
699
700 self->direction = GTK_TEXT_DIR_NONE;
701 self->shortcut_type = GTK_SHORTCUT_ACCELERATOR;
702
703 self->image = g_object_new (GTK_TYPE_IMAGE,
704 "visible", FALSE,
705 "valign", GTK_ALIGN_CENTER,
706 "no-show-all", TRUE,
707 NULL);
708 GTK_CONTAINER_CLASS (dzl_shortcuts_shortcut_parent_class)->add (GTK_CONTAINER (self), GTK_WIDGET (self->image));
709
710 self->accelerator = g_object_new (DZL_TYPE_SHORTCUT_LABEL,
711 "visible", TRUE,
712 "valign", GTK_ALIGN_CENTER,
713 "no-show-all", TRUE,
714 NULL);
715 GTK_CONTAINER_CLASS (dzl_shortcuts_shortcut_parent_class)->add (GTK_CONTAINER (self), GTK_WIDGET (self->accelerator));
716
717 self->title_box = g_object_new (GTK_TYPE_BOX,
718 "visible", TRUE,
719 "valign", GTK_ALIGN_CENTER,
720 "hexpand", TRUE,
721 "orientation", GTK_ORIENTATION_VERTICAL,
722 NULL);
723 GTK_CONTAINER_CLASS (dzl_shortcuts_shortcut_parent_class)->add (GTK_CONTAINER (self), GTK_WIDGET (self->title_box));
724
725 self->title = g_object_new (GTK_TYPE_LABEL,
726 "visible", TRUE,
727 "xalign", 0.0f,
728 NULL);
729 gtk_container_add (GTK_CONTAINER (self->title_box), GTK_WIDGET (self->title));
730
731 self->subtitle = g_object_new (GTK_TYPE_LABEL,
732 "visible", FALSE,
733 "no-show-all", TRUE,
734 "xalign", 0.0f,
735 NULL);
736 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self->subtitle)),
737 GTK_STYLE_CLASS_DIM_LABEL);
738 gtk_container_add (GTK_CONTAINER (self->title_box), GTK_WIDGET (self->subtitle));
739 }
740