1 /* Workspace-local defs.
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 ViewClass *parent_class = NULL;
37 
38 static void
workspacedefs_text_changed(GtkTextBuffer * buffer,Workspacedefs * workspacedefs)39 workspacedefs_text_changed( GtkTextBuffer *buffer,
40 	Workspacedefs *workspacedefs )
41 {
42 #ifdef DEBUG
43 	printf( "workspacedefs_text_changed\n" );
44 #endif /*DEBUG*/
45 
46 	if( !workspacedefs->changed ) {
47 		workspacedefs->changed = TRUE;
48 
49 #ifdef DEBUG
50 		printf( "\t(changed = TRUE)\n" );
51 #endif /*DEBUG*/
52 
53 		/* The workspace hasn't changed, but this will queue a refresh
54 		 * on us.
55 		 */
56 		iobject_changed( IOBJECT( workspacedefs->ws ) );
57 	}
58 }
59 
60 static void
workspacedefs_refresh(vObject * vobject)61 workspacedefs_refresh( vObject *vobject )
62 {
63 	Workspacedefs *workspacedefs = WORKSPACEDEFS( vobject );
64 	Workspace *ws = workspacedefs->ws;
65 	char txt[256];
66 	VipsBuf buf = VIPS_BUF_STATIC( txt );
67 
68 #ifdef DEBUG
69 	printf( "workspacedefs_refresh:\n" );
70 #endif /*DEBUG*/
71 
72 	if( !workspacedefs->changed ) {
73 		guint text_hash = g_str_hash( ws->local_defs );
74 
75 		if( text_hash != workspacedefs->text_hash ) {
76 			g_signal_handlers_block_by_func(
77 				gtk_text_view_get_buffer(
78 					GTK_TEXT_VIEW( workspacedefs->text ) ),
79 				workspacedefs_text_changed, workspacedefs );
80 			text_view_set_text(
81 				GTK_TEXT_VIEW( workspacedefs->text ),
82 				ws->local_defs, TRUE );
83 			g_signal_handlers_unblock_by_func(
84 				gtk_text_view_get_buffer(
85 					GTK_TEXT_VIEW( workspacedefs->text ) ),
86 				workspacedefs_text_changed, workspacedefs );
87 
88 			workspacedefs->text_hash = text_hash;
89 		}
90 	}
91 
92 	if( ws->local_kit ) {
93 		int n = icontainer_get_n_children( ICONTAINER(
94 			ws->local_kit ) );
95 
96 		vips_buf_appendf( &buf, ngettext( "%d definition",
97 			"%d definitions", n ), n );
98 	}
99 	if( workspacedefs->errors ) {
100 		if( !vips_buf_is_empty( &buf ) )
101 			vips_buf_appendf( &buf, ", " );
102 		vips_buf_appendf( &buf, _( "errors" ) );
103 	}
104 	if( workspacedefs->changed ) {
105 		if( !vips_buf_is_empty( &buf ) )
106 			vips_buf_appendf( &buf, ", " );
107 		vips_buf_appendf( &buf, _( "modified" ) );
108 	}
109 	set_glabel( workspacedefs->status, "%s", vips_buf_all( &buf ) );
110 
111 	VOBJECT_CLASS( parent_class )->refresh( vobject );
112 }
113 
114 static void
workspacedefs_link(vObject * vobject,iObject * iobject)115 workspacedefs_link( vObject *vobject, iObject *iobject )
116 {
117 	Workspacedefs *workspacedefs = WORKSPACEDEFS( vobject );
118 	Workspace *ws = WORKSPACE( iobject );
119 
120 	g_assert( !workspacedefs->ws );
121 
122 	workspacedefs->ws = ws;
123 
124 	VOBJECT_CLASS( parent_class )->link( vobject, iobject );
125 }
126 
127 static void
workspacedefs_class_init(WorkspacedefsClass * class)128 workspacedefs_class_init( WorkspacedefsClass *class )
129 {
130 	vObjectClass *vobject_class = (vObjectClass *) class;
131 
132 	parent_class = g_type_class_peek_parent( class );
133 
134 	vobject_class->refresh = workspacedefs_refresh;
135 	vobject_class->link = workspacedefs_link;
136 }
137 
138 static gboolean
workspacedefs_set_text_from_file(Workspacedefs * workspacedefs,const char * fname)139 workspacedefs_set_text_from_file( Workspacedefs *workspacedefs,
140 	const char *fname )
141 {
142 	Workspace *ws = workspacedefs->ws;
143 
144 	workspacedefs->changed = FALSE;
145 	workspacedefs->errors = FALSE;
146 	if( !workspace_local_set_from_file( ws, fname ) ) {
147 		text_view_select_text( GTK_TEXT_VIEW( workspacedefs->text ),
148 			input_state.charpos - yyleng, input_state.charpos );
149 		workspacedefs->errors = TRUE;
150 
151 		return( FALSE );
152 	}
153 
154 	symbol_recalculate_all();
155 
156 	return( TRUE );
157 }
158 
159 /* Callback from load browser.
160  */
161 static void
workspacedefs_load_file_cb(iWindow * iwnd,void * client,iWindowNotifyFn nfn,void * sys)162 workspacedefs_load_file_cb( iWindow *iwnd,
163 	void *client, iWindowNotifyFn nfn, void *sys )
164 {
165 	Filesel *filesel = FILESEL( iwnd );
166 	Workspacedefs *workspacedefs = WORKSPACEDEFS( client );
167 	char *fname;
168 
169 	if( !(fname = filesel_get_filename( filesel )) ) {
170 		nfn( sys, IWINDOW_ERROR );
171 		return;
172 	}
173 
174 	if( !workspacedefs_set_text_from_file( workspacedefs, fname ) ) {
175 		g_free( fname );
176 		nfn( sys, IWINDOW_ERROR );
177 		return;
178 	}
179 
180 	g_free( fname );
181 
182 	nfn( sys, IWINDOW_YES );
183 }
184 
185 static void
workspacedefs_replace_cb(GtkWidget * wid,Workspacedefs * workspacedefs)186 workspacedefs_replace_cb( GtkWidget *wid, Workspacedefs *workspacedefs )
187 {
188 	GtkWidget *filesel;
189 
190 	filesel = filesel_new();
191 	iwindow_set_title( IWINDOW( filesel ),
192 		_( "Replace Definition From File" ) );
193 	filesel_set_flags( FILESEL( filesel ), FALSE, FALSE );
194 	filesel_set_filetype( FILESEL( filesel ), filesel_type_definition, 0 );
195 	iwindow_set_parent( IWINDOW( filesel ), GTK_WIDGET( wid ) );
196 	filesel_set_done( FILESEL( filesel ),
197 		workspacedefs_load_file_cb, workspacedefs );
198 	iwindow_build( IWINDOW( filesel ) );
199 
200 	gtk_widget_show( GTK_WIDGET( filesel ) );
201 }
202 
203 static void
workspacedefs_save_as_cb(GtkWidget * wid,Workspacedefs * workspacedefs)204 workspacedefs_save_as_cb( GtkWidget *wid, Workspacedefs *workspacedefs )
205 {
206 	Workspace *ws = workspacedefs->ws;
207 
208 	if( ws->local_kit )
209 		filemodel_inter_saveas( IWINDOW( wid ),
210 			FILEMODEL( ws->local_kit ) );
211 }
212 
213 static gboolean
workspacedefs_set_text(Workspacedefs * workspacedefs,const char * txt)214 workspacedefs_set_text( Workspacedefs *workspacedefs, const char *txt )
215 {
216 	Workspace *ws = workspacedefs->ws;
217 
218 	workspacedefs->changed = FALSE;
219 	workspacedefs->errors = FALSE;
220 	workspacedefs->text_hash = g_str_hash( txt );
221 	if( !workspace_local_set( ws, txt ) ) {
222 		text_view_select_text( GTK_TEXT_VIEW( workspacedefs->text ),
223 			input_state.charpos - yyleng, input_state.charpos );
224 		workspacedefs->errors = TRUE;
225 
226 		return( FALSE );
227 	}
228 
229 	symbol_recalculate_all();
230 
231 	return( TRUE );
232 }
233 
234 /* "Process" in defs area.
235  */
236 static void
workspacedefs_process_cb(GtkWidget * wid,Workspacedefs * workspacedefs)237 workspacedefs_process_cb( GtkWidget *wid, Workspacedefs *workspacedefs )
238 {
239 	char *txt;
240 
241 #ifdef DEBUG
242 	printf( "workspacedefs_process_cb:\n" );
243 	printf( "\tchanged = FALSE\n" );
244 #endif /*DEBUG*/
245 
246 	txt = text_view_get_text( GTK_TEXT_VIEW( workspacedefs->text ) );
247 	if( !workspacedefs_set_text( workspacedefs, txt ) )
248 		iwindow_alert( wid, GTK_MESSAGE_ERROR );
249 	g_free( txt );
250 }
251 
252 static void
workspacedefs_init(Workspacedefs * workspacedefs)253 workspacedefs_init( Workspacedefs *workspacedefs )
254 {
255 	GtkWidget *pane;
256 	Popupbutton *popupbutton;
257 	GtkWidget *swin;
258 	GtkWidget *hbox;
259 	GtkWidget *but;
260 
261 #ifdef DEBUG
262 	printf( "workspacedefs_init:\n" );
263 #endif /*DEBUG*/
264 
265 	workspacedefs->changed = FALSE;
266 	workspacedefs->errors = FALSE;
267 	workspacedefs->text_hash = 0;
268 
269 	pane = menu_build( _( "Workspace definitions" ) );
270 	menu_add_but( pane, _( "Replace From _File" ),
271 		GTK_SIGNAL_FUNC( workspacedefs_replace_cb ), workspacedefs );
272 	menu_add_but( pane, GTK_STOCK_SAVE_AS,
273 		GTK_SIGNAL_FUNC( workspacedefs_save_as_cb ), workspacedefs );
274 
275 	hbox = gtk_hbox_new( FALSE, 7 );
276 	gtk_box_pack_start( GTK_BOX( workspacedefs ), hbox, FALSE, FALSE, 0 );
277 	gtk_widget_show( hbox );
278 
279 	popupbutton = popupbutton_new();
280 	popupbutton_set_menu( popupbutton, pane );
281         gtk_box_pack_start( GTK_BOX( hbox ), GTK_WIDGET( popupbutton ),
282 		FALSE, FALSE, 0 );
283 	gtk_widget_show( GTK_WIDGET( popupbutton ) );
284 
285 	but = gtk_button_new_with_label( _( "Process" ) );
286         g_signal_connect( G_OBJECT( but ), "clicked",
287                 G_CALLBACK( workspacedefs_process_cb ), workspacedefs );
288 	gtk_box_pack_start( GTK_BOX( hbox ), but, FALSE, FALSE, 0 );
289 	gtk_widget_show( but );
290 	workspacedefs->status = gtk_label_new( NULL );
291 	gtk_misc_set_alignment( GTK_MISC( workspacedefs->status ), 0, 0.5 );
292 	gtk_box_pack_start( GTK_BOX( hbox ),
293 		workspacedefs->status, TRUE, TRUE, 0 );
294 	gtk_widget_show( workspacedefs->status );
295 
296 	swin = gtk_scrolled_window_new( NULL, NULL );
297 	gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( swin ),
298 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
299 	gtk_box_pack_end( GTK_BOX( workspacedefs ), swin, TRUE, TRUE, 0 );
300 	gtk_widget_show( swin );
301 	workspacedefs->text = program_text_new();
302         g_signal_connect( gtk_text_view_get_buffer(
303 		GTK_TEXT_VIEW( workspacedefs->text ) ), "changed",
304                 G_CALLBACK( workspacedefs_text_changed ), workspacedefs );
305 	gtk_container_add( GTK_CONTAINER( swin ), workspacedefs->text );
306 	gtk_widget_show( workspacedefs->text );
307 }
308 
309 GtkType
workspacedefs_get_type(void)310 workspacedefs_get_type( void )
311 {
312 	static GtkType type = 0;
313 
314 	if( !type ) {
315 		static const GtkTypeInfo info = {
316 			"Workspacedefs",
317 			sizeof( Workspacedefs ),
318 			sizeof( WorkspacedefsClass ),
319 			(GtkClassInitFunc) workspacedefs_class_init,
320 			(GtkObjectInitFunc) workspacedefs_init,
321 			/* reserved_1 */ NULL,
322 			/* reserved_2 */ NULL,
323 			(GtkClassInitFunc) NULL,
324 		};
325 
326 		type = gtk_type_unique( TYPE_VOBJECT, &info );
327 	}
328 
329 	return( type );
330 }
331 
332 Workspacedefs *
workspacedefs_new(void)333 workspacedefs_new( void )
334 {
335 	Workspacedefs *workspacedefs = gtk_type_new( TYPE_WORKSPACEDEFS );
336 
337 	return( workspacedefs );
338 }
339 
340