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

#include <Wt/WJavaScript>
#include <Wt/Ext/Panel>

namespace Wt {
  namespace Ext {

/*! \class TabWidget Wt/Ext/TabWidget Wt/Ext/TabWidget
 *  \brief A widget that organizes contents in tab panes
 *
 * This widget has an API that is similar to the WTabWidget.
 *
 * Unlike WTabWidget, each tab is actually represented by a Panel, and
 * methods are provided to add a panel directly (see addTab(Panel
 * *)). The panel titles are then used as the tab labels.
 *
 * The widget inherits from Panel, and uses a WDefaultLayout
 * to contain the tab panels. Adding panels to the layout is
 * equivalent to adding tabs to the tab widget.
 *
 * \image html ExtTabWidget-1.png "Example of a TabWidget"
 *
 * \ingroup ext
 */
class WT_EXT_API TabWidget : public Panel
{
public:
  /*! \brief Create a new TabWidget
   */
  TabWidget(WContainerWidget *parent = 0);

  /*! \brief Add a new tab, with <i>child</i> as content, and the given label.
   *
   * This is implemented by creating a panel for the widget, and setting the
   * panel title to be the label.
   *
   * \sa addTab(Panel *), removeTab(int), widget(int)
   */
  void addTab(WWidget *child, const WString& label);

  /*! \brief Add a new tab panel.
   *
   * The panel title is used as the tab label.
   *
   * \sa addTab(WWidget *, const WString&)
   */
  void addTab(Panel *panel);

  /*! \brief Remove a tab.
   *
   * \sa addTab(Panel *), addTab(WWidget *, const WString&)
   * \sa indexOf(WWidget *)
   */
  void removeTab(int index);

  /*! \brief Return the number of tabs.
   */
  int count() const;

  /*! \brief Return t the panel at the given tab <i>index</i>.
   *
   * \sa widget(int)
   */
  Panel *panel(int index) const;

  /*! \brief Return the content widget at the given tab <i>index</i>.
   *
   * \sa panel(int)
   */
  WWidget *widget(int index) const;

  /*! \brief Return the index of the given widget/panel.
   *
   * If the widget was not added to this tab widget, then -1 is returned.
   */
  int indexOf(WWidget *widget) const;

  /*! \brief Activate the tab at <i>index</i>.
   *
   * \sa setCurrentWidget(WWidget *), currentIndex()
   * \sa currentChanged() signal
   */
  void setCurrentIndex(int index);

  /*! \brief Return the index of the activated tab.
   *
   * \sa setCurrentIndex(int)
   */
  int currentIndex() const;

  /*! \brief Activate the tab showing the given <i>widget</i>
   *
   * This is equivalent to setCurrentIndex(indexOf(<i>widget</i>))
   * \sa currentWidget(), setCurrentIndex(int)
   */
  void setCurrentWidget(WWidget *widget);

  /*! \brief Return the widget of the activated tab.
   *
   * \sa setCurrentWidget(WWidget *), currentIndex()
   */
  WWidget *currentWidget() const;

  /*! \brief Enable or disable a tab.
   *
   * Enables or disables the tab at <i>index</i>. A disabled tab cannot be
   * activated.
   */
  void setTabEnabled(int index, bool enable);

  /*! \brief Returns if a tab is enabled.
   */
  bool isTabEnabled(int index) const;

  /*! \brief Hide or show a tab.
   *
   * Hides are shows the tab at <i>index</i>.
   */
  void setTabHidden(int index, bool hidden);

  /*! \brief Return if a tab is hidden.
   */
  bool isTabHidden(int index) const;

  /*! \brief Change the label for a tab.
   *
   * This is equivalent to panel(<i>index</i>)->setTitle(<i>label</i>);
   *
   * \sa tabText(int)
   */
  void setTabText(int index, const WString& label);

  /*! \brief Return the label for a tab.
   *
   * \sa setTabText(int, const WString&)
   */
  const WString& tabText(int index) const;

  /*! \brief Set the tooltip for a tab.
   *
   * The tooltip is shown when the user hovers over the label.
   *
   * <b>This seems currently broken in extjs 2.0.</b>
   */
  void setTabToolTip(int index, const WString& tip);

  /*! \brief Return the tooltip for a tab.
   */
  const WString tabToolTip(int index) const;

  virtual void refresh();

  /*! \brief %Signal emitted when the user activates a tab.
   *
   * The index of the newly activated tab is passed as an argument.
   */
  Signal<int>& currentChanged() { return currentChanged_; }

protected:
  virtual void updateExt();
  virtual void createConfig(std::ostream& config);
  virtual std::string extClassName() const;

  virtual void removeChild(WWidget *child);

private:
  Signal<int>  currentChanged_;
  JSignal<int> jCurrentChanged_;
  std::vector<Panel *> panels_;
  int currentIndex_;
  
  virtual std::string createJS(DomElement *inContainer);

  void onTabChange(int index);
};

  }
}

#endif // EXT_TABWIDGET_H_
