// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2007 Koen Deforche, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
#ifndef WDIALOG_H_
#define WDIALOG_H_

#include <WCompositeWidget>

namespace Wt {

class WContainerWidget;
class WTable;
class WText;

/*! \class WDialog WDialog WDialog
 *  \brief A %WDialog emulates a modal window.
 *
 * A modal window blocks the user interface, and does not allow the
 * user to interact with any other part of the user interface until
 * the dialog is closed.
 *
 * There are two distinct ways for using a %WDialog window.
 *
 * The easiest way is using the exec() method: after creating a
 * %WDialog window, call the exec() method which blocks until
 * the dialog window is closed, and returns the dialog
 * result. Typically, an OK button will be connected to the accept()
 * slot, and a Cancel button to the reject() slot. This solution has
 * the drawback that it is not scalable to many concurrent sessions,
 * since every recursive event loop (which is running durring the
 * exec() method) locks a thread. Therefore it is only suitable for
 * software to be deployed on an intranet.
 *
 * A second way is by treating the %WDialog as another widget. In this
 * case, the %WDialog is created with the proper content, and for
 * example an OK button is connected to a method which deletes the
 * dialog.
 *
 * Widgets may be added to the dialog, by adding to the contents()
 * ContainerWidget.
 *
 * Only one %WDialog window may exist at any time in a single
 * application. An attempt to instantiate a second dialog will result
 * in an exception that terminates the session.
 */
class WT_API WDialog : public WCompositeWidget
{
public:
  /*! \brief The result of a modal dialog execution.
   */
  enum DialogCode { Rejected, //!< Dialog closed with reject()
		    Accepted  //!< Dialog closed with accept()
  };

  /*! \brief Construct a %WDialog with a given caption.
   *
   * Only a single Dialog may be constructed at any time. Unlike other widgets,
   * a dialog does not need to be added to a container widget.
   */
  WDialog(const WString& caption = WString());

  /*! \brief Destruct a %WDialog.
   */
  ~WDialog();

  /*! \brief Set the dialog caption.
   */
  void setCaption(const WString& caption);

  /*! \brief Get the dialog caption.
   */
  const WString& caption() const;

  /*! \brief Get the dialog contents container.
   *
   * Content to the dialog window may be added to this container widget. 
   */
  WContainerWidget *contents() const { return contents_; }

  /*! \brief Execute the dialog in a recursive event loop.
   *
   * Executes the dialog. This blocks the current thread of execution
   * until one of done(Dialog), accept() or reject() is called.
   *
   * <i>Warning: using exec() does not scale to many concurrent
   * sessions, since the thread is locked.</i>
   *
   * \sa done(DialogCode r), accept(), reject()
   */
  DialogCode exec();

  /*! \brief Stop a recursive event loop.
   *
   * Sets the dialog result, and ends a recursive event loop that was
   * started using the exec() method.
   */
  virtual void done(DialogCode r);

  /*! \brief Stop a recursive event loop with result is Accepted.
   *
   * \sa done(DialogCode r), reject()
   */
  virtual void accept();

  /*! \brief Stop a recursive event loop with result is Rejected.
   *
   * \sa done(DialogCode r), accept()
   */
  virtual void reject();

  /*! \brief Signal emitted when the recursive event loop is ended.
   *
   * \sa done(DialogCode r), accept(), reject()
   */
  Signal<DialogCode> finished;

  /*! \brief Get the result that was set for this dialog.
   *
   * \sa done(DialogCode r)
   */
  DialogCode result() const { return result_; }

private:
  WTable           *impl_;
  WText            *caption_;
  WContainerWidget *contents_;

  DialogCode result_;

  bool recursiveEventLoop_;
};

}

#endif // WDIALOG_H_
