1 | /* gtkshortcutsshortcut.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 "config.h" |
20 | |
21 | #include "gtkshortcutsshortcutprivate.h" |
22 | |
23 | #include "gtkimage.h" |
24 | #include "gtkbox.h" |
25 | #include "gtkintl.h" |
26 | #include "gtklabel.h" |
27 | #include "gtkprivate.h" |
28 | #include "gtkwidgetprivate.h" |
29 | #include "gtkshortcutlabel.h" |
30 | #include "gtkshortcutswindowprivate.h" |
31 | #include "gtksizegroup.h" |
32 | #include "gtktypebuiltins.h" |
33 | |
34 | /** |
35 | * GtkShortcutsShortcut: |
36 | * |
37 | * A `GtkShortcutsShortcut` represents a single keyboard shortcut or gesture |
38 | * with a short text. |
39 | * |
40 | * This widget is only meant to be used with `GtkShortcutsWindow`. |
41 | */ |
42 | |
43 | struct _GtkShortcutsShortcut |
44 | { |
45 | GtkWidget parent_instance; |
46 | |
47 | GtkBox *box; |
48 | GtkImage *image; |
49 | GtkShortcutLabel *accelerator; |
50 | GtkLabel *title; |
51 | GtkLabel *subtitle; |
52 | GtkLabel *title_box; |
53 | |
54 | GtkSizeGroup *accel_size_group; |
55 | GtkSizeGroup *title_size_group; |
56 | |
57 | gboolean subtitle_set; |
58 | gboolean icon_set; |
59 | GtkTextDirection direction; |
60 | char *action_name; |
61 | GtkShortcutType shortcut_type; |
62 | }; |
63 | |
64 | struct _GtkShortcutsShortcutClass |
65 | { |
66 | GtkWidgetClass parent_class; |
67 | }; |
68 | |
69 | G_DEFINE_TYPE (GtkShortcutsShortcut, gtk_shortcuts_shortcut, GTK_TYPE_WIDGET) |
70 | |
71 | enum { |
72 | PROP_0, |
73 | PROP_ACCELERATOR, |
74 | PROP_ICON, |
75 | PROP_ICON_SET, |
76 | PROP_TITLE, |
77 | PROP_SUBTITLE, |
78 | PROP_SUBTITLE_SET, |
79 | PROP_ACCEL_SIZE_GROUP, |
80 | PROP_TITLE_SIZE_GROUP, |
81 | PROP_DIRECTION, |
82 | PROP_SHORTCUT_TYPE, |
83 | PROP_ACTION_NAME, |
84 | LAST_PROP |
85 | }; |
86 | |
87 | static GParamSpec *properties[LAST_PROP]; |
88 | |
89 | static void |
90 | gtk_shortcuts_shortcut_set_accelerator (GtkShortcutsShortcut *self, |
91 | const char *accelerator) |
92 | { |
93 | gtk_shortcut_label_set_accelerator (self: self->accelerator, accelerator); |
94 | } |
95 | |
96 | static void |
97 | gtk_shortcuts_shortcut_set_accel_size_group (GtkShortcutsShortcut *self, |
98 | GtkSizeGroup *group) |
99 | { |
100 | if (self->accel_size_group) |
101 | { |
102 | gtk_size_group_remove_widget (size_group: self->accel_size_group, GTK_WIDGET (self->accelerator)); |
103 | gtk_size_group_remove_widget (size_group: self->accel_size_group, GTK_WIDGET (self->image)); |
104 | } |
105 | |
106 | if (group) |
107 | { |
108 | gtk_size_group_add_widget (size_group: group, GTK_WIDGET (self->accelerator)); |
109 | gtk_size_group_add_widget (size_group: group, GTK_WIDGET (self->image)); |
110 | } |
111 | |
112 | g_set_object (&self->accel_size_group, group); |
113 | } |
114 | |
115 | static void |
116 | gtk_shortcuts_shortcut_set_title_size_group (GtkShortcutsShortcut *self, |
117 | GtkSizeGroup *group) |
118 | { |
119 | if (self->title_size_group) |
120 | gtk_size_group_remove_widget (size_group: self->title_size_group, GTK_WIDGET (self->title_box)); |
121 | if (group) |
122 | gtk_size_group_add_widget (size_group: group, GTK_WIDGET (self->title_box)); |
123 | |
124 | g_set_object (&self->title_size_group, group); |
125 | } |
126 | |
127 | static void |
128 | update_subtitle_from_type (GtkShortcutsShortcut *self) |
129 | { |
130 | const char *subtitle; |
131 | |
132 | if (self->subtitle_set) |
133 | return; |
134 | |
135 | switch (self->shortcut_type) |
136 | { |
137 | case GTK_SHORTCUT_ACCELERATOR: |
138 | case GTK_SHORTCUT_GESTURE: |
139 | subtitle = NULL; |
140 | break; |
141 | |
142 | case GTK_SHORTCUT_GESTURE_PINCH: |
143 | subtitle = _("Two finger pinch" ); |
144 | break; |
145 | |
146 | case GTK_SHORTCUT_GESTURE_STRETCH: |
147 | subtitle = _("Two finger stretch" ); |
148 | break; |
149 | |
150 | case GTK_SHORTCUT_GESTURE_ROTATE_CLOCKWISE: |
151 | subtitle = _("Rotate clockwise" ); |
152 | break; |
153 | |
154 | case GTK_SHORTCUT_GESTURE_ROTATE_COUNTERCLOCKWISE: |
155 | subtitle = _("Rotate counterclockwise" ); |
156 | break; |
157 | |
158 | case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_LEFT: |
159 | subtitle = _("Two finger swipe left" ); |
160 | break; |
161 | |
162 | case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_RIGHT: |
163 | subtitle = _("Two finger swipe right" ); |
164 | break; |
165 | |
166 | case GTK_SHORTCUT_GESTURE_SWIPE_LEFT: |
167 | subtitle = _("Swipe left" ); |
168 | break; |
169 | |
170 | case GTK_SHORTCUT_GESTURE_SWIPE_RIGHT: |
171 | subtitle = _("Swipe right" ); |
172 | break; |
173 | |
174 | default: |
175 | subtitle = NULL; |
176 | break; |
177 | } |
178 | |
179 | gtk_label_set_label (self: self->subtitle, str: subtitle); |
180 | gtk_widget_set_visible (GTK_WIDGET (self->subtitle), visible: subtitle != NULL); |
181 | g_object_notify (G_OBJECT (self), property_name: "subtitle" ); |
182 | } |
183 | |
184 | static void |
185 | gtk_shortcuts_shortcut_set_subtitle_set (GtkShortcutsShortcut *self, |
186 | gboolean subtitle_set) |
187 | { |
188 | if (self->subtitle_set != subtitle_set) |
189 | { |
190 | self->subtitle_set = subtitle_set; |
191 | g_object_notify (G_OBJECT (self), property_name: "subtitle-set" ); |
192 | } |
193 | update_subtitle_from_type (self); |
194 | } |
195 | |
196 | static void |
197 | gtk_shortcuts_shortcut_set_subtitle (GtkShortcutsShortcut *self, |
198 | const char *subtitle) |
199 | { |
200 | gtk_label_set_label (self: self->subtitle, str: subtitle); |
201 | gtk_widget_set_visible (GTK_WIDGET (self->subtitle), visible: subtitle && subtitle[0]); |
202 | gtk_shortcuts_shortcut_set_subtitle_set (self, subtitle_set: subtitle && subtitle[0]); |
203 | |
204 | g_object_notify (G_OBJECT (self), property_name: "subtitle" ); |
205 | } |
206 | |
207 | static void |
208 | update_icon_from_type (GtkShortcutsShortcut *self) |
209 | { |
210 | GIcon *icon; |
211 | |
212 | if (self->icon_set) |
213 | return; |
214 | |
215 | switch (self->shortcut_type) |
216 | { |
217 | case GTK_SHORTCUT_GESTURE_PINCH: |
218 | icon = g_themed_icon_new (iconname: "gesture-pinch-symbolic" ); |
219 | break; |
220 | |
221 | case GTK_SHORTCUT_GESTURE_STRETCH: |
222 | icon = g_themed_icon_new (iconname: "gesture-stretch-symbolic" ); |
223 | break; |
224 | |
225 | case GTK_SHORTCUT_GESTURE_ROTATE_CLOCKWISE: |
226 | icon = g_themed_icon_new (iconname: "gesture-rotate-clockwise-symbolic" ); |
227 | break; |
228 | |
229 | case GTK_SHORTCUT_GESTURE_ROTATE_COUNTERCLOCKWISE: |
230 | icon = g_themed_icon_new (iconname: "gesture-rotate-anticlockwise-symbolic" ); |
231 | break; |
232 | |
233 | case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_LEFT: |
234 | icon = g_themed_icon_new (iconname: "gesture-two-finger-swipe-left-symbolic" ); |
235 | break; |
236 | |
237 | case GTK_SHORTCUT_GESTURE_TWO_FINGER_SWIPE_RIGHT: |
238 | icon = g_themed_icon_new (iconname: "gesture-two-finger-swipe-right-symbolic" ); |
239 | break; |
240 | |
241 | case GTK_SHORTCUT_GESTURE_SWIPE_LEFT: |
242 | icon = g_themed_icon_new (iconname: "gesture-swipe-left-symbolic" ); |
243 | break; |
244 | |
245 | case GTK_SHORTCUT_GESTURE_SWIPE_RIGHT: |
246 | icon = g_themed_icon_new (iconname: "gesture-swipe-right-symbolic" ); |
247 | break; |
248 | |
249 | case GTK_SHORTCUT_ACCELERATOR: |
250 | case GTK_SHORTCUT_GESTURE: |
251 | default: |
252 | icon = NULL; |
253 | break; |
254 | } |
255 | |
256 | if (icon) |
257 | { |
258 | gtk_image_set_from_gicon (image: self->image, icon); |
259 | gtk_image_set_pixel_size (image: self->image, pixel_size: 64); |
260 | g_object_unref (object: icon); |
261 | } |
262 | } |
263 | |
264 | static void |
265 | gtk_shortcuts_shortcut_set_icon_set (GtkShortcutsShortcut *self, |
266 | gboolean icon_set) |
267 | { |
268 | if (self->icon_set != icon_set) |
269 | { |
270 | self->icon_set = icon_set; |
271 | g_object_notify (G_OBJECT (self), property_name: "icon-set" ); |
272 | } |
273 | update_icon_from_type (self); |
274 | } |
275 | |
276 | static void |
277 | gtk_shortcuts_shortcut_set_icon (GtkShortcutsShortcut *self, |
278 | GIcon *gicon) |
279 | { |
280 | gtk_image_set_from_gicon (image: self->image, icon: gicon); |
281 | gtk_shortcuts_shortcut_set_icon_set (self, icon_set: gicon != NULL); |
282 | g_object_notify (G_OBJECT (self), property_name: "icon" ); |
283 | } |
284 | |
285 | static void |
286 | update_visible_from_direction (GtkShortcutsShortcut *self) |
287 | { |
288 | if (self->direction == GTK_TEXT_DIR_NONE || |
289 | self->direction == gtk_widget_get_direction (GTK_WIDGET (self))) |
290 | { |
291 | gtk_widget_show (GTK_WIDGET (self)); |
292 | } |
293 | else |
294 | { |
295 | gtk_widget_hide (GTK_WIDGET (self)); |
296 | } |
297 | } |
298 | |
299 | static void |
300 | gtk_shortcuts_shortcut_set_direction (GtkShortcutsShortcut *self, |
301 | GtkTextDirection direction) |
302 | { |
303 | if (self->direction == direction) |
304 | return; |
305 | |
306 | self->direction = direction; |
307 | |
308 | update_visible_from_direction (self); |
309 | |
310 | g_object_notify (G_OBJECT (self), property_name: "direction" ); |
311 | } |
312 | |
313 | static void |
314 | gtk_shortcuts_shortcut_direction_changed (GtkWidget *widget, |
315 | GtkTextDirection previous_dir) |
316 | { |
317 | update_visible_from_direction (GTK_SHORTCUTS_SHORTCUT (widget)); |
318 | |
319 | GTK_WIDGET_CLASS (gtk_shortcuts_shortcut_parent_class)->direction_changed (widget, previous_dir); |
320 | } |
321 | |
322 | static void |
323 | gtk_shortcuts_shortcut_set_type (GtkShortcutsShortcut *self, |
324 | GtkShortcutType type) |
325 | { |
326 | if (self->shortcut_type == type) |
327 | return; |
328 | |
329 | self->shortcut_type = type; |
330 | |
331 | update_subtitle_from_type (self); |
332 | update_icon_from_type (self); |
333 | |
334 | gtk_widget_set_visible (GTK_WIDGET (self->accelerator), visible: type == GTK_SHORTCUT_ACCELERATOR); |
335 | gtk_widget_set_visible (GTK_WIDGET (self->image), visible: type != GTK_SHORTCUT_ACCELERATOR); |
336 | |
337 | |
338 | g_object_notify (G_OBJECT (self), property_name: "shortcut-type" ); |
339 | } |
340 | |
341 | static void |
342 | gtk_shortcuts_shortcut_set_action_name (GtkShortcutsShortcut *self, |
343 | const char *action_name) |
344 | { |
345 | g_free (mem: self->action_name); |
346 | self->action_name = g_strdup (str: action_name); |
347 | |
348 | g_object_notify (G_OBJECT (self), property_name: "action-name" ); |
349 | } |
350 | |
351 | static void |
352 | gtk_shortcuts_shortcut_get_property (GObject *object, |
353 | guint prop_id, |
354 | GValue *value, |
355 | GParamSpec *pspec) |
356 | { |
357 | GtkShortcutsShortcut *self = GTK_SHORTCUTS_SHORTCUT (object); |
358 | |
359 | switch (prop_id) |
360 | { |
361 | case PROP_TITLE: |
362 | g_value_set_string (value, v_string: gtk_label_get_label (self: self->title)); |
363 | break; |
364 | |
365 | case PROP_SUBTITLE: |
366 | g_value_set_string (value, v_string: gtk_label_get_label (self: self->subtitle)); |
367 | break; |
368 | |
369 | case PROP_SUBTITLE_SET: |
370 | g_value_set_boolean (value, v_boolean: self->subtitle_set); |
371 | break; |
372 | |
373 | case PROP_ACCELERATOR: |
374 | g_value_set_string (value, v_string: gtk_shortcut_label_get_accelerator (self: self->accelerator)); |
375 | break; |
376 | |
377 | case PROP_ICON: |
378 | g_value_set_object (value, v_object: gtk_image_get_gicon (image: self->image)); |
379 | break; |
380 | |
381 | case PROP_ICON_SET: |
382 | g_value_set_boolean (value, v_boolean: self->icon_set); |
383 | break; |
384 | |
385 | case PROP_DIRECTION: |
386 | g_value_set_enum (value, v_enum: self->direction); |
387 | break; |
388 | |
389 | case PROP_SHORTCUT_TYPE: |
390 | g_value_set_enum (value, v_enum: self->shortcut_type); |
391 | break; |
392 | |
393 | case PROP_ACTION_NAME: |
394 | g_value_set_string (value, v_string: self->action_name); |
395 | break; |
396 | |
397 | default: |
398 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
399 | } |
400 | } |
401 | |
402 | static void |
403 | gtk_shortcuts_shortcut_set_property (GObject *object, |
404 | guint prop_id, |
405 | const GValue *value, |
406 | GParamSpec *pspec) |
407 | { |
408 | GtkShortcutsShortcut *self = GTK_SHORTCUTS_SHORTCUT (object); |
409 | |
410 | switch (prop_id) |
411 | { |
412 | case PROP_ACCELERATOR: |
413 | gtk_shortcuts_shortcut_set_accelerator (self, accelerator: g_value_get_string (value)); |
414 | break; |
415 | |
416 | case PROP_ICON: |
417 | gtk_shortcuts_shortcut_set_icon (self, gicon: g_value_get_object (value)); |
418 | break; |
419 | |
420 | case PROP_ICON_SET: |
421 | gtk_shortcuts_shortcut_set_icon_set (self, icon_set: g_value_get_boolean (value)); |
422 | break; |
423 | |
424 | case PROP_ACCEL_SIZE_GROUP: |
425 | gtk_shortcuts_shortcut_set_accel_size_group (self, GTK_SIZE_GROUP (g_value_get_object (value))); |
426 | break; |
427 | |
428 | case PROP_TITLE: |
429 | gtk_label_set_label (self: self->title, str: g_value_get_string (value)); |
430 | break; |
431 | |
432 | case PROP_SUBTITLE: |
433 | gtk_shortcuts_shortcut_set_subtitle (self, subtitle: g_value_get_string (value)); |
434 | break; |
435 | |
436 | case PROP_SUBTITLE_SET: |
437 | gtk_shortcuts_shortcut_set_subtitle_set (self, subtitle_set: g_value_get_boolean (value)); |
438 | break; |
439 | |
440 | case PROP_TITLE_SIZE_GROUP: |
441 | gtk_shortcuts_shortcut_set_title_size_group (self, GTK_SIZE_GROUP (g_value_get_object (value))); |
442 | break; |
443 | |
444 | case PROP_DIRECTION: |
445 | gtk_shortcuts_shortcut_set_direction (self, direction: g_value_get_enum (value)); |
446 | break; |
447 | |
448 | case PROP_SHORTCUT_TYPE: |
449 | gtk_shortcuts_shortcut_set_type (self, type: g_value_get_enum (value)); |
450 | break; |
451 | |
452 | case PROP_ACTION_NAME: |
453 | gtk_shortcuts_shortcut_set_action_name (self, action_name: g_value_get_string (value)); |
454 | break; |
455 | |
456 | default: |
457 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
458 | break; |
459 | } |
460 | } |
461 | |
462 | static void |
463 | gtk_shortcuts_shortcut_finalize (GObject *object) |
464 | { |
465 | GtkShortcutsShortcut *self = GTK_SHORTCUTS_SHORTCUT (object); |
466 | |
467 | g_clear_object (&self->accel_size_group); |
468 | g_clear_object (&self->title_size_group); |
469 | g_free (mem: self->action_name); |
470 | gtk_widget_unparent (GTK_WIDGET (self->box)); |
471 | |
472 | G_OBJECT_CLASS (gtk_shortcuts_shortcut_parent_class)->finalize (object); |
473 | } |
474 | |
475 | void |
476 | gtk_shortcuts_shortcut_update_accel (GtkShortcutsShortcut *self, |
477 | GtkWindow *window) |
478 | { |
479 | GtkApplication *app; |
480 | char **accels; |
481 | char *str; |
482 | |
483 | if (self->action_name == NULL) |
484 | return; |
485 | |
486 | app = gtk_window_get_application (window); |
487 | if (app == NULL) |
488 | return; |
489 | |
490 | accels = gtk_application_get_accels_for_action (application: app, detailed_action_name: self->action_name); |
491 | str = g_strjoinv (separator: " " , str_array: accels); |
492 | |
493 | gtk_shortcuts_shortcut_set_accelerator (self, accelerator: str); |
494 | |
495 | g_free (mem: str); |
496 | g_strfreev (str_array: accels); |
497 | } |
498 | |
499 | static void |
500 | gtk_shortcuts_shortcut_measure (GtkWidget *widget, |
501 | GtkOrientation orientation, |
502 | int for_size, |
503 | int *minimum, |
504 | int *natural, |
505 | int *minimum_baseline, |
506 | int *natural_baseline) |
507 | { |
508 | gtk_widget_measure (GTK_WIDGET (GTK_SHORTCUTS_SHORTCUT (widget)->box), |
509 | orientation, for_size, |
510 | minimum, natural, |
511 | minimum_baseline, natural_baseline); |
512 | } |
513 | |
514 | static void |
515 | gtk_shortcuts_shortcut_snapshot (GtkWidget *widget, |
516 | GtkSnapshot *snapshot) |
517 | { |
518 | gtk_widget_snapshot_child (widget, GTK_WIDGET (GTK_SHORTCUTS_SHORTCUT (widget)->box), snapshot); |
519 | } |
520 | |
521 | static void |
522 | gtk_shortcuts_shortcut_size_allocate (GtkWidget *widget, |
523 | int width, |
524 | int height, |
525 | int baseline) |
526 | { |
527 | GTK_WIDGET_CLASS (gtk_shortcuts_shortcut_parent_class)->size_allocate (widget, width, height, baseline); |
528 | |
529 | gtk_widget_size_allocate (GTK_WIDGET (GTK_SHORTCUTS_SHORTCUT (widget)->box), |
530 | allocation: &(GtkAllocation) { |
531 | 0, 0, |
532 | width, height |
533 | }, baseline: -1); |
534 | } |
535 | |
536 | static void |
537 | gtk_shortcuts_shortcut_class_init (GtkShortcutsShortcutClass *klass) |
538 | { |
539 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
540 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
541 | |
542 | object_class->finalize = gtk_shortcuts_shortcut_finalize; |
543 | object_class->get_property = gtk_shortcuts_shortcut_get_property; |
544 | object_class->set_property = gtk_shortcuts_shortcut_set_property; |
545 | |
546 | widget_class->direction_changed = gtk_shortcuts_shortcut_direction_changed; |
547 | widget_class->measure = gtk_shortcuts_shortcut_measure; |
548 | widget_class->snapshot = gtk_shortcuts_shortcut_snapshot; |
549 | widget_class->size_allocate = gtk_shortcuts_shortcut_size_allocate; |
550 | |
551 | /** |
552 | * GtkShortcutsShortcut:accelerator: |
553 | * |
554 | * The accelerator(s) represented by this object. |
555 | * |
556 | * This property is used if [property@Gtk.ShortcutsShortcut:shortcut-type] |
557 | * is set to %GTK_SHORTCUT_ACCELERATOR. |
558 | * |
559 | * The syntax of this property is (an extension of) the syntax understood |
560 | * by [func@Gtk.accelerator_parse]. Multiple accelerators can be specified |
561 | * by separating them with a space, but keep in mind that the available width |
562 | * is limited. |
563 | * |
564 | * It is also possible to specify ranges of shortcuts, using "..." between |
565 | * the keys. Sequences of keys can be specified using a "+" or "&" between |
566 | * the keys. |
567 | * |
568 | * Examples: |
569 | * |
570 | * - A single shortcut: <ctl><alt>delete |
571 | * - Two alternative shortcuts: <shift>a Home |
572 | * - A range of shortcuts: <alt>1...<alt>9 |
573 | * - Several keys pressed together: Control_L&Control_R |
574 | * - A sequence of shortcuts or keys: <ctl>c+<ctl>x |
575 | * |
576 | * Use "+" instead of "&" when the keys may (or have to be) pressed |
577 | * sequentially (e.g use "t+t" for 'press the t key twice'). |
578 | * |
579 | * Note that <, > and & need to be escaped as <, > and & when used |
580 | * in .ui files. |
581 | */ |
582 | properties[PROP_ACCELERATOR] = |
583 | g_param_spec_string (name: "accelerator" , |
584 | P_("Accelerator" ), |
585 | P_("The accelerator keys for shortcuts of type “Accelerator”" ), |
586 | NULL, |
587 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
588 | |
589 | /** |
590 | * GtkShortcutsShortcut:icon: |
591 | * |
592 | * An icon to represent the shortcut or gesture. |
593 | * |
594 | * This property is used if [property@Gtk.ShortcutsShortcut:shortcut-type] |
595 | * is set to %GTK_SHORTCUT_GESTURE. |
596 | * |
597 | * For the other predefined gesture types, GTK provides an icon on its own. |
598 | */ |
599 | properties[PROP_ICON] = |
600 | g_param_spec_object (name: "icon" , |
601 | P_("Icon" ), |
602 | P_("The icon to show for shortcuts of type “Other Gesture”" ), |
603 | G_TYPE_ICON, |
604 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
605 | |
606 | /** |
607 | * GtkShortcutsShortcut:icon-set: |
608 | * |
609 | * %TRUE if an icon has been set. |
610 | */ |
611 | properties[PROP_ICON_SET] = |
612 | g_param_spec_boolean (name: "icon-set" , |
613 | P_("Icon Set" ), |
614 | P_("Whether an icon has been set" ), |
615 | FALSE, |
616 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
617 | |
618 | /** |
619 | * GtkShortcutsShortcut:title: |
620 | * |
621 | * The textual description for the shortcut or gesture represented by |
622 | * this object. |
623 | * |
624 | * This should be a short string that can fit in a single line. |
625 | */ |
626 | properties[PROP_TITLE] = |
627 | g_param_spec_string (name: "title" , |
628 | P_("Title" ), |
629 | P_("A short description for the shortcut" ), |
630 | default_value: "" , |
631 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
632 | |
633 | /** |
634 | * GtkShortcutsShortcut:subtitle: |
635 | * |
636 | * The subtitle for the shortcut or gesture. |
637 | * |
638 | * This is typically used for gestures and should be a short, one-line |
639 | * text that describes the gesture itself. For the predefined gesture |
640 | * types, GTK provides a subtitle on its own. |
641 | */ |
642 | properties[PROP_SUBTITLE] = |
643 | g_param_spec_string (name: "subtitle" , |
644 | P_("Subtitle" ), |
645 | P_("A short description for the gesture" ), |
646 | default_value: "" , |
647 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
648 | |
649 | /** |
650 | * GtkShortcutsShortcut:subtitle-set: |
651 | * |
652 | * %TRUE if a subtitle has been set. |
653 | */ |
654 | properties[PROP_SUBTITLE_SET] = |
655 | g_param_spec_boolean (name: "subtitle-set" , |
656 | P_("Subtitle Set" ), |
657 | P_("Whether a subtitle has been set" ), |
658 | FALSE, |
659 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
660 | |
661 | /** |
662 | * GtkShortcutsShortcut:accel-size-group: |
663 | * |
664 | * The size group for the accelerator portion of this shortcut. |
665 | * |
666 | * This is used internally by GTK, and must not be modified by applications. |
667 | */ |
668 | properties[PROP_ACCEL_SIZE_GROUP] = |
669 | g_param_spec_object (name: "accel-size-group" , |
670 | P_("Accelerator Size Group" ), |
671 | P_("Accelerator Size Group" ), |
672 | GTK_TYPE_SIZE_GROUP, |
673 | flags: (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); |
674 | |
675 | /** |
676 | * GtkShortcutsShortcut:title-size-group: |
677 | * |
678 | * The size group for the textual portion of this shortcut. |
679 | * |
680 | * This is used internally by GTK, and must not be modified by applications. |
681 | */ |
682 | properties[PROP_TITLE_SIZE_GROUP] = |
683 | g_param_spec_object (name: "title-size-group" , |
684 | P_("Title Size Group" ), |
685 | P_("Title Size Group" ), |
686 | GTK_TYPE_SIZE_GROUP, |
687 | flags: (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); |
688 | |
689 | /** |
690 | * GtkShortcutsShortcut:direction: |
691 | * |
692 | * The text direction for which this shortcut is active. |
693 | * |
694 | * If the shortcut is used regardless of the text direction, |
695 | * set this property to %GTK_TEXT_DIR_NONE. |
696 | */ |
697 | properties[PROP_DIRECTION] = |
698 | g_param_spec_enum (name: "direction" , |
699 | P_("Direction" ), |
700 | P_("Text direction for which this shortcut is active" ), |
701 | enum_type: GTK_TYPE_TEXT_DIRECTION, |
702 | default_value: GTK_TEXT_DIR_NONE, |
703 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY)); |
704 | |
705 | /** |
706 | * GtkShortcutsShortcut:shortcut-type: |
707 | * |
708 | * The type of shortcut that is represented. |
709 | */ |
710 | properties[PROP_SHORTCUT_TYPE] = |
711 | g_param_spec_enum (name: "shortcut-type" , |
712 | P_("Shortcut Type" ), |
713 | P_("The type of shortcut that is represented" ), |
714 | enum_type: GTK_TYPE_SHORTCUT_TYPE, |
715 | default_value: GTK_SHORTCUT_ACCELERATOR, |
716 | flags: (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY)); |
717 | |
718 | /** |
719 | * GtkShortcutsShortcut:action-name: |
720 | * |
721 | * A detailed action name. |
722 | * |
723 | * If this is set for a shortcut of type %GTK_SHORTCUT_ACCELERATOR, |
724 | * then GTK will use the accelerators that are associated with the |
725 | * action via [method@Gtk.Application.set_accels_for_action], and |
726 | * setting [property@Gtk.ShortcutsShortcut:accelerator] is not necessary. |
727 | */ |
728 | properties[PROP_ACTION_NAME] = |
729 | g_param_spec_string (name: "action-name" , |
730 | P_("Action Name" ), |
731 | P_("The name of the action" ), |
732 | NULL, |
733 | flags: G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); |
734 | |
735 | g_object_class_install_properties (oclass: object_class, n_pspecs: LAST_PROP, pspecs: properties); |
736 | gtk_widget_class_set_css_name (widget_class, I_("shortcut" )); |
737 | gtk_widget_class_set_accessible_role (widget_class, accessible_role: GTK_ACCESSIBLE_ROLE_GROUP); |
738 | } |
739 | |
740 | static void |
741 | gtk_shortcuts_shortcut_init (GtkShortcutsShortcut *self) |
742 | { |
743 | self->box = g_object_new (GTK_TYPE_BOX, |
744 | first_property_name: "orientation" , GTK_ORIENTATION_HORIZONTAL, |
745 | "spacing" , 12, |
746 | NULL); |
747 | gtk_widget_set_parent (GTK_WIDGET (self->box), GTK_WIDGET (self)); |
748 | |
749 | self->direction = GTK_TEXT_DIR_NONE; |
750 | self->shortcut_type = GTK_SHORTCUT_ACCELERATOR; |
751 | |
752 | self->image = g_object_new (GTK_TYPE_IMAGE, |
753 | first_property_name: "visible" , FALSE, |
754 | "valign" , GTK_ALIGN_CENTER, |
755 | "accessible-role" , GTK_ACCESSIBLE_ROLE_PRESENTATION, |
756 | NULL); |
757 | gtk_box_append (GTK_BOX (self->box), GTK_WIDGET (self->image)); |
758 | |
759 | self->accelerator = g_object_new (GTK_TYPE_SHORTCUT_LABEL, |
760 | first_property_name: "visible" , TRUE, |
761 | "valign" , GTK_ALIGN_CENTER, |
762 | NULL); |
763 | gtk_box_append (GTK_BOX (self->box), GTK_WIDGET (self->accelerator)); |
764 | |
765 | self->title_box = g_object_new (GTK_TYPE_BOX, |
766 | first_property_name: "visible" , TRUE, |
767 | "valign" , GTK_ALIGN_CENTER, |
768 | "hexpand" , TRUE, |
769 | "orientation" , GTK_ORIENTATION_VERTICAL, |
770 | NULL); |
771 | gtk_box_append (GTK_BOX (self->box), GTK_WIDGET (self->title_box)); |
772 | |
773 | self->title = g_object_new (GTK_TYPE_LABEL, |
774 | first_property_name: "visible" , TRUE, |
775 | "xalign" , 0.0f, |
776 | NULL); |
777 | gtk_box_append (GTK_BOX (self->title_box), GTK_WIDGET (self->title)); |
778 | |
779 | self->subtitle = g_object_new (GTK_TYPE_LABEL, |
780 | first_property_name: "visible" , FALSE, |
781 | "xalign" , 0.0f, |
782 | NULL); |
783 | gtk_widget_add_css_class (GTK_WIDGET (self->subtitle), css_class: "dim-label" ); |
784 | gtk_box_append (GTK_BOX (self->title_box), GTK_WIDGET (self->subtitle)); |
785 | } |
786 | |