From 95f302ce4fbf3d923b52131495a77ef41b37e8c5 Mon Sep 17 00:00:00 2001 From: xue <> Date: Fri, 7 Sep 2007 13:34:10 +0000 Subject: Added support of TDataGrid to allow grouping consecutive cells with the same content. --- framework/Web/UI/WebControls/TDataGrid.php | 68 +++++++++++++++++++++++- framework/Web/UI/WebControls/TDataGridColumn.php | 32 +++++++++-- framework/Web/UI/WebControls/THyperLink.php | 16 +++--- 3 files changed, 104 insertions(+), 12 deletions(-) (limited to 'framework/Web') diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php index 547c769d..9803d511 100644 --- a/framework/Web/UI/WebControls/TDataGrid.php +++ b/framework/Web/UI/WebControls/TDataGrid.php @@ -185,6 +185,10 @@ class TDataGrid extends TBaseDataList implements INamingContainer * @var TDataGridColumnCollection automatically created column collection */ private $_autoColumns=null; + /** + * @var TList all columns including both manually and automatically created columns + */ + private $_allColumns=null; /** * @var TDataGridItemCollection datagrid item collection */ @@ -948,6 +952,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer $columns=new TList($this->getColumns()); $columns->mergeWith($this->_autoColumns); + $this->_allColumns=$columns; $items=$this->getItems(); @@ -1012,6 +1017,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer } else $columns=$this->getColumns(); + $this->_allColumns=$columns; $items=$this->getItems(); @@ -1066,6 +1072,66 @@ class TDataGrid extends TBaseDataList implements INamingContainer } } + /** + * Merges consecutive cells who have the same text. + * @since 3.1.1 + */ + private function groupCells() + { + if(($columns=$this->_allColumns)===null) + return; + $items=$this->getItems(); + foreach($columns as $id=>$column) + { + if(!$column->getEnableCellGrouping()) + continue; + $prevCell=null; + $prevCellText=null; + foreach($items as $item) + { + $itemType=$item->getItemType(); + $cell=$item->getCells()->itemAt($id); + if(!$cell->getVisible()) + continue; + if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem) + { + if(($cellText=$this->getCellText($cell))==='') + { + $prevCell=null; + $prevCellText=null; + continue; + } + if($prevCell===null || $prevCellText!==$cellText) + { + $prevCell=$cell; + $prevCellText=$cellText; + } + else + { + if(($rowSpan=$prevCell->getRowSpan())===0) + $rowSpan=1; + $prevCell->setRowSpan($rowSpan+1); + $cell->setVisible(false); + } + } + } + } + } + + private function getCellText($cell) + { + if(($data=$cell->getText())==='' && $cell->getHasControls()) + { + $controls=$cell->getControls(); + foreach($controls as $control) + { + if($control instanceof IDataRenderer) + return $control->getData(); + } + } + return $data; + } + /** * Creates a datagrid item instance based on the item type and index. * @param integer zero-based item index @@ -1089,7 +1155,6 @@ class TDataGrid extends TBaseDataList implements INamingContainer $this->getControls()->add($item); $item->dataBind(); $this->onItemDataBound($param); - $item->setDataItem(null); } else { @@ -1485,6 +1550,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer { if($this->getHasControls()) { + $this->groupCells(); if($this->_useEmptyTemplate) { $control=new TWebControl; diff --git a/framework/Web/UI/WebControls/TDataGridColumn.php b/framework/Web/UI/WebControls/TDataGridColumn.php index 161f24eb..73c374b0 100644 --- a/framework/Web/UI/WebControls/TDataGridColumn.php +++ b/framework/Web/UI/WebControls/TDataGridColumn.php @@ -27,15 +27,23 @@ Prado::using('System.Web.UI.WebControls.TDataGrid'); * The {@link getItemStyle ItemStyle} is applied to cells that belong to * non-header and -footer datagrid items. * + * When the datagrid enables sorting, if the {@link setSortExpression SortExpression} + * is not empty, the header cell will display a button (linkbutton or imagebutton) + * that will bubble the sort command event to the datagrid. + * * Since v3.1.0, TDataGridColumn has introduced two new properties {@link setHeaderRenderer HeaderRenderer} * and {@link setFooterRenderer FooterRenderer} which can be used to specify * the layout of header and footer column cells. * A renderer refers to a control class that is to be instantiated as a control. * For more details, see {@link TRepeater} and {@link TDataList}. * - * When the datagrid enables sorting, if the {@link setSortExpression SortExpression} - * is not empty, the header cell will display a button (linkbutton or imagebutton) - * that will bubble the sort command event to the datagrid. + * Since v3.1.1, TDataGridColumn has introduced {@link setEnableCellGrouping EnableCellGrouping}. + * If a column has this property set true, consecutive cells having the same content in this + * column will be grouped into one cell. + * Note, there are some limitations to cell grouping. We determine the cell content according to + * the cell's {@link TTableCell::getText Text} property. If the text is empty and the cell has + * some child controls, we will pick up the first control who implements {@link IDataRenderer} + * and obtain its {@link IDataRenderer::getData Data} property. * * The following datagrid column types are provided by the framework currently, * - {@link TBoundColumn}, associated with a specific field in datasource and displays the corresponding data. @@ -236,6 +244,24 @@ abstract class TDataGridColumn extends TApplicationComponent $this->setViewState('SortExpression',$value,''); } + /** + * @return boolean whether cells having the same content should be grouped together. Defaults to false. + * @since 3.1.1 + */ + public function getEnableCellGrouping() + { + return $this->getViewState('EnableCellGrouping',false); + } + + /** + * @param boolean whether cells having the same content should be grouped together. + * @since 3.1.1 + */ + public function setEnableCellGrouping($value) + { + $this->setViewState('EnableCellGrouping',TPropertyValue::ensureBoolean($value),false); + } + /** * @return boolean whether the column is visible. Defaults to true. */ diff --git a/framework/Web/UI/WebControls/THyperLink.php b/framework/Web/UI/WebControls/THyperLink.php index 13a9ab41..0287029f 100644 --- a/framework/Web/UI/WebControls/THyperLink.php +++ b/framework/Web/UI/WebControls/THyperLink.php @@ -145,27 +145,27 @@ class THyperLink extends TWebControl implements IDataRenderer /** * Returns the URL to link to when the THyperLink component is clicked. * This method is required by {@link IDataRenderer}. - * It is the same as {@link getNavigateUrl()}. - * @return string the URL to link to when the THyperLink component is clicked - * @see getNavigateUrl + * It is the same as {@link getText()}. + * @return string the text caption + * @see getText * @since 3.1.0 */ public function getData() { - return $this->getNavigateUrl(); + return $this->getText(); } /** * Sets the URL to link to when the THyperLink component is clicked. * This method is required by {@link IDataRenderer}. - * It is the same as {@link setNavigateUrl()}. - * @param string the URL to link to when the THyperLink component is clicked - * @see setNavigateUrl + * It is the same as {@link setText()}. + * @param string the text caption to be set + * @see setText * @since 3.1.0 */ public function setData($value) { - $this->setNavigateUrl($value); + $this->setText($value); } /** -- cgit v1.2.3