/*
 * ===========================
 * VDK Visual Development Kit
 * Version 0.5
 * December 1998
 * ===========================
 *
 * Copyright (C) 1998, Mario Motta
 * Developed by Mario Motta <mmotta@guest.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-130
 */ 

#ifndef VDKCTREE_H
#define VDKCTREE_H
#include <vdk/vdkcustom.h>
/*
 */
typedef GtkCTreeNode*                  VDKTreeNode;
typedef VDKArray<VDKTreeNode>          VDKTreeNodeArray;
typedef VDKList<GtkCTreeNode>          VDKTreeNodeList;
typedef VDKListIterator<GtkCTreeNode>  VDKTreeNodeListIterator;
/*!
  \class VDKCustomTree
  \brief This class wraps gtkctree widget.

  \par Signals
  \arg \b select_node_signal, emitted on selecting a tree node (or double
  clicking on extended selection mode). SelectedNode property contains
  selected node address. SelectedNode is set to NULL if no
  node is selected.
  \arg \b unselect_node_signal, emitted on unselecting a tree node .
  UnselectedNode property contains uelected node address. 
  UnselectedNode is set to NULL if no node is unselected.

  \par Tip
  VDKTreeNode is defined as GtkCTreeNode*

  \par EXAMPLES
  On ./testvdk/ctreewin.cc
 */
class VDKCustomTree: public VDKCustom
{
  int tree_column;
 protected:
  VDKTreeNodeArray WideSelection;

  static void ColumnClick(GtkWidget* w,
		  gint column,
		  gpointer s);
  static void NodeSelection(GtkWidget* ,
		  GtkCTreeNode* node,
		  int column,
		  gpointer s);
  static void NodeUnselection(GtkWidget* ,
		  GtkCTreeNode* node,
		  int column,
		  gpointer s);
  static int  ButtonPress (GtkWidget* wid, 
			   GdkEventButton *ev, 
			   gpointer s);

  void SetStyle(VDKTreeNode node);
  void ConnectSignals();
  void SetSpacing(int sp)
    { gtk_ctree_set_spacing(GTK_CTREE(custom_widget), sp); }
  void SetLineStyle(GtkCTreeLineStyle ls)
    { gtk_ctree_set_line_style (GTK_CTREE(custom_widget), ls); }
  void SetExpanderStyle(GtkCTreeExpanderStyle es)
    { gtk_ctree_set_expander_style (GTK_CTREE(custom_widget), es); }
  void SetSelectedNode(VDKTreeNode node);
  void SetUnselectedNode(VDKTreeNode node);
  // properties
 public:
  /*!
    Sets/gets spacing distance (default 5)
   */
  __rwproperty(VDKCustomTree,int) Spacing;
  /*!
    Sets/gets selected node, setting to NULL will select root node.
    An aswer NULL means no node selected.
   */
  __rwproperty(VDKCustomTree,VDKTreeNode) SelectedNode;
  /*!
    Sets/gets selected column, an answer == -1 means no column
    selected.
   */
  __rproperty(VDKCustomTree,int) SelectedColumn;
  /*!
    Sets/gets unselected node, setting to NULL will unselect root node.
    An aswer NULL means no node unselected.
   */
  __rwproperty(VDKCustomTree,VDKTreeNode) UnselectedNode;
  /*!
    Sets/gets unselected column, an answer == -1 means no column
    unselected.
   */
  __rproperty(VDKCustomTree,int) UnselectedColumn;
  /*!
    Sets/gets line style arg. (default GTK_CTREE_LINES_SOLID)
   */
  __rwproperty(VDKCustomTree,GtkCTreeLineStyle) LineStyle;
  /*!
    Sets/gets expander style (default GTK_CTREE_EXPANDER_SQUARE)
   */
  __rwproperty(VDKCustomTree,GtkCTreeExpanderStyle) ExpanderStyle;
 public:
  /*!
    Constructor
    \param columns, number of columns
    \param titles, an array of title strings
    \param mode, selection mode
    \param tree_column, key column
   */
  VDKCustomTree(VDKForm* owner,
		int columns = 1,
		char **titles = NULL,
		GtkSelectionMode mode = GTK_SELECTION_SINGLE,
		int tree_column = 0);
  /*!
    Destructor
   */
  virtual ~VDKCustomTree();
  /*!
    Add a node to <parent> tree.
    \param text, an array of strings
    \param parent, if NULL add the node as a new root (same as adding
    a row to a VDKCustomList)
    \param isLeaf, if is a leaf or not
    \param pixmap_closed, pixmap showed when node is collapsed
    \param pixmap_open, pixmap showed when node is expanded
   */
  VDKTreeNode AddNode(char  *text[],
		      GtkCTreeNode *parent,
		      bool expanded = true,
		      bool isLeaf = false,
		      char **pixmap_closed = NULL,
		      char** pixmap_opened = NULL );
  /*!
    Removes a node, return true on success
    \param node , node to be removed
   */
  bool RemoveNode(VDKTreeNode node);
  /*!
    Removes all nodes with key==<key>, return number of removed nodes
   */
  int RemoveKey(char* key);
  virtual void Clear();
  // selection (most for similarity with VDKCustomList)
  /*!
    Returns selected node
   */
  VDKTreeNode Selection() { return SelectedNode; }
  /*!
    Returns unselected node
   */
  VDKTreeNode Unselection() { return UnselectedNode; }
  /*!
    Returns an array of selected nodes (valid on multiple and
    extended mode)
   */
  VDKTreeNodeArray& Selections();
  // access operator
  /*!
    Returns a tuple of <node> node, an array containing all columns
    texts.
    \param node
   */
  Tuple operator[](VDKTreeNode node);
  /*!
    Returns a list of nodes that match <key>.
    Returned list should be deleted by user or it will leak.
   */
  VDKTreeNodeList* Find(char* key);
  // some useful functions on nodes
  /*!
    Returns true if <node> is a leaf
    \param node
   */
  bool IsLeaf(VDKTreeNode node);
  /*!
    Returns node key
    \param node
   */
  char* Key(VDKTreeNode node);
  /*!
    Returns true if <node> is expanded
    \param node
   */
  bool IsExpanded(VDKTreeNode node);
#ifdef USE_SIGCPLUSPLUS
 public:
  /*!
    Extended LS signal system:
    Received when a node is selected
    \param VDKTreeNode selected node
    \param int column selected column
  */
  VDKSignal2<void, VDKTreeNode, int> OnNodeSelect;
  /*!
    Extended LS signal system:
    Received when a node is unselected
    \param VDKTreeNode unselected node
    \param int column unselected column
  */
  VDKSignal2<void, VDKTreeNode, int> OnNodeUnselect;
  /*!
    Extended LS signal system:
    Received when a node is moved
    \param VDKTreeNode unselected node
    \param VDKTreeNode new parent
    \param VDKTreeNode new sibling
  */
  VDKSignal3<void, VDKTreeNode, VDKTreeNode, VDKTreeNode> OnTreeMove;
  /*!
    Extended LS signal system:
    Received when a node is expanded
    \param VDKTreeNode expanded node
  */
  VDKSignal1<void, VDKTreeNode> OnTreeExpand;
 protected:  
  static void make_gtksigc_connection(VDKCustomTree* obj);
 private:
  static void _handle_tree_move(GtkWidget*, GtkCTreeNode* node, 
				GtkCTreeNode* new_parent,
				GtkCTreeNode* new_sibling, 
				gpointer obj);
  static void _handle_tree_expand(GtkWidget*, GtkCTreeNode* node,
				  gpointer obj);
#endif /* USE_SIGCPLUSPLUS */
};

#endif
