1 /* an ip arrow class object in a workspace
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 static ClassmodelClass *parent_class = NULL;
37
38 static void
iarrow_finalize(GObject * gobject)39 iarrow_finalize( GObject *gobject )
40 {
41 iArrow *iarrow;
42
43 #ifdef DEBUG
44 printf( "iarrow_finalize\n" );
45 #endif /*DEBUG*/
46
47 g_return_if_fail( gobject != NULL );
48 g_return_if_fail( IS_IARROW( gobject ) );
49
50 iarrow = IARROW( gobject );
51
52 /* My instance finalize stuff.
53 */
54 iregion_instance_destroy( &iarrow->instance );
55 vips_buf_destroy( &iarrow->caption_buffer );
56
57 G_OBJECT_CLASS( parent_class )->finalize( gobject );
58 }
59
60 static void *
iarrow_generate_caption_sub(iImage * iimage,iArrow * iarrow,gboolean * first)61 iarrow_generate_caption_sub( iImage *iimage, iArrow *iarrow, gboolean *first )
62 {
63 Workspace *ws = HEAPMODEL( iarrow )->row->ws;
64 Row *row = HEAPMODEL( iimage )->row;
65
66 /* Suppress this name in the caption if it's a superclass. If this
67 * thing is on a super, it's on the subclass too ... not helpful to
68 * have it twice.
69 */
70 if( !is_super( row->sym ) ) {
71 if( *first )
72 *first = FALSE;
73 else
74 vips_buf_appends( &iarrow->caption_buffer, ", " );
75
76 row_qualified_name_relative( ws->sym, row,
77 &iarrow->caption_buffer );
78 }
79
80 return( NULL );
81 }
82
83 static const char *
iarrow_generate_caption(iObject * iobject)84 iarrow_generate_caption( iObject *iobject )
85 {
86 static const char *names[] = {
87 CLASS_HGUIDE,
88 CLASS_VGUIDE,
89 CLASS_MARK,
90 CLASS_ARROW,
91 NULL
92 };
93
94 iArrow *iarrow = IARROW( iobject );
95 VipsBuf *buf = &iarrow->caption_buffer;
96 const int nimages = g_slist_length( CLASSMODEL( iarrow )->iimages );
97 Expr *expr;
98 gboolean result;
99 gboolean first;
100 int i;
101
102 if( !HEAPMODEL( iarrow )->row ||
103 !(expr = HEAPMODEL( iarrow )->row->expr) ||
104 !heap_is_class( &expr->root, &result ) ||
105 !result )
106 return( _( "No image" ) );
107
108 vips_buf_rewind( buf );
109 heapmodel_name( HEAPMODEL( iarrow ), buf );
110 vips_buf_appendf( buf, " " );
111
112 /* Used in (eg.) "Mark at (10, 10) on [A1, A2]"
113 */
114 vips_buf_appendf( buf, _( "on" ) );
115 vips_buf_appendf( buf, " " );
116 if( nimages > 1 )
117 vips_buf_appendf( buf, "[" );
118 first = TRUE;
119 slist_map2( CLASSMODEL( iarrow )->iimages,
120 (SListMap2Fn) iarrow_generate_caption_sub, iarrow, &first );
121 if( nimages > 1 )
122 vips_buf_appendf( buf, "]" );
123 vips_buf_appendf( buf, " " );
124
125 for( i = 0; names[i]; i++ ) {
126 if( !heap_is_instanceof( names[i], &expr->root, &result ) )
127 break;
128
129 if( result ) {
130 switch( i ) {
131 case 0:
132 vips_buf_appendf( buf, _( "at %d" ),
133 iarrow->instance.area.top );
134 break;
135
136 case 1:
137 vips_buf_appendf( buf, _( "at %d" ),
138 iarrow->instance.area.left );
139 break;
140
141 case 2:
142 vips_buf_appendf( buf, _( "at (%d, %d)" ),
143 iarrow->instance.area.left,
144 iarrow->instance.area.top );
145 break;
146
147 case 3:
148 vips_buf_appendf( buf,
149 _( "at (%d, %d), offset (%d, %d)" ),
150 iarrow->instance.area.left,
151 iarrow->instance.area.top,
152 iarrow->instance.area.width,
153 iarrow->instance.area.height );
154 break;
155
156 default:
157 g_assert( 0 );
158 }
159
160 break;
161 }
162 }
163
164 return( vips_buf_all( buf ) );
165 }
166
167 static View *
iarrow_view_new(Model * model,View * parent)168 iarrow_view_new( Model *model, View *parent )
169 {
170 return( valueview_new() );
171 }
172
173 static void *
iarrow_update_model(Heapmodel * heapmodel)174 iarrow_update_model( Heapmodel *heapmodel )
175 {
176 /* Parent first ... this will update our instance vars.
177 */
178 if( HEAPMODEL_CLASS( parent_class )->update_model( heapmodel ) )
179 return( heapmodel );
180
181 if( heapmodel->row->expr ) {
182 iArrow *iarrow = IARROW( heapmodel );
183
184 /* Update who-has-displays-on-what stuff.
185 */
186 classmodel_iimage_update( CLASSMODEL( iarrow ),
187 iarrow->instance.ii );
188
189 /* Need to make sure the caption is regenerated.
190 */
191 iobject_changed( IOBJECT( heapmodel ) );
192 }
193
194 return( NULL );
195 }
196
197 static void *
iarrow_get_instance(Classmodel * classmodel)198 iarrow_get_instance( Classmodel *classmodel )
199 {
200 iArrow *iarrow = IARROW( classmodel );
201
202 return( &iarrow->instance );
203 }
204
205 static void
iarrow_class_init(iArrowClass * class)206 iarrow_class_init( iArrowClass *class )
207 {
208 GObjectClass *gobject_class = (GObjectClass *) class;
209 iObjectClass *iobject_class = (iObjectClass *) class;
210 iContainerClass *icontainer_class = (iContainerClass *) class;
211 ModelClass *model_class = (ModelClass *) class;
212 HeapmodelClass *heapmodel_class = (HeapmodelClass *) class;
213 ClassmodelClass *classmodel_class = (ClassmodelClass *) class;
214
215 /* We share methods with iregion in a sort of MI way ... iregion needs
216 * to be initialised before we can work. Force it to start up.
217 */
218 (void) iregion_get_type();
219
220 parent_class = g_type_class_peek_parent( class );
221
222 /* Create signals.
223 */
224
225 /* Init methods.
226 */
227 gobject_class->finalize = iarrow_finalize;
228
229 iobject_class->generate_caption = iarrow_generate_caption;
230
231 icontainer_class->parent_add = iregion_parent_add;
232
233 model_class->view_new = iarrow_view_new;
234 model_class->edit = iregion_edit;
235 model_class->save = iregion_save;
236 model_class->load = iregion_load;
237
238 heapmodel_class->update_model = iarrow_update_model;
239 heapmodel_class->update_heap = iregion_update_heap;
240
241 classmodel_class->class_get = iregion_class_get;
242 classmodel_class->class_new = iregion_class_new;
243 classmodel_class->get_instance = iarrow_get_instance;
244
245 /* Static init.
246 */
247 model_register_loadable( MODEL_CLASS( class ) );
248 }
249
250 static void
iarrow_init(iArrow * iarrow)251 iarrow_init( iArrow *iarrow )
252 {
253 iregion_instance_init( &iarrow->instance, CLASSMODEL( iarrow ) );
254 vips_buf_init_dynamic( &iarrow->caption_buffer, MAX_LINELENGTH );
255
256 iobject_set( IOBJECT( iarrow ), CLASS_ARROW, NULL );
257 }
258
259 GType
iarrow_get_type(void)260 iarrow_get_type( void )
261 {
262 static GType type = 0;
263
264 if( !type ) {
265 static const GTypeInfo info = {
266 sizeof( iArrowClass ),
267 NULL, /* base_init */
268 NULL, /* base_finalize */
269 (GClassInitFunc) iarrow_class_init,
270 NULL, /* class_finalize */
271 NULL, /* class_data */
272 sizeof( iArrow ),
273 32, /* n_preallocs */
274 (GInstanceInitFunc) iarrow_init,
275 };
276
277 type = g_type_register_static( TYPE_CLASSMODEL,
278 "iArrow", &info, 0 );
279 }
280
281 return( type );
282 }
283