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