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

#include <Wt/WWidget>

namespace Wt {

/*! \class WCompositeWidget Wt/WCompositeWidget Wt/WCompositeWidget
 *  \brief A widget that hides the implementation of composite widgets.
 *
 * Composite widgets, built on top of the WebWidgets, should derive
 * from this class, and use setImplementation() to set the widget that
 * implements the composite widget (which is typically a WContainerWidget
 * or a WTable, or another widget that allows composition, including perhaps
 * another %WCompositeWidget).
 *
 * Using this class you can completely hide the implementation of your
 * composite widget, and provide access to only the standard WWidget
 * methods.
 *
 * \if cpp
 * Usage example:
 * \code
 * class MyWidget : public Wt::WCompositeWidget
 * {
 * public:
 *   MyWidget(WContainerWidget *parent = 0)
 *     : WCompositeWidget(parent)
 *       // initialize members ...
 *   {
 *     setImplementation(impl_ = new WContainerWidget());
 *
 *     // further initialization code ...
 *   }
 *
 * private:
 *   Wt::WContainerWidget *impl_;
 * };
 * \endcode
 * \endif
 */
class WT_API WCompositeWidget : public WWidget
{
public:
  /*! \brief Creates a %WCompositeWidget.
   *
   * You need to set an implemetation using setImplementation() directly
   * after construction.
   */
  WCompositeWidget(WContainerWidget* parent = 0);

  /*! \brief Creates a %WCompositeWidget with given implementation.
   *
   * \sa setImplementation()
   */
  WCompositeWidget(WWidget *implementation, WContainerWidget* parent);

  ~WCompositeWidget();

  using WWidget::removeChild;

  virtual void setObjectName(const std::string& name);
  virtual std::string objectName() const;
  virtual const std::string id() const;

  virtual void setPositionScheme(PositionScheme scheme);
  virtual PositionScheme positionScheme() const;
  virtual void setOffsets(const WLength& offset, WFlags<Side> sides = All);
  virtual WLength offset(Side s) const;
  virtual void resize(const WLength& width, const WLength& height);
  virtual WLength width() const;
  virtual WLength height() const;
  virtual void setMinimumSize(const WLength& width, const WLength& height);
  virtual WLength minimumWidth() const;
  virtual WLength minimumHeight() const;
  virtual void setMaximumSize(const WLength& width, const WLength& height);
  virtual WLength maximumWidth() const;
  virtual WLength maximumHeight() const;
  virtual void setLineHeight(const WLength& height);
  virtual WLength lineHeight() const;
  virtual void setFloatSide(Side s);
  virtual Side floatSide() const;
  virtual void setClearSides(WFlags<Side> sides);
  virtual WFlags<Side> clearSides() const;
  virtual void setMargin(const WLength& margin, WFlags<Side> sides = All);
  virtual WLength margin(Side side) const;
  virtual void setHiddenKeepsGeometry(bool enabled);
  virtual bool hiddenKeepsGeometry() const;
  virtual void setHidden(bool hidden, const WAnimation& animation = WAnimation());
  virtual bool isHidden() const;
  virtual bool isVisible() const;
  virtual void setDisabled(bool disabled);
  virtual bool isDisabled() const;
  virtual bool isEnabled() const;
  virtual void setPopup(bool popup);
  virtual bool isPopup() const;
  virtual void setInline(bool isInline);
  virtual bool isInline() const;
  virtual void setDecorationStyle(const WCssDecorationStyle& style);
  virtual WCssDecorationStyle& decorationStyle();
  virtual const WCssDecorationStyle& decorationStyle() const;
  virtual void setStyleClass(const WT_USTRING& styleClass);
  void setStyleClass(const char *styleClass);
  virtual WT_USTRING styleClass() const;
  virtual void addStyleClass(const WT_USTRING& styleClass, bool force = false);
  void addStyleClass(const char *styleClass, bool force = false);
  virtual void removeStyleClass(const WT_USTRING& styleClass,
				bool force = false);
  void removeStyleClass(const char *styleClass, bool force = false);
  virtual bool hasStyleClass(const WT_USTRING& styleClass) const;
  virtual void setVerticalAlignment(AlignmentFlag alignment,
				    const WLength& length = WLength::Auto);
  virtual AlignmentFlag verticalAlignment() const;
  virtual WLength verticalAlignmentLength() const;
  virtual WWebWidget *webWidget();
  virtual void setToolTip(const WString& text,
			  TextFormat textFormat = PlainText);
  virtual WString toolTip() const;
  virtual void setDeferredToolTip(bool enable,
                                  TextFormat textFormat = PlainText);
  virtual void refresh();
  virtual void setAttributeValue(const std::string& name,
				 const WT_USTRING& value);
  virtual WT_USTRING attributeValue(const std::string& name) const;
  virtual void setJavaScriptMember(const std::string& name,
				   const std::string& value);
  virtual std::string javaScriptMember(const std::string& name) const;
  virtual void callJavaScriptMember(const std::string& name,
				    const std::string& args);
  virtual void load();
  virtual bool loaded() const;
  virtual void setCanReceiveFocus(bool enabled);
  virtual bool canReceiveFocus() const;
  virtual void setFocus(bool focus);
  virtual bool setFirstFocus();
  virtual bool hasFocus() const;
  virtual void setTabIndex(int index);
  virtual int tabIndex() const;
  virtual int zIndex() const;
  virtual void setId(const std::string& id);
  virtual WWidget *find(const std::string& name);
  virtual WWidget *findById(const std::string& name);
  virtual void setSelectable(bool selectable);  
  virtual void doJavaScript(const std::string& js);
  virtual void propagateSetEnabled(bool enabled);

#ifndef WT_TARGET_JAVA
  using WWidget::setFocus;
#endif

protected:
  virtual void addChild(WWidget *child);
  virtual void removeChild(WWidget *child);
  virtual void setHideWithOffsets(bool how);

  virtual bool isStubbed() const;
  virtual void enableAjax();

  /*! \brief Set the implementation widget
   *
   * This sets the widget that implements this compositeWidget. Ownership
   * of the widget is completely transferred (including deletion).
   *
   * \note You cannot change the implementation of a composite widget after
   *       it has been rendered.
   */
  void setImplementation(WWidget *widget);
 
  /*! \brief Get the implementation widget
   *
   * This returns the widget that implements this compositeWidget.
   */
  WWidget* implementation() { return impl_; };

  WWidget *takeImplementation();

  virtual void getSDomChanges(std::vector<DomElement *>& result,
			      WApplication *app);
  virtual bool needsToBeRendered() const;

  virtual int boxPadding(Orientation orientation) const;
  virtual int boxBorder(Orientation orientation) const;
  virtual void render(WFlags<RenderFlag> flags);

private:
  WWidget *impl_;

  virtual void setLayout(WLayout *layout);
  virtual WLayout *layout();
  virtual WLayoutItemImpl *createLayoutItemImpl(WLayoutItem *layoutItem);
};

}

#endif // WCOMPOSITE_WIDGET_H_
