1 /* abstract base class for all nip objects
2  */
3 
4 /*
5 
6     Copyright (C) 1991-2003 The National Gallery
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License along
19     with this program; if not, write to the Free Software Foundation, Inc.,
20     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 
22  */
23 
24 /*
25 
26     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27 
28  */
29 
30 /*
31 #define DEBUG
32  */
33 
34 #include "ip.h"
35 
36 /* Our signals.
37  */
38 enum {
39 	SIG_DESTROY,	/* End lifetime */
40 	SIG_CHANGED,	/* iObject has changed somehow */
41 	SIG_LAST
42 };
43 
44 static GObjectClass *parent_class = NULL;
45 
46 static guint iobject_signals[SIG_LAST] = { 0 };
47 
48 /* Don't emit "destroy" immediately, do it from the _dispose handler.
49  */
50 void *
iobject_destroy(iObject * iobject)51 iobject_destroy( iObject *iobject )
52 {
53 #ifdef DEBUG
54 	printf( "iobject_destroy: " );
55 	iobject_print( iobject );
56 #endif /*DEBUG*/
57 
58 	if( !iobject->in_destruction )
59 		g_object_run_dispose( G_OBJECT( iobject ) );
60 
61 	return( NULL );
62 }
63 
64 void *
iobject_changed(iObject * iobject)65 iobject_changed( iObject *iobject )
66 {
67 	g_return_val_if_fail( iobject != NULL, NULL );
68 	g_return_val_if_fail( IS_IOBJECT( iobject ), NULL );
69 
70 #ifdef DEBUG
71 	printf( "iobject_changed: " );
72 	iobject_print( iobject );
73 #endif /*DEBUG*/
74 
75 	g_signal_emit( G_OBJECT( iobject ), iobject_signals[SIG_CHANGED], 0 );
76 
77 	return( NULL );
78 }
79 
80 void *
iobject_info(iObject * iobject,VipsBuf * buf)81 iobject_info( iObject *iobject, VipsBuf *buf )
82 {
83 	iObjectClass *iobject_class = IOBJECT_GET_CLASS( iobject );
84 
85 	g_return_val_if_fail( iobject != NULL, NULL );
86 	g_return_val_if_fail( IS_IOBJECT( iobject ), NULL );
87 
88 	if( iobject_class->info )
89 		iobject_class->info( iobject, buf );
90 
91 	return( NULL );
92 }
93 
94 static void
iobject_dispose(GObject * gobject)95 iobject_dispose( GObject *gobject )
96 {
97 	iObject *iobject = IOBJECT( gobject );
98 
99 #ifdef DEBUG
100 	printf( "iobject_dispose: " );
101 	iobject_print( iobject );
102 #endif /*DEBUG*/
103 
104 	if( !iobject->in_destruction ) {
105 		iobject->in_destruction = TRUE;
106 		g_signal_emit( G_OBJECT( iobject ),
107 			iobject_signals[SIG_DESTROY], 0 );
108 		iobject->in_destruction = FALSE;
109 	}
110 
111 	G_OBJECT_CLASS( parent_class )->dispose( gobject );
112 }
113 
114 static void
iobject_finalize(GObject * gobject)115 iobject_finalize( GObject *gobject )
116 {
117 	iObject *iobject = IOBJECT( gobject );
118 
119 #ifdef DEBUG
120 	printf( "iobject_finalize: " );
121 	iobject_print( iobject );
122 #endif /*DEBUG*/
123 
124 	/* Unlike GTK, we allow floating objects to be finalized. Handy if a
125 	 * _new() fails. So don't assert( !iobject->floating );
126 	 */
127 
128 	IM_FREE( iobject->name );
129 	IM_FREE( iobject->caption );
130 
131 	G_OBJECT_CLASS( parent_class )->finalize( gobject );
132 }
133 
134 static void
iobject_real_destroy(iObject * iobject)135 iobject_real_destroy( iObject *iobject )
136 {
137 }
138 
139 static void
iobject_real_changed(iObject * iobject)140 iobject_real_changed( iObject *iobject )
141 {
142 	iObjectClass *iobject_class = IOBJECT_GET_CLASS( iobject );
143 
144 	if( iobject_class->generate_caption )
145 		IM_SETSTR( iobject->caption,
146 			iobject_class->generate_caption( iobject ) );
147 }
148 
149 static void
iobject_real_info(iObject * iobject,VipsBuf * buf)150 iobject_real_info( iObject *iobject, VipsBuf *buf )
151 {
152 	if( iobject->name )
153 		vips_buf_appendf( buf, "name = \"%s\"\n", iobject->name );
154 	if( iobject->caption )
155 		vips_buf_appendf( buf, "caption = \"%s\"\n", iobject->caption );
156 	vips_buf_appendf( buf, "iObject :: \"%s\"\n",
157 		G_OBJECT_TYPE_NAME( iobject ) );
158 }
159 
160 static void
iobject_class_init(iObjectClass * class)161 iobject_class_init( iObjectClass *class )
162 {
163 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
164 
165 	parent_class = g_type_class_peek_parent( class );
166 
167 	gobject_class->dispose = iobject_dispose;
168 	gobject_class->finalize = iobject_finalize;
169 
170 	class->destroy = iobject_real_destroy;
171 	class->changed = iobject_real_changed;
172 	class->info = iobject_real_info;
173 	class->generate_caption = NULL;
174 
175 	class->user_name = _( "Object" );
176 
177 	/* Create signals.
178 	 */
179 	iobject_signals[SIG_DESTROY] = g_signal_new( "destroy",
180 		G_TYPE_FROM_CLASS( gobject_class ),
181 		G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
182 		G_STRUCT_OFFSET( iObjectClass, destroy ),
183 		NULL, NULL,
184 		g_cclosure_marshal_VOID__VOID,
185 		G_TYPE_NONE, 0 );
186 	iobject_signals[SIG_CHANGED] = g_signal_new( "changed",
187 		G_OBJECT_CLASS_TYPE( gobject_class ),
188 		G_SIGNAL_RUN_FIRST,
189 		G_STRUCT_OFFSET( iObjectClass, changed ),
190 		NULL, NULL,
191 		g_cclosure_marshal_VOID__VOID,
192 		G_TYPE_NONE, 0 );
193 }
194 
195 static void
iobject_init(iObject * iobject)196 iobject_init( iObject *iobject )
197 {
198 #ifdef DEBUG
199 	printf( "iobject_init: " );
200 	iobject_print( iobject );
201 #endif /*DEBUG*/
202 
203 	/* Init our instance fields.
204 	 */
205 	iobject->name = NULL;
206 	iobject->caption = NULL;
207 	iobject->floating = TRUE;
208 	iobject->in_destruction = FALSE;
209 }
210 
211 GType
iobject_get_type(void)212 iobject_get_type( void )
213 {
214 	static GType iobject_type = 0;
215 
216 	if( !iobject_type ) {
217 		static const GTypeInfo info = {
218 			sizeof( iObjectClass ),
219 			NULL,           /* base_init */
220 			NULL,           /* base_finalize */
221 			(GClassInitFunc) iobject_class_init,
222 			NULL,           /* class_finalize */
223 			NULL,           /* class_data */
224 			sizeof( iObject ),
225 			32,             /* n_preallocs */
226 			(GInstanceInitFunc) iobject_init,
227 		};
228 
229 		iobject_type = g_type_register_static( G_TYPE_OBJECT,
230 			"iObject", &info, 0 );
231 	}
232 
233 	return( iobject_type );
234 }
235 
236 /* Test the name field ... handy with map.
237  */
238 void *
iobject_test_name(iObject * iobject,const char * name)239 iobject_test_name( iObject *iobject, const char *name )
240 {
241 	g_return_val_if_fail( iobject != NULL, NULL );
242 	g_return_val_if_fail( IS_IOBJECT( iobject ), NULL );
243 
244 	if( iobject->name && strcmp( iobject->name, name ) == 0 )
245 		return( iobject );
246 
247 	return( NULL );
248 }
249 
250 void *
iobject_print(iObject * iobject)251 iobject_print( iObject *iobject )
252 {
253 	g_print( "%s \"%s\" (%p)\n",
254 		G_OBJECT_TYPE_NAME( iobject ),
255 		NN( iobject->name ),
256 		iobject );
257 
258 	return( NULL );
259 }
260 
261 void
iobject_set(iObject * iobject,const char * name,const char * caption)262 iobject_set( iObject *iobject, const char *name, const char *caption )
263 {
264 	gboolean changed = FALSE;
265 
266 	g_return_if_fail( iobject != NULL );
267 	g_return_if_fail( IS_IOBJECT( iobject ) );
268 
269 	if( name && name != iobject->name ) {
270 		IM_SETSTR( iobject->name, name );
271 		changed = TRUE;
272 	}
273 	if( caption && caption != iobject->caption ) {
274 		IM_SETSTR( iobject->caption, caption );
275 		changed = TRUE;
276 	}
277 
278 	if( changed )
279 		iobject_changed( iobject );
280 
281 #ifdef DEBUG
282 	printf( "iobject_set: " );
283 	iobject_print( iobject );
284 #endif /*DEBUG*/
285 }
286 
287 void
iobject_sink(iObject * iobject)288 iobject_sink( iObject *iobject )
289 {
290 	g_assert( IS_IOBJECT( iobject ) );
291 
292 	if( iobject->floating ) {
293 		iobject->floating = FALSE;
294 		g_object_unref( G_OBJECT( iobject ) );
295 	}
296 }
297 
298 void
iobject_dump(iObject * iobject)299 iobject_dump( iObject *iobject )
300 {
301 	char txt[1000];
302 	VipsBuf buf = VIPS_BUF_STATIC( txt );
303 
304 	iobject_info( iobject, &buf );
305 	printf( "%s", vips_buf_all( &buf ) );
306 }
307