1 /*
2 * glade-gtk-flow-box.c - GladeWidgetAdaptor for GtkFlowBox widget
3 *
4 * Copyright (C) 2014 Red Hat, Inc.
5 *
6 * Authors:
7 * Matthias Clasen <mclasen@redhat.com>
8 *
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23 #include <config.h>
24
25 #include <gtk/gtk.h>
26 #include <glib/gi18n-lib.h>
27 #include <string.h>
28
29 #include <gladeui/glade.h>
glade_gtk_expander_post_create(GladeWidgetAdaptor * adaptor,GObject * expander,GladeCreateReason reason)30 #include "glade-gtk.h"
31
32 static void
33 sync_child_positions (GtkFlowBox *flowbox)
34 {
35 GList *l, *children;
36 int position;
37 static gboolean recursion = FALSE;
38
39 /* Avoid feedback loop */
40 if (recursion)
41 return;
42
43 children = gtk_container_get_children (GTK_CONTAINER (flowbox));
44
45 position = 0;
46 for (l = children; l; l = g_list_next (l))
47 {
48 gint old_position;
49
50 glade_widget_pack_property_get (glade_widget_get_from_gobject (l->data),
51 "position", &old_position);
52 if (position != old_position)
53 {
54 /* Update glade with the new value */
55 recursion = TRUE;
56 glade_widget_pack_property_set (glade_widget_get_from_gobject (l->data),
57 "position", position);
58 recursion = FALSE;
59 }
60
61 position++;
62 }
63
64 g_list_free (children);
65 }
66
67 static void
68 glade_gtk_flowbox_insert (GtkFlowBox *flowbox,
69 GtkFlowBoxChild *child,
glade_gtk_expander_replace_child(GladeWidgetAdaptor * adaptor,GtkWidget * container,GtkWidget * current,GtkWidget * new_widget)70 gint position)
71 {
72 gtk_flow_box_insert (flowbox, GTK_WIDGET (child), position);
73 sync_child_positions (flowbox);
74 }
75
76 static void
77 glade_gtk_flowbox_reorder (GtkFlowBox *flowbox,
78 GtkFlowBoxChild *child,
79 gint position)
80 {
81 gtk_container_remove (GTK_CONTAINER (flowbox), GTK_WIDGET (child));
82 gtk_flow_box_insert (flowbox, GTK_WIDGET (child), position);
83 sync_child_positions (flowbox);
84 }
85
86 void
87 glade_gtk_flowbox_get_child_property (GladeWidgetAdaptor *adaptor,
88 GObject *container,
89 GObject *child,
90 const gchar *property_name,
91 GValue *value)
92 {
93 g_return_if_fail (GTK_IS_FLOW_BOX (container));
94 g_return_if_fail (GTK_IS_FLOW_BOX_CHILD (child));
95
96 if (strcmp (property_name, "position") == 0)
glade_gtk_expander_add_child(GladeWidgetAdaptor * adaptor,GObject * object,GObject * child)97 {
98 gint position = gtk_flow_box_child_get_index (GTK_FLOW_BOX_CHILD (child));
99 g_value_set_int (value, position);
100 }
101 else
102 {
103 /* Chain Up */
104 GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_get_property (adaptor,
105 container,
106 child,
107 property_name,
108 value);
109 }
110 }
111
112 void
113 glade_gtk_flowbox_set_child_property (GladeWidgetAdaptor *adaptor,
114 GObject *container,
115 GObject *child,
116 const gchar *property_name,
117 GValue *value)
118 {
glade_gtk_expander_remove_child(GladeWidgetAdaptor * adaptor,GObject * object,GObject * child)119 g_return_if_fail (GTK_IS_FLOW_BOX (container));
120 g_return_if_fail (GTK_IS_FLOW_BOX_CHILD (child));
121
122 g_return_if_fail (property_name != NULL || value != NULL);
123
124 if (strcmp (property_name, "position") == 0)
125 {
126 gint position;
127
128 position = g_value_get_int (value);
129 glade_gtk_flowbox_reorder (GTK_FLOW_BOX (container),
130 GTK_FLOW_BOX_CHILD (child),
131 position);
132 }
133 else
134 {
135 /* Chain Up */
136 GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
137 container,
glade_gtk_expander_write_child(GladeWidgetAdaptor * adaptor,GladeWidget * widget,GladeXmlContext * context,GladeXmlNode * node)138 child,
139 property_name,
140 value);
141 }
142 }
143
144 gboolean
145 glade_gtk_flowbox_add_verify (GladeWidgetAdaptor *adaptor,
146 GtkWidget *container,
147 GtkWidget *child,
148 gboolean user_feedback)
149 {
150 if (!GTK_IS_FLOW_BOX_CHILD (child))
151 {
152 if (user_feedback)
153 {
154 GladeWidgetAdaptor *tool_item_adaptor =
155 glade_widget_adaptor_get_by_type (GTK_TYPE_FLOW_BOX_CHILD);
156
157 glade_util_ui_message (glade_app_get_window (),
158 GLADE_UI_INFO, NULL,
159 ONLY_THIS_GOES_IN_THAT_MSG,
160 glade_widget_adaptor_get_title (tool_item_adaptor),
161 glade_widget_adaptor_get_title (adaptor));
162 }
163
164 return FALSE;
165 }
166
167 return TRUE;
168 }
169
170 void
171 glade_gtk_flowbox_add_child (GladeWidgetAdaptor *adaptor,
172 GObject *object,
173 GObject *child)
174 {
175 g_return_if_fail (GTK_IS_FLOW_BOX (object));
176 g_return_if_fail (GTK_IS_FLOW_BOX_CHILD (child));
177
178 /* Insert to the end of the list */
179 glade_gtk_flowbox_insert (GTK_FLOW_BOX (object),
180 GTK_FLOW_BOX_CHILD (child),
181 -1);
182 }
183
184 void
185 glade_gtk_flowbox_remove_child (GladeWidgetAdaptor *adaptor,
186 GObject *object,
187 GObject *child)
188 {
189 gtk_container_remove (GTK_CONTAINER (object), GTK_WIDGET (child));
190 sync_child_positions (GTK_FLOW_BOX (object));
191 }
192
193 static void
194 glade_gtk_flowbox_child_insert_action (GladeWidgetAdaptor *adaptor,
195 GObject *container,
196 GObject *object,
197 gboolean after)
198 {
199 GladeWidget *parent;
200 GladeWidget *gchild;
201 gint position;
202
203 parent = glade_widget_get_from_gobject (container);
204 glade_command_push_group (_("Insert Child on %s"), glade_widget_get_name (parent));
205
206 position = gtk_flow_box_child_get_index (GTK_FLOW_BOX_CHILD (object));
207 if (after)
208 position++;
209
210 gchild = glade_command_create (glade_widget_adaptor_get_by_type (GTK_TYPE_FLOW_BOX_CHILD),
211 parent,
212 NULL,
213 glade_widget_get_project (parent));
214 glade_widget_pack_property_set (gchild, "position", position);
215
216 glade_command_pop_group ();
217 }
218
219 void
220 glade_gtk_flowbox_action_activate (GladeWidgetAdaptor * adaptor,
221 GObject * object,
222 const gchar * action_path)
223 {
224 if (strcmp (action_path, "add_child") == 0)
225 {
226 GladeWidgetAdaptor *adaptor = glade_widget_adaptor_get_by_type (GTK_TYPE_FLOW_BOX_CHILD);
227 GladeWidget *gparent = glade_widget_get_from_gobject (object);
228 GladeProject *project = glade_widget_get_project (gparent);
229
230 glade_command_create (adaptor, gparent, NULL, project);
231
232 glade_project_selection_set (project, object, TRUE);
233 }
234 else
235 GWA_GET_CLASS (GTK_TYPE_CONTAINER)->action_activate (adaptor,
236 object, action_path);
237 }
238
239 void
240 glade_gtk_flowbox_child_action_activate (GladeWidgetAdaptor *adaptor,
241 GObject *container,
242 GObject *object,
243 const gchar *action_path)
244 {
245 if (strcmp (action_path, "insert_after") == 0)
246 {
247 glade_gtk_flowbox_child_insert_action (adaptor, container, object,
248 TRUE);
249 }
250 else if (strcmp (action_path, "insert_before") == 0)
251 {
252 glade_gtk_flowbox_child_insert_action (adaptor, container, object,
253 FALSE);
254 }
255 else
256 {
257 GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_action_activate (adaptor,
258 container,
259 object,
260 action_path);
261 }
262 }
263