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

#include <Wt/WDialog>
#include <Wt/WSignalMapper>

namespace Wt {

class WContainerWidget;
class WImage;
class WPushButton;
class WText;

/*! \class WMessageBox Wt/WMessageBox Wt/WMessageBox
 *  \brief A standard dialog for confirmation or to get simple user input
 *
 * The messagebox shows a message in a dialog window, with a number
 * of buttons. These buttons may be standard buttons, or customized.
 *
 * A messagebox is (usually) modal, and can be instantiated
 * synchronously or asynchronously.
 *
 * When using a messagebox asynchronously, there is no API call that
 * waits for the messagebox to be processed. Then, the usage is similar
 * to instantiating a WDialog (or any other widget). You need to connect
 * to the buttonClicked signal with a method that interpretes
 * the result and deletes the message box.
 *
 * The synchronous use of a messagebox involves the use of the static
 * show() method, which blocks the current thread until the user has
 * processed the messabebox. Since this uses the WDialog::exec(), it
 * suffers from the same scalability issues. See documentation of
 * WDialog for more details.
 * 
 * \if cpp
 * Example code (using the exec() method, not recommended):
 * \code
 * StandardButton
 *   result = WMessageBox::show("Confirm", "About to wreak havoc... Continue ?",
 *                              Ok | Cancel);
 * \endcode
 * \endif
 *
 * This will show a message box that looks like this:
 *
 * <TABLE border="0" align="center"> <TR> <TD> 
 * \image html WMessageBox-default-1.png "Example of a WMessageBox (default)"
 * </TD> <TD>
 * \image html WMessageBox-polished-1.png "Example of a WMessageBox (polished)"
 * </TD> </TR> </TABLE>
 *
 * <h3>i18n</h3>
 *
 * The strings used in the WMessageBox buttons can be translated by overriding
 * the default values for the following localization keys:
 * - Wt.WMessageBox.Abort: Abort
 * - Wt.WMessageBox.Cancel: Cancel
 * - Wt.WMessageBox.Ignore: Ignore
 * - Wt.WMessageBox.No: No
 * - Wt.WMessageBox.NoToAll: No to All
 * - Wt.WMessageBox.Ok: Ok
 * - Wt.WMessageBox.Retry: Retry
 * - Wt.WMessageBox.Yes: Yes
 * - Wt.WMessageBox.YesToAll: Yes to All
 */
class WT_API WMessageBox : public WDialog
{
public:
  using WDialog::show;

  /*! \brief Creates an empty message box.
   */
  WMessageBox(WObject *parent = 0);

  /*! \brief Creates a message box with given caption, text, icon, and
   *         buttons.
   */
  WMessageBox(const WString& caption, const WString& text, Icon icon,
	      WFlags<StandardButton> buttons, WObject *parent = 0);

  /*! \brief Sets the text for the message box.
   */
  void setText(const WString& text);

  /*! \brief Returns the message box text.
   */
  const WString& text() const;

  /*! \brief Returns the text widget.
   *
   * This may be useful to customize the style or layout of the displayed
   * text.
   */
  WText *textWidget() const { return text_; }

  /*! \brief Sets the icon.
   */
  void setIcon(Icon icon);

  /*! \brief Returns the icon.
   */
  Icon icon() const { return icon_; }

  /* !\brief Returns the icon image.
   *
   * This may be useful to customize the style or layout of the displayed
   * icon. If icon() == NoIcon, then this method returns \c 0.
   */
  WImage *iconImage() const { return iconImage_; }

  /*! \brief Add a custom button with given text.
   *
   * When the button is clicked, the associated result will be returned.
   */
  WPushButton *addButton(const WString& text, StandardButton result);

  /*! \brief Sets standard buttons for the message box.
   */
  void setButtons(WFlags<StandardButton> buttons);

  /*! \brief Returns the standard buttons.
   */
  WFlags<StandardButton> buttons() const { return buttons_; }

  /*! \brief Returns the button widget for the given standard button.
   *
   * This may be useful to customize the style or layout of the button.
   */
  WPushButton *button(StandardButton b);

  /*! \brief Returns the result of this message box.
   *
   * This value is only defined after a button has been clicked.
   */
  StandardButton buttonResult() { return result_; }

  /*! \brief Convenience method to show a message box, blocking the current
   *         thread.
   *
   * Show a message box, blocking the current thread until the message box
   * is closed, and return the result. The use of this method is not
   * recommended since it uses WDialog::exec(). See documentation of
   * WDialog for detailed information.
   *
   * \if java 
   * <i>This functionality is only available on Servlet 3.0 compatible 
   * servlet containers.</i>
   * \endif
   */
  static StandardButton show(const WString& caption,
			     const WString& text,
			     WFlags<StandardButton> buttons,
			     const WAnimation& animation = WAnimation());

  /*! \brief %Signal emitted when a button is clicked.
   */
  Signal<StandardButton>& buttonClicked() { return buttonClicked_; }

private:
  WFlags<StandardButton> buttons_;
  Icon icon_;
  StandardButton result_;
  Signal<StandardButton> buttonClicked_;

  WText            *text_;
  WImage           *iconImage_;

  WSignalMapper<StandardButton, NoClass> *buttonMapper_;

  void create();

  void onButtonClick(StandardButton b);
  void mappedButtonClick(StandardButton b);

  static StandardButton order_[];

  static const char *buttonText_[];
  static const char *iconURI[];
};

}

#endif // WMESSAGEBOX_
