1 /* run the display for a option 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 GraphicviewClass *parent_class = NULL;
37 
38 /* Copy a gslist of strings.
39  */
40 static GSList *
lstring_copy(GSList * lstring)41 lstring_copy( GSList *lstring )
42 {
43 	GSList *new;
44 	GSList *p;
45 
46 	new = NULL;
47 	for( p = lstring; p; p = p->next )
48 		new = g_slist_prepend( new,
49 			g_strdup( (const char *) p->data ) );
50 
51 	new = g_slist_reverse( new );
52 
53 	return( new );
54 }
55 
56 /* Are two lstrings equal?
57  */
58 static gboolean
lstring_equal(GSList * a,GSList * b)59 lstring_equal( GSList *a, GSList *b )
60 {
61 	for( ; a && b; a = a->next, b = b->next )
62 		if( strcmp( (const char *) a->data,
63 			(const char *) b->data ) != 0 )
64 			return( FALSE );
65 
66 	if( a || b )
67 		return( FALSE );
68 
69 	return( TRUE );
70 }
71 
72 static void
optionview_destroy(GtkObject * object)73 optionview_destroy( GtkObject *object )
74 {
75 	Optionview *optionview;
76 
77 	g_return_if_fail( object != NULL );
78 	g_return_if_fail( IS_OPTIONVIEW( object ) );
79 
80 	optionview = OPTIONVIEW( object );
81 
82 	/* My instance destroy stuff.
83 	 */
84 	IM_FREEF( slist_free_all, optionview->labels );
85 
86 	GTK_OBJECT_CLASS( parent_class )->destroy( object );
87 }
88 
89 static void
optionview_link(View * view,Model * model,View * parent)90 optionview_link( View *view, Model *model, View *parent )
91 {
92 	Optionview *optionview = OPTIONVIEW( view );
93 
94 	VIEW_CLASS( parent_class )->link( view, model, parent );
95 
96 	if( GRAPHICVIEW( view )->sview )
97 		gtk_size_group_add_widget( GRAPHICVIEW( view )->sview->group,
98 			optionview->label );
99 }
100 
101 /* Change to a optionview widget ... update the model.
102  */
103 static void
optionview_change_cb(GtkWidget * wid,Optionview * optionview)104 optionview_change_cb( GtkWidget *wid, Optionview *optionview )
105 {
106 	Option *option = OPTION( VOBJECT( optionview )->iobject );
107 	Classmodel *classmodel = CLASSMODEL( option );
108 
109 	const int nvalue = gtk_combo_box_get_active(
110 		GTK_COMBO_BOX( optionview->options ) );
111 
112 	if( option->value != nvalue ) {
113 		option->value = nvalue;
114 
115 		classmodel_update( classmodel );
116 		symbol_recalculate_all();
117 	}
118 }
119 
120 static gboolean
optionview_scroll_cb(GtkWidget * wid,GdkEvent * event,Optionview * optionview)121 optionview_scroll_cb( GtkWidget *wid, GdkEvent *event, Optionview *optionview )
122 {
123 	/* Stop any other scroll handlers running. We don't want the scroll
124 	 * wheel to change widgets while we're moving.
125 	 */
126 	return( TRUE );
127 }
128 
129 static void
optionview_refresh(vObject * vobject)130 optionview_refresh( vObject *vobject )
131 {
132 	Optionview *optionview = OPTIONVIEW( vobject );
133 	Option *option = OPTION( VOBJECT( optionview )->iobject );
134 
135 	GSList *p;
136 	int i;
137 
138 #ifdef DEBUG
139 	printf( "optionview_refresh: " );
140 	row_name_print( HEAPMODEL( option )->row );
141 	printf( "\n" );
142 #endif /*DEBUG*/
143 
144 	/* Only rebuild the menu if there's been a change.
145 	 */
146 	if( !lstring_equal( optionview->labels, option->labels ) ) {
147 		/* If the menu is currently up, we can get strange things
148 		 * happening if we destroy it.
149 		 */
150 		if( optionview->options )
151 			gtk_combo_box_popdown(
152 				GTK_COMBO_BOX( optionview->options ) );
153 		IM_FREEF( gtk_widget_destroy, optionview->options );
154 
155 		optionview->options = gtk_combo_box_new_text();
156 		for( p = option->labels, i = 0; p; p = p->next, i++ )
157 			gtk_combo_box_append_text(
158 				GTK_COMBO_BOX( optionview->options ),
159 				(const char *) p->data );
160 		gtk_box_pack_start( GTK_BOX( optionview->hbox ),
161 			optionview->options, TRUE, TRUE, 0 );
162 
163 		gtk_signal_connect( GTK_OBJECT( optionview->options ),
164 			"changed",
165 			GTK_SIGNAL_FUNC( optionview_change_cb ), optionview );
166 		gtk_widget_show( optionview->options );
167 
168 		IM_FREEF( slist_free_all, optionview->labels );
169 		optionview->labels = lstring_copy( option->labels );
170 
171 		g_signal_connect( GTK_OBJECT( optionview->options ),
172 			"scroll-event",
173 			GTK_SIGNAL_FUNC( optionview_scroll_cb ), optionview );
174 	}
175 
176 	if( optionview->options ) {
177 		gtk_signal_handler_block_by_data(
178 			GTK_OBJECT( optionview->options ), optionview );
179 		gtk_combo_box_set_active( GTK_COMBO_BOX( optionview->options ),
180 			option->value );
181 		gtk_signal_handler_unblock_by_data(
182 			GTK_OBJECT( optionview->options ), optionview );
183 	}
184 
185 	set_glabel( optionview->label, _( "%s:" ), IOBJECT( option )->caption );
186 
187 	VOBJECT_CLASS( parent_class )->refresh( vobject );
188 }
189 
190 static void
optionview_class_init(OptionviewClass * class)191 optionview_class_init( OptionviewClass *class )
192 {
193 	GtkObjectClass *object_class = (GtkObjectClass *) class;
194 	vObjectClass *vobject_class = (vObjectClass *) class;
195 	ViewClass *view_class = (ViewClass *) class;
196 
197 	parent_class = g_type_class_peek_parent( class );
198 
199 	object_class->destroy = optionview_destroy;
200 
201 	/* Create signals.
202 	 */
203 
204 	/* Init methods.
205 	 */
206 	vobject_class->refresh = optionview_refresh;
207 
208 	view_class->link = optionview_link;
209 }
210 
211 static void
optionview_init(Optionview * optionview)212 optionview_init( Optionview *optionview )
213 {
214         optionview->hbox = gtk_hbox_new( FALSE, 12 );
215         gtk_box_pack_start( GTK_BOX( optionview ),
216 		optionview->hbox, TRUE, FALSE, 0 );
217 
218         optionview->label = gtk_label_new( "" );
219         gtk_misc_set_alignment( GTK_MISC( optionview->label ), 0, 0.5 );
220 	gtk_box_pack_start( GTK_BOX( optionview->hbox ),
221 		optionview->label, FALSE, FALSE, 2 );
222 
223 	optionview->options = NULL;
224 
225 	optionview->labels = NULL;
226 
227         gtk_widget_show_all( optionview->hbox );
228 }
229 
230 GtkType
optionview_get_type(void)231 optionview_get_type( void )
232 {
233 	static GtkType optionview_type = 0;
234 
235 	if( !optionview_type ) {
236 		static const GtkTypeInfo sinfo = {
237 			"Optionview",
238 			sizeof( Optionview ),
239 			sizeof( OptionviewClass ),
240 			(GtkClassInitFunc) optionview_class_init,
241 			(GtkObjectInitFunc) optionview_init,
242 			/* reserved_1 */ NULL,
243 			/* reserved_2 */ NULL,
244 			(GtkClassInitFunc) NULL,
245 		};
246 
247 		optionview_type = gtk_type_unique( TYPE_GRAPHICVIEW, &sinfo );
248 	}
249 
250 	return( optionview_type );
251 }
252 
253 View *
optionview_new(void)254 optionview_new( void )
255 {
256 	Optionview *optionview = gtk_type_new( TYPE_OPTIONVIEW );
257 
258 	return( VIEW( optionview ) );
259 }
260