From 5a63c2c1989ed9fdcf8fbe00ec8161934768daf3 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sat, 14 Jan 2006 03:30:53 +0000 Subject: Added TBaseDataList (nearly completed). --- framework/Web/UI/WebControls/TCheckBoxList.php | 34 +- framework/Web/UI/WebControls/TDataList.php | 1091 ++++++++++++++++++++++++ framework/Web/UI/WebControls/TRepeatInfo.php | 59 +- framework/Web/UI/WebControls/TRepeater.php | 89 +- framework/Web/UI/WebControls/TStyle.php | 1 - 5 files changed, 1163 insertions(+), 111 deletions(-) create mode 100644 framework/Web/UI/WebControls/TDataList.php (limited to 'framework/Web/UI') diff --git a/framework/Web/UI/WebControls/TCheckBoxList.php b/framework/Web/UI/WebControls/TCheckBoxList.php index 28ab11ea..168c7ef0 100644 --- a/framework/Web/UI/WebControls/TCheckBoxList.php +++ b/framework/Web/UI/WebControls/TCheckBoxList.php @@ -101,19 +101,6 @@ class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingCont return new TTableStyle; } - /** - * @return TRepeatInfo repeat information (primarily used by control developers) - */ - protected function getRepeatInfo() - { - if(($repeatInfo=$this->getViewState('RepeatInfo',null))===null) - { - $repeatInfo=new TRepeatInfo; - $this->setViewState('RepeatInfo',$repeatInfo,null); - } - return $repeatInfo; - } - /** * @return string the alignment of the text caption, defaults to 'Right'. */ @@ -131,6 +118,20 @@ class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingCont $this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,array('Left','Right')),'Right'); } + + /** + * @return TRepeatInfo repeat information (primarily used by control developers) + */ + protected function getRepeatInfo() + { + if(($repeatInfo=$this->getViewState('RepeatInfo',null))===null) + { + $repeatInfo=new TRepeatInfo; + $this->setViewState('RepeatInfo',$repeatInfo,null); + } + return $repeatInfo; + } + /** * @return integer the number of columns that the list should be displayed with. Defaults to 0 meaning not set. */ @@ -140,7 +141,6 @@ class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingCont } /** - * Sets the number of columns that the list should be displayed with. * @param integer the number of columns that the list should be displayed with. */ public function setRepeatColumns($value) @@ -157,8 +157,7 @@ class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingCont } /** - * Sets the direction of traversing the list (Vertical, Horizontal) - * @param string the direction of traversing the list + * @param string the direction (Vertical, Horizontal) of traversing the list */ public function setRepeatDirection($value) { @@ -174,7 +173,6 @@ class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingCont } /** - * Sets how the list should be displayed, using table or using line breaks (Table, Flow) * @param string how the list should be displayed, using table or using line breaks (Table, Flow) */ public function setRepeatLayout($value) @@ -259,7 +257,7 @@ class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingCont * @param integer index of the item being rendered * @return null */ - public function getItemStyle($itemType,$index) + public function generateItemStyle($itemType,$index) { return null; } diff --git a/framework/Web/UI/WebControls/TDataList.php b/framework/Web/UI/WebControls/TDataList.php new file mode 100644 index 00000000..666a344a --- /dev/null +++ b/framework/Web/UI/WebControls/TDataList.php @@ -0,0 +1,1091 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TBaseDataList class + */ +Prado::using('System.Web.UI.WebControls.TBaseDataList'); + + +/** + * TDataList class + * + * TDataList represents a data bound and updatable list control. + * + * It can be used to display and maintain a list of data items (rows, records). + * There are three kinds of layout determined by the RepeatLayout + * property. The Table layout displays a table and each table cell + * contains a data item. The Flow layout uses the span tag to organize + * the presentation of data items. The Raw layout displays all templated + * content without any additional decorations (therefore, you can use arbitrary + * complex UI layout). In case when the layout is Table or Flow, + * the number of table/flow columns is determined by the RepeatColumns + * property, and the data items are enumerated according to the RepeatDirection property. + * + * To use TDataList, sets its DataSource property and invokes dataBind() + * afterwards. The data will be populated into the TDataList and saved as data items. + * A data item can be at one of three states: normal, selected and edit. + * The state determines which template is used to display the item. + * In particular, data items are displayed using the following templates, + * ItemTemplate, AlternatingItemTemplate, + * SelectedItemTemplate, EditItemTemplate. In addition, the + * HeaderTemplate, FooterTemplate, and SeparatorTemplate + * can be used to decorate the overall presentation. + * + * To change the state of a data item, set either the EditItemIndex property + * or the SelectedItemIndex property. + * + * When an item template contains a button control that raises an OnCommand + * event, the event will be bubbled up to the data list control. + * If the event's command name is recognizable by the data list control, + * a corresponding item event will be raised. The following item events will be + * raised upon a specific command: + * - OnEditCommand, edit + * - OnCancelCommand, cancel + * - OnSelectCommand, select + * - OnDeleteCommand, delete + * - OnUpdateCommand, update + * The data list will always raise an OnItemCommand + * upon its receiving a bubbled OnCommand event. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUser +{ + /** + * Number of seconds that a cached template will expire after + */ + const CACHE_EXPIRY=18000; + /** + * @var array in-memory cache of parsed templates + */ + private static $_templates=array(); + /** + * @var TDataListItemCollection item list + */ + private $_items=null; + /** + * @var string Various item templates + */ + private $_itemTemplate=''; + private $_alternatingItemTemplate=''; + private $_selectedItemTemplate=''; + private $_editItemTemplate=''; + private $_headerTemplate=''; + private $_footerTemplate=''; + private $_separatorTemplate=''; + + /** + * @return TDataListItemCollection item list + */ + public function getItems() + { + if(!$this->_items) + $this->_items=new TDataListItemCollection; + return $this->_items; + } + + /** + * @return integer number of items + */ + public function getItemCount() + { + return $this->_items?$this->_items->getCount():0; + } + + /** + * @return string the template for item + */ + public function getItemTemplate() + { + return $this->_itemTemplate; + } + + /** + * @param string the template for item + */ + public function setItemTemplate($value) + { + $this->_itemTemplate=$value; + } + + /** + * @return TTableItemStyle the style for item + */ + public function getItemStyle() + { + if(($style=$this->getViewState('ItemStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('ItemStyle',$style,null); + } + return $style; + } + + /** + * @return string the template for each alternating item + */ + public function getAlternatingItemTemplate() + { + return $this->_alternatingItemTemplate; + } + + /** + * @param string the template for each alternating item + */ + public function setAlternatingItemTemplate($value) + { + $this->_alternatingItemTemplate=$value; + } + + /** + * @return TTableItemStyle the style for each alternating item + */ + public function getAlternatingItemStyle() + { + if(($style=$this->getViewState('AlternatingItemStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('AlternatingItemStyle',$style,null); + } + return $style; + } + + /** + * @return TTableItemStyle the selected item template string + */ + public function getSelectedItemTemplate() + { + return $this->_selectedItemTemplate; + } + + /** + * @param string the selected item template + */ + public function setSelectedItemTemplate($value) + { + $this->_selectedItemTemplate=$value; + } + + /** + * @return TTableItemStyle the style for selected item + */ + public function getSelectedItemStyle() + { + if(($style=$this->getViewState('SelectedItemStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('SelectedItemStyle',$style,null); + } + return $style; + } + + /** + * @return string the edit item template string + */ + public function getEditItemTemplate() + { + return $this->_editItemTemplate; + } + + /** + * @param string the edit item template + */ + public function setEditItemTemplate($value) + { + $this->_editItemTemplate=$value; + } + + /** + * @return TTableItemStyle the style for edit item + */ + public function getEditItemStyle() + { + if(($style=$this->getViewState('EditItemStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('EditItemStyle',$style,null); + } + return $style; + } + + /** + * @return string the header template string + */ + public function getHeaderTemplate() + { + return $this->_headerTemplate; + } + + /** + * @param string the header template + */ + public function setHeaderTemplate($value) + { + $this->_headerTemplate=$value; + } + + /** + * @return TTableItemStyle the style for header + */ + public function getHeaderStyle() + { + if(($style=$this->getViewState('HeaderStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('HeaderStyle',$style,null); + } + return $style; + } + + /** + * @return string the footer template string + */ + public function getFooterTemplate() + { + return $this->_footerTemplate; + } + + /** + * @param string the footer template + */ + public function setFooterTemplate($value) + { + $this->_footerTemplate=$value; + } + + /** + * @return TTableItemStyle the style for footer + */ + public function getFooterStyle() + { + if(($style=$this->getViewState('FooterStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('FooterStyle',$style,null); + } + return $style; + } + + /** + * @return TTableItemStyle the separator template string + */ + public function getSeparatorTemplate() + { + return $this->_separatorTemplate; + } + + /** + * @param string the separator template + */ + public function setSeparatorTemplate($value) + { + $this->_separatorTemplate=$value; + } + + /** + * @return TTableItemStyle the style for separator + */ + public function getSeparatorStyle() + { + if(($style=$this->getViewState('SeparatorStyle',null))===null) + { + $style=new TTableItemStyle; + $this->setViewState('SeparatorStyle',$style,null); + } + return $style; + } + + /** + * @return integer the zero-based index of the selected item in {@link getItems Items}. + * A value -1 means no item selected. + */ + public function getSelectedItemIndex() + { + return $this->getViewState('SelectedItemIndex',-1); + } + + /** + * Selects an item by its index in {@link getItems Items}. + * Previously selected item will be un-selected. + * If the item to be selected is already in edit mode, it will remain in edit mode. + * If the index is less than 0, any existing selection will be cleared up. + * @param integer the selected item index + */ + public function setSelectedItemIndex($value) + { + if(($value=TPropertyValue::ensureInteger($value))<0) + $value=-1; + if(($current=$this->getSelectedItemIndex())!==$value) + { + $this->setViewState('SelectedItemIndex',$value,-1); + $items=$this->getItems(); + $itemCount=$items->getCount(); + if($current>=0 && $current<$itemCount) + { + $item=$items->itemAt($current); + if($item->getItemType()!=='EditItem') + $item->setItemType($current%2?'AlternatingItem':'Item'); + } + if($value>=0 && $value<$itemCount) + { + $item=$items->itemAt($value); + if($item->getItemType()!=='EditItem') + $item->setItemType('SelectedItem'); + } + } + } + + /** + * @return TDataListItem the selected item, null if no item is selected. + */ + public function getSelectedItem() + { + $index=$this->getSelectedItemIndex(); + $items=$this->getItems(); + if($index>=0 && $index<$items->getCount()) + return $items->itemAt($index); + else + return null; + } + + /** + * @return integer the zero-based index of the edit item in {@link getItems Items}. + * A value -1 means no item is in edit mode. + */ + public function getEditItemIndex() + { + return $this->getViewState('EditItemIndex',-1); + } + + /** + * Edits an item by its index in {@link getItems Items}. + * Previously editting item will change to normal item state. + * If the index is less than 0, any existing edit item will be cleared up. + * @param integer the edit item index + */ + public function setEditItemIndex($value) + { + if(($value=TPropertyValue::ensureInteger($value))<0) + $value=-1; + if(($current=$this->getEditItemIndex())!==$value) + { + $this->setViewState('EditItemIndex',$value,-1); + $items=$this->getItems(); + $itemCount=$items->getCount(); + if($current>=0 && $current<$itemCount) + $items->itemAt($current)->setItemType($current%2?'AlternatingItem':'Item'); + if($value>=0 && $value<$itemCount) + $items->itemAt($value)->setItemType('EditItem'); + } + } + + /** + * @return TDataListItem the edit item + */ + public function getEditItem() + { + $index=$this->getEditItemIndex(); + $items=$this->getItems(); + if($index>=0 && $index<$items->getCount()) + return $items->itemAt($index); + else + return null; + } + + /** + * @return boolean whether the header should be shown. Defaults to true. + */ + public function getShowHeader() + { + return $this->getViewState('ShowHeader',true); + } + + /** + * @param boolean whether to show header + */ + public function setShowHeader($value) + { + $this->setViewState('ShowHeader',TPropertyValue::ensureBoolean($value),true); + } + + /** + * @return boolean whether the footer should be shown. Defaults to true. + */ + public function getShowFooter() + { + return $this->getViewState('ShowFooter',true); + } + + /** + * @param boolean whether to show footer + */ + public function setShowFooter($value) + { + $this->setViewState('ShowFooter',TPropertyValue::ensureBoolean($value),true); + } + + /** + * @return TRepeatInfo repeat information (primarily used by control developers) + */ + protected function getRepeatInfo() + { + if(($repeatInfo=$this->getViewState('RepeatInfo',null))===null) + { + $repeatInfo=new TRepeatInfo; + $this->setViewState('RepeatInfo',$repeatInfo,null); + } + return $repeatInfo; + } + + /** + * @return integer the number of columns that the list should be displayed with. Defaults to 0 meaning not set. + */ + public function getRepeatColumns() + { + return $this->getRepeatInfo()->getRepeatColumns(); + } + + /** + * @param integer the number of columns that the list should be displayed with. + */ + public function setRepeatColumns($value) + { + $this->getRepeatInfo()->setRepeatColumns($value); + } + + /** + * @return string the direction of traversing the list, defaults to 'Vertical' + */ + public function getRepeatDirection() + { + return $this->getRepeatInfo()->getRepeatDirection(); + } + + /** + * @param string the direction (Vertical, Horizontal) of traversing the list + */ + public function setRepeatDirection($value) + { + $this->getRepeatInfo()->setRepeatDirection($value); + } + + /** + * @return string how the list should be displayed, using table or using line breaks. Defaults to 'Table'. + */ + public function getRepeatLayout() + { + return $this->getRepeatInfo()->getRepeatLayout(); + } + + /** + * @param string how the list should be displayed, using table or using line breaks (Table, Flow) + */ + public function setRepeatLayout($value) + { + $this->getRepeatInfo()->setRepeatLayout($value); + } + + /** + * Handles BubbleEvent. + * This method overrides parent's implementation to handle + * {@link onItemCommand ItemCommand} event which is bubbled from + * {@link TDataListItem} child controls. + * If the event parameter is {@link TDataListCommandEventParameter} and + * the command name is a recognized one, which includes 'select', 'edit', + * 'delete', 'update', and 'cancel' (case-insensitive), then a + * corresponding command event is also raised (such as {@link onEditCommand EditCommand}). + * This method should only be used by control developers. + * @param TControl the sender of the event + * @param TEventParameter event parameter + * @return boolean whether the event bubbling should stop here. + */ + protected function onBubbleEvent($sender,$param) + { + if($param instanceof TDataListCommandEventParameter) + { + $this->onItemCommand($param); + $command=$param->getCommandName(); + if(strcasecmp($command,'select')===0) + { + $this->setSelectedIndex($param->getItem()->getItemIndex()); + $this->onSelectedIndexChanged(null); + return true; + } + else if(strcasecmp($command,'edit')===0) + { + $this->onEditCommand($param); + return true; + } + else if(strcasecmp($command,'delete')===0) + { + $this->onDeleteCommand($param); + return true; + } + else if(strcasecmp($command,'update')===0) + { + $this->onUpdateCommand($param); + return true; + } + else if(strcasecmp($command,'cancel')===0) + { + $this->onCancelCommand($param); + return true; + } + } + return false; + } + + + /** + * Raises ItemCreated event. + * This method is invoked after a data list item is created and instantiated with + * template, but before added to the page hierarchy. + * The {@link TDataListItem} 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. + * @param TDataListItemEventParameter event parameter + */ + public function onItemCreated($param) + { + $this->raiseEvent('ItemCreated',$this,$param); + } + + /** + * Raises ItemDataBound event. + * This method is invoked right after an item is data bound. + * The {@link TDataListItem} 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. + * @param TDataListItemEventParameter event parameter + */ + public function onItemDataBound($param) + { + $this->raiseEvent('ItemDataBound',$this,$param); + } + + /** + * Raises ItemCommand event. + * This method is invoked when a child control of the data list + * raises an Command event. + * @param TDataListCommandEventParameter event parameter + */ + protected function onItemCommand($param) + { + $this->raiseEvent('ItemCommand',$this,$param); + } + + /** + * Raises SelectCommand event. + * This method is invoked when a child control of the data list + * raises an Command event and the command name is 'select' (case-insensitive). + * @param TDataListCommandEventParameter event parameter + */ + protected function onSelectCommand($param) + { + $this->raiseEvent('SelectCommand',$this,$param); + } + + /** + * Raises EditCommand event. + * This method is invoked when a child control of the data list + * raises an Command event and the command name is 'edit' (case-insensitive). + * @param TDataListCommandEventParameter event parameter + */ + protected function onEditCommand($param) + { + $this->raiseEvent('EditCommand',$this,$param); + } + + /** + * Raises DeleteCommand event. + * This method is invoked when a child control of the data list + * raises an Command event and the command name is 'delete' (case-insensitive). + * @param TDataListCommandEventParameter event parameter + */ + protected function onDeleteCommand($param) + { + $this->raiseEvent('DeleteCommand',$this,$param); + } + + /** + * Raises UpdateCommand event. + * This method is invoked when a child control of the data list + * raises an Command event and the command name is 'update' (case-insensitive). + * @param TDataListCommandEventParameter event parameter + */ + protected function onUpdateCommand($param) + { + $this->raiseEvent('UpdateCommand',$this,$param); + } + + /** + * Raises CancelCommand event. + * This method is invoked when a child control of the data list + * raises an Command event and the command name is 'cancel' (case-insensitive). + * @param TDataListCommandEventParameter event parameter + */ + protected function onCancelCommand($param) + { + $this->raiseEvent('CancelCommand',$this,$param); + } + + /** + * Returns a value indicating whether this control contains header item. + * This method is required by {@link IRepeatInfoUser} interface. + * @return boolean always false. + */ + public function getHasHeader() + { + return ($this->getShowHeader() && $this->_headerTemplate!=='') + } + + /** + * Returns a value indicating whether this control contains footer item. + * This method is required by {@link IRepeatInfoUser} interface. + * @return boolean always false. + */ + public function getHasFooter() + { + return ($this->getShowFooter() && $this->_footerTemplate!=='') + } + + /** + * Returns a value indicating whether this control contains separator items. + * This method is required by {@link IRepeatInfoUser} interface. + * @return boolean always false. + */ + public function getHasSeparators() + { + return $this->_separatorTemplate!==''; + } + + /** + * Returns a style used for rendering items. + * This method is required by {@link IRepeatInfoUser} interface. + * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager) + * @param integer index of the item being rendered + * @return TStyle item style + */ + public function generateItemStyle($itemType,$index) + { + if(($item=$this->getItem($itemType,$index))!==null && $item->getHasStyle()) + return $item->getStyle(); + else + return null; + } + + private function getItem($itemType,$index) + { + switch($itemType) + { + case 'Header': return $this->getControls()->itemAt(0); + case 'Footer': return $this->getControls()->itemAt($this->getControls()->getCount()-1); + case 'Item': + case 'AlternatingItem': + case 'SelectedItem': + case 'EditItem': + return $this->getItems()->itemAt($index); + case 'Separator': + $i=$index+$index+1; + if($this->_headerTemplate!=='') + $i++; + return $this->getControls->itemAt($i); + } + return null + } + + /** + * Initializes a data list item. + * The item is added as a child of the data list and the corresponding + * template is instantiated within the item. + * @param TRepeaterItem item to be initialized + */ + protected function initializeItem($item) + { + $tplContent=''; + switch($item->getItemType()) + { + case 'Header': $tplContent=$this->_headerTemplate; break; + case 'Footer': $tplContent=$this->_footerTemplate; break; + case 'Item': $tplContent=$this->_itemTemplate; break; + case 'AlternatingItem': + if($this->_alternatingItemTemplate!=='') + $tplContent=$this->_alternatingItemTemplate; + else + $tplContent=$this->_itemTemplate; + break; + case 'Separator': $tplContent=$this->_separatorTemplate; break; + case 'SelectedItem': + if($this->_selectedItemTemplate==='') + { + if($item->getItemIndex()%2 && $this->_alternatingItemTemplate!=='') + $tplContent=$this->_alternatingItemTemplate; + else + $tplContent=$this->_itemTemplate; + } + else + $tplContent=$this->_selectedItemTemplate; + break; + case 'EditItem': + if($this->_editItemTemplate==='') + { + if($item->getItemIndex()===$this->getSelectedIndex() && $this->_selectedItemTemplate!=='') + $tplContent=$this->_selectedItemTemplate; + else if($item->getItemIndex()%2 && $this->_alternatingItemTemplate!=='') + $tplContent=$this->_alternatingItemTemplate; + else + $tplContent=$this->_itemTemplate; + } + else + $tplContent=$this->_editItemTemplate; + default: break; + } + if($tplContent!=='') + $this->createTemplate($tplContent)->instantiateIn($item); + } + + protected function createTemplate($str) + { + $key=md5($str); + $contextPath=$this->getTemplateControl()->getTemplate()->getContextPath(); + if(($cache=$this->getApplication()->getCache())!==null) + { + if(($template=$cache->get($key))===null) + { + $template=new TTemplate($str,$contextPath); + $cache->set($key,$template,self::CACHE_EXPIRY); + } + } + else + { + if(isset(self::$_templates[$key])) + $template=self::$_templates[$key]; + else + { + $template=new TTemplate($str,$contextPath); + self::$_templates[$key]=$template; + } + } + return $template; + } + + /** + * Renders an item in the list. + * This method is required by {@link IRepeatInfoUser} interface. + * @param THtmlWriter writer for rendering purpose + * @param TRepeatInfo repeat information + * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager) + * @param integer zero-based index of the item in the item list + */ + public function renderItem($writer,$repeatInfo,$itemType,$index) + { + $item=$this->getItems()->itemAt($index); + if($item->getHasAttributes()) + $this->_repeatedControl->getAttributes()->copyFrom($item->getAttributes()); + else if($this->_repeatedControl->getHasAttributes()) + $this->_repeatedControl->getAttributes()->clear(); + $this->_repeatedControl->setID("$index"); + $this->_repeatedControl->setText($item->getText()); + $this->_repeatedControl->setChecked($item->getSelected()); + $this->_repeatedControl->setAttribute('value',$item->getValue()); + $this->_repeatedControl->setEnabled($this->_isEnabled && $item->getEnabled()); + $this->_repeatedControl->renderControl($writer); + } + + // how to save item state??? c.f. TRepeater + + /** + * Renders the checkbox list control. + * This method overrides the parent implementation. + * @param THtmlWriter writer for rendering purpose. + */ + protected function render($writer) + { + if($this->getItemCount()>0) + { + $this->_isEnabled=$this->getEnabled(true); + $repeatInfo=$this->getRepeatInfo(); + $accessKey=$this->getAccessKey(); + $tabIndex=$this->getTabIndex(); + $this->_repeatedControl->setTextAlign($this->getTextAlign()); + $this->_repeatedControl->setAccessKey($accessKey); + $this->_repeatedControl->setTabIndex($tabIndex); + $this->setAccessKey(''); + $this->setTabIndex(0); + $repeatInfo->renderRepeater($writer,$this); + $this->setAccessKey($accessKey); + $this->setTabIndex($tabIndex); + } + } +} + + +/** + * TDataListItemEventParameter class + * + * TDataListItemEventParameter encapsulates the parameter data for OnItemCreated + * event of TDataList controls. + * + * @author Qiang Xue + * @version v1.0, last update on 2004/08/13 21:44:52 + * @package System.Web.UI.WebControls + */ +class TDataListItemEventParameter extends TEventParameter +{ + /** + * The TDataListItem control responsible for the event. + * @var TDataListItem + */ + public $item=null; +} + +/** + * TDataListCommandEventParameter class + * + * TDataListCommandEventParameter encapsulates the parameter data for OnItemCommand + * event of TDataList controls. + * + * @author Qiang Xue + * @version v1.0, last update on 2004/08/13 21:44:52 + * @package System.Web.UI.WebControls + */ +class TDataListCommandEventParameter extends TCommandEventParameter +{ + /** + * The TDataListItem control responsible for the event. + * @var TDataListItem + */ + public $item=null; + /** + * The control originally raises the OnCommand event. + * @var TControl + */ + public $source=null; +} + + +class TDataListItemCollection extends TCollection +{ + protected $list=null; + + public function __construct($list) + { + parent::__construct(); + $this->list=$list; + } + + protected function onAddItem($item) + { + if($item instanceof TDataListItem) + { + $this->list->addBody($item); + return true; + } + else + return false; + } + + protected function onRemoveItem($item) + { + $this->list->getBodies()->remove($item); + } +} + + +/** + * TDataGridItem class + * + * A TDataGridItem control represents an item in the TDataGrid control, such + * as heading section, footer section, data item, or pager section. The + * item type can be determined by Type property. + * The data items are stored in the Items property of TDataGrid control. + * The index and data value of the item can be accessed via Index + * and Data properties, respectively. + * + * Since TDataGridItem inherits from TTableRow, you can also access + * the Cells property to get the table cells in the item. + * + * Namespace: System.Web.UI.WebControls + * + * Properties + * - ItemIndex, mixed + *
Gets or sets the index of the data item in the Items collection of datagrid. + * - Data, mixed + *
Gets or sets the value of the data item. + * - Type, mixed + *
Gets or sets the type of the item (Header, Footer, Item, AlternatingItem, EditItem, SelectedItem, Separator) + * + * @author Qiang Xue + * @version v1.0, last update on 2004/08/13 21:44:52 + * @package System.Web.UI.WebControls + */ +class TDataGridItem extends TTableRow +{ + /** + * Header + */ + const TYPE_HEADER='Header'; + /** + * Footer + */ + const TYPE_FOOTER='Footer'; + /** + * Data item + */ + const TYPE_ITEM='Item'; + /** + * Alternating data item + */ + const TYPE_ALTERNATING_ITEM='AlternatingItem'; + /** + * Selected item + */ + const TYPE_SELECTED_ITEM='SelectedItem'; + /** + * Edit item + */ + const TYPE_EDIT_ITEM='EditItem'; + /** + * Pager + */ + const TYPE_PAGER='Pager'; + /** + * index of the data item + * @var mixed + */ + private $index=''; + /** + * value of the data item + * @var mixed + */ + private $data=null; + /** + * type of the TDataGridItem + * @var string + */ + private $type=''; + + /** + * Constructor. + * Initializes the type to 'Item'. + */ + public function __construct() + { + $this->type=self::TYPE_ITEM; + parent::__construct(); + } + + /** + * @return mixed the index of the data item + */ + public function getItemIndex() + { + return $this->index; + } + + /** + * Sets the index of the data item + * @param mixed the data item index + */ + public function setItemIndex($value) + { + $this->index=$value; + } + + /** + * @return mixed the value of the data item + */ + public function getData() + { + return $this->data; + } + + /** + * Sets the value of the data item + * @param mixed the value of the data item + */ + public function setData($value) + { + $this->data=$value; + } + + /** + * @return string the item type + */ + public function getType() + { + return $this->type; + } + + /** + * Sets the item type + * @param string the item type + */ + public function setType($value) + { + $this->type=$value; + } + + /** + * Handles OnBubbleEvent. + * This method overrides parent's implementation to bubble + * OnItemCommand event if an OnCommand + * event is bubbled from a child control. + * This method should only be used by control developers. + * @param TControl the sender of the event + * @param TEventParameter event parameter + * @return boolean whether the event bubbling should stop here. + */ + protected function onBubbleEvent($sender,$param) + { + if($param instanceof TCommandEventParameter) + { + $ce=new TDataGridCommandEventParameter; + $ce->name=$param->name; + $ce->parameter=$param->parameter; + $ce->source=$sender; + $ce->item=$this; + $this->raiseBubbleEvent($this,$ce); + return true; + } + else + return false; + } + + /** + * Renders the body content of this table. + * @return string the rendering result + */ + protected function renderBody() + { + $content="\n"; + $cols=$this->getParent()->getColumns(); + $n=$cols->length(); + foreach($this->getCells() as $index=>$cell) + { + if($cell->isVisible()) + { + if(!isset($cols[$index]) || $cols[$index]->isVisible() || $this->getType()===self::TYPE_PAGER) + $content.=$cell->render()."\n"; + } + } + return $content; + } +} + +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TRepeatInfo.php b/framework/Web/UI/WebControls/TRepeatInfo.php index 40787bb4..ce6efe8d 100644 --- a/framework/Web/UI/WebControls/TRepeatInfo.php +++ b/framework/Web/UI/WebControls/TRepeatInfo.php @@ -42,7 +42,7 @@ interface IRepeatInfoUser * @param integer zero-based index of the current rendering item. * @return TStyle CSS style used for rendering items (including header, footer and separators) */ - public function getItemStyle($itemType,$index); + public function generateItemStyle($itemType,$index); /** * Renders an item. * @param THtmlWriter writer for the rendering purpose @@ -71,14 +71,6 @@ interface IRepeatInfoUser */ class TRepeatInfo extends TComponent { - /** - * @var string caption of the table used to organize the repeated items - */ - private $_caption=''; - /** - * @var string alignment of the caption of the table used to organize the repeated items - */ - private $_captionAlign='NotSet'; /** * @var integer number of columns that the items should be arranged in */ @@ -92,39 +84,6 @@ class TRepeatInfo extends TComponent */ private $_repeatLayout='Table'; - /** - * @return string caption of the table layout - */ - public function getCaption() - { - return $this->_caption; - } - - /** - * @param string caption of the table layout - */ - public function setCaption($value) - { - $this->_caption=$value; - } - - /** - * @return string alignment of the caption of the table layout. Defaults to 'NotSet'. - */ - public function getCaptionAlign() - { - return $this->_captionAlign; - } - - /** - * @return string alignment of the caption of the table layout. - * Valid values include 'NotSet','Top','Bottom','Left','Right'. - */ - public function setCaptionAlign($value) - { - $this->_captionAlign=TPropertyValue::ensureEnum($value,array('NotSet','Top','Bottom','Left','Right')); - } - /** * @return integer the number of columns that the repeated items should be displayed in. Defaults to 0, meaning not set. */ @@ -138,7 +97,9 @@ class TRepeatInfo extends TComponent */ public function setRepeatColumns($value) { - $this->_repeatColumns=TPropertyValue::ensureInteger($value); + if(($value=TPropertyValue::ensureInteger($value))<0) + throw new TInvalidDataValueException('repeatinfo_repeatcolumns_invalid'); + $this->_repeatColumns=$value; } /** @@ -232,7 +193,7 @@ class TRepeatInfo extends TComponent { if($column==0) $writer->renderBeginTag('tr'); - if(($style=$user->getItemStyle('Item',$i))!==null) + if(($style=$user->generateItemStyle('Item',$i))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Item',$i); @@ -240,7 +201,7 @@ class TRepeatInfo extends TComponent $writer->writeLine(); if($hasSeparators && $i!=$itemCount-1) { - if(($style=$user->getItemStyle('Separator',$i))!==null) + if(($style=$user->generateItemStyle('Separator',$i))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Separator',$i); @@ -337,7 +298,7 @@ class TRepeatInfo extends TComponent if($index>=$itemCount) continue; $renderedItems++; - if(($style=$user->getItemStyle('Item',$index))!==null) + if(($style=$user->generateItemStyle('Item',$index))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Item',$index); @@ -352,7 +313,7 @@ class TRepeatInfo extends TComponent $writer->renderEndTag(); $writer->renderBeginTag('tr'); } - if(($style=$user->getItemStyle('Separator',$index))!==null) + if(($style=$user->generateItemStyle('Separator',$index))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Separator',$index); @@ -431,7 +392,7 @@ class TRepeatInfo extends TComponent if($columns>1) $writer->addAttribute('colspan',"$columns"); $writer->addAttribute('scope','col'); - if(($style=$user->getItemStyle('Header',-1))!==null) + if(($style=$user->generateItemStyle('Header',-1))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('th'); $user->renderItem($writer,$this,'Header',-1); @@ -461,7 +422,7 @@ class TRepeatInfo extends TComponent $writer->renderBeginTag('tr'); if($columns>1) $writer->addAttribute('colspan',"$columns"); - if(($style=$user->getItemStyle('Footer',-1))!==null) + if(($style=$user->generateItemStyle('Footer',-1))!==null) $style->addAttributesToRender($writer); $writer->renderBeginTag('td'); $user->renderItem($writer,$this,'Footer',-1); diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php index d0d513b0..664faa68 100644 --- a/framework/Web/UI/WebControls/TRepeater.php +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -48,6 +48,10 @@ class TRepeater extends TDataBoundControl implements INamingContainer * Number of seconds that a cached template will expire after */ const CACHE_EXPIRY=18000; + /** + * @var array in-memory cache of parsed templates + */ + private static $_templates=array(); /** * @var string template for each item */ @@ -80,10 +84,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer * @var TRepeaterItem footer item */ private $_footer=null; - /** - * @var array in-memory cache of parsed templates - */ - private static $_templates=array(); /** * No body content should be added to repeater. @@ -268,29 +268,32 @@ class TRepeater extends TDataBoundControl implements INamingContainer break; } if($tplContent!=='') + $this->createTemplate($tplContent)->instantiateIn($item); + } + + protected function createTemplate($str) + { + $key=md5($str); + $contextPath=$this->getTemplateControl()->getTemplate()->getContextPath(); + if(($cache=$this->getApplication()->getCache())!==null) { - $key=md5($tplContent); - $contextPath=$this->getTemplateControl()->getTemplate()->getContextPath(); - if(($cache=$this->getApplication()->getCache())!==null) + if(($template=$cache->get($key))===null) { - if(($template=$cache->get($key))===null) - { - $template=new TTemplate($tplContent,$contextPath); - $cache->set($key,$template,self::CACHE_EXPIRY); - } + $template=new TTemplate($str,$contextPath); + $cache->set($key,$template,self::CACHE_EXPIRY); } + } + else + { + if(isset(self::$_templates[$key])) + $template=self::$_templates[$key]; else { - if(isset(self::$_templates[$key])) - $template=self::$_templates[$key]; - else - { - $template=new TTemplate($tplContent,$contextPath); - self::$_templates[$key]=$template; - } + $template=new TTemplate($str,$contextPath); + self::$_templates[$key]=$template; } - $template->instantiateIn($item); } + return $template; } /** @@ -386,14 +389,35 @@ class TRepeater extends TDataBoundControl implements INamingContainer $this->setViewState('ItemCount',$itemIndex,0); } + /** + * Handles BubbleEvent. + * This method overrides parent's implementation to handle + * {@link onItemCommand ItemCommand} event which is bubbled from + * {@link TRepeaterItem} child controls. + * This method should only be used by control developers. + * @param TControl the sender of the event + * @param TEventParameter event parameter + * @return boolean whether the event bubbling should stop here. + */ + protected function onBubbleEvent($sender,$param) + { + if($param instanceof TRepeaterCommandEventParameter) + { + $this->onItemCommand($param); + return true; + } + else + return false; + } + /** * Raises ItemCreated 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 + * 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. - * can be determined from the event parameter. * @param TRepeaterItemEventParameter event parameter */ protected function onItemCreated($param) @@ -405,9 +429,9 @@ class TRepeater extends TDataBoundControl implements INamingContainer * Raises ItemDataBound event. * This method is invoked right after an item is data bound. * The {@link TRepeaterItem} 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. - * can be determined from the event parameter. * @param TRepeaterItemEventParameter event parameter */ protected function onItemDataBound($param) @@ -415,27 +439,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer $this->raiseEvent('ItemDataBound',$this,$param); } - /** - * Handles BubbleEvent. - * This method overrides parent's implementation to handle - * {@link onItemCommand ItemCommand} event which is bubbled from - * {@link TRepeaterItem} child controls. - * This method should only be used by control developers. - * @param TControl the sender of the event - * @param TEventParameter event parameter - * @return boolean whether the event bubbling should stop here. - */ - protected function onBubbleEvent($sender,$param) - { - if($param instanceof TRepeaterCommandEventParameter) - { - $this->onItemCommand($param); - return true; - } - else - return false; - } - /** * Raises ItemCommand event. * This method is invoked after a button control in diff --git a/framework/Web/UI/WebControls/TStyle.php b/framework/Web/UI/WebControls/TStyle.php index bc77bfcf..112efbca 100644 --- a/framework/Web/UI/WebControls/TStyle.php +++ b/framework/Web/UI/WebControls/TStyle.php @@ -617,5 +617,4 @@ class TTableItemStyle extends TStyle } } - ?> \ No newline at end of file -- cgit v1.2.3