//	Zinc Application Framework - Z_TABLE.HPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#if !defined(Z_TABLE_HPP)
#define Z_TABLE_HPP
#include <z_win.hpp>
#include <z_data.hpp>

// --------------------------------------------------------------------------
// ----- ZafTable -----------------------------------------------------------
// --------------------------------------------------------------------------

class ZAF_EXPORT ZafTable;

// ----- ZafTableHeader -----------------------------------------------------

enum ZafTableHeaderType
{
	ZAF_CORNER_HEADER,
	ZAF_COLUMN_HEADER,
	ZAF_ROW_HEADER
};

class ZAF_EXPORT ZafTableHeader : public ZafWindow
{
public:
	// --- General members ---
	ZafTableHeader(int width, int height,
		ZafTableHeaderType headerType = ZAF_ROW_HEADER);
	ZafTableHeader(const ZafTableHeader &copy);
	virtual ~ZafTableHeader(void);
	ZafTable *Table(void) const;

	// --- Persistent members ---
	virtual ZafWindowObject *Duplicate(void);
#if defined(USE_ZAF_PERSISTENCE)
	ZafTableHeader(const ZafIChar *name, ZafObjectPersistence &persist);
	static ZafElement *Read(const ZafIChar *name, ZafObjectPersistence &persist);
	virtual void Write(ZafObjectPersistence &persist);
#endif

	// --- Attributes & data access ---
	// get
	ZafTableHeaderType HeaderType(void) const;
	ZafWindowObject *VirtualField(void) const;
	// set
	virtual ZafTableHeaderType SetHeaderType(ZafTableHeaderType headerType);
	virtual ZafWindowObject *SetVirtualField(ZafWindowObject *virtualField);

	// --- Window members ---
	virtual ZafWindowObject *NotifySelection(ZafWindowObject *object, bool selected);
	virtual bool SetDestroyable(bool destroyable);
	virtual bool SetLocked(bool locked);
	virtual bool SetMaximized(bool maximized);
	virtual bool SetMinimized(bool minimized);
	virtual bool SetModal(bool modal);
	virtual bool SetMoveable(bool moveable);
	virtual bool SetNormalHotKeys(bool normalHotKeys);
	virtual ZafWindow *SetOwner(ZafWindow *owner);
	virtual bool SetSizeable(bool sizeable);
	virtual bool SetTemporary(bool temporary);

	// --- Window object members ---
	virtual void ConvertRegion(ZafRegionStruct &region, ZafCoordinateType newType);
	virtual ZafEventType Event(const ZafEventStruct &event);
	virtual bool SetAcceptDrop(bool acceptDrop);
	virtual bool SetBordered(bool bordered);
	virtual bool SetFocus(bool currentFocus);
	virtual const ZafIChar *SetHelpContext(const ZafIChar *helpContext);
	virtual bool SetNoncurrent(bool noncurrent);
	virtual ZafRegionType SetRegionType(ZafRegionType regionType);
	virtual bool SetSupportObject(bool supportObject);
	virtual ZafUserFunction SetUserFunction(ZafUserFunction userFunction);

	// --- Advanced event handling ---
#	if defined(ZAF_MACINTOSH)
	virtual ZafEventType DispatchMouseEvent(const ZafEventStruct &event);
#	elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	virtual ZafEventType DispatchMouseEvent(const ZafEventStruct &event);
	virtual ZafWindowObject *FindMouseObject(const ZafEventStruct &event);
#	endif

	// --- List members ---
	virtual ZafWindowObject *Add(ZafWindowObject *object, ZafWindowObject *position = ZAF_NULLP(ZafWindowObject));
	virtual ZafWindowObject *Subtract(ZafWindowObject *object);

	ZafTableHeader &operator+(ZafWindowObject *object) { Add(object); return(*this); }
	ZafTableHeader &operator-(ZafWindowObject *object) { Subtract(object); return(*this); }

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;

	// --- Special OS members ---
	virtual OSWindowID OSScreenID(ZafScreenIDType type = ZAF_SCREENID) const;

protected:
	friend class ZAF_EXPORT OSTableHeader;
	friend class ZAF_EXPORT ZafTable;

	// --- General members ---
	ZafTableHeaderType headerType;
	ZafWindowObject *virtualField;

	virtual ZafEventType Draw(const ZafEventStruct &event, ZafEventType ccode);
	virtual ZafEventType DrawBorder(ZafRegionStruct &region, ZafEventType ccode);
	virtual ZafEventType DrawFocus(ZafRegionStruct &region, ZafEventType ccode);
	virtual const ZafPaletteStruct *MapClassPalette(ZafPaletteType type, ZafPaletteState state);

	// --- Special OS members ---
	virtual void OSRegisterObject(void);

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members ---
	void ReadData(ZafObjectPersistence &persist);
	virtual ZafObjectConstructor ReadFunction(void) { return (ZafTableHeader::Read); }
	void WriteData(ZafObjectPersistence &persist);
#endif

private:
	static ZafPaletteMap ZAF_FARDATA defaultPaletteMap[];
};

// --- inline functions ---
inline ZafTableHeaderType ZafTableHeader::HeaderType(void) const { return headerType; }
inline ZafWindowObject *ZafTableHeader::VirtualField(void) const { return virtualField; }
inline ZafTable *ZafTableHeader::Table(void) const { return ((ZafTable *)parent); }

// ----- ZafTableRecord -----------------------------------------------------

class ZAF_EXPORT ZafTableRecord : public ZafWindow
{
public:
	// --- General members ---
	ZafTableRecord(int width, int height);
	ZafTableRecord(const ZafTableRecord &copy);
	virtual ~ZafTableRecord(void);
	virtual bool ActivateObject(ZafWindowObject *object);
	virtual bool DeactivateObject(ZafWindowObject *object);
	ZafTable *Table(void) const;

	// --- Persistent members ---
	virtual ZafWindowObject *Duplicate(void);
#if defined(USE_ZAF_PERSISTENCE)
	ZafTableRecord(const ZafIChar *name, ZafObjectPersistence &persist);
	static ZafElement *Read(const ZafIChar *name, ZafObjectPersistence &persist);
	virtual void Write(ZafObjectPersistence &persist);
#endif

	// --- Attributes & data access ---
	// get
	ZafOffset Offset(void) const;
	// set
	virtual ZafOffset SetOffset(ZafOffset offset);

	// --- Window members ---
	virtual bool SetDestroyable(bool destroyable);
	virtual bool SetLocked(bool locked);
	virtual bool SetMaximized(bool maximized);
	virtual bool SetMinimized(bool minimized);
	virtual bool SetModal(bool modal);
	virtual bool SetMoveable(bool moveable);
	virtual bool SetNormalHotKeys(bool normalHotKeys);
	virtual ZafWindow *SetOwner(ZafWindow *owner);
	virtual bool SetSizeable(bool sizeable);
	virtual bool SetTemporary(bool temporary);

	// --- Window object members ---
	virtual void ConvertRegion(ZafRegionStruct &region, ZafCoordinateType newType);
	virtual ZafEventType Event(const ZafEventStruct &event);
	ZafLogicalEvent LogicalEvent(const ZafEventStruct &event);
	virtual bool SetAcceptDrop(bool acceptDrop);
	virtual bool SetBordered(bool bordered);
	virtual bool SetDisabled(bool disabled);
	virtual bool SetFocus(bool currentFocus);
	virtual bool SetNoncurrent(bool noncurrent);
	virtual bool SetParentDrawFocus(bool parentDrawFocus);
	virtual ZafRegionType SetRegionType(ZafRegionType regionType);
	virtual bool SetSelected(bool selected);
	virtual bool SetSupportObject(bool supportObject);

	// --- Advanced event handling ---
#	if defined(ZAF_MACINTOSH)
	virtual ZafEventType DispatchMouseEvent(const ZafEventStruct &event);
#	elif defined(ZAF_INDEPENDENT) || defined(ZAF_CURSES)
	virtual ZafEventType DispatchMouseEvent(const ZafEventStruct &event);
	virtual ZafWindowObject *FindMouseObject(const ZafEventStruct &event);
#	endif

	// --- List & Element members ---
	virtual ZafWindowObject *Add(ZafWindowObject *object, ZafWindowObject *position = ZAF_NULLP(ZafWindowObject));
	ZafTableRecord *Next(void) const { return((ZafTableRecord *)next); }
	ZafTableRecord *Previous(void) const { return((ZafTableRecord *)previous); }
	virtual ZafWindowObject *Subtract(ZafWindowObject *object);

	ZafTableRecord &operator+(ZafWindowObject *object) { Add(object); return(*this); }
	ZafTableRecord &operator-(ZafWindowObject *object) { Subtract(object); return(*this); }

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;

	// --- Special OS members ---
	virtual OSWindowID OSScreenID(ZafScreenIDType type = ZAF_SCREENID) const;

protected:
	friend class ZAF_EXPORT OSTableRecord;
	friend class ZAF_EXPORT ZafTable;

	virtual ZafEventType Draw(const ZafEventStruct &event, ZafEventType ccode);
	virtual ZafEventType DrawFocus(ZafRegionStruct &region, ZafEventType ccode);
	virtual ZafEventType MoveEvent(const ZafEventStruct &event);
	virtual ZafWindowObject *NotifyFocus(ZafWindowObject *object, bool focus);

	// --- Special OS members ---
	virtual void OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state);
	virtual void OSRegisterObject(void);

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members ---
	virtual ZafObjectConstructor ReadFunction(void) { return (ZafTableRecord::Read); }
#endif

private:
	static ZafEventMap ZAF_FARDATA defaultEventMap[];

	ZafOffset offset;
};

// --- inline functions ---
inline ZafOffset ZafTableRecord::Offset(void) const { return (offset); }
inline ZafTable *ZafTableRecord::Table(void) const { return ((ZafTable *)parent); }

// ----- ZafTable -----------------------------------------------------------

class ZAF_EXPORT ZafTable : public ZafWindow 
{
public:
	typedef ZafError (*MemberTableFunction)(ZafTableRecord &record, ZafWindowObject *row);

	// --- General members ---
	ZafTable(int left, int top, int width, int height,
		int headerWidth, int headerHeight, int rowHeight = 1);
	ZafTable(const ZafTable &copy);
	virtual ~ZafTable(void);

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members ---
	ZafTable(const ZafIChar *name, ZafObjectPersistence &persist);
	virtual void Write(ZafObjectPersistence &persist);
	static ZafElement *Read(const ZafIChar *name, ZafObjectPersistence &persist);
#endif

	// --- Attributes & data access ---
	virtual ZafError DeleteRecord(ZafOffset deleteOffset);
	ZafError Flush(ZafOffset offset = -1);
	virtual ZafError InsertRecord(ZafOffset insertOffset);
	virtual ZafError ReadRecord(ZafTableRecord &record, ZafWindowObject *row);
	virtual ZafError ReadRecordData(ZafTableRecord &record, ZafWindowObject *row);
	ZafError Repopulate(ZafOffset offset = -1);
	virtual ZafError SeekNextRecord(void);
	virtual ZafError SeekPreviousRecord(void);
	virtual ZafError SeekRandomRecord(ZafOffset offset, ZafSeek location);
	MemberTableFunction SetReadFunction(MemberTableFunction readFunction);
	MemberTableFunction SetWriteFunction(MemberTableFunction writeFunction);
	virtual ZafOffset Tell(void);
	virtual ZafError WriteRecord(ZafTableRecord &record, ZafWindowObject *row);
	virtual ZafError WriteRecordData(ZafTableRecord &record, ZafWindowObject *row);

	// get
	ZafOffset BottomOffset(void) const;
	ZafOffset CurrentOffset(void) const;
	ZafOffset FocusOffset(void) const;
	bool Grid(void) const;
	ZafLogicalColor HeaderBackgroundColor(ZafLogicalColor *color = ZAF_NULLP(ZafLogicalColor), ZafLogicalColor *mono = ZAF_NULLP(ZafLogicalColor));
	int HeaderHeight(void) const;
	int HeaderWidth(void) const;
	ZafLogicalColor HeaderTextColor(ZafLogicalColor *color = ZAF_NULLP(ZafLogicalColor), ZafLogicalColor *mono = ZAF_NULLP(ZafLogicalColor));
	ZafOffset MaxOffset(void) const;
	ZafTableRecord *Record(ZafOffset offset);
	int RowHeight(void) const;
	ZafOffset TopOffset(void) const;
	ZafTableRecord *VirtualRecord(void) const;
	// set
	virtual ZafOffset SetBottomOffset(ZafOffset currentOffset);
	ZafError SetColumnText(int columnNumber, const ZafIChar *text);
	virtual ZafOffset SetCurrentOffset(ZafOffset currentOffset);
	virtual ZafOffset SetFocusOffset(ZafOffset focusOffset);
	virtual bool SetGrid(bool grid);
	virtual ZafLogicalColor SetHeaderBackgroundColor(ZafLogicalColor color, ZafLogicalColor mono = ZAF_MONO_NULL);
	virtual int SetHeaderHeight(int headerHeight);
	virtual int SetHeaderWidth(int headerWidth);
	virtual ZafLogicalColor SetHeaderTextColor(ZafLogicalColor color, ZafLogicalColor mono = ZAF_MONO_NULL);
	virtual ZafOffset SetMaxOffset(ZafOffset maxOffset);
	virtual int SetRowHeight(int rowHeight, ZafCoordinateType coordinateType = ZAF_CELL);
	virtual ZafOffset SetTopOffset(ZafOffset topOffset);
	virtual ZafTableRecord *SetVirtualRecord(ZafTableRecord *virtualRecord);

	// --- Window members ---
	virtual ZafWindowObject *NotifySelection(ZafWindowObject *object, bool selected);
	virtual bool SetDestroyable(bool destroyable);
	virtual bool SetLocked(bool locked);
	virtual bool SetMaximized(bool maximized);
	virtual bool SetMinimized(bool minimized);
	virtual bool SetModal(bool modal);
	virtual bool SetMoveable(bool moveable);
	virtual bool SetNormalHotKeys(bool normalHotKeys);
	virtual ZafWindow *SetOwner(ZafWindow *owner);
	virtual bool SetSizeable(bool sizeable);
	virtual bool SetTemporary(bool temporary);

	// --- Window object members ---
	virtual ZafEventType Event(const ZafEventStruct &event);
	ZafLogicalEvent LogicalEvent(const ZafEventStruct &event);
	virtual bool SetAcceptDrop(bool acceptDrop);
	virtual ZafCoordinateType SetCoordinateType(ZafCoordinateType coordinateType);

	// --- List members ---
	virtual ZafWindowObject *Add(ZafWindowObject *object, ZafWindowObject *position = ZAF_NULLP(ZafWindowObject));
	virtual ZafWindowObject *Add(ZafWindowObject *object, const ZafIChar *title, ZafWindowObject *position = ZAF_NULLP(ZafWindowObject));
	ZafTableRecord *Current(void) const { return((ZafTableRecord *)current); }
	ZafTableRecord *First(void) const { return((ZafTableRecord *)first); }
	ZafTableRecord *Get(int index) { return((ZafTableRecord *)ZafList::Get(index)); }
	ZafTableRecord *Last(void) const { return((ZafTableRecord *)last); }
	virtual ZafWindowObject *Subtract(ZafWindowObject *object);

	ZafTable &operator+(ZafWindowObject *object) { Add(object); return(*this); }
	ZafTable &operator-(ZafWindowObject *object) { Subtract(object); return(*this); }

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;

	// --- Special OS members ---
	virtual OSWindowID OSScreenID(ZafScreenIDType type = ZAF_SCREENID) const;
#if defined(ZAF_MOTIF)
	bool firstTimeDrawing;
	bool getChildPalette;
	bool sizing;
#endif

protected:
	friend class ZAF_EXPORT OSTable;

	// --- General members ---
	ZafTableRecord *virtualRecord;
	ZafOffset currentOffset, maxOffset;
	int focusSize;
	MemberTableFunction readFunction;
	MemberTableFunction writeFunction;

	ZafError DefaultReadFunction(ZafTableRecord &record, ZafWindowObject *row);
	ZafError DefaultWriteFunction(ZafTableRecord &record, ZafWindowObject *row);

	virtual ZafEventType Draw(const ZafEventStruct &event, ZafEventType ccode);
	virtual ZafEventType DrawFocus(ZafRegionStruct &region, ZafEventType ccode);
	virtual const ZafPaletteStruct *MapClassPalette(ZafPaletteType type, ZafPaletteState state);
	virtual ZafEventType MoveEvent(const ZafEventStruct &event);
	virtual ZafWindowObject *NotifyFocus(ZafWindowObject *object, bool focus);
	virtual ZafEventType ScrollEvent(const ZafEventStruct &event);
	ZafError SeekOptimized(ZafOffset offset);

	ZafTableHeader *ColumnTableHeader(void) const;
	ZafTableHeader *CornerTableHeader(void) const;
	ZafTableHeader *RowTableHeader(void) const;

	// --- Special OS members ---
	virtual void OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state);
	virtual void OSRegisterObject(void);

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistent members ---
	void ReadData(ZafObjectPersistence &persist);
	virtual ZafObjectConstructor ReadFunction(void) { return (ZafTable::Read); }
	void WriteData(ZafObjectPersistence &persist);
#endif

private:
	friend class ZAF_EXPORT ZafTableHeader;
	friend class ZAF_EXPORT ZafTableRecord;

	static ZafPaletteMap ZAF_FARDATA defaultPaletteMap[];
	static ZafEventMap ZAF_FARDATA defaultEventMap[];

	bool grid;
	int itemWidth, itemHeight;
	ZafOffset focusRecord;
	int focusField;
	void ComputeNextPosition(ZafTableRecord *object, ZafWindowObject *rowField, int &line);
	void ComputePreviousPosition(ZafTableRecord *object, ZafWindowObject *rowField, int &line);
	void ComputeRecordPositions(ZafOffset startOffset);
	void DrawGrid(const ZafRegionStruct &drawRegion, const ZafRegionStruct &clip);
};

// --- inline functions ---
inline ZafOffset ZafTable::BottomOffset(void) const { return Last() ? Last()->Offset() : -1; }
inline ZafOffset ZafTable::CurrentOffset(void) const { return currentOffset; }
inline ZafOffset ZafTable::FocusOffset(void) const { return focusRecord; }
inline bool ZafTable::Grid(void) const { return (grid); }
inline ZafOffset ZafTable::MaxOffset(void) const { return maxOffset; }
inline ZafOffset ZafTable::TopOffset(void) const { return First() ? First()->Offset() : -1; }
inline ZafTableRecord *ZafTable::VirtualRecord(void) const { return virtualRecord; }
inline ZafTable::MemberTableFunction ZafTable::SetReadFunction(MemberTableFunction newReadFunction) { readFunction = newReadFunction; return (readFunction); }
inline ZafTable::MemberTableFunction ZafTable::SetWriteFunction(MemberTableFunction newWriteFunction) { writeFunction = newWriteFunction; return (writeFunction); }

#if defined(ZAF_MOTIF)
const int ZAF_HEADER_OBJECT_SHIFT = 1;
#else
const int ZAF_HEADER_OBJECT_SHIFT = 0;
#endif

#endif // Z_TABLE_HPP

