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 "size-groups.h"
22 #include "window.h"
23
24 #include "gtkcomboboxtext.h"
25 #include "gtkframe.h"
26 #include "gtklabel.h"
27 #include "gtklistbox.h"
28 #include "gtksizegroup.h"
29 #include "gtkswitch.h"
30 #include "gtkwidgetprivate.h"
31
32
33 typedef struct {
34 GtkListBoxRow parent;
35 GtkWidget *widget;
36 } SizeGroupRow;
37
38 typedef struct {
39 GtkListBoxRowClass parent;
40 } SizeGroupRowClass;
41
42 enum {
43 PROP_WIDGET = 1,
44 LAST_PROPERTY
45 };
46
47 GParamSpec *properties[LAST_PROPERTY] = { NULL };
48
49 GType size_group_row_get_type (void);
50
G_DEFINE_TYPE(SizeGroupRow,size_group_row,GTK_TYPE_LIST_BOX_ROW)51 G_DEFINE_TYPE (SizeGroupRow, size_group_row, GTK_TYPE_LIST_BOX_ROW)
52
53 static void
54 size_group_row_init (SizeGroupRow *row)
55 {
56 }
57
58 static void
size_group_row_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)59 size_group_row_get_property (GObject *object,
60 guint property_id,
61 GValue *value,
62 GParamSpec *pspec)
63 {
64 SizeGroupRow *row = (SizeGroupRow*)object;
65
66 switch (property_id)
67 {
68 case PROP_WIDGET:
69 g_value_set_pointer (value, row->widget);
70 break;
71 default:
72 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
73 break;
74 }
75 }
76
77 static void
size_group_row_widget_destroyed(GtkWidget * widget,SizeGroupRow * row)78 size_group_row_widget_destroyed (GtkWidget *widget, SizeGroupRow *row)
79 {
80 GtkWidget *parent;
81
82 parent = gtk_widget_get_parent (GTK_WIDGET (row));
83 if (parent)
84 gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (row));
85 }
86
87 static void
set_widget(SizeGroupRow * row,GtkWidget * widget)88 set_widget (SizeGroupRow *row, GtkWidget *widget)
89 {
90 if (row->widget)
91 g_signal_handlers_disconnect_by_func (row->widget,
92 size_group_row_widget_destroyed, row);
93
94 row->widget = widget;
95
96 if (row->widget)
97 g_signal_connect (row->widget, "destroy",
98 G_CALLBACK (size_group_row_widget_destroyed), row);
99 }
100
101 static void
size_group_row_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)102 size_group_row_set_property (GObject *object,
103 guint property_id,
104 const GValue *value,
105 GParamSpec *pspec)
106 {
107 SizeGroupRow *row = (SizeGroupRow*)object;
108
109 switch (property_id)
110 {
111 case PROP_WIDGET:
112 set_widget (row, g_value_get_pointer (value));
113 break;
114 default:
115 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
116 break;
117 }
118 }
119 static void
size_group_row_finalize(GObject * object)120 size_group_row_finalize (GObject *object)
121 {
122 SizeGroupRow *row = (SizeGroupRow *)object;
123
124 set_widget (row, NULL);
125
126 G_OBJECT_CLASS (size_group_row_parent_class)->finalize (object);
127 }
128
129 static void
size_group_state_flags_changed(GtkWidget * widget,GtkStateFlags old_state)130 size_group_state_flags_changed (GtkWidget *widget,
131 GtkStateFlags old_state)
132 {
133 SizeGroupRow *row = (SizeGroupRow*)widget;
134 GtkStateFlags state;
135
136 if (!row->widget)
137 return;
138
139 state = gtk_widget_get_state_flags (widget);
140 if ((state & GTK_STATE_FLAG_PRELIGHT) != (old_state & GTK_STATE_FLAG_PRELIGHT))
141 {
142 if (state & GTK_STATE_FLAG_PRELIGHT)
143 gtk_inspector_start_highlight (row->widget);
144 else
145 gtk_inspector_stop_highlight (row->widget);
146 }
147 }
148
149 static void
size_group_row_class_init(SizeGroupRowClass * class)150 size_group_row_class_init (SizeGroupRowClass *class)
151 {
152 GObjectClass *object_class = G_OBJECT_CLASS (class);
153 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
154
155 object_class->finalize = size_group_row_finalize;
156 object_class->get_property = size_group_row_get_property;
157 object_class->set_property = size_group_row_set_property;
158
159 widget_class->state_flags_changed = size_group_state_flags_changed;
160
161 properties[PROP_WIDGET] =
162 g_param_spec_pointer ("widget", "Widget", "Widget", G_PARAM_READWRITE);
163
164 g_object_class_install_properties (object_class, LAST_PROPERTY, properties);
165
166 }
167
G_DEFINE_TYPE(GtkInspectorSizeGroups,gtk_inspector_size_groups,GTK_TYPE_BOX)168 G_DEFINE_TYPE (GtkInspectorSizeGroups, gtk_inspector_size_groups, GTK_TYPE_BOX)
169
170 static void
171 clear_view (GtkInspectorSizeGroups *sl)
172 {
173 GList *children, *l;
174 GtkWidget *child;
175
176 children = gtk_container_get_children (GTK_CONTAINER (sl));
177 for (l = children; l; l = l->next)
178 {
179 child = l->data;
180 gtk_container_remove (GTK_CONTAINER (sl), child);
181 }
182 g_list_free (children);
183 }
184
185 static void
add_widget(GtkInspectorSizeGroups * sl,GtkListBox * listbox,GtkWidget * widget)186 add_widget (GtkInspectorSizeGroups *sl,
187 GtkListBox *listbox,
188 GtkWidget *widget)
189 {
190 GtkWidget *row;
191 GtkWidget *label;
192 gchar *text;
193
194 row = g_object_new (size_group_row_get_type (), "widget", widget, NULL);
195 text = g_strdup_printf ("%p (%s)", widget, g_type_name_from_instance ((GTypeInstance*)widget));
196 label = gtk_label_new (text);
197 g_free (text);
198 g_object_set (label, "margin", 10, NULL);
199 gtk_widget_set_halign (label, GTK_ALIGN_START);
200 gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
201 gtk_widget_show (label);
202 gtk_container_add (GTK_CONTAINER (row), label);
203 gtk_container_add (GTK_CONTAINER (listbox), row);
204 }
205
206 static void
add_size_group(GtkInspectorSizeGroups * sl,GtkSizeGroup * group)207 add_size_group (GtkInspectorSizeGroups *sl,
208 GtkSizeGroup *group)
209 {
210 GtkWidget *frame, *box, *box2;
211 GtkWidget *label, *sw, *combo;
212 GSList *widgets, *l;
213 GtkWidget *listbox;
214
215 frame = gtk_frame_new (NULL);
216 gtk_container_add (GTK_CONTAINER (sl), frame);
217 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
218 gtk_style_context_add_class (gtk_widget_get_style_context (box), GTK_STYLE_CLASS_VIEW);
219 gtk_container_add (GTK_CONTAINER (frame), box);
220
221 box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
222 gtk_container_add (GTK_CONTAINER (box), box2);
223
224 label = gtk_label_new (_("Ignore hidden"));
225 g_object_set (label, "margin", 10, NULL);
226 gtk_widget_set_halign (label, GTK_ALIGN_START);
227 gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
228 gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
229
230 sw = gtk_switch_new ();
231 g_object_set (sw, "margin", 10, NULL);
232 gtk_widget_set_halign (sw, GTK_ALIGN_END);
233 gtk_widget_set_valign (sw, GTK_ALIGN_BASELINE);
234 g_object_bind_property (group, "ignore-hidden",
235 sw, "active",
236 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
237 gtk_box_pack_start (GTK_BOX (box2), sw, FALSE, FALSE, 0);
238
239 box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
240 gtk_container_add (GTK_CONTAINER (box), box2);
241
242 label = gtk_label_new (_("Mode"));
243 g_object_set (label, "margin", 10, NULL);
244 gtk_widget_set_halign (label, GTK_ALIGN_START);
245 gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
246 gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
247
248 combo = gtk_combo_box_text_new ();
249 g_object_set (combo, "margin", 10, NULL);
250 gtk_widget_set_halign (combo, GTK_ALIGN_END);
251 gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE);
252 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), C_("sizegroup mode", "None"));
253 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), C_("sizegroup mode", "Horizontal"));
254 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), C_("sizegroup mode", "Vertical"));
255 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), C_("sizegroup mode", "Both"));
256 g_object_bind_property (group, "mode",
257 combo, "active",
258 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
259 gtk_box_pack_start (GTK_BOX (box2), combo, FALSE, FALSE, 0);
260
261 listbox = gtk_list_box_new ();
262 gtk_container_add (GTK_CONTAINER (box), listbox);
263 gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE);
264
265 widgets = gtk_size_group_get_widgets (group);
266 for (l = widgets; l; l = l->next)
267 add_widget (sl, GTK_LIST_BOX (listbox), GTK_WIDGET (l->data));
268
269 gtk_widget_show_all (frame);
270 }
271
272 void
gtk_inspector_size_groups_set_object(GtkInspectorSizeGroups * sl,GObject * object)273 gtk_inspector_size_groups_set_object (GtkInspectorSizeGroups *sl,
274 GObject *object)
275 {
276 GSList *groups, *l;
277
278 clear_view (sl);
279
280 if (!GTK_IS_WIDGET (object))
281 {
282 gtk_widget_hide (GTK_WIDGET (sl));
283 return;
284 }
285
286 groups = _gtk_widget_get_sizegroups (GTK_WIDGET (object));
287 if (groups)
288 gtk_widget_show (GTK_WIDGET (sl));
289 for (l = groups; l; l = l->next)
290 {
291 GtkSizeGroup *group = l->data;
292 add_size_group (sl, group);
293 }
294 }
295
296 static void
gtk_inspector_size_groups_init(GtkInspectorSizeGroups * sl)297 gtk_inspector_size_groups_init (GtkInspectorSizeGroups *sl)
298 {
299 g_object_set (sl,
300 "orientation", GTK_ORIENTATION_VERTICAL,
301 "margin-start", 60,
302 "margin-end", 60,
303 "margin-bottom", 60,
304 "margin-bottom", 30,
305 "spacing", 10,
306 NULL);
307 }
308
309 static void
gtk_inspector_size_groups_class_init(GtkInspectorSizeGroupsClass * klass)310 gtk_inspector_size_groups_class_init (GtkInspectorSizeGroupsClass *klass)
311 {
312 }
313
314 // vim: set et sw=2 ts=2:
315