// 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_CONTAINER_H_
#define EXT_CONTAINER_H_

#include <Wt/Ext/Component>

namespace Wt {
  namespace Ext {

    class LayoutImpl;
    class TabWidget;

/*! \class Container Wt/Ext/Container Wt/Ext/Container
 *  \brief A container class which manages its contents using layout managers.
 *
 * The %Container is the %Ext equivalent of WContainerWidget, and
 * manages other widgets. Unlike %WContainerWidget, %Container can
 * only use layout managers to manage its content.
 *
 * Typically, panels will be added directly into a layout (which may
 * be part of an Ext::Container or a WContainerWidget), and are
 * components to organize your user interface. You may also add a
 * container inside a plain WContainerWidget, but then you should set
 * a size for the container (using WWidget::resize()), in pixels.
 *
 * In most cases, using a Panel is more convenient than a Container,
 * since a Panel also manages standard GUI components (such as
 * menu/tool bars), and interactive controls (for resizing, for
 * example). There is however one case where you need to use a
 * Container, which is when you wish to use a layout manager to manage
 * the contents of the entire view port. In that case, you should use
 * a Container to represent the view port, by adding the Container as
 * only child directly to the application's WApplication::root()
 * container.
 *
 * For example, the following creates a top borderlayout that spans
 * the entire viewport:
 * \code
 * Wt::Ext::Container *rootContainer = new Wt::Ext::Container(app->root());
 * Wt::WBorderLayout *topLayout = new Wt::WBorderLayout()
 * rootContainer->setLayout(topLayout);
 * \endcode
 */
class WT_EXT_API Container : public Component
{
public:
  /*! \brief Create a new container.
   *
   * When a <i>parent</i> is specified, or the container is after
   * construction added to a WContainerWidget, the container should be
   * given an explicit size in pixels, using WWidget::resize().
   */
  Container(WContainerWidget *parent = 0);

  /*! \brief Destroy the container.
   */
  virtual ~Container();

  /*! \brief Set a layout manager for the container.
   *
   * Only a single layout manager may be set. Note that you can nest
   * layout managers inside each other, to create a complex layout
   * hierarchy.
   *
   * \sa layout()
   */
  void setLayout(WLayout *layout);

  /*! \brief Get the layout manager that was set for the container.
   *
   * If no layout manager was previously set using setLayout(WLayout
   * *), a default layout manager is created (WDefaultLayout), which
   * does not attempt to size widgets to fit the entire container
   * region.
   *
   * \sa setLayout(WLayout *)
   */
  WLayout *layout();

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

  virtual std::string extClassName() const;

  virtual void removeChild(WWidget *child);

  virtual void getDomChanges(std::vector<DomElement *>& result,
			     WApplication *app);

private:
  WLayout  *layout_;
  WWidget  *widget_;
  bool     layoutChanged_;

  bool inWtLayout() const;

  void setWidget(WWidget *widget);
  WWidget *widget() const { return widget_; }

  void addLayoutConfig(Widget *w, std::ostream& config);
  static void setSizeConfig(std::ostream& config, WWidget *w);
  virtual bool applySelfCss() const;

  void add(WWidget *w);

  void setLayoutChanged();

  virtual WLayoutItemImpl *createLayoutItemImpl(WLayoutItem *item);
  Ext::LayoutImpl *layoutImpl() const;

  friend class Ext::LayoutImpl;
  friend class Widget;
  friend class WWidgetItemImpl;
  friend class TabWidget;
};

  }
}

#endif // EXT_CONTAINER_WIDGET_H_
