1 /* an editable expression
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 /* Sub fn. of below.
39 */
40 static void *
expression_get_itext_sub(Row * row)41 expression_get_itext_sub( Row *row )
42 {
43 Model *itext;
44
45 /*
46
47 FIXME ... yuk, map + strcmp
48
49 could make subcolumn indexed by symbol name? probably not
50 worth it
51
52 */
53 if( row->sym &&
54 strcmp( IOBJECT( row->sym )->name, MEMBER_EXPR ) == 0 &&
55 row->child_rhs &&
56 (itext = row->child_rhs->itext) )
57 return( itext );
58
59 return( NULL );
60 }
61
62 /* Look down our RHS and try to grab the itext for our MEMBER_EXPR.
63 * Expressionview presents this as the editable formula.
64 *
65 * We can't call the editable member "value", since this imples (elsewhere in
66 * nip anway) an unboxed value. Our editable member could also be boxed .. so
67 * have a different name of reduce confusion a little. Also means we can
68 * define an Expression which inherits from expr.
69 */
70 iText *
expression_get_itext(Expression * expression)71 expression_get_itext( Expression *expression )
72 {
73 Row *row = HEAPMODEL( expression )->row;
74
75 if( row->child_rhs && row->child_rhs->scol )
76 return( (iText *) subcolumn_map(
77 SUBCOLUMN( row->child_rhs->scol ),
78 (row_map_fn) expression_get_itext_sub,
79 NULL, NULL ) );
80
81 return( NULL );
82 }
83
84 static View *
expression_view_new(Model * model,View * parent)85 expression_view_new( Model *model, View *parent )
86 {
87 return( expressionview_new() );
88 }
89
90 static xmlNode *
expression_save(Model * model,xmlNode * xnode)91 expression_save( Model *model, xmlNode *xnode )
92 {
93 xmlNode *xthis;
94
95 if( !(xthis = MODEL_CLASS( parent_class )->save( model, xnode )) )
96 return( NULL );
97
98 if( !set_sprop( xthis, "caption", IOBJECT( model )->caption ) )
99 return( NULL );
100
101 return( xthis );
102 }
103
104 static gboolean
expression_load(Model * model,ModelLoadState * state,Model * parent,xmlNode * xnode)105 expression_load( Model *model,
106 ModelLoadState *state, Model *parent, xmlNode *xnode )
107 {
108 char caption[MAX_STRSIZE];
109
110 g_assert( IS_RHS( parent ) );
111
112 if( get_sprop( xnode, "caption", caption, MAX_STRSIZE ) )
113 iobject_set( IOBJECT( model ), NULL, caption );
114
115 return( MODEL_CLASS( parent_class )->load( model,
116 state, parent, xnode ) );
117 }
118
119 /* Update Expression from heap.
120 */
121 static gboolean
expression_class_get(Classmodel * classmodel,PElement * root)122 expression_class_get( Classmodel *classmodel, PElement *root )
123 {
124 char caption[MAX_STRSIZE];
125
126 #ifdef DEBUG
127 printf( "expression_class_get: " );
128 row_name_print( HEAPMODEL( classmodel )->row );
129 printf( "\n" );
130 #endif /*DEBUG*/
131
132 if( !class_get_member_string( root, MEMBER_CAPTION,
133 caption, MAX_STRSIZE ) )
134 return( FALSE );
135 iobject_set( IOBJECT( classmodel ), NULL, caption );
136
137 return( TRUE );
138 }
139
140 static void
expression_class_init(ExpressionClass * class)141 expression_class_init( ExpressionClass *class )
142 {
143 ModelClass *model_class = (ModelClass *) class;
144 ClassmodelClass *classmodel_class = (ClassmodelClass *) class;
145
146 parent_class = g_type_class_peek_parent( class );
147
148 /* Create signals.
149 */
150
151 /* Init methods.
152 */
153 model_class->view_new = expression_view_new;
154 model_class->save = expression_save;
155 model_class->load = expression_load;
156
157 classmodel_class->class_get = expression_class_get;
158
159 /* Static init.
160 */
161 model_register_loadable( MODEL_CLASS( class ) );
162 }
163
164 static void
expression_init(Expression * expression)165 expression_init( Expression *expression )
166 {
167 iobject_set( IOBJECT( expression ), CLASS_EXPRESSION, NULL );
168 }
169
170 GType
expression_get_type(void)171 expression_get_type( void )
172 {
173 static GType type = 0;
174
175 if( !type ) {
176 static const GTypeInfo info = {
177 sizeof( ExpressionClass ),
178 NULL, /* base_init */
179 NULL, /* base_finalize */
180 (GClassInitFunc) expression_class_init,
181 NULL, /* class_finalize */
182 NULL, /* class_data */
183 sizeof( Expression ),
184 32, /* n_pexpressionlocs */
185 (GInstanceInitFunc) expression_init,
186 };
187
188 type = g_type_register_static( TYPE_CLASSMODEL,
189 "Expression", &info, 0 );
190 }
191
192 return( type );
193 }
194