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

#include <Wt/WCompositeWidget>

namespace Wt {

class WCheckBox;
class WPopupMenu;
class WText;

/*! \class WPopupMenuItem Wt/WPopupMenuItem Wt/WPopupMenuItem
 *  \brief An item in a popup menu.
 *
 * An item may have a text, icon, and can be checkable or lead to a
 * submenu.
 *
 * When the mouse hovers over the item, its class is changed from
 * "Wt-item" to "Wt-selected".
 *
 * \sa WPopupMenu
 */
class WT_API WPopupMenuItem : public WCompositeWidget
{
public:
  /*! \brief Creates a new item with given text.
   *
   * \sa WPopupMenu::addItem(const WString& text)
   */
  WPopupMenuItem(const WString& text);

  /*! \brief Creates a new item with given icon and text.
   *
   * The icon is displayed left to the text.
   *
   * \note The icon should have a width of 16 pixels.
   *
   * \sa WPopupMenu::addItem(const std::string& iconPath, const WString& text)
   */
  WPopupMenuItem(const std::string& iconPath, const WString& text);

  /*! \brief Destructor.
   */
  ~WPopupMenuItem();

  /*! \brief Sets the item text.
   *
   * \sa setIcon()
   */
  void setText(const WString& text);

  /*! \brief Returns the item text.
   *
   * \sa setText()
   */
  const WString& text() const;

  /*! \brief Sets the item icon path.
   *
   * The icon should have a width of 16 pixels.
   *
   * \sa setText()
   */
  void setIcon(const std::string& path);

  /*! \brief Returns the item icon path.
   *
   * \sa setIcon()
   */
  std::string icon();

  /*! \brief Sets if the item is checkable.
   *
   * When an item is checkable, a checkbox is displayed to the left of the
   * item text (instead of an icon).
   *
   * \sa setChecked(), isChecked()
   */
  void setCheckable(bool checkable);

  /*! \brief Returns whether the item is checkable.
   *
   * \sa setCheckable()
   */
  bool isCheckable() const { return checkBox_ != 0; }

  /*! \brief Associates a link with the item.
   *
   * You may turn the item into an anchor by specifying an link for it.
   * The link may point to a URL, a resource, or an internal path.
   *
   * The default link is a \p null link, which disables the anchor-like
   * functionality.
   */
  void setLink(const WLink& link);

  /*! \brief Returns the associated link.
   *
   * \sa setLink()
   */
  WLink link() const;

  /*! \brief Sets the link target.
   *
   * \sa setLink()
   */
  void setLinkTarget(AnchorTarget target);

  /*! \brief Returns the link target.
   *
   * \sa setLinkTarget()
   */
  AnchorTarget linkTarget() const;

  /*! \brief Sets a sub menu for the item.
   *
   * Sets a submenu for the item. Ownership of the submenu is transferred
   * to the item.
   *
   * \sa popupMenu()
   */
  void setPopupMenu(WPopupMenu *menu);

  /*! \brief Returns the sub menu.
   *
   * \sa setPopupMenu()
   */
  WPopupMenu *popupMenu() const { return subMenu_; }

  /*! \brief Sets the checked state.
   *
   * This is only used when isCheckable() == \c true.
   *
   * \sa setCheckable(bool), isCheckable()
   */
  void setChecked(bool checked);

  /*! \brief Returns the checked state.
   *
   * This is only used when isCheckable() == \c true.
   *
   * \sa setChecked(bool), isCheckable()
   */
  bool isChecked() const;

  /*! \brief Sets whether the menu item can be selected.
   *
   * Only a menu item that can be selected can be the result of a
   * popup menu selection.
   *
   * The default value is \c true for a normal menu item, and \c false
   * for a menu item that has a submenu.
   *
   * An item that is selectable but is disabled can still not be
   * selected.
   */
  void setSelectable(bool selectable);

  /*! \brief Returns whether the menu item can be selected.
   *
   * \sa setSelectable()
   */
  bool isSelectable() const { return selectable_; }

  /*! \brief Sets associated additional data with the item.
   */
  void setData(void *data) { data_ = data; }

  /*! \brief Returns additional data of the item.
   */
  void *data() const { return data_; }

  WCheckBox *checkBox() const { return checkBox_; }

  /*! \brief %Signal emitted when an item is activated.
   *
   * Returns this item as argument.
   *
   * \sa WPopupMenu::triggered()
   */
  Signal<WPopupMenuItem *>& triggered() { return triggered_; }

  virtual void load();
  virtual void setDisabled(bool disabled);

protected:
  virtual void render(WFlags<RenderFlag> flags);

private:
  // Constructs a separator
  WPopupMenuItem(bool);

  WAnchor     *impl_;
  WText       *text_;
  WCheckBox   *checkBox_;
  WPopupMenu  *subMenu_;
  void        *data_;
  bool         separator_, selectable_, rendered_;

  Signal<WPopupMenuItem *> triggered_;

  void create();
  void renderOver();
  void renderOut();
  void renderSelected(bool selected);
  void onMouseUp();

  WPopupMenu *parentMenu();
  WPopupMenu *topLevelMenu();

  friend class WPopupMenu;
};

}

#endif // WPOPUP_MENU_ITEM_H_
