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

#include <Wt/WObject>

namespace Wt {

class WContainerWidget;
class WMenu;
class WWidget;

/*! \brief A single item in a menu.
 *
 * By default, a WMenuItem is rendered as a plain WText widget.
 *
 * To provide another look for the menu items (such as perhaps adding
 * an icon), you can specialize this class, and reimplement the
 * virtual methods:
 *
 * <ul>
 *   <li>createItemWidget(): to provide another widget to represent the
 *     item.</li>
 *   <li>optionally, activateSignal(): to bind the event for activating
 *     the item to something else than the clicked event.</li>
 *   <li>optionally, renderSelected(bool): if you need to do additional
 *     styling to reflect a selection, other than changing style classes.</li>
 * </ul>
 *
 * \sa WMenu
 * \sa WMenu::addItem(WMenuItem *)
 */
class WT_API WMenuItem : public WObject
{
public:
  /*! \brief When should the contents be loaded ?
   */
  enum LoadPolicy { LazyLoading,     //!< Lazy loading: on first use
		    PreLoading       //!< Pre-loading: before first use
  };

  /*! \brief Create a new WMenuItem.
   *
   * The text specifies the item text. The contents is the widget that must
   * be shown in the WMenu contents stack when the item is selected.
   *
   * The load policy specifies whether the contents widgets is transmitted
   * only when it the item is activated for the first time (LazyLoading)
   * or transmitted prior to first rendering.
   */
  WMenuItem(const WString& text, WWidget *contents,
	    LoadPolicy policy);

  /* !\brief Delete a WMenuItem.
   */
  ~WMenuItem();

  /*! \brief Get the text for this item.
   */
  const WString& text() const { return text_; }

  /*! \brief Set the text for this item.
   */
  virtual void setText(const WString& text);

public slots:
  /*! \brief Select this item.
   */
  void select();

protected:
  /*! \brief Get the widget that represents the item in the WMenu.
   *
   * This returns the widget that was previously created
   * using createItemWidget().
   */
  WWidget *itemWidget();

  /*! \brief Render the item selected or unselected.
   *
   * The default implementation will set the styleclass to 'item' for
   * an unselected, and 'itemselected' for a selected item.
   *
   * Note that this methods is called from within a stateless slot
   * implementation, and thus should be stateless as well.
   */
  virtual void renderSelected(bool selected);

protected:
  /*! \brief Create the widget that represents the item in the WMenu.
   *
   * The default implementation will create and return a WText representation,
   * unless the menu has history tacking activated and the agent is a
   * web spider. In that case, a WAnchor is will be used to create a link.
   *
   * Note that if you reimplement this method, you should also reimplement
   * setText(const WString&) and activateSignal().
   */
  virtual WWidget *createItemWidget();

  /*! \brief Get the signal that will be used to activate the item.
   *
   * The default implementation will try to cast the itemWidget() to
   * a WInteractWidget and bind the clicked signal.
   */
  virtual SignalBase& activateSignal();

  WString           text_;

private:
  WWidget *contents();
  void     loadContents();
  void     setMenu(WMenu *menu);

private:
  WWidget          *itemWidget_;
  WContainerWidget *contentsContainer_;
  WWidget          *contents_;
  WMenu            *menu_;

  void selectVisual();
  void undoSelectVisual();

  friend class WMenu;
};

}

#endif // WMENU_ITEM_H_
