1 /*
2 * Copyright (c) 2014 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19 #include <glib/gi18n-lib.h>
20
21 #include "gestures.h"
22 #include "object-tree.h"
23
24 #include "gtksizegroup.h"
25 #include "gtkcomboboxtext.h"
26 #include "gtklistbox.h"
27 #include "gtkgesture.h"
28 #include "gtklabel.h"
29 #include "gtkframe.h"
30 #include "gtkwidgetprivate.h"
31
32 enum
33 {
34 PROP_0,
35 PROP_OBJECT_TREE
36 };
37
38 struct _GtkInspectorGesturesPrivate
39 {
40 GtkSizeGroup *sizegroup;
41 GObject *object;
42 GtkInspectorObjectTree *object_tree;
43 };
44
G_DEFINE_TYPE_WITH_PRIVATE(GtkInspectorGestures,gtk_inspector_gestures,GTK_TYPE_BOX)45 G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorGestures, gtk_inspector_gestures, GTK_TYPE_BOX)
46
47 static void
48 gtk_inspector_gestures_init (GtkInspectorGestures *sl)
49 {
50 sl->priv = gtk_inspector_gestures_get_instance_private (sl);
51 sl->priv->sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
52 g_object_set (sl,
53 "orientation", GTK_ORIENTATION_VERTICAL,
54 "margin-start", 60,
55 "margin-end", 60,
56 "margin-top", 60,
57 "margin-bottom", 30,
58 "spacing", 10,
59 NULL);
60 }
61
62 static void
clear_all(GtkInspectorGestures * sl)63 clear_all (GtkInspectorGestures *sl)
64 {
65 GList *children, *l;
66 GtkWidget *child;
67
68 children = gtk_container_get_children (GTK_CONTAINER (sl));
69 for (l = children; l; l = l->next)
70 {
71 child = l->data;
72 gtk_container_remove (GTK_CONTAINER (sl), child);
73 }
74 g_list_free (children);
75 }
76
77 static void
phase_changed_cb(GtkComboBox * combo,GtkInspectorGestures * sl)78 phase_changed_cb (GtkComboBox *combo, GtkInspectorGestures *sl)
79 {
80 GtkWidget *row;
81 GtkPropagationPhase phase;
82 GtkGesture *gesture;
83
84 phase = gtk_combo_box_get_active (combo);
85 row = gtk_widget_get_ancestor (GTK_WIDGET (combo), GTK_TYPE_LIST_BOX_ROW);
86 gesture = GTK_GESTURE (g_object_get_data (G_OBJECT (row), "gesture"));
87 gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), phase);
88 }
89
90 static void
row_activated(GtkListBox * box,GtkListBoxRow * row,GtkInspectorGestures * sl)91 row_activated (GtkListBox *box,
92 GtkListBoxRow *row,
93 GtkInspectorGestures *sl)
94 {
95 GObject *gesture;
96
97 gesture = G_OBJECT (g_object_get_data (G_OBJECT (row), "gesture"));
98 gtk_inspector_object_tree_select_object (sl->priv->object_tree, gesture);
99 }
100
101 static void
add_gesture(GtkInspectorGestures * sl,GObject * object,GtkWidget * listbox,GtkGesture * gesture,GtkPropagationPhase phase)102 add_gesture (GtkInspectorGestures *sl,
103 GObject *object,
104 GtkWidget *listbox,
105 GtkGesture *gesture,
106 GtkPropagationPhase phase)
107 {
108 GtkWidget *row;
109 GtkWidget *box;
110 GtkWidget *label;
111 GtkWidget *combo;
112
113 row = gtk_list_box_row_new ();
114 gtk_container_add (GTK_CONTAINER (listbox), row);
115 gtk_widget_show (row);
116 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 40);
117 gtk_container_add (GTK_CONTAINER (row), box);
118 g_object_set (box, "margin", 10, NULL);
119 gtk_widget_show (box);
120 label = gtk_label_new (g_type_name_from_instance ((GTypeInstance*)gesture));
121 g_object_set (label, "xalign", 0.0, NULL);
122 gtk_container_add (GTK_CONTAINER (box), label);
123 gtk_size_group_add_widget (sl->priv->sizegroup, label);
124 gtk_widget_show (label);
125 gtk_widget_set_halign (label, GTK_ALIGN_START);
126 gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
127
128 combo = gtk_combo_box_text_new ();
129 gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combo), GTK_PHASE_NONE, C_("event phase", "None"));
130 gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combo), GTK_PHASE_CAPTURE, C_("event phase", "Capture"));
131 gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combo), GTK_PHASE_BUBBLE, C_("event phase", "Bubble"));
132 gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combo), GTK_PHASE_TARGET, C_("event phase", "Target"));
133 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), phase);
134 gtk_container_add (GTK_CONTAINER (box), combo);
135 gtk_widget_show (combo);
136 gtk_widget_set_halign (label, GTK_ALIGN_END);
137 gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
138
139 g_object_set_data (G_OBJECT (row), "gesture", gesture);
140 g_signal_connect (combo, "changed", G_CALLBACK (phase_changed_cb), sl);
141 }
142
143 static void
add_gesture_group(GtkInspectorGestures * sl,GObject * object,GtkGesture * gesture,GHashTable * hash)144 add_gesture_group (GtkInspectorGestures *sl,
145 GObject *object,
146 GtkGesture *gesture,
147 GHashTable *hash)
148 {
149 GtkWidget *frame;
150 GtkWidget *listbox;
151 GList *list, *l;
152 GtkGesture *g;
153 GtkPropagationPhase phase;
154
155 frame = gtk_frame_new (NULL);
156 gtk_widget_show (frame);
157 gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
158
159 listbox = gtk_list_box_new ();
160 g_signal_connect (listbox, "row-activated", G_CALLBACK (row_activated), sl);
161 gtk_container_add (GTK_CONTAINER (frame), listbox);
162 gtk_widget_show (listbox);
163 gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE);
164
165 list = gtk_gesture_get_group (gesture);
166 for (l = list; l; l = l->next)
167 {
168 g = l->data;
169 phase = GPOINTER_TO_INT (g_hash_table_lookup (hash, g));
170 add_gesture (sl, object, listbox, g, phase);
171 g_hash_table_remove (hash, g);
172 }
173 g_list_free (list);
174
175 gtk_container_add (GTK_CONTAINER (sl), frame);
176 }
177
178 void
gtk_inspector_gestures_set_object(GtkInspectorGestures * sl,GObject * object)179 gtk_inspector_gestures_set_object (GtkInspectorGestures *sl,
180 GObject *object)
181 {
182 GHashTable *hash;
183 GHashTableIter iter;
184 GList *list, *l;
185 gint phase;
186
187 clear_all (sl);
188 gtk_widget_hide (GTK_WIDGET (sl));
189
190 if (!GTK_IS_WIDGET (object))
191 return;
192
193 hash = g_hash_table_new (g_direct_hash, g_direct_equal);
194 for (phase = GTK_PHASE_NONE; phase <= GTK_PHASE_TARGET; phase++)
195 {
196 list = _gtk_widget_list_controllers (GTK_WIDGET (object), phase);
197 for (l = list; l; l = l->next)
198 {
199 GtkEventController *controller = l->data;
200
201 if (GTK_IS_GESTURE (controller))
202 g_hash_table_insert (hash, controller, GINT_TO_POINTER (phase));
203 }
204 g_list_free (list);
205 }
206
207 if (g_hash_table_size (hash))
208 gtk_widget_show (GTK_WIDGET (sl));
209
210 while (g_hash_table_size (hash) > 0)
211 {
212 gpointer key, value;
213 GtkGesture *gesture;
214 g_hash_table_iter_init (&iter, hash);
215 (void)g_hash_table_iter_next (&iter, &key, &value);
216 gesture = key;
217 add_gesture_group (sl, object, gesture, hash);
218 }
219
220 g_hash_table_unref (hash);
221 }
222
223 static void
get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)224 get_property (GObject *object,
225 guint param_id,
226 GValue *value,
227 GParamSpec *pspec)
228 {
229 GtkInspectorGestures *sl = GTK_INSPECTOR_GESTURES (object);
230
231 switch (param_id)
232 {
233 case PROP_OBJECT_TREE:
234 g_value_take_object (value, sl->priv->object_tree);
235 break;
236
237 default:
238 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
239 break;
240 }
241 }
242
243 static void
set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)244 set_property (GObject *object,
245 guint param_id,
246 const GValue *value,
247 GParamSpec *pspec)
248 {
249 GtkInspectorGestures *sl = GTK_INSPECTOR_GESTURES (object);
250
251 switch (param_id)
252 {
253 case PROP_OBJECT_TREE:
254 sl->priv->object_tree = g_value_get_object (value);
255 break;
256
257 default:
258 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
259 break;
260 }
261 }
262
263 static void
gtk_inspector_gestures_class_init(GtkInspectorGesturesClass * klass)264 gtk_inspector_gestures_class_init (GtkInspectorGesturesClass *klass)
265 {
266 GObjectClass *object_class = G_OBJECT_CLASS (klass);
267
268 object_class->get_property = get_property;
269 object_class->set_property = set_property;
270
271 g_object_class_install_property (object_class, PROP_OBJECT_TREE,
272 g_param_spec_object ("object-tree", "Widget Tree", "Widget tree",
273 GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
274 }
275
276 // vim: set et sw=2 ts=2:
277