/******************************************************************************
 JXTreeListWidget.h

	Copyright © 1997 by Glenn W. Bach. All rights reserved.

 ******************************************************************************/

#ifndef _H_JXTreeListWidget
#define _H_JXTreeListWidget

#include <JXStyleTable.h>

class JTreeNode;
class JTreeList;
class JXTLWAdjustToTreeTask;

class JXTreeListWidget : public JXStyleTable
{
	friend class JXTLWAdjustToTreeTask;

public:

	enum OpenAllAction
	{
		kOpenSiblings,
		kOpenDescendants
	};

public:

	JXTreeListWidget(JTreeList* treeList,
					 JXScrollbarSet* scrollbarSet, JXContainer* enclosure,
					 const HSizingOption hSizing, const VSizingOption vSizing,
					 const JCoordinate x, const JCoordinate y,
					 const JCoordinate w, const JCoordinate h);

	virtual	~JXTreeListWidget();

	JTreeList*			GetTreeList();
	const JTreeList*	GetTreeList() const;

	JIndex	GetToggleOpenColIndex() const;
	JIndex	GetNodeColIndex() const;

	void	ScrollToNode(const JTreeNode* node);
	void	GetSelectedNodes(JPtrArray<JTreeNode>* list);
	void	SelectNodes(const JPtrArray<JTreeNode>& list);
	void	OpenSelectedNodes(const JBoolean all = kFalse);
	void	CloseSelectedNodes(const JBoolean all = kFalse);
	void	ToggleNode(const JIndex index, const JBoolean all = kFalse);

	JSize	GetIndentWidth() const;
	void	SetIndentWidth(const JSize width);
	JSize	GetNodeIndent(const JIndex index) const;

	OpenAllAction	GetOpenAllAction() const;
	JSize			GetMaxOpenDepth() const;
	void			SetOpenAllAction(const OpenAllAction action, const JSize maxDepth);

	virtual void		HandleKeyPress(const int key, const JXKeyModifiers& modifiers);
	virtual JBoolean	IsSelectable(const JPoint& cell,
									 const JBoolean forExtend) const;
	virtual JBoolean	IsEditable(const JPoint& cell) const;

protected:

	void	JXTreeListWidgetX();

	JBoolean	WillDrawSelection() const;
	void		ShouldDrawSelection(const JBoolean draw);

	JIndex	GetElasticColIndex() const;
	void	SetElasticColIndex(const JIndex index);

	void			NeedsAdjustToTree();
	virtual void	AdjustToTree();
	virtual JSize	GetMinCellWidth(const JPoint& cell) const = 0;

	virtual void	TableDrawCell(JPainter& p, const JPoint& cell, const JRect& rect);
	virtual void	TLWDrawNode(JPainter& p, const JPoint& cell, const JRect& rect) = 0;

	JBoolean		IsDraggingToggle() const;
	virtual void	HandleMouseDown(const JPoint& pt, const JXMouseButton button,
									const JSize clickCount,
						 			const JXButtonStates& buttonStates,
									const JXKeyModifiers& modifiers);
	virtual void	HandleMouseDrag(const JPoint& pt, const JXButtonStates& buttonStates,
									const JXKeyModifiers& modifiers);
	virtual void	HandleMouseUp(const JPoint& pt, const JXMouseButton button,
								  const JXButtonStates& buttonStates,
								  const JXKeyModifiers& modifiers);

	virtual void	ApertureResized(const JCoordinate dw, const JCoordinate dh);
	virtual void	Receive(JBroadcaster* sender, const Message& message);

private:

	JTreeList*	itsTreeList;
	JIndex		itsToggleOpenColIndex;
	JIndex		itsNodeColIndex;
	JSize		itsIndentWidth;
	JBoolean	itsDrawSelectionFlag;

	JArray<JSize>*	itsMinColWidths;		// minimum width of each column
	JIndex			itsElasticColIndex;		// column that can expand to fill aperture width

	JXTLWAdjustToTreeTask*	itsAdjustToTreeTask;	// can be NULL

	// used during node move

	JPtrArray<JTreeNode>*	itsReselectNodeList;	// contents owned by JTree
	JString*				itsSavedScrollSetup;	// NULL except during move

	// used while dragging

	JBoolean		itsToggleDragFlag;
	JBoolean		itsMouseInToggleFlag;
	JCoordinate		itsToggleDragIndex;		// JCoordinate to avoid signed-unsigned compare
	OpenAllAction	itsOpenAllAction;
	JSize			itsMaxOpenDepth;		// max depth when opening descendants

private:

	void	AdjustColWidths();

	void	HandlePrepareForNodeMove();
	void	HandleNodeMoveFinished();

	// not allowed

	JXTreeListWidget(const JXTreeListWidget& source);
	const JXTreeListWidget& operator=(const JXTreeListWidget& source);

public:

	// JBroadcaster messages

	static const JCharacter* kNodeDblClicked;

	class NodeDblClicked : public JBroadcaster::Message
		{
		public:

			NodeDblClicked(const JTreeNode* node, const JPoint& cell)
				:
				JBroadcaster::Message(kNodeDblClicked),
				itsNode(node),
				itsCell(cell)
			{ };

			const JTreeNode*
			GetNode() const
			{
				return itsNode;
			};

			JIndex
			GetRow() const
			{
				return itsCell.y;
			};

			JIndex
			GetColumn() const
			{
				return itsCell.x;
			};

			const JPoint&
			GetCell() const
			{
				return itsCell;
			};

		private:

			const JTreeNode*	itsNode;
			JPoint				itsCell;
		};
};


/******************************************************************************
 GetTreeList

 ******************************************************************************/

inline JTreeList*
JXTreeListWidget::GetTreeList()
{
	return itsTreeList;
}

inline const JTreeList*
JXTreeListWidget::GetTreeList()
	const
{
	return itsTreeList;
}

/******************************************************************************
 Column indices

 ******************************************************************************/

inline JIndex
JXTreeListWidget::GetToggleOpenColIndex()
	const
{
	return itsToggleOpenColIndex;
}

inline JIndex
JXTreeListWidget::GetNodeColIndex()
	const
{
	return itsNodeColIndex;
}

/******************************************************************************
 Elastic column index

	Set the index to zero to force all columns to their minimum width.

 ******************************************************************************/

inline JIndex
JXTreeListWidget::GetElasticColIndex()
	const
{
	return itsElasticColIndex;
}

inline void
JXTreeListWidget::SetElasticColIndex
	(
	const JIndex index
	)
{
	itsElasticColIndex = index;
	NeedsAdjustToTree();
}

/******************************************************************************
 Indent width

	This specified how far a nodes children should be indented relative
	to the node itself.

 ******************************************************************************/

inline JSize
JXTreeListWidget::GetIndentWidth()
	const
{
	return itsIndentWidth;
}

inline void
JXTreeListWidget::SetIndentWidth
	(
	const JSize width
	)
{
	itsIndentWidth = width;
	NeedsAdjustToTree();
}

/******************************************************************************
 Draw selection (protected)

 ******************************************************************************/

inline JBoolean
JXTreeListWidget::WillDrawSelection()
	const
{
	return itsDrawSelectionFlag;
}

inline void
JXTreeListWidget::ShouldDrawSelection
	(
	const JBoolean draw
	)
{
	itsDrawSelectionFlag = draw;
}

/******************************************************************************
 Open all action

	This specifies what happens when ToggleNode() is called with all==kTrue
	and what meta-click in the ToggleOpen column does.

 ******************************************************************************/

inline JXTreeListWidget::OpenAllAction
JXTreeListWidget::GetOpenAllAction()
	const
{
	return itsOpenAllAction;
}

inline JSize
JXTreeListWidget::GetMaxOpenDepth()
	const
{
	return itsMaxOpenDepth;
}

inline void
JXTreeListWidget::SetOpenAllAction
	(
	const OpenAllAction	action,
	const JSize			maxDepth
	)
{
	itsOpenAllAction = action;
	itsMaxOpenDepth  = maxDepth;
}

/******************************************************************************
 IsDraggingToggle (protected)

 ******************************************************************************/

inline JBoolean
JXTreeListWidget::IsDraggingToggle()
	const
{
	return itsToggleDragFlag;
}

#endif
