Subversion Repositories travelsized

Rev

Rev 410 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This file is part of Travelsized CMS
 *              A content management system with modules, based on wiki syntax
 *
 * Author: Dan Jensen <admin@leinir.dk>
 * Copyright 2003/2004
 *
 * 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.
 *
 * The GNU General Public License is available at: http://www.gnu.org/copyleft/
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**
The table class contains and manages the model of a table, including CSS classes and cell spans

Sample code for the Table class:
\code
$testtable = new Table("table", "defaultrow", "defaultcell");
$testtable->addRow( null );
$testtable->addRow( "row2" );
$testtable->addRows( 5 );
$testtable->addColumn();
$testtable->addColumn( "column2" );
$testtable->addColumns( 5 );
$testtable->setContent( 0, 0, "0-0" );
$testtable->setContent( 0, 1, "0-1" );
$testtable->setContent( 0, 2, "0-2" );
$testtable->setContent( 0, 3, "0-3" );
$testtable->setContent( 0, 4, "0-4" );
$testtable->setContent( 0, 5, "0-5" );
$testtable->setRowContent( 1, true, "1-0", "1-1", "1-2", "1-3", "1-4", "1-5" );
$testtable->setRowContent( 2, true, "2-0", "2-1", "2-2", "2-3", "2-4", "2-5" );
$testtable->setRowContent( 3, true, "3-0", "3-1", "3-2", "3-3", "3-4", "3-5" );
$testtable->setRowContent( 4, true, "4-0", "4-1", "4-2", "4-3", "4-4", "4-5" );
$testtable->setRowContent( 5, true, "5-0", "5-1", "5-2", "5-3", "5-4", "5-5" );

$testtable->setSpan( 1, 1, null, 3 );
$testtable->setSpan( 2, 1, 2, null );
$testtable->setSpan( 3, 3, 2, 2 );

echo $testtable->render();


$testtable2 = new Table("table", "defaultrow", "defaultcell");
$testtable2->newRow();
$testtable2->newCell("0.0");
$testtable2->newCell("0.1");
$testtable2->newRow();
$testtable2->newCell("1.0");
$testtable2->newCell("1.1", 2);
echo $testtable2->render();
\endcode
*/

class Table
{
        var $cells;                        ///< @var Array containing the table's cells in the form [row][col] = array( content => "", styleClass => "", rowSpan => "", colSpan => "", $pageData = true, inSpan => false) If styleClass == null, columnClass is used
        var $rows;                         ///< @var Array containing the styles for the rows, and wether the row is a header row rows[] = array( styleClass => "", headerRow => false )
        var $columns;                      ///< @var Array cointaining the styles for each cell in the column. If != null, this overrides the table's default style
       
        var $tableClass;                   ///< @var What is this table's CSS class
        var $defaultRowClass;              ///< @var What is the default class for rows
        var $defaultCellClass;             ///< @var What is the default class cells will be given if they have no class, and the column they are in has no class assigned to them
       
        ///\private
        var $currentRow;                   ///< @var Points to the current row - used for sequential table construction
        var $currentCell;                  ///< @var Points to the current cell in the current row - used for sequential table construction
       
        /**
         * Construct a new table instance
         *
         * @param    tableClass    The table's CSS class
         * @param    defaultRowClass The default class of news rows
         * @param    defaultCellClass The fallback class for contained cells. This will be used if the cell has no class assigned, and it is contained in a column with no class assigned
         * @param    rows          How many rows are in this table. Most often this will be 0, to be added later using addRow and addRows
         * @param    columns       How many columns are in this table. Most often this will be 0, to be added later using addColumn and addColumns
         */

        function Table( $tableClass = "setup", $defaultRowClass = "setup", $defaultCellClass = "setup", $rows = 0, $columns = 0 )
        {
                $this->tableClass = $tableClass;
                $this->defaultRowClass = $defaultRowClass;
                $this->defaultCellClass = $defaultCellClass;
               
                $this->cells = array();
                $this->rows = array();
                $this->columns = array();
               
                if( $rows > 0 )
                        for( $i = 0; $i < $rows; $i++ )
                                $this->addRow();
               
                if( $columns > 0 )
                        for( $i = 0; $i < $columns; $i++ )
                                $this->addColumn();
        }
       
        /**
         * This will add a range of rows to the table, at an optional specified position
         *
         * @param    thisRowClass  A string describing which class to give the row
         * @param    headerRow     A boolean describing wether this is a header row
         * @param    where         An optional integer describing which row to add the row after. Defaults to the end
         */

        function addRow( $thisRowClass = null, $headerRow = false, $where = null )
        {
                if( $where == null )
                {
                        $where = count($this->rows);
                }
                else
                {
                        ///\todo Make this work!
                        // Move the existing rows and cells out of the way to make space for the new row
                        for( $i = count($this->rows) - 1; $i > $where; $i-- )
                        {
                                $this->rows[$i + 1] = $this->rows[$i];
                                $this->cells[$i + 1] = $this->cells[$i];
                        }
                }
                $this->rows[$where] = array( "styleClass" => $thisRowClass, "headerRow" => $headerRow );
        }
       
        /**
         * This will add a range of rows to the table, at an optional specified position
         *
         * @param    howMany       A string describing how many rows you wish to add to the table
         * @param    headerRow     A boolean describing wether these are header rows
         * @param    where         An optional integer describing which row to add the rows after. Defaults to the end
         * @param    theseRowClass A string describing which class to give the rows
         */

        function addRows( $howMany, $theseRowClass = null, $headerRow = false, $where = null )
        {
                if( $where == null )
                {
                        for( $i = 1; $i < $howMany; $i++ )
                                $this->addRow( $theseRowClass, $headerRow );
                }
                else
                {
                        $stopHere = $where + $howMany;
                        for( $i = $where; $i < $stopHere; $i++ )
                                $this->addRow( $theseRowClass, $headerRow, $i );
                }
        }
       
        /**
         * Set wether a row contains a line of headers
         *
         * @param    row           The row to set header status for
         * @param    headerRow     Boolean describing wether the row is a header row or not
         */

        function setRowHeader( $row, $headerRow = true )
        {
                $this->rows[$row]["headerRow"] = $headerRow;
        }
       
        /**
         * Add a new column to the table as an optional position and with an optional class
         *
         * @param    thisColumnClass The class to assign to this row
         * @param    where         An optional integer describing which column to add this column after. Defaults to the end
         */

        function addColumn( $thisColumnClass = null, $where = null )
        {
                if( $where == null )
                        $where = count($this->columns);
                else
                {
                        ///\todo Make this work!
                        for( $i = count($this->columns); $i > $where; $i-- )
                                $this->columns[$i + 1] = $this->columns[$i];
                       
                        // Remember to move all cells out of the way when $where != null!
                        foreach( $this->cells as $key => $value )
                        {
                                for( $i = count($this->columns); $i > $where; $i-- )
                                        $this->cells[$key][$i + 1] = $this->cells[$key][$i];
                        }
                }
                $this->columns[$where] = array( "styleClass" => $thisColumnClass );
        }
       
        /**
         * This will add a range of columns to the table, at an optional specified position
         *
         * @param    howMany       A string describing how many rows you wish to add to the table
         * @param    theseRowClass A string describing which class to give the rows
         * @param    where         An optional integer describing which row to add the rows after. Defaults to the end
         */

        function addColumns( $howMany, $theseColumnClass = null, $where = null )
        {
                if( $where == null )
                {
                        for( $i = 1; $i < $howMany; $i++ )
                                $this->addColumn( $theseColumnClass );
                }
                else
                {
                        $stopHere = $where + $howMany;
                        for( $i = $where; $i < $stopHere; $i++ )
                                $this->addColumn( $theseColumnClass, $i );
                }
        }
       
        /**
         * Set the contents of the specified cell with either rendered HTML or pagedata
         *
         * @param    row           The cell's identifying row
         * @param    column        The cell's identifying column
         * @param    content       The new content for this cell
         * @param    pageData      Are the contents to be interpreted as pagedata
         */

        function setContent( $row, $column, $content, $pageData = true )
        {
                $this->cells[$row][$column]["content"] = $content;
                $this->cells[$row][$column]["pageData"] = $pageData;
        }
       
        /**
         * Set the content of an entire row in one go
         *
         * @param    row           The row to set the content of
         * @param    pageData      Are the contents to be interpreted as pagedata
         * @param    contents      All remaining arguments are interpreted as content to set for the cells in the row
         */

        function setRowContent( $row, $pageData = true )
        {
                $contents = func_get_args();
                $contents = array_slice( $contents, 2 );
                foreach( $contents as $key => $value )
                        $this->setContent( $row, $key, $value, $pageData );
        }
       
        /**
         * Set the span of a single cell. If one or both of the spanranges is null, the cell is reset to not span
         *
         * @param    row           The cell's identifying row
         * @param    column        The cell's identifying column
         * @param    rowSpan       An integer defining how many rows to span. If null, the cell is reset to not span any rows
         * @param    colSpan       An integer defining how many columns to span. If null, the cell is reset to not span any columns
         */

        function setSpan( $row, $column, $rowSpan = null, $colSpan = null )
        {
                // First, reset the old span-range
                $oldRowSpan = $this->cells[$row][$column]["rowSpan"] + $row;
                $oldColSpan = $this->cells[$row][$column]["colSpan"] + $column;
                for( $theRow = $row; $theRow < $oldRowSpan; $theRow++ )
                        for( $theCol = $column; $theCol < $oldColSpan; $theCol++ )
                                $this->cells[$theRow][$theCol]["inSpan"] = false;
               
               
                // Mark cells as part of span
                $newRowSpan = $row + $rowSpan;
                $newColSpan = $column + $colSpan;
                if( $rowSpan == null )
                {
                        $theRow = $row;
                        for( $theCol = $column; $theCol < $newColSpan; $theCol++ )
                        {
                                $this->cells[$theRow][$theCol]["inSpan"] = true;
                                $this->cells[$theRow][$theCol]["rowSpan"] = null;
                                $this->cells[$theRow][$theCol]["colSpan"] = null;
                        }
                }
                else if( $colSpan == null )
                {
                        $theCol = $column;
                        for( $theRow = $row; $theRow < $newRowSpan; $theRow++ )
                        {
                                $this->cells[$theRow][$theCol]["inSpan"] = true;
                                $this->cells[$theRow][$theCol]["rowSpan"] = null;
                                $this->cells[$theRow][$theCol]["colSpan"] = null;
                        }
                }
                else
                {
                        for( $theRow = $row; $theRow < $newRowSpan; $theRow++ )
                        {
                                for( $theCol = $column; $theCol < $newColSpan; $theCol++ )
                                {
                                        $this->cells[$theRow][$theCol]["inSpan"] = true;
                                        $this->cells[$theRow][$theCol]["rowSpan"] = null;
                                        $this->cells[$theRow][$theCol]["colSpan"] = null;
                                }
                        }
                }
               
                // Then set the new span-range
                $this->cells[$row][$column]["inSpan"] = false;
                $this->cells[$row][$column]["rowSpan"] = $rowSpan;
                $this->cells[$row][$column]["colSpan"] = $colSpan;
        }
       
        /**
         * Set the row span of a single cell. If spanrange is null, the cell is reset to not span
         *
         * @param    row           The cell's identifying row
         * @param    column        The cell's identifying column
         * @param    spanrange     An integer defining how many rows to span. If null, the cell is reset to not span any rows
         */

        function setRowSpan( $row, $column, $spanrange = null )
        {
                $this->setSpan( $row, $column, $spanrange, $this->cells[$row][$column]["colSpan"] );
        }
       
        /**
         * Set the column span of a single cell. If spanrange is null, the cell is reset to not span
         *
         * @param    row           The cell's identifying row
         * @param    column        The cell's identifying column
         * @param    spanrange     An integer defining how many columns to span. If null, the cell is reset to not span any columns
         */

        function setColSpan( $row, $column, $spanrange = null )
        {
                $this->setSpan( $row, $column, $this->cells[$row][$column]["rowSpan"], $spanrange );
        }
       
        /**
         * Set the CSS style of a single cell. If className is null, the cell is reset to not have a style set (column class will then override)
         *
         * @param    row           The cell's identifying row
         * @param    column        The cell's identifying column
         * @param    className     A string defining which special class to assign this cell. If null, the cell is reset to fallback style
         */

        function setStyleClass( $row, $column, $className = null )
        {
                $this->cells[$row][$column]["styleClass"] = $className;
        }
       
        /**
         * Get the contents of a specified cell.
         *
         * @param    row           The cell's identifying row
         * @param    column        The cell's identifying column
         */

        function getContent( $row, $column )
        {
                return $this->cells[$row][$column]["content"];
        }
       
        /**
         * Sequentially create a new row at the end of the table and set the current column to none
         *
         * @param    thisRowClass  A string describing which class to give the row
         * @param    headerRow     A boolean describing wether this is a header row
         */

        function newRow( $thisRowClass = null, $headerRow = false )
        {
                $this->addRow( $thisRowClass, $headerRow );
                $this->currentRow = endKey($this->rows);
                $this->currentCell = -1;
        }
       
        /**
         * Sequentially add a new cell and set the contents of it, at the end of the current row
         *
         * @param    content       The contents for the new cell
         * @param    colSpan       Optional. If the cell is to span a number of cells, input it here
         */

        function newCell( $content, $colSpan = null, $styleClass = null )
        {
                $this->currentCell++;
                $nextCurrent = $this->currentCell;
               
                // Make sure the column(s) actually exists
                if( !array_key_exists( $this->currentCell, $this->columns ) && $colSpan == null )
                        $this->addColumn();
                else if( $colSpan != null )
                {
                        for( $i = 0 ; $i < $colSpan ; $i++ )
                                if( !array_key_exists( $this->currentCell + $i , $this->columns ) )
                                        $this->addColumn();
                        $nextCurrent = endkey($this->columns) + $i;
                        $this->setColSpan( $this->currentRow, $this->currentCell, $colSpan );
                }
               
                $this->setContent( $this->currentRow, $this->currentCell, $content );
                $this->setStyleClass( $this->currentRow, $this->currentCell, $styleClass );
               
                // Make sure the next current cell doesn't overwrite column spans...
                $this->currentCell = $nextCurrent;
        }
       
        /**
         * This function returns the rendered table
         *
         * @return   Renders the table and returns a string containing this
         */

        function render()
        {
                $renderedContent = "<table class=\"" . $this->tableClass . "\">";
                foreach( $this->rows as $rowID => $row )
                {
                        $styleClass = ( $this->rows[$rowID]["styleClass"] == null ) ? $this->defaultRowClass : $this->rows[$rowID]["styleClass"];
                        $renderedContent .= "\n <tr class=\"$styleClass\">";
                       
                        foreach( $this->columns as $columnID => $column )
                        {
                                // We have to make sure first that the cell actually exists
                                if( ! array_key_exists( $rowID, $this->cells ) )
                                {
                                        if( $this->columns[$columnID]["styleClass"] == null )
                                                $cellClass = $this->defaultCellClass;
                                        else
                                                $cellClass = $this->columns[$columnID]["styleClass"];
                                               
                                        $cellType = ( $row["headerRow"] ) ? "th" : "td";
                                        $rowSpan = ( $this->cells[$rowID][$columnID]["rowSpan"] > 0 ) ? " rowspan=\"" . $this->cells[$rowID][$columnID]["rowSpan"] . "\"" : "";
                                        $columnSpan = ( $this->cells[$rowID][$columnID]["colSpan"] > 0 ) ? " colspan=\"" . $this->cells[$rowID][$columnID]["colSpan"] . "\"" : "";
                                       
                                        $renderedContent .= "\n         <$cellType class=\"$cellClass\"></$cellType>";
                                }
                                // And in case it does exist, we don't render the cell if it's part of a span field
                                else if( ! $this->cells[$rowID][$columnID]["inSpan"] )
                                {
                                        if( $this->cells[$rowID][$columnID]["styleClass"] == null )
                                        {
                                                if( $this->columns[$columnID]["styleClass"] == null )
                                                        $cellClass = $this->defaultCellClass;
                                                else
                                                        $cellClass = $this->columns[$columnID]["styleClass"];
                                        }
                                        else
                                                $cellClass = $this->cells[$rowID][$columnID]["styleClass"];
                                       
                                        $cellType = ( $row["headerRow"] ) ? "th" : "td";
                                        $rowSpan = ( $this->cells[$rowID][$columnID]["rowSpan"] != 0 ) ? " rowspan=\"" . $this->cells[$rowID][$columnID]["rowSpan"] . "\"" : "";
                                        $columnSpan = ( $this->cells[$rowID][$columnID]["colSpan"] != 0 ) ? " colspan=\"" . $this->cells[$rowID][$columnID]["colSpan"] . "\"" : "";
                                        $cellContent = ( $this->cells[$rowID][$columnID]["pageData"] ) ? parse_page_data( $this->cells[$rowID][$columnID]["content"] ) : $this->cells[$rowID][$columnID]["content"];
                                       
                                        $renderedContent .= "\n         <" . $cellType .  $rowSpan . $columnSpan . " class=\"$cellClass\">" . $cellContent . "</$cellType>";
                                }
                        }
                       
                        $renderedContent .= "\n </tr>";
                }
                $renderedContent .= "</table>";
                return $renderedContent;
        }
}
?>