///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//         This example code is from the book:
//
//           Object-Oriented Programming with C++ and OSF/Motif, 2nd Edition
//         by
//           Douglas Young
//           Prentice Hall, 1995
//           ISBN 0-13-20925507
//
//         Copyright 1995 by Prentice Hall
//         All Rights Reserved
//
//  Permission to use, copy, modify, and distribute this software for 
//  any purpose except publication and without fee is hereby granted, provided 
//  that the above copyright notice appear in all copies of the software.
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////
// DialogManager.C: Support cached dialog widgets
//////////////////////////////////////////////////////////
#include "DialogManager.h"
#include "Application.h"
#include <Xm/MessageB.h>
#include <assert.h>

DialogManager::DialogManager ( const char *name ): UIComponent ( name )
{
    // Empty
}
Widget DialogManager::getDialog()
{
    Widget newDialog = NULL;
    
    // If the permanent widget exists and is not in use,
    // just return it
    
    if ( _w && !XtIsManaged ( _w ) )
	return ( _w );
    
    // Get a widget from the derived class
    
    newDialog = createDialog ( theApplication->baseWidget() ) ;
    
    if ( newDialog != _w )
    {
	XtAddCallback ( newDialog, XmNokCallback, 
			&DialogManager::actionCallback,
			( XtPointer ) this );
	
	XtAddCallback ( newDialog, XmNcancelCallback, 
			&DialogManager::actionCallback,
			( XtPointer ) this );
	
	XtAddCallback ( newDialog, XmNhelpCallback, 
			&DialogManager::actionCallback,
			( XtPointer ) this );
    }
    
    if ( !_w )           // If this is the first dialog to be 
	_w = newDialog;  // created, save it to be used again
    
    return ( newDialog );
}
Widget DialogManager::post ( const char    *text,
			     void          *clientData,
			     DialogCallback ok,
			     DialogCallback cancel,
			     DialogCallback help)
{
    // Get a dialog widget from the cache
    
    Widget dialog = getDialog();
    
    // Make sure the dialog exists, and that it is an XmMessageBox
    // or subclass, since the callbacks assume this widget type
    
    assert ( dialog );
    assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
    
    // Convert the text string to a compound string and 
    // specify this to be the message displayed in the dialog
    
    XmString xmstr = XmStringCreateSimple ( (char*) text ); 
    XtVaSetValues ( dialog, XmNmessageString, xmstr, NULL );
    XmStringFree ( xmstr );
    
    // Create an object to carry the additional data needed
    // to cache the dialogs
    
    DialogCallbackData *dcb = new DialogCallbackData ( clientData,ok,
						       cancel, help );
    XtVaSetValues ( dialog, XmNuserData, dcb, NULL );
    
    if ( !help )	    
    {
	Widget w = XmMessageBoxGetChild ( dialog, XmDIALOG_HELP_BUTTON );
	XtUnmanageChild ( w );
    }
    
    // Post the dialog
    
    XtManageChild ( dialog );
    return ( dialog );
}
void DialogManager::actionCallback ( Widget    w, 
				     XtPointer clientData,
				     XtPointer callData )
{
    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) callData;
    DialogManager      *obj = ( DialogManager * ) clientData;
    DialogCallback      callback;
    DialogCallbackData *dcd;
    
    XtVaGetValues ( w, XmNuserData, &dcd, NULL );
    
    switch ( cbs->reason) {
    case XmCR_OK:
	callback = dcd->ok();
	break;
    case XmCR_CANCEL:
	callback = dcd->cancel();
	break;
    case XmCR_HELP:
	callback = dcd->help();
	break;
    };
    
    if ( callback != NULL )
        ( *callback )( dcd->clientData() );
    
    delete dcd;
    
    if ( obj->baseWidget() != w )
        XtDestroyWidget ( w );
}







