// GridRow.h
// e.moon 5may99 (GridView layout manager)
//
// PURPOSE
//   Represents a single row in a grid-based layout
//   (contained cells are organized by row and column.)
//
//   As well as storing row positioning and other state
//   information, the GridRow is responsible for keeping
//   track of all cells (BViews) in its row.  The base
//   GridRow implementation handles this completely.
//
// HISTORY
//   e.moon 5may99: adapted from previous GridView.h
//   - replaced grip/cell-height with a simpler border size member
//     (the GridView is now responsible for drawing grips itself)
//   - hooks: +++++

#ifndef __GRIDROW_H__
#define __GRIDROW_H__

#include <vector>

#include <SupportDefs.h>

#include "cortex_defs.h"
__BEGIN_CORTEX_NAMESPACE

class GridView;

class GridRow {
	friend GridView;

public:				// ctor/dtor/accessors
	virtual ~GridRow();	
	GridRow(
		float		height=0.0,
		int32		flags=0,
		void*		pCookie=0);

	int32 flags() const { return m_flags; }
	void* cookie() const { return m_pCookie; }
	
	const float height() const { return m_height; }
	const float borderHeight() const { return m_borderHeight; }
	const float yOffset() const { return m_yOffset; }
	
public:				// hooks

private:				// members & icky internals
	int32				m_flags;
	void*				m_pCookie;
	
	// height, border size & y-offset maintained by the GridView
	float				m_height;
	float				m_borderHeight;
	float				m_yOffset;

	// cells in this row:
	// cells are stored in a vector, indexed by column.
	// columns for which no cell exists are marked by pCell == 0
	
	class CellEntry {
	public:
		CellEntry() : pCell(0), columnSpan(0), rowSpan(1) {}
		CellEntry(BView* p, uint32 _columnSpan, uint32 _rowSpan=1) :
			pCell(p), columnSpan(_columnSpan), rowSpan(_rowSpan) {}
/*
		CellEntry(const CellEntry& clone) {
			pCell = clone.pCell;
			columnSpan = clone.columnSpan; rowSpan = clone.rowSpan;
		}
		CellEntry& operator=(const CellEntry& clone) {
			pCell = clone.pCell;
			columnSpan = clone.columnSpan; rowSpan = clone.rowSpan;
			return *this;
		}
*/
	public:
		BView*	pCell;
		uint32	columnSpan;

		// added 4may99 e.moon:
		// - rowSpan: if 1 or greater, this entry represents the top-left
		//   'slot' occupied by the cell.  if 0, this entry is a placeholder
		//   for a multi-row cell (scan previous rows to find its origin)
		uint32	rowSpan;
	};
	
	typedef 							vector<CellEntry>
											cell_vector;
	
	cell_vector					m_cells;
	static const int32		s_defCellVectorSize = 8;

private:				// implementation

	float cellHeight() const { return m_height - m_borderHeight; }

	// cell operations
	BView* cellAt(uint32 column) const;
	
	bool canAddCell(
		BView* pCell,
		uint32 column,
		uint32 columnSpan) const;
	
	status_t addCell(BView* pCell,
		uint32 column,
		uint32 columnSpan,
		uint32 rowSpan); //nyi 4may99: added rowSpan (set to 0 for
										 //rows following the origin

	status_t removeCell(uint32 column, BView** poCell);
	
	// find a cell, if it overlaps the given column
	// returns true if found, false if no cell overlaps the given column
	bool hitTest(uint32 column, BView** poCell,
		uint32* poOriginColumn,
		uint32* poColumnSpan=0) const;

	// returns the number of rows spanned by the cell at the given column,
	// 0 if this slot is overlapped by a cell in a row above this one,
	// -1 if no cell overlaps the given column at this row	
	int32 rowSpan(uint32 column) const;
	
	// returns the number of columns spanned by the cell at the given
	// column (which must be the first column spanned by that cell), or
	// 0 if no cell has its origin in the given column
	uint32 columnSpan(uint32 column) const;
	
	// add empty column (does not move cell views)
	status_t insertColumn(uint32 column);

	// delete column (& cell view, if it exists)
	status_t deleteColumn(uint32 column);

	// delete all views
	void deleteViews();
};

__END_CORTEX_NAMESPACE
#endif /* __GRIDROW_H__ */
