1 /*
2  * glade-editable.c
3  *
4  * Copyright (C) 2008 Tristan Van Berkom.
5  *
6  * Authors:
7  *   Tristan Van Berkom <tvb@gnome.org>
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  */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <glib/gi18n-lib.h>
29 
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #include "glade-project.h"
34 #include "glade-widget.h"
35 #include "glade-editable.h"
36 
37 G_DEFINE_INTERFACE (GladeEditable, glade_editable, GTK_TYPE_WIDGET);
38 
39 static GQuark glade_editable_project_quark = 0;
40 static GQuark glade_editable_widget_quark = 0;
41 static GQuark glade_editable_loading_quark = 0;
42 static GQuark glade_editable_destroy_quark = 0;
43 
44 static void
45 project_changed (GladeProject  *project,
46                  GladeCommand  *command,
47                  gboolean       execute,
48 		 GladeEditable *editable)
49 {
50   GladeWidget *widget;
51 
52   widget = g_object_get_qdata (G_OBJECT (editable), glade_editable_widget_quark);
53 
54   glade_editable_load (editable, widget);
55 }
56 
57 static void
58 project_closed (GladeProject  *project,
59 		GladeEditable *editable)
60 {
61   glade_editable_load (editable, NULL);
62 }
63 
64 static void
65 editable_destroyed (GladeEditable *editable)
66 {
67   glade_editable_load (editable, NULL);
68 }
69 
70 static void
71 glade_editable_load_default (GladeEditable  *editable,
72 			     GladeWidget    *widget)
73 {
74   GladeWidget  *old_widget;
75   GladeProject *old_project;
76 
77   old_widget  = g_object_get_qdata (G_OBJECT (editable), glade_editable_widget_quark);
78   old_project = g_object_get_qdata (G_OBJECT (editable), glade_editable_project_quark);
79 
80   if (old_widget != widget)
81     {
82       if (old_widget)
83 	{
84 	  g_signal_handlers_disconnect_by_func (old_project, G_CALLBACK (project_changed), editable);
85 	  g_signal_handlers_disconnect_by_func (old_project, G_CALLBACK (project_closed), editable);
86 
87 	  g_object_set_qdata (G_OBJECT (editable), glade_editable_widget_quark, NULL);
88 	  g_object_set_qdata (G_OBJECT (editable), glade_editable_project_quark, NULL);
89 	}
90 
91       if (widget)
92 	{
93 	  GladeProject *project = glade_widget_get_project (widget);
94 
95 	  g_object_set_qdata (G_OBJECT (editable), glade_editable_widget_quark, widget);
96 	  g_object_set_qdata (G_OBJECT (editable), glade_editable_project_quark, project);
97 
98 	  g_signal_connect (project, "changed",
99 			    G_CALLBACK (project_changed), editable);
100 	  g_signal_connect (project, "close",
101 			    G_CALLBACK (project_closed), editable);
102 	}
103     }
104 }
105 
106 static void
107 glade_editable_default_init (GladeEditableIface *iface)
108 {
109   glade_editable_project_quark = g_quark_from_static_string ("glade-editable-project-quark");
110   glade_editable_widget_quark  = g_quark_from_static_string ("glade-editable-widget-quark");
111   glade_editable_loading_quark = g_quark_from_static_string ("glade-editable-loading-quark");
112   glade_editable_destroy_quark = g_quark_from_static_string ("glade-editable-destroy-quark");
113 
114   iface->load = glade_editable_load_default;
115 }
116 
117 /**
118  * glade_editable_load:
119  * @editable: A #GladeEditable
120  * @widget: the #GladeWidget to load
121  *
122  * Loads @widget property values into @editable
123  * (the editable will watch the widgets properties
124  * until its loaded with another widget or %NULL)
125  */
126 void
127 glade_editable_load (GladeEditable *editable, GladeWidget *widget)
128 {
129   GladeEditableIface *iface;
130   g_return_if_fail (GLADE_IS_EDITABLE (editable));
131   g_return_if_fail (widget == NULL || GLADE_IS_WIDGET (widget));
132 
133   /* Connect to the destroy signal once, make sure we unload the widget and disconnect
134    * to any signals when destroying
135    */
136   if (!GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (editable), glade_editable_destroy_quark)))
137     {
138       g_signal_connect (editable, "destroy", G_CALLBACK (editable_destroyed), NULL);
139       g_object_set_qdata (G_OBJECT (editable), glade_editable_destroy_quark, GINT_TO_POINTER (TRUE));
140     }
141 
142   iface = GLADE_EDITABLE_GET_IFACE (editable);
143 
144   g_object_set_qdata (G_OBJECT (editable), glade_editable_loading_quark, GINT_TO_POINTER (TRUE));
145 
146   if (iface->load)
147     iface->load (editable, widget);
148   else
149     g_critical ("No GladeEditable::load() support on type %s",
150                 G_OBJECT_TYPE_NAME (editable));
151 
152   g_object_set_qdata (G_OBJECT (editable), glade_editable_loading_quark, GINT_TO_POINTER (FALSE));
153 }
154 
155 
156 /**
157  * glade_editable_set_show_name:
158  * @editable: A #GladeEditable
159  * @show_name: Whether or not to show the name entry
160  *
161  * This only applies for the general page in the property
162  * editor, editables that embed the #GladeEditorTable implementation
163  * for the general page should use this to forward the message
164  * to its embedded editable.
165  */
166 void
167 glade_editable_set_show_name (GladeEditable *editable, gboolean show_name)
168 {
169   GladeEditableIface *iface;
170   g_return_if_fail (GLADE_IS_EDITABLE (editable));
171 
172   iface = GLADE_EDITABLE_GET_IFACE (editable);
173 
174   if (iface->set_show_name)
175     iface->set_show_name (editable, show_name);
176 }
177 
178 GladeWidget *
179 glade_editable_loaded_widget (GladeEditable *editable)
180 {
181   return g_object_get_qdata (G_OBJECT (editable), glade_editable_widget_quark);
182 }
183 
184 gboolean
185 glade_editable_loading (GladeEditable *editable)
186 {
187   return GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (editable), glade_editable_loading_quark));
188 }
189 
190 void
191 glade_editable_block (GladeEditable *editable)
192 {
193   GladeProject *project;
194 
195   g_return_if_fail (GLADE_IS_EDITABLE (editable));
196 
197   project = g_object_get_qdata (G_OBJECT (editable), glade_editable_project_quark);
198 
199   g_return_if_fail (GLADE_IS_PROJECT (project));
200 
201   g_signal_handlers_block_by_func (project, G_CALLBACK (project_changed), editable);
202 }
203 
204 void
205 glade_editable_unblock (GladeEditable *editable)
206 {
207   GladeProject *project;
208 
209   g_return_if_fail (GLADE_IS_EDITABLE (editable));
210 
211   project = g_object_get_qdata (G_OBJECT (editable), glade_editable_project_quark);
212 
213   g_return_if_fail (GLADE_IS_PROJECT (project));
214 
215   g_signal_handlers_unblock_by_func (project, G_CALLBACK (project_changed), editable);
216 }
217