/******************************************************************************
 JXUNIXDirTable.h

	Interface for the JXUNIXDirTable class

	Copyright © 1996 by Glenn W. Bach.
	Copyright © 1998 by John Lindal.  All rights reserved.

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

#ifndef _H_JXUNIXDirTable
#define _H_JXUNIXDirTable

#include <JXTable.h>

class JString;
class JUNIXDirInfo;
class JUNIXDirEntry;
class JXImage;
class JXIdleTask;
class JXUNIXDirUpdateTask;

class JXUNIXDirTable : public JXTable
{
public:

	JXUNIXDirTable(JUNIXDirInfo* data,
				   JXScrollbarSet* scrollbarSet, JXContainer* enclosure,
				   const HSizingOption hSizing, const VSizingOption vSizing,
				   const JCoordinate x, const JCoordinate y,
				   const JCoordinate w, const JCoordinate h);

	virtual ~JXUNIXDirTable();

	const JString&	GetPath() const;

	JBoolean	HasSelection() const;
	JBoolean	HasSingleSelection() const;
	JBoolean	GetFirstSelection(const JUNIXDirEntry** theEntry) const;
	JBoolean	GetSelection(JPtrArray<JUNIXDirEntry>* entryList) const;
	JBoolean	SelectSingleEntry(const JIndex index, const JBoolean scroll = kTrue);
	void		SelectFirstEntry(const JBoolean scroll = kTrue);
	void		SelectLastEntry(const JBoolean scroll = kTrue);
	void		SelectAll();
	JBoolean	ClosestMatch(const JCharacter* prefixStr, JIndex* index) const;

	void	ShowHidden(const JBoolean showHidden);
	void	AllowSelectFiles(const JBoolean allowSelectFiles, const JBoolean allowMultiple);
	void	AllowDblClickInactive(const JBoolean allow);
	void	InstallShortcuts();

	JBoolean	GoToSelectedDirectory();

	JBoolean	WillSelectWhenChangePath() const;
	void		ShouldSelectWhenChangePath(const JBoolean select);

	virtual void	HandleKeyPress(const int key, const JXKeyModifiers& modifiers);
	virtual void	HandleShortcut(const int key, const JXKeyModifiers& modifiers);

	// for use by JXUNIXDirUpdateTask

	void	UpdateDisplay();

protected:

	JBoolean	ItemIsActive(const JIndex index) const;
	JBoolean	ItemIsFile(const JIndex index) const;

	JBoolean	GetNextSelectable(const JIndex startIndex, const JBoolean forMulti,
								  JIndex* nextIndex) const;
	JBoolean	GetPrevSelectable(const JIndex startIndex, const JBoolean forMulti,
								  JIndex* nextIndex) const;
	JBoolean	ItemIsSelectable(const JIndex index, const JBoolean forMulti) const;

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

	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 JBoolean	WillAcceptDrop(const JArray<Atom>& typeList, Atom* action,
									   const Time time, const JXWidget* source);
	virtual void		HandleDNDDrop(const JPoint& pt, const JArray<Atom>& typeList,
									  const Atom action, const Time time,
									  const JXWidget* source);

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

private:

	enum DragType
	{
		kInvalidDrag,
		kSelectSingleDrag,
		kSelectCellDrag,
		kDeselectCellDrag,
		kSelectRangeDrag
	};

private:

	JUNIXDirInfo*			itsDirInfo;			// not owned
	JRunArray<JBoolean>*	itsActiveCells;
	JXUNIXDirUpdateTask*	itsDirUpdateTask;

	DragType	itsDragType;
	JBoolean	itsAllowSelectFilesFlag;
	JBoolean	itsAllowSelectMultipleFlag;		// kTrue => select multiple files, but not directories
	JBoolean	itsAllowDblClickInactiveFlag;	// kTrue => broadcast FileDblClicked even if inactive
	JBoolean	itsSelectWhenChangePathFlag;	// kTrue => select first entry when path changes
	JSize		itsMaxStringWidth;
	JString*	itsKeyBuffer;

	JBoolean			itsReselectFlag;		// kFalse => select first item in directory
	JPtrArray<JString>*	itsReselectNameList;	// non-empty => reselect after AdjustTableContents()
	JPoint				itsReselectScrollOffset;

	JXImage*	itsFileIcon;
	JXImage*	itsFolderIcon;
	JXImage*	itsExecIcon;
	JXImage*	itsUnknownIcon;

private:

	void	HandleDoubleClick(const JIndex index);

	void	AdjustTableContents();
	void	RememberSelections();
	void	CleanSelection();
	void	AdjustColWidths();

	// not allowed

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

public:

	// JBroadcaster messages

	static const JCharacter* kFileDblClicked;

	class FileDblClicked : public JBroadcaster::Message
		{
		public:

			FileDblClicked(const JUNIXDirEntry& entry, const JBoolean active)
				:
				JBroadcaster::Message(kFileDblClicked),
				itsDirEntry(entry),
				itsActiveFlag(active)
			{ };

			const JUNIXDirEntry&
			GetDirEntry() const
			{
				return itsDirEntry;
			};

			JBoolean
			IsActive() const
			{
				return itsActiveFlag;
			};

		private:

			const JUNIXDirEntry&	itsDirEntry;
			JBoolean				itsActiveFlag;
		};
};


/******************************************************************************
 AllowDblClickInactive

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

inline void
JXUNIXDirTable::AllowDblClickInactive
	(
	const JBoolean allow
	)
{
	itsAllowDblClickInactiveFlag = allow;
}

/******************************************************************************
 Select first item when path changes

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

inline JBoolean
JXUNIXDirTable::WillSelectWhenChangePath()
	const
{
	return itsSelectWhenChangePathFlag;
}

inline void
JXUNIXDirTable::ShouldSelectWhenChangePath
	(
	const JBoolean select
	)
{
	itsSelectWhenChangePathFlag = select;
}

/******************************************************************************
 ItemIsActive (protected)

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

inline JBoolean
JXUNIXDirTable::ItemIsActive
	(
	const JIndex index
	)
	const
{
	return itsActiveCells->GetElement(index);
}

/******************************************************************************
 ItemIsSelectable (protected)

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

inline JBoolean
JXUNIXDirTable::ItemIsSelectable
	(
	const JIndex	index,
	const JBoolean	forMulti
	)
	const
{
	return JI2B( ItemIsActive(index) && (!forMulti || ItemIsFile(index)) );
}

#endif
