diff options
| -rw-r--r-- | .gitattributes | 3 | ||||
| -rw-r--r-- | demos/quickstart/protected/controls/TopicList.tpl | 2 | ||||
| -rw-r--r-- | demos/quickstart/protected/pages/Controls/DataGrid.page | 9 | ||||
| -rw-r--r-- | demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.page | 14 | ||||
| -rw-r--r-- | demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.php | 25 | ||||
| -rw-r--r-- | framework/Collections/TList.php | 4 | ||||
| -rw-r--r-- | framework/Collections/TMap.php | 4 | ||||
| -rw-r--r-- | framework/Collections/TPagedDataSource.php | 4 | ||||
| -rw-r--r-- | framework/Web/UI/TControl.php | 2 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TBaseDataList.php | 40 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TBoundColumn.php | 8 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataGrid.php | 443 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataGridColumn.php | 4 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TDataList.php | 28 | ||||
| -rw-r--r-- | framework/Web/UI/WebControls/TTable.php | 72 | 
15 files changed, 605 insertions, 57 deletions
| diff --git a/.gitattributes b/.gitattributes index 33f32358..e3cbd8ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -36,6 +36,7 @@ demos/quickstart/protected/pages/Configurations/Templates1.page -text  demos/quickstart/protected/pages/Configurations/Templates2.page -text  demos/quickstart/protected/pages/Configurations/Templates3.page -text  demos/quickstart/protected/pages/Construction.page -text +demos/quickstart/protected/pages/Controls/DataGrid.page -text  demos/quickstart/protected/pages/Controls/DataList.page -text  demos/quickstart/protected/pages/Controls/List.page -text  demos/quickstart/protected/pages/Controls/Overview.page -text @@ -48,6 +49,8 @@ demos/quickstart/protected/pages/Controls/Samples/TCompareValidator/Home.page -t  demos/quickstart/protected/pages/Controls/Samples/TCompareValidator/Home.php -text  demos/quickstart/protected/pages/Controls/Samples/TCustomValidator/Home.page -text  demos/quickstart/protected/pages/Controls/Samples/TCustomValidator/Home.php -text +demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.page -text +demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.php -text  demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample1.page -text  demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample1.php -text  demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page -text diff --git a/demos/quickstart/protected/controls/TopicList.tpl b/demos/quickstart/protected/controls/TopicList.tpl index c7e36184..f9992425 100644 --- a/demos/quickstart/protected/controls/TopicList.tpl +++ b/demos/quickstart/protected/controls/TopicList.tpl @@ -38,7 +38,7 @@  <a href="?page=Controls.Validation">Validation Controls</a><br/>
  <a href="?page=Controls.Repeater">TRepeater</a><br/>
  <a href="?page=Controls.DataList">TDataList</a><br/>
 -<a href="?page=Construction">TDataGrid</a><br/>
 +<a href="?page=Controls.DataGrid">TDataGrid</a><br/>
  <a href="?page=Construction">Active Controls</a><br/>
  <a href="?page=Construction">Authoring New Controls</a><br/>
  </div>
 diff --git a/demos/quickstart/protected/pages/Controls/DataGrid.page b/demos/quickstart/protected/pages/Controls/DataGrid.page new file mode 100644 index 00000000..9170fe45 --- /dev/null +++ b/demos/quickstart/protected/pages/Controls/DataGrid.page @@ -0,0 +1,9 @@ +<com:TContent ID="body" >
 +
 +<h1>TDataGrid</h1>
 +<p>
 +TBC
 +</p>
 +<com:RunBar PagePath="Controls.Samples.TDataGrid.Sample1" />
 +
 +</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.page b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.page new file mode 100644 index 00000000..5c24405e --- /dev/null +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.page @@ -0,0 +1,14 @@ +<com:TContent ID="body">
 +
 +<h1>TDataGrid Sample 1</h1>
 +
 +<com:TDataGrid
 +	ID="DataGrid"
 +	ItemStyle.BackColor="blue"
 +	ItemStyle.Font.Italic="true"
 +	ItemStyle.ForeColor="white"
 +	AlternatingItemStyle.BackColor="green"
 +	SelectedItemStyle.BackColor="red">
 +</com:TDataGrid>
 +
 +</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.php b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.php new file mode 100644 index 00000000..bf11b133 --- /dev/null +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample1.php @@ -0,0 +1,25 @@ +<?php
 +
 +class Sample1 extends TPage
 +{
 +	protected function getDataSource()
 +	{
 +		return array(
 +			array('name'=>'John','age'=>'31'),
 +			array('name'=>'Bea','age'=>'35'),
 +			array('name'=>'Rose','age'=>'33'),
 +			array('name'=>'Diane','age'=>'37'),
 +			array('name'=>'Bob','age'=>'30'),
 +		);
 +	}
 +
 +	public function onLoad($param)
 +	{
 +		parent::onLoad($param);
 +		$this->DataGrid->DataSource=$this->getDataSource();
 +		$this->DataGrid->SelectedItemIndex=2;
 +		$this->DataGrid->dataBind();
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/framework/Collections/TList.php b/framework/Collections/TList.php index b9fbd589..2946053b 100644 --- a/framework/Collections/TList.php +++ b/framework/Collections/TList.php @@ -246,7 +246,7 @@ class TList extends TComponent implements IteratorAggregate,ArrayAccess  			foreach($data as $item)
  				$this->add($item);
  		}
 -		else
 +		else if($data!==null)
  			throw new TInvalidDataTypeException('list_data_not_iterable');
  	}
 @@ -263,7 +263,7 @@ class TList extends TComponent implements IteratorAggregate,ArrayAccess  			foreach($data as $item)
  				$this->add($item);
  		}
 -		else
 +		else if($data!==null)
  			throw new TInvalidDataTypeException('list_data_not_iterable');
  	}
 diff --git a/framework/Collections/TMap.php b/framework/Collections/TMap.php index 73665136..d5a44322 100644 --- a/framework/Collections/TMap.php +++ b/framework/Collections/TMap.php @@ -180,7 +180,7 @@ class TMap extends TComponent implements IteratorAggregate,ArrayAccess  			foreach($data as $key=>$value)
  				$this->add($key,$value);
  		}
 -		else
 +		else if($data!==null)
  			throw new TInvalidDataTypeException('map_data_not_iterable');
  	}
 @@ -197,7 +197,7 @@ class TMap extends TComponent implements IteratorAggregate,ArrayAccess  			foreach($data as $key=>$value)
  				$this->add($key,$value);
  		}
 -		else
 +		else if($data!==null)
  			throw new TInvalidDataTypeException('map_data_not_iterable');
  	}
 diff --git a/framework/Collections/TPagedDataSource.php b/framework/Collections/TPagedDataSource.php index 5632e778..71e7c9e6 100644 --- a/framework/Collections/TPagedDataSource.php +++ b/framework/Collections/TPagedDataSource.php @@ -42,8 +42,10 @@ class TPagedDataSource extends TComponent implements IteratorAggregate  	{
  		if(!($value instanceof TMap) && !($value instanceof TList))
  		{
 -			if(is_array($value) || ($value instanceof Traversable))
 +			if(is_array($value))
  				$value=new TMap($value);
 +			else if($value instanceof Traversable)
 +				$value=new TList($value);
  			else if($value!==null)
  				throw new TInvalidDataTypeException('pageddatasource_datasource_invalid');
  		}
 diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php index 382e3811..26aa5dc4 100644 --- a/framework/Web/UI/TControl.php +++ b/framework/Web/UI/TControl.php @@ -953,7 +953,7 @@ class TControl extends TComponent  				$namingContainer->clearNameTable();
  		}
 -		if($this->_stage>=self::CS_INITIALIZED)
 +		if($this->_stage>=self::CS_CHILD_INITIALIZED)
  		{
  			$control->initRecursive($namingContainer);
  			if($this->_stage>=self::CS_STATE_LOADED)
 diff --git a/framework/Web/UI/WebControls/TBaseDataList.php b/framework/Web/UI/WebControls/TBaseDataList.php index f5a09815..351fbbc9 100644 --- a/framework/Web/UI/WebControls/TBaseDataList.php +++ b/framework/Web/UI/WebControls/TBaseDataList.php @@ -43,11 +43,6 @@ Prado::using('System.Web.UI.WebControls.TDataBoundControl');  abstract class TBaseDataList extends TDataBoundControl
  {
  	/**
 -	 * @var TList list of key values
 -	 */
 -	private $_dataKeys=null;
 -
 -	/**
  	 * No body content should be added to data list control.
  	 * This method is invoked when body content is parsed and added to this control.
  	 * @param mixed body content to be added
 @@ -200,9 +195,38 @@ abstract class TBaseDataList extends TDataBoundControl  	 */
  	public function getDataKeys()
  	{
 -		if(!$this->_dataKeys)
 -			$this->_dataKeys=new TList;
 -		return $this->_dataKeys;
 +		if(($dataKeys=$this->getViewState('DataKeys',null))===null)
 +		{
 +			$dataKeys=new TList;
 +			$this->setViewState('DataKeys',$dataKeys,null);
 +		}
 +		return $dataKeys;
 +	}
 +
 +	/**
 +	 * Returns the value of the data at the specified field.
 +	 * If data is an array, TMap or TList, the value will be returned at the index
 +	 * of the specified field. If the data is a component with a property named
 +	 * as the field name, the property value will be returned.
 +	 * Otherwise, an exception will be raised.
 +	 * @param mixed data item
 +	 * @param mixed field name
 +	 * @return mixed data value at the specified field
 +	 * @throws TInvalidDataValueException if the data is invalid
 +	 */
 +	protected function getDataFieldValue($data,$field)
 +	{
 +		if(is_array($data))
 +			return $data[$field];
 +		else if(($data instanceof TMap) || ($data instanceof TList))
 +			return $data->itemAt($field);
 +		else if(($data instanceof TComponent) && $data->canGetProperty($field))
 +		{
 +			$getter='get'.$field;
 +			return $data->$getter();
 +		}
 +		else
 +			throw new TInvalidDataValueException('basedatalist_datafield_invalid');
  	}
  	/**
 diff --git a/framework/Web/UI/WebControls/TBoundColumn.php b/framework/Web/UI/WebControls/TBoundColumn.php index 729f21fd..84f52034 100644 --- a/framework/Web/UI/WebControls/TBoundColumn.php +++ b/framework/Web/UI/WebControls/TBoundColumn.php @@ -107,11 +107,14 @@ class TBoundColumn extends TDataGridColumn  					$cell->getControls()->add($textBox);
  					$control=$textBox;
  				}
 +				if(($dataField=$this->getDataField())!=='')
 +					$control->attachEventHandler('DataBinding',array($this,'dataBindColumn'));
 +				break;
  			case 'Item':
  			case 'AlternatingItem':
  			case 'SelectedItem':
  				if(($dataField=$this->getDataField())!=='')
 -					$control->attachEventHandler('DataBinding',array($this,'dataBindColumn'));
 +					$cell->attachEventHandler('DataBinding',array($this,'dataBindColumn'));
  				break;
  		}
  	}
 @@ -120,8 +123,9 @@ class TBoundColumn extends TDataGridColumn  	{
  		$item=$sender->getNamingContainer();
  		$data=$item->getDataItem();
 +		$formatString=$this->getDataFormatString();
  		if(($field=$this->getDataField())!=='')
 -			$value=$this->formatDataValue($this->getDataFieldValue($data,$field));
 +			$value=$this->formatDataValue($formatString,$this->getDataFieldValue($data,$field));
  		else
  			$value=$this->formatDataValue($data);
  		if(($sender instanceof TTableCell) || ($sender instanceof TTextBox))
 diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php index 205b97a0..f25f8036 100644 --- a/framework/Web/UI/WebControls/TDataGrid.php +++ b/framework/Web/UI/WebControls/TDataGrid.php @@ -10,6 +10,10 @@   * @package System.Web.UI.WebControls
   */
 +Prado::using('System.Web.UI.WebControls.TBaseDataList');
 +Prado::using('System.Collections.TPagedDataSource');
 +Prado::using('System.Web.UI.WebControls.TTable');
 +
  /**
   * TDataGrid class
   *
 @@ -74,7 +78,7 @@   * datasource. The number of pages <b>PageCount</b> is calculated based the item number and the
   * <b>PageSize</b> property. The datagrid will manage which section of the data source to be displayed
   * based on the <b>CurrentPageIndex</b> property.
 - * The second approach calculates the page number based on the <b>VirtualItemCount</b> property and
 + * The second approach calculates the page number based on the <b>VirtualCount</b> property and
   * the <b>PageSize</b> property. The datagrid will always display from the beginning of the datasource
   * upto the number of <b>PageSize> data items. This approach is especially useful when the datasource may
   * contain too many data items to be managed by the datagrid efficiently.
 @@ -119,6 +123,12 @@ class TDataGrid extends TBaseDataList  		return 'table';
  	}
 +	public function addParsedObject($object)
 +	{
 +		if($object instanceof TDataGridColumn)
 +			$this->getColumns()->add($object);
 +	}
 +
  	public function getColumns()
  	{
  		if(!$this->_columns)
 @@ -126,6 +136,13 @@ class TDataGrid extends TBaseDataList  		return $this->_columns;
  	}
 +	public function getAutoColumns()
 +	{
 +		if(!$this->_autoColumns)
 +			$this->_autoColumns=new TDataGridColumnCollection;
 +		return $this->_autoColumns;
 +	}
 +
  	public function getItems()
  	{
  		if(!$this->_items)
 @@ -140,7 +157,10 @@ class TDataGrid extends TBaseDataList  	 */
  	protected function createStyle()
  	{
 -		return new TTableStyle;
 +		$style=new TTableStyle;
 +		$style->setGridLines('Both');
 +		$style->setCellSpacing(0);
 +		return $style;
  	}
  	/**
 @@ -483,19 +503,19 @@ class TDataGrid extends TBaseDataList  	/**
  	 * @return integer virtual number of items in the grid. Defaults to 0, meaning not set.
  	 */
 -	public function getVirtualItemCount()
 +	public function getVirtualCount()
  	{
 -		return $this->getViewState('VirtualItemCount',0);
 +		return $this->getViewState('VirtualCount',0);
  	}
  	/**
  	 * @param integer virtual number of items in the grid
  	 */
 -	public function setVirtualItemCount($value)
 +	public function setVirtualCount($value)
  	{
  		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			throw new TInvalidDataValueException('datagrid_virtualitemcount_invalid');
 -		$this->setViewState('VirtualItemCount',$value,0);
 +			throw new TInvalidDataValueException('datagrid_virtualcount_invalid');
 +		$this->setViewState('VirtualCount',$value,0);
  	}
  	/**
 @@ -515,11 +535,11 @@ class TDataGrid extends TBaseDataList  	}
  	/**
 -	 * @return boolean whether the footer should be displayed Defaults to true.
 +	 * @return boolean whether the footer should be displayed. Defaults to false.
  	 */
  	public function getShowFooter()
  	{
 -		return $this->getViewState('ShowFooter',true);
 +		return $this->getViewState('ShowFooter',false);
  	}
  	/**
 @@ -527,7 +547,7 @@ class TDataGrid extends TBaseDataList  	 */
  	public function setShowFooter($value)
  	{
 -		$this->setViewState('ShowFooter',TPropertyValue::ensureBoolean($value),true);
 +		$this->setViewState('ShowFooter',TPropertyValue::ensureBoolean($value),false);
  	}
  	/**
 @@ -693,13 +713,386 @@ class TDataGrid extends TBaseDataList  	{
  		$this->raiseEvent('PageIndexChanged',$this,$param);
  	}
 +
 +	/**
 +	 * Saves item count in viewstate.
 +	 * This method is invoked right before control state is to be saved.
 +	 * @param mixed event parameter
 +	 */
 +	protected function onSaveState($param)
 +	{
 +		if($this->_items)
 +			$this->setViewState('ItemCount',$this->_items->getCount(),0);
 +		else
 +			$this->clearViewState('ItemCount');
 +	}
 +
 +	/**
 +	 * Loads item count information from viewstate.
 +	 * This method is invoked right after control state is loaded.
 +	 * @param mixed event parameter
 +	 */
 +	protected function onLoadState($param)
 +	{
 +		if(!$this->getIsDataBound())
 +			$this->restoreItemsFromViewState();
 +		$this->clearViewState('ItemCount');
 +	}
 +
 +	private function createPagedDataSource()
 +	{
 +		$ds=new TPagedDataSource;
 +		$ds->setCurrentPageIndex($this->getCurrentPageIndex());
 +		$ds->setPageSize($this->getPageSize());
 +		$ds->setAllowPaging($this->getAllowPaging());
 +		$ds->setAllowCustomPaging($this->getAllowCustomPaging());
 +		$ds->setVirtualCount($this->getVirtualCount());
 +		return $ds;
 +	}
 +
 +	/**
 +	 * Clears up all items in the data list.
 +	 */
 +	public function reset()
 +	{
 +		$this->getControls()->clear();
 +		$this->getItems()->clear();
 +		$this->_header=null;
 +		$this->_footer=null;
 +	}
 +
 +	protected function restoreGridFromViewState()
 +	{
 +		$this->reset();
 +		$this->_pagedDataSource=$ds=$this->createPagedDataSource();
 +		// set dummy data source
 +		// create columns from viewstate
 +		if($columns->getCount()>0)
 +		{
 +			foreach($columns as $column)
 +				$column->initialize();
 +			$allowPaging=$ds->getAllowPaging();
 +			if($allowPaging)
 +				// create pager
 +			// create header
 +			// may need to use the first row of data to build items here
 +			$selectedIndex=$this->getSelectedItemIndex();
 +			$editIndex=$this->getEditItemIndex();
 +			$index=0;
 +			foreach($ds as $data)
 +			{
 +				if($index===$editIndex)
 +					$itemType='EditItem';
 +				else if($index===$selectedIndex)
 +					$itemType='SelectedItem';
 +				else if($index % 2)
 +					$itemType='AlternatingItem';
 +				else
 +					$itemType='Item';
 +				// create item
 +				$index++;
 +			}
 +			// create footer
 +			// create pager
 +		}
 +		$this->_pagedDataSource=null;
 +	}
 +
 +	/**
 +	 * Performs databinding to populate data list items from data source.
 +	 * This method is invoked by dataBind().
 +	 * You may override this function to provide your own way of data population.
 +	 * @param Traversable the data
 +	 */
 +	protected function performDataBinding($data)
 +	{
 +		$this->reset();
 +		$keys=$this->getDataKeys();
 +		$keys->clear();
 +		$keyField=$this->getDataKeyField();
 +		$this->_pagedDataSource=$ds=$this->createPagedDataSource();
 +		$ds->setDataSource($data);
 +		$allowPaging=$ds->getAllowPaging();
 +		if($allowPaging && $ds->getCurrentPageIndex()>=$ds->getPageCount())
 +			throw new TInvalidDataValueException('datagrid_currentpageindex_invalid');
 +		$columns=$this->getAllColumns($ds);
 +		$items=$this->getItems();
 +
 +		if(($columnCount=$columns->getCount())>0)
 +		{
 +			foreach($columns as $column)
 +				$column->initialize();
 +			$allowPaging=$ds->getAllowPaging();
 +			if($allowPaging)
 +				$this->createPager(-1,-1,$columnCount,$ds);
 +			$this->createItemInternal(-1,-1,'Header',true,null,$columns);
 +			$selectedIndex=$this->getSelectedItemIndex();
 +			$editIndex=$this->getEditItemIndex();
 +			$index=0;
 +			$dsIndex=$ds->getAllowPaging()?$ds->getFirstIndexInPage():0;
 +			foreach($ds as $data)
 +			{
 +				if($keyField!=='')
 +					$keys->add($this->getDataFieldValue($data,$keyField));
 +				if($index===$editIndex)
 +					$itemType='EditItem';
 +				else if($index===$selectedIndex)
 +					$itemType='SelectedItem';
 +				else if($index % 2)
 +					$itemType='AlternatingItem';
 +				else
 +					$itemType='Item';
 +				$items->add($this->createItemInternal($index,$dsIndex,$itemType,true,$data,$columns));
 +				$index++;
 +				$dsIndex++;
 +			}
 +			$this->createItemInternal(-1,-1,'Footer',true,null,$columns);
 +			if($allowPaging)
 +				$this->createPager(-1,-1,$columnCount,$ds);
 +			$this->setViewState('ItemCount',$index,0);
 +			$this->setViewState('PageCount',$ds->getPageCount(),0);
 +			$this->setViewState('DataSourceCount',$ds->getDataSourceCount(),0);
 +		}
 +		else
 +		{
 +			$this->setViewState('ItemCount',$index,0);
 +			$this->setViewState('PageCount',0,0);
 +			$this->setViewState('DataSourceCount',0,0);
 +		}
 +		$this->_pagedDataSource=null;
 +	}
 +
 +	/**
 +	 * Creates a datagrid item instance based on the item type and index.
 +	 * @param integer zero-based item index
 +	 * @param string item type, may be 'Header', 'Footer', 'Item', 'Separator', 'AlternatingItem', 'SelectedItem', 'EditItem'.
 +	 * @return TDataGridItem created data list item
 +	 */
 +	protected function createItem($itemIndex,$dataSourceIndex,$itemType)
 +	{
 +		return new TDataGridItem($itemIndex,$dataSourceIndex,$itemType);
 +	}
 +
 +	private function createItemInternal($itemIndex,$dataSourceIndex,$itemType,$dataBind,$dataItem,$columns)
 +	{
 +		$item=$this->createItem($itemIndex,$dataSourceIndex,$itemType);
 +		$this->initializeItem($item,$columns);
 +		$param=new TDataGridItemEventParameter($item);
 +		if($dataBind)
 +		{
 +			$item->setDataItem($dataItem);
 +			$this->onItemCreated($param);
 +			$this->getControls()->add($item);
 +			$item->dataBind();
 +			$this->onItemDataBound($param);
 +			$item->setDataItem(null);
 +		}
 +		else
 +		{
 +			$this->onItemCreated($param);
 +			$this->getControls()->add($item);
 +		}
 +		return $item;
 +	}
 +
 +	protected function initializeItem($item,$columns)
 +	{
 +		$cells=$item->getCells();
 +		$itemType=$item->getItemType();
 +		$index=0;
 +		foreach($columns as $column)
 +		{
 +			if($itemType==='Header')
 +				$cell=new TTableHeaderCell;
 +			else
 +				$cell=new TTableCell;
 +			$column->initializeCell($cell,$index,$itemType);
 +			$cells->add($cell);
 +			$index++;
 +		}
 +	}
 +
 +	private function createPager($itemIndex,$dataSourceIndex,$columnSpan,$pagedDataSource)
 +	{
 +		$item=$this->createItem($itemIndex,$dataSourceIndex,'Pager');
 +		$this->initializePager($item,$columnSpan,$pagedDataSource);
 +		$this->onItemCreated(new TDataGridItemEventParameter($item));
 +		$this->getControls()->add($item);
 +		return $item;
 +	}
 +
 +	protected function initializePager($pager,$columnSpan,$pagedDataSource)
 +	{
 +		$cell=new TTableCell;
 +		if($columnSpan>1)
 +			$cell->setColumnSpan($columnSpan);
 +		$this->buildPager($cell,$pagedDataSource);
 +		$pager->getCells()->add($cell);
 +	}
 +
 +	protected function buildPager($cell,$dataSource)
 +	{
 +		switch($this->getPagerStyle()->getMode())
 +		{
 +			case 'NextPrev':
 +				$this->buildNextPrevPager($cell,$dataSource);
 +				break;
 +			case 'Numeric':
 +				$this->buildNumericPager($cell,$dataSource);
 +				break;
 +		}
 +	}
 +
 +	protected function buildNextPrevPager($cell,$dataSource)
 +	{
 +		$style=$this->getPagerStyle();
 +		$controls=$cell->getControls();
 +		if($dataSource->getIsFirstPage())
 +		{
 +			$label=new TLabel;
 +			$label->setText($style->getPrevPageText());
 +			$controls->add($label);
 +		}
 +		else
 +		{
 +			$button=new TLinkButton;
 +			$button->setText($style->getPrevPageText());
 +			$button->setCommandName('page');
 +			$button->setCommandParameter('prev');
 +			$button->setCausesValidation(false);
 +			$controls->add($button);
 +		}
 +		$controls->add(' ');
 +		if($dataSource->getIsLastPage())
 +		{
 +			$label=new TLabel;
 +			$label->setText($style->getNextPageText());
 +			$controls->add($label);
 +		}
 +		else
 +		{
 +			$button=new TLinkButton;
 +			$button->setText($style->getNextPageText());
 +			$button->setCommandName('page');
 +			$button->setCommandParameter('next');
 +			$button->setCausesValidation(false);
 +			$controls->add($button);
 +		}
 +	}
 +
 +	protected function buildNumericPager($cell,$dataSource)
 +	{
 +		$style=$this->getPagerStyle();
 +		$controls=$cell->getControls();
 +		$pageCount=$dataSource->getPageCount();
 +		$pageIndex=$dataSource->getCurrentPageIndex()+1;
 +		$maxButtonCount=$style->getPageButtonCount();
 +		$buttonCount=$maxButtonCount>$pageCount?$pageCount:$maxButtonCount;
 +		$startPageIndex=1;
 +		$endPageIndex=$buttonCount;
 +		if($pageIndex>$endPageIndex)
 +		{
 +			$startPageIndex=((int)($pageIndex/$maxButtonCount))*$maxButtonCount+1;
 +			if(($endPageIndex=$startPageIndex+$maxButtonCount-1)>$pageCount)
 +				$endPageIndex=$pageCount;
 +			if($endPageIndex-$startPageIndex+1<$maxButtonCount)
 +			{
 +				if(($startPageIndex=$endPageIndex-$maxButtonCount+1)<1)
 +					$startPageIndex=1;
 +			}
 +		}
 +
 +		if($startPageIndex>1)
 +		{
 +			$button=new TLinkButton;
 +			$button->setText('...');
 +			$button->setCommandName('page');
 +			$button->setCommandParameter($startPageIndex-1);
 +			$button->setCausesValidation(false);
 +			$controls->add($button);
 +			$controls->add(' ');
 +		}
 +
 +		for($i=$startPageIndex;$i<=$endPageIndex;++$i)
 +		{
 +			if($i===$pageIndex)
 +			{
 +				$label=new TLabel;
 +				$label->setText("$i");
 +				$controls->add($label);
 +			}
 +			else
 +			{
 +				$button=new TLinkButton;
 +				$button->setText("$i");
 +				$button->setCommandName('page');
 +				$button->setCommandParameter($i);
 +				$button->setCausesValidation(false);
 +				$controls->add($button);
 +			}
 +			if($i<$endPageIndex)
 +				$controls->add(' ');
 +		}
 +
 +		if($pageCount>$endPageIndex)
 +		{
 +			$controls->add(' ');
 +			$button=new TLinkButton;
 +			$button->setText('...');
 +			$button->setCommandName('page');
 +			$button->setCommandParameter($endPageIndex+1);
 +			$button->setCausesValidation(false);
 +			$controls->add($button);
 +		}
 +	}
 +
 +	protected function getAllColumns($dataSource)
 +	{
 +		$list=new TList($this->getColumns());
 +		$list->mergeWith($this->createAutoColumns($dataSource));
 +		return $list;
 +	}
 +
 +	protected function createAutoColumns($dataSource)
 +	{
 +		if(!$dataSource || $dataSource->getCount()<=0)
 +			return null;
 +		$autoColumns=$this->getAutoColumns();
 +		$autoColumns->clear();
 +		foreach($dataSource as $row)
 +		{
 +			foreach($row as $key=>$value)
 +			{
 +				$column=new TBoundColumn;
 +				if(is_string($key))
 +				{
 +					$column->setHeaderText($key);
 +					$column->setDataField($key);
 +					$column->setSortExpression($key);
 +					$column->setOwner($this);
 +					$autoColumns->add($column);
 +				}
 +				else
 +				{
 +					$column->setHeaderText('Item');
 +					$column->setDataField($key);
 +					$column->setSortExpression('Item');
 +					$column->setOwner($this);
 +					$autoColumns->add($column);
 +				}
 +			}
 +			break;
 +		}
 +		return $autoColumns;
 +	}
  }
 +
  /**
   * TDataGridItemEventParameter class
   *
   * TDataGridItemEventParameter encapsulates the parameter data for
   * {@link TDataGrid::onItemCreated ItemCreated} event of {@link TDataGrid} controls.
 - * The {@link getItem Item} property indicates the DataList item related with the event.
 + * The {@link getItem Item} property indicates the datagrid item related with the event.
   *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Revision: $  $Date: $
 @@ -716,7 +1109,7 @@ class TDataGridItemEventParameter extends TEventParameter  	/**
  	 * Constructor.
 -	 * @param TDataGridItem DataList item related with the corresponding event
 +	 * @param TDataGridItem datagrid item related with the corresponding event
  	 */
  	public function __construct(TDataGridItem $item)
  	{
 @@ -724,7 +1117,7 @@ class TDataGridItemEventParameter extends TEventParameter  	}
  	/**
 -	 * @return TDataGridItem DataList item related with the corresponding event
 +	 * @return TDataGridItem datagrid item related with the corresponding event
  	 */
  	public function getItem()
  	{
 @@ -738,7 +1131,7 @@ class TDataGridItemEventParameter extends TEventParameter   * TDataGridCommandEventParameter encapsulates the parameter data for
   * {@link TDataGrid::onItemCommand ItemCommand} event of {@link TDataGrid} controls.
   *
 - * The {@link getItem Item} property indicates the DataList item related with the event.
 + * The {@link getItem Item} property indicates the datagrid item related with the event.
   * The {@link getCommandSource CommandSource} refers to the control that originally
   * raises the Command event.
   *
 @@ -760,7 +1153,7 @@ class TDataGridCommandEventParameter extends TCommandEventParameter  	/**
  	 * Constructor.
 -	 * @param TDataGridItem DataList item responsible for the event
 +	 * @param TDataGridItem datagrid item responsible for the event
  	 * @param TControl original event sender
  	 * @param TCommandEventParameter original event parameter
  	 */
 @@ -903,7 +1296,7 @@ class TDataGridPageChangedEventParameter extends TEventParameter   * such as heading section, footer section, or a data item.
   * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}>
   * and {@link getDataItem DataItem} properties, respectively. The type of the item
 - * is given by {@link getItemType ItemType} property. Property {@link getDataSetIndex DataSetIndex}
 + * is given by {@link getItemType ItemType} property. Property {@link getDataSourceIndex DataSourceIndex}
   * gives the index of the item from the bound data source.
   *
   * @author Qiang Xue <qiang.xue@gmail.com>
 @@ -914,13 +1307,13 @@ class TDataGridPageChangedEventParameter extends TEventParameter  class TDataGridItem extends TTableRow implements INamingContainer
  {
  	/**
 -	 * @var integer index of the data item in the Items collection of DataList
 +	 * @var integer index of the data item in the Items collection of datagrid
  	 */
  	private $_itemIndex='';
  	/**
  	 * @var integer index of the item from the bound data source
  	 */
 -	private $_dataSetIndex=0;
 +	private $_dataSourceIndex=0;
  	/**
  	 * type of the TDataGridItem
  	 * @var string
 @@ -934,13 +1327,13 @@ class TDataGridItem extends TTableRow implements INamingContainer  	/**
  	 * Constructor.
 -	 * @param integer zero-based index of the item in the item collection of DataList
 +	 * @param integer zero-based index of the item in the item collection of datagrid
  	 * @param string item type, can be 'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'.
  	 */
 -	public function __construct($itemIndex,$dataSetIndex,$itemType)
 +	public function __construct($itemIndex,$dataSourceIndex,$itemType)
  	{
  		$this->_itemIndex=$itemIndex;
 -		$this->_dataSetIndex=$dataSetIndex;
 +		$this->_dataSourceIndex=$dataSourceIndex;
  		$this->setItemType($itemType);
  	}
 @@ -961,7 +1354,7 @@ class TDataGridItem extends TTableRow implements INamingContainer  	}
  	/**
 -	 * @return integer zero-based index of the item in the item collection of DataList
 +	 * @return integer zero-based index of the item in the item collection of datagrid
  	 */
  	public function getItemIndex()
  	{
 @@ -971,9 +1364,9 @@ class TDataGridItem extends TTableRow implements INamingContainer  	/**
  	 * @return integer the index of the datagrid item from the bound data source
  	 */
 -	public function getDataSetIndex()
 +	public function getDataSourceIndex()
  	{
 -		return $this->_dataSetIndex;
 +		return $this->_dataSourceIndex;
  	}
  	/**
 @@ -1080,7 +1473,7 @@ class TDataGridPagerStyle extends TTableItemStyle  	public function setMode($value)
  	{
 -		$this->_mode=TPropertyValue::ensureEnum($value,'NextPrev','NumericPages');
 +		$this->_mode=TPropertyValue::ensureEnum($value,'NextPrev','Numeric');
  	}
  	public function getNextPageText()
 diff --git a/framework/Web/UI/WebControls/TDataGridColumn.php b/framework/Web/UI/WebControls/TDataGridColumn.php index dc1d8521..5e43f735 100644 --- a/framework/Web/UI/WebControls/TDataGridColumn.php +++ b/framework/Web/UI/WebControls/TDataGridColumn.php @@ -206,12 +206,12 @@ abstract class TDataGridColumn extends TComponent  		return $this->_viewState;
  	}
 -	protected function getOwner()
 +	public function getOwner()
  	{
  		return $this->_owner;
  	}
 -	protected function setOwner(TDataGrid $value)
 +	public function setOwner(TDataGrid $value)
  	{
  		$this->_owner=$value;
  	}
 diff --git a/framework/Web/UI/WebControls/TDataList.php b/framework/Web/UI/WebControls/TDataList.php index ebaf9568..6f61f8ef 100644 --- a/framework/Web/UI/WebControls/TDataList.php +++ b/framework/Web/UI/WebControls/TDataList.php @@ -415,6 +415,22 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs  	}
  	/**
 +	 * @return mixed the key value of the currently selected item
 +	 * @throws TInvalidOperationException if {@link getDataKeyField DataKeyField} is empty.
 +	 */
 +	public function getSelectedDataKey()
 +	{
 +		if($this->getDataKeyField()==='')
 +			throw new TInvalidOperationException('datalist_datakeyfield_required');
 +		$index=$this->getSelectedIndex();
 +		$dataKeys=$this->getDataKeys();
 +		if($index>=0 && $index<$dataKeys->getCount())
 +			return $dataKeys->itemAt($index);
 +		else
 +			return null;
 +	}
 +
 +	/**
  	 * @return integer the zero-based index of the edit item in {@link getItems Items}.
  	 * A value -1 means no item is in edit mode.
  	 */
 @@ -1091,17 +1107,7 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs  		foreach($data as $dataItem)
  		{
  			if($keyField!=='')
 -			{
 -				if(is_array($dataItem) || ($dataItem instanceof TMap))
 -					$keys->add($dataItem[$keyField]);
 -				else if(($dataItem instanceof TComponent) && $dataItem->canGetProperty($keyField))
 -				{
 -					$getter='get'.$keyField;
 -					$keys->add($dataItem->$getter());
 -				}
 -				else
 -					throw new TInvalidDataValueException('datalist_keyfield_invalid',$keyField);
 -			}
 +				$keys->add($this->getDataFieldValue($dataItem,$keyField));
  			if($itemIndex===0 && $this->_headerTemplate!=='')
  				$this->_header=$this->createItemInternal(-1,'Header',true,null);
  			if($hasSeparator && $itemIndex>0)
 diff --git a/framework/Web/UI/WebControls/TTable.php b/framework/Web/UI/WebControls/TTable.php index 13cbd0b1..3ca3d51d 100644 --- a/framework/Web/UI/WebControls/TTable.php +++ b/framework/Web/UI/WebControls/TTable.php @@ -124,7 +124,7 @@ class TTable extends TWebControl  	public function getRows()
  	{
  		if(!$this->_rows)
 -			$this->_rows=new TTableRowCollection();
 +			$this->_rows=new TTableRowCollection($this);
  		return $this->_rows;
  	}
 @@ -352,7 +352,7 @@ class TTableRow extends TWebControl  	public function getCells()
  	{
  		if(!$this->_cells)
 -			$this->_cells=new TTableCellCollection();
 +			$this->_cells=new TTableCellCollection($this);
  		return $this->_cells;
  	}
 @@ -698,6 +698,20 @@ class TTableHeaderCell extends TTableCell  class TTableRowCollection extends TList
  {
  	/**
 +	 * @var mixed row collection owner
 +	 */
 +	private $_owner=null;
 +
 +	/**
 +	 * Constructor.
 +	 * @param mixed row collection owner
 +	 */
 +	public function __construct($owner=null)
 +	{
 +		$this->_owner=$owner;
 +	}
 +
 +	/**
  	 * Only string or instance of TControl can be added into collection.
  	 * @param mixed the item to be added
  	 */
 @@ -705,6 +719,26 @@ class TTableRowCollection extends TList  	{
  		return ($item instanceof TTableRow);
  	}
 +
 +	/**
 +	 * Overrides the parent implementation with customized processing of the newly added item.
 +	 * @param mixed the newly added item
 +	 */
 +	protected function addedItem($item)
 +	{
 +		if($this->_owner)
 +			$this->_owner->getControls()->add($item);
 +	}
 +
 +	/**
 +	 * Overrides the parent implementation with customized processing of the removed item.
 +	 * @param mixed the removed item
 +	 */
 +	protected function removedItem($item)
 +	{
 +		if($this->_owner)
 +			$this->_owner->getControls()->remove($item);
 +	}
  }
 @@ -721,6 +755,20 @@ class TTableRowCollection extends TList  class TTableCellCollection extends TList
  {
  	/**
 +	 * @var mixed cell collection owner
 +	 */
 +	private $_owner=null;
 +
 +	/**
 +	 * Constructor.
 +	 * @param mixed cell collection owner
 +	 */
 +	public function __construct($owner=null)
 +	{
 +		$this->_owner=$owner;
 +	}
 +
 +	/**
  	 * Only string or instance of TTableCell can be added into collection.
  	 * @param mixed the item to be added
  	 */
 @@ -728,5 +776,25 @@ class TTableCellCollection extends TList  	{
  		return ($item instanceof TTableCell);
  	}
 +
 +	/**
 +	 * Overrides the parent implementation with customized processing of the newly added item.
 +	 * @param mixed the newly added item
 +	 */
 +	protected function addedItem($item)
 +	{
 +		if($this->_owner)
 +			$this->_owner->getControls()->add($item);
 +	}
 +
 +	/**
 +	 * Overrides the parent implementation with customized processing of the removed item.
 +	 * @param mixed the removed item
 +	 */
 +	protected function removedItem($item)
 +	{
 +		if($this->_owner)
 +			$this->_owner->getControls()->remove($item);
 +	}
  }
  ?>
\ No newline at end of file | 
