// 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 WDATEPICKER_H_
#define WDATEPICKER_H_

#include <Wt/WCompositeWidget>
#include <Wt/WDate>
#include <Wt/WJavaScriptSlot>
#include <set>

namespace Wt {

class WCalendar;
class WInteractWidget;
class WLineEdit;
class WTemplate;

/*! \class WDatePicker Wt/WDatePicker Wt/WDatePicker
 *  \brief A date picker.
 *
 * A date picker shows a line edit and an icon which when clicked
 * popups a WCalendar for editing the date. Any date entered in the
 * line edit is reflected in the calendar, and vice-versa.
 *
 * Each of these widgets may be accessed individually (lineEdit(),
 * calendar(), and displayWidget()) and there is a constructor that
 * allows you to specify an existing line edit and display widget.
 * 
 * The date format used by default is <tt>"dd/MM/yyyy"</tt> and can be
 * changed using setFormat(). At any time, the date set may be read
 * using date(), or can be changed using setDate().
 *
 * \if cpp
 * Usage example:
 * \code
 * Wt::WDatePicker *picker = new Wt::WDatePicker(this);
 * picker->setFormat("dd-MM-yyyy");
 * picker->setDate(Wt::WDate(1976, 6, 14));
 * \endcode
 * \endif
 *
 * <h3>CSS</h3>
 *
 * The date picker is styled by the current CSS theme. The look can be
 * overridden using the <tt>Wt-datepicker</tt> and <tt>Wt-outset</tt>
 * CSS class; the calendar itself can be styled as documented in
 * WCalendar.
 *
 * <TABLE border="0" align="center"> <TR> <TD> 
 * \image html WDatePicker-default-1.png "Example of a WDatePicker (default theme) 
 * </TD> <TD> 
 * \image html WDatePicker-polished-1.png "Example of a WDatePicker (polished theme) 
 * </TD> </TR> </TABLE>
 */
class WT_API WDatePicker : public WCompositeWidget
{
public:
  /*! \brief Create a new date picker.
   *
   * This constructor creates a line edit with an icon that leads to a
   * popup calendar. A WDateValidator is configured for the line edit.
   */
  WDatePicker(WContainerWidget *parent = 0);

  /*! \brief Create a new date picker.
   *
   * This constructor creates a line edit with an icon that leads to a
   * popup calendar. A WDateValidator is configured for the line edit.
   *
   * \p i18n is passed to the WCalendar constructor.
   */
  WDatePicker(bool i18n, WContainerWidget *parent = 0);

  /*! \brief Create a new date picker for existing line edit and with custom
   *         display widget.
   *
   * The \p displayWidget is a button or image which much be
   * clicked to open the date picker. This widget will become owned by
   * the picker.
   *
   * The \p forEdit argument is the lineEdit that works in
   * conjunction with the date picker. This widget does not become
   * part of the date picker, and may be located anywhere else.
   *
   * \p i18n is passed to the WCalendar constructor.
   */
  WDatePicker(WInteractWidget *displayWidget,
	      WLineEdit *forEdit,
	      bool i18n = false, WContainerWidget *parent = 0);

  /*! \brief Sets the format used for parsing or writing the date in
   *         the line edit.
   *
   * Sets the format used for representing the date in the line edit.
   * If the line edit has a WDateValidator configured for it, then also
   * there the format is updated.
   *
   * The default format is <tt>'dd/MM/yyyy'</tt>.
   *
   * \sa format(), WDate::toString()
   */
  void setFormat(const WT_USTRING& format);

  /*! \brief Returns the format.
   *
   * \sa setFormat()
   */
  const WT_USTRING& format() const { return format_; }

  /*! \brief The calendar widget.
   *
   * Returns the calendar widget.
   */
  WCalendar *calendar() const { return calendar_; }

  /*! \brief The line edit.
   *
   * Returns the line edit which works in conjunction with this date
   * picker.
   */
  WLineEdit *lineEdit() const { return forEdit_; }

  /*! \brief The display widget.
   *
   * Returns the widget which is displayed to activate the calendar.
   */
  WInteractWidget *displayWidget() const { return displayWidget_; }

  /*! \brief The current date.
   *
   * Reads the current date from the lineEdit().
   *
   * \if cpp
   * Returns an invalid date (for which WDate::isValid() returns
   * \c false) if the date could not be parsed using the current
   * format(). <br>
   * \elseif java
   * Returns \c null if the date could not be parsed using the current
   * format(). <br>
   * \endif
   *
   * \sa setDate(), WDate::fromString(), WLineEdit::text()
   */
  WDate date() const;

  /*! \brief Sets the current date.
   *
   * Does nothing if the current date is \p Null.
   *
   * \sa date()
   */
  void setDate(const WDate& date);

  /*! \brief Sets whether the widget is enabled.
   *
   * This is the oppositie of setDisabled().
   */
  void setEnabled(bool enabled);

  virtual void setDisabled(bool disabled);

  /*! \brief Hide/unhide the widget.
   */
  void setHidden(bool hidden);

private:
  WT_USTRING        format_;
  WInteractWidget  *displayWidget_;
  WLineEdit        *forEdit_;

  WContainerWidget *layout_;
  WTemplate        *popup_;
  WCalendar        *calendar_;

  JSlot positionJS_;

  void createDefault(bool i18n);
  void create(WInteractWidget *displayWidget, WLineEdit *forEdit, bool i18n);

  void setFromCalendar();
  void setFromLineEdit();
};

}

#endif // WDATEPICKER_H_
