Location: PHPKode > projects > Aukyla Document Management System > base/Tables.php
<?php
/*
     Tables.php, provides functions for building tables
     Copyright (C) 2004 Arend van Beelen, Auton Rijnsburg

     This program is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the Free
     Software Foundation; either version 2 of the License, or (at your option)
     any later version.

     This program 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 General Public License for
     more details.

     You should have received a copy of the GNU General Public License along
     with this program; if not, write to the Free Software Foundation, Inc.,
     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

     For any questions, comments or whatever, you may mail me at: hide@address.com
*/

require_once('Widgets.php');

/**
 * @brief Class that provides functions for building and displaying tables.
 */
class Table extends Container
{
	/**
	 * Constructor. Creates an empty table.
	 *
	 * @param parent Parent widget to add the table to.
	 */
	public function __construct(Container $parent)
	{
		parent::__construct($parent);

		$this->width = 0;
		$this->header = false;
		$this->footer = false;
		$this->lastRow = false;
	}

	/**
	 * Sets whether rows should alternate. This provides a quick way to let
	 * rows alternate in color by setting the CSS class 'alternate' on every
	 * second row.
	 *
	 * @param rowsAlternate Set to @p true to indicate rows should alternate,
	 *                      @p false otherwise.
	 *
	 * @sa rowsAlternate()
	 */
	public function setRowsAlternate($rowsAlternate)
	{
		$this->rowsAlternate = $rowsAlternate;
	}

	/**
	 * Returns whether the rows in this table alternate.
	 *
	 * @return @p true if this table's rows alternate, @p false otherwise.
	 *
	 * @sa setRowsAlternate()
	 */
	public function rowsAlternate()
	{
		return $this->rowsAlternate;
	}

	/**
	 * Sets whether columns should alternate. This provides a quick way to
	 * let columns alternate in color by setting the CSS class 'alternate'
	 * on every second column.
	 *
	 * @param columnsAlternate Set to @p true to indicate columns should
	 *                         alternate, @p false otherwise.
	 *
	 * @sa columnsAlternate()
	 */
	public function setColumnsAlternate($columnsAlternate)
	{
		$this->columnsAlternate = $columnsAlternate;
	}

	/**
	 * Returns whether the columns in this table alternate.
	 *
	 * @return @p true if this table's columns alternate, @p false otherwise.
	 *
	 * @sa setColumnsAlternate()
	 */
	public function columnsAlternate()
	{
		return $this->columnsAlternate;
	}

	/**
	 * Adds a widget to the children list.
	 *
	 * Only TableRow can be added to a Table.
	 *
	 * @note You shouldn't have to call this function directly as the
	 * constructor of widgets will already call this function for you.
	 *
	 * @param widget The widget to add to the children list.
	 */
	public function addWidget(TableRow $widget)
	{
		parent::addWidget($widget);
		$this->lastRow = $widget;
	}

	/**
	 * Sets the width of the table in the number of columns. By default, the
	 * number of columns is determined by the row with the highest number of
	 * columns.
	 *
	 * @param width The number of columns the table should be wide.
	 */
	public function setWidth($width)
	{
		$this->width = $width;
	}

	/**
	 * Returns the number of columns of the table.
	 *
	 * @return The number of columns the table is wide.
	 */
	public function width()
	{
		return $this->width;
	}

	/**
	 * Returns the last row added to the table.
	 *
	 * @return The row last added to the table, or @p false if no rows have
	 *         been added yet.
	 */
	public function lastRow()
	{
		return $this->lastRow;
	}

	/**
	 * Returns a given TableCell from this table.
	 *
	 * @param row    The row number from to which the cell belongs, starting from
	 *               0.
	 * @param column The column number of the cell, starting from 0.
	 * @return A TableCell instance, or @p NULL if this cell does not exist.
	 */
	public function cell($row, $column)
	{
		return $this->children[$row]->cell($column);
	}

	/**
	 * Shows the table.
	 */
	public function show()
	{
		Output::write('<table'.$this->parentProperties().'>');

		foreach($this->children as $child)
		{
			if($child->width() > $this->width)
			{
				$this->width = $child->width();
			}
		}

		Output::write('<columns>');
		for($i = 0; $i < $this->width; $i++)
		{
			Output::write('<column/>');
		}
		Output::write('</columns>'.
		              '<rows>');
		$i = 0;
		foreach($this->children as $child)
		{
			if($this->rowsAlternate)
			{
				$alternate = (($i = ($i + 1) % 2) == 0);
			}
			else
			{
				$alternate = false;
			}

			$child->show($alternate, $this->columnsAlternate);
		}
		Output::write('</rows>'.
		              '</table>');
	}

	private $width;
	private $rowsAlternate;
	private $columnsAlternate;
	private $header;
	private $footer;
	private $lastRow;
}

/**
 * @brief A table row.
 */
class TableRow extends Container
{
	/**
	 * Constructor. Creates an empty table row.
	 *
	 * @param parent Table to add the row to.
	 */
	public function __construct(Table $parent)
	{
		$previousRow = $parent->lastRow();

		parent::__construct($parent);

		if($previousRow !== false)
		{
			$rowSpans = $previousRow->rowSpans();
			$this->width = sizeof($rowSpans);
			for($i = 0; $i < $this->width; $i++)
			{
				$rowSpans[$i]--;
				if($rowSpans[$i] == 0)
				{
					unset($rowSpans[$i]);
				}
			}
			$this->rowSpans = $rowSpans;
		}
		else
		{
			$this->width = 0;
			$this->rowSpans = array();
		}
	}

	public function addWidget(Widget $widget)
	{
		if(!is_a($widget, 'TableCell'))
		{
			die('Can only add TableCell to a TableRow.');
		}

		parent::addWidget($widget);
		$this->width += $widget->columnSpan();
		if($widget->rowSpan() > 1)
		{
			$this->rowSpans[] = $widget->rowSpan() - 1;
		}
	}

	/**
	 * Returns the number of columns of the row.
	 *
	 * @return The number of columns the row is wide.
	 */
	public function width()
	{
		return $this->width;
	}

	/**
	 * Returns a given TableCell from this row.
	 *
	 * @param n The cell number to return, starting from 0.
	 * @return A TableCell instance, or @p NULL if this cell does not exist.
	 */
	public function cell($n)
	{
		return $this->children[$n];
	}

	/**
	 * Shows the table row.
	 *
	 * @param alternate        Boolean determining whether this row is an
	 *                         alternate row.
	 * @param columnsAlternate Boolean determining whether the columns in this
	 *                         header should alternate.
	 */
	public function show($alternate = false, $columnsAlternate = false)
	{
		if($this->cssClass == '' && $alternate)
		{
			$this->setCssClass('alternate');
		}

		$this->showMissingColumns();

		Output::write('<row'.$this->parentProperties().'>');
		$i = 0;
		foreach($this->children as $child)
		{
			$alternate = ($columnsAlternate ? (($i = ($i + 1) % 2) == 0) : false);

			$child->show($alternate);
		}
		Output::write('</row>');
	}

	/**
	 * @internal
	 */
	public function adjustColumnSpan($adjustment)
	{
		$this->width += $adjustment;
	}

	/**
	 * Shows any missing columns in this row.
	 */
	protected function showMissingColumns()
	{
		if($this->width < $this->parent->width())
		{
			$missingColumns = $this->parent->width() - $this->width;
			while($missingColumns > 0)
			{
				new TableCell($this);
				$missingColumns--;
			}
		}
	}

	/**
	 * @internal
	 */
	private function rowSpans()
	{
		return $this->rowSpans;
	}

	protected $children;
	protected $cssClass;
	protected $parent;

	/**
	 * Number of cells this row contains.
	 */
	protected $width;
	private $rowSpans;
}

/**
 * @brief A table cell.
 */
class TableCell extends RawContainer
{
	/**
	 * Constructor. Creates a table cell.
	 *
	 * @param parent Table row to add the cell to.
	 * @param text   Optional text to show in the cell.
	 */
	public function __construct(TableRow $parent, $text = '')
	{
		$this->colspan = 1;
		$this->rowspan = 1;

		parent::__construct($parent, $text);
	}

	/**
	 * Sets the column span of the cell.
	 *
	 * @param columnSpan The number of columns the cell will span.
	 */
	public function setColumnSpan($columnSpan)
	{
		$this->parent->adjustColumnSpan($columnSpan - $this->colspan);

		$this->colspan = $columnSpan;
	}

	/**
	 * Returns the column span of the cell.
	 *
	 * @return The number of columns the cell will span.
	 */
	public function columnSpan()
	{
		return $this->colspan;
	}

	/**
	 * Sets the row span of the cell.
	 *
	 * @param rowSpan The number of rows the cell will span.
	 */
	public function setRowSpan($rowSpan)
	{
		$this->rowspan = $rowSpan;
	}

	/**
	 * Returns the row span of the cell.
	 *
	 * @return The number of rows the cell will span.
	 */
	public function rowSpan()
	{
		return $this->rowspan;
	}

	/**
	 * Shows the table cell.
	 */
	public function show($alternate = false)
	{
		if($this->cssClass == '' && $alternate)
		{
			$this->setCssClass('alternate');
		}

		$colspanProperty = ($this->colspan == '1' ? '' : " columnspan=\"{$this->colspan}\"");
		$rowspanProperty = ($this->rowspan == '1' ? '' : " rowspan=\"{$this->rowspan}\"");

		Output::write('<cell'.$this->parentProperties()."$colspanProperty$rowspanProperty>");
		parent::show();
		Output::write('</cell>');
	}

	protected $cssClass;
	protected $parent;

	private $colspan;
	private $rowspan;
}

/**
 * @brief A grid used to layout widgets.
 *
 * A grid layout provides an easy way to align widgets in a grid. A grid by
 * default is not visible itself, only the child widgets are visible.
 *
 * Grids work by setting up a maximum number of columns and adding all child
 * widgets in rows with this number of columns beneith each other. So if you
 * create a grid with a width of 3 columns and you add 9 widgets, the 1st, 4th
 * and 7th widgets will be aligned below each other. The same applies for the
 * 2nd, 5th and 8th widgets and for the 3rd, 6th and 9th widgets.
 *
 * The Table functions setRowsAlternate() and setColumnsAlternate() are
 * normally available for this class.
 */
class GridLayout extends Table
{
	/**
	 * Constructor. Creates an empty grid layout.
	 *
	 * @param parent  Parent widget to add the table to.
	 * @param columns The number of columns the layout should be wide.
	 */
	public function __construct(Container $parent, $columns)
	{
		parent::__construct($parent);

		$this->columns = $columns;
		$this->currentColumn = $columns;
		$this->columnWidths = array();
		$this->addCssStyle('border: 0px');
	}

	/**
	 * Applies widths to the grid's columns.
	 *
	 * Use this function to determine the width of the grid's columns.
	 *
	 * Example, if you have a grid layout with 3 columns, you can set widths like
	 * this:
	 *
	 * @code
	 * $gridLayout->setColumnWidths(array('45%', '10%', '45%'));
	 * @endcode
	 *
	 * @note Call this function before adding widgets to the grid.
	 *
	 * @param widths An array containing widths for the respective columns. Use
	 *               CSS units like percentages or pixels to set the widths.
	 */
	public function setColumnWidths($widths)
	{
		$this->columnWidths = $widths;
	}

	public function addWidget(Widget $widget)
	{
		if(is_a($widget, 'TableRow'))
		{
			parent::addWidget($widget);
		}
		else
		{
			if($this->currentColumn >= $this->columns)
			{
				$this->currentRow = new TableRow($this);
				$this->currentColumn = 0;
			}

			$cell = new TableCell($this->currentRow);
			$cell->addWidget($widget);
			if(isset($this->columnWidths[$this->currentColumn]))
			{
				$cell->addCssStyle("width: {$this->columnWidths[$this->currentColumn]}");
			}

			$this->currentColumn++;
		}
	}

	private $columns;
	private $currentColumn;
	private $currentRow;
	private $columnWidths;
}

?>
Return current item: Aukyla Document Management System