// 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_PANEL_H_
#define EXT_PANEL_H_

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

namespace Wt {
  namespace Ext {

    class ToolBar;
    class Button;

/*! \class Panel Wt/Ext/Panel Wt/Ext/Panel
 *  \brief A container with a title and standard GUI elements.
 *
 * Like a Container, from which %Panel derives, a panel organizes its
 * contents using layout managers.
 *
 * The panel provides standard user-interface elements, such as a
 * title bar, top and bottom tool/menu bars, and footer buttons, and a
 * panel may be configured to be resizable and collapsible.
 *
 * Typically, panels will be added directly into a layout, and are
 * components to organize your user interface. You may also add a
 * panel to a plain container widget, but then you should set a size
 * for the panel (using WWidget::resize()), in pixels.
 *
 * When a panel is added to WApplication::root(), as single widget, it
 * acts like a plain Container, and thus none of the panel specific
 * features (tool bars, buttons, etc...) are available. If you want to
 * have a top-level Panel, you need thus to do something like this:
 * \code
   // create the root container
   Wt::Ext::Container *rootContainer = new Wt::Ext::Container(app->root());

   // create the root panel and fit it inside the container
   Wt::Ext::Panel *rootPanel = new Wt::Ext::Panel();
   rootContainer->setLayout(new Wt::WFitLayout());
   rootContainer->layout()->addWidget(rootPanel);

   \endcode
 *
 * \ingroup ext
 */
class WT_EXT_API Panel : public Container
{
public:
  /*! \brief Create a new panel.
   *
   * When a <i>parent</i> is specified, or the panel is after
   * construction added to a WContainerWidget, the panel should be
   * given an explicit size in pixels, using WWidget::resize().
   */
  Panel(WContainerWidget *parent = 0);

  /*! \brief Destruct a panel.
   */
  ~Panel();

  /*! \brief Set a tool bar at the top of the panel.
   *
   * <i>Note: you can only set a tool bar before the panel is rendered.</i>
   *
   * \sa topToolBar(), setBottomToolBar(ToolBar *)
   */
  void setTopToolBar(ToolBar *toolBar);

  /*! \brief Return the top tool bar.
   *
   * \sa setTopToolBar(ToolBar *), bottomToolBar()
   */
  ToolBar *topToolBar() const { return topToolBar_; }

  /*! \brief Set a tool bar at the bottom of the panel.
   *
   * <i>Note: you can only set a tool bar before the panel is rendered.</i>
   *
   * \sa bottomToolBar(), setTopToolBar(ToolBar *)
   */
  void setBottomToolBar(ToolBar *bottomBar);  

  /*! \brief Return the top tool bar.
   *
   * \sa setBottomToolBar(ToolBar *), topToolBar()
   */
  ToolBar *bottomToolBar() const { return bottomToolBar_; }

  /*! \brief Add a button to the footer of the panel.
   *
   * The button is displayed below the contents, but above a bottom tool bar
   * if it is set.
   *
   * \sa removeFooterButton(Button *), Dialog::addButton(Button *)
   */
  void addFooterButton(Button *button);

  /*! \brief Remove a button from the footer of the panel.
   *
   * Transfers ownership back, and so you must delete the button if you
   * wish to destroy it.
   *
   * \sa addFooterButton(Button *), Dialog::removeButton(Button *)
   */
  void removeFooterButton(Button *button);

  /*! \brief Retrn the list of footer buttons.
   *
   * \sa addFooterButton(Button *), removeFooterButton(Button *)
   */
  const std::vector<Button *>& footerButtons() const { return footerButtons_; }

  /*! \brief Set a title.
   *
   * The panel title is set in the title bar. This method also makes
   * the title bar visible by calling setTitleBar(true).
   *
   * When the panel is added to a TabWidget, the title serves as the
   * tab label.
   * 
   * \sa title(), setTitleBar(bool)
   */
  void setTitle(const WString& title);

  /*! \brief Get the title.
   *
   * \sa setTitle(const WString&)
   */
  const WString& title() const { return title_; }

  /*! \brief Show or hide a title bar for the panel.
   *
   * The title bar appears at the top of the panel, above the contents
   * and the top tool bar (if there is one). By default, the title bar
   * is not shown unless a title is set.
   *
   * \sa setTitle(const WString&)
   */
  void setTitleBar(bool enable);

  /*! \brief Get the title bar.
   *
   * \sa setTitleBar(bool)
   */
  bool titleBar() const { return titleBar_; }

  /*! \brief Set to use animations for the expand/collapse operation.
   *
   * By default, the expand/collapse operation of a panel is not
   * animated. This setting is ignored if the panel is not
   * collapsible.
   *
   * \sa animate(), setCollapsible(bool)
   */
  void setAnimate(bool on);

  /*! \brief Return if using animations for expand/collapse.
   *
   * \sa setAnimate(bool)
   */
  bool animate() const { return animate_; }

  /*! \brief Option to show scroll bars when needed.
   *
   * By default, scrollbars are disabled.
   */
  void setAutoScrollBars(bool on);

  /*! \brief Return if showing scroll bars when needed.
   *
   * \sa setAutoScrollBars(bool)
   */
  bool autoScrollBars() const { return autoScrollBars_; }

  /*! \brief Change the border around the panel.
   *
   * By default, a panel has a small border around it. Set <i>show</i>
   * false to disable the border.
   *
   * \sa border()
   */
  void setBorder(bool show);

  /*! \brief Get the border setting.
   *
   * \sa setBorder(bool)
   */
  bool border() const { return border_; }

  /*! \brief Set the panel expanded or callapsed.
   *
   * When <i>on</i> is <i>true</i>, the panel is collapsed, minimizing
   * screen real estate.
   *
   * Initially, a panel is expanded.
   *
   * \sa setCollapsible(bool on)
   */
  void setCollapsed(bool on);
  
  /*! \brief Collapse the panel
   *
   * \sa setCollapsible(bool on)
   */
  void collapse();

  /*! \brief Expand the panel
   *
   * \sa setCollapsible(bool on)
   */
  void expand();

  /*! \brief Return if the panel is collapsed.
   *
   * \sa setCollapsed(bool)
   * \sa collapsed() and expanded() signals
   */
  bool isCollapsed() const { return isCollapsed_; }

  /*! \brief Allow the user to collapse/expand the panel.
   *
   * When <i>on</i> is <i>true</i>, a button is added to the title bar, which
   * may be used to collapse/expand the panel.
   *
   * By default, a panel is not collapsible.
   *
   * \sa isCollapsed(), isCollapsible(), setCollapsed(bool)
   */
  void setCollapsible(bool on);

  /*! \brief Return if the user may collapse/expand the panel.
   *
   * \sa setCollapsible()
   */
  bool isCollapsible() const { return collapsible_; } 

  /*! \brief Allow the user to resize the panel.
   *
   * If true, then, depending on the layout the panel is in, a resize
   * handle will be displayed at one of the panel borders.
   *
   * By default, a panel may not be resized by the user.
   */
  void setResizable(bool on);

  /*! \brief Return if the user may resize the panel.
   *
   * \sa setResizable()
   */
  bool isResizable() const { return split_; }

  /*! \brief %Signal emitted when the panel is collapsed.
   *
   * \sa setCollapsible()
   */
  JSignal<>& collapsed() { return collapsed_; }

  /*! \brief %Signal emitted when the panel is expanded.
   *
   * \sa setCollapsible()
   */
  JSignal<>& expanded() { return expanded_; }

  virtual void refresh();

protected:
  virtual void updateExt();
  virtual void createConfig(std::ostream& config);
  virtual std::string createJS(DomElement *inContainer);

  void setDefaultButton(Button *button);
  Button *defaultButton() const { return defaultButton_; }

protected:
  virtual void removeChild(WWidget *child);

private:
  JSignal<> collapsed_, expanded_;

  bool    titleBar_, animate_, autoScrollBars_, border_, isCollapsed_,
    collapsible_, split_;
  WString title_;

  ToolBar *topToolBar_;
  ToolBar *bottomToolBar_;

  std::vector<Button *>  footerButtons_;
  Button                *defaultButton_;

  void onExpand();
  void onCollapse();

  friend class Button;
};

  }
}

#endif // EXT_PANEL_H_
