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

#include <Wt/WCompositeWidget>

namespace Wt {

class WTree;
class WTreeTableNode;
class WText;

/*! \class WTreeTable Wt/WTreeTable Wt/WTreeTable
 *  \brief A table with a navigatable tree in the first column.
 *
 * A %WTreeTable implements a tree table, where additional data
 * associated is associated with tree items, which are organized in
 * columns.
 *
 * Unlike the MVC-based WTreeView widget, the tree renders a widget
 * hierarchy, rather than a hierarhical standard model. This provides
 * extra flexibility (as any widget can be used as contents), at the
 * cost of server-side, client-side and bandwidth resources
 * (especially for large tree tables).
 *
 * The actual data is organized and provided by WTreeTableNode widgets.
 *
 * To use the tree table, you must first use addColumn() to specify
 * the additional data columns. Then, you must set the tree root using
 * setTreeRoot() and bind additional information (text or other
 * widgets) in each node using WTreeTableNode::setColumnWidget().
 *
 * To apply a style to the table header hou should use CSS in
 * conjunction with the style class ("header") that is set for the
 * header row. Alternatively, you may access the header directly using
 * headerWidget(). To apply a different style to each column header,
 * you can access each column header widget using \link header()
 * header(int)\endlink, e.g. to set a style class.
 *
 * The table cannot be given a height using CSS style rules, instead you
 * must use layout managers, or use resize().
 *
 * \sa WTreeTableNode
 * \sa WTreeView
 */
class WT_API WTreeTable : public WCompositeWidget
{
public:
  /*! \brief Construct a new WTreeTable.
   *
   * The treeRoot() is 0. The table should first be properly dimensioned
   * using addColumn() calls, and then data using setTreeRoot().
   */
  WTreeTable(WContainerWidget *parent = 0);

  /*! \brief Add a column.
   *
   * Add a column, by specifying a header and a column width.
   */
  void addColumn(const WString& header, const WLength& width);

  /*! \brief The number of columns in this table.
   *
   * Returns the number of columns in the table, including in the count
   * the first column which contains the tree.
   */
  int numColumns() const { return columnWidths_.size(); }

  /*! \brief Set the tree root.
   *
   * Sets the data for the tree table, and specify the header for the
   * first column.
   *
   * \sa treeRoot(), setTree(WTree *tree, const WString&)
   */
  void setTreeRoot(WTreeTableNode *root, const WString& header);

  /*! \brief Get the tree root.
   */
  WTreeTableNode *treeRoot();

  /*! \brief Set the tree which provides the data for the tree table.
   *
   * \sa setTreeRoot(WTreeTableNode *, const WString&).
   */
  void setTree(WTree *tree, const WString& header);

  /*! \brief Get the tree that provides the data this table.
   *
   * \sa setTree(WTree *tree, const WString&).
   */
  WTree *tree() const { return tree_; }

  /*! \brief Get the column width for the given column.
   *
   * The width of the first column (with index 0), containing the
   * tree, is implied by the width set for the table minus the width
   * of all other columns.
   *
   * \sa addColumn(const WString&, const WLength&)
   */
  WLength columnWidth(int column) const { return columnWidths_[column]; }

  /*! \brief Get the header for the given column.
   *
   * \sa addColumn(const WString&, const WLength&)
   */
  WText *header(int column) const;

  /*! \brief Get the header widget.
   */
  WWidget *headerWidget() const;

private:
  WContainerWidget *impl_;
  WContainerWidget *headers_;
  WContainerWidget *headerContainer_;
  WTree            *tree_;

  std::vector<WLength> columnWidths_;  
};

}

#endif // WTREETABLE_H_
