
#ifndef _dialog_h_
#define _dialog_h_





/*
 *
 *          Copyright (C) 1995, M. A. Sridhar
 *  
 *
 *     This software is Copyright M. A. Sridhar, 1995. You are free
 *     to copy, modify or distribute this software  as you see fit,
 *     and to use  it  for  any  purpose, provided   this copyright
 *     notice and the following   disclaimer are included  with all
 *     copies.
 *
 *                        DISCLAIMER
 *
 *     The author makes no warranties, either expressed or implied,
 *     with respect  to  this  software, its  quality, performance,
 *     merchantability, or fitness for any particular purpose. This
 *     software is distributed  AS IS.  The  user of this  software
 *     assumes all risks  as to its quality  and performance. In no
 *     event shall the author be liable for any direct, indirect or
 *     consequential damages, even if the  author has been  advised
 *     as to the possibility of such damages.
 *
 */



/*
  Authors:   M. A. Sridhar
             N. Bhowmik
*/


// The behavior of the Dialog is an enhancement of that of the Composite,
// in that  Dialog supports the notion of {\it dialog events\/} on certain
// designated children; a dialog event is simply a (view id, event type)
// pair.  A Dialog is created with a set of dialog events
// that are significant to it, and remembers the most recent dialog event
// that occurred on it. The
// types of dialog events, and the identities of the children they must occur
// on, can be specified when the Dialog is constructed. 
//
// The Dialog also includes the method {\tt ExecuteModal}, which causes the
// Dialog to run modally until one of the dialog events occurs on the
// corresponding child. If this
// method is not invoked, the Dialog is modeless.



#if defined(__GNUC__)
#pragma interface
#endif


#include "base/objset.h"
#include "ui/composit.h"

//[ Global
struct UI_DialogEventDescriptor {
    UI_ViewID  id;
    UI_EventType type;
};
//] Global


class YACL_UI UI_Dialog : public UI_CompositeVObject {

public:

    // -------------------- Construction and destruction ------------------

    UI_Dialog (UI_CompositeVObject* parent, UI_ViewDescriptor* children,
               const UI_Rectangle& shape,
               UI_DialogEventDescriptor* events = NULL,
               UI_ViewID defaultPushButton = UI_IDOK,
               CL_AbstractBinding* validator = NULL);
    // Constructor: build a dialog ``manually'', by specifying the parent and
    // shape, all the children of the dialog (in the {\tt children} array), and
    // the dialog events for this Dialog. Both {\tt children}
    // and {\tt events} must point to arrays of elements whose
    // last element has ${\tt id} \le 0$. If the {\tt children} pointer is
    // NULL, the Dialog assumes that Select events originating from either of
    // children with id's {\tt UI_IDOK} and {\tt UI_IDCANCEL} are the dialog
    // events. The {\tt defaultPushButton} parameter specifies the view id
    // of the default button, i.e., the button we pretend was pressed when
    // the user hits the enter key.
    //
    // If specified, the Binding {\tt validator} is executed when the user
    // attempts to terminate the Dialog with the default push button. The
    // parameter to the Binding's method will be this Dialog. If the
    // validator returns FALSE, the dialog refuses to terminate its modal
    // state. (The Dialog makes a clone of the validator binding, so it does
    // not borrow {\tt validator}.)
    

#if defined(__MS_WINDOWS__) || defined(__MS_WIN32__)
    UI_Dialog(UI_CompositeVObject* parent, const char* resourceName,
              UI_DialogEventDescriptor* events = NULL,
              UI_ViewID defaultPushButton = -1,
              CL_AbstractBinding* bind = NULL);
    // Resource-based construction (only under MS-Windows).

#endif
    
    // ---------------------- Dialog events ----------------------------
    virtual bool AddDialogEvent    (UI_ViewID id, UI_EventType type);
    // Add a dialog event with view id {\tt id} and type {\tt type} to the
    // set of dialog events recognized by this Dialog.

    virtual bool RemoveDialogEvent (UI_ViewID id, UI_EventType type);
    // Remove a dialog event from this Dialog's remembered set. Return FALSE
    // if no such dialog event was recognized by this Dialog.

    UI_DialogEventDescriptor LastDialogEvent () { return _lastEvent;};
    // Return the most recent dialog event. If this event contains an id of
    // $-1$, then no dialog events have occurred yet.
    
    // ---------------------- Modal execution ----------------------------
    
    UI_DialogEventDescriptor ExecuteModal ();
    // Execute the given dialog modally until a dialog event occurs, and
    // return that event.

    bool InModalState ();
    // Are we currently running modally?
    
    // ---------------- Basic methods ---------------------------------
    
    const char* ClassName() const {return "UI_Dialog";};

    // ------------------- End public protocol -------------------------

    
protected:
    virtual bool MakeVisualElement ();
    // Override method inherited from VisualObject.
    
    ~UI_Dialog ();
    // Destructor.

    void CloseDown ();
    // Event handler for the CloseDown event. The implementation checks if
    // the Dialog is currently in modal state, and if so, causes {\tt
    // ExecuteModal} to return to its caller. If not, it closes down the
    // Dialog.

    bool _EventOccurred (UI_Event&);
    // Override the event dependent method inherited from
    // CompositeVObject. The implementation takes care of default push
    // button behavior.


#if defined(__MS_WINDOWS__) || defined(__MS_WIN32__)
    void SetStyle ();
    // [Specific to Windows. YACL internal use only.] Set up the style
    // for this dialog. This overrides the inherited method.

    virtual ulong ExtendedStyle () const;
    //  [YACL internal use only] MS-Windows-specific: overrides the
    //  inherited method.
    
#endif
    //
    // Instance Variables:
    //
    UI_DialogEventDescriptor    _lastEvent;
    CL_ObjectSet                _dialogEvents;
    UI_ViewID                   _defaultPushBtn;
    CL_AbstractBinding*         _validator;

private:

    void _Init (UI_DialogEventDescriptor*, UI_ViewID, CL_AbstractBinding*);
    
    bool EventFilter (UI_Event&);
    // The event filter used by the modal event loop.
    
    bool RunFinished ();
    // The termination filter used by the modal event loop.

    bool _DialogEventOccurred (UI_Event&);
    // The event dependent method.

    bool                        _closed;
    bool                        _modalState;


#if defined(__OS2__)
    virtual void _ComputeWindowShape (RECTL& );
    // [Specific to OS/2 and Windows. YACL internal use only.]
    
#endif
};



inline bool UI_Dialog::InModalState ()
{
    return _modalState;
}


#endif

