From 633ae42f1c6f7069ba155ffa1bbc3b42fe189bb4 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sun, 4 Feb 2007 03:30:32 +0000 Subject: Added renderer feature to TRepeater. --- framework/Exceptions/messages.txt | 17 +- framework/Web/UI/WebControls/TButton.php | 28 +- framework/Web/UI/WebControls/TCheckBox.php | 28 +- framework/Web/UI/WebControls/TDataBoundControl.php | 41 ++ framework/Web/UI/WebControls/THiddenField.php | 29 +- framework/Web/UI/WebControls/TImage.php | 28 +- framework/Web/UI/WebControls/TInlineFrame.php | 28 +- framework/Web/UI/WebControls/TLabel.php | 28 +- framework/Web/UI/WebControls/TLinkButton.php | 28 +- framework/Web/UI/WebControls/TLiteral.php | 28 +- framework/Web/UI/WebControls/TRepeater.php | 586 ++++++++++++++++----- framework/Web/UI/WebControls/TTableCell.php | 28 +- framework/Web/UI/WebControls/TTextBox.php | 28 +- framework/interfaces.php | 23 + 14 files changed, 802 insertions(+), 146 deletions(-) (limited to 'framework') diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 1df4349f..1b9ab749 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -250,27 +250,24 @@ comparevalidator_controltocompare_invalid = TCompareValidator.ControlToCompare c listcontrolvalidator_invalid_control = {0}.ControlToValidate contains an invalid TListControl ID path, "{1}" is a {2}. repeater_template_required = TRepeater.{0} requires a template instance implementing ITemplate interface. +repeater_itemtype_unknown = Unknow repeater item type {0}. +repeateritemcollection_item_invalid = TRepeaterItemCollection can only accept objects that are instance of TControl or its descendant class. + datalist_template_required = TDataList.{0} requires a template instance implementing ITemplate interface. +datalistitemcollection_datalistitem_required = TDataListItemCollection can only accept TDataListItem objects. + datagrid_template_required = TDataGrid.{0} requires a template instance implementing ITemplate interface. templatecolumn_template_required = TTemplateColumn.{0} requires a template instance implementing ITemplate interface. - datagrid_currentpageindex_invalid = TDataGrid.CurrentPageIndex must be no less than 0. datagrid_pagesize_invalid = TDataGrid.PageSize must be greater than 0. datagrid_virtualitemcount_invalid = TDataGrid.VirtualItemCount must be no less than 0. - +datagriditemcollection_datagriditem_required = TDataGridItemCollection can only accept TDataGridItem objects. +datagridcolumncollection_datagridcolumn_required = TDataGridColumnCollection can only accept TDataGridColumn objects. datagridpagerstyle_pagebuttoncount_invalid = TDataGridPagerStyle.PageButtonCount must be greater than 0. datafieldaccessor_data_invalid = TDataFieldAccessor is trying to evaluate a field value of an invalid data. Make sure the data is an array, TMap, TList, or object that contains the specified field '{0}'. datafieldaccessor_datafield_invalid = TDataFieldAccessor is trying to evaluate data value of an unknown field '{0}'. -repeateritemcollection_repeateritem_required = TRepeaterItemCollection can only accept TRepeaterItem objects. - -datagriditemcollection_datagriditem_required = TDataGridItemCollection can only accept TDataGridItem objects. - -datagridcolumncollection_datagridcolumn_required = TDataGridColumnCollection can only accept TDataGridColumn objects. - -datalistitemcollection_datalistitem_required = TDataListItemCollection can only accept TDataListItem objects. - tablerowcollection_tablerow_required = TTableRowCollection can only accept TTableRow objects. tablecellcollection_tablerow_required = TTableCellCollection can only accept TTableCell objects. diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php index 0b118495..34f27ff2 100644 --- a/framework/Web/UI/WebControls/TButton.php +++ b/framework/Web/UI/WebControls/TButton.php @@ -47,7 +47,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl +class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer { /** * @return string tag name of the button @@ -221,6 +221,32 @@ class TButton extends TWebControl implements IPostBackEventHandler, IButtonContr $this->setViewState('Text',$value,''); } + /** + * Returns the caption of the button. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getText()}. + * @return string caption of the button. + * @see getText + * @since 3.1.0 + */ + public function getData() + { + return $this->getText(); + } + + /** + * Sets the caption of the button. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setText()}. + * @param string caption of the button + * @see setText + * @since 3.1.0 + */ + public function setData($value) + { + $this->setText($value); + } + /** * @return boolean whether postback event trigger by this button will cause input validation, default is true */ diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php index fefc9331..78002644 100644 --- a/framework/Web/UI/WebControls/TCheckBox.php +++ b/framework/Web/UI/WebControls/TCheckBox.php @@ -40,7 +40,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable +class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer { /** * @return string tag name of the button @@ -179,6 +179,32 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl $this->setViewState('Checked',TPropertyValue::ensureBoolean($value),false); } + /** + * Returns the value indicating whether the checkbox is checked. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getChecked()}. + * @return boolean whether the checkbox is checked. + * @see getChecked + * @since 3.1.0 + */ + public function getData() + { + return $this->getChecked(); + } + + /** + * Sets the value indicating whether the checkbox is to be checked or not. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setChecked()}. + * @param boolean whether the checkbox is to be checked + * @see setChecked + * @since 3.1.0 + */ + public function setData($value) + { + $this->setChecked($value); + } + /** * @return boolean whether clicking on the checkbox will post the page. */ diff --git a/framework/Web/UI/WebControls/TDataBoundControl.php b/framework/Web/UI/WebControls/TDataBoundControl.php index 6e1d1003..b043060d 100644 --- a/framework/Web/UI/WebControls/TDataBoundControl.php +++ b/framework/Web/UI/WebControls/TDataBoundControl.php @@ -542,4 +542,45 @@ class TListItemType extends TEnumerable const Pager='Pager'; } + +/** + * IItemDataRenderer interface. + * + * IItemDataRenderer defines the interface that an item renderer + * needs to implement. Besides the {@link getData Data} property, a list item + * renderer also needs to provide {@link getItemIndex ItemIndex} and + * {@link getItemType ItemType} property. + * + * @author Qiang Xue + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.0 + */ +interface IItemDataRenderer extends IDataRenderer +{ + /** + * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection. + * If the item is not in the collection (e.g. it is a header item), it returns -1. + * @return integer zero-based index of the item. + */ + public function getItemIndex(); + + /** + * Sets the zero-based index for the item. + * If the item is not in the item collection (e.g. it is a header item), -1 should be used. + * @param integer zero-based index of the item. + */ + public function setItemIndex($value); + + /** + * @return TListItemType the item type. + */ + public function getItemType(); + + /** + * @param TListItemType the item type. + */ + public function setItemType($value); +} + ?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/THiddenField.php b/framework/Web/UI/WebControls/THiddenField.php index f9fdd3b0..8a8a0c8a 100644 --- a/framework/Web/UI/WebControls/THiddenField.php +++ b/framework/Web/UI/WebControls/THiddenField.php @@ -23,7 +23,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class THiddenField extends TControl implements IPostBackDataHandler, IValidatable +class THiddenField extends TControl implements IPostBackDataHandler, IValidatable, IDataRenderer { /** * @return string tag name of the hidden field. @@ -131,6 +131,33 @@ class THiddenField extends TControl implements IPostBackDataHandler, IValidatabl $this->setViewState('Value',$value,''); } + /** + * Returns the value of the hidden field. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getValue()}. + * @return string value of the hidden field + * @see getValue + * @since 3.1.0 + */ + public function getData() + { + return $this->getValue(); + } + + /** + * Sets the value of the hidden field. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setValue()}. + * @param string value of the hidden field + * @see setValue + * @since 3.1.0 + */ + public function setData($value) + { + $this->setValue($value); + } + + /** * @return boolean whether theming is enabled for this control. Defaults to false. */ diff --git a/framework/Web/UI/WebControls/TImage.php b/framework/Web/UI/WebControls/TImage.php index 00e32765..24efd064 100644 --- a/framework/Web/UI/WebControls/TImage.php +++ b/framework/Web/UI/WebControls/TImage.php @@ -25,7 +25,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TImage extends TWebControl +class TImage extends TWebControl implements IDataRenderer { /** * @return string tag name of image control @@ -114,6 +114,32 @@ class TImage extends TWebControl $this->setViewState('ImageUrl',$value,''); } + /** + * Returns the URL of the image file. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getImageUrl()}. + * @return string the URL of the image file. + * @see getImageUrl + * @since 3.1.0 + */ + public function getData() + { + return $this->getImageUrl(); + } + + /** + * Sets the URL of the image. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setImageUrl()}. + * @param string the URL of the image file. + * @see setImageUrl + * @since 3.1.0 + */ + public function setData($value) + { + $this->setImageUrl($value); + } + /** * @return string the URL to long description */ diff --git a/framework/Web/UI/WebControls/TInlineFrame.php b/framework/Web/UI/WebControls/TInlineFrame.php index c893f399..e0a57eca 100644 --- a/framework/Web/UI/WebControls/TInlineFrame.php +++ b/framework/Web/UI/WebControls/TInlineFrame.php @@ -31,7 +31,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TInlineFrame extends TWebControl +class TInlineFrame extends TWebControl implements IDataRenderer { /** * @return string tag name of the iframe. @@ -105,6 +105,32 @@ class TInlineFrame extends TWebControl $this->setViewState('FrameUrl',$value,''); } + /** + * Returns the URL that this iframe will load content from + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getFrameUrl()}. + * @return string the URL that this iframe will load content from + * @see getFrameUrl + * @since 3.1.0 + */ + public function getData() + { + return $this->getFrameUrl(); + } + + /** + * Sets the URL that this iframe will load content from. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setFrameUrl()}. + * @param string the URL that this iframe will load content from + * @see setFrameUrl + * @since 3.1.0 + */ + public function setData($value) + { + $this->setFrameUrl($value); + } + /** * @return TInlineFrameScrollBars the visibility and position of scroll bars in an iframe. Defaults to TInlineFrameScrollBars::Auto. */ diff --git a/framework/Web/UI/WebControls/TLabel.php b/framework/Web/UI/WebControls/TLabel.php index 5d213529..7821580a 100644 --- a/framework/Web/UI/WebControls/TLabel.php +++ b/framework/Web/UI/WebControls/TLabel.php @@ -30,7 +30,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TLabel extends TWebControl +class TLabel extends TWebControl implements IDataRenderer { private $_forControl=''; @@ -107,6 +107,32 @@ class TLabel extends TWebControl $this->setViewState('Text',$value,''); } + /** + * Returns the text value of the label. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getText()}. + * @return string the text value of the label + * @see getText + * @since 3.1.0 + */ + public function getData() + { + return $this->getText(); + } + + /** + * Sets the text value of the label. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setText()}. + * @param string the text value of the label + * @see setText + * @since 3.1.0 + */ + public function setData($value) + { + $this->setText($value); + } + /** * @return string the associated control ID */ diff --git a/framework/Web/UI/WebControls/TLinkButton.php b/framework/Web/UI/WebControls/TLinkButton.php index ffa83d02..b193226e 100644 --- a/framework/Web/UI/WebControls/TLinkButton.php +++ b/framework/Web/UI/WebControls/TLinkButton.php @@ -54,7 +54,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl +class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer { /** * @return string tag name of the button @@ -182,6 +182,32 @@ class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonC $this->setViewState('Text',$value,''); } + /** + * Returns the caption of the button. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getText()}. + * @return string caption of the button. + * @see getText + * @since 3.1.0 + */ + public function getData() + { + return $this->getText(); + } + + /** + * Sets the caption of the button. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setText()}. + * @param string caption of the button + * @see setText + * @since 3.1.0 + */ + public function setData($value) + { + $this->setText($value); + } + /** * @return string the command name associated with the {@link onCommand OnCommand} event. */ diff --git a/framework/Web/UI/WebControls/TLiteral.php b/framework/Web/UI/WebControls/TLiteral.php index 02061304..3ebb4039 100644 --- a/framework/Web/UI/WebControls/TLiteral.php +++ b/framework/Web/UI/WebControls/TLiteral.php @@ -31,7 +31,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TLiteral extends TControl +class TLiteral extends TControl implements IDataRenderer { /** * @return string the static text of the TLiteral @@ -50,6 +50,32 @@ class TLiteral extends TControl $this->setViewState('Text',$value,''); } + /** + * Returns the static text of the TLiteral. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getText()}. + * @return string the static text of the TLiteral + * @see getText + * @since 3.1.0 + */ + public function getData() + { + return $this->getText(); + } + + /** + * Sets the static text of the TLiteral. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setText()}. + * @param string the static text of the TLiteral + * @see setText + * @since 3.1.0 + */ + public function setData($value) + { + $this->setText($value); + } + /** * @return boolean whether the rendered text should be HTML-encoded. Defaults to false. */ diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php index 046e0a88..f6093667 100644 --- a/framework/Web/UI/WebControls/TRepeater.php +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -17,52 +17,74 @@ Prado::using('System.Web.UI.WebControls.TDataBoundControl'); Prado::using('System.Util.TDataFieldAccessor'); /** - * TRepeater class + * TRepeater class. * - * TRepeater displays its content defined in templates repeatedly based on - * the given data specified by the {@link setDataSource DataSource} or - * {@link setDataSourceID DataSourceID} property. The templates can contain - * static text, controls and special tags. + * TRepeater displays its content repeatedly based on the data fetched from + * {@link setDataSource DataSource}. + * The repeated contents in TRepeater are called items, which are controls and + * can be accessed through {@link getItems Items}. When {@link dataBind()} is invoked, + * TRepeater creates an item for each row of data and binds the data row to the item. + * Optionally, a repeater can have a header, a footer and/or separators between items. * - * The {@link setHeaderTemplate HeaderTemplate} property specifies the content - * template that will be displayed at the beginning, while - * {@link setFooterTemplate FooterTemplate} at the end. - * If present, these two templates will only be rendered when the repeater is - * given non-empty data. In this case, for each data item the content defined - * by {@link setItemTemplate ItemTemplate} will be generated and displayed once. - * If {@link setAlternatingItemTemplate AlternatingItemTemplate} is not empty, - * then the corresponding content will be displayed alternatively with that - * in {@link setItemTemplate ItemTemplate}. The content in - * {@link setSeparatorTemplate SeparatorTemplate}, if not empty, will be - * displayed between items. + * The layout of the repeated contents are specified by inline templates. + * Repeater items, header, footer, etc. are being instantiated with the corresponding + * templates when data is being bound to the repeater. * - * Each repeater item has a {@link TRepeaterItem::getItemType type} - * which tells the position of the item in the repeater. An item in the header - * of the repeater is of type TListItemType::Header. A body item may be of either - * TListItemType::Item or TListItemType::AlternatingItem, depending whether the item - * index is odd or even. + * Since v3.1.0, the layout can also be by renderers. A renderer is a control class + * that can be instantiated as repeater items, header, etc. A renderer can thus be viewed + * as an external template (in fact, it can also be non-templated controls). * - * You can retrive the repeated contents by the {@link getItems Items} property. - * The header and footer items can be accessed by {@link getHeader Header} - * and {@link getFooter Footer} properties, respectively. + * A renderer can be any control class. + * -If the class implements {@link IDataRenderer}, the Data + * property will be set as the data row during databinding. Many PRADO controls + * implement this interface, such as {@link TLabel}, {@link TTextBox}, etc. + * - If the class implements {@link IItemDataRenderer}, the ItemIndex property will be set + * as the zero-based index of the item in the repeater item collection, and + * the ItemType property as the item's type (such as TListItemType::Item). + * {@link TRepeaterItemRenderer} may be used as the convenient base class which + * already implements {@link IDataItemRenderer}. * - * When TRepeater creates an item, it will raise an {@link onItemCreated OnItemCreated} - * so that you may customize the newly created item. - * When databinding is performed by TRepeater, for each item once it has finished - * databinding, an {@link onItemDataBound OnItemDataBound} event will be raised. + * The following properties are used to specify different types of template and renderer + * for a repeater: + * - {@link setItemTemplate ItemTemplate}, {@link setItemRenderer ItemRenderer}: + * for each repeated row of data + * - {@link setAlternatingItemTemplate AlternatingItemTemplate}, {@link setAlternatingItemRenderer AlternatingItemRenderer}: + * for each alternating row of data. If not set, {@link setItemTemplate ItemTemplate} or {@link setItemRenderer ItemRenderer} + * will be used instead. + * - {@link setHeaderTemplate HeaderTemplate}, {@link setHeaderRenderer HeaderRenderer}: + * for the repeater header. + * - {@link setFooterTemplate FooterTemplate}, {@link setFooterRenderer FooterRenderer}: + * for the repeater footer. + * - {@link setSeparatorTemplate SeparatorTemplate}, {@link setSeparatorRenderer SeparatorRenderer}: + * for content to be displayed between items. + * - {@link setEmptyTemplate EmptyTemplate}, {@link setEmptyRenderer EmptyRenderer}: + * used when data bound to the repeater is empty. + * + * If a content type is defined with both a template and a renderer, the latter takes precedence. + * + * When {@link dataBind()} is being called, TRepeater undergoes the following lifecycles for each row of data: + * - create item based on templates or renderers + * - set the row of data to the item + * - raise {@link onItemCreated OnItemCreated}: + * - add the item as a child control + * - call dataBind() of the item + * - raise {@link onItemDataBound OnItemDataBound}: * * TRepeater raises an {@link onItemCommand OnItemCommand} whenever a button control * within some repeater item raises a OnCommand event. Therefore, * you can handle all sorts of OnCommand event in a central place by * writing an event handler for {@link onItemCommand OnItemCommand}. * - * Note, the data bound to the repeater are reset to null after databinding. - * There are several ways to access the data associated with a repeater item: - * - Access the data in {@link onItemDataBound OnItemDataBound} event + * When a page containing a repeater is post back, the repeater will restore automatically + * all its contents, including items, header, footer and separators. + * However, the data row associated with each item will not be recovered and become null. + * To access the data, use one of the following ways: * - Use {@link getDataKeys DataKeys} to obtain the data key associated with * the specified repeater item and use the key to fetch the corresponding data * from some persistent storage such as DB. - * - Save the data in viewstate and get it back during postbacks. + * - Save the whole dataset in viewstate, which will restore the dataset automatically upon postback. + * Be aware though, if the size of your dataset is big, your page size will become big. Some + * complex data may also have serializing problem if saved in viewstate. * * @author Qiang Xue * @version $Id$ @@ -110,14 +132,148 @@ class TRepeater extends TDataBoundControl implements INamingContainer */ private $_items=null; /** - * @var TRepeaterItem header item + * @var TControl header item */ private $_header=null; /** - * @var TRepeaterItem footer item + * @var TControl footer item */ private $_footer=null; + + /** + * @return string the class name for repeater items. Defaults to empty, meaning not set. + */ + public function getItemRenderer() + { + return $this->getViewState('ItemRenderer',''); + } + + /** + * Sets the item renderer class. + * + * If not empty, the class will be used to instantiate as repeater items. + * This property takes precedence over {@link getItemTemplate ItemTemplate}. + * + * @param string the renderer class name in namespace format. + * @see setItemTemplate + */ + public function setItemRenderer($value) + { + $this->setViewState('ItemRenderer',$value,''); + } + + /** + * @return string the class name for alternative repeater items. Defaults to empty, meaning not set. + */ + public function getAlternatingItemRenderer() + { + return $this->getViewState('AlternatingItemRenderer',''); + } + + /** + * Sets the alternative item renderer class. + * + * If not empty, the class will be used to instantiate as alternative repeater items. + * This property takes precedence over {@link getAlternatingItemTemplate AlternatingItemTemplate}. + * + * @param string the renderer class name in namespace format. + * @see setAlternatingItemTemplate + */ + public function setAlternatingItemRenderer($value) + { + $this->setViewState('AlternatingItemRenderer',$value,''); + } + + /** + * @return string the class name for repeater item separators. Defaults to empty, meaning not set. + */ + public function getSeparatorRenderer() + { + return $this->getViewState('SeparatorRenderer',''); + } + + /** + * Sets the repeater item separator renderer class. + * + * If not empty, the class will be used to instantiate as repeater item separators. + * This property takes precedence over {@link getSeparatorTemplate SeparatorTemplate}. + * + * @param string the renderer class name in namespace format. + * @see setSeparatorTemplate + */ + public function setSeparatorRenderer($value) + { + $this->setViewState('SeparatorRenderer',$value,''); + } + + /** + * @return string the class name for repeater header item. Defaults to empty, meaning not set. + */ + public function getHeaderRenderer() + { + return $this->getViewState('HeaderRenderer',''); + } + + /** + * Sets the repeater header renderer class. + * + * If not empty, the class will be used to instantiate as repeater header item. + * This property takes precedence over {@link getHeaderTemplate HeaderTemplate}. + * + * @param string the renderer class name in namespace format. + * @see setHeaderTemplate + */ + public function setHeaderRenderer($value) + { + $this->setViewState('HeaderRenderer',$value,''); + } + + /** + * @return string the class name for repeater footer item. Defaults to empty, meaning not set. + */ + public function getFooterRenderer() + { + return $this->getViewState('FooterRenderer',''); + } + + /** + * Sets the repeater footer renderer class. + * + * If not empty, the class will be used to instantiate as repeater footer item. + * This property takes precedence over {@link getFooterTemplate FooterTemplate}. + * + * @param string the renderer class name in namespace format. + * @see setFooterTemplate + */ + public function setFooterRenderer($value) + { + $this->setViewState('FooterRenderer',$value,''); + } + + /** + * @return string the class name for empty repeater item. Defaults to empty, meaning not set. + */ + public function getEmptyRenderer() + { + return $this->getViewState('EmptyRenderer',''); + } + + /** + * Sets the repeater empty renderer class. + * + * The empty renderer is created as the child of the repeater + * if data bound to the repeater is empty. + * This property takes precedence over {@link getEmptyTemplate EmptyTemplate}. + * + * @param string the renderer class name in namespace format. + * @see setEmptyTemplate + */ + public function setEmptyRenderer($value) + { + $this->setViewState('EmptyRenderer',$value,''); + } + /** * @return ITemplate the template for repeater items */ @@ -239,7 +395,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer } /** - * @return TRepeaterItem the header item + * @return TControl the header item */ public function getHeader() { @@ -247,7 +403,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer } /** - * @return TRepeaterItem the footer item + * @return TControl the footer item */ public function getFooter() { @@ -255,7 +411,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer } /** - * @return TRepeaterItemCollection list of {@link TRepeaterItem} controls + * @return TRepeaterItemCollection list of repeater item controls */ public function getItems() { @@ -294,66 +450,117 @@ class TRepeater extends TDataBoundControl implements INamingContainer } /** - * Creates a repeater item instance based on the item type and index. - * @param integer zero-based item index + * Creates a repeater item. + * This method invokes {@link createItem} to create a new repeater item. + * @param integer zero-based item index. * @param string item type, may be 'Header', 'Footer', 'Empty', 'Item', 'Separator', 'AlternatingItem'. - * @return TRepeaterItem created repeater item + * @return TControl the created item, null if item is not created */ - protected function createItem($itemIndex,$itemType) + private function createItemInternal($itemIndex,$itemType) { - return new TRepeaterItem($itemIndex,$itemType); + if(($item=$this->createItem($itemIndex,$itemType))!==null) + { + $param=new TRepeaterItemEventParameter($item); + $this->onItemCreated($param); + $this->getControls()->add($item); + return $item; + } + else + return null; } /** - * Creates a repeater item and does databinding if needed. + * Creates a repeater item and performs databinding. * This method invokes {@link createItem} to create a new repeater item. * @param integer zero-based item index. * @param string item type, may be 'Header', 'Footer', 'Empty', 'Item', 'Separator', 'AlternatingItem'. - * @param boolean whether to do databinding for the item * @param mixed data to be associated with the item - * @return TRepeaterItem the created item + * @return TControl the created item, null if item is not created */ - private function createItemInternal($itemIndex,$itemType,$dataBind,$dataItem) + private function createItemWithDataInternal($itemIndex,$itemType,$dataItem) { - $item=$this->createItem($itemIndex,$itemType); - $this->initializeItem($item); - $param=new TRepeaterItemEventParameter($item); - if($dataBind) + if(($item=$this->createItem($itemIndex,$itemType))!==null) { - $item->setDataItem($dataItem); + $param=new TRepeaterItemEventParameter($item); + if($item instanceof IDataRenderer) + $item->setData($dataItem); $this->onItemCreated($param); $this->getControls()->add($item); $item->dataBind(); $this->onItemDataBound($param); - $item->setDataItem(null); + return $item; } else - { - $this->onItemCreated($param); - $this->getControls()->add($item); - } - return $item; + return null; } /** - * Initializes a repeater item. - * The item is added as a child of the repeater and the corresponding - * template is instantiated within the item. - * @param TRepeaterItem item to be initialized + * Creates a repeater item instance based on the item type and index. + * @param integer zero-based item index + * @param string item type, may be 'Header', 'Footer', 'Empty', 'Item', 'Separator', 'AlternatingItem'. + * @return TControl created repeater item */ - protected function initializeItem($item) + protected function createItem($itemIndex,$itemType) { $template=null; - switch($item->getItemType()) + $classPath=null; + switch($itemType) { - case TListItemType::Header: $template=$this->_headerTemplate; break; - case TListItemType::Footer: $template=$this->_footerTemplate; break; - case TListItemType::Item : $template=$this->_itemTemplate; break; - case TListItemType::Separator : $template=$this->_separatorTemplate; break; - case TListItemType::AlternatingItem : $template=$this->_alternatingItemTemplate===null ? $this->_itemTemplate : $this->_alternatingItemTemplate; break; + case TListItemType::Item : + $classPath=$this->getItemRenderer(); + $template=$this->_itemTemplate; + break; + case TListItemType::AlternatingItem : + if(($classPath=$this->getAlternatingItemRenderer())==='') + $classPath=$this->getItemRenderer(); + $template=$this->_alternatingItemTemplate===null ? $this->_itemTemplate : $this->_alternatingItemTemplate; + break; + case TListItemType::Header : + $classPath=$this->getHeaderRenderer(); + $template=$this->_headerTemplate; + break; + case TListItemType::Footer : + $classPath=$this->getFooterRenderer(); + $template=$this->_footerTemplate; + break; + case TListItemType::Separator : + $classPath=$this->getSeparatorRenderer(); + $template=$this->_separatorTemplate; + break; + default: + throw new TInvalidDataValueException('repeater_itemtype_unknown',$itemType); } - if($template!==null) + if($classPath!=='') + { + $item=Prado::createComponent($classPath); + if($item instanceof IItemDataRenderer) + { + $item->setItemIndex($itemIndex); + $item->setItemType($itemType); + } + } + else if($template!==null) + { + $item=new TRepeaterItem; + $item->setItemIndex($itemIndex); + $item->setItemType($itemType); $template->instantiateIn($item); + } + else + $item=null; + + return $item; + } + + /** + * Creates empty repeater content. + */ + protected function createEmptyContent() + { + if(($classPath=$this->getEmptyRenderer())!=='') + $this->getControls()->add(Prado::createComponent($classPath)); + else if($this->_emptyTemplate!==null) + $this->_emptyTemplate->instantiateIn($this); } /** @@ -413,21 +620,19 @@ class TRepeater extends TDataBoundControl implements INamingContainer if(($itemCount=$this->getViewState('ItemCount',0))>0) { $items=$this->getItems(); - $hasSeparator=$this->_separatorTemplate!==null; - if($this->_headerTemplate!==null) - $this->_header=$this->createItemInternal(-1,TListItemType::Header,false,null); + $hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!==''; + $this->_header=$this->createItemInternal(-1,TListItemType::Header); for($i=0;$i<$itemCount;++$i) { if($hasSeparator && $i>0) - $this->createItemInternal($i-1,TListItemType::Separator,false,null); + $this->createItemInternal($i-1,TListItemType::Separator); $itemType=$i%2==0?TListItemType::Item : TListItemType::AlternatingItem; $items->add($this->createItemInternal($i,$itemType,false,null)); } - if($this->_footerTemplate!==null) - $this->_footer=$this->createItemInternal(-1,TListItemType::Footer,false,null); + $this->_footer=$this->createItemInternal(-1,TListItemType::Footer); } - else if($this->_emptyTemplate!==null) - $this->_emptyTemplate->instantiateIn($this); + else + $this->createEmptyContent(); $this->clearChildState(); } @@ -447,35 +652,32 @@ class TRepeater extends TDataBoundControl implements INamingContainer $items=$this->getItems(); $itemIndex=0; - $hasSeparator=$this->_separatorTemplate!==null; + $hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!==''; foreach($data as $key=>$dataItem) { if($keyField!=='') $keys->add($this->getDataFieldValue($dataItem,$keyField)); else $keys->add($key); - if($itemIndex===0 && $this->_headerTemplate!==null) - $this->_header=$this->createItemInternal(-1,TListItemType::Header,true,null); + if($itemIndex===0) + $this->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null); if($hasSeparator && $itemIndex>0) - $this->createItemInternal($itemIndex-1,TListItemType::Separator,true,null); + $this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null); $itemType=$itemIndex%2==0?TListItemType::Item : TListItemType::AlternatingItem; - $items->add($this->createItemInternal($itemIndex,$itemType,true,$dataItem)); + $items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem)); $itemIndex++; } - if($itemIndex>0 && $this->_footerTemplate!==null) - $this->_footer=$this->createItemInternal(-1,TListItemType::Footer,true,null); - if($itemIndex===0 && $this->_emptyTemplate!==null) - { - $this->_emptyTemplate->instantiateIn($this); - $this->dataBindChildren(); - } + if($itemIndex>0) + $this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null); + else + $this->createEmptyContent(); $this->setViewState('ItemCount',$itemIndex,0); } /** * This method overrides parent's implementation to handle * {@link onItemCommand OnItemCommand} event which is bubbled from - * {@link TRepeaterItem} child controls. + * repeater items and their child controls. * This method should only be used by control developers. * @param TControl the sender of the event * @param TEventParameter event parameter @@ -496,7 +698,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer * Raises OnItemCreated event. * This method is invoked after a repeater item is created and instantiated with * template, but before added to the page hierarchy. - * The {@link TRepeaterItem} control responsible for the event + * The repeater item control responsible for the event * can be determined from the event parameter. * If you override this method, be sure to call parent's implementation * so that event handlers have chance to respond to the event. @@ -510,7 +712,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer /** * Raises OnItemDataBound event. * This method is invoked right after an item is data bound. - * The {@link TRepeaterItem} control responsible for the event + * The repeater item control responsible for the event * can be determined from the event parameter. * If you override this method, be sure to call parent's implementation * so that event handlers have chance to respond to the event. @@ -524,11 +726,11 @@ class TRepeater extends TDataBoundControl implements INamingContainer /** * Raises OnItemCommand event. * This method is invoked after a button control in - * a template raises Command event. - * The {@link TRepeaterItem} control responsible for the event + * a template raises OnCommand event. + * The repeater control responsible for the event * can be determined from the event parameter. * The event parameter also contains the information about - * the initial sender of the Command event, command name + * the initial sender of the OnCommand event, command name * and command parameter. * You may override this method to provide customized event handling. * Be sure to call parent's implementation so that @@ -572,22 +774,22 @@ class TRepeater extends TDataBoundControl implements INamingContainer class TRepeaterItemEventParameter extends TEventParameter { /** - * The TRepeaterItem control responsible for the event. - * @var TRepeaterItem + * The repeater item control responsible for the event. + * @var TControl */ private $_item=null; /** * Constructor. - * @param TRepeaterItem repeater item related with the corresponding event + * @param TControl repeater item related with the corresponding event */ - public function __construct(TRepeaterItem $item) + public function __construct($item) { $this->_item=$item; } /** - * @return TRepeaterItem repeater item related with the corresponding event + * @return TControl repeater item related with the corresponding event */ public function getItem() { @@ -613,17 +815,17 @@ class TRepeaterItemEventParameter extends TEventParameter class TRepeaterCommandEventParameter extends TCommandEventParameter { /** - * @var TRepeaterItem the TRepeaterItem control responsible for the event. + * @var TControl the repeater item control responsible for the event. */ private $_item=null; /** - * @var TControl the control originally raises the Command event. + * @var TControl the control originally raises the OnCommand event. */ private $_source=null; /** * Constructor. - * @param TRepeaterItem repeater item responsible for the event + * @param TControl repeater item responsible for the event * @param TControl original event sender * @param TCommandEventParameter original event parameter */ @@ -635,7 +837,7 @@ class TRepeaterCommandEventParameter extends TCommandEventParameter } /** - * @return TRepeaterItem the TRepeaterItem control responsible for the event. + * @return TControl the repeater item control responsible for the event. */ public function getItem() { @@ -643,7 +845,7 @@ class TRepeaterCommandEventParameter extends TCommandEventParameter } /** - * @return TControl the control originally raises the Command event. + * @return TControl the control originally raises the OnCommand event. */ public function getCommandSource() { @@ -665,34 +867,153 @@ class TRepeaterCommandEventParameter extends TCommandEventParameter * @package System.Web.UI.WebControls * @since 3.0 */ -class TRepeaterItem extends TControl implements INamingContainer +class TRepeaterItem extends TControl implements INamingContainer, IItemDataRenderer { /** * index of the data item in the Items collection of repeater */ - private $_itemIndex=''; + private $_itemIndex; /** * type of the TRepeaterItem * @var TListItemType */ private $_itemType; /** - * value of the data item + * data associated with this item * @var mixed */ - private $_dataItem=null; + private $_data; /** - * Constructor. - * @param integer zero-based index of the item in the item collection of repeater - * @param TListItemType item type + * @return TListItemType item type + */ + public function getItemType() + { + return $this->_itemType; + } + + /** + * @param TListItemType item type. + */ + public function setItemType($value) + { + $this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType'); + } + + /** + * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection. + * If the item is not in the collection (e.g. it is a header item), it returns -1. + * @return integer zero-based index of the item. + */ + public function getItemIndex() + { + return $this->_itemIndex; + } + + /** + * Sets the zero-based index for the item. + * If the item is not in the item collection (e.g. it is a header item), -1 should be used. + * @param integer zero-based index of the item. + */ + public function setItemIndex($value) + { + $this->_itemIndex=TPropertyValue::ensureInteger($value); + } + + /** + * @return mixed data associated with the item + */ + public function getData() + { + return $this->_data; + } + + /** + * @param mixed data to be associated with the item + */ + public function setData($value) + { + $this->_data=$value; + } + + /** + * This property is deprecated since v3.1.0. + * @return mixed data associated with the item + * @deprecated deprecated since v3.1.0. Use {@link getData} instead. + */ + public function getDataItem() + { + return $this->getData(); + } + + /** + * This property is deprecated since v3.1.0. + * @param mixed data to be associated with the item + * @deprecated deprecated since version 3.1.0. Use {@link setData} instead. */ - public function __construct($itemIndex,$itemType) + public function setDataItem($value) { - $this->_itemIndex=$itemIndex; - $this->setItemType($itemType); + return $this->setData($value); } + /** + * 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) + { + $this->raiseBubbleEvent($this,new TRepeaterCommandEventParameter($this,$sender,$param)); + return true; + } + else + return false; + } +} + + +/** + * TRepeaterItemRenderer class + * + * TRepeaterItemRenderer can be used as a convenient base class to + * define an item renderer class for {@link TRepeater}. + * that implements + * + * Because TRepeaterItemRenderer extends from {@link TTemplateControl}, derived child classes + * can have templates to define their presentational layout. + * + * TRepeaterItemRenderer implements {@link IItemDataRenderer} interface, + * which enables the following properties that are related with data-bound controls: + * - {@link getItemIndex ItemIndex}: zero-based index of this control in the repeater item collection. + * - {@link getItemType ItemType}: item type of this control, such as TListItemType::AlternatingItem + * - {@link getData Data}: data associated with this control + + * @author Qiang Xue + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.0 + */ +class TRepeaterItemRenderer extends TTemplateControl implements IItemDataRenderer +{ + /** + * index of the data item in the Items collection of repeater + */ + private $_itemIndex; + /** + * type of the TRepeaterItem + * @var TListItemType + */ + private $_itemType; + /** + * data associated with this item + * @var mixed + */ + private $_data; + /** * @return TListItemType item type */ @@ -710,32 +1031,44 @@ class TRepeaterItem extends TControl implements INamingContainer } /** - * @return integer zero-based index of the item in the item collection of repeater + * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection. + * If the item is not in the collection (e.g. it is a header item), it returns -1. + * @return integer zero-based index of the item. */ public function getItemIndex() { return $this->_itemIndex; } + /** + * Sets the zero-based index for the item. + * If the item is not in the item collection (e.g. it is a header item), -1 should be used. + * @param integer zero-based index of the item. + */ + public function setItemIndex($value) + { + $this->_itemIndex=TPropertyValue::ensureInteger($value); + } + /** * @return mixed data associated with the item */ - public function getDataItem() + public function getData() { - return $this->_dataItem; + return $this->_data; } /** * @param mixed data to be associated with the item */ - public function setDataItem($value) + public function setData($value) { - $this->_dataItem=$value; + $this->_data=$value; } /** * This method overrides parent's implementation by wrapping event parameter - * for Command event with item information. + * 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. @@ -752,6 +1085,7 @@ class TRepeaterItem extends TControl implements INamingContainer } } + /** * TRepeaterItemCollection class. * @@ -766,17 +1100,17 @@ class TRepeaterItemCollection extends TList { /** * Inserts an item at the specified position. - * This overrides the parent implementation by inserting only TRepeaterItem. + * This overrides the parent implementation by inserting only objects that are descendant of {@link TControl}. * @param integer the speicified position. - * @param mixed new item - * @throws TInvalidDataTypeException if the item to be inserted is not a TRepeaterItem. + * @param TControl new item + * @throws TInvalidDataTypeException if the item to be inserted is not a control. */ public function insertAt($index,$item) { - if($item instanceof TRepeaterItem) + if($item instanceof TControl) parent::insertAt($index,$item); else - throw new TInvalidDataTypeException('repeateritemcollection_repeateritem_required'); + throw new TInvalidDataTypeException('repeateritemcollection_item_invalid'); } } diff --git a/framework/Web/UI/WebControls/TTableCell.php b/framework/Web/UI/WebControls/TTableCell.php index dad2e69b..a0a10fde 100644 --- a/framework/Web/UI/WebControls/TTableCell.php +++ b/framework/Web/UI/WebControls/TTableCell.php @@ -32,7 +32,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TTableCell extends TWebControl +class TTableCell extends TWebControl implements IDataRenderer { /** * @return string tag name for the table cell @@ -166,6 +166,32 @@ class TTableCell extends TWebControl $this->setViewState('Text',$value,''); } + /** + * Returns the text content of the table cell. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getText()}. + * @return string the text content of the table cell. + * @see getText + * @since 3.1.0 + */ + public function getData() + { + return $this->getText(); + } + + /** + * Sets the text content of the table cell. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setText()}. + * @param string the text content of the table cell. + * @see setText + * @since 3.1.0 + */ + public function setData($value) + { + $this->setText($value); + } + /** * Adds attributes to renderer. * @param THtmlWriter the renderer diff --git a/framework/Web/UI/WebControls/TTextBox.php b/framework/Web/UI/WebControls/TTextBox.php index e8ad92db..047a3084 100644 --- a/framework/Web/UI/WebControls/TTextBox.php +++ b/framework/Web/UI/WebControls/TTextBox.php @@ -48,7 +48,7 @@ * @package System.Web.UI.WebControls * @since 3.0 */ -class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable +class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer { /** * Default number of rows (for MultiLine text box) @@ -423,6 +423,32 @@ class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable $this->_safeText = null; } + /** + * Returns the text content of the TTextBox control. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getText()}. + * @return string the text content of the TTextBox control. + * @see getText + * @since 3.1.0 + */ + public function getData() + { + return $this->getText(); + } + + /** + * Sets the text content of the TTextBox control. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setText()}. + * @param string the text content of the TTextBox control. + * @see setText + * @since 3.1.0 + */ + public function setData($value) + { + $this->setText($value); + } + /** * @return string safe text content with javascript stripped off */ diff --git a/framework/interfaces.php b/framework/interfaces.php index f37325c8..48164dc0 100644 --- a/framework/interfaces.php +++ b/framework/interfaces.php @@ -322,4 +322,27 @@ interface ICallbackEventHandler public function raiseCallbackEvent($eventArgument); } +/** + * IDataRenderer interface. + * + * If a control wants to be used a renderer for another data-bound control, + * this interface must be implemented. + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.1 + */ +interface IDataRenderer +{ + /** + * @return mixed the data bound to this object + */ + public function getData(); + + /** + * @param mixed the data to be bound to this object + */ + public function setData($value); +} ?> \ No newline at end of file -- cgit v1.2.3