From aac749d4fbfdf3508d97f7dfe4d7c2c03597edbb Mon Sep 17 00:00:00 2001 From: xue <> Date: Mon, 26 Jun 2006 02:52:44 +0000 Subject: Merge from 3.0 branch till 1202. --- .gitattributes | 2 + HISTORY | 2 + framework/Web/UI/TPage.php | 2 +- framework/Web/UI/WebControls/TDataGrid.php | 17 +- framework/Web/UI/WebControls/TDataList.php | 3 + framework/Web/UI/WebControls/TListControl.php | 28 +- framework/Web/UI/WebControls/TPager.php | 759 ++++++++++++++++++++++++++ framework/Web/UI/WebControls/TPanel.php | 222 +------- framework/Web/UI/WebControls/TPanelStyle.php | 235 ++++++++ framework/Web/UI/WebControls/TRepeater.php | 3 + 10 files changed, 1034 insertions(+), 239 deletions(-) create mode 100644 framework/Web/UI/WebControls/TPager.php create mode 100644 framework/Web/UI/WebControls/TPanelStyle.php diff --git a/.gitattributes b/.gitattributes index 15501094..3c3ac2f0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1650,7 +1650,9 @@ framework/Web/UI/WebControls/TLiteral.php -text framework/Web/UI/WebControls/TMarkdown.php -text framework/Web/UI/WebControls/TMultiView.php -text framework/Web/UI/WebControls/TOutputCache.php -text +framework/Web/UI/WebControls/TPager.php -text framework/Web/UI/WebControls/TPanel.php -text +framework/Web/UI/WebControls/TPanelStyle.php -text framework/Web/UI/WebControls/TPlaceHolder.php -text framework/Web/UI/WebControls/TRadioButton.php -text framework/Web/UI/WebControls/TRadioButtonList.php -text diff --git a/HISTORY b/HISTORY index a041c0b3..477d1a30 100644 --- a/HISTORY +++ b/HISTORY @@ -14,6 +14,7 @@ Version 3.0.2 July 2, 2006 BUG: Ticket#182 - List and validator controls cause problem in child classes (Qiang) BUG: Ticket#191 - Duplicated postbacks occur when using TButton with validators (Qiang) BUG: Ticket#213 - PRADO Requirements Checker charset error (Qiang) +BUG: Ticket#234 - Postback target could be out of date (Qiang) BUG: Ticket#244 - redirect() needs absolute URL (Qiang) BUG: Ticket#245 - getIsSecureConnection() is not working correctly (Qiang) CHG: ensureChildControls() is now invoked in TControl::initRecursive (Qiang) @@ -26,6 +27,7 @@ ENH: Ticket#232 - Allow <%# %> and <%= %> embedded within property values (Qiang ENH: TRepeater, TDataList and TDataGrid will store data indices in DataKeys if DataKeyField is not set. (Qiang) ENH: Added TPageService.BasePageClass property (Qiang) ENH: Added TDataGrid.EmptyTemplate property (Qiang) +NEW: Added TPager (Qiang) Version 3.0.1 June 4, 2006 ========================== diff --git a/framework/Web/UI/TPage.php b/framework/Web/UI/TPage.php index 57c66a31..8839e6a2 100644 --- a/framework/Web/UI/TPage.php +++ b/framework/Web/UI/TPage.php @@ -821,7 +821,7 @@ class TPage extends TTemplateControl $this->_controlsPostDataChanged[]=$control; } else if($control instanceof IPostBackEventHandler) - $this->setPostBackEventTarget($control); + $this->_postData->add(self::FIELD_POSTBACK_TARGET,$key); // not calling setPostBackEventTarget() because the control may be removed later unset($this->_controlsRequiringPostData[$key]); } else if($beforeLoad) diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php index dae2d2cd..4fe63f52 100644 --- a/framework/Web/UI/WebControls/TDataGrid.php +++ b/framework/Web/UI/WebControls/TDataGrid.php @@ -1049,7 +1049,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer } /** - * Performs databinding to populate data list items from data source. + * Performs databinding to populate datagrid items from data source. * This method is invoked by {@link dataBind()}. * You may override this function to provide your own way of data population. * @param Traversable the bound data @@ -1069,8 +1069,9 @@ class TDataGrid extends TBaseDataList implements INamingContainer if($ds->getCount()===0 && $ds->getCurrentPageIndex()===0 && $this->_emptyTemplate!==null) { - $this->_emptyTemplate->instantiateIn($this); $this->_useEmptyTemplate=true; + $this->_emptyTemplate->instantiateIn($this); + $this->dataBindChildren(); $this->clearViewState('ItemCount'); $this->clearViewState('PageCount'); $this->clearViewState('DataSourceCount'); @@ -1757,7 +1758,7 @@ class TDataGridCommandEventParameter extends TCommandEventParameter * {@link TDataGrid::onSortCommand SortCommand} event of {@link TDataGrid} controls. * * The {@link getCommandSource CommandSource} property refers to the control - * that originally raises the Command event, while {@link getSortExpression SortExpression} + * that originally raises the OnCommand event, while {@link getSortExpression SortExpression} * gives the sort expression carried with the sort command. * * @author Qiang Xue @@ -1778,7 +1779,7 @@ class TDataGridSortCommandEventParameter extends TEventParameter /** * Constructor. - * @param TControl the control originally raises the Command event. + * @param TControl the control originally raises the OnCommand event. * @param TDataGridCommandEventParameter command event parameter */ public function __construct($source,TDataGridCommandEventParameter $param) @@ -1788,7 +1789,7 @@ class TDataGridSortCommandEventParameter extends TEventParameter } /** - * @return TControl the control originally raises the Command event. + * @return TControl the control originally raises the OnCommand event. */ public function getCommandSource() { @@ -1811,7 +1812,7 @@ class TDataGridSortCommandEventParameter extends TEventParameter * {@link TDataGrid::onPageIndexChanged PageIndexChanged} event of {@link TDataGrid} controls. * * The {@link getCommandSource CommandSource} property refers to the control - * that originally raises the Command event, while {@link getNewPageIndex NewPageIndex} + * that originally raises the OnCommand event, while {@link getNewPageIndex NewPageIndex} * returns the new page index carried with the page command. * * @author Qiang Xue @@ -1832,7 +1833,7 @@ class TDataGridPageChangedEventParameter extends TEventParameter /** * Constructor. - * @param TControl the control originally raises the Command event. + * @param TControl the control originally raises the OnCommand event. * @param integer new page index */ public function __construct($source,$newPageIndex) @@ -1842,7 +1843,7 @@ class TDataGridPageChangedEventParameter extends TEventParameter } /** - * @return TControl the control originally raises the Command event. + * @return TControl the control originally raises the OnCommand event. */ public function getCommandSource() { diff --git a/framework/Web/UI/WebControls/TDataList.php b/framework/Web/UI/WebControls/TDataList.php index 0dac2be2..b6888225 100644 --- a/framework/Web/UI/WebControls/TDataList.php +++ b/framework/Web/UI/WebControls/TDataList.php @@ -1174,7 +1174,10 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs if($itemIndex>0 && $this->_footerTemplate!==null) $this->_footer=$this->createItemInternal(-1,'Footer',true,null); if($itemIndex===0 && $this->_emptyTemplate!==null) + { $this->_emptyTemplate->instantiateIn($this); + $this->dataBindChildren(); + } $this->setViewState('ItemCount',$itemIndex,0); } diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 3ad46db8..b070f26b 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -471,7 +471,7 @@ abstract class TListControl extends TDataBoundControl $this->_items->itemAt($index)->setSelected(true); } } - + if($this->getAdapter() instanceof IListControlAdaptee) $this->getAdapter()->setSelectedIndices($indices); } @@ -558,9 +558,9 @@ abstract class TListControl extends TDataBoundControl throw new TInvalidDataValueException('listcontrol_selectedvalue_invalid',get_class($this),$value); } } - + if($this->getAdapter() instanceof IListControlAdaptee) - $this->getAdapter()->setSelectedValues($values); + $this->getAdapter()->setSelectedValues($values); } /** @@ -589,9 +589,9 @@ abstract class TListControl extends TDataBoundControl foreach($this->_items as $item) $item->setSelected(false); } - + if($this->getAdapter() instanceof IListControlAdaptee) - $this->getAdapter()->clearSelection(); + $this->getAdapter()->clearSelection(); } /** @@ -727,7 +727,7 @@ class TListItemCollection extends TList $this->insertAt($index,$item); return $item; } - + /** * @return TListItem new item. */ @@ -852,15 +852,15 @@ class TListItemCollection extends TList * @package System.Web.UI.ActiveControls * @since 3.0 */ -interface IListControlAdaptee +interface IListControlAdapter { - /** - * Selects an item based on zero-base index on the client side. + /** + * Selects an item based on zero-base index on the client side. * @param integer the index (zero-based) of the item to be selected */ public function setSelectedIndex($index); - /** - * Selects a list of item based on zero-base indices on the client side. + /** + * Selects a list of item based on zero-base indices on the client side. * @param array list of index of items to be selected */ public function setSelectedIndices($indices); @@ -870,13 +870,13 @@ interface IListControlAdaptee * @param string the value of the item to be selected. */ public function setSelectedValue($value); - - /** + + /** * Sets selection by a list of item values on the client side. * @param array list of the selected item values */ public function setSelectedValues($values); - + /** * Clears all existing selections on the client side. */ diff --git a/framework/Web/UI/WebControls/TPager.php b/framework/Web/UI/WebControls/TPager.php new file mode 100644 index 00000000..f802e8d7 --- /dev/null +++ b/framework/Web/UI/WebControls/TPager.php @@ -0,0 +1,759 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataBoundControl'); +Prado::using('System.Web.UI.WebControls.TPanelStyle'); +Prado::using('System.Collections.TPagedDataSource'); +Prado::using('System.Collections.TDummyDataSource'); + +/** + * TPager class. + * + * TPager creates a pager that controls the paging of the data populated + * to a data-bound control specified by {@link setControlToPaginate ControlToPaginate}. + * To specify the number of data items displayed on each page, set + * the {@link setPageSize PageSize} property, and to specify which + * page of data to be displayed, set {@link setCurrentPageIndex CurrentPageIndex}. + * + * When the size of the original data is too big to be loaded all in the memory, + * one can enable custom paging. In custom paging, the total number of data items + * is specified manually via {@link setVirtualItemCount VirtualItemCount}, and the data source + * only needs to contain the current page of data. To enable custom paging, + * set {@link setAllowCustomPaging AllowCustomPaging} to true. + * + * TPager can be in one of three {@link setMode Mode}: + * - NextPrev: a next page and a previous page button are rendered. + * - Numeric: a list of page index buttons are rendered. + * - List: a dropdown list of page indices are rendered. + * + * TPager raises an {@link onPageIndexChanged OnPageIndexChanged} event when + * the end-user interacts with it and specifies a new page (e.g. clicking + * on a page button that leads to a new page.) The new page index may be obtained + * from the event parameter's property {@link TPagerPageChangedEventParameter::getNewPageIndex NewPageIndex}. + * + * When multiple pagers are associated with the same data-bound control, + * these pagers will do synchronization among each other so that the interaction + * with one pager will automatically update the UI of the other relevant pagers. + * + * The following example shows a typical usage of TPager: + * + * $pager->ControlToPaginate="Path.To.Control"; + * $pager->DataSource=$data; + * $pager->dataBind(); + * + * Note, the data is assigned to the pager and dataBind() is invoked against the pager. + * Without the pager, one has to set datasource for the target control and call + * its dataBind() directly. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + * @since 3.0.2 + */ +class TPager extends TDataBoundControl implements INamingContainer +{ + /** + * Command name that TPager understands. + */ + const CMD_PAGE='Page'; + const CMD_PAGE_NEXT='Next'; + const CMD_PAGE_PREV='Previous'; + const CMD_PAGE_FIRST='First'; + const CMD_PAGE_LAST='Last'; + + /** + * @var array list of all pagers, used to synchronize their appearance + */ + static private $_pagers=array(); + + /** + * Registers the pager itself to a global list. + * This method overrides the parent implementation and is invoked during + * OnInit control lifecycle. + * @param mixed event parameter + */ + public function onInit($param) + { + parent::onInit($param); + self::$_pagers[]=$this; + } + + /** + * Unregisters the pager from a global list. + * This method overrides the parent implementation and is invoked during + * OnUnload control lifecycle. + * @param mixed event parameter + */ + public function onUnload($param) + { + parent::onUnload($param); + if(($index=array_search($this,self::$_pagers,true))!==false) + unset(self::$_pagers[$index]); + } + + /** + * Restores the pager state. + * This method overrides the parent implementation and is invoked when + * the control is loading persistent state. + */ + public function loadState() + { + parent::loadState(); + if(!$this->getEnableViewState(true)) + return; + if(!$this->getIsDataBound()) + $this->restoreFromViewState(); + } + + /** + * @return string the ID path of the control whose content would be paginated. + */ + public function getControlToPaginate() + { + return $this->getViewState('ControlToPaginate',''); + } + + /** + * Sets the ID path of the control whose content would be paginated. + * The ID path is the dot-connected IDs of the controls reaching from + * the pager's naming container to the target control. + * @param string the ID path + */ + public function setControlToPaginate($value) + { + $this->setViewState('ControlToPaginate',$value,''); + } + + /** + * @return integer the zero-based index of the current page. Defaults to 0. + */ + public function getCurrentPageIndex() + { + return $this->getViewState('CurrentPageIndex',0); + } + + /** + * @param integer the zero-based index of the current page + * @throws TInvalidDataValueException if the value is less than 0 + */ + public function setCurrentPageIndex($value) + { + if(($value=TPropertyValue::ensureInteger($value))<0) + throw new TInvalidDataValueException('pager_currentpageindex_invalid'); + $this->setViewState('CurrentPageIndex',$value,0); + } + + /** + * @return integer the number of data items on each page. Defaults to 10. + */ + public function getPageSize() + { + return $this->getViewState('PageSize',10); + } + + /** + * @param integer the number of data items on each page. + * @throws TInvalidDataValueException if the value is less than 1 + */ + public function setPageSize($value) + { + if(($value=TPropertyValue::ensureInteger($value))<1) + throw new TInvalidDataValueException('pager_pagesize_invalid'); + $this->setViewState('PageSize',TPropertyValue::ensureInteger($value),10); + } + + /** + * @return integer number of pages + */ + public function getPageCount() + { + if(($count=$this->getItemCount())<1) + return 1; + else + { + $pageSize=$this->getPageSize(); + return (int)(($count+$pageSize-1)/$pageSize); + } + } + + /** + * @return boolean whether the custom paging is enabled. Defaults to false. + */ + public function getAllowCustomPaging() + { + return $this->getViewState('AllowCustomPaging',false); + } + + /** + * Sets a value indicating whether the custom paging should be enabled. + * When the pager is in custom paging mode, the {@link setVirtualItemCount VirtualItemCount} + * property is used to determine the paging, and the data items in the + * {@link setDataSource DataSource} are considered to be in the current page. + * @param boolean whether the custom paging is enabled + */ + public function setAllowCustomPaging($value) + { + $this->setViewState('AllowCustomPaging',TPropertyValue::ensureBoolean($value),false); + } + + /** + * @return integer virtual number of data items in the data source. Defaults to 0. + * @see setAllowCustomPaging + */ + public function getVirtualItemCount() + { + return $this->getViewState('VirtualItemCount',0); + } + + /** + * @param integer virtual number of data items in the data source. + * @throws TInvalidDataValueException if the value is less than 0 + * @see setAllowCustomPaging + */ + public function setVirtualItemCount($value) + { + if(($value=TPropertyValue::ensureInteger($value))<0) + throw new TInvalidDataValueException('pager_virtualitemcount_invalid'); + $this->setViewState('VirtualItemCount',$value,0); + } + + /** + * @return integer total number of items in the datasource. + */ + public function getItemCount() + { + return $this->getViewState('ItemCount',0); + } + + /** + * @return string pager mode. Defaults to 'NextPrev'. + */ + public function getMode() + { + return $this->getViewState('Mode','NextPrev'); + } + + /** + * @param string pager mode. Valid values include 'NextPrev', 'Numeric' and 'List'. + */ + public function setMode($value) + { + $this->setViewState('Mode',TPropertyValue::ensureEnum($value,'NextPrev','Numeric','List'),'NextPrev'); + } + + /** + * @return string the type of command button for paging. Defaults to 'LinkButton'. + */ + public function getButtonType() + { + return $this->getViewState('ButtonType','LinkButton'); + } + + /** + * @param string the type of command button for paging. Valid values include 'LinkButton' and 'PushButton'. + */ + public function setButtonType($value) + { + $this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'LinkButton','PushButton')); + } + + /** + * @return string text for the next page button. Defaults to '>'. + */ + public function getNextPageText() + { + return $this->getViewState('NextPageText','>'); + } + + /** + * @param string text for the next page button. + */ + public function setNextPageText($value) + { + $this->setViewState('NextPageText',$value,'>'); + } + + /** + * @return string text for the previous page button. Defaults to '<'. + */ + public function getPrevPageText() + { + return $this->getViewState('PrevPageText','<'); + } + + /** + * @param string text for the next page button. + */ + public function setPrevPageText($value) + { + $this->setViewState('PrevPageText',$value,'<'); + } + + /** + * @return string text for the first page button. Defaults to '<<'. + */ + public function getFirstPageText() + { + return $this->getViewState('FirstPageText','<<'); + } + + /** + * @param string text for the first page button. If empty, the first page button will not be rendered. + */ + public function setFirstPageText($value) + { + $this->setViewState('FirstPageText',$value,'<<'); + } + + /** + * @return string text for the last page button. Defaults to '>>'. + */ + public function getLastPageText() + { + return $this->getViewState('LastPageText','>>'); + } + + /** + * @param string text for the last page button. If empty, the last page button will not be rendered. + */ + public function setLastPageText($value) + { + $this->setViewState('LastPageText',$value,'>>'); + } + + /** + * @return integer maximum number of pager buttons to be displayed. Defaults to 10. + */ + public function getPageButtonCount() + { + return $this->getViewState('PageButtonCount',10); + } + + /** + * @param integer maximum number of pager buttons to be displayed + * @throws TInvalidDataValueException if the value is less than 1. + */ + public function setPageButtonCount($value) + { + if(($value=TPropertyValue::ensureInteger($value))<1) + throw new TInvalidDataValueException('pager_pagebuttoncount_invalid'); + $this->setViewState('PageButtonCount',$value,10); + } + + /** + * @return TPagedDataSource creates a paged data source + */ + private function createPagedDataSource() + { + $ds=new TPagedDataSource; + $ds->setAllowPaging(true); + $customPaging=$this->getAllowCustomPaging(); + $ds->setAllowCustomPaging($customPaging); + $ds->setCurrentPageIndex($this->getCurrentPageIndex()); + $ds->setPageSize($this->getPageSize()); + if($customPaging) + $ds->setVirtualItemCount($this->getVirtualItemCount()); + return $ds; + } + + /** + * Removes the existing child controls. + */ + protected function reset() + { + $this->getControls()->clear(); + } + + /** + * Restores the pager from viewstate. + */ + protected function restoreFromViewState() + { + $this->reset(); + $ds=$this->createPagedDataSource(); + $ds->setDataSource(new TDummyDataSource($this->getItemCount())); + $this->buildPager($ds); + } + + /** + * Performs databinding to populate data items from data source. + * This method is invoked by {@link dataBind()}. + * You may override this function to provide your own way of data population. + * @param Traversable the bound data + */ + protected function performDataBinding($data) + { + $this->reset(); + + $controlID=$this->getControlToPaginate(); + if(($targetControl=$this->getNamingContainer()->findControl($controlID))===null || !($targetControl instanceof TDataBoundControl)) + throw new TConfigurationException('pager_controltopaginate_invalid',$controlID); + + $ds=$this->createPagedDataSource(); + $ds->setDataSource($this->getDataSource()); + $this->setViewState('ItemCount',$ds->getDataSourceCount()); + + $this->buildPager($ds); + $this->synchronizePagers($targetControl,$ds); + + $targetControl->setDataSource($ds); + $targetControl->dataBind(); + } + + /** + * Synchronizes the state of all pagers who have the same {@link getControlToPaginate ControlToPaginate}. + * @param TDataBoundControl the control whose content is to be paginated + * @param TPagedDataSource the paged data source associated with the pager + */ + protected function synchronizePagers($targetControl,$dataSource) + { + foreach(self::$_pagers as $pager) + { + if($pager!==$this && $pager->getNamingContainer()->findControl($pager->getControlToPaginate())===$targetControl) + { + $pager->reset(); + $pager->setCurrentPageIndex($dataSource->getCurrentPageIndex()); + $customPaging=$dataSource->getAllowCustomPaging(); + $pager->setAllowCustomPaging($customPaging); + $pager->setViewState('ItemCount',$dataSource->getDataSourceCount()); + if($customPaging) + $pager->setVirtualItemCount($dataSource->getVirtualItemCount()); + $pager->buildPager($dataSource); + } + } + } + + /** + * Builds the pager content based on the pager mode. + * Current implementation includes building 'NextPrev', 'Numeric' and 'List' pagers. + * Derived classes may override this method to provide additional pagers. + * @param TPagedDataSource data source bound to the target control + */ + protected function buildPager($dataSource) + { + switch($this->getMode()) + { + case 'NextPrev': + $this->buildNextPrevPager($dataSource); + break; + case 'Numeric': + $this->buildNumericPager($dataSource); + break; + case 'List': + $this->buildListPager($dataSource); + break; + } + } + + /** + * Creates a pager button. + * Depending on the button type, a TLinkButton or a TButton may be created. + * If it is enabled (clickable), its command name and parameter will also be set. + * Derived classes may override this method to create additional types of buttons, such as TImageButton. + * @param string button type, either LinkButton or PushButton + * @param boolean whether the button should be enabled + * @param string caption of the button + * @param string CommandName corresponding to the OnCommand event of the button + * @param string CommandParameter corresponding to the OnCommand event of the button + * @return mixed the button instance + */ + protected function createPagerButton($buttonType,$enabled,$text,$commandName,$commandParameter) + { + if($buttonType==='LinkButton') + { + if($enabled) + $button=new TLinkButton; + else + { + $button=new TLabel; + $button->setText($text); + return $button; + } + } + else + { + $button=new TButton; + if(!$enabled) + $button->setEnabled(false); + } + $button->setText($text); + $button->setCommandName($commandName); + $button->setCommandParameter($commandParameter); + $button->setCausesValidation(false); + return $button; + } + + /** + * Builds a next-prev pager + * @param TPagedDataSource data source bound to the pager + */ + protected function buildNextPrevPager($dataSource) + { + $buttonType=$this->getButtonType(); + $controls=$this->getControls(); + if($dataSource->getIsFirstPage()) + { + if(($text=$this->getFirstPageText())!=='') + { + $label=$this->createPagerButton($buttonType,false,$text,'',''); + $controls->add($label); + $controls->add("\n"); + } + $label=$this->createPagerButton($buttonType,false,$this->getPrevPageText(),'',''); + $controls->add($label); + } + else + { + if(($text=$this->getFirstPageText())!=='') + { + $button=$this->createPagerButton($buttonType,true,$text,self::CMD_PAGE_FIRST,''); + $controls->add($button); + $controls->add("\n"); + } + $button=$this->createPagerButton($buttonType,true,$this->getPrevPageText(),self::CMD_PAGE_PREV,''); + $controls->add($button); + } + $controls->add("\n"); + if($dataSource->getIsLastPage()) + { + $label=$this->createPagerButton($buttonType,false,$this->getNextPageText(),'',''); + $controls->add($label); + if(($text=$this->getLastPageText())!=='') + { + $controls->add("\n"); + $label=$this->createPagerButton($buttonType,false,$text,'',''); + $controls->add($label); + } + } + else + { + $button=$this->createPagerButton($buttonType,true,$this->getNextPageText(),self::CMD_PAGE_NEXT,''); + $controls->add($button); + if(($text=$this->getLastPageText())!=='') + { + $controls->add("\n"); + $button=$this->createPagerButton($buttonType,true,$text,self::CMD_PAGE_LAST,''); + $controls->add($button); + } + } + } + + /** + * Builds a numeric pager + * @param TPagedDataSource data source bound to the pager + */ + protected function buildNumericPager($dataSource) + { + $buttonType=$this->getButtonType(); + $controls=$this->getControls(); + $pageCount=$dataSource->getPageCount(); + $pageIndex=$dataSource->getCurrentPageIndex()+1; + $maxButtonCount=$this->getPageButtonCount(); + $buttonCount=$maxButtonCount>$pageCount?$pageCount:$maxButtonCount; + $startPageIndex=1; + $endPageIndex=$buttonCount; + if($pageIndex>$endPageIndex) + { + $startPageIndex=((int)(($pageIndex-1)/$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) + { + if(($text=$this->getFirstPageText())!=='') + { + $button=$this->createPagerButton($buttonType,true,$text,self::CMD_PAGE_FIRST,''); + $controls->add($button); + $controls->add("\n"); + } + $prevPageIndex=$startPageIndex-1; + $button=$this->createPagerButton($buttonType,true,$this->getPrevPageText(),self::CMD_PAGE,"$prevPageIndex"); + $controls->add($button); + $controls->add("\n"); + } + + for($i=$startPageIndex;$i<=$endPageIndex;++$i) + { + if($i===$pageIndex) + { + $label=$this->createPagerButton($buttonType,false,"$i",'',''); + $controls->add($label); + } + else + { + $button=$this->createPagerButton($buttonType,true,"$i",self::CMD_PAGE,"$i"); + $controls->add($button); + } + if($i<$endPageIndex) + $controls->add("\n"); + } + + if($pageCount>$endPageIndex) + { + $controls->add("\n"); + $nextPageIndex=$endPageIndex+1; + $button=$this->createPagerButton($buttonType,true,$this->getNextPageText(),self::CMD_PAGE,"$nextPageIndex"); + $controls->add($button); + if(($text=$this->getLastPageText())!=='') + { + $controls->add("\n"); + $button=$this->createPagerButton($buttonType,true,$text,self::CMD_PAGE_LAST,''); + $controls->add($button); + } + } + } + + /** + * Builds a dropdown list pager + * @param TPagedDataSource data source bound to the pager + */ + protected function buildListPager($dataSource) + { + $list=new TDropDownList; + $this->getControls()->add($list); + $list->setDataSource(range(1,$dataSource->getPageCount())); + $list->dataBind(); + $list->setSelectedIndex($dataSource->getCurrentPageIndex()); + $list->setAutoPostBack(true); + $list->attachEventHandler('OnSelectedIndexChanged',array($this,'listIndexChanged')); + } + + /** + * Event handler to the OnSelectedIndexChanged event of the dropdown list. + * This handler will raise {@link onPageIndexChanged OnPageIndexChanged} event. + * @param TDropDownList the dropdown list control raising the event + * @param TEventParameter event parameter + */ + public function listIndexChanged($sender,$param) + { + $pageIndex=$sender->getSelectedIndex(); + $this->onPageIndexChanged(new TPagerPageChangedEventParameter($sender,$pageIndex)); + } + + /** + * This event is raised when page index is changed due to a page button click. + * @param TPagerPageChangedEventParameter event parameter + */ + public function onPageIndexChanged($param) + { + $this->raiseEvent('OnPageIndexChanged',$this,$param); + } + + /** + * Processes a bubbled event. + * This method overrides parent's implementation by wrapping event parameter + * for OnCommand event with item information. + * @param TControl the sender of the event + * @param TEventParameter event parameter + * @return boolean whether the event bubbling should stop here. + */ + public function bubbleEvent($sender,$param) + { + if($param instanceof TCommandEventParameter) + { + $command=$param->getCommandName(); + if(strcasecmp($command,self::CMD_PAGE)===0) + { + $pageIndex=TPropertyValue::ensureInteger($param->getCommandParameter())-1; + $this->onPageIndexChanged(new TPagerPageChangedEventParameter($sender,$pageIndex)); + return true; + } + else if(strcasecmp($command,self::CMD_PAGE_NEXT)===0) + { + $pageIndex=$this->getCurrentPageIndex()+1; + $this->onPageIndexChanged(new TPagerPageChangedEventParameter($sender,$pageIndex)); + return true; + } + else if(strcasecmp($command,self::CMD_PAGE_PREV)===0) + { + $pageIndex=$this->getCurrentPageIndex()-1; + $this->onPageIndexChanged(new TPagerPageChangedEventParameter($sender,$pageIndex)); + return true; + } + else if(strcasecmp($command,self::CMD_PAGE_FIRST)===0) + { + $this->onPageIndexChanged(new TPagerPageChangedEventParameter($sender,0)); + return true; + } + else if(strcasecmp($command,self::CMD_PAGE_LAST)===0) + { + $this->onPageIndexChanged(new TPagerPageChangedEventParameter($sender,$this->getPageCount()-1)); + return true; + } + return false; + } + else + return false; + } +} + +/** + * TPagerPageChangedEventParameter class + * + * TPagerPageChangedEventParameter encapsulates the parameter data for + * {@link TPager::onPageIndexChanged PageIndexChanged} event of {@link TPager} controls. + * + * The {@link getCommandSource CommandSource} property refers to the control + * that originally raises the OnCommand event, while {@link getNewPageIndex NewPageIndex} + * returns the new page index carried with the page command. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + * @since 3.0.2 + */ +class TPagerPageChangedEventParameter extends TEventParameter +{ + /** + * @var integer new page index + */ + private $_newIndex; + /** + * @var TControl original event sender + */ + private $_source=null; + + /** + * Constructor. + * @param TControl the control originally raises the OnCommand event. + * @param integer new page index + */ + public function __construct($source,$newPageIndex) + { + $this->_source=$source; + $this->_newIndex=$newPageIndex; + } + + /** + * @return TControl the control originally raises the OnCommand event. + */ + public function getCommandSource() + { + return $this->_source; + } + + /** + * @return integer new page index + */ + public function getNewPageIndex() + { + return $this->_newIndex; + } +} + +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TPanel.php b/framework/Web/UI/WebControls/TPanel.php index 03f0a3a3..27006b94 100644 --- a/framework/Web/UI/WebControls/TPanel.php +++ b/framework/Web/UI/WebControls/TPanel.php @@ -10,6 +10,11 @@ * @package System.Web.UI.WebControls */ +/** + * Includes TPanelStyle class file + */ +Prado::using('System.Web.UI.WebControls.TPanelStyle'); + /** * TPanel class * @@ -52,6 +57,7 @@ class TPanel extends TWebControl /** * Creates a style object to be used by the control. * This method overrides the parent impementation by creating a TPanelStyle object. + * @return TPanelStyle the style used by TPanel. */ protected function createStyle() { @@ -228,220 +234,4 @@ class TPanel extends TWebControl } } -/** - * TPanelStyle class. - * TPanelStyle represents the CSS style specific for panel HTML tag. - * - * @author Qiang Xue - * @version $Revision: $ $Date: $ - * @package System.Web.UI.WebControls - * @since 3.0 - */ -class TPanelStyle extends TStyle -{ - /** - * @var string the URL of the background image for the panel component - */ - private $_backImageUrl=null; - /** - * @var string alignment of the content in the panel. - */ - private $_direction=null; - /** - * @var string horizontal alignment of the contents within the panel - */ - private $_horizontalAlign=null; - /** - * @var string visibility and position of scroll bars - */ - private $_scrollBars=null; - /** - * @var boolean whether the content wraps within the panel - */ - private $_wrap=null; - - /** - * Adds attributes related to CSS styles to renderer. - * This method overrides the parent implementation. - * @param THtmlWriter the writer used for the rendering purpose - */ - public function addAttributesToRender($writer) - { - if(($url=trim($this->getBackImageUrl()))!=='') - $this->setStyleField('background-image','url('.$url.')'); - - switch($this->getScrollBars()) - { - case 'Horizontal': $this->setStyleField('overflow-x','scroll'); break; - case 'Vertical': $this->setStyleField('overflow-y','scroll'); break; - case 'Both': $this->setStyleField('overflow','scroll'); break; - case 'Auto': $this->setStyleField('overflow','auto'); break; - } - - if(($align=$this->getHorizontalAlign())!=='NotSet') - $this->setStyleField('text-align',strtolower($align)); - - if(!$this->getWrap()) - $this->setStyleField('white-space','nowrap'); - - if(($direction=$this->getDirection())!=='NotSet') - { - if($direction==='LeftToRight') - $this->setStyleField('direction','ltr'); - else - $this->setStyleField('direction','rtl'); - } - - parent::addAttributesToRender($writer); - } - - /** - * @return string the URL of the background image for the panel component. - */ - public function getBackImageUrl() - { - return $this->_backImageUrl===null?'':$this->_backImageUrl; - } - - /** - * Sets the URL of the background image for the panel component. - * @param string the URL - */ - public function setBackImageUrl($value) - { - $this->_backImageUrl=$value; - } - - /** - * @return string alignment of the content in the panel. Defaults to 'NotSet'. - */ - public function getDirection() - { - return $this->_direction===null?'NotSet':$this->_direction; - } - - /** - * @param string alignment of the content in the panel. - * Valid values include 'NotSet', 'LeftToRight', 'RightToLeft'. - */ - public function setDirection($value) - { - $this->_direction=TPropertyValue::ensureEnum($value,array('NotSet','LeftToRight','RightToLeft')); - } - - /** - * @return boolean whether the content wraps within the panel. Defaults to true. - */ - public function getWrap() - { - return $this->_wrap===null?true:$this->_wrap; - } - - /** - * Sets the value indicating whether the content wraps within the panel. - * @param boolean whether the content wraps within the panel. - */ - public function setWrap($value) - { - $this->_wrap=TPropertyValue::ensureBoolean($value); - } - - /** - * @return string the horizontal alignment of the contents within the panel, defaults to 'NotSet'. - */ - public function getHorizontalAlign() - { - return $this->_horizontalAlign===null?'NotSet':$this->_horizontalAlign; - } - - /** - * Sets the horizontal alignment of the contents within the panel. - * Valid values include 'NotSet', 'Justify', 'Left', 'Right', 'Center' - * @param string the horizontal alignment - */ - public function setHorizontalAlign($value) - { - $this->_horizontalAlign=TPropertyValue::ensureEnum($value,array('NotSet','Left','Right','Center','Justify')); - } - - /** - * @return string the visibility and position of scroll bars in a panel control, defaults to None. - */ - public function getScrollBars() - { - return $this->_scrollBars===null?'None':$this->_scrollBars; - } - - /** - * @param string the visibility and position of scroll bars in a panel control. - * Valid values include None, Auto, Both, Horizontal and Vertical. - */ - public function setScrollBars($value) - { - $this->_scrollBars=TPropertyValue::ensureEnum($value,array('None','Auto','Both','Horizontal','Vertical')); - } - - /** - * Sets the style attributes to default values. - * This method overrides the parent implementation by - * resetting additional TTableStyle specific attributes. - */ - public function reset() - { - parent::reset(); - $this->_backImageUrl=null; - $this->_direction=null; - $this->_horizontalAlign=null; - $this->_scrollBars=null; - $this->_wrap=null; - } - - /** - * Copies the fields in a new style to this style. - * If a style field is set in the new style, the corresponding field - * in this style will be overwritten. - * @param TStyle the new style - */ - public function copyFrom($style) - { - parent::copyFrom($style); - if($style instanceof TPanelStyle) - { - if($style->_backImageUrl!==null) - $this->_backImageUrl=$style->_backImageUrl; - if($style->_direction!==null) - $this->_direction=$style->_direction; - if($style->_horizontalAlign!==null) - $this->_horizontalAlign=$style->_horizontalAlign; - if($style->_scrollBars!==null) - $this->_scrollBars=$style->_scrollBars; - if($style->_wrap!==null) - $this->_wrap=$style->_wrap; - } - } - - /** - * Merges the style with a new one. - * If a style field is not set in this style, it will be overwritten by - * the new one. - * @param TStyle the new style - */ - public function mergeWith($style) - { - parent::mergeWith($style); - if($style instanceof TPanelStyle) - { - if($this->_backImageUrl===null && $style->_backImageUrl!==null) - $this->_backImageUrl=$style->_backImageUrl; - if($this->_direction===null && $style->_direction!==null) - $this->_direction=$style->_direction; - if($this->_horizontalAlign===null && $style->_horizontalAlign!==null) - $this->_horizontalAlign=$style->_horizontalAlign; - if($this->_scrollBars===null && $style->_scrollBars!==null) - $this->_scrollBars=$style->_scrollBars; - if($this->_wrap===null && $style->_wrap!==null) - $this->_wrap=$style->_wrap; - } - } -} ?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TPanelStyle.php b/framework/Web/UI/WebControls/TPanelStyle.php new file mode 100644 index 00000000..02f366b8 --- /dev/null +++ b/framework/Web/UI/WebControls/TPanelStyle.php @@ -0,0 +1,235 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TStyle class file + */ +Prado::using('System.Web.UI.WebControls.TStyle'); + +/** + * TPanelStyle class. + * TPanelStyle represents the CSS style specific for panel HTML tag. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TPanelStyle extends TStyle +{ + /** + * @var string the URL of the background image for the panel component + */ + private $_backImageUrl=null; + /** + * @var string alignment of the content in the panel. + */ + private $_direction=null; + /** + * @var string horizontal alignment of the contents within the panel + */ + private $_horizontalAlign=null; + /** + * @var string visibility and position of scroll bars + */ + private $_scrollBars=null; + /** + * @var boolean whether the content wraps within the panel + */ + private $_wrap=null; + + /** + * Adds attributes related to CSS styles to renderer. + * This method overrides the parent implementation. + * @param THtmlWriter the writer used for the rendering purpose + */ + public function addAttributesToRender($writer) + { + if(($url=trim($this->getBackImageUrl()))!=='') + $this->setStyleField('background-image','url('.$url.')'); + + switch($this->getScrollBars()) + { + case 'Horizontal': $this->setStyleField('overflow-x','scroll'); break; + case 'Vertical': $this->setStyleField('overflow-y','scroll'); break; + case 'Both': $this->setStyleField('overflow','scroll'); break; + case 'Auto': $this->setStyleField('overflow','auto'); break; + } + + if(($align=$this->getHorizontalAlign())!=='NotSet') + $this->setStyleField('text-align',strtolower($align)); + + if(!$this->getWrap()) + $this->setStyleField('white-space','nowrap'); + + if(($direction=$this->getDirection())!=='NotSet') + { + if($direction==='LeftToRight') + $this->setStyleField('direction','ltr'); + else + $this->setStyleField('direction','rtl'); + } + + parent::addAttributesToRender($writer); + } + + /** + * @return string the URL of the background image for the panel component. + */ + public function getBackImageUrl() + { + return $this->_backImageUrl===null?'':$this->_backImageUrl; + } + + /** + * Sets the URL of the background image for the panel component. + * @param string the URL + */ + public function setBackImageUrl($value) + { + $this->_backImageUrl=$value; + } + + /** + * @return string alignment of the content in the panel. Defaults to 'NotSet'. + */ + public function getDirection() + { + return $this->_direction===null?'NotSet':$this->_direction; + } + + /** + * @param string alignment of the content in the panel. + * Valid values include 'NotSet', 'LeftToRight', 'RightToLeft'. + */ + public function setDirection($value) + { + $this->_direction=TPropertyValue::ensureEnum($value,array('NotSet','LeftToRight','RightToLeft')); + } + + /** + * @return boolean whether the content wraps within the panel. Defaults to true. + */ + public function getWrap() + { + return $this->_wrap===null?true:$this->_wrap; + } + + /** + * Sets the value indicating whether the content wraps within the panel. + * @param boolean whether the content wraps within the panel. + */ + public function setWrap($value) + { + $this->_wrap=TPropertyValue::ensureBoolean($value); + } + + /** + * @return string the horizontal alignment of the contents within the panel, defaults to 'NotSet'. + */ + public function getHorizontalAlign() + { + return $this->_horizontalAlign===null?'NotSet':$this->_horizontalAlign; + } + + /** + * Sets the horizontal alignment of the contents within the panel. + * Valid values include 'NotSet', 'Justify', 'Left', 'Right', 'Center' + * @param string the horizontal alignment + */ + public function setHorizontalAlign($value) + { + $this->_horizontalAlign=TPropertyValue::ensureEnum($value,array('NotSet','Left','Right','Center','Justify')); + } + + /** + * @return string the visibility and position of scroll bars in a panel control, defaults to None. + */ + public function getScrollBars() + { + return $this->_scrollBars===null?'None':$this->_scrollBars; + } + + /** + * @param string the visibility and position of scroll bars in a panel control. + * Valid values include None, Auto, Both, Horizontal and Vertical. + */ + public function setScrollBars($value) + { + $this->_scrollBars=TPropertyValue::ensureEnum($value,array('None','Auto','Both','Horizontal','Vertical')); + } + + /** + * Sets the style attributes to default values. + * This method overrides the parent implementation by + * resetting additional TTableStyle specific attributes. + */ + public function reset() + { + parent::reset(); + $this->_backImageUrl=null; + $this->_direction=null; + $this->_horizontalAlign=null; + $this->_scrollBars=null; + $this->_wrap=null; + } + + /** + * Copies the fields in a new style to this style. + * If a style field is set in the new style, the corresponding field + * in this style will be overwritten. + * @param TStyle the new style + */ + public function copyFrom($style) + { + parent::copyFrom($style); + if($style instanceof TPanelStyle) + { + if($style->_backImageUrl!==null) + $this->_backImageUrl=$style->_backImageUrl; + if($style->_direction!==null) + $this->_direction=$style->_direction; + if($style->_horizontalAlign!==null) + $this->_horizontalAlign=$style->_horizontalAlign; + if($style->_scrollBars!==null) + $this->_scrollBars=$style->_scrollBars; + if($style->_wrap!==null) + $this->_wrap=$style->_wrap; + } + } + + /** + * Merges the style with a new one. + * If a style field is not set in this style, it will be overwritten by + * the new one. + * @param TStyle the new style + */ + public function mergeWith($style) + { + parent::mergeWith($style); + if($style instanceof TPanelStyle) + { + if($this->_backImageUrl===null && $style->_backImageUrl!==null) + $this->_backImageUrl=$style->_backImageUrl; + if($this->_direction===null && $style->_direction!==null) + $this->_direction=$style->_direction; + if($this->_horizontalAlign===null && $style->_horizontalAlign!==null) + $this->_horizontalAlign=$style->_horizontalAlign; + if($this->_scrollBars===null && $style->_scrollBars!==null) + $this->_scrollBars=$style->_scrollBars; + if($this->_wrap===null && $style->_wrap!==null) + $this->_wrap=$style->_wrap; + } + } +} + +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php index a2fc01d7..eb599341 100644 --- a/framework/Web/UI/WebControls/TRepeater.php +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -452,7 +452,10 @@ class TRepeater extends TDataBoundControl implements INamingContainer if($itemIndex>0 && $this->_footerTemplate!==null) $this->_footer=$this->createItemInternal(-1,self::IT_FOOTER,true,null); if($itemIndex===0 && $this->_emptyTemplate!==null) + { $this->_emptyTemplate->instantiateIn($this); + $this->dataBindChildren(); + } $this->setViewState('ItemCount',$itemIndex,0); } -- cgit v1.2.3