<?php
    //========================================================================================================================
    /**
     * DOMエレメント拡張コンポーネントクラス（tableタグ使用）
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    require_once(BASE_LIB.'/Components.php');
            
    class HtmlTableGrid extends Components{
        private $_datasource;
        private $_format;           //設定情報
        private $_headerSW;         //ヘッダ表示用非切替
        private $_tableAttr;        //tableタグ属性リスト
        private $_headCellAttr;     //theadタグ属性リスト
        private $_gridCellAttr;     //tbodyタグ属性リスト
        private $_config;           //各種設定
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * コンストラクタ/デストラクタ
         *
         * @param object    $elementID      エレメントID
         * @param array     $datasource     データ連想配列（フィールド名($format内の'dataIndex'で対応づける)
         * @param array     $format         表示フォーマット情報
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function __construct($elementID, $datasource, $format){
            parent::__construct($elementID, 'div');
            
            $this->_datasource  = $datasource;
            $this->_headerSW    = TRUE;
            $this->_format      = $format;
            
            //設定デフォルト値
            $this->_format['fixedColCount'] = 0;
            $this->_format['headHeight']    = 20;
            $this->_format['scrollBarSize'] = 16;

            $this->_config      = array(
                //スタイル
                'base'          => array(
                    'position'      => 'absolute',
                    'overflow'      => 'hidden',
                    'left'          => '0px',
                    'top'           => '0px',
                    'width'         => $format['width'].'px',
                    'height'        => $format['height'].'px',
                    'border-width'  => '1px',
                    'border-style'  => 'none none none solid',
                    'border-color'  => 'silver',
                    'background-color'   => 'gainsboro',
                ),
                'head'          => array(
                    'position'      => 'absolute',
                    'overflow'      => 'hidden',
                    'border-width'  => '1px',
                    'border-style'  => 'solid solid none none',
                    'border-color'  => 'silver',
                ),
                'grid'          => array(
                    'position'      => 'absolute',
                    'overflow'      => 'scroll',
                    'border-width'  => '1px',
                    'border-style'  => 'solid solid solid none',
                    'border-color'  => 'silver',
                ),
                'fixedHead'     => array(
                    'position'      => 'absolute',
                    'overflow'      => 'hidden',
                    'border-width'  => '1px',
                    'border-style'  => 'solid solid none none',
                    'border-color'  => 'silver',
                ),
                'fixedGrid'     => array(
                    'position'      => 'absolute',
                    'overflow'      => 'hidden',
                    'border-width'  => '1px',
                    'border-style'  => 'solid solid solid none',
                    'border-color'  => 'silver',
                ),
                'headerSpace'        => array(
                    'position'      => 'absolute',
                    'overflow'      => 'hidden',
                    'border'        => '1px solid silver',
                    'border-style'  => 'solid solid none none',
                ),
                'fixedSpace'        => array(
                    'position'      => 'absolute',
                    'overflow'      => 'hidden',
                    'border'        => '1px solid silver',
                    'border-style'  => 'none solid solid none',
                ),
            );
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * グリッド各部サイズ設定
         */
        //-------------------------------------------------------------------------------------------------------------------
        private function _adjustGridSize(){
            //幅デフォルト値算出（全カラム幅の合計）
            list($gridWidth, $fixedWidth)  = $this->_getWidths();
            
            //計算用
            $headHeight     = $this->_format['headHeight'];
            $scrollBarSize  = $this->_format['scrollBarSize'];

            //設定デフォルト値
            $this->config(array(
                //□■ヘッダdivタグ設定
                //□□
                'head'          => array(
                    'left'          => $fixedWidth.'px',
                    'top'           => '0px',
                    'width'         => ($this->_format['width'] - $fixedWidth - $scrollBarSize).'px',
                    'height'        => $headHeight.'px',
                ),
                //□□グリッドdivタグ設定
                //□■
                'grid'          => array(
                    'left'          => $fixedWidth.'px',
                    'top'           => $this->_format['headHeight'].'px',
                    'width'         => ($this->_format['width'] - $fixedWidth).'px',
                    'height'        => ($this->_format['height'] - $headHeight).'px',
                ),
                //■□固定列ヘッダdivタグ設定
                //□□
                'fixedHead'     => array(
                    'left'          => '0px',
                    'top'           => '0px',
                    'width'         => $fixedWidth.'px',
                    'height'        => $headHeight.'px',
                ),
                //□□固定列グリッドdivタグ設定
                //■□
                'fixedGrid'     => array(
                    'left'          => '0px',
                    'top'           => $this->_format['headHeight'].'px',
                    'width'         => $fixedWidth.'px',
                    'height'        => ($this->_format['height'] - $headHeight - $scrollBarSize).'px',
                ),
                //-----------------------------------------------------------------------------------------------------------
                //□■ヘッダ部スペーサー
                //□□
                'headerSpace'   => array(
                    'left'          => ($this->_format['width'] - $scrollBarSize).'px',
                    'top'           => '0px',
                    'width'         => ($scrollBarSize - 1).'px',
                    'height'        => $headHeight.'px',
                ),
                //□□固定列部スペーサー
                //■□
                'fixedSpace'   => array(
                    'left'          => '0px',
                    'top'           => ($this->_format['height'] - $scrollBarSize).'px',
                    'width'         => $fixedWidth.'px',
                    'height'        => ($scrollBarSize - 1).'px',
                ),
            ));

            return $gridWidth;
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * エレメント組込処理
         * @param object    $parent         親オブジェクト(Region)
         * @param string    $containerID    組込先エレメントID(NULLの場合はbodyタグ)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function mount($parent, $containerID){
            parent::mount($parent, $containerID);
            
            //同期設定
            $parent->getTopRegion()->addLoadJs('initGrid', quoted($this->_elementID));

            //グリッド各部サイズ設定
            $gridWidth  = $this->_adjustGridSize();

            //ベースdivタグ設定
            $this->style($this->_config['base']);
            
            //□■ヘッダdivタグ設定
            //□□
            $headDiv    = new HtmlElement($this->_elementID.'_HEAD', 'div');
            $headDiv->style($this->_config['head']);
            $parent->appendElement($headDiv, $this->_elementID);
            
            $headThead  = new Table($this->_elementID.'_HEAD_TABLE', NULL, $this->_format);
            $headThead->tableAttribute('width', $gridWidth);
            $headThead->tableAttribute('frame', 'void');
            $headThead->columnRange($this->_format['fixedColCount'], count($this->_format['columns']));
            $headThead->mountHeaderWithTableTag($parent, $this->_elementID.'_HEAD');
            
            //□□グリッドdivタグ設定
            //□■
            $gridDiv    = new HtmlElement($this->_elementID.'_GRID', 'div');
            $gridDiv->style($this->_config['grid']);
            $parent->appendElement($gridDiv, $this->_elementID);
            
            $gridTable  = new Table($this->_elementID.'_GRID_TABLE', $this->_datasource, $this->_format);
            $gridTable->headerOff();
            $gridTable->tableAttribute('width', $gridWidth);
            $gridTable->tableAttribute('frame', 'void');
            $gridTable->columnRange($this->_format['fixedColCount'], count($this->_format['columns']));
            $gridTable->append($parent, $this->_elementID.'_GRID');
            
            //□■ヘッダ部スペーサー
            //□□
            $headSpace  = new HtmlElement($this->_elementID.'_HEAD_SPACE', 'div');
            $headSpace->style($this->_config['headerSpace']);
            $parent->appendElement($headSpace, $this->_elementID);

            //■□固定列
            //■□
            if ($this->_format['fixedColCount'] > 0){
                //■□固定列ヘッダdivタグ設定
                //□□
                $fixedHeadDiv   = new HtmlElement($this->_elementID.'_FIXED_HEAD', 'div');
                $fixedHeadDiv->style($this->_config['fixedHead']);
                $parent->appendElement($fixedHeadDiv, $this->_elementID);
            
                $fixedHeadTable  = new Table($this->_elementID.'_FIXED_HEAD_TABLE', $this->_datasource, $this->_format);
                $fixedHeadTable->tableAttribute('frame', 'void');
                $fixedHeadTable->columnRange(0, $this->_format['fixedColCount'] - 1);
                $fixedHeadTable->mountHeaderWithTableTag($parent, $this->_elementID.'_FIXED_HEAD');
            
                //□□固定列グリッドdivタグ設定
                //■□
                $fixedColDiv    = new HtmlElement($this->_elementID.'_FIXED_COL', 'div');
                $fixedColDiv->style($this->_config['fixedGrid']);
                $parent->appendElement($fixedColDiv, $this->_elementID);
            
                $fixedColTable  = new Table($this->_elementID.'_FIXED_COL_TABLE', $this->_datasource, $this->_format);
                $fixedColTable->headerOff();
                $fixedColTable->tableAttribute('frame', 'void');
                $fixedColTable->columnRange(0, $this->_format['fixedColCount'] - 1);
                $fixedColTable->append($parent, $this->_elementID.'_FIXED_COL');

                //□□固定列部スペーサー
                //■□
                $headSpace  = new HtmlElement($this->_elementID.'_FIXED_SPACE', 'div');
                $headSpace->style($this->_config['fixedSpace']);
                $parent->appendElement($headSpace, $this->_elementID);
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 各種グリッド設定値セット
         * @param array     $config     設定（設定名=>各種設定値の連想配列 の連想配列)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function config($config){
            foreach ($config as $_key => $_conf){
                if (!array_key_exists($_key, $this->_config)){
                    $this->_config[$_key]   = array();
                }
                $this->_config[$_key]   = array_merge($this->_config[$_key], $_conf);
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * style設定メソッド
         * 基礎divタグのスタイルを変更する
         * @param array     $style      スタイル（スタイル名=>スタイル値の連想配列またはスタイル名文字列
         * @param string    $value      スタイル値（$attributeが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function style($style, $value = NULL){
            parent::style($style, $value);
            
            $conf   = (is_array($style) ? $style : array($style => $value));
            $this->config(array('base' => $conf));
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * ヘッダ高設定
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function headHeight($headHeight){
            $this->_format['headHeight']    = $headHeight;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 固定列数設定
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function fixedColCount($fixedColCount){
            $this->_format['fixedColCount'] = $fixedColCount;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 幅算出
         */
        //-------------------------------------------------------------------------------------------------------------------
        private function _getWidths(){
            $gridWidth = 0;
            $fixedWidth = 0;
            foreach($this->_format['columns'] as $_index => $_columns){
                if ($_index >= $this->_format['fixedColCount']){
                    $gridWidth  += $_columns['width'];
                }
                else{
                    $fixedWidth += $_columns['width'];
                }
            }
            return array($gridWidth, $fixedWidth);
        }
    }
    
?>
