<?php
    require_once(BASE_LIB.'/HtmlElement.php');
    require_once(BASE_LIB.'/Components.php');
    //========================================================================================================================
    /**
     * グリッドクラス(DOM不使用)
     *
     * 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/
     */
    //========================================================================================================================
    class HtmlGrid extends HtmlElement{
        private $_datasource;       //データソース(連想配列)
        private $_config;           //各種設定

        private $_style         = array();  //ベースdivタグスタイル
        private $_colStyle      = array();  //列データ部スタイル
        private $_headStyle     = array();  //列ヘッダ部スタイル
        
        private $_colAttr       = array();  //列データ部属性
        
        private $_gridObject    = NULL;     //グリッド構成オブジェクト
        private $_formElement   = array();  //グリッド内フォーム構成エレメントリスト
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * コンストラクタ/デストラクタ
         * @param object    $elementID      エレメントID
         * @param array     $datasource     データーソース：連想配列（フィールド名($columns内の'dataIndex'で対応づける)
         * @param array     $config         表示フォーマット情報
         *                                  width:          グリッド全体幅(scroll指定の場合は列幅合計となり使用しない)
         *                                  height:         グリッド全体高(scroll指定の場合は全レコード数×行高となり使用しない)
         *                                  columns:        列表示情報
         *                                      header:         ヘッダー文字列
         *                                      width:          列幅(ピクセル)
         *                                      dataIndex:      データソース対応インデックス得(連想配列のキー)
         *                                      colStyle:       列データ部スタイル(連想配列)
         *                                      headStyle:      列ヘッダ部スタイル(連想配列)
         *                                  [オプション設定値]
         *                                  showHeader:     ヘッダー表示有無切替(TRUE/FALSE)
         *                                  scroll:         スクロール表示切替(TRUE/FALSE)
         *                                  fixedColCount:  固定列数(スクロール表示の場合のみ有効)
         *                                  headHeight:     ヘッダー高
         *                                  cellHeight:     データ行高
         *                                  scrollBarSize:  スクロールバー幅
         *                                  zebraColors:    背景色リスト：複数色指定すると行毎に順番に背景色を切り替える
         *                                  fixedColors:    固定部背景色リスト：複数色指定すると行毎に順番に背景色を切り替える
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function __construct($elementID, $datasource, $config){
            parent::__construct($elementID, '');

            $this->_elementID   = $elementID;
            $this->_datasource  = $datasource;
            $this->_config      = $config;

            //---------------------------------------------------------------------------------------------------------------
            //各種設定デフォルト値
            $this->_config  = array(
                'showHeader'    => TRUE,
                'scroll'        => TRUE,
                'fixedColCount' => 0,
                'headHeight'    => 24,
                'cellHeight'    => 24,
                'scrollBarSize' => 15,
                'zebraColors'   => array('white', 'whitesmoke'),
                'fixedColors'   => array('white', 'whitesmoke'),
            );
            
            //各種設定値セット
            $this->_config  = array_merge($this->_config, $config);
        }

        //---------------------------------------------------------------------------------------------
        /**
         * 設定値(config)
         */
        //---------------------------------------------------------------------------------------------
        public function __call($name, $params){
            //設定値有無チェック
            if (!array_key_exists($name, $this->_config)){
                return parent::__call($name, $params);
            }
            
            //セッター
            if (count($params) > 0){
                $this->_config[$name]   = $params[0];
            }
            //ゲッター
            else{
                return $this->_config[$name];
            }
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * グリッド描画
         * ※draw()メソッドは置換キーワードを使用する場合は必須メソッド(Region->response()で使用)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function draw(){      
            //パラメータ整合性チェック
            if ((!$this->scroll()) && ($this->fixedColCount() > 0)){
                die(message('HtmlGrid', 'fixedColCount'));
            }
                    
            //各部基本ID設定
            $gridID             = $this->_elementID;
            $gridBaseID         = $gridID.'_GRID';
            $headID             = $gridID.'_HEAD';
            $headRowID          = $headID.'_ROW';
            $gridRowID          = $gridID.'_ROW';
            
            $fixedID            = $gridID.'_FIXED';
            $fixedGridBaseID    = $fixedID;
            $fixedHeadID        = $fixedID.'_HEAD';
            $fixedHeadRowID     = $fixedHeadID.'_ROW';
            $fixedGridRowID     = $fixedID.'_ROW';
            
            //ベースdivタグ
            $this->_gridObject  = new GridParts($gridID);
            $this->_gridObject->attribute('lb_type', 'HTML_GRID');
            $this->_gridObject->attribute('value', '__GRID_BASE_DIV');

            //----------------------------------------------------------------------------------------------------------
            //ヘッダー部
            if ($this->showHeader()){
                $headBase   = $this->_gridObject->addChild(new GridParts($headID));
                $headBase->attribute('class', $headID);

                $headRow    = $headBase->addChild(new gridParts($headRowID));
                $headRow->attribute('class', $headRowID);
            
                //ヘッダ列
                foreach ($this->columns() as $_colIndex => $_column){
                    //対象カラムチェック
                    if ($_colIndex < $this->fixedColCount()){
                        continue;
                    }
                    
                    //パーツ生成
                    $headRow->addChild(new GridParts($headID.'_'.$_column['dataIndex'], $_column['header']));
                }
                
                //スペーサー
                if ($this->scroll()){
                    $this->_gridObject->addChild(new GridParts($headID.'_SPACE'));
                }
            }
            
            //----------------------------------------------------------------------------------------------------------
            //グリッド部
            $gridBase       = new GridParts($gridBaseID);
            $this->_gridObject->addChild($gridBase);
            if (count($this->_datasource) > 0){
                $zebraColors    = $this->zebraColors();
                $colorCount     = count($zebraColors);
                
                //グリッド内INPUTエレメント準備
                foreach ($this->columns() as $_colIndex => $_column){
                    if (array_key_exists('xtype', $_column)){
                        //対象カラムチェック
                        if ($_colIndex >= $this->fixedColCount()){
                            $this->_formElement[$_column['dataIndex']]  = $this->_getFormTag($gridID, $_column);
                        }
                        else{
                            $this->_formElement[$_column['dataIndex']]  = $this->_getFormTag($fixedID, $_column);
                        }
                    }
                }

                //グリッドデータ部編集
                foreach ($this->_datasource as $_index => $_rec){
                    $gridRow    = $gridBase->addChild(new GridParts($gridRowID.'_'.$_index));
                    $gridRow->attribute('class', $gridRowID);
                    $gridRow->style('top', ($_index * $this->cellHeight()).'px');
                    if ($colorCount > 1){
                        $gridRow->style('background-color', $zebraColors[$_index % $colorCount]);
                    }
                
                    //グリッド列
                    foreach ($this->columns() as $_colIndex => $_column){
                        //対象カラムチェック
                        if ($_colIndex < $this->fixedColCount()){
                            continue;
                        }
                        
                        //パーツ生成
                        $gridColID  = $gridID.'_'.$_column['dataIndex'];
                        if (!array_key_exists($_column['dataIndex'], $this->_formElement)){
                            $gridCol    = $gridRow->addChild(new GridParts($gridColID.'_'.$_index, $_rec[$_column['dataIndex']]));
                        }
                        else{
                            $tagImage   = $this->_createParts($gridID, $_index, $_rec, $_column);
                            $gridCol    = $gridRow->addChild(new GridParts($gridColID.'_DIV'.$_index, $tagImage));
                        }
                        
                        //属性追加
                        $gridCol->attribute('class', $gridColID);
                        if (array_key_exists($_column['dataIndex'], $this->_colAttr)){
                             $gridCol->attribute($this->_colAttr[$_column['dataIndex']]);
                        }
                    }
                }
            }
            
            //----------------------------------------------------------------------------------------------------------
            //固定列部
            if ($this->fixedColCount() > 0){
                //------------------------------------------------------------------------------------------------------
                //ヘッダー部
                if ($this->showHeader()){
                    $fixedHeadBase  = $this->_gridObject->addChild(new GridParts($fixedHeadID));
                    $fixedHeadBase->attribute('class', $fixedHeadID);

                    $fixedHeadRow   = $fixedHeadBase->addChild(new gridParts($fixedHeadRowID));
                    $fixedHeadRow->attribute('class', $fixedHeadRowID);
        
                    //ヘッダ列
                    foreach ($this->columns() as $_colIndex => $_column){
                        //対象カラムチェック
                        if ($_colIndex >= $this->fixedColCount()){
                            continue;
                        }
                
                        //パーツ生成
                        $fixedHeadRow->addChild(new GridParts($fixedHeadID.'_'.$_column['dataIndex'], $_column['header']));
                    }
            
                    if ($this->scroll()){
                        $fixedHeadSpaceID    = $fixedHeadID.'_SPACE';
            
                    }
                }
            
                //------------------------------------------------------------------------------------------------------
                //グリッド部
                $fixedGridBase      = new GridParts($fixedGridBaseID);
                $this->_gridObject->addChild($fixedGridBase);
                if (count($this->_datasource) > 0){
                    $fixedColors        = $this->fixedColors();
                    $colorCount         = count($fixedColors);
                    foreach ($this->_datasource as $_index => $_rec){
                        $fixedGridRow    = $fixedGridBase->addChild(new GridParts($fixedGridRowID.'_'.$_index));
                        $fixedGridRow->attribute('class', $fixedGridRowID);
                        $fixedGridRow->style('top', ($_index * $this->cellHeight()).'px');
                        if ($colorCount > 1){
                            $fixedGridRow->style('background-color', $fixedColors[$_index % $colorCount]);
                        }
                
                        //グリッド列
                        foreach ($this->columns() as $_colIndex => $_column){
                            //対象カラムチェック
                            if ($_colIndex >= $this->fixedColCount()){
                                continue;
                            }
                        
                            //パーツ生成
                            $fixedGridColID  = $fixedID.'_'.$_column['dataIndex'];
                            if (!array_key_exists($_column['dataIndex'], $this->_formElement)){
                                $fixedGridCol    = $fixedGridRow->addChild(new GridParts($fixedGridColID.'_'.$_index, $_rec[$_column['dataIndex']]));
                            }
                            else{
                                $tagImage   = $this->_createParts($fixedID, $_index, $_rec, $_column);
                                $fixedGridCol    = $fixedGridRow->addChild(new GridParts($fixedGridColID.'_DIV'.$_index, $tagImage));
                            }
                            $fixedGridCol->attribute('class', $fixedGridColID);
                        }
                    }
                }
                    
                //------------------------------------------------------------------------------------------------------
                //スペーサー
                if ($this->scroll()){
                    $this->_gridObject->addChild(new GridParts($fixedID.'_SPACE'));
                }
            }
            
            //描画処理
            $this->_gridObject->build($gridText);
            return implode("\n", $gridText);
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * タグ種類別編集処理
         * @param array     $column     テーブルフォーマット情報の連想配列
         * @return object   タグ文字列
         */
        //-------------------------------------------------------------------------------------------------------------------
        private function _getFormTag($gridID, $column){
            $gridColID  = $gridID.'_'.$column['dataIndex'];
            $region     = new Region();

            switch ($column['xtype']){
                case 'input':
                    $element    = new HtmlElement('(#@ELEMENT_ID#)', $column['xtype']);
                    $element->attribute('type', $column['xconfig']['type']);
                    switch ($column['xconfig']['type']){
                        case 'text':
                            $element->attribute('value', '(#@VALUE#)');
                            break;
                            
                        case 'button':
                            $element->attribute('value', '(#@VALUE#)');
                            break;
                            
                        case 'checkbox':
                            $element->attribute('checked', '(#@DUMMY#)');
                            break;
                            
                        default:
                            break;
                    }
                    break;
                    
                //リンク：データソース[dataIndex]の値を表示し、データソース[xconfig[dataIndex]]の値をリンク先(href)に設定
                case 'a':
                    $element    = new HtmlElement('(#@ELEMENT_ID#)', $column['xtype']);
                    $element->attribute('TEXT_NODE', '(#@VALUE#)');
                    $element->attribute('href', '(#@X_VALUE#)');
                    break;
                    
                //コンボボックス
                case 'combobox':
                    require_once(BASE_LIB.'/Components.php');
                    $element   = new Combobox('(#@ELEMENT_ID#)', $column['xconfig']['options'], '##DUMMY_ALL##');
                    $element->append($region);
                    break;                    
                    
                default:
                    $element    = new HtmlElement('(#@ELEMENT_ID#)', $column['xtype']);
                    $element->attribute('value', '(#@VALUE#)');
                    break;
            }

            //tag文字列作成
            $element->attribute('class', $gridColID.'_CONTENT');
            $region->appendElement($element);
            return trim($region->build()->saveHTML());
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * タグ種類別キーワード置換処理
         * @param array     $column     テーブルフォーマット情報の連想配列
         * @return object   タグ文字列
         */
        //-------------------------------------------------------------------------------------------------------------------
        private function _createParts($gridID, $_index, $_rec, $_column){
            //パーツ生成
            $gridColID  = $gridID.'_'.$_column['dataIndex'];

            $tagImage   = $this->_formElement[$_column['dataIndex']];
            $tagImage   = str_replace('(#@ELEMENT_ID#)', $gridColID.'_'.$_index, $tagImage);
            $tagImage   = str_replace('(#@VALUE#)', $_rec[$_column['dataIndex']], $tagImage);
            if (array_key_exists('dataIndex', $_column['xconfig'])){
                $tagImage   = str_replace('(#@X_VALUE#)', $_rec[$_column['xconfig']['dataIndex']], $tagImage);
            }
            //チェックボックス
            if (array_key_exists('value', $_column['xconfig'])){
                $tagImage   = str_replace('checked', ($_rec[$_column['dataIndex']] === $_column['xconfig']['value'] ? 'checked' : ''), $tagImage);
            }
            //コンボボックス
            if (array_key_exists('options', $_column['xconfig'])){
                foreach ($_column['xconfig']['options'] as $_optionValue => $_optionText){
                    if ($_rec[$_column['dataIndex']] !== $_optionValue){
                        $valueAttr  = 'value="'.$_optionValue.'"';
                        $tagImage   = str_replace($valueAttr.' selected', $valueAttr, $tagImage);
                    }
                }
            }

            return  $tagImage;
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * スタイルDOM組込
         * @param object    $parent         組込み先リージョンオブジェクト
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function addStyleCss($parent){
            //共通サイズ準備
            list($fixedWidth, $gridWidth)   = $this->_getWidths();
            $headHeight     = ($this->showHeader() ? $this->headHeight() : 0);
            $gridHeight     = $this->cellHeight() * count($this->_datasource);
        
            //各部基本ID設定
            $gridID             = $this->_elementID;
            $gridBaseID         = $gridID.'_GRID';
            $headID             = $gridID.'_HEAD';
            $headRowID          = $headID.'_ROW';
            $gridRowID          = $gridID.'_ROW';
            
            $fixedID            = $gridID.'_FIXED';
            $fixedGridBaseID    = $fixedID;
            $fixedHeadID        = $fixedID.'_HEAD';
            $fixedHeadRowID     = $fixedHeadID.'_ROW';
            $fixedGridRowID     = $fixedID.'_ROW';

            $wPadding   = 2;
            
            //----------------------------------------------------------------------------------------------------------
            //ヘッダー部
            if ($this->showHeader()){
                $headCol    = array();
                $widthTotal = 0;
                foreach ($this->columns() as $_colIndex => $_column){
                    //対象カラムチェック
                    if ($_colIndex < $this->fixedColCount()){
                        continue;
                    }
                
                    //ヘッダ
                    $headColID  = $headID.'_'.$_column['dataIndex'];
                    $headCol[$headColID]  = array(
                        'position'      => 'absolute',
                        'left'          => $widthTotal.'px',
                        'top'           => '0px',
                        'width'         => ($_column['width'] - ($wPadding * 2)).'px',
                        'height'        => $this->headHeight().'px',
                        'line-height'   => $this->headHeight().'px',
                        'border'        => '1px solid silver',
                        'border-style'  => 'none solid solid none',
                        'text-align'    => 'center',
                        'padding-left'  => $wPadding.'px',
                        'padding-right' => $wPadding.'px',
                    );

                    $wHeadStyle  = array();
                    if (array_key_exists('headStyle', $_column)){
                        $wHeadStyle  = $_column['headStyle'];
                    }
                    
                    if (array_key_exists($_column['dataIndex'], $this->_headStyle)){
                        $wHeadStyle  = array_merge($wHeadStyle, $this->_headStyle[$_column['dataIndex']]);
                    }
                                    
                    $headCol[$headColID]    = array_merge($headCol[$headColID], $wHeadStyle);

                
                    $widthTotal += $_column['width'];
                }                
            
                //ヘッダー部行スタイル
                $headRow    = array(
                    'position'          => 'absolute',
                    'left'              => '0px',
                    'top'               => '0px',
                    'width'             => $gridWidth.'px',
                    'height'            => $this->headHeight().'px',
                );

                //ヘッダー部ベーススタイル
                $headBase    = array(
                    'position'          => 'absolute',
                    'left'              => $fixedWidth.'px',
                    'top'               => '0px',
                    'width'             => ($this->scroll() ? ($this->width() - $fixedWidth - $this->scrollBarSize()) : $gridWidth).'px',
                    'height'            => $this->headHeight().'px',
                    'overflow'          => ($this->scroll() ? 'hidden' : 'visible'),
                    'background-color'  => 'gainsboro',
                );
                
                //スペーサー
                if ($this->scroll()){
                    $wAdjust    = 0;
                    $headSpace    = array(
                        'position'      => 'absolute',
                        'left'          => ($this->width() - $this->scrollBarSize() - $wAdjust).'px',
                        'top'           => '0px',
                        'width'         => ($this->scrollBarSize() + $wAdjust).'px',
                        'height'        => $this->headHeight().'px',
                        'border'        => '1px solid silver',
                        'border-style'  => 'none none none solid',
                        'background-color'  => 'gainsboro',
                    );
                }
            }
            
            //----------------------------------------------------------------------------------------------------------
            //グリッド部
            $gridCol    = array();
            $widthTotal = 0;
            foreach ($this->columns() as $_colIndex => $_column){
                //対象カラムチェック
                if ($_colIndex < $this->fixedColCount()){
                    continue;
                }
            
                //グリッド
                $gridColID  = $gridID.'_'.$_column['dataIndex'];
                $gridCol[$gridColID]  = array(
                    'position'      => 'absolute',
                    'left'          => $widthTotal.'px',
                    'top'           => '0px',
                    'width'         => ($_column['width'] - ($wPadding * 2)).'px',
                    'height'        => $this->cellHeight().'px',
                    'line-height'   => $this->cellHeight().'px',
                    'border'        => '1px solid silver',
                    'border-style'  => 'solid solid none none',
                    'padding-left'  => $wPadding.'px',
                    'padding-right' => $wPadding.'px',
                );
                
                //タイプ別サイズ調整
                $margin   = 1;
                $wWidth   = $_column['width'];
                $wHeight  = $this->cellHeight();
                $wLHeight = $this->cellHeight();
                    
                $wContentStyle  = array(
                    'position'      => 'absolute',
                    'left'          => $margin.'px',
                    'top'           => $margin.'px',
                    'width'         => $wWidth.'px',
                    'height'        => $wHeight.'px',
                    'line-height'   => $wLHeight.'px',
                    'padding-left'  => $wPadding.'px',
                    'padding-right' => $wPadding.'px',
                );
                
                if (array_key_exists('xtype', $_column)){
                    switch($_column['xtype']){
                        case 'input':
                            switch($_column['xconfig']['type']){
                                case 'text':
                                    $wContentStyle['left'] = '2px';
                                    $wContentStyle['top'] = '1px';
                                    $wContentStyle['width'] = ($wWidth - ($margin * 2) - 10).'px';
                                    $wContentStyle['height'] = ($wHeight - ($margin * 2) - 4).'px';
                                    $wContentStyle['line-height'] = ($wHeight - ($margin * 2) - 4).'px';
                                    break;
                                case 'checkbox':
                                    unset($wContentStyle['width']);
                                    unset($wContentStyle['height']);
                                    unset($wContentStyle['line-height']);
                                    break;
                                case 'button':
                                    $wContentStyle['width'] = ($wWidth - ($margin * 2)).'px';
                                    $wContentStyle['height'] = ($wHeight - ($margin * 2)).'px';
                                    unset($wContentStyle['line-height']);
                                    break;
                            }
                            break;
                   }
                }

                $gridColContent[$gridColID.'_CONTENT']  = $wContentStyle;
                
                $wColStyle  = array();
                if (array_key_exists('colStyle', $_column)){
                    $wColStyle  = $_column['colStyle'];
                }
                
                if (array_key_exists($_column['dataIndex'], $this->_colStyle)){
                    $wColStyle  = array_merge($wColStyle, $this->_colStyle[$_column['dataIndex']]);
                }
                
                $gridCol[$gridColID]                    = array_merge($gridCol[$gridColID], $wColStyle);
                $gridColContent[$gridColID.'_CONTENT']  = array_merge($gridColContent[$gridColID.'_CONTENT'], $wColStyle);
                
                $widthTotal += $_column['width'];
            }

            //グリッド部行スタイル
            $gridRow    = array(
                'position'          => 'absolute',
                'left'              => '0px',
                'width'             => $gridWidth.'px',
                'height'            => $this->cellHeight().'px',
                'border'            => '1px solid silver',
                'border-style'      => 'none none solid none',
            );

            //グリッド部ベーススタイル
            $gridBase    = array(
                'position'          => 'absolute',
                'left'              => $fixedWidth.'px',
                'top'               => $headHeight.'px',
                'width'             => ($this->scroll() ? ($this->width() - $fixedWidth + 4) : $gridWidth).'px',
                'height'            => ($this->scroll() ? $this->height() - $this->headHeight() : $gridHeight).'px',
                'overflow'          => ($this->scroll() ? 'scroll' : 'visible'),
            );
            
            //----------------------------------------------------------------------------------------------------------
            //固定列部
            if (($this->scroll()) && ($this->fixedColCount() > 0)){
                //------------------------------------------------------------------------------------------------------
                //固定列ヘッダー部
                if ($this->showHeader()){
                    $fixedHeadCol    = array();
                    $widthTotal = 0;
                    foreach ($this->columns() as $_colIndex => $_column){
                        //対象カラムチェック
                        if ($_colIndex >= $this->fixedColCount()){
                            continue;
                        }
                
                        //ヘッダ
                        $fixedHeadColID  = $fixedHeadID.'_'.$_column['dataIndex'];
                        $fixedHeadCol[$fixedHeadColID]  = array(
                            'position'      => 'absolute',
                            'left'          => $widthTotal.'px',
                            'top'           => '0px',
                            'width'         => ($_column['width'] - ($wPadding * 2)).'px',
                            'height'        => $this->cellHeight().'px',
                            'line-height'   => $this->cellHeight().'px',
                            'border'        => '1px solid silver',
                            'border-style'  => 'none solid solid none',
                            'text-align'    => 'center',
                            'padding-left'  => $wPadding.'px',
                            'padding-right' => $wPadding.'px',
                        );

                        $wFixedHeadStyle  = array();
                        if (array_key_exists('headStyle', $_column)){
                            $wFixedHeadStyle  = $_column['headStyle'];
                        }
                    
                        if (array_key_exists($_column['dataIndex'], $this->_headStyle)){
                            $wFixedHeadStyle  = array_merge($wFixedHeadStyle, $this->_headStyle[$_column['dataIndex']]);
                        }

                        $fixedHeadCol[$fixedHeadColID]  = array_merge($fixedHeadCol[$fixedHeadColID], $wFixedHeadStyle);

                        $widthTotal += $_column['width'];
                    }
                

                    //ヘッダー部行スタイル
                    $fixedHeadRow    = array(
                        'position'          => 'absolute',
                        'left'              => '0px',
                        'top'               => '0px',
                        'width'             => $gridWidth.'px',
                        'height'            => $this->headHeight().'px',
                    );

                    //ヘッダー部ベーススタイル
                    $fixedHeadBase    = array(
                        'position'          => 'absolute',
                        'left'              => '0px',
                        'top'               => '0px',
                        'width'             => $fixedWidth.'px',
                        'height'            => $this->headHeight().'px',
                        'border'            => '1px solid silver',
                        'border-style'      => 'none solid none none',
                        'overflow'          => 'hidden',
                        'background-color'  => 'gainsboro',
                    );
                }

                //------------------------------------------------------------------------------------------------------
                //固定列グリッド部
                $fixedGridCol    = array();
                $widthTotal = 0;
                foreach ($this->columns() as $_colIndex => $_column){
                    //対象カラムチェック
                    if ($_colIndex >= $this->fixedColCount()){
                        continue;
                    }
            
                    //グリッド
                    $fixedGridColID = $fixedID.'_'.$_column['dataIndex'];
                    $fixedGridCol[$fixedGridColID]  = array(
                        'position'      => 'absolute',
                        'left'          => $widthTotal.'px',
                        'top'           => '0px',
                        'width'         => ($_column['width'] - ($wPadding * 2)).'px',
                        'height'        => $this->cellHeight().'px',
                        'line-height'   => $this->cellHeight().'px',
                        'border'        => '1px solid silver',
                        'border-style'  => 'solid solid none none',
                        'padding-left'  => $wPadding.'px',
                        'padding-right' => $wPadding.'px',
                    );
                
                    $margin     = 1;
                    $fixedGridColContent[$fixedGridColID.'_CONTENT']  = array(
                        'position'      => 'absolute',
                        'left'          => $margin.'px',
                        'top'           => $margin.'px',
                        'width'         => ($_column['width'] - ($margin * 2)).'px',
                        'height'        => ($this->cellHeight() - ($margin * 2)).'px',
                        'line-height'   => ($this->cellHeight() - ($margin * 2)).'px',
                        'padding-left'  => $wPadding.'px',
                        'padding-right' => $wPadding.'px',
                    );
                    
                    $wFixedColStyle  = array();
                    if (array_key_exists('colStyle', $_column)){
                        $wFixedColStyle  = $_column['colStyle'];
                    }
                    
                    if (array_key_exists($_column['dataIndex'], $this->_colStyle)){
                        $wFixedColStyle  = array_merge($wFixedColStyle, $this->_colStyle[$_column['dataIndex']]);
                    }

                    $fixedGridCol[$fixedGridColID]                    = array_merge($fixedGridCol[$fixedGridColID], $wFixedColStyle);
                    $fixedGridColContent[$fixedGridColID.'_CONTENT']  = array_merge($fixedGridColContent[$fixedGridColID.'_CONTENT'], $wFixedColStyle);

                    $widthTotal += $_column['width'];
                }

                //グリッド部行スタイル
                $fixedGridRow    = array(
                    'position'          => 'absolute',
                    'left'              => '0px',
                    'width'             => $fixedWidth.'px',
                    'height'            => $this->cellHeight().'px',
                    'border'            => '1px solid silver',
                    'border-style'      => 'none none solid none',
                );

                //グリッド部ベーススタイル
                $fixedGridBase    = array(
                    'position'          => 'absolute',
                    'left'              => '0px',
                    'top'               => $headHeight.'px',
                    'width'             => ($fixedWidth - 0).'px',
                    'height'            => ($this->height() - $this->headHeight() - $this->scrollBarSize()).'px',
                    'border'            => '1px solid silver',
                    'border-style'      => 'none solid none none',
                    'overflow'          => 'hidden',
                );
 
                //スペーサー
                $fixedSpace    = array(
                    'position'      => 'absolute',
                    'left'          => '0px',
                    'top'           => ($this->height() - $this->scrollBarSize()).'px',
                    'width'         => $fixedWidth.'px',
                    'height'        => $this->scrollBarSize().'px',
                    'border'        => '1px solid silver',
                    'border-style'  => 'none solid none none',
                    'background-color'  => 'gainsboro',
                );
            }

            //----------------------------------------------------------------------------------------------------------
            //ベースdivタグ
            $base   = array(
                'position'          => 'relative',
                'top'               => '0px',
                'left'              => '0px',
                'width'             => ($this->scroll() ? $this->width() : $gridWidth).'px',
                'height'            => ($this->scroll() ? $this->height() : ($headHeight + $gridHeight)).'px',
                'border'            => '1px solid silver',
                'border-style'      => 'solid solid solid solid',
                'overflow'          => ($this->scroll() ? 'hidden' : 'visible'),
            );
            $base   = array_merge($base, $this->_style);

            //----------------------------------------------------------------------------------------------------------
            //CSS定義
            $parent->addStyleCss('#'.$this->_elementID, $base);
            
            $parent->addStyleCss('#'.$headID, $headBase);
            foreach ($headCol as $_colName => $_style){
                $parent->addStyleCss('#'.$_colName, $_style);
            }

            if ($this->scroll()){
                $parent->addStyleCss('#'.$headID.'_SPACE', $headSpace);
            }
            
            $parent->addStyleCss('#'.$gridBaseID, $gridBase);
            $parent->addStyleCss('.'.$gridRowID, $gridRow);
            foreach ($gridCol as $_colName => $_style){
                $parent->addStyleCss('.'.$_colName, $_style);
            }
            foreach ($gridColContent as $_colName => $_style){
                $parent->addStyleCss('.'.$_colName, $_style);
            }

            if (($this->scroll()) && ($this->fixedColCount() > 0)){
                $parent->addStyleCss('#'.$fixedHeadID, $fixedHeadBase);
                foreach ($fixedHeadCol as $_colName => $_style){
                    $parent->addStyleCss('#'.$_colName, $_style);
                }

                $parent->addStyleCss('#'.$fixedGridBaseID, $fixedGridBase);
                $parent->addStyleCss('.'.$fixedGridRowID, $fixedGridRow);
                foreach ($fixedGridCol as $_colName => $_style){
                    $parent->addStyleCss('.'.$_colName, $_style);
                }
                foreach ($fixedGridColContent as $_colName => $_style){
                    $parent->addStyleCss('.'.$_colName, $_style);
                }
                $parent->addStyleCss('#'.$fixedID.'_SPACE', $fixedSpace);
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * スタイル設定
         * 基礎divタグのスタイルを変更する
         * @param array     $style      スタイル（スタイル名=>スタイル値の連想配列またはスタイル名文字列
         * @param string    $value      スタイル値（$attributeが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function style($name, $value = NULL){
            $style          = (is_array($name) ? $name : array($name => $value));
            $this->_style   = array_merge($this->_style, $style);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 列データ部スタイル設定
         * @param string    $colID      スタイル指定先列ID
         * @param array     $style      スタイル（スタイル名=>スタイル値の連想配列またはスタイル名文字列
         * @param string    $value      スタイル値（$styleが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function colStyle($colID, $style, $value = NULL){
            $styleList  = (is_array($style) ? $style : array($style => $value));
            $this->_colStyle[$colID]    = array_merge($this->_colStyle, $styleList);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 列ヘッダ部スタイル設定
         * @param string    $colID      スタイル指定先列ID
         * @param array     $style      スタイル（スタイル名=>スタイル値の連想配列またはスタイル名文字列
         * @param string    $value      スタイル値（$styleが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function headStyle($colID, $style, $value = NULL){
            $styleList  = (is_array($style) ? $style : array($style => $value));
            $this->_headStyle[$colID]   = array_merge($this->_headStyle, $styleList);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 列データ部属性設定
         * @param string    $colID      属性指定先列ID
         * @param array     $attr       属性（属性名=>属性値の連想配列または属性名文字列
         * @param string    $value      属性値（$attrが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function colAttr($colID, $attr, $value = NULL){
            $attrList  = (is_array($attr) ? $attr : array($attr => $value));
            $this->_colAttr[$colID]    = array_merge($this->_colAttr, $attrList);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 幅算出
         */
        //-------------------------------------------------------------------------------------------------------------------
        private function _getWidths(){
            $gridWidth = 0;
            $fixedWidth = 0;
            foreach($this->columns() as $_index => $_columns){
                if ($_index >= $this->fixedColCount()){
                    $gridWidth  += $_columns['width'];
                }
                else{
                    $fixedWidth += $_columns['width'];
                }
            }
            return array($fixedWidth, $gridWidth);
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 置換キーワードDOM組込
         * @param object    $parent         組込み先リージョンオブジェクト
         * @param string    $containerID    コンテナーエレメントID：HTML展開時に従属ビューと差し替えるエレメントのID
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function append($parent, $containerID = NULL){
            $this->_mountCommon($parent);
            $parent->appendKeyword($this->_elementID, $containerID, $this);
        }

        public function displace($parent, $containerID = NULL){
            $this->_mountCommon($parent);
            $parent->displaceKeyword($this->_elementID, $containerID, $this);
        }

        public function replace($parent, $containerID = NULL){
            $this->_mountCommon($parent);
            $parent->replaceKeyword($this->_elementID, $containerID, $this);
        }
        
        //組み込み共通処理
        private function _mountCommon($parent){
            $columns    = json_encode($this->columns());            
            $parent->getTopRegion()->addJsInclude(JS_LIB_DIR.'/htmlGrid.js');   //グリッド用スクリプトインクルード
            $parent->getTopRegion()->addLoadJsFunction('initGrid', quoted($this->_elementID).','.$this->fixedColCount().','.quoted($columns));
            $this->addStyleCss($parent);    //スタイル
            $parent->appendElement($this);  //イベント            
        }

        /**
         * クライアント側処理情報ゲッタ
         * @return array    クライアント側処理情報
         */
        public function clientProc(){
            $columns    = json_encode($this->columns()); 
            return "initGrid(".quoted($this->_elementID).','.$this->fixedColCount().','.quoted($columns).");";
        }

        public function keywordType(){
            return get_class();
        }
    }
    
    //========================================================================================================================
    /**
     * グリッドパーツクラス
     *
     * 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/
     */
    //========================================================================================================================
    class GridParts{
        private $_elementID;
        private $_attr          = array();
        private $_style         = array();
        private $_childList     = array();
        private $_content       = '';
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * コンストラクタ
         * @param strin     $elementID  エレメントID
         * @param string    $content    パーツ内容
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function __construct($elementID, $content = ''){
            $this->_elementID   = $elementID;
            $this->_content     = $content;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 従属パーツ追加
         * @param object    $child  従属パーツオブジェクト
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function addChild($child){
            $this->_childList[]     = $child;
            return $child;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * スタイル設定
         * @param array     $style      スタイル（スタイル名=>スタイル値の連想配列またはスタイル名文字列
         * @param string    $value      スタイル値（$styleが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function style($name, $value = NULL){
            $style          = (is_array($name) ? $name : array($name => $value));
            $this->_style   = array_merge($this->_style, $style);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 属性設定
         * @param array     $attr       属性（属性名=>属性値の連想配列または属性名文字列
         * @param string    $value      属性値（$attributeが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function attribute($name, $value = NULL){
            $attr           = (is_array($name) ? $name : array($name => $value));
            $this->_attr    = array_merge($this->_attr, $attr);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * パーツ構築
         * @param array     $buildList  構築イメージ格納配列
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function build(&$buildList){
            $attr   = (count($this->_attr) == 0 ? '' : getParamList($this->_attr, $operator = '=', $connect = ' ', $quote = '"', $prefix = '', $suffix = ''));
            $style  = (count($this->_style) == 0 ? '' : getParamList($this->_style, $operator = ':', $connect = ';', $quote = '', $prefix = ' style="', $suffix = ';"'));
            
            $buildList[]    = '<div id="'.$this->_elementID.'" '.$attr.$style.'>';
            if ($this->_content !== ''){
                $buildList[]    = $this->_content;
            }
            foreach ($this->_childList as $_child){
                $_child->build($buildList);
            }
            $buildList[]    = '</div>';
        }
    }

?>
