1 /* make and manage base dialogs ... subclass off this for others
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 #include "ip.h"
31
32 /*
33 #define DEBUG
34 */
35
36 static iWindowClass *parent_class = NULL;
37
38 /* An OK button: label (can be a stock) plus a callback.
39 */
40 typedef struct {
41 char *label;
42 iWindowFn done_cb;
43 } OKButton;
44
45 static void *
okbutton_free(OKButton * ok)46 okbutton_free( OKButton *ok )
47 {
48 IM_FREEF( g_free, ok->label );
49 ok->done_cb = NULL;
50 IM_FREEF( g_free, ok );
51
52 return( NULL );
53 }
54
55 static OKButton *
okbutton_new(char * label,iWindowFn done_cb)56 okbutton_new( char *label, iWindowFn done_cb )
57 {
58 OKButton *ok;
59
60 ok = g_new( OKButton, 1 );
61 ok->label = g_strdup( label );
62 ok->done_cb = done_cb;
63
64 return( ok );
65 }
66
67 /* Handy destroy callback ... just free client.
68 */
69 void
idialog_free_client(iDialog * idlg,void * client)70 idialog_free_client( iDialog *idlg, void *client )
71 {
72 IM_FREE( client );
73 }
74
75 /* Notify our parent.
76 */
77 static void
idialog_notify_parent(iDialog * idlg,iWindowResult result)78 idialog_notify_parent( iDialog *idlg, iWindowResult result )
79 {
80 if( idlg->nfn ) {
81 iWindowNotifyFn nfn = idlg->nfn;
82
83 idlg->nfn = NULL;
84 nfn( idlg->sys, result );
85 }
86 }
87
88 static void *
idialog_set_sensitive(GtkWidget * w,gboolean state)89 idialog_set_sensitive( GtkWidget *w, gboolean state )
90 {
91 gtk_widget_set_sensitive( w, state );
92
93 return( NULL );
94 }
95
96 /* Set OK sensitivities.
97 */
98 void
idialog_set_ok_button_state(iDialog * idlg,gboolean state)99 idialog_set_ok_button_state( iDialog *idlg, gboolean state )
100 {
101 slist_map( idlg->ok_but_l,
102 (SListMapFn) idialog_set_sensitive, GINT_TO_POINTER( state ) );
103 }
104
105 /* Set all the button sensitivities.
106 */
107 static void
idialog_set_button_state(iDialog * idlg,gboolean state)108 idialog_set_button_state( iDialog *idlg, gboolean state )
109 {
110 idialog_set_ok_button_state( idlg, state );
111 if( idlg->but_cancel )
112 gtk_widget_set_sensitive( idlg->but_cancel, state );
113 if( idlg->but_help )
114 gtk_widget_set_sensitive( idlg->but_help, state );
115 }
116
117 /* Sub-fn of below. Come back from a popdown notify.
118 */
119 static void
idialog_popdown_notify(void * sys,iWindowResult result)120 idialog_popdown_notify( void *sys, iWindowResult result )
121 {
122 iWindowSusp *susp = IWINDOW_SUSP( sys );
123 iDialog *idlg = IDIALOG( susp->client );
124
125 if( result == IWINDOW_YES )
126 /* If our caller hasn't been notified yet, post off a FALSE.
127 */
128 idialog_notify_parent( idlg, IWINDOW_NO );
129
130 /* Pass result on to our suspension (ie. back to iwindow).
131 */
132 iwindow_susp_return( susp, result );
133
134 /* Housekeeping.
135 */
136 iwindow_notify_return( IWINDOW( idlg ) );
137 }
138
139 /* Our popdown callback ... here from iwindow.
140 */
141 static void
idialog_popdown_cb(iWindow * iwnd,void * client,iWindowNotifyFn nfn,void * sys)142 idialog_popdown_cb( iWindow *iwnd, void *client,
143 iWindowNotifyFn nfn, void *sys )
144 {
145 iDialog *idlg = IDIALOG( client );
146 iWindowSusp *susp = iwindow_susp_new( NULL, iwnd, idlg, nfn, sys );
147
148 #ifdef DEBUG
149 printf( "idialog_popdown_cb: %s\n", IWINDOW( idlg )->title );
150 #endif /*DEBUG*/
151
152 /* Trigger user popdown.
153 */
154 iwindow_notify_send( IWINDOW( idlg ),
155 idlg->popdown_cb, idlg->client, idialog_popdown_notify, susp );
156 }
157
158 /* Sub-fn of below. Come back from a done notify.
159 */
160 static void
idialog_done_notify(void * sys,iWindowResult result)161 idialog_done_notify( void *sys, iWindowResult result )
162 {
163 iDialog *idlg = IDIALOG( sys );
164
165 #ifdef DEBUG
166 printf( "idialog_done_notify: %s\n", IWINDOW( idlg )->title );
167 #endif /*DEBUG*/
168
169 idialog_set_button_state( idlg, TRUE );
170
171 /* If all ok, popdown and tell our parent.
172 */
173 if( result == IWINDOW_YES ) {
174 /* Unless we're pinned up, that is.
175 */
176 if( !(idlg->tog_pin &&
177 gtk_toggle_button_get_active(
178 GTK_TOGGLE_BUTTON( idlg->tog_pin ) )) ) {
179 idialog_notify_parent( idlg, result );
180 iwindow_kill( IWINDOW( idlg ) );
181 }
182 }
183
184 /* Alert on failure.
185 */
186 if( result == IWINDOW_ERROR )
187 iwindow_alert( GTK_WIDGET( idlg ), GTK_MESSAGE_ERROR );
188
189 /* Clean up.
190 */
191 iwindow_notify_return( IWINDOW( idlg ) );
192 }
193
194 /* Make a DONE event happen. Used (for example) by the browse window to force
195 * a done in the enclosing FSB on double click on icon.
196 */
197 void
idialog_done_trigger(iDialog * idlg,int pos)198 idialog_done_trigger( iDialog *idlg, int pos )
199 {
200 OKButton *ok = (OKButton *) g_slist_nth_data( idlg->ok_disp_l, pos );
201
202 #ifdef DEBUG
203 printf( "idialog_done_trigger: %s, %d\n",
204 IWINDOW( idlg )->title, pos );
205 #endif /*DEBUG*/
206
207 /* Trigger user done callback.
208 */
209 g_assert( pos >= 0 );
210 g_assert( ok->done_cb );
211 idialog_set_button_state( idlg, FALSE );
212 iwindow_notify_send( IWINDOW( idlg ),
213 ok->done_cb, idlg->client, idialog_done_notify, idlg );
214 }
215
216 /* Sub-fn of below.
217 */
218 static void
idialog_cancel_notify(void * sys,iWindowResult result)219 idialog_cancel_notify( void *sys, iWindowResult result )
220 {
221 iDialog *idlg = IDIALOG( sys );
222
223 #ifdef DEBUG
224 printf( "idialog_cancel_notify: %s\n", IWINDOW( idlg )->title );
225 #endif /*DEBUG*/
226
227 idialog_set_button_state( idlg, TRUE );
228
229 /* Send cancel message back to parent if our client cancel was OK.
230 */
231 if( result == IWINDOW_YES ) {
232 idialog_notify_parent( idlg, IWINDOW_NO );
233 iwindow_kill( IWINDOW( idlg ) );
234 }
235
236 /* Alert on error.
237 */
238 if( result == IWINDOW_ERROR )
239 iwindow_alert( GTK_WIDGET( idlg ), GTK_MESSAGE_ERROR );
240
241 /* Clean up.
242 */
243 iwindow_notify_return( IWINDOW( idlg ) );
244 }
245
246 static void
idialog_cancel_trigger(iDialog * idlg)247 idialog_cancel_trigger( iDialog *idlg )
248 {
249 #ifdef DEBUG
250 printf( "idialog_cancel_trigger: %s\n", IWINDOW( idlg )->title );
251 #endif /*DEBUG*/
252
253 /* Trigger user cancel function.
254 */
255 idialog_set_button_state( idlg, FALSE );
256 iwindow_notify_send( IWINDOW( idlg ),
257 idlg->cancel_cb, idlg->client, idialog_cancel_notify, idlg );
258 }
259
260 /* Button callbacks from gtk.
261 */
262 static void
idialog_done_cb(GtkWidget * w,iDialog * idlg)263 idialog_done_cb( GtkWidget *w, iDialog *idlg )
264 {
265 int pos = g_slist_index( idlg->ok_but_l, w );
266
267 g_assert( pos != -1 );
268
269 idialog_done_trigger( idlg, pos );
270 }
271
272 static void
idialog_cancel_cb(GtkWidget * w,iDialog * idlg)273 idialog_cancel_cb( GtkWidget *w, iDialog *idlg )
274 {
275 idialog_cancel_trigger( idlg );
276 }
277
278 static void
idialog_help_cb(GtkWidget * w,iDialog * idlg)279 idialog_help_cb( GtkWidget *w, iDialog *idlg )
280 {
281 if( idlg->help_tag )
282 box_help( GTK_WIDGET( idlg ), idlg->help_tag );
283 }
284
285 static void
idialog_destroy(GtkObject * object)286 idialog_destroy( GtkObject *object )
287 {
288 iDialog *idlg;
289
290 #ifdef DEBUG
291 printf( "idialog_destroy\n" );
292 #endif /*DEBUG*/
293
294 g_return_if_fail( object != NULL );
295 g_return_if_fail( IS_IDIALOG( object ) );
296
297 idlg = IDIALOG( object );
298
299 #ifdef DEBUG
300 printf( "... %s\n", IWINDOW( idlg )->title );
301 #endif /*DEBUG*/
302
303 /* My instance destroy stuff.
304 */
305
306 if( idlg->destroy_cb ) {
307 idlg->destroy_cb( idlg, idlg->client );
308 idlg->destroy_cb = NULL;
309 }
310
311 FREESID( idlg->destroy_sid, idlg->iobject );
312 slist_map( idlg->ok_l, (SListMapFn) okbutton_free, NULL );
313 IM_FREEF( g_slist_free, idlg->ok_l );
314 IM_FREEF( g_slist_free, idlg->ok_disp_l );
315 IM_FREEF( g_slist_free, idlg->ok_but_l );
316
317 GTK_OBJECT_CLASS( parent_class )->destroy( object );
318 }
319
320 static void
idialog_realize(GtkWidget * widget)321 idialog_realize( GtkWidget *widget )
322 {
323 iDialog *idlg = IDIALOG( widget );
324
325 #ifdef DEBUG
326 printf( "idialog_realize: %s\n", IWINDOW( idlg )->title );
327 #endif /*DEBUG*/
328
329 GTK_WIDGET_CLASS( parent_class )->realize( widget );
330
331 if( idlg->entry )
332 gtk_widget_grab_focus( GTK_WIDGET( idlg->entry ) );
333 }
334
335 /* The object we represent has been destroyed, kill us too.
336 */
337 static void
idialog_iobject_destroy(iObject * iobject,iDialog * idlg)338 idialog_iobject_destroy( iObject *iobject, iDialog *idlg )
339 {
340 #ifdef DEBUG
341 printf( "idialog_iobject_destroy: %s\n", IWINDOW( idlg )->title );
342 #endif /*DEBUG*/
343
344 /* This object has gone.
345 */
346 idlg->iobject = NULL;
347
348 iwindow_kill( IWINDOW( idlg ) );
349 }
350
351 static void *
idialog_build_ok(OKButton * ok,iDialog * idlg)352 idialog_build_ok( OKButton *ok, iDialog *idlg )
353 {
354 GtkWidget *but;
355
356 but = build_button( ok->label,
357 GTK_SIGNAL_FUNC( idialog_done_cb ), idlg );
358 idlg->ok_disp_l = g_slist_prepend( idlg->ok_disp_l, ok );
359 idlg->ok_but_l = g_slist_prepend( idlg->ok_but_l, but );
360 gtk_box_pack_start( GTK_BOX( idlg->bb ), but, TRUE, TRUE, 0 );
361 gtk_widget_show( but );
362
363 return( NULL );
364 }
365
366 static void *
idialog_build_cancel(iDialog * idlg)367 idialog_build_cancel( iDialog *idlg )
368 {
369 idlg->but_cancel = build_button( idlg->cancel_text,
370 GTK_SIGNAL_FUNC( idialog_cancel_cb ), idlg );
371 gtk_box_pack_start( GTK_BOX( idlg->bb ),
372 idlg->but_cancel, TRUE, TRUE, 0 );
373 gtk_widget_show( idlg->but_cancel );
374
375 return( NULL );
376 }
377
378 /* Set a button to be the dialog default. Turn off button_focus for complex
379 * dialogs like file_chooser which have their on focus systems.
380 */
381 static void
idialog_set_default(iDialog * idlg,GtkWidget * widget)382 idialog_set_default( iDialog *idlg, GtkWidget *widget )
383 {
384 if( idlg->button_focus )
385 gtk_widget_grab_focus( widget );
386
387 GTK_WIDGET_SET_FLAGS( widget, GTK_CAN_DEFAULT );
388 gtk_window_set_default( GTK_WINDOW( idlg ), widget );
389 }
390
391 static void
idialog_build(GtkWidget * widget)392 idialog_build( GtkWidget *widget )
393 {
394 iDialog *idlg = IDIALOG( widget );
395 iWindow *iwnd = IWINDOW( idlg );
396
397 #ifdef DEBUG
398 printf( "idialog_build: %s\n", iwnd->title );
399 #endif /*DEBUG*/
400
401 /* Call all builds in superclasses.
402 */
403 if( IWINDOW_CLASS( parent_class )->build )
404 (*IWINDOW_CLASS( parent_class )->build)( widget );
405
406 /* delete_event and destroy handled by our superclass.
407 */
408 iwindow_set_popdown( iwnd, idialog_popdown_cb, idlg );
409
410 gtk_window_set_modal( GTK_WINDOW( idlg ), idlg->modal );
411
412 idlg->work = gtk_vbox_new( FALSE, 6 );
413 gtk_container_set_border_width( GTK_CONTAINER( idlg->work ), 12 );
414 gtk_box_pack_start( GTK_BOX( iwnd->work ), idlg->work, TRUE, TRUE, 0 );
415
416 if( !idlg->nosep ) {
417 GtkWidget *sep;
418
419 sep = gtk_hseparator_new();
420 gtk_box_pack_start( GTK_BOX( iwnd->work ),
421 sep, FALSE, FALSE, 2 );
422 gtk_widget_show( sep );
423 }
424
425 idlg->hb = gtk_hbox_new( FALSE, 6 );
426 gtk_container_set_border_width( GTK_CONTAINER( idlg->hb ), 12 );
427 gtk_box_pack_start( GTK_BOX( iwnd->work ), idlg->hb, FALSE, FALSE, 0 );
428 gtk_widget_show( idlg->hb );
429
430 if( idlg->pinup ) {
431 idlg->tog_pin = gtk_check_button_new_with_label(
432 _( "Pin up" ) );
433 set_tooltip( idlg->tog_pin,
434 _( "Check this to pin the dialog up" ) );
435 gtk_box_pack_start( GTK_BOX( idlg->hb ),
436 idlg->tog_pin, FALSE, FALSE, 0 );
437 gtk_widget_show( idlg->tog_pin );
438 }
439
440 idlg->bb = gtk_hbutton_box_new();
441 gtk_button_box_set_layout( GTK_BUTTON_BOX( idlg->bb ),
442 GTK_BUTTONBOX_END );
443 gtk_box_set_spacing( GTK_BOX( idlg->bb ), 6 );
444 gtk_box_pack_end( GTK_BOX( idlg->hb ), idlg->bb, FALSE, FALSE, 0 );
445 gtk_widget_show( idlg->bb );
446
447 /* Default button order:
448 *
449 * Help OK3 OK2 Cancel OK1
450 *
451 * win32 button order:
452 *
453 * OK1 OK2 OK3 Cancel Help
454 */
455
456 #ifdef OS_WIN32
457
458 /* OK buttons.
459 */
460 slist_map( idlg->ok_l,
461 (SListMapFn) idialog_build_ok, idlg );
462
463 if( idlg->cancel_cb ) {
464 idialog_build_cancel( idlg );
465
466 /* Cancel grabs default if it's the only button. Set focus
467 * too; user build can change this later.
468 */
469 if( !idlg->ok_l )
470 idialog_set_default( idlg, idlg->but_cancel );
471 }
472
473 if( idlg->help_tag ) {
474 idlg->but_help = build_button( GTK_STOCK_HELP,
475 GTK_SIGNAL_FUNC( idialog_help_cb ), idlg );
476 gtk_widget_show( idlg->but_help );
477 }
478
479 #else /*!OS_WIN32*/
480
481 if( idlg->help_tag ) {
482 idlg->but_help = build_button( GTK_STOCK_HELP,
483 GTK_SIGNAL_FUNC( idialog_help_cb ), idlg );
484 gtk_box_pack_end( GTK_BOX( idlg->bb ),
485 idlg->but_help, TRUE, TRUE, 0 );
486 gtk_button_box_set_child_secondary( GTK_BUTTON_BOX( idlg->bb ),
487 idlg->but_help, TRUE );
488 gtk_widget_show( idlg->but_help );
489 }
490
491 /* Add OK2, 3, etc.
492 */
493 if( idlg->ok_l && idlg->ok_l->next )
494 slist_map_rev( idlg->ok_l->next,
495 (SListMapFn) idialog_build_ok, idlg );
496
497 if( idlg->cancel_cb ) {
498 idialog_build_cancel( idlg );
499
500 /* Cancel grabs default if it's the only button. Set focus
501 * too; user build can change this later.
502 */
503 if( !idlg->ok_l )
504 idialog_set_default( idlg, idlg->but_cancel );
505 }
506
507 /* Make OK1
508 */
509 if( idlg->ok_l ) {
510 OKButton *ok1 = (OKButton *) idlg->ok_l->data;
511
512 idialog_build_ok( ok1, idlg );
513 }
514
515 #endif /*lots*/
516
517 /* OK1 grabs the default.
518 */
519 if( idlg->ok_but_l )
520 idialog_set_default( idlg, idlg->ok_but_l->data );
521
522 /* Escape triggers cancel, if there is a cancel.
523 */
524 if( idlg->cancel_cb )
525 gtk_widget_add_accelerator( idlg->but_cancel,
526 "clicked", iwnd->accel_group, GDK_Escape, 0, 0 );
527 else {
528 /* If there's just 1 OK, that gets Esc too.
529 */
530 if( idlg->ok_but_l &&
531 g_slist_length( idlg->ok_but_l ) == 1 )
532 gtk_widget_add_accelerator(
533 GTK_WIDGET( idlg->ok_but_l->data ), "clicked",
534 iwnd->accel_group, GDK_Escape, 0, 0 );
535 }
536
537 /* F1 triggers help.
538 */
539 if( idlg->but_help )
540 gtk_widget_add_accelerator(
541 idlg->but_help,
542 "clicked", iwnd->accel_group, GDK_F1, 0, 0 );
543
544 /* Build user dialog contents.
545 */
546 if( idlg->build )
547 idlg->build( iwnd, idlg->work,
548 idlg->build_a, idlg->build_b, idlg->build_c );
549
550 if( idlg->iobject )
551 idlg->destroy_sid = g_signal_connect( idlg->iobject, "destroy",
552 G_CALLBACK( idialog_iobject_destroy ), idlg );
553
554 gtk_widget_show( idlg->work );
555 }
556
557 static void
idialog_class_init(iDialogClass * class)558 idialog_class_init( iDialogClass *class )
559 {
560 GtkObjectClass *object_class = (GtkObjectClass *) class;
561 GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
562 iWindowClass *iwindow_class = (iWindowClass *) class;
563
564 parent_class = g_type_class_peek_parent( class );
565
566 object_class->destroy = idialog_destroy;
567
568 widget_class->realize = idialog_realize;
569
570 iwindow_class->build = idialog_build;
571 iwindow_class->transient = TRUE;
572
573 /* Create signals.
574 */
575
576 /* Init methods.
577 */
578 }
579
580 static void
idialog_init(iDialog * idlg)581 idialog_init( iDialog *idlg )
582 {
583 #ifdef DEBUG
584 printf( "idialog_init: %s\n", IWINDOW( idlg )->title );
585 #endif /*DEBUG*/
586
587 /* Init our instance fields.
588 */
589 idlg->iobject = NULL;
590 idlg->destroy_sid = 0;
591
592 idlg->work = NULL;
593
594 idlg->ok_l = NULL;
595 idlg->ok_disp_l = NULL;
596 idlg->ok_but_l = NULL;
597
598 idlg->but_cancel = NULL;
599 idlg->but_help = NULL;
600 idlg->tog_pin = NULL;
601
602 idlg->entry = NULL;
603
604 idlg->modal = FALSE;
605 idlg->pinup = FALSE;
606 idlg->nosep = FALSE;
607 idlg->button_focus = TRUE;
608
609 idlg->help_tag = NULL;
610
611 idlg->cancel_text = GTK_STOCK_CANCEL;
612
613 idlg->cancel_cb = NULL;
614 idlg->popdown_cb = NULL;
615 idlg->destroy_cb = NULL;
616 idlg->client = NULL;
617
618 idlg->arg = NULL;
619
620 idlg->nfn = iwindow_notify_null;
621 idlg->sys = NULL;
622
623 gtk_window_set_position( GTK_WINDOW( idlg ),
624 GTK_WIN_POS_CENTER_ON_PARENT );
625 }
626
627 GtkType
idialog_get_type(void)628 idialog_get_type( void )
629 {
630 static GtkType type = 0;
631
632 if( !type ) {
633 static const GtkTypeInfo info = {
634 "iDialog",
635 sizeof( iDialog ),
636 sizeof( iDialogClass ),
637 (GtkClassInitFunc) idialog_class_init,
638 (GtkObjectInitFunc) idialog_init,
639 /* reserved_1 */ NULL,
640 /* reserved_2 */ NULL,
641 (GtkClassInitFunc) NULL,
642 };
643
644 type = gtk_type_unique( TYPE_IWINDOW, &info );
645 }
646
647 return( type );
648 }
649
650 GtkWidget *
idialog_new()651 idialog_new()
652 {
653 iDialog *idlg = gtk_type_new( TYPE_IDIALOG );
654 GtkWindow *gwnd = GTK_WINDOW( idlg );
655
656 /* Init gtk base class.
657 */
658 gwnd->type = GTK_WINDOW_TOPLEVEL;
659
660 return( GTK_WIDGET( idlg ) );
661 }
662
663 void
idialog_set_iobject(iDialog * idlg,iObject * iobject)664 idialog_set_iobject( iDialog *idlg, iObject *iobject )
665 {
666 idlg->iobject = iobject;
667 }
668
669 void
idialog_set_pinup(iDialog * idlg,gboolean pinup)670 idialog_set_pinup( iDialog *idlg, gboolean pinup )
671 {
672 idlg->pinup = pinup;
673
674 if( idlg->tog_pin )
675 gtk_toggle_button_set_active(
676 GTK_TOGGLE_BUTTON( idlg->tog_pin ), TRUE );
677 }
678
679 void
idialog_set_modal(iDialog * idlg,gboolean modal)680 idialog_set_modal( iDialog *idlg, gboolean modal )
681 {
682 idlg->modal = modal;
683 }
684
685 void
idialog_set_nosep(iDialog * idlg,gboolean nosep)686 idialog_set_nosep( iDialog *idlg, gboolean nosep )
687 {
688 idlg->nosep = nosep;
689 }
690
691 void
idialog_set_button_focus(iDialog * idlg,gboolean button_focus)692 idialog_set_button_focus( iDialog *idlg, gboolean button_focus )
693 {
694 idlg->button_focus = button_focus;
695 }
696
697 void
idialog_set_help_tag(iDialog * idlg,const char * help_tag)698 idialog_set_help_tag( iDialog *idlg, const char *help_tag )
699 {
700 IM_SETSTR( idlg->help_tag, help_tag );
701 }
702
703 void
idialog_set_callbacks(iDialog * idlg,iWindowFn cancel_cb,iWindowFn popdown_cb,iDialogFreeFn destroy_cb,void * client)704 idialog_set_callbacks( iDialog *idlg,
705 iWindowFn cancel_cb, iWindowFn popdown_cb,
706 iDialogFreeFn destroy_cb, void *client )
707 {
708 idlg->cancel_cb = cancel_cb;
709 idlg->popdown_cb = popdown_cb;
710 idlg->destroy_cb = destroy_cb;
711 idlg->client = client;
712 }
713
714 void
idialog_add_ok(iDialog * idlg,iWindowFn done_cb,const char * fmt,...)715 idialog_add_ok( iDialog *idlg, iWindowFn done_cb, const char *fmt, ... )
716 {
717 va_list ap;
718 char buf[1024];
719
720 va_start( ap, fmt );
721 (void) im_vsnprintf( buf, 1024, fmt, ap );
722 va_end( ap );
723
724 /* So the last OK button added is the default one (and at the head of
725 * the list). [OK1, OK2, OK3, OK4]
726 */
727 idlg->ok_l = g_slist_prepend( idlg->ok_l,
728 okbutton_new( buf, done_cb ) );
729 }
730
731 void
idialog_set_notify(iDialog * idlg,iWindowNotifyFn nfn,void * sys)732 idialog_set_notify( iDialog *idlg, iWindowNotifyFn nfn, void *sys )
733 {
734 idlg->nfn = nfn;
735 idlg->sys = sys;
736 }
737
738 void
idialog_set_build(iDialog * idlg,iWindowBuildFn build,void * build_a,void * build_b,void * build_c)739 idialog_set_build( iDialog *idlg,
740 iWindowBuildFn build, void *build_a, void *build_b, void *build_c )
741 {
742 idlg->build = build;
743 idlg->build_a = build_a;
744 idlg->build_b = build_b;
745 idlg->build_c = build_c;
746 }
747
748 void
idialog_set_cancel_text(iDialog * idlg,const char * cancel_text)749 idialog_set_cancel_text( iDialog *idlg, const char *cancel_text )
750 {
751 idlg->cancel_text = cancel_text;
752 }
753
754 void
idialog_set_default_entry(iDialog * idlg,GtkEntry * entry)755 idialog_set_default_entry( iDialog *idlg, GtkEntry *entry )
756 {
757 gtk_entry_set_activates_default( entry, TRUE );
758 idlg->entry = entry;
759 }
760
761 /* Set up an entry inside a dialog ... set tooltip, set start
762 * value, link to OK button in enclosing dialog.
763 */
764 void
idialog_init_entry(iDialog * idlg,GtkWidget * entry,const char * tip,const char * fmt,...)765 idialog_init_entry( iDialog *idlg, GtkWidget *entry,
766 const char *tip, const char *fmt, ... )
767 {
768 va_list ap;
769
770 va_start( ap, fmt );
771 set_gentryv( entry, fmt, ap );
772 va_end( ap );
773 set_tooltip( entry, "%s", tip );
774 idialog_set_default_entry( idlg, GTK_ENTRY( entry ) );
775 }
776