Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / MotifApp / DialogManager.C
1 /* $XConsortium: DialogManager.C /main/5 1996/04/21 19:32:05 drk $ */
2 /*
3  *+SNOTICE
4  *
5  *      $XConsortium: DialogManager.C /main/5 1996/04/21 19:32:05 drk $
6  *
7  *      RESTRICTED CONFIDENTIAL INFORMATION:
8  *      
9  *      The information in this document is subject to special
10  *      restrictions in a confidential disclosure agreement bertween
11  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
12  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
13  *      Sun's specific written approval.  This documment and all copies
14  *      and derivative works thereof must be returned or destroyed at
15  *      Sun's request.
16  *
17  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
18  *
19  *+ENOTICE
20  */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 //////////////////////////////////////////////////////////////////////////////
24 //         This example code is from the book:
25 //
26 //           Object-Oriented Programming with C++ and OSF/Motif
27 //         by
28 //           Douglas Young
29 //           Prentice Hall, 1992
30 //           ISBN 0-13-630252-1 
31 //
32 //         Copyright 1991 by Prentice Hall
33 //         All Rights Reserved
34 //
35 //  Permission to use, copy, modify, and distribute this software for 
36 //  any purpose except publication and without fee is hereby granted, provided 
37 //  that the above copyright notice appear in all copies of the software.
38 ///////////////////////////////////////////////////////////////////////////////
39 //////////////////////////////////////////////////////////////////////////////
40
41
42 //////////////////////////////////////////////////////////
43 // DialogManager.C: Support cached dialog widgets
44 //////////////////////////////////////////////////////////
45 #include "DialogManager.h"
46 #include "Application.h"
47 #include <Xm/MessageB.h>
48 #include <assert.h>
49
50 #include <nl_types.h>
51 extern nl_catd catd;
52
53 #include "NLS.hh"
54
55 DialogManager::DialogManager ( char   *name ): UIComponent ( name )
56 {
57     // Empty
58 }
59
60 Widget DialogManager::getDialog()
61 {
62     Widget newDialog = NULL;
63     
64     // If the permanent widget exists and is not in use,
65     // just return it
66     
67     if ( _w && !XtIsManaged ( _w ) )
68         return _w;
69     
70     // Get a widget from the derived class
71     
72     newDialog = createDialog ( theApplication->baseWidget() ) ;
73     
74     // If this is a temporary dialog, install callbacks to 
75     // destroy it when the user pops it down.
76     
77     if ( _w )
78     {
79         XtAddCallback ( newDialog, 
80                        XmNokCallback, 
81                        &DialogManager::destroyTmpDialogCallback,
82                        (XtPointer) this );
83         
84         XtAddCallback ( newDialog, 
85                        XmNcancelCallback, 
86                        &DialogManager::destroyTmpDialogCallback,
87                        (XtPointer) this );
88     }
89     else                 // If this is the first dialog to be 
90         _w = newDialog;  // created, save it to be used again.
91     
92     return newDialog;
93 }
94
95 Widget DialogManager::getDialog(
96     Widget w
97 )
98 {
99     Widget newDialog = NULL;
100     
101     // If the permanent widget exists and is not in use,
102     // just return it
103     
104     if ( _w && !XtIsManaged ( _w ) )
105         return _w;
106     
107     // Get a widget from the derived class
108     // Parent the dialog to the widget passed in
109     
110     newDialog = createDialog (w);
111     
112     // If this is a temporary dialog, install callbacks to 
113     // destroy it when the user pops it down.
114     
115     if ( _w )
116     {
117         XtAddCallback ( newDialog, 
118                        XmNokCallback, 
119                        &DialogManager::destroyTmpDialogCallback,
120                        (XtPointer) this );
121         
122         XtAddCallback ( newDialog, 
123                        XmNcancelCallback, 
124                        &DialogManager::destroyTmpDialogCallback,
125                        (XtPointer) this );
126     }
127     else                 // If this is the first dialog to be 
128         _w = newDialog;  // created, save it to be used again.
129     
130     return newDialog;
131 }
132
133 void DialogManager::destroyTmpDialogCallback ( Widget     w, 
134                                               XtPointer,
135                                               XtPointer clientData)
136 {
137     XtDestroyWidget ( w );
138
139     // We must set the wiget handle to NULL to prevent multiple
140     // destroys.
141     ((DialogManager *)clientData)->_w = NULL;
142 }
143
144 Widget DialogManager::post (char          *title,
145                             char          *text,
146                             Widget         wid,
147                             void          *clientData,
148                             DialogCallback ok,
149                             DialogCallback cancel,
150                             DialogCallback help)
151 {
152     // Get a dialog widget from the cache
153     
154     Widget dialog = getDialog(wid);
155     
156     // Make sure the dialog exists, and that it is an XmMessageBox
157     // or subclass, since the callbacks assume this widget type
158     
159     assert ( dialog != NULL );
160 //    assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
161         
162         // Convert the text string to a compound string and 
163         // specify this to be the message displayed in the dialog.
164         
165     XmString titleStr = XmStringCreateLocalized (title);
166     XmString xmstr = XmStringCreateLocalized ( text );
167     XtVaSetValues ( dialog, 
168                     XmNmessageString, xmstr,
169                     XmNdialogTitle, titleStr,
170                     NULL );
171     XmStringFree ( xmstr );
172     XmStringFree ( titleStr );
173     
174     // Create an object to carry the additional data needed
175     // to cache the dialogs.
176     
177     DialogCallbackData *dcb = new DialogCallbackData( this, 
178                                                      clientData,
179                                                      ok, cancel, 
180                                                      help );
181     // Install callback function for each button 
182     // support by Motif dialogs. If there is no help callback
183     // unmanage the corresponding button instead, if possible.
184
185     if ( ok )
186       XtAddCallback ( dialog, 
187                       XmNokCallback, 
188                       &DialogManager::okCallback,
189                       (XtPointer) dcb );
190     else
191       {
192         Widget w = XmMessageBoxGetChild ( dialog,
193                                           XmDIALOG_OK_BUTTON );
194         XtUnmanageChild ( w );
195       }
196
197
198     if ( cancel )
199       XtAddCallback ( dialog, 
200                       XmNcancelCallback, 
201                       &DialogManager::cancelCallback,
202                       (XtPointer) dcb );
203     else
204       {
205         Widget w = XmMessageBoxGetChild ( dialog,
206                                           XmDIALOG_CANCEL_BUTTON );
207         XtUnmanageChild ( w );
208       }
209     
210     
211     if ( help )     
212         XtAddCallback ( dialog, 
213                        XmNhelpCallback, 
214                        &DialogManager::helpCallback,
215                        (XtPointer) dcb );
216     else
217     {
218         Widget w = XmMessageBoxGetChild ( dialog,
219                                          XmDIALOG_HELP_BUTTON );
220         XtUnmanageChild ( w );
221     }
222     
223     // Post the dialog.
224     
225     XtManageChild ( dialog );
226
227     
228     return dialog;
229 }
230
231 Widget DialogManager::post (char          *title,
232                             char          *text,
233                             void          *clientData,
234                             DialogCallback ok,
235                             DialogCallback cancel,
236                             DialogCallback help)
237 {
238     // Get a dialog widget from the cache
239     
240     Widget dialog = getDialog();
241     
242     // Make sure the dialog exists, and that it is an XmMessageBox
243     // or subclass, since the callbacks assume this widget type
244     
245     assert ( dialog != NULL );
246 //    assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
247         
248         // Convert the text string to a compound string and 
249         // specify this to be the message displayed in the dialog.
250         
251     XmString titleStr = XmStringCreateLocalized (title);
252     XmString xmstr = XmStringCreateLocalized ( text );
253     XtVaSetValues ( dialog, 
254                     XmNmessageString, xmstr,
255                     XmNdialogTitle, titleStr,
256                     NULL );
257     XmStringFree ( xmstr );
258     XmStringFree ( titleStr );
259     
260     // Create an object to carry the additional data needed
261     // to cache the dialogs.
262     
263     DialogCallbackData *dcb = new DialogCallbackData( this, 
264                                                      clientData,
265                                                      ok, cancel, 
266                                                      help );
267     // Install callback function for each button 
268     // support by Motif dialogs. If there is no help callback
269     // unmanage the corresponding button instead, if possible.
270
271     if ( ok )
272       XtAddCallback ( dialog, 
273                       XmNokCallback, 
274                       &DialogManager::okCallback,
275                       (XtPointer) dcb );
276     else
277       {
278         Widget w = XmMessageBoxGetChild ( dialog,
279                                           XmDIALOG_OK_BUTTON );
280         XtUnmanageChild ( w );
281       }
282
283
284     if ( cancel )
285       XtAddCallback ( dialog, 
286                       XmNcancelCallback, 
287                       &DialogManager::cancelCallback,
288                       (XtPointer) dcb );
289     else
290       {
291         Widget w = XmMessageBoxGetChild ( dialog,
292                                           XmDIALOG_CANCEL_BUTTON );
293         XtUnmanageChild ( w );
294       }
295     
296     
297     if ( help )     
298         XtAddCallback ( dialog, 
299                        XmNhelpCallback, 
300                        &DialogManager::helpCallback,
301                        (XtPointer) dcb );
302     else
303     {
304         Widget w = XmMessageBoxGetChild ( dialog,
305                                          XmDIALOG_HELP_BUTTON );
306         XtUnmanageChild ( w );
307     }
308     
309     // Post the dialog.
310     
311     XtManageChild ( dialog );
312
313     
314     return dialog;
315 }
316
317 void DialogManager::okCallback ( Widget    w, 
318                                 XtPointer clientData,
319                                 XtPointer )
320 {
321     DialogCallbackData *dcd = (DialogCallbackData *) clientData;
322     DialogManager      *obj = (DialogManager *) dcd->dialogManager();
323     DialogCallback      callback;
324     
325     // If caller specified an ok callback, call the function
326     
327     if ( ( callback = dcd->ok() ) != NULL )
328         ( *callback )( dcd->clientData() );
329     
330     // Reset for the next time
331     
332     obj->cleanup ( w, dcd );
333 }
334
335 void DialogManager::cancelCallback ( Widget    w, 
336                                     XtPointer clientData,
337                                     XtPointer )
338 {
339     DialogCallbackData *dcd = (DialogCallbackData *) clientData;
340     DialogManager      *obj = (DialogManager *) dcd->dialogManager();
341     DialogCallback      callback;
342     
343     if ( ( callback = dcd->cancel() ) != NULL )
344         ( *callback )( dcd->clientData() );
345     
346     obj->cleanup ( w, dcd );
347 }
348
349 void DialogManager::helpCallback ( Widget    w, 
350                                   XtPointer clientData,
351                                   XtPointer )
352 {
353     DialogCallbackData *dcd = (DialogCallbackData *) clientData;
354     DialogManager      *obj = (DialogManager *) dcd->dialogManager();
355     DialogCallback      callback;
356     
357     if ( ( callback = dcd->help() ) != NULL )
358         ( *callback )( dcd->clientData() );
359     
360     obj->cleanup ( w, dcd );
361 }
362
363 void DialogManager::cleanup ( Widget w, DialogCallbackData *dcd )
364 {
365     // Remove all callbacks to avoid having duplicate 
366     // callback functions installed.
367     
368     XtRemoveCallback ( w, 
369                       XmNokCallback, 
370                       &DialogManager::okCallback,
371                       (XtPointer) dcd );
372     
373     XtRemoveCallback ( w, 
374                       XmNcancelCallback, 
375                       &DialogManager::cancelCallback,
376                       (XtPointer) dcd );
377     
378     XtRemoveCallback ( w, 
379                       XmNhelpCallback, 
380                       &DialogManager::helpCallback,
381                       (XtPointer) dcd );
382     
383     // Delete the DialogCallbackData instance for this posting
384     
385     delete dcd;
386 }
387
388 void
389 DialogManager::forceUpdate( Widget w )
390 {
391   Widget diashell, topshell;
392   Window diawindow, topwindow;
393
394   Display               *dpy;
395   XWindowAttributes     xwa;
396   XEvent                event;
397   if ( !w )
398     return;
399   XtAppContext cxt=XtWidgetToApplicationContext( w );
400   for (diashell=w;!XtIsShell(diashell);diashell=XtParent(diashell));
401   for ( topshell=diashell;XtIsTopLevelShell( topshell );
402         topshell = XtParent( topshell ) );
403
404 //  if (XtIsRealized(diashell) && XtIsRealized(topshell)){
405     dpy=XtDisplay(diashell);
406     diawindow=XtWindow(diashell);
407     topwindow=XtWindow(topshell);
408     while ( XGetWindowAttributes(dpy,diawindow,&xwa) && 
409             xwa.map_state != IsViewable && XEventsQueued(dpy,QueuedAlready)){
410 //      if ( XGetWindowAttributes( dpy, topwindow, &xwa ) &&
411 //         xwa.map_state != IsViewable )
412 //        break;
413       XtAppNextEvent( cxt, &event );
414       XtDispatchEvent( &event );
415     }
416 //  }
417   XmUpdateDisplay(topshell);
418 }
419
420
421
422 // Added this extra functionality
423
424 void
425 my_okCallback( int *data )
426 {
427     *data=1;
428 }
429
430 void
431 my_cancelCallback( int *data )
432 {
433     *data=2;
434 }
435
436 int
437 DialogManager::post_and_return(
438         char *title_str, 
439         char *text_str,
440         Widget wid
441 )
442 {
443     int answer = 0;
444     XmString okLabel, cancelLabel;
445
446     // They may have been set via the overloaded post_and_return()
447     // method before. Reset them to their default values...
448
449     okLabel = XmStringCreateLocalized(GETMSG(catd, 1, 2, "OK"));
450     cancelLabel = XmStringCreateLocalized(GETMSG(catd, 1, 3, "Cancel"));
451
452     Widget dlg = this->getDialog(wid);
453
454     // Make sure the dialog exists, and that it is an XmMessageBox
455     // or subclass, since the callbacks assume this widget type
456     
457     assert ( dlg != NULL );
458
459     XtVaSetValues(dlg,
460                   XmNokLabelString, okLabel,
461                   XmNcancelLabelString, cancelLabel,
462                   NULL);
463
464     Widget dialog =
465         this->post(title_str,
466                    text_str,
467                    wid,
468                    (void *) &answer,
469                    ( DialogCallback ) &my_okCallback,
470                    ( DialogCallback ) &my_cancelCallback);
471
472     forceUpdate( dialog );
473     while ( answer==0 ) 
474         XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
475
476     // Process just one more event to pop down dialog.
477     XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
478
479     return(answer);
480
481 }
482
483 int
484 DialogManager::post_and_return(
485         char *title_str, 
486         char *text_str,
487         char *okLabelString,
488         Widget wid
489 )
490 {
491     int answer = 0;
492     XmString okLabel;
493
494     okLabel = XmStringCreateLocalized(okLabelString);
495
496     Widget dlg = this->getDialog(wid);
497
498     // Make sure the dialog exists, and that it is an XmMessageBox
499     // or subclass, since the callbacks assume this widget type
500     
501     assert ( dlg != NULL );
502
503     XtVaSetValues(dlg,
504                   XmNokLabelString, okLabel,
505                   NULL);
506
507     Widget dialog = this->post(title_str,
508                                text_str,
509                                wid,
510                                (void *) &answer,
511                                ( DialogCallback ) &my_okCallback);
512
513     forceUpdate( dialog );
514     while ( answer==0 ) 
515         XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
516
517     // Process just one more event to pop down dialog.
518     XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
519
520     return(answer);
521
522 }
523
524 int
525 DialogManager::post_and_return(
526         char *title_str, 
527         char *text_str,
528         char *okLabelString,
529         char *cancelLabelString,
530         Widget wid
531
532 )
533 {
534     int answer = 0;
535     XmString okLabel, cancelLabel;
536
537     okLabel = XmStringCreateLocalized(okLabelString);
538     cancelLabel = XmStringCreateLocalized(cancelLabelString);
539
540     Widget dlg = this->getDialog(wid);
541
542     // Make sure the dialog exists, and that it is an XmMessageBox
543     // or subclass, since the callbacks assume this widget type
544     
545     assert ( dlg != NULL );
546
547     XtVaSetValues(dlg,
548                   XmNokLabelString, okLabel,
549                   XmNcancelLabelString, cancelLabel,
550                   NULL);
551
552     Widget dialog = this->post(title_str,
553                                text_str,
554                                wid,
555                                (void *) &answer,
556                                ( DialogCallback ) &my_okCallback,
557                                ( DialogCallback ) &my_cancelCallback);
558
559     forceUpdate( dialog );
560     while ( answer==0 ) 
561         XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
562
563     // Process just one more event to pop down dialog.
564     XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
565
566     return(answer);
567
568 }
569
570
571