diff options
Diffstat (limited to 'framework/Web/UI/WebControls')
91 files changed, 31557 insertions, 31557 deletions
diff --git a/framework/Web/UI/WebControls/TAccordion.php b/framework/Web/UI/WebControls/TAccordion.php index 22ff6b71..bfe3451d 100644 --- a/framework/Web/UI/WebControls/TAccordion.php +++ b/framework/Web/UI/WebControls/TAccordion.php @@ -1,744 +1,744 @@ -<?php
 -/**
 - * TAccordion class file.
 - *
 - * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -
 -/**
 - * Class TAccordion.
 - *
 - * TAccordion displays an accordion control. Users can click on the view headers to switch among
 - * different accordion views. Each accordion view is an independent panel that can contain arbitrary content.
 - *
 - * A TAccordion control consists of one or several {@link TAccordionView} controls representing the possible
 - * accordion views. At any time, only one accordion view is visible (active), which is specified by any of
 - * the following properties:
 - * - {@link setActiveViewIndex ActiveViewIndex} - the zero-based integer index of the view in the view collection.
 - * - {@link setActiveViewID ActiveViewID} - the text ID of the visible view.
 - * - {@link setActiveView ActiveView} - the visible view instance.
 - * If both {@link setActiveViewIndex ActiveViewIndex} and {@link setActiveViewID ActiveViewID}
 - * are set, the latter takes precedence.
 - *
 - * TAccordion uses CSS to specify the appearance of the accordion headers and panel. By default,
 - * an embedded CSS file will be published which contains the default CSS for TTabPanel.
 - * You may also use your own CSS file by specifying the {@link setCssUrl CssUrl} property.
 - * The following properties specify the CSS classes used for elements in a TAccordion:
 - * - {@link setCssClass CssClass} - the CSS class name for the outer-most div element (defaults to 'accordion');
 - * - {@link setHeaderCssClass HeaderCssClass} - the CSS class name for nonactive accordion div elements (defaults to 'accordion-header');
 - * - {@link setActiveHeaderCssClass ActiveHeaderCssClass} - the CSS class name for the active accordion div element (defaults to 'accordion-header-active');
 - * - {@link setViewCssClass ViewCssClass} - the CSS class for the div element enclosing view content (defaults to 'accordion-view');
 - *
 - * When the user clicks on a view header, the switch between the old visible view and the clicked one is animated.
 - * You can use the {@link setAnimationDuration AnimationDuration} property to set the animation length in seconds;
 - * it defaults to 1 second, and when set to 0 it will produce an immediate switch with no animation.
 - *
 - * The TAccordion auto-sizes itself to the largest of all views, so it can encompass all of them without scrolling.
 - * If you want to specify a fixed height (in pixels), use the {@link setViewHeight ViewHeight} property.
 - * When a TAccordion is nested inside another, it's adviced to manually specify a {@link setViewHeight ViewHeight} for the internal TAccordion
 - *
 - * To use TAccordion, write a template like following:
 - * <code>
 - * <com:TAccordion>
 - *   <com:TAccordionView Caption="View 1">
 - *     content for view 1
 - *   </com:TAccordionView>
 - *   <com:TAccordionView Caption="View 2">
 - *     content for view 2
 - *   </com:TAccordionView>
 - *   <com:TAccordionView Caption="View 3">
 - *     content for view 3
 - *   </com:TAccordionView>
 - * </com:TAccordion>
 - * </code>
 - *
 - * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu>
 - * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -
 -class TAccordion extends TWebControl implements IPostBackDataHandler
 -{
 -	private $_dataChanged=false;
 -
 -	/**
 -	 * @return string tag name for the control
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'div';
 -	}
 -
 -	/**
 -	 * Adds object parsed from template to the control.
 -	 * This method adds only {@link TAccordionView} objects into the {@link getViews Views} collection.
 -	 * All other objects are ignored.
 -	 * @param mixed object parsed from template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TAccordionView)
 -			$this->getControls()->add($object);
 -	}
 -
 -	/**
 -	 * Returns the index of the active accordion view.
 -	 * Note, this property may not return the correct index.
 -	 * To ensure the correctness, call {@link getActiveView()} first.
 -	 * @return integer the zero-based index of the active accordion view. If -1, it means no active accordion view. Default is 0 (the first view is active).
 -	 */
 -	public function getActiveViewIndex()
 -	{
 -		return $this->getViewState('ActiveViewIndex',0);
 -	}
 -
 -	/**
 -	 * @param integer the zero-based index of the current view in the view collection. -1 if no active view.
 -	 * @throws TInvalidDataValueException if the view index is invalid
 -	 */
 -	public function setActiveViewIndex($value)
 -	{
 -		$this->setViewState('ActiveViewIndex',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * Returns the ID of the active accordion view.
 -	 * Note, this property may not return the correct ID.
 -	 * To ensure the correctness, call {@link getActiveView()} first.
 -	 * @return string The ID of the active accordion view. Defaults to '', meaning not set.
 -	 */
 -	public function getActiveViewID()
 -	{
 -		return $this->getViewState('ActiveViewID','');
 -	}
 -
 -	/**
 -	 * @param string The ID of the active accordion view.
 -	 */
 -	public function setActiveViewID($value)
 -	{
 -		$this->setViewState('ActiveViewID',$value,'');
 -	}
 -
 -	/**
 -	 * Returns the currently active view.
 -	 * This method will examin the ActiveViewID, ActiveViewIndex and Views collection to
 -	 * determine which view is currently active. It will update ActiveViewID and ActiveViewIndex accordingly.
 -	 * @return TAccordionView the currently active view, null if no active view
 -	 * @throws TInvalidDataValueException if the active view ID or index set previously is invalid
 -	 */
 -	public function getActiveView()
 -	{
 -		$activeView=null;
 -		$views=$this->getViews();
 -		if(($id=$this->getActiveViewID())!=='')
 -		{
 -			if(($index=$views->findIndexByID($id))>=0)
 -				$activeView=$views->itemAt($index);
 -			else
 -				throw new TInvalidDataValueException('tabpanel_activeviewid_invalid',$id);
 -		}
 -		else if(($index=$this->getActiveViewIndex())>=0)
 -		{
 -			if($index<$views->getCount())
 -				$activeView=$views->itemAt($index);
 -			else
 -				throw new TInvalidDataValueException('tabpanel_activeviewindex_invalid',$index);
 -		}
 -		else
 -		{
 -			foreach($views as $index=>$view)
 -			{
 -				if($view->getActive())
 -				{
 -					$activeView=$view;
 -					break;
 -				}
 -			}
 -		}
 -		if($activeView!==null)
 -			$this->activateView($activeView);
 -		return $activeView;
 -	}
 -
 -	/**
 -	 * @param TAccordionView the view to be activated
 -	 * @throws TInvalidOperationException if the view is not in the view collection
 -	 */
 -	public function setActiveView($view)
 -	{
 -		if($this->getViews()->indexOf($view)>=0)
 -			$this->activateView($view);
 -		else
 -			throw new TInvalidOperationException('tabpanel_view_inexistent');
 -	}
 -
 -	/**
 -	* @return string URL for the CSS file including all relevant CSS class definitions. Defaults to ''.
 -	*/
 -	public function getCssUrl()
 -	{
 -		return $this->getViewState('CssUrl','default');
 -	}
 -
 -	/**
 -	* @param string URL for the CSS file including all relevant CSS class definitions.
 -	*/
 -	public function setCssUrl($value)
 -	{
 -		$this->setViewState('CssUrl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -		* @return string CSS class for the whole accordion control div. 
 -	*/
 -	public function getCssClass()
 -	{
 -		$cssClass=parent::getCssClass();
 -			return $cssClass===''?'accordion':$cssClass;
 -	}
 -
 -	/**
 -		* @return string CSS class for the currently displayed view div. Defaults to 'accordion-view'.
 -	*/
 -	public function getViewCssClass()
 -	{
 -		return $this->getViewStyle()->getCssClass();
 -	}
 -
 -	/**
 -	* @param string CSS class for the currently displayed view div.
 -	*/
 -	public function setViewCssClass($value)
 -	{
 -		$this->getViewStyle()->setCssClass($value);
 -	}
 -
 -	/**
 -		* @return string CSS class for the currently displayed view div. Defaults to 'accordion-view'.
 -	*/
 -	public function getAnimationDuration()
 -	{
 -		return $this->getViewState('AnimationDuration','1');
 -	}
 -
 -	/**
 -	* @param string CSS class for the currently displayed view div.
 -	*/
 -	public function setAnimationDuration($value)
 -	{
 -		$this->setViewState('AnimationDuration',$value);
 -	}
 -
 -	/**
 -	 * @return TStyle the style for all the view div
 -	 */
 -	public function getViewStyle()
 -	{
 -		if(($style=$this->getViewState('ViewStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$style->setCssClass('accordion-view');
 -			$this->setViewState('ViewStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return string CSS class for view headers. Defaults to 'accordion-header'.
 -	 */
 -	public function getHeaderCssClass()
 -	{
 -		return $this->getHeaderStyle()->getCssClass();
 -	}
 -
 -	/**
 -	 * @param string CSS class for view headers.
 -	 */
 -	public function setHeaderCssClass($value)
 -	{
 -		$this->getHeaderStyle()->setCssClass($value);
 -	}
 -
 -	/**
 -	 * @return TStyle the style for all the inactive header div
 -	 */
 -	public function getHeaderStyle()
 -	{
 -		if(($style=$this->getViewState('HeaderStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$style->setCssClass('accordion-header');
 -			$this->setViewState('HeaderStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return string Extra CSS class for the active header. Defaults to 'accordion-header-active'.
 -	 */
 -	public function getActiveHeaderCssClass()
 -	{
 -		return $this->getActiveHeaderStyle()->getCssClass();
 -	}
 -
 -	/**
 -	 * @param string Extra CSS class for the active header. Will be added to the normal header specified by HeaderCssClass.
 -	 */
 -	public function setActiveHeaderCssClass($value)
 -	{
 -		$this->getActiveHeaderStyle()->setCssClass($value);
 -	}
 -
 -	/**
 -	 * @return TStyle the style for the active header div
 -	 */
 -	public function getActiveHeaderStyle()
 -	{
 -		if(($style=$this->getViewState('ActiveHeaderStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$style->setCssClass('accordion-header-active');
 -			$this->setViewState('ActiveHeaderStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return integer Maximum height for the accordion views. If non specified, the accordion will auto-sized to the largest of all views, so it can encompass all of them without scrolling
 -	 */
 -	public function getViewHeight()
 -	{
 -		return TPropertyValue::ensureInteger($this->getViewState('ViewHeight'));
 -	}
 -
 -	/**
 -	 * @param integer Maximum height for the accordion views. If any of the accordion's views' content is larger, those views will be made scrollable when activated
 -	 */
 -	public function setViewHeight($value)
 -	{
 -		$this->setViewState('ViewHeight', TPropertyValue::ensureInteger($value));
 -	}
 -
 -	/**
 -	 * Activates the specified view.
 -	 * If there is any other view currently active, it will be deactivated.
 -	 * @param TAccordionView the view to be activated. If null, all views will be deactivated.
 -	 */
 -	protected function activateView($view)
 -	{
 -		$this->setActiveViewIndex(-1);
 -		$this->setActiveViewID('');
 -		foreach($this->getViews() as $index=>$v)
 -		{
 -			if($view===$v)
 -			{
 -				$this->setActiveViewIndex($index);
 -				$this->setActiveViewID($view->getID(false));
 -				$view->setActive(true);
 -			}
 -			else
 -				$v->setActive(false);
 -		}
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the control has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		if(($index=$values[$this->getClientID().'_1'])!==null)
 -		{
 -			$index=(int)$index;
 -			$currentIndex=$this->getActiveViewIndex();
 -			if($currentIndex!==$index)
 -			{
 -				$this->setActiveViewID(''); // clear up view ID
 -				$this->setActiveViewIndex($index);
 -				return $this->_dataChanged=true;
 -			}
 -		}
 -		return false;
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method is required by {@link IPostBackDataHandler} interface.
 -	 * It is invoked by the framework when {@link getActiveViewIndex ActiveViewIndex} property
 -	 * is changed on postback.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		// do nothing
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$writer->addAttribute('id',$this->getClientID());
 -		$this->setCssClass($this->getCssClass());
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Registers CSS and JS.
 -	 * This method is invoked right before the control rendering, if the control is visible.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		$this->getActiveView();  // determine the active view
 -		$this->registerStyleSheet();
 -	}
 -
 -	/**
 -	 * Registers the CSS relevant to the TAccordion.
 -	 * It will register the CSS file specified by {@link getCssUrl CssUrl}.
 -	 * If that is not set, it will use the default CSS.
 -	 */
 -	protected function registerStyleSheet()
 -	{
 -		$url = $this->getCssUrl();
 -		
 -		if($url === '') {
 -			return;
 -		}
 -		
 -		if($url === 'default') {
 -			$url = $this->getApplication()->getAssetManager()->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'accordion.css');
 -		}
 -		
 -		if($url !== '') {
 -			$this->getPage()->getClientScript()->registerStyleSheetFile($url, $url);
 -		}
 -	}
 -
 -	/**
 -	 * Registers the relevant JavaScript.
 -	 */
 -	protected function registerClientScript()
 -	{
 -		$id=$this->getClientID();
 -		$options=TJavaScript::encode($this->getClientOptions());
 -		$className=$this->getClientClassName();
 -		$page=$this->getPage();
 -		$cs=$page->getClientScript();
 -		$cs->registerPradoScript('accordion');
 -		$code="new $className($options);";
 -		$cs->registerEndScript("prado:$id", $code);
 -		// ensure an item is always active and visible
 -		$index = $this->getActiveViewIndex();
 -		if(!$this->getViews()->itemAt($index)->Visible)
 -			$index=0;
 -		$cs->registerHiddenField($id.'_1', $index);
 -		$page->registerRequiresPostData($this);
 -		$page->registerRequiresPostData($id."_1");
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TAccordion';
 -	}
 -
 -	/**
 -	 * @return array the options for JavaScript
 -	 */
 -	protected function getClientOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['ActiveHeaderCssClass'] = $this->getActiveHeaderCssClass();
 -		$options['HeaderCssClass'] = $this->getHeaderCssClass();
 -		$options['Duration'] = $this->getAnimationDuration();
 -
 -		if (($viewheight = $this->getViewHeight())>0)
 -			$options['maxHeight'] = $viewheight;
 -		$views = array();
 -		foreach($this->getViews() as $view)
 -			$views[$view->getClientID()] = $view->getVisible() ? '1': '0';
 -		$options['Views'] = $views;
 -
 -		return $options;
 -	}
 -
 -	/**
 -	 * Creates a control collection object that is to be used to hold child controls
 -	 * @return TAccordionViewCollection control collection
 -	 */
 -	protected function createControlCollection()
 -	{
 -		return new TAccordionViewCollection($this);
 -	}
 -
 -	/**
 -	 * @return TAccordionViewCollection list of {@link TAccordionView} controls
 -	 */
 -	public function getViews()
 -	{
 -		return $this->getControls();
 -	}
 -
 -	public function render($writer)
 -	{
 -		$this->registerClientScript();
 -		parent::render($writer);
 -	}
 -
 -	/**
 -	 * Renders body contents of the accordion control.
 -	 * @param THtmlWriter the writer used for the rendering purpose.
 -	 */
 -	public function renderContents($writer)
 -	{
 -		$views=$this->getViews();
 -		if($views->getCount()>0)
 -		{
 -			$writer->writeLine();
 -			foreach($views as $view)
 -			{
 -				$view->renderHeader($writer);
 -				$view->renderControl($writer);
 -				$writer->writeLine();
 -			}
 -		}
 -	}
 -
 -}
 -
 -/**
 - * Class TAccordionView.
 - *
 - * TAccordionView represents a single view in a {@link TAccordion}.
 - * 
 - * TAccordionView is represented inside the {@link TAccordion} with an header label whose text is defined by
 - * the {@link setCaption Caption} property; optionally the label can be an hyperlink: use the
 - * {@link setNavigateUrl NavigateUrl} property to define the destination url.
 - *
 - * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu>
 - * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -class TAccordionView extends TWebControl
 -{
 -	private $_active=false;
 -
 -	/**
 -	 * @return the tag name for the view element
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'div';
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		if(!$this->getActive() && $this->getPage()->getClientSupportsJavaScript())
 -			$this->getStyle()->setStyleField('display','none');
 -
 -		$this->getStyle()->mergeWith($this->getParent()->getViewStyle());
 -
 -		parent::addAttributesToRender($writer);
 -
 -		$writer->addAttribute('id',$this->getClientID());
 -	}
 -
 -	/**
 -	 * @return string the caption displayed on this header. Defaults to ''.
 -	 */
 -	public function getCaption()
 -	{
 -		return $this->getViewState('Caption','');
 -	}
 -
 -	/**
 -	 * @param string the caption displayed on this header
 -	 */
 -	public function setCaption($value)
 -	{
 -		$this->setViewState('Caption',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string the URL of the target page. Defaults to ''.
 -	 */
 -	public function getNavigateUrl()
 -	{
 -		return $this->getViewState('NavigateUrl','');
 -	}
 -
 -	/**
 -	 * Sets the URL of the target page.
 -	 * If not empty, clicking on this header will redirect the browser to the specified URL.
 -	 * @param string the URL of the target page.
 -	 */
 -	public function setNavigateUrl($value)
 -	{
 -		$this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string the text content displayed on this view. Defaults to ''.
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text content to be displayed on this view.
 -	 * If this is not empty, the child content of the view will be ignored.
 -	 * @param string the text content displayed on this view
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return boolean whether this accordion view is active. Defaults to false.
 -	 */
 -	public function getActive()
 -	{
 -		return $this->_active;
 -	}
 -
 -	/**
 -	 * @param boolean whether this accordion view is active.
 -	 */
 -	public function setActive($value)
 -	{
 -		$this->_active=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * Renders body contents of the accordion view.
 -	 * @param THtmlWriter the writer used for the rendering purpose.
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if(($text=$this->getText())!=='')
 -			$writer->write($text);
 -		else if($this->getHasControls())
 -			parent::renderContents($writer);
 -	}
 -
 -	/**
 -	 * Renders the header associated with the accordion view.
 -	 * @param THtmlWriter the writer for rendering purpose.
 -	 */
 -	public function renderHeader($writer)
 -	{
 -		if($this->getVisible(false) && $this->getPage()->getClientSupportsJavaScript())
 -		{
 -			$writer->addAttribute('id',$this->getClientID().'_0');
 -
 -			$style=$this->getActive()?$this->getParent()->getActiveHeaderStyle():$this->getParent()->getHeaderStyle();
 -			
 -			$style->addAttributesToRender($writer);
 -
 -			$writer->renderBeginTag($this->getTagName());
 -
 -			$this->renderHeaderContent($writer);
 -
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	/**
 -	 * Renders the content in the header.
 -	 * By default, a hyperlink is displayed.
 -	 * @param THtmlWriter the HTML writer
 -	 */
 -	protected function renderHeaderContent($writer)
 -	{
 -		$url = $this->getNavigateUrl();
 -		if(($caption=$this->getCaption())==='')
 -			$caption=' ';
 -			
 -		if ($url!='')
 -			$writer->write("<a href=\"{$url}\">");
 -		$writer->write("{$caption}");
 -		if ($url!='')
 -			$writer->write("</a>");
 -	}
 -}
 -
 -/**
 - * Class TAccordionViewCollection.
 - *
 - * TAccordionViewCollection is a collection of {@link TAccordionView} to be used inside a {@link TAccordion}.
 - * 
 - * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu>
 - * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -class TAccordionViewCollection extends TControlCollection
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by performing sanity check on the type of new item.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a {@link TAccordionView} object.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TAccordionView)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('tabviewcollection_tabview_required');
 -	}
 -
 -	/**
 -	 * Finds the index of the accordion view whose ID is the same as the one being looked for.
 -	 * @param string the explicit ID of the accordion view to be looked for
 -	 * @return integer the index of the accordion view found, -1 if not found.
 -	 */
 -	public function findIndexByID($id)
 -	{
 -		foreach($this as $index=>$view)
 -		{
 -			if($view->getID(false)===$id)
 -				return $index;
 -		}
 -		return -1;
 -	}
 -}
 -
 -?>
 +<?php +/** + * TAccordion class file. + * + * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $ + * @package System.Web.UI.WebControls + * @since 3.2 + */ + +/** + * Class TAccordion. + * + * TAccordion displays an accordion control. Users can click on the view headers to switch among + * different accordion views. Each accordion view is an independent panel that can contain arbitrary content. + * + * A TAccordion control consists of one or several {@link TAccordionView} controls representing the possible + * accordion views. At any time, only one accordion view is visible (active), which is specified by any of + * the following properties: + * - {@link setActiveViewIndex ActiveViewIndex} - the zero-based integer index of the view in the view collection. + * - {@link setActiveViewID ActiveViewID} - the text ID of the visible view. + * - {@link setActiveView ActiveView} - the visible view instance. + * If both {@link setActiveViewIndex ActiveViewIndex} and {@link setActiveViewID ActiveViewID} + * are set, the latter takes precedence. + * + * TAccordion uses CSS to specify the appearance of the accordion headers and panel. By default, + * an embedded CSS file will be published which contains the default CSS for TTabPanel. + * You may also use your own CSS file by specifying the {@link setCssUrl CssUrl} property. + * The following properties specify the CSS classes used for elements in a TAccordion: + * - {@link setCssClass CssClass} - the CSS class name for the outer-most div element (defaults to 'accordion'); + * - {@link setHeaderCssClass HeaderCssClass} - the CSS class name for nonactive accordion div elements (defaults to 'accordion-header'); + * - {@link setActiveHeaderCssClass ActiveHeaderCssClass} - the CSS class name for the active accordion div element (defaults to 'accordion-header-active'); + * - {@link setViewCssClass ViewCssClass} - the CSS class for the div element enclosing view content (defaults to 'accordion-view'); + * + * When the user clicks on a view header, the switch between the old visible view and the clicked one is animated. + * You can use the {@link setAnimationDuration AnimationDuration} property to set the animation length in seconds; + * it defaults to 1 second, and when set to 0 it will produce an immediate switch with no animation. + * + * The TAccordion auto-sizes itself to the largest of all views, so it can encompass all of them without scrolling. + * If you want to specify a fixed height (in pixels), use the {@link setViewHeight ViewHeight} property. + * When a TAccordion is nested inside another, it's adviced to manually specify a {@link setViewHeight ViewHeight} for the internal TAccordion + * + * To use TAccordion, write a template like following: + * <code> + * <com:TAccordion> + *   <com:TAccordionView Caption="View 1"> + *     content for view 1 + *   </com:TAccordionView> + *   <com:TAccordionView Caption="View 2"> + *     content for view 2 + *   </com:TAccordionView> + *   <com:TAccordionView Caption="View 3"> + *     content for view 3 + *   </com:TAccordionView> + * </com:TAccordion> + * </code> + * + * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu> + * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $ + * @package System.Web.UI.WebControls + * @since 3.2 + */ + +class TAccordion extends TWebControl implements IPostBackDataHandler +{ +	private $_dataChanged=false; + +	/** +	 * @return string tag name for the control +	 */ +	protected function getTagName() +	{ +		return 'div'; +	} + +	/** +	 * Adds object parsed from template to the control. +	 * This method adds only {@link TAccordionView} objects into the {@link getViews Views} collection. +	 * All other objects are ignored. +	 * @param mixed object parsed from template +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TAccordionView) +			$this->getControls()->add($object); +	} + +	/** +	 * Returns the index of the active accordion view. +	 * Note, this property may not return the correct index. +	 * To ensure the correctness, call {@link getActiveView()} first. +	 * @return integer the zero-based index of the active accordion view. If -1, it means no active accordion view. Default is 0 (the first view is active). +	 */ +	public function getActiveViewIndex() +	{ +		return $this->getViewState('ActiveViewIndex',0); +	} + +	/** +	 * @param integer the zero-based index of the current view in the view collection. -1 if no active view. +	 * @throws TInvalidDataValueException if the view index is invalid +	 */ +	public function setActiveViewIndex($value) +	{ +		$this->setViewState('ActiveViewIndex',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * Returns the ID of the active accordion view. +	 * Note, this property may not return the correct ID. +	 * To ensure the correctness, call {@link getActiveView()} first. +	 * @return string The ID of the active accordion view. Defaults to '', meaning not set. +	 */ +	public function getActiveViewID() +	{ +		return $this->getViewState('ActiveViewID',''); +	} + +	/** +	 * @param string The ID of the active accordion view. +	 */ +	public function setActiveViewID($value) +	{ +		$this->setViewState('ActiveViewID',$value,''); +	} + +	/** +	 * Returns the currently active view. +	 * This method will examin the ActiveViewID, ActiveViewIndex and Views collection to +	 * determine which view is currently active. It will update ActiveViewID and ActiveViewIndex accordingly. +	 * @return TAccordionView the currently active view, null if no active view +	 * @throws TInvalidDataValueException if the active view ID or index set previously is invalid +	 */ +	public function getActiveView() +	{ +		$activeView=null; +		$views=$this->getViews(); +		if(($id=$this->getActiveViewID())!=='') +		{ +			if(($index=$views->findIndexByID($id))>=0) +				$activeView=$views->itemAt($index); +			else +				throw new TInvalidDataValueException('tabpanel_activeviewid_invalid',$id); +		} +		else if(($index=$this->getActiveViewIndex())>=0) +		{ +			if($index<$views->getCount()) +				$activeView=$views->itemAt($index); +			else +				throw new TInvalidDataValueException('tabpanel_activeviewindex_invalid',$index); +		} +		else +		{ +			foreach($views as $index=>$view) +			{ +				if($view->getActive()) +				{ +					$activeView=$view; +					break; +				} +			} +		} +		if($activeView!==null) +			$this->activateView($activeView); +		return $activeView; +	} + +	/** +	 * @param TAccordionView the view to be activated +	 * @throws TInvalidOperationException if the view is not in the view collection +	 */ +	public function setActiveView($view) +	{ +		if($this->getViews()->indexOf($view)>=0) +			$this->activateView($view); +		else +			throw new TInvalidOperationException('tabpanel_view_inexistent'); +	} + +	/** +	* @return string URL for the CSS file including all relevant CSS class definitions. Defaults to ''. +	*/ +	public function getCssUrl() +	{ +		return $this->getViewState('CssUrl','default'); +	} + +	/** +	* @param string URL for the CSS file including all relevant CSS class definitions. +	*/ +	public function setCssUrl($value) +	{ +		$this->setViewState('CssUrl',TPropertyValue::ensureString($value),''); +	} + +	/** +		* @return string CSS class for the whole accordion control div.  +	*/ +	public function getCssClass() +	{ +		$cssClass=parent::getCssClass(); +			return $cssClass===''?'accordion':$cssClass; +	} + +	/** +		* @return string CSS class for the currently displayed view div. Defaults to 'accordion-view'. +	*/ +	public function getViewCssClass() +	{ +		return $this->getViewStyle()->getCssClass(); +	} + +	/** +	* @param string CSS class for the currently displayed view div. +	*/ +	public function setViewCssClass($value) +	{ +		$this->getViewStyle()->setCssClass($value); +	} + +	/** +		* @return string CSS class for the currently displayed view div. Defaults to 'accordion-view'. +	*/ +	public function getAnimationDuration() +	{ +		return $this->getViewState('AnimationDuration','1'); +	} + +	/** +	* @param string CSS class for the currently displayed view div. +	*/ +	public function setAnimationDuration($value) +	{ +		$this->setViewState('AnimationDuration',$value); +	} + +	/** +	 * @return TStyle the style for all the view div +	 */ +	public function getViewStyle() +	{ +		if(($style=$this->getViewState('ViewStyle',null))===null) +		{ +			$style=new TStyle; +			$style->setCssClass('accordion-view'); +			$this->setViewState('ViewStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return string CSS class for view headers. Defaults to 'accordion-header'. +	 */ +	public function getHeaderCssClass() +	{ +		return $this->getHeaderStyle()->getCssClass(); +	} + +	/** +	 * @param string CSS class for view headers. +	 */ +	public function setHeaderCssClass($value) +	{ +		$this->getHeaderStyle()->setCssClass($value); +	} + +	/** +	 * @return TStyle the style for all the inactive header div +	 */ +	public function getHeaderStyle() +	{ +		if(($style=$this->getViewState('HeaderStyle',null))===null) +		{ +			$style=new TStyle; +			$style->setCssClass('accordion-header'); +			$this->setViewState('HeaderStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return string Extra CSS class for the active header. Defaults to 'accordion-header-active'. +	 */ +	public function getActiveHeaderCssClass() +	{ +		return $this->getActiveHeaderStyle()->getCssClass(); +	} + +	/** +	 * @param string Extra CSS class for the active header. Will be added to the normal header specified by HeaderCssClass. +	 */ +	public function setActiveHeaderCssClass($value) +	{ +		$this->getActiveHeaderStyle()->setCssClass($value); +	} + +	/** +	 * @return TStyle the style for the active header div +	 */ +	public function getActiveHeaderStyle() +	{ +		if(($style=$this->getViewState('ActiveHeaderStyle',null))===null) +		{ +			$style=new TStyle; +			$style->setCssClass('accordion-header-active'); +			$this->setViewState('ActiveHeaderStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return integer Maximum height for the accordion views. If non specified, the accordion will auto-sized to the largest of all views, so it can encompass all of them without scrolling +	 */ +	public function getViewHeight() +	{ +		return TPropertyValue::ensureInteger($this->getViewState('ViewHeight')); +	} + +	/** +	 * @param integer Maximum height for the accordion views. If any of the accordion's views' content is larger, those views will be made scrollable when activated +	 */ +	public function setViewHeight($value) +	{ +		$this->setViewState('ViewHeight', TPropertyValue::ensureInteger($value)); +	} + +	/** +	 * Activates the specified view. +	 * If there is any other view currently active, it will be deactivated. +	 * @param TAccordionView the view to be activated. If null, all views will be deactivated. +	 */ +	protected function activateView($view) +	{ +		$this->setActiveViewIndex(-1); +		$this->setActiveViewID(''); +		foreach($this->getViews() as $index=>$v) +		{ +			if($view===$v) +			{ +				$this->setActiveViewIndex($index); +				$this->setActiveViewID($view->getID(false)); +				$view->setActive(true); +			} +			else +				$v->setActive(false); +		} +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the control has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		if(($index=$values[$this->getClientID().'_1'])!==null) +		{ +			$index=(int)$index; +			$currentIndex=$this->getActiveViewIndex(); +			if($currentIndex!==$index) +			{ +				$this->setActiveViewID(''); // clear up view ID +				$this->setActiveViewIndex($index); +				return $this->_dataChanged=true; +			} +		} +		return false; +	} + +	/** +	 * Raises postdata changed event. +	 * This method is required by {@link IPostBackDataHandler} interface. +	 * It is invoked by the framework when {@link getActiveViewIndex ActiveViewIndex} property +	 * is changed on postback. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		// do nothing +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 */ +	protected function addAttributesToRender($writer) +	{ +		$writer->addAttribute('id',$this->getClientID()); +		$this->setCssClass($this->getCssClass()); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Registers CSS and JS. +	 * This method is invoked right before the control rendering, if the control is visible. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		$this->getActiveView();  // determine the active view +		$this->registerStyleSheet(); +	} + +	/** +	 * Registers the CSS relevant to the TAccordion. +	 * It will register the CSS file specified by {@link getCssUrl CssUrl}. +	 * If that is not set, it will use the default CSS. +	 */ +	protected function registerStyleSheet() +	{ +		$url = $this->getCssUrl(); +		 +		if($url === '') { +			return; +		} +		 +		if($url === 'default') { +			$url = $this->getApplication()->getAssetManager()->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'accordion.css'); +		} +		 +		if($url !== '') { +			$this->getPage()->getClientScript()->registerStyleSheetFile($url, $url); +		} +	} + +	/** +	 * Registers the relevant JavaScript. +	 */ +	protected function registerClientScript() +	{ +		$id=$this->getClientID(); +		$options=TJavaScript::encode($this->getClientOptions()); +		$className=$this->getClientClassName(); +		$page=$this->getPage(); +		$cs=$page->getClientScript(); +		$cs->registerPradoScript('accordion'); +		$code="new $className($options);"; +		$cs->registerEndScript("prado:$id", $code); +		// ensure an item is always active and visible +		$index = $this->getActiveViewIndex(); +		if(!$this->getViews()->itemAt($index)->Visible) +			$index=0; +		$cs->registerHiddenField($id.'_1', $index); +		$page->registerRequiresPostData($this); +		$page->registerRequiresPostData($id."_1"); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TAccordion'; +	} + +	/** +	 * @return array the options for JavaScript +	 */ +	protected function getClientOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['ActiveHeaderCssClass'] = $this->getActiveHeaderCssClass(); +		$options['HeaderCssClass'] = $this->getHeaderCssClass(); +		$options['Duration'] = $this->getAnimationDuration(); + +		if (($viewheight = $this->getViewHeight())>0) +			$options['maxHeight'] = $viewheight; +		$views = array(); +		foreach($this->getViews() as $view) +			$views[$view->getClientID()] = $view->getVisible() ? '1': '0'; +		$options['Views'] = $views; + +		return $options; +	} + +	/** +	 * Creates a control collection object that is to be used to hold child controls +	 * @return TAccordionViewCollection control collection +	 */ +	protected function createControlCollection() +	{ +		return new TAccordionViewCollection($this); +	} + +	/** +	 * @return TAccordionViewCollection list of {@link TAccordionView} controls +	 */ +	public function getViews() +	{ +		return $this->getControls(); +	} + +	public function render($writer) +	{ +		$this->registerClientScript(); +		parent::render($writer); +	} + +	/** +	 * Renders body contents of the accordion control. +	 * @param THtmlWriter the writer used for the rendering purpose. +	 */ +	public function renderContents($writer) +	{ +		$views=$this->getViews(); +		if($views->getCount()>0) +		{ +			$writer->writeLine(); +			foreach($views as $view) +			{ +				$view->renderHeader($writer); +				$view->renderControl($writer); +				$writer->writeLine(); +			} +		} +	} + +} + +/** + * Class TAccordionView. + * + * TAccordionView represents a single view in a {@link TAccordion}. + *  + * TAccordionView is represented inside the {@link TAccordion} with an header label whose text is defined by + * the {@link setCaption Caption} property; optionally the label can be an hyperlink: use the + * {@link setNavigateUrl NavigateUrl} property to define the destination url. + * + * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu> + * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $ + * @package System.Web.UI.WebControls + * @since 3.2 + */ +class TAccordionView extends TWebControl +{ +	private $_active=false; + +	/** +	 * @return the tag name for the view element +	 */ +	protected function getTagName() +	{ +		return 'div'; +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 */ +	protected function addAttributesToRender($writer) +	{ +		if(!$this->getActive() && $this->getPage()->getClientSupportsJavaScript()) +			$this->getStyle()->setStyleField('display','none'); + +		$this->getStyle()->mergeWith($this->getParent()->getViewStyle()); + +		parent::addAttributesToRender($writer); + +		$writer->addAttribute('id',$this->getClientID()); +	} + +	/** +	 * @return string the caption displayed on this header. Defaults to ''. +	 */ +	public function getCaption() +	{ +		return $this->getViewState('Caption',''); +	} + +	/** +	 * @param string the caption displayed on this header +	 */ +	public function setCaption($value) +	{ +		$this->setViewState('Caption',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string the URL of the target page. Defaults to ''. +	 */ +	public function getNavigateUrl() +	{ +		return $this->getViewState('NavigateUrl',''); +	} + +	/** +	 * Sets the URL of the target page. +	 * If not empty, clicking on this header will redirect the browser to the specified URL. +	 * @param string the URL of the target page. +	 */ +	public function setNavigateUrl($value) +	{ +		$this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string the text content displayed on this view. Defaults to ''. +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text content to be displayed on this view. +	 * If this is not empty, the child content of the view will be ignored. +	 * @param string the text content displayed on this view +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return boolean whether this accordion view is active. Defaults to false. +	 */ +	public function getActive() +	{ +		return $this->_active; +	} + +	/** +	 * @param boolean whether this accordion view is active. +	 */ +	public function setActive($value) +	{ +		$this->_active=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * Renders body contents of the accordion view. +	 * @param THtmlWriter the writer used for the rendering purpose. +	 */ +	public function renderContents($writer) +	{ +		if(($text=$this->getText())!=='') +			$writer->write($text); +		else if($this->getHasControls()) +			parent::renderContents($writer); +	} + +	/** +	 * Renders the header associated with the accordion view. +	 * @param THtmlWriter the writer for rendering purpose. +	 */ +	public function renderHeader($writer) +	{ +		if($this->getVisible(false) && $this->getPage()->getClientSupportsJavaScript()) +		{ +			$writer->addAttribute('id',$this->getClientID().'_0'); + +			$style=$this->getActive()?$this->getParent()->getActiveHeaderStyle():$this->getParent()->getHeaderStyle(); +			 +			$style->addAttributesToRender($writer); + +			$writer->renderBeginTag($this->getTagName()); + +			$this->renderHeaderContent($writer); + +			$writer->renderEndTag(); +		} +	} + +	/** +	 * Renders the content in the header. +	 * By default, a hyperlink is displayed. +	 * @param THtmlWriter the HTML writer +	 */ +	protected function renderHeaderContent($writer) +	{ +		$url = $this->getNavigateUrl(); +		if(($caption=$this->getCaption())==='') +			$caption=' '; +			 +		if ($url!='') +			$writer->write("<a href=\"{$url}\">"); +		$writer->write("{$caption}"); +		if ($url!='') +			$writer->write("</a>"); +	} +} + +/** + * Class TAccordionViewCollection. + * + * TAccordionViewCollection is a collection of {@link TAccordionView} to be used inside a {@link TAccordion}. + *  + * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu> + * @version $Id: TAccordion.php 2915 2011-05-15 16:26:11Z ctrlaltca@gmail.com $ + * @package System.Web.UI.WebControls + * @since 3.2 + */ +class TAccordionViewCollection extends TControlCollection +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by performing sanity check on the type of new item. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a {@link TAccordionView} object. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TAccordionView) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('tabviewcollection_tabview_required'); +	} + +	/** +	 * Finds the index of the accordion view whose ID is the same as the one being looked for. +	 * @param string the explicit ID of the accordion view to be looked for +	 * @return integer the index of the accordion view found, -1 if not found. +	 */ +	public function findIndexByID($id) +	{ +		foreach($this as $index=>$view) +		{ +			if($view->getID(false)===$id) +				return $index; +		} +		return -1; +	} +} + +?> diff --git a/framework/Web/UI/WebControls/TBaseDataList.php b/framework/Web/UI/WebControls/TBaseDataList.php index bc591174..01e7dbcf 100644 --- a/framework/Web/UI/WebControls/TBaseDataList.php +++ b/framework/Web/UI/WebControls/TBaseDataList.php @@ -1,190 +1,190 @@ -<?php
 -/**
 - * TBaseDataList class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TBaseDataList class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TDataBoundControl and TDataFieldAccessor classes
 - */
 -Prado::using('System.Web.UI.WebControls.TDataBoundControl');
 -Prado::using('System.Util.TDataFieldAccessor');
 -
 -/**
 - * TBaseDataList class
 - *
 - * TBaseDataList is the base class for data listing controls, including
 - * {@link TDataList} and {@link TDataGrid}.
 - *
 - * The key field in the data source is specified by {@link setKeyField KeyField},
 - * while {@link getKeyValues KeyValues} stores the key values of each record in
 - * a data listing control. You may use the list item index to obtain the corresponding
 - * database key value.
 - *
 - * TBaseDataList also implements a few properties used for presentation based
 - * on tabular layout. The {@link setCaption Caption}, whose alignment is
 - * specified via {@link setCaptionAlign CaptionAlign}, is rendered as the table caption.
 - * The table cellpadding and cellspacing are specified by
 - * {@link setCellPadding CellPadding} and {@link setCellSpacing CellSpacing}
 - * properties, respectively. The {@link setGridLines GridLines} specifies how
 - * the table should display its borders, and the horizontal alignment of the table
 - * content can be specified via {@link setHorizontalAlign HorizontalAlign}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class TBaseDataList extends TDataBoundControl
 -{
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableStyle} to be used by the data list control.
 -	 * @return TTableStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableStyle;
 -	}
 -
 -	/**
 -	 * @return integer the cellspacing for the table layout. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellSpacing()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getCellSpacing();
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * @param integer the cellspacing for the table layout.
 -	 */
 -	public function setCellSpacing($value)
 -	{
 -		$this->getStyle()->setCellSpacing($value);
 -	}
 -
 -	/**
 -	 * @return integer the cellpadding for the table layout. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellPadding()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getCellPadding();
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * @param integer the cellpadding for the table layout
 -	 */
 -	public function setCellPadding($value)
 -	{
 -		$this->getStyle()->setCellPadding($value);
 -	}
 -
 -	/**
 -	 * @return THorizontalAlign the horizontal alignment of the table content. Defaults to THorizontalAlign::NotSet.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getHorizontalAlign();
 -		else
 -			return THorizontalAlign::NotSet;
 -	}
 -
 -	/**
 -	 * @param THorizontalAlign the horizontal alignment of the table content.
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->getStyle()->setHorizontalAlign($value);
 -	}
 -
 -	/**
 -	 * @return TTableGridLines the grid line setting of the table layout. Defaults to TTableGridLines::None.
 -	 */
 -	public function getGridLines()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getGridLines();
 -		else
 -			return TTableGridLines::None;
 -	}
 -
 -	/**
 -	 * Sets the grid line style of the table layout.
 -	 * @param TTableGridLines the grid line setting of the table
 -	 */
 -	public function setGridLines($value)
 -	{
 -		$this->getStyle()->setGridLines($value);
 -	}
 -
 -
 -	/**
 -	 * @return string the field of the data source that provides the keys of the list items.
 -	 */
 -	public function getDataKeyField()
 -	{
 -		return $this->getViewState('DataKeyField','');
 -	}
 -
 -	/**
 -	 * @param string the field of the data source that provides the keys of the list items.
 -	 */
 -	public function setDataKeyField($value)
 -	{
 -		$this->setViewState('DataKeyField',$value,'');
 -	}
 -
 -	/**
 -	 * @return TList the keys used in the data listing control.
 -	 */
 -	public function getDataKeys()
 -	{
 -		if(($dataKeys=$this->getViewState('DataKeys',null))===null)
 -		{
 -			$dataKeys=new TList;
 -			$this->setViewState('DataKeys',$dataKeys,null);
 -		}
 -		return $dataKeys;
 -	}
 -
 -	/**
 -	 * Returns the value of the data at the specified field.
 -	 * If data is an array, TMap or TList, the value will be returned at the index
 -	 * of the specified field. If the data is a component with a property named
 -	 * as the field name, the property value will be returned.
 -	 * Otherwise, an exception will be raised.
 -	 * @param mixed data item
 -	 * @param mixed field name
 -	 * @return mixed data value at the specified field
 -	 * @throws TInvalidDataValueException if the data is invalid
 -	 */
 -	protected function getDataFieldValue($data,$field)
 -	{
 -		return TDataFieldAccessor::getDataFieldValue($data,$field);
 -	}
 -
 -	/**
 -	 * Raises OnSelectedIndexChanged event.
 -	 * This method is invoked when a different item is selected
 -	 * in a data listing control between posts to the server.
 -	 * @param mixed event parameter
 -	 */
 -	public function onSelectedIndexChanged($param)
 -	{
 -		$this->raiseEvent('OnSelectedIndexChanged',$this,$param);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TDataBoundControl and TDataFieldAccessor classes + */ +Prado::using('System.Web.UI.WebControls.TDataBoundControl'); +Prado::using('System.Util.TDataFieldAccessor'); + +/** + * TBaseDataList class + * + * TBaseDataList is the base class for data listing controls, including + * {@link TDataList} and {@link TDataGrid}. + * + * The key field in the data source is specified by {@link setKeyField KeyField}, + * while {@link getKeyValues KeyValues} stores the key values of each record in + * a data listing control. You may use the list item index to obtain the corresponding + * database key value. + * + * TBaseDataList also implements a few properties used for presentation based + * on tabular layout. The {@link setCaption Caption}, whose alignment is + * specified via {@link setCaptionAlign CaptionAlign}, is rendered as the table caption. + * The table cellpadding and cellspacing are specified by + * {@link setCellPadding CellPadding} and {@link setCellSpacing CellSpacing} + * properties, respectively. The {@link setGridLines GridLines} specifies how + * the table should display its borders, and the horizontal alignment of the table + * content can be specified via {@link setHorizontalAlign HorizontalAlign}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TBaseDataList extends TDataBoundControl +{ +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableStyle} to be used by the data list control. +	 * @return TTableStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableStyle; +	} + +	/** +	 * @return integer the cellspacing for the table layout. Defaults to -1, meaning not set. +	 */ +	public function getCellSpacing() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getCellSpacing(); +		else +			return -1; +	} + +	/** +	 * @param integer the cellspacing for the table layout. +	 */ +	public function setCellSpacing($value) +	{ +		$this->getStyle()->setCellSpacing($value); +	} + +	/** +	 * @return integer the cellpadding for the table layout. Defaults to -1, meaning not set. +	 */ +	public function getCellPadding() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getCellPadding(); +		else +			return -1; +	} + +	/** +	 * @param integer the cellpadding for the table layout +	 */ +	public function setCellPadding($value) +	{ +		$this->getStyle()->setCellPadding($value); +	} + +	/** +	 * @return THorizontalAlign the horizontal alignment of the table content. Defaults to THorizontalAlign::NotSet. +	 */ +	public function getHorizontalAlign() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getHorizontalAlign(); +		else +			return THorizontalAlign::NotSet; +	} + +	/** +	 * @param THorizontalAlign the horizontal alignment of the table content. +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->getStyle()->setHorizontalAlign($value); +	} + +	/** +	 * @return TTableGridLines the grid line setting of the table layout. Defaults to TTableGridLines::None. +	 */ +	public function getGridLines() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getGridLines(); +		else +			return TTableGridLines::None; +	} + +	/** +	 * Sets the grid line style of the table layout. +	 * @param TTableGridLines the grid line setting of the table +	 */ +	public function setGridLines($value) +	{ +		$this->getStyle()->setGridLines($value); +	} + + +	/** +	 * @return string the field of the data source that provides the keys of the list items. +	 */ +	public function getDataKeyField() +	{ +		return $this->getViewState('DataKeyField',''); +	} + +	/** +	 * @param string the field of the data source that provides the keys of the list items. +	 */ +	public function setDataKeyField($value) +	{ +		$this->setViewState('DataKeyField',$value,''); +	} + +	/** +	 * @return TList the keys used in the data listing control. +	 */ +	public function getDataKeys() +	{ +		if(($dataKeys=$this->getViewState('DataKeys',null))===null) +		{ +			$dataKeys=new TList; +			$this->setViewState('DataKeys',$dataKeys,null); +		} +		return $dataKeys; +	} + +	/** +	 * Returns the value of the data at the specified field. +	 * If data is an array, TMap or TList, the value will be returned at the index +	 * of the specified field. If the data is a component with a property named +	 * as the field name, the property value will be returned. +	 * Otherwise, an exception will be raised. +	 * @param mixed data item +	 * @param mixed field name +	 * @return mixed data value at the specified field +	 * @throws TInvalidDataValueException if the data is invalid +	 */ +	protected function getDataFieldValue($data,$field) +	{ +		return TDataFieldAccessor::getDataFieldValue($data,$field); +	} + +	/** +	 * Raises OnSelectedIndexChanged event. +	 * This method is invoked when a different item is selected +	 * in a data listing control between posts to the server. +	 * @param mixed event parameter +	 */ +	public function onSelectedIndexChanged($param) +	{ +		$this->raiseEvent('OnSelectedIndexChanged',$this,$param); +	} +} + diff --git a/framework/Web/UI/WebControls/TBoundColumn.php b/framework/Web/UI/WebControls/TBoundColumn.php index 43ef28c2..b7bbc5da 100644 --- a/framework/Web/UI/WebControls/TBoundColumn.php +++ b/framework/Web/UI/WebControls/TBoundColumn.php @@ -1,249 +1,249 @@ -<?php
 -/**
 - * TBoundColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -
 -/**
 - * TBoundColumn class
 - *
 - * TBoundColumn represents a column that is bound to a field in a data source.
 - * The cells in the column will be displayed using the data indexed by
 - * {@link setDataField DataField}. You can customize the display by
 - * setting {@link setDataFormatString DataFormatString}.
 - *
 - * If {@link setReadOnly ReadOnly} is false, TBoundColumn will display cells in edit mode
 - * with textboxes. Otherwise, a static text is displayed.
 - *
 - * When a datagrid row is in edit mode, the textbox control in the TBoundColumn
 - * can be accessed by one of the following two methods:
 - * <code>
 - * $datagridItem->BoundColumnID->TextBox
 - * $datagridItem->BoundColumnID->Controls[0]
 - * </code>
 - * The second method is possible because the textbox control created within the
 - * datagrid cell is the first child.
 - *
 - * Since v3.1.0, TBoundColumn has introduced two new properties {@link setItemRenderer ItemRenderer}
 - * and {@link setEditItemRenderer EditItemRenderer} which can be used to specify
 - * the layout of the datagrid cells in browsing and editing mode.
 - * A renderer refers to a control class that is to be instantiated as a control.
 - * For more details, see {@link TRepeater} and {@link TDataList}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TBoundColumn extends TDataGridColumn
 -{
 -	/**
 -	 * @return string the class name for the item cell renderer. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getItemRenderer()
 -	{
 -		return $this->getViewState('ItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the item cell renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as a child control in the item cells of the column.
 -	 *
 -	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property
 -	 * will be set as the data associated with the datagrid cell during databinding.
 -	 * The data can be either the whole data row or a field of the row if
 -	 * {@link getDataField DataField} is not empty. If {@link getDataFormatString DataFormatString}
 -	 * is not empty, the data will be formatted first before passing to the renderer.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @since 3.1.0
 -	 */
 -	public function setItemRenderer($value)
 -	{
 -		$this->setViewState('ItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for the edit item cell renderer. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getEditItemRenderer()
 -	{
 -		return $this->getViewState('EditItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the edit item cell renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as a child control in the item cell that is in edit mode.
 -	 *
 -	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property
 -	 * will be set as the data associated with the datagrid cell during databinding.
 -	 * The data can be either the whole data row or a field of the row if
 -	 * {@link getDataField DataField} is not empty. If {@link getDataFormatString DataFormatString}
 -	 * is not empty, the data will be formatted first before passing to the renderer.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @since 3.1.0
 -	 */
 -	public function setEditItemRenderer($value)
 -	{
 -		$this->setViewState('EditItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field name from the data source to bind to the column
 -	 */
 -	public function getDataField()
 -	{
 -		return $this->getViewState('DataField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the column
 -	 */
 -	public function setDataField($value)
 -	{
 -		$this->setViewState('DataField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the bound data will be displayed.
 -	 */
 -	public function getDataFormatString()
 -	{
 -		return $this->getViewState('DataFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the bound data will be displayed.
 -	 */
 -	public function setDataFormatString($value)
 -	{
 -		$this->setViewState('DataFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether the items in the column can be edited. Defaults to false.
 -	 */
 -	public function getReadOnly()
 -	{
 -		return $this->getViewState('ReadOnly',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the items in the column can be edited
 -	 */
 -	public function setReadOnly($value)
 -	{
 -		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It creates a textbox for item in edit mode and the column is not read-only.
 -	 * Otherwise it displays a static text.
 -	 * The caption of the button and the static text are retrieved
 -	 * from the datasource.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		$item=$cell->getParent();
 -		switch($itemType)
 -		{
 -			case TListItemType::Item:
 -			case TListItemType::AlternatingItem:
 -			case TListItemType::SelectedItem:
 -				if(($classPath=$this->getItemRenderer())!=='')
 -				{
 -					$control=Prado::createComponent($classPath);
 -					if($control instanceof IItemDataRenderer)
 -					{
 -						$control->setItemIndex($item->getItemIndex());
 -						$control->setItemType($item->getItemType());
 -					}
 -					$cell->getControls()->add($control);
 -				}
 -				else
 -					$control=$cell;
 -				$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -				break;
 -			case TListItemType::EditItem:
 -				if(!$this->getReadOnly())
 -				{
 -					if(($classPath=$this->getEditItemRenderer())!=='')
 -					{
 -						$control=Prado::createComponent($classPath);
 -						if($control instanceof IItemDataRenderer)
 -						{
 -							$control->setItemIndex($item->getItemIndex());
 -							$control->setItemType($item->getItemType());
 -						}
 -						$cell->getControls()->add($control);
 -						$cell->registerObject('EditControl',$control);
 -					}
 -					else
 -					{
 -						$control=Prado::createComponent('System.Web.UI.WebControls.TTextBox');
 -						$cell->getControls()->add($control);
 -						$cell->registerObject('TextBox',$control);
 -					}
 -				}
 -				else
 -				{
 -					if(($classPath=$this->getItemRenderer())!=='')
 -					{
 -						$control=Prado::createComponent($classPath);
 -						if($control instanceof IItemDataRenderer)
 -						{
 -							$control->setItemIndex($item->getItemIndex());
 -							$control->setItemType($item->getItemType());
 -						}
 -						$cell->getControls()->add($control);
 -					}
 -					else
 -						$control=$cell;
 -				}
 -				$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -				break;
 -			default:
 -				parent::initializeCell($cell,$columnIndex,$itemType);
 -				break;
 -		}
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		$item=$sender->getNamingContainer();
 -		$data=$item->getData();
 -		$formatString=$this->getDataFormatString();
 -		if(($field=$this->getDataField())!=='')
 -			$value=$this->formatDataValue($formatString,$this->getDataFieldValue($data,$field));
 -		else
 -			$value=$this->formatDataValue($formatString,$data);
 -		$sender->setData($value);
 -	}
 -}
 -
 +<?php +/** + * TBoundColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); + +/** + * TBoundColumn class + * + * TBoundColumn represents a column that is bound to a field in a data source. + * The cells in the column will be displayed using the data indexed by + * {@link setDataField DataField}. You can customize the display by + * setting {@link setDataFormatString DataFormatString}. + * + * If {@link setReadOnly ReadOnly} is false, TBoundColumn will display cells in edit mode + * with textboxes. Otherwise, a static text is displayed. + * + * When a datagrid row is in edit mode, the textbox control in the TBoundColumn + * can be accessed by one of the following two methods: + * <code> + * $datagridItem->BoundColumnID->TextBox + * $datagridItem->BoundColumnID->Controls[0] + * </code> + * The second method is possible because the textbox control created within the + * datagrid cell is the first child. + * + * Since v3.1.0, TBoundColumn has introduced two new properties {@link setItemRenderer ItemRenderer} + * and {@link setEditItemRenderer EditItemRenderer} which can be used to specify + * the layout of the datagrid cells in browsing and editing mode. + * A renderer refers to a control class that is to be instantiated as a control. + * For more details, see {@link TRepeater} and {@link TDataList}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TBoundColumn extends TDataGridColumn +{ +	/** +	 * @return string the class name for the item cell renderer. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getItemRenderer() +	{ +		return $this->getViewState('ItemRenderer',''); +	} + +	/** +	 * Sets the item cell renderer class. +	 * +	 * If not empty, the class will be used to instantiate as a child control in the item cells of the column. +	 * +	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property +	 * will be set as the data associated with the datagrid cell during databinding. +	 * The data can be either the whole data row or a field of the row if +	 * {@link getDataField DataField} is not empty. If {@link getDataFormatString DataFormatString} +	 * is not empty, the data will be formatted first before passing to the renderer. +	 * +	 * @param string the renderer class name in namespace format. +	 * @since 3.1.0 +	 */ +	public function setItemRenderer($value) +	{ +		$this->setViewState('ItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for the edit item cell renderer. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getEditItemRenderer() +	{ +		return $this->getViewState('EditItemRenderer',''); +	} + +	/** +	 * Sets the edit item cell renderer class. +	 * +	 * If not empty, the class will be used to instantiate as a child control in the item cell that is in edit mode. +	 * +	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property +	 * will be set as the data associated with the datagrid cell during databinding. +	 * The data can be either the whole data row or a field of the row if +	 * {@link getDataField DataField} is not empty. If {@link getDataFormatString DataFormatString} +	 * is not empty, the data will be formatted first before passing to the renderer. +	 * +	 * @param string the renderer class name in namespace format. +	 * @since 3.1.0 +	 */ +	public function setEditItemRenderer($value) +	{ +		$this->setViewState('EditItemRenderer',$value,''); +	} + +	/** +	 * @return string the field name from the data source to bind to the column +	 */ +	public function getDataField() +	{ +		return $this->getViewState('DataField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the column +	 */ +	public function setDataField($value) +	{ +		$this->setViewState('DataField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the bound data will be displayed. +	 */ +	public function getDataFormatString() +	{ +		return $this->getViewState('DataFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the bound data will be displayed. +	 */ +	public function setDataFormatString($value) +	{ +		$this->setViewState('DataFormatString',$value,''); +	} + +	/** +	 * @return boolean whether the items in the column can be edited. Defaults to false. +	 */ +	public function getReadOnly() +	{ +		return $this->getViewState('ReadOnly',false); +	} + +	/** +	 * @param boolean whether the items in the column can be edited +	 */ +	public function setReadOnly($value) +	{ +		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It creates a textbox for item in edit mode and the column is not read-only. +	 * Otherwise it displays a static text. +	 * The caption of the button and the static text are retrieved +	 * from the datasource. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		$item=$cell->getParent(); +		switch($itemType) +		{ +			case TListItemType::Item: +			case TListItemType::AlternatingItem: +			case TListItemType::SelectedItem: +				if(($classPath=$this->getItemRenderer())!=='') +				{ +					$control=Prado::createComponent($classPath); +					if($control instanceof IItemDataRenderer) +					{ +						$control->setItemIndex($item->getItemIndex()); +						$control->setItemType($item->getItemType()); +					} +					$cell->getControls()->add($control); +				} +				else +					$control=$cell; +				$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +				break; +			case TListItemType::EditItem: +				if(!$this->getReadOnly()) +				{ +					if(($classPath=$this->getEditItemRenderer())!=='') +					{ +						$control=Prado::createComponent($classPath); +						if($control instanceof IItemDataRenderer) +						{ +							$control->setItemIndex($item->getItemIndex()); +							$control->setItemType($item->getItemType()); +						} +						$cell->getControls()->add($control); +						$cell->registerObject('EditControl',$control); +					} +					else +					{ +						$control=Prado::createComponent('System.Web.UI.WebControls.TTextBox'); +						$cell->getControls()->add($control); +						$cell->registerObject('TextBox',$control); +					} +				} +				else +				{ +					if(($classPath=$this->getItemRenderer())!=='') +					{ +						$control=Prado::createComponent($classPath); +						if($control instanceof IItemDataRenderer) +						{ +							$control->setItemIndex($item->getItemIndex()); +							$control->setItemType($item->getItemType()); +						} +						$cell->getControls()->add($control); +					} +					else +						$control=$cell; +				} +				$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +				break; +			default: +				parent::initializeCell($cell,$columnIndex,$itemType); +				break; +		} +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		$item=$sender->getNamingContainer(); +		$data=$item->getData(); +		$formatString=$this->getDataFormatString(); +		if(($field=$this->getDataField())!=='') +			$value=$this->formatDataValue($formatString,$this->getDataFieldValue($data,$field)); +		else +			$value=$this->formatDataValue($formatString,$data); +		$sender->setData($value); +	} +} + diff --git a/framework/Web/UI/WebControls/TBulletedList.php b/framework/Web/UI/WebControls/TBulletedList.php index 1b32059f..51982c3e 100644 --- a/framework/Web/UI/WebControls/TBulletedList.php +++ b/framework/Web/UI/WebControls/TBulletedList.php @@ -1,492 +1,492 @@ -<?php
 -/**
 - * TBulletedList class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TBulletedList class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TListControl class
 - */
 -Prado::using('System.Web.UI.WebControls.TListControl');
 -
 -/**
 - * TBulletedList class
 - *
 - * TBulletedList displays items in a bullet format.
 - * The bullet style is specified by {@link setBulletStyle BulletStyle}. When
 - * the style is 'CustomImage', the {@link setBackImageUrl BulletImageUrl}
 - * specifies the image used as bullets.
 - *
 - * TBulletedList displays the item texts in three different modes, specified
 - * via {@link setDisplayMode DisplayMode}. When the mode is Text, the item texts
 - * are displayed as static texts; When the mode is 'HyperLink', each item
 - * is displayed as a hyperlink whose URL is given by the item value, and the
 - * {@link setTarget Target} property can be used to specify the target browser window;
 - * When the mode is 'LinkButton', each item is displayed as a link button which
 - * posts back to the page if a user clicks on that and the event {@link onClick OnClick}
 - * will be raised under such a circumstance.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TBulletedList extends TListControl implements IPostBackEventHandler
 -{
 -	/**
 -	 * @var boolean cached property value of Enabled
 -	 */
 -	private $_isEnabled;
 -	/**
 -	 * @var TPostBackOptions postback options
 -	 */
 -	private $_postBackOptions;
 -
 -	private $_currentRenderItemIndex;
 -
 -	/**
 -	 * Raises the postback event.
 -	 * This method is required by {@link IPostBackEventHandler} interface.
 -	 * If {@link getCausesValidation CausesValidation} is true, it will
 -	 * invoke the page's {@link TPage::validate validate} method first.
 -	 * It will raise {@link onClick OnClick} events.
 -	 * This method is mainly used by framework and control developers.
 -	 * @param TEventParameter the event parameter
 -	 */
 -	public function raisePostBackEvent($param)
 -	{
 -		if($this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onClick(new TBulletedListEventParameter((int)$param));
 -	}
 -
 -	/**
 -	 * @return string tag name of the bulleted list
 -	 */
 -	protected function getTagName()
 -	{
 -		switch($this->getBulletStyle())
 -		{
 -			case TBulletStyle::Numbered:
 -			case TBulletStyle::LowerAlpha:
 -			case TBulletStyle::UpperAlpha:
 -			case TBulletStyle::LowerRoman:
 -			case TBulletStyle::UpperRoman:
 -				return 'ol';
 -		}
 -		return 'ul';
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TBulletedList';
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This overrides the parent implementation with additional bulleted list specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$needStart=false;
 -		switch($this->getBulletStyle())
 -		{
 -			case TBulletStyle::None:
 -				$writer->addStyleAttribute('list-style-type','none');
 -				$needStart=true;
 -				break;
 -			case TBulletStyle::Numbered:
 -				$writer->addStyleAttribute('list-style-type','decimal');
 -				$needStart=true;
 -				break;
 -			case TBulletStyle::LowerAlpha:
 -				$writer->addStyleAttribute('list-style-type','lower-alpha');
 -				$needStart=true;
 -				break;
 -			case TBulletStyle::UpperAlpha:
 -				$writer->addStyleAttribute('list-style-type','upper-alpha');
 -				$needStart=true;
 -				break;
 -			case TBulletStyle::LowerRoman:
 -				$writer->addStyleAttribute('list-style-type','lower-roman');
 -				$needStart=true;
 -				break;
 -			case TBulletStyle::UpperRoman:
 -				$writer->addStyleAttribute('list-style-type','upper-roman');
 -				$needStart=true;
 -				break;
 -			case TBulletStyle::Disc:
 -				$writer->addStyleAttribute('list-style-type','disc');
 -				break;
 -			case TBulletStyle::Circle:
 -				$writer->addStyleAttribute('list-style-type','circle');
 -				break;
 -			case TBulletStyle::Square:
 -				$writer->addStyleAttribute('list-style-type','square');
 -				break;
 -			case TBulletStyle::CustomImage:
 -				$url=$this->getBulletImageUrl();
 -				$writer->addStyleAttribute('list-style-image',"url($url)");
 -				break;
 -		}
 -		if($needStart && ($start=$this->getFirstBulletNumber())!=1)
 -			$writer->addAttribute('start',"$start");
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * @return string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'.
 -	 */
 -	public function getBulletImageUrl()
 -	{
 -		return $this->getViewState('BulletImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'.
 -	 */
 -	public function setBulletImageUrl($value)
 -	{
 -		$this->setViewState('BulletImageUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return TBulletStyle style of bullets. Defaults to TBulletStyle::NotSet.
 -	 */
 -	public function getBulletStyle()
 -	{
 -		return $this->getViewState('BulletStyle',TBulletStyle::NotSet);
 -	}
 -
 -	/**
 -	 * @param TBulletStyle style of bullets.
 -	 */
 -	public function setBulletStyle($value)
 -	{
 -		$this->setViewState('BulletStyle',TPropertyValue::ensureEnum($value,'TBulletStyle'),TBulletStyle::NotSet);
 -	}
 -
 -	/**
 -	 * @return TBulletedListDisplayMode display mode of the list. Defaults to TBulletedListDisplayMode::Text.
 -	 */
 -	public function getDisplayMode()
 -	{
 -		return $this->getViewState('DisplayMode',TBulletedListDisplayMode::Text);
 -	}
 -
 -	/**
 -	 * @return TBulletedListDisplayMode display mode of the list.
 -	 */
 -	public function setDisplayMode($value)
 -	{
 -		$this->setViewState('DisplayMode',TPropertyValue::ensureEnum($value,'TBulletedListDisplayMode'),TBulletedListDisplayMode::Text);
 -	}
 -
 -	/**
 -	 * @return integer starting index when {@link getBulletStyle BulletStyle} is one of
 -	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'.
 -	 * Defaults to 1.
 -	 */
 -	public function getFirstBulletNumber()
 -	{
 -		return $this->getViewState('FirstBulletNumber',1);
 -	}
 -
 -	/**
 -	 * @param integer starting index when {@link getBulletStyle BulletStyle} is one of
 -	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'.
 -	 */
 -	public function setFirstBulletNumber($value)
 -	{
 -		$this->setViewState('FirstBulletNumber',TPropertyValue::ensureInteger($value),1);
 -	}
 -
 -	/**
 -	 * Raises 'OnClick' event.
 -	 * This method is invoked when the {@link getDisplayMode DisplayMode} is 'LinkButton'
 -	 * and end-users click on one of the buttons.
 -	 * @param TBulletedListEventParameter event parameter.
 -	 */
 -	public function onClick($param)
 -	{
 -		$this->raiseEvent('OnClick',$this,$param);
 -	}
 -
 -	/**
 -	 * @return string the target window or frame to display the Web page content
 -	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of
 -	 * the hyperlinks is clicked.
 -	 */
 -	public function getTarget()
 -	{
 -		return $this->getViewState('Target','');
 -	}
 -
 -	/**
 -	 * @param string the target window or frame to display the Web page content
 -	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of
 -	 * the hyperlinks is clicked.
 -	 */
 -	public function setTarget($value)
 -	{
 -		$this->setViewState('Target',$value,'');
 -	}
 -
 -	/**
 -	 * Renders the control.
 -	 * @param THtmlWriter the writer for the rendering purpose.
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->getHasItems())
 -			parent::render($writer);
 -	}
 -
 -	/**
 -	 * Renders the body contents.
 -	 * @param THtmlWriter the writer for the rendering purpose.
 -	 */
 -	public function renderContents($writer)
 -	{
 -		$this->_isEnabled=$this->getEnabled(true);
 -		$this->_postBackOptions=$this->getPostBackOptions();
 -		$writer->writeLine();
 -		foreach($this->getItems() as $index=>$item)
 -		{
 -			if($item->getHasAttributes())
 -				$writer->addAttributes($item->getAttributes());
 -			$writer->renderBeginTag('li');
 -			$this->renderBulletText($writer,$item,$index);
 -			$writer->renderEndTag();
 -			$writer->writeLine();
 -		}
 -	}
 -
 -	/**
 -	 * Renders each item
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param TListItem item to be rendered
 -	 * @param integer index of the item being rendered
 -	 */
 -	protected function renderBulletText($writer,$item,$index)
 -	{
 -		switch($this->getDisplayMode())
 -		{
 -			case TBulletedListDisplayMode::Text:
 -				$this->renderTextItem($writer, $item, $index);
 -				break;
 -			case TBulletedListDisplayMode::HyperLink:
 -				$this->renderHyperLinkItem($writer, $item, $index);
 -				break;
 -			case TBulletedListDisplayMode::LinkButton:
 -				$this->renderLinkButtonItem($writer, $item, $index);
 -				break;
 -		}
 -	}
 -
 -	protected function renderTextItem($writer, $item, $index)
 -	{
 -		if($item->getEnabled())
 -			$writer->write(THttpUtility::htmlEncode($item->getText()));
 -		else
 -		{
 -			$writer->addAttribute('disabled','disabled');
 -			$writer->renderBeginTag('span');
 -			$writer->write(THttpUtility::htmlEncode($item->getText()));
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	protected function renderHyperLinkItem($writer, $item, $index)
 -	{
 -		if(!$this->_isEnabled || !$item->getEnabled())
 -			$writer->addAttribute('disabled','disabled');
 -		else
 -		{
 -			$writer->addAttribute('href',$item->getValue());
 -			if(($target=$this->getTarget())!=='')
 -				$writer->addAttribute('target',$target);
 -		}
 -		if(($accesskey=$this->getAccessKey())!=='')
 -			$writer->addAttribute('accesskey',$accesskey);
 -		$writer->renderBeginTag('a');
 -		$writer->write(THttpUtility::htmlEncode($item->getText()));
 -		$writer->renderEndTag();
 -	}
 -
 -	protected function renderLinkButtonItem($writer, $item, $index)
 -	{
 -		if(!$this->_isEnabled || !$item->getEnabled())
 -			$writer->addAttribute('disabled','disabled');
 -		else
 -		{
 -			$this->_currentRenderItemIndex = $index;
 -			$writer->addAttribute('id', $this->getClientID().$index);
 -			$writer->addAttribute('href', "javascript:;//".$this->getClientID().$index);
 -			$cs = $this->getPage()->getClientScript();
 -			$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -		}
 -		if(($accesskey=$this->getAccessKey())!=='')
 -			$writer->addAttribute('accesskey',$accesskey);
 -		$writer->renderBeginTag('a');
 -		$writer->write(THttpUtility::htmlEncode($item->getText()));
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * @return array postback options used for linkbuttons.
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		$options['EventParameter'] = $this->_currentRenderItemIndex;
 -		$options['ID'] = $this->getClientID().$this->_currentRenderItemIndex;
 -		$options['StopEvent'] = true;
 -		return $options;
 -	}
 -
 -	protected function canCauseValidation()
 -	{
 -		$group = $this->getValidationGroup();
 -		$hasValidators = $this->getPage()->getValidators($group)->getCount()>0;
 -		return $this->getCausesValidation() && $hasValidators;
 -	}
 -
 -	/**
 -	 * @throws TNotSupportedException if this method is invoked
 -	 */
 -	public function setAutoPostBack($value)
 -	{
 -		throw new TNotSupportedException('bulletedlist_autopostback_unsupported');
 -	}
 -
 -	/**
 -	 * @throws TNotSupportedException if this method is invoked
 -	 */
 -	public function setSelectedIndex($index)
 -	{
 -		throw new TNotSupportedException('bulletedlist_selectedindex_unsupported');
 -	}
 -
 -	/**
 -	 * @throws TNotSupportedException if this method is invoked
 -	 */
 -	public function setSelectedIndices($indices)
 -	{
 -		throw new TNotSupportedException('bulletedlist_selectedindices_unsupported');
 -	}
 -
 -	/**
 -	 * @throws TNotSupportedException if this method is invoked
 -	 */
 -	public function setSelectedValue($value)
 -	{
 -		throw new TNotSupportedException('bulletedlist_selectedvalue_unsupported');
 -	}
 -
 -	/**
 -	 * @throws TNotSupportedException if this method is invoked
 -	 */
 -	public function setSelectedValues($values)
 -	{
 -		throw new TNotSupportedException('bulletedlist_selectedvalue_unsupported');
 -	}
 -}
 -
 -/**
 - * TBulletedListEventParameter
 - * Event parameter for {@link TBulletedList::onClick Click} event of the
 - * bulleted list. The {@link getIndex Index} gives the zero-based index
 - * of the item that is currently being clicked.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TBulletedListEventParameter extends TEventParameter
 -{
 -	/**
 -	 * @var integer index of the item clicked
 -	 */
 -	private $_index;
 -
 -	/**
 -	 * Constructor.
 -	 * @param integer index of the item clicked
 -	 */
 -	public function __construct($index)
 -	{
 -		$this->_index=$index;
 -	}
 -
 -	/**
 -	 * @return integer zero-based index of the item (rendered as a link button) that is clicked
 -	 */
 -	public function getIndex()
 -	{
 -		return $this->_index;
 -	}
 -}
 -
 -/**
 - * TBulletStyle class.
 - * TBulletStyle defines the enumerable type for the possible bullet styles that may be used
 - * for a {@link TBulletedList} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TBulletStyle extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const None='None';
 -	const Numbered='Numbered';
 -	const LowerAlpha='LowerAlpha';
 -	const UpperAlpha='UpperAlpha';
 -	const LowerRoman='LowerRoman';
 -	const UpperRoman='UpperRoman';
 -	const Disc='Disc';
 -	const Circle='Circle';
 -	const Square='Square';
 -	const CustomImage='CustomImage';
 -}
 -
 -/**
 - * TBulletedListDisplayMode class.
 - * TBulletedListDisplayMode defines the enumerable type for the possible display mode
 - * of a {@link TBulletedList} control.
 - *
 - * The following enumerable values are defined:
 - * - Text: the bulleted list items are displayed as plain texts
 - * - HyperLink: the bulleted list items are displayed as hyperlinks
 - * - LinkButton: the bulleted list items are displayed as link buttons that can cause postbacks
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TBulletedListDisplayMode extends TEnumerable
 -{
 -	const Text='Text';
 -	const HyperLink='HyperLink';
 -	const LinkButton='LinkButton';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TListControl class + */ +Prado::using('System.Web.UI.WebControls.TListControl'); + +/** + * TBulletedList class + * + * TBulletedList displays items in a bullet format. + * The bullet style is specified by {@link setBulletStyle BulletStyle}. When + * the style is 'CustomImage', the {@link setBackImageUrl BulletImageUrl} + * specifies the image used as bullets. + * + * TBulletedList displays the item texts in three different modes, specified + * via {@link setDisplayMode DisplayMode}. When the mode is Text, the item texts + * are displayed as static texts; When the mode is 'HyperLink', each item + * is displayed as a hyperlink whose URL is given by the item value, and the + * {@link setTarget Target} property can be used to specify the target browser window; + * When the mode is 'LinkButton', each item is displayed as a link button which + * posts back to the page if a user clicks on that and the event {@link onClick OnClick} + * will be raised under such a circumstance. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TBulletedList extends TListControl implements IPostBackEventHandler +{ +	/** +	 * @var boolean cached property value of Enabled +	 */ +	private $_isEnabled; +	/** +	 * @var TPostBackOptions postback options +	 */ +	private $_postBackOptions; + +	private $_currentRenderItemIndex; + +	/** +	 * Raises the postback event. +	 * This method is required by {@link IPostBackEventHandler} interface. +	 * If {@link getCausesValidation CausesValidation} is true, it will +	 * invoke the page's {@link TPage::validate validate} method first. +	 * It will raise {@link onClick OnClick} events. +	 * This method is mainly used by framework and control developers. +	 * @param TEventParameter the event parameter +	 */ +	public function raisePostBackEvent($param) +	{ +		if($this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onClick(new TBulletedListEventParameter((int)$param)); +	} + +	/** +	 * @return string tag name of the bulleted list +	 */ +	protected function getTagName() +	{ +		switch($this->getBulletStyle()) +		{ +			case TBulletStyle::Numbered: +			case TBulletStyle::LowerAlpha: +			case TBulletStyle::UpperAlpha: +			case TBulletStyle::LowerRoman: +			case TBulletStyle::UpperRoman: +				return 'ol'; +		} +		return 'ul'; +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TBulletedList'; +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This overrides the parent implementation with additional bulleted list specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$needStart=false; +		switch($this->getBulletStyle()) +		{ +			case TBulletStyle::None: +				$writer->addStyleAttribute('list-style-type','none'); +				$needStart=true; +				break; +			case TBulletStyle::Numbered: +				$writer->addStyleAttribute('list-style-type','decimal'); +				$needStart=true; +				break; +			case TBulletStyle::LowerAlpha: +				$writer->addStyleAttribute('list-style-type','lower-alpha'); +				$needStart=true; +				break; +			case TBulletStyle::UpperAlpha: +				$writer->addStyleAttribute('list-style-type','upper-alpha'); +				$needStart=true; +				break; +			case TBulletStyle::LowerRoman: +				$writer->addStyleAttribute('list-style-type','lower-roman'); +				$needStart=true; +				break; +			case TBulletStyle::UpperRoman: +				$writer->addStyleAttribute('list-style-type','upper-roman'); +				$needStart=true; +				break; +			case TBulletStyle::Disc: +				$writer->addStyleAttribute('list-style-type','disc'); +				break; +			case TBulletStyle::Circle: +				$writer->addStyleAttribute('list-style-type','circle'); +				break; +			case TBulletStyle::Square: +				$writer->addStyleAttribute('list-style-type','square'); +				break; +			case TBulletStyle::CustomImage: +				$url=$this->getBulletImageUrl(); +				$writer->addStyleAttribute('list-style-image',"url($url)"); +				break; +		} +		if($needStart && ($start=$this->getFirstBulletNumber())!=1) +			$writer->addAttribute('start',"$start"); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * @return string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'. +	 */ +	public function getBulletImageUrl() +	{ +		return $this->getViewState('BulletImageUrl',''); +	} + +	/** +	 * @param string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'. +	 */ +	public function setBulletImageUrl($value) +	{ +		$this->setViewState('BulletImageUrl',$value,''); +	} + +	/** +	 * @return TBulletStyle style of bullets. Defaults to TBulletStyle::NotSet. +	 */ +	public function getBulletStyle() +	{ +		return $this->getViewState('BulletStyle',TBulletStyle::NotSet); +	} + +	/** +	 * @param TBulletStyle style of bullets. +	 */ +	public function setBulletStyle($value) +	{ +		$this->setViewState('BulletStyle',TPropertyValue::ensureEnum($value,'TBulletStyle'),TBulletStyle::NotSet); +	} + +	/** +	 * @return TBulletedListDisplayMode display mode of the list. Defaults to TBulletedListDisplayMode::Text. +	 */ +	public function getDisplayMode() +	{ +		return $this->getViewState('DisplayMode',TBulletedListDisplayMode::Text); +	} + +	/** +	 * @return TBulletedListDisplayMode display mode of the list. +	 */ +	public function setDisplayMode($value) +	{ +		$this->setViewState('DisplayMode',TPropertyValue::ensureEnum($value,'TBulletedListDisplayMode'),TBulletedListDisplayMode::Text); +	} + +	/** +	 * @return integer starting index when {@link getBulletStyle BulletStyle} is one of +	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'. +	 * Defaults to 1. +	 */ +	public function getFirstBulletNumber() +	{ +		return $this->getViewState('FirstBulletNumber',1); +	} + +	/** +	 * @param integer starting index when {@link getBulletStyle BulletStyle} is one of +	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'. +	 */ +	public function setFirstBulletNumber($value) +	{ +		$this->setViewState('FirstBulletNumber',TPropertyValue::ensureInteger($value),1); +	} + +	/** +	 * Raises 'OnClick' event. +	 * This method is invoked when the {@link getDisplayMode DisplayMode} is 'LinkButton' +	 * and end-users click on one of the buttons. +	 * @param TBulletedListEventParameter event parameter. +	 */ +	public function onClick($param) +	{ +		$this->raiseEvent('OnClick',$this,$param); +	} + +	/** +	 * @return string the target window or frame to display the Web page content +	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of +	 * the hyperlinks is clicked. +	 */ +	public function getTarget() +	{ +		return $this->getViewState('Target',''); +	} + +	/** +	 * @param string the target window or frame to display the Web page content +	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of +	 * the hyperlinks is clicked. +	 */ +	public function setTarget($value) +	{ +		$this->setViewState('Target',$value,''); +	} + +	/** +	 * Renders the control. +	 * @param THtmlWriter the writer for the rendering purpose. +	 */ +	public function render($writer) +	{ +		if($this->getHasItems()) +			parent::render($writer); +	} + +	/** +	 * Renders the body contents. +	 * @param THtmlWriter the writer for the rendering purpose. +	 */ +	public function renderContents($writer) +	{ +		$this->_isEnabled=$this->getEnabled(true); +		$this->_postBackOptions=$this->getPostBackOptions(); +		$writer->writeLine(); +		foreach($this->getItems() as $index=>$item) +		{ +			if($item->getHasAttributes()) +				$writer->addAttributes($item->getAttributes()); +			$writer->renderBeginTag('li'); +			$this->renderBulletText($writer,$item,$index); +			$writer->renderEndTag(); +			$writer->writeLine(); +		} +	} + +	/** +	 * Renders each item +	 * @param THtmlWriter writer for the rendering purpose +	 * @param TListItem item to be rendered +	 * @param integer index of the item being rendered +	 */ +	protected function renderBulletText($writer,$item,$index) +	{ +		switch($this->getDisplayMode()) +		{ +			case TBulletedListDisplayMode::Text: +				$this->renderTextItem($writer, $item, $index); +				break; +			case TBulletedListDisplayMode::HyperLink: +				$this->renderHyperLinkItem($writer, $item, $index); +				break; +			case TBulletedListDisplayMode::LinkButton: +				$this->renderLinkButtonItem($writer, $item, $index); +				break; +		} +	} + +	protected function renderTextItem($writer, $item, $index) +	{ +		if($item->getEnabled()) +			$writer->write(THttpUtility::htmlEncode($item->getText())); +		else +		{ +			$writer->addAttribute('disabled','disabled'); +			$writer->renderBeginTag('span'); +			$writer->write(THttpUtility::htmlEncode($item->getText())); +			$writer->renderEndTag(); +		} +	} + +	protected function renderHyperLinkItem($writer, $item, $index) +	{ +		if(!$this->_isEnabled || !$item->getEnabled()) +			$writer->addAttribute('disabled','disabled'); +		else +		{ +			$writer->addAttribute('href',$item->getValue()); +			if(($target=$this->getTarget())!=='') +				$writer->addAttribute('target',$target); +		} +		if(($accesskey=$this->getAccessKey())!=='') +			$writer->addAttribute('accesskey',$accesskey); +		$writer->renderBeginTag('a'); +		$writer->write(THttpUtility::htmlEncode($item->getText())); +		$writer->renderEndTag(); +	} + +	protected function renderLinkButtonItem($writer, $item, $index) +	{ +		if(!$this->_isEnabled || !$item->getEnabled()) +			$writer->addAttribute('disabled','disabled'); +		else +		{ +			$this->_currentRenderItemIndex = $index; +			$writer->addAttribute('id', $this->getClientID().$index); +			$writer->addAttribute('href', "javascript:;//".$this->getClientID().$index); +			$cs = $this->getPage()->getClientScript(); +			$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +		} +		if(($accesskey=$this->getAccessKey())!=='') +			$writer->addAttribute('accesskey',$accesskey); +		$writer->renderBeginTag('a'); +		$writer->write(THttpUtility::htmlEncode($item->getText())); +		$writer->renderEndTag(); +	} + +	/** +	 * @return array postback options used for linkbuttons. +	 */ +	protected function getPostBackOptions() +	{ +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['EventTarget'] = $this->getUniqueID(); +		$options['EventParameter'] = $this->_currentRenderItemIndex; +		$options['ID'] = $this->getClientID().$this->_currentRenderItemIndex; +		$options['StopEvent'] = true; +		return $options; +	} + +	protected function canCauseValidation() +	{ +		$group = $this->getValidationGroup(); +		$hasValidators = $this->getPage()->getValidators($group)->getCount()>0; +		return $this->getCausesValidation() && $hasValidators; +	} + +	/** +	 * @throws TNotSupportedException if this method is invoked +	 */ +	public function setAutoPostBack($value) +	{ +		throw new TNotSupportedException('bulletedlist_autopostback_unsupported'); +	} + +	/** +	 * @throws TNotSupportedException if this method is invoked +	 */ +	public function setSelectedIndex($index) +	{ +		throw new TNotSupportedException('bulletedlist_selectedindex_unsupported'); +	} + +	/** +	 * @throws TNotSupportedException if this method is invoked +	 */ +	public function setSelectedIndices($indices) +	{ +		throw new TNotSupportedException('bulletedlist_selectedindices_unsupported'); +	} + +	/** +	 * @throws TNotSupportedException if this method is invoked +	 */ +	public function setSelectedValue($value) +	{ +		throw new TNotSupportedException('bulletedlist_selectedvalue_unsupported'); +	} + +	/** +	 * @throws TNotSupportedException if this method is invoked +	 */ +	public function setSelectedValues($values) +	{ +		throw new TNotSupportedException('bulletedlist_selectedvalue_unsupported'); +	} +} + +/** + * TBulletedListEventParameter + * Event parameter for {@link TBulletedList::onClick Click} event of the + * bulleted list. The {@link getIndex Index} gives the zero-based index + * of the item that is currently being clicked. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TBulletedListEventParameter extends TEventParameter +{ +	/** +	 * @var integer index of the item clicked +	 */ +	private $_index; + +	/** +	 * Constructor. +	 * @param integer index of the item clicked +	 */ +	public function __construct($index) +	{ +		$this->_index=$index; +	} + +	/** +	 * @return integer zero-based index of the item (rendered as a link button) that is clicked +	 */ +	public function getIndex() +	{ +		return $this->_index; +	} +} + +/** + * TBulletStyle class. + * TBulletStyle defines the enumerable type for the possible bullet styles that may be used + * for a {@link TBulletedList} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TBulletStyle extends TEnumerable +{ +	const NotSet='NotSet'; +	const None='None'; +	const Numbered='Numbered'; +	const LowerAlpha='LowerAlpha'; +	const UpperAlpha='UpperAlpha'; +	const LowerRoman='LowerRoman'; +	const UpperRoman='UpperRoman'; +	const Disc='Disc'; +	const Circle='Circle'; +	const Square='Square'; +	const CustomImage='CustomImage'; +} + +/** + * TBulletedListDisplayMode class. + * TBulletedListDisplayMode defines the enumerable type for the possible display mode + * of a {@link TBulletedList} control. + * + * The following enumerable values are defined: + * - Text: the bulleted list items are displayed as plain texts + * - HyperLink: the bulleted list items are displayed as hyperlinks + * - LinkButton: the bulleted list items are displayed as link buttons that can cause postbacks + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TBulletedListDisplayMode extends TEnumerable +{ +	const Text='Text'; +	const HyperLink='HyperLink'; +	const LinkButton='LinkButton'; +} + diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php index 71256a5b..caa0332c 100644 --- a/framework/Web/UI/WebControls/TButton.php +++ b/framework/Web/UI/WebControls/TButton.php @@ -1,368 +1,368 @@ -<?php
 -/**
 - * TButton class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TButton class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TButton class
 - *
 - * TButton creates a click button on the page. It is mainly used to submit data to a page.
 - *
 - * TButton raises two server-side events, {@link onClick OnClick} and {@link onCommand OnCommand},
 - * when it is clicked on the client-side. The difference between these two events
 - * is that the event {@link onCommand OnCommand} is bubbled up to the button's ancestor controls.
 - * And within the event parameter for {@link onCommand OnCommand} contains the reference
 - * to the {@link setCommandName CommandName} and {@link setCommandParameter CommandParameter}
 - * property values that are set for the button object. This allows you to create multiple TButton
 - * components on a Web page and programmatically determine which one is clicked
 - * with what parameter.
 - *
 - * Clicking on button can also trigger form validation, if
 - * {@link setCausesValidation CausesValidation} is true.
 - * The validation may be restricted within a certain group of validator
 - * controls by setting {@link setValidationGroup ValidationGroup} property.
 - * If validation is successful, the data will be post back to the same page.
 - *
 - * TButton displays the {@link setText Text} property as the button caption.
 - *
 - * TButton can be one of three {@link setButtonType ButtonType}: Submit, Button and Reset.
 - * By default, it is a Submit button and the form submission uses the browser's
 - * default submission capability. If it is Button or Reset, postback may occur
 - * if one of the following conditions is met:
 - * - an event handler is attached to {@link onClick OnClick} event;
 - * - an event handler is attached to {@link onCommand OnCommand} event;
 - * - the button is in a non-empty validation group.
 - * In addition, clicking on a Reset button will clear up all input fields
 - * if the button does not cause a postback.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer
 -{
 -	/**
 -	 * @return string tag name of the button
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'input';
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This overrides the parent implementation with additional button specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$page=$this->getPage();
 -		$page->ensureRenderInForm($this);
 -		$writer->addAttribute('type',strtolower($this->getButtonType()));
 -		if(($uniqueID=$this->getUniqueID())!=='')
 -			$writer->addAttribute('name',$uniqueID);
 -		$writer->addAttribute('value',$this->getText());
 -		if($this->getEnabled(true))
 -		{
 -			if($this->getEnableClientScript() && $this->needPostBackScript())
 -				$this->renderClientControlScript($writer);
 -		}
 -		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
 -			$writer->addAttribute('disabled','disabled');
 -
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the client-script code.
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$writer->addAttribute('id',$this->getClientID());
 -		$this->getPage()->getClientScript()->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TButton';
 -	}
 -
 -	/**
 -	 * @return boolean whether to perform validation if the button is clicked
 -	 */
 -	protected function canCauseValidation()
 -	{
 -		if($this->getCausesValidation())
 -		{
 -			$group=$this->getValidationGroup();
 -			return $this->getPage()->getValidators($group)->getCount()>0;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @param boolean set by a panel to register this button as the default button for the panel.
 -	 */
 -	public function setIsDefaultButton($value)
 -	{
 -		$this->setViewState('IsDefaultButton', TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean true if this button is registered as a default button for a panel.
 -	 */
 -	public function getIsDefaultButton()
 -	{
 -		return $this->getViewState('IsDefaultButton', false);
 -	}
 -
 -	/**
 -	 * @return boolean whether the button needs javascript to do postback
 -	 */
 -	protected function needPostBackScript()
 -	{
 -		return $this->canCauseValidation() || ($this->getButtonType()!==TButtonType::Submit &&
 -			($this->hasEventHandler('OnClick') || $this->hasEventHandler('OnCommand')))
 -			|| $this->getIsDefaultButton();
 -	}
 -
 -	/**
 -	 * Returns postback specifications for the button.
 -	 * This method is used by framework and control developers.
 -	 * @return array parameters about how the button defines its postback behavior.
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ID']=$this->getClientID();
 -		$options['CausesValidation']=$this->getCausesValidation();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		$options['ValidationGroup']=$this->getValidationGroup();
 -
 -		return $options;
 -	}
 -
 -	/**
 -	 * Renders the body content enclosed between the control tag.
 -	 * This overrides the parent implementation with nothing to be rendered.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -	}
 -
 -	/**
 -	 * This method is invoked when the button is clicked.
 -	 * The method raises 'OnClick' event to fire up the event handlers.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handler can be invoked.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onClick($param)
 -	{
 -		$this->raiseEvent('OnClick',$this,$param);
 -	}
 -
 -	/**
 -	 * This method is invoked when the button is clicked.
 -	 * The method raises 'OnCommand' event to fire up the event handlers.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handlers can be invoked.
 -	 * @param TCommandEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onCommand($param)
 -	{
 -		$this->raiseEvent('OnCommand',$this,$param);
 -		$this->raiseBubbleEvent($this,$param);
 -	}
 -
 -	/**
 -	 * Raises the postback event.
 -	 * This method is required by {@link IPostBackEventHandler} interface.
 -	 * If {@link getCausesValidation CausesValidation} is true, it will
 -	 * invoke the page's {@link TPage::validate validate} method first.
 -	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
 -	 * This method is mainly used by framework and control developers.
 -	 * @param TEventParameter the event parameter
 -	 */
 -	public function raisePostBackEvent($param)
 -	{
 -		if($this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onClick(null);
 -		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
 -	}
 -
 -	/**
 -	 * @return string caption of the button
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * @param string caption of the button
 -	 */
 -	public function setText($value)
 -	{
 -		$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
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by this button will cause input validation
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the command name associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function getCommandName()
 -	{
 -		return $this->getViewState('CommandName','');
 -	}
 -
 -	/**
 -	 * @param string the command name associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function setCommandName($value)
 -	{
 -		$this->setViewState('CommandName',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the parameter associated with the {@link onCommand OnCommand} event
 -	 */
 -	public function getCommandParameter()
 -	{
 -		return $this->getViewState('CommandParameter','');
 -	}
 -
 -	/**
 -	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function setCommandParameter($value)
 -	{
 -		$this->setViewState('CommandParameter',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the button causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the button causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * @return TButtonType the type of the button. Defaults to TButtonType::Submit.
 -	 */
 -	public function getButtonType()
 -	{
 -		return $this->getViewState('ButtonType',TButtonType::Submit);
 -	}
 -
 -	/**
 -	 * @param TButtonType the type of the button.
 -	 */
 -	public function setButtonType($value)
 -	{
 -		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TButtonType'),TButtonType::Submit);
 -	}
 -}
 -
 -/**
 - * TButtonType class.
 - * TButtonType defines the enumerable type for the possible types that a {@link TButton} can take.
 - *
 - * The following enumerable values are defined:
 - * - Submit: a normal submit button
 - * - Reset: a reset button
 - * - Button: a client button (normally does not perform form submission)
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TButtonType extends TEnumerable
 -{
 -	const Submit='Submit';
 -	const Reset='Reset';
 -	const Button='Button';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TButton class + * + * TButton creates a click button on the page. It is mainly used to submit data to a page. + * + * TButton raises two server-side events, {@link onClick OnClick} and {@link onCommand OnCommand}, + * when it is clicked on the client-side. The difference between these two events + * is that the event {@link onCommand OnCommand} is bubbled up to the button's ancestor controls. + * And within the event parameter for {@link onCommand OnCommand} contains the reference + * to the {@link setCommandName CommandName} and {@link setCommandParameter CommandParameter} + * property values that are set for the button object. This allows you to create multiple TButton + * components on a Web page and programmatically determine which one is clicked + * with what parameter. + * + * Clicking on button can also trigger form validation, if + * {@link setCausesValidation CausesValidation} is true. + * The validation may be restricted within a certain group of validator + * controls by setting {@link setValidationGroup ValidationGroup} property. + * If validation is successful, the data will be post back to the same page. + * + * TButton displays the {@link setText Text} property as the button caption. + * + * TButton can be one of three {@link setButtonType ButtonType}: Submit, Button and Reset. + * By default, it is a Submit button and the form submission uses the browser's + * default submission capability. If it is Button or Reset, postback may occur + * if one of the following conditions is met: + * - an event handler is attached to {@link onClick OnClick} event; + * - an event handler is attached to {@link onCommand OnCommand} event; + * - the button is in a non-empty validation group. + * In addition, clicking on a Reset button will clear up all input fields + * if the button does not cause a postback. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer +{ +	/** +	 * @return string tag name of the button +	 */ +	protected function getTagName() +	{ +		return 'input'; +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This overrides the parent implementation with additional button specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$page=$this->getPage(); +		$page->ensureRenderInForm($this); +		$writer->addAttribute('type',strtolower($this->getButtonType())); +		if(($uniqueID=$this->getUniqueID())!=='') +			$writer->addAttribute('name',$uniqueID); +		$writer->addAttribute('value',$this->getText()); +		if($this->getEnabled(true)) +		{ +			if($this->getEnableClientScript() && $this->needPostBackScript()) +				$this->renderClientControlScript($writer); +		} +		else if($this->getEnabled()) // in this case, parent will not render 'disabled' +			$writer->addAttribute('disabled','disabled'); + +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Renders the client-script code. +	 */ +	protected function renderClientControlScript($writer) +	{ +		$writer->addAttribute('id',$this->getClientID()); +		$this->getPage()->getClientScript()->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TButton'; +	} + +	/** +	 * @return boolean whether to perform validation if the button is clicked +	 */ +	protected function canCauseValidation() +	{ +		if($this->getCausesValidation()) +		{ +			$group=$this->getValidationGroup(); +			return $this->getPage()->getValidators($group)->getCount()>0; +		} +		else +			return false; +	} + +	/** +	 * @param boolean set by a panel to register this button as the default button for the panel. +	 */ +	public function setIsDefaultButton($value) +	{ +		$this->setViewState('IsDefaultButton', TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean true if this button is registered as a default button for a panel. +	 */ +	public function getIsDefaultButton() +	{ +		return $this->getViewState('IsDefaultButton', false); +	} + +	/** +	 * @return boolean whether the button needs javascript to do postback +	 */ +	protected function needPostBackScript() +	{ +		return $this->canCauseValidation() || ($this->getButtonType()!==TButtonType::Submit && +			($this->hasEventHandler('OnClick') || $this->hasEventHandler('OnCommand'))) +			|| $this->getIsDefaultButton(); +	} + +	/** +	 * Returns postback specifications for the button. +	 * This method is used by framework and control developers. +	 * @return array parameters about how the button defines its postback behavior. +	 */ +	protected function getPostBackOptions() +	{ +		$options['ID']=$this->getClientID(); +		$options['CausesValidation']=$this->getCausesValidation(); +		$options['EventTarget'] = $this->getUniqueID(); +		$options['ValidationGroup']=$this->getValidationGroup(); + +		return $options; +	} + +	/** +	 * Renders the body content enclosed between the control tag. +	 * This overrides the parent implementation with nothing to be rendered. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +	} + +	/** +	 * This method is invoked when the button is clicked. +	 * The method raises 'OnClick' event to fire up the event handlers. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handler can be invoked. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onClick($param) +	{ +		$this->raiseEvent('OnClick',$this,$param); +	} + +	/** +	 * This method is invoked when the button is clicked. +	 * The method raises 'OnCommand' event to fire up the event handlers. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handlers can be invoked. +	 * @param TCommandEventParameter event parameter to be passed to the event handlers +	 */ +	public function onCommand($param) +	{ +		$this->raiseEvent('OnCommand',$this,$param); +		$this->raiseBubbleEvent($this,$param); +	} + +	/** +	 * Raises the postback event. +	 * This method is required by {@link IPostBackEventHandler} interface. +	 * If {@link getCausesValidation CausesValidation} is true, it will +	 * invoke the page's {@link TPage::validate validate} method first. +	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events. +	 * This method is mainly used by framework and control developers. +	 * @param TEventParameter the event parameter +	 */ +	public function raisePostBackEvent($param) +	{ +		if($this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onClick(null); +		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter())); +	} + +	/** +	 * @return string caption of the button +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * @param string caption of the button +	 */ +	public function setText($value) +	{ +		$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 +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by this button will cause input validation +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the command name associated with the {@link onCommand OnCommand} event. +	 */ +	public function getCommandName() +	{ +		return $this->getViewState('CommandName',''); +	} + +	/** +	 * @param string the command name associated with the {@link onCommand OnCommand} event. +	 */ +	public function setCommandName($value) +	{ +		$this->setViewState('CommandName',$value,''); +	} + +	/** +	 * @return string the parameter associated with the {@link onCommand OnCommand} event +	 */ +	public function getCommandParameter() +	{ +		return $this->getViewState('CommandParameter',''); +	} + +	/** +	 * @param string the parameter associated with the {@link onCommand OnCommand} event. +	 */ +	public function setCommandParameter($value) +	{ +		$this->setViewState('CommandParameter',$value,''); +	} + +	/** +	 * @return string the group of validators which the button causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the button causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * @return TButtonType the type of the button. Defaults to TButtonType::Submit. +	 */ +	public function getButtonType() +	{ +		return $this->getViewState('ButtonType',TButtonType::Submit); +	} + +	/** +	 * @param TButtonType the type of the button. +	 */ +	public function setButtonType($value) +	{ +		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TButtonType'),TButtonType::Submit); +	} +} + +/** + * TButtonType class. + * TButtonType defines the enumerable type for the possible types that a {@link TButton} can take. + * + * The following enumerable values are defined: + * - Submit: a normal submit button + * - Reset: a reset button + * - Button: a client button (normally does not perform form submission) + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TButtonType extends TEnumerable +{ +	const Submit='Submit'; +	const Reset='Reset'; +	const Button='Button'; +} + diff --git a/framework/Web/UI/WebControls/TButtonColumn.php b/framework/Web/UI/WebControls/TButtonColumn.php index 9d754004..f0f387e7 100644 --- a/framework/Web/UI/WebControls/TButtonColumn.php +++ b/framework/Web/UI/WebControls/TButtonColumn.php @@ -1,278 +1,278 @@ -<?php
 -/**
 - * TButtonColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TButtonColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -Prado::using('System.Web.UI.WebControls.TButton');
 -Prado::using('System.Web.UI.WebControls.TLinkButton');
 -Prado::using('System.Web.UI.WebControls.TImageButton');
 -
 -/**
 - * TButtonColumn class
 - *
 - * TButtonColumn contains a user-defined command button, such as Add or Remove,
 - * that corresponds with each row in the column.
 - *
 - * The caption of the buttons in the column is determined by {@link setText Text}
 - * and {@link setDataTextField DataTextField} properties. If both are present,
 - * the latter takes precedence. The {@link setDataTextField DataTextField} property
 - * refers to the name of the field in datasource whose value will be used as the button caption.
 - * If {@link setDataTextFormatString DataTextFormatString} is not empty,
 - * the value will be formatted before rendering.
 - *
 - * The buttons in the column can be set to display as hyperlinks or push buttons
 - * by setting the {@link setButtonType ButtonType} property.
 - * The {@link setCommandName CommandName} will assign its value to
 - * all button's <b>CommandName</b> property. The datagrid will capture
 - * the command event where you can write event handlers based on different command names.
 - * The buttons' <b>CausesValidation</b> and <b>ValidationGroup</b> property values
 - * are determined by the column's corresponding properties.
 - *
 - * The buttons in the column can be accessed by one of the following two methods:
 - * <code>
 - * $datagridItem->ButtonColumnID->Button
 - * $datagridItem->ButtonColumnID->Controls[0]
 - * </code>
 - * The second method is possible because the button control created within the
 - * datagrid cell is the first child.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TButtonColumn extends TDataGridColumn
 -{
 -	/**
 -	 * @return string the text caption of the button
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text caption of the button.
 -	 * @param string the text caption to be set
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field name from the data source to bind to the button caption
 -	 */
 -	public function getDataTextField()
 -	{
 -		return $this->getViewState('DataTextField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the button caption
 -	 */
 -	public function setDataTextField($value)
 -	{
 -		$this->setViewState('DataTextField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the button caption will be displayed.
 -	 */
 -	public function getDataTextFormatString()
 -	{
 -		return $this->getViewState('DataTextFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the button caption will be displayed.
 -	 */
 -	public function setDataTextFormatString($value)
 -	{
 -		$this->setViewState('DataTextFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the URL of the image file for image buttons
 -	 */
 -	public function getImageUrl()
 -	{
 -		return $this->getViewState('ImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL of the image file for image buttons
 -	 */
 -	public function setImageUrl($value)
 -	{
 -		$this->setViewState('ImageUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field name from the data source to bind to the button image url
 -	 */
 -	public function getDataImageUrlField()
 -	{
 -		return $this->getViewState('DataImageUrlField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the button image url
 -	 */
 -	public function setDataImageUrlField($value)
 -	{
 -		$this->setViewState('DataImageUrlField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the button image url will be displayed.
 -	 */
 -	public function getDataImageUrlFormatString()
 -	{
 -		return $this->getViewState('DataImageUrlFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the button image url will be displayed.
 -	 */
 -	public function setDataImageUrlFormatString($value)
 -	{
 -		$this->setViewState('DataImageUrlFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return TButtonColumnType the type of command button. Defaults to TButtonColumnType::LinkButton.
 -	 */
 -	public function getButtonType()
 -	{
 -		return $this->getViewState('ButtonType',TButtonColumnType::LinkButton);
 -	}
 -
 -	/**
 -	 * @param TButtonColumnType the type of command button
 -	 */
 -	public function setButtonType($value)
 -	{
 -		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TButtonColumnType'),TButtonColumnType::LinkButton);
 -	}
 -
 -	/**
 -	 * @return string the command name associated with the <b>OnCommand</b> event.
 -	 */
 -	public function getCommandName()
 -	{
 -		return $this->getViewState('CommandName','');
 -	}
 -
 -	/**
 -	 * Sets the command name associated with the <b>Command</b> event.
 -	 * @param string the text caption to be set
 -	 */
 -	public function setCommandName($value)
 -	{
 -		$this->setViewState('CommandName',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by this button will cause input validation
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the button causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the button causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It creates a command button within the cell.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem)
 -		{
 -			$buttonType=$this->getButtonType();
 -			if($buttonType===TButtonColumnType::LinkButton)
 -				$button=new TLinkButton;
 -			else if($buttonType===TButtonColumnType::PushButton)
 -				$button=new TButton;
 -			else // image button
 -			{
 -				$button=new TImageButton;
 -				$button->setImageUrl($this->getImageUrl());
 -			}
 -			$button->setText($this->getText());
 -			$button->setCommandName($this->getCommandName());
 -			$button->setCausesValidation($this->getCausesValidation());
 -			$button->setValidationGroup($this->getValidationGroup());
 -			if($this->getDataTextField()!=='' || ($buttonType===TButtonColumnType::ImageButton && $this->getDataImageUrlField()!==''))
 -				$button->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -			$cell->getControls()->add($button);
 -			$cell->registerObject('Button',$button);
 -		}
 -		else
 -			parent::initializeCell($cell,$columnIndex,$itemType);
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		if($sender instanceof IButtonControl)
 -		{
 -			if(($field=$this->getDataTextField())!=='')
 -			{
 -				$value=$this->getDataFieldValue($sender->getNamingContainer()->getData(),$field);
 -				$text=$this->formatDataValue($this->getDataTextFormatString(),$value);
 -				$sender->setText($text);
 -			}
 -			if(($sender instanceof TImageButton) && ($field=$this->getDataImageUrlField())!=='')
 -			{
 -				$value=$this->getDataFieldValue($sender->getNamingContainer()->getData(),$field);
 -				$url=$this->formatDataValue($this->getDataImageUrlFormatString(),$value);
 -				$sender->setImageUrl($url);
 -			}
 -		}
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); +Prado::using('System.Web.UI.WebControls.TButton'); +Prado::using('System.Web.UI.WebControls.TLinkButton'); +Prado::using('System.Web.UI.WebControls.TImageButton'); + +/** + * TButtonColumn class + * + * TButtonColumn contains a user-defined command button, such as Add or Remove, + * that corresponds with each row in the column. + * + * The caption of the buttons in the column is determined by {@link setText Text} + * and {@link setDataTextField DataTextField} properties. If both are present, + * the latter takes precedence. The {@link setDataTextField DataTextField} property + * refers to the name of the field in datasource whose value will be used as the button caption. + * If {@link setDataTextFormatString DataTextFormatString} is not empty, + * the value will be formatted before rendering. + * + * The buttons in the column can be set to display as hyperlinks or push buttons + * by setting the {@link setButtonType ButtonType} property. + * The {@link setCommandName CommandName} will assign its value to + * all button's <b>CommandName</b> property. The datagrid will capture + * the command event where you can write event handlers based on different command names. + * The buttons' <b>CausesValidation</b> and <b>ValidationGroup</b> property values + * are determined by the column's corresponding properties. + * + * The buttons in the column can be accessed by one of the following two methods: + * <code> + * $datagridItem->ButtonColumnID->Button + * $datagridItem->ButtonColumnID->Controls[0] + * </code> + * The second method is possible because the button control created within the + * datagrid cell is the first child. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TButtonColumn extends TDataGridColumn +{ +	/** +	 * @return string the text caption of the button +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text caption of the button. +	 * @param string the text caption to be set +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value,''); +	} + +	/** +	 * @return string the field name from the data source to bind to the button caption +	 */ +	public function getDataTextField() +	{ +		return $this->getViewState('DataTextField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the button caption +	 */ +	public function setDataTextField($value) +	{ +		$this->setViewState('DataTextField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the button caption will be displayed. +	 */ +	public function getDataTextFormatString() +	{ +		return $this->getViewState('DataTextFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the button caption will be displayed. +	 */ +	public function setDataTextFormatString($value) +	{ +		$this->setViewState('DataTextFormatString',$value,''); +	} + +	/** +	 * @return string the URL of the image file for image buttons +	 */ +	public function getImageUrl() +	{ +		return $this->getViewState('ImageUrl',''); +	} + +	/** +	 * @param string the URL of the image file for image buttons +	 */ +	public function setImageUrl($value) +	{ +		$this->setViewState('ImageUrl',$value,''); +	} + +	/** +	 * @return string the field name from the data source to bind to the button image url +	 */ +	public function getDataImageUrlField() +	{ +		return $this->getViewState('DataImageUrlField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the button image url +	 */ +	public function setDataImageUrlField($value) +	{ +		$this->setViewState('DataImageUrlField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the button image url will be displayed. +	 */ +	public function getDataImageUrlFormatString() +	{ +		return $this->getViewState('DataImageUrlFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the button image url will be displayed. +	 */ +	public function setDataImageUrlFormatString($value) +	{ +		$this->setViewState('DataImageUrlFormatString',$value,''); +	} + +	/** +	 * @return TButtonColumnType the type of command button. Defaults to TButtonColumnType::LinkButton. +	 */ +	public function getButtonType() +	{ +		return $this->getViewState('ButtonType',TButtonColumnType::LinkButton); +	} + +	/** +	 * @param TButtonColumnType the type of command button +	 */ +	public function setButtonType($value) +	{ +		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TButtonColumnType'),TButtonColumnType::LinkButton); +	} + +	/** +	 * @return string the command name associated with the <b>OnCommand</b> event. +	 */ +	public function getCommandName() +	{ +		return $this->getViewState('CommandName',''); +	} + +	/** +	 * Sets the command name associated with the <b>Command</b> event. +	 * @param string the text caption to be set +	 */ +	public function setCommandName($value) +	{ +		$this->setViewState('CommandName',$value,''); +	} + +	/** +	 * @return boolean whether postback event trigger by this button will cause input validation, default is true +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by this button will cause input validation +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the group of validators which the button causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the button causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It creates a command button within the cell. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem) +		{ +			$buttonType=$this->getButtonType(); +			if($buttonType===TButtonColumnType::LinkButton) +				$button=new TLinkButton; +			else if($buttonType===TButtonColumnType::PushButton) +				$button=new TButton; +			else // image button +			{ +				$button=new TImageButton; +				$button->setImageUrl($this->getImageUrl()); +			} +			$button->setText($this->getText()); +			$button->setCommandName($this->getCommandName()); +			$button->setCausesValidation($this->getCausesValidation()); +			$button->setValidationGroup($this->getValidationGroup()); +			if($this->getDataTextField()!=='' || ($buttonType===TButtonColumnType::ImageButton && $this->getDataImageUrlField()!=='')) +				$button->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +			$cell->getControls()->add($button); +			$cell->registerObject('Button',$button); +		} +		else +			parent::initializeCell($cell,$columnIndex,$itemType); +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		if($sender instanceof IButtonControl) +		{ +			if(($field=$this->getDataTextField())!=='') +			{ +				$value=$this->getDataFieldValue($sender->getNamingContainer()->getData(),$field); +				$text=$this->formatDataValue($this->getDataTextFormatString(),$value); +				$sender->setText($text); +			} +			if(($sender instanceof TImageButton) && ($field=$this->getDataImageUrlField())!=='') +			{ +				$value=$this->getDataFieldValue($sender->getNamingContainer()->getData(),$field); +				$url=$this->formatDataValue($this->getDataImageUrlFormatString(),$value); +				$sender->setImageUrl($url); +			} +		} +	} +} + diff --git a/framework/Web/UI/WebControls/TCaptcha.php b/framework/Web/UI/WebControls/TCaptcha.php index 7bcf5643..5ec870ce 100644 --- a/framework/Web/UI/WebControls/TCaptcha.php +++ b/framework/Web/UI/WebControls/TCaptcha.php @@ -1,495 +1,495 @@ -<?php
 -/**
 - * TCaptcha class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TImage');
 -
 -/**
 - * TCaptcha class.
 - *
 - * Notice: while this class is easy to use and implement, it does not provide full security.
 - * In fact, it's easy to bypass the checks reusing old, already-validated tokens (reply attack).
 - * A better alternative is provided by {@link TReCaptcha}.
 - *
 - * TCaptcha displays a CAPTCHA (a token displayed as an image) that can be used
 - * to determine if the input is entered by a real user instead of some program.
 - *
 - * Unlike other CAPTCHA scripts, TCaptcha does not need session or cookie.
 - *
 - * The token (a string consisting of alphanumeric characters) displayed is automatically
 - * generated and can be configured in several ways. To specify the length of characters
 - * in the token, set {@link setMinTokenLength MinTokenLength} and {@link setMaxTokenLength MaxTokenLength}.
 - * To use case-insensitive comparison and generate upper-case-only token, set {@link setCaseSensitive CaseSensitive}
 - * to false. Advanced users can try to set {@link setTokenAlphabet TokenAlphabet}, which
 - * specifies what characters can appear in tokens.
 - *
 - * The validation of the token is related with two properties: {@link setTestLimit TestLimit}
 - * and {@link setTokenExpiry TokenExpiry}. The former specifies how many times a token can
 - * be tested with on the server side, and the latter says when a generated token will expire.
 - *
 - * To specify the appearance of the generated token image, set {@link setTokenImageTheme TokenImageTheme}
 - * to be an integer between 0 and 63. And to adjust the generated image size, set {@link setTokenFontSize TokenFontSize}
 - * (you may also set {@link TWebControl::setWidth Width}, but the scaled image may not look good.)
 - * By setting {@link setChangingTokenBackground ChangingTokenBackground} to true, the image background
 - * of the token will be variating even though the token is the same during postbacks.
 - *
 - * Upon postback, user input can be validated by calling {@link validate()}.
 - * The {@link TCaptchaValidator} control can also be used to do validation, which provides
 - * client-side validation besides the server-side validation.  By default, the token will
 - * remain the same during multiple postbacks. A new one can be generated by calling
 - * {@link regenerateToken()} manually.
 - *
 - * The following template shows a typical use of TCaptcha control:
 - * <code>
 - * <com:TCaptcha ID="Captcha" />
 - * <com:TTextBox ID="Input" />
 - * <com:TCaptchaValidator CaptchaControl="Captcha"
 - *                        ControlToValidate="Input"
 - *                        ErrorMessage="You are challenged!" />
 - * </code>
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TCaptcha extends TImage
 -{
 -	const MIN_TOKEN_LENGTH=2;
 -	const MAX_TOKEN_LENGTH=40;
 -	private $_privateKey;
 -	private $_validated=false;
 -
 -	/**
 -	 * @return integer the theme of the token image. Defaults to 0.
 -	 */
 -	public function getTokenImageTheme()
 -	{
 -		return $this->getViewState('TokenImageTheme',0);
 -	}
 -
 -	/**
 -	 * Sets the theme of the token image.
 -	 * You may test each theme to find out the one you like the most.
 -	 * Below is the explanation of the theme value:
 -	 * It is treated as a 5-bit integer. Each bit toggles a specific feature of the image.
 -	 * Bit 0 (the least significant): whether the image is opaque (1) or transparent (0).
 -	 * Bit 1: whether we should add white noise to the image (1) or not (0).
 -	 * Bit 2: whether we should add a grid to  the image (1) or not (0).
 -	 * Bit 3: whether we should add some scribbles to the image (1) or not (0).
 -	 * Bit 4: whether the image background should be morphed (1) or not (0).
 -	 * Bit 5: whether the token text should cast a shadow (1) or not (0).
 -	 * @param integer the theme of the token image. It must be an integer between 0 and 63.
 -	 */
 -	public function setTokenImageTheme($value)
 -	{
 -		$value=TPropertyValue::ensureInteger($value);
 -		if($value>=0 && $value<=63)
 -			$this->setViewState('TokenImageTheme',$value,0);
 -		else
 -			throw new TConfigurationException('captcha_tokenimagetheme_invalid',0,63);
 -	}
 -
 -	/**
 -	 * @return integer the font size used for displaying the token in an image. Defaults to 30.
 -	 */
 -	public function getTokenFontSize()
 -	{
 -		return $this->getViewState('TokenFontSize',30);
 -	}
 -
 -	/**
 -	 * Sets the font size used for displaying the token in an image.
 -	 * This property affects the generated token image size.
 -	 * The image width is proportional to this font size.
 -	 * @param integer the font size used for displaying the token in an image. It must be an integer between 20 and 100.
 -	 */
 -	public function setTokenFontSize($value)
 -	{
 -		$value=TPropertyValue::ensureInteger($value);
 -		if($value>=20 && $value<=100)
 -			$this->setViewState('TokenFontSize',$value,30);
 -		else
 -			throw new TConfigurationException('captcha_tokenfontsize_invalid',20,100);
 -	}
 -
 -	/**
 -	 * @return integer the minimum length of the token. Defaults to 4.
 -	 */
 -	public function getMinTokenLength()
 -	{
 -		return $this->getViewState('MinTokenLength',4);
 -	}
 -
 -	/**
 -	 * @param integer the minimum length of the token. It must be between 2 and 40.
 -	 */
 -	public function setMinTokenLength($value)
 -	{
 -		$length=TPropertyValue::ensureInteger($value);
 -		if($length>=self::MIN_TOKEN_LENGTH && $length<=self::MAX_TOKEN_LENGTH)
 -			$this->setViewState('MinTokenLength',$length,4);
 -		else
 -			throw new TConfigurationException('captcha_mintokenlength_invalid',self::MIN_TOKEN_LENGTH,self::MAX_TOKEN_LENGTH);
 -	}
 -
 -	/**
 -	 * @return integer the maximum length of the token. Defaults to 6.
 -	 */
 -	public function getMaxTokenLength()
 -	{
 -		return $this->getViewState('MaxTokenLength',6);
 -	}
 -
 -	/**
 -	 * @param integer the maximum length of the token. It must be between 2 and 40.
 -	 */
 -	public function setMaxTokenLength($value)
 -	{
 -		$length=TPropertyValue::ensureInteger($value);
 -		if($length>=self::MIN_TOKEN_LENGTH && $length<=self::MAX_TOKEN_LENGTH)
 -			$this->setViewState('MaxTokenLength',$length,6);
 -		else
 -			throw new TConfigurationException('captcha_maxtokenlength_invalid',self::MIN_TOKEN_LENGTH,self::MAX_TOKEN_LENGTH);
 -	}
 -
 -	/**
 -	 * @return boolean whether the token should be treated as case-sensitive. Defaults to true.
 -	 */
 -	public function getCaseSensitive()
 -	{
 -		return $this->getViewState('CaseSensitive',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether the token should be treated as case-sensitive. If false, only upper-case letters will appear in the token.
 -	 */
 -	public function setCaseSensitive($value)
 -	{
 -		$this->setViewState('CaseSensitive',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the characters that may appear in the token. Defaults to '234578adefhijmnrtABDEFGHJLMNRT'.
 -	 */
 -	public function getTokenAlphabet()
 -	{
 -		return $this->getViewState('TokenAlphabet','234578adefhijmnrtABDEFGHJLMNRT');
 -	}
 -
 -	/**
 -	 * @param string the characters that may appear in the token. At least 2 characters must be specified.
 -	 */
 -	public function setTokenAlphabet($value)
 -	{
 -		if(strlen($value)<2)
 -			throw new TConfigurationException('captcha_tokenalphabet_invalid');
 -		$this->setViewState('TokenAlphabet',$value,'234578adefhijmnrtABDEFGHJLMNRT');
 -	}
 -
 -	/**
 -	 * @return integer the number of seconds that a generated token will remain valid. Defaults to 600 seconds (10 minutes).
 -	 */
 -	public function getTokenExpiry()
 -	{
 -		return $this->getViewState('TokenExpiry',600);
 -	}
 -
 -	/**
 -	 * @param integer the number of seconds that a generated token will remain valid. A value smaller than 1 means the token will not expire.
 -	 */
 -	public function setTokenExpiry($value)
 -	{
 -		$this->setViewState('TokenExpiry',TPropertyValue::ensureInteger($value),600);
 -	}
 -
 -	/**
 -	 * @return boolean whether the background of the token image should be variated during postbacks. Defaults to false.
 -	 */
 -	public function getChangingTokenBackground()
 -	{
 -		return $this->getViewState('ChangingTokenBackground',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the background of the token image should be variated during postbacks.
 -	 */
 -	public function setChangingTokenBackground($value)
 -	{
 -		$this->setViewState('ChangingTokenBackground',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return integer how many times a generated token can be tested. Defaults to 5.
 -	 */
 -	public function getTestLimit()
 -	{
 -		return $this->getViewState('TestLimit',5);
 -	}
 -
 -	/**
 -	 * @param integer how many times a generated token can be tested. For unlimited tests, set it to 0.
 -	 */
 -	public function setTestLimit($value)
 -	{
 -		$this->setViewState('TestLimit',TPropertyValue::ensureInteger($value),5);
 -	}
 -
 -	/**
 -	 * @return boolean whether the currently generated token has expired.
 -	 */
 -	public function getIsTokenExpired()
 -	{
 -		if(($expiry=$this->getTokenExpiry())>0 && ($start=$this->getViewState('TokenGenerated',0))>0)
 -			return $expiry+$start<time();
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @return string the public key used for generating the token. A random one will be generated and returned if this is not set.
 -	 */
 -	public function getPublicKey()
 -	{
 -		if(($publicKey=$this->getViewState('PublicKey',''))==='')
 -		{
 -			$publicKey=$this->generateRandomKey();
 -			$this->setPublicKey($publicKey);
 -		}
 -		return $publicKey;
 -	}
 -
 -	/**
 -	 * @param string the public key used for generating the token. A random one will be generated if this is not set.
 -	 */
 -	public function setPublicKey($value)
 -	{
 -		$this->setViewState('PublicKey',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the token that will be displayed
 -	 */
 -	public function getToken()
 -	{
 -		return $this->generateToken($this->getPublicKey(),$this->getPrivateKey(),$this->getTokenAlphabet(),$this->getTokenLength(),$this->getCaseSensitive());
 -	}
 -
 -	/**
 -	 * @return integer the length of the token to be generated.
 -	 */
 -	protected function getTokenLength()
 -	{
 -		if(($tokenLength=$this->getViewState('TokenLength'))===null)
 -		{
 -			$minLength=$this->getMinTokenLength();
 -			$maxLength=$this->getMaxTokenLength();
 -			if($minLength>$maxLength)
 -				$tokenLength=rand($maxLength,$minLength);
 -			else if($minLength<$maxLength)
 -				$tokenLength=rand($minLength,$maxLength);
 -			else
 -				$tokenLength=$minLength;
 -			$this->setViewState('TokenLength',$tokenLength);
 -		}
 -		return $tokenLength;
 -	}
 -
 -	/**
 -	 * @return string the private key used for generating the token. This is randomly generated and kept in a file for persistency.
 -	 */
 -	public function getPrivateKey()
 -	{
 -		if($this->_privateKey===null)
 -		{
 -			$fileName=$this->generatePrivateKeyFile();
 -			$content=file_get_contents($fileName);
 -			$matches=array();
 -			if(preg_match("/privateKey='(.*?)'/ms",$content,$matches)>0)
 -				$this->_privateKey=$matches[1];
 -			else
 -				throw new TConfigurationException('captcha_privatekey_unknown');
 -		}
 -		return $this->_privateKey;
 -	}
 -
 -	/**
 -	 * Validates a user input with the token.
 -	 * @param string user input
 -	 * @return boolean if the user input is not the same as the token.
 -	 */
 -	public function validate($input)
 -	{
 -		$number=$this->getViewState('TestNumber',0);
 -		if(!$this->_validated)
 -		{
 -			$this->setViewState('TestNumber',++$number);
 -			$this->_validated=true;
 -		}
 -		if($this->getIsTokenExpired() || (($limit=$this->getTestLimit())>0 && $number>$limit))
 -		{
 -			$this->regenerateToken();
 -			return false;
 -		}
 -		return ($this->getToken()===($this->getCaseSensitive()?$input:strtoupper($input)));
 -	}
 -
 -	/**
 -	 * Regenerates the token to be displayed.
 -	 * By default, a token, once generated, will remain the same during the following page postbacks.
 -	 * Calling this method will generate a new token.
 -	 */
 -	public function regenerateToken()
 -	{
 -		$this->clearViewState('TokenLength');
 -		$this->setPublicKey('');
 -		$this->clearViewState('TokenGenerated');
 -		$this->clearViewState('RandomSeed');
 -		$this->clearViewState('TestNumber',0);
 -	}
 -
 -	/**
 -	 * Configures the image URL that shows the token.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		if(!self::checkRequirements())
 -			throw new TConfigurationException('captcha_imagettftext_required');
 -		if(!$this->getViewState('TokenGenerated',0))
 -		{
 -			$manager=$this->getApplication()->getAssetManager();
 -			$manager->publishFilePath($this->getFontFile());
 -			$url=$manager->publishFilePath($this->getCaptchaScriptFile());
 -			$url.='?options='.urlencode($this->getTokenImageOptions());
 -			$this->setImageUrl($url);
 -
 -			$this->setViewState('TokenGenerated',time());
 -		}
 -	}
 -
 -	/**
 -	 * @return string the options to be passed to the token image generator
 -	 */
 -	protected function getTokenImageOptions()
 -	{
 -		$privateKey=$this->getPrivateKey();  // call this method to ensure private key is generated
 -		$token=$this->getToken();
 -		$options=array();
 -		$options['publicKey']=$this->getPublicKey();
 -		$options['tokenLength']=strlen($token);
 -		$options['caseSensitive']=$this->getCaseSensitive();
 -		$options['alphabet']=$this->getTokenAlphabet();
 -		$options['fontSize']=$this->getTokenFontSize();
 -		$options['theme']=$this->getTokenImageTheme();
 -		if(($randomSeed=$this->getViewState('RandomSeed',0))===0)
 -		{
 -			$randomSeed=(int)(microtime()*1000000);
 -			$this->setViewState('RandomSeed',$randomSeed);
 -		}
 -		$options['randomSeed']=$this->getChangingTokenBackground()?0:$randomSeed;
 -		$str=serialize($options);
 -		return base64_encode(md5($privateKey.$str).$str);
 -	}
 -
 -	/**
 -	 * @return string the file path of the PHP script generating the token image
 -	 */
 -	protected function getCaptchaScriptFile()
 -	{
 -		return dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'captcha.php';
 -	}
 -
 -	protected function getFontFile()
 -	{
 -		return dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'verase.ttf';
 -	}
 -
 -	/**
 -	 * Generates a file with a randomly generated private key.
 -	 * @return string the path of the file keeping the private key
 -	 */
 -	protected function generatePrivateKeyFile()
 -	{
 -		$captchaScript=$this->getCaptchaScriptFile();
 -		$path=dirname($this->getApplication()->getAssetManager()->getPublishedPath($captchaScript));
 -		$fileName=$path.DIRECTORY_SEPARATOR.'captcha_key.php';
 -		if(!is_file($fileName))
 -		{
 -			@mkdir($path);
 -			$key=$this->generateRandomKey();
 -			$content="<?php
 -\$privateKey='$key';
 -?>";
 -			file_put_contents($fileName,$content);
 -		}
 -		return $fileName;
 -	}
 -
 -	/**
 -	 * @return string a randomly generated key
 -	 */
 -	protected function generateRandomKey()
 -	{
 -		return md5(rand().rand().rand().rand());
 -	}
 -
 -	/**
 -	 * Generates the token.
 -	 * @param string public key
 -	 * @param string private key
 -	 * @param integer the length of the token
 -	 * @param boolean whether the token is case sensitive
 -	 * @return string the token generated.
 -	 */
 -	protected function generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive)
 -	{
 -		$token=substr($this->hash2string(md5($publicKey.$privateKey),$alphabet).$this->hash2string(md5($privateKey.$publicKey),$alphabet),0,$tokenLength);
 -		return $caseSensitive?$token:strtoupper($token);
 -	}
 -
 -	/**
 -	 * Converts a hash string into a string with characters consisting of alphanumeric characters.
 -	 * @param string the hexadecimal representation of the hash string
 -	 * @param string the alphabet used to represent the converted string. If empty, it means '234578adefhijmnrtwyABDEFGHIJLMNQRTWY', which excludes those confusing characters.
 -	 * @return string the converted string
 -	 */
 -	protected function hash2string($hex,$alphabet='')
 -	{
 -		if(strlen($alphabet)<2)
 -			$alphabet='234578adefhijmnrtABDEFGHJLMNQRT';
 -		$hexLength=strlen($hex);
 -		$base=strlen($alphabet);
 -		$result='';
 -		for($i=0;$i<$hexLength;$i+=6)
 -		{
 -			$number=hexdec(substr($hex,$i,6));
 -			while($number)
 -			{
 -				$result.=$alphabet[$number%$base];
 -				$number=floor($number/$base);
 -			}
 -		}
 -		return $result;
 -	}
 -
 -	/**
 -	 * Checks the requirements needed for generating CAPTCHA images.
 -	 * TCaptach requires GD2 with TrueType font support and PNG image support.
 -	 * @return boolean whether the requirements are satisfied.
 -	 */
 -	public static function checkRequirements()
 -	{
 -		return extension_loaded('gd') && function_exists('imagettftext') && function_exists('imagepng');
 -	}
 -}
 -
 +<?php +/** + * TCaptcha class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TImage'); + +/** + * TCaptcha class. + * + * Notice: while this class is easy to use and implement, it does not provide full security. + * In fact, it's easy to bypass the checks reusing old, already-validated tokens (reply attack). + * A better alternative is provided by {@link TReCaptcha}. + * + * TCaptcha displays a CAPTCHA (a token displayed as an image) that can be used + * to determine if the input is entered by a real user instead of some program. + * + * Unlike other CAPTCHA scripts, TCaptcha does not need session or cookie. + * + * The token (a string consisting of alphanumeric characters) displayed is automatically + * generated and can be configured in several ways. To specify the length of characters + * in the token, set {@link setMinTokenLength MinTokenLength} and {@link setMaxTokenLength MaxTokenLength}. + * To use case-insensitive comparison and generate upper-case-only token, set {@link setCaseSensitive CaseSensitive} + * to false. Advanced users can try to set {@link setTokenAlphabet TokenAlphabet}, which + * specifies what characters can appear in tokens. + * + * The validation of the token is related with two properties: {@link setTestLimit TestLimit} + * and {@link setTokenExpiry TokenExpiry}. The former specifies how many times a token can + * be tested with on the server side, and the latter says when a generated token will expire. + * + * To specify the appearance of the generated token image, set {@link setTokenImageTheme TokenImageTheme} + * to be an integer between 0 and 63. And to adjust the generated image size, set {@link setTokenFontSize TokenFontSize} + * (you may also set {@link TWebControl::setWidth Width}, but the scaled image may not look good.) + * By setting {@link setChangingTokenBackground ChangingTokenBackground} to true, the image background + * of the token will be variating even though the token is the same during postbacks. + * + * Upon postback, user input can be validated by calling {@link validate()}. + * The {@link TCaptchaValidator} control can also be used to do validation, which provides + * client-side validation besides the server-side validation.  By default, the token will + * remain the same during multiple postbacks. A new one can be generated by calling + * {@link regenerateToken()} manually. + * + * The following template shows a typical use of TCaptcha control: + * <code> + * <com:TCaptcha ID="Captcha" /> + * <com:TTextBox ID="Input" /> + * <com:TCaptchaValidator CaptchaControl="Captcha" + *                        ControlToValidate="Input" + *                        ErrorMessage="You are challenged!" /> + * </code> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TCaptcha extends TImage +{ +	const MIN_TOKEN_LENGTH=2; +	const MAX_TOKEN_LENGTH=40; +	private $_privateKey; +	private $_validated=false; + +	/** +	 * @return integer the theme of the token image. Defaults to 0. +	 */ +	public function getTokenImageTheme() +	{ +		return $this->getViewState('TokenImageTheme',0); +	} + +	/** +	 * Sets the theme of the token image. +	 * You may test each theme to find out the one you like the most. +	 * Below is the explanation of the theme value: +	 * It is treated as a 5-bit integer. Each bit toggles a specific feature of the image. +	 * Bit 0 (the least significant): whether the image is opaque (1) or transparent (0). +	 * Bit 1: whether we should add white noise to the image (1) or not (0). +	 * Bit 2: whether we should add a grid to  the image (1) or not (0). +	 * Bit 3: whether we should add some scribbles to the image (1) or not (0). +	 * Bit 4: whether the image background should be morphed (1) or not (0). +	 * Bit 5: whether the token text should cast a shadow (1) or not (0). +	 * @param integer the theme of the token image. It must be an integer between 0 and 63. +	 */ +	public function setTokenImageTheme($value) +	{ +		$value=TPropertyValue::ensureInteger($value); +		if($value>=0 && $value<=63) +			$this->setViewState('TokenImageTheme',$value,0); +		else +			throw new TConfigurationException('captcha_tokenimagetheme_invalid',0,63); +	} + +	/** +	 * @return integer the font size used for displaying the token in an image. Defaults to 30. +	 */ +	public function getTokenFontSize() +	{ +		return $this->getViewState('TokenFontSize',30); +	} + +	/** +	 * Sets the font size used for displaying the token in an image. +	 * This property affects the generated token image size. +	 * The image width is proportional to this font size. +	 * @param integer the font size used for displaying the token in an image. It must be an integer between 20 and 100. +	 */ +	public function setTokenFontSize($value) +	{ +		$value=TPropertyValue::ensureInteger($value); +		if($value>=20 && $value<=100) +			$this->setViewState('TokenFontSize',$value,30); +		else +			throw new TConfigurationException('captcha_tokenfontsize_invalid',20,100); +	} + +	/** +	 * @return integer the minimum length of the token. Defaults to 4. +	 */ +	public function getMinTokenLength() +	{ +		return $this->getViewState('MinTokenLength',4); +	} + +	/** +	 * @param integer the minimum length of the token. It must be between 2 and 40. +	 */ +	public function setMinTokenLength($value) +	{ +		$length=TPropertyValue::ensureInteger($value); +		if($length>=self::MIN_TOKEN_LENGTH && $length<=self::MAX_TOKEN_LENGTH) +			$this->setViewState('MinTokenLength',$length,4); +		else +			throw new TConfigurationException('captcha_mintokenlength_invalid',self::MIN_TOKEN_LENGTH,self::MAX_TOKEN_LENGTH); +	} + +	/** +	 * @return integer the maximum length of the token. Defaults to 6. +	 */ +	public function getMaxTokenLength() +	{ +		return $this->getViewState('MaxTokenLength',6); +	} + +	/** +	 * @param integer the maximum length of the token. It must be between 2 and 40. +	 */ +	public function setMaxTokenLength($value) +	{ +		$length=TPropertyValue::ensureInteger($value); +		if($length>=self::MIN_TOKEN_LENGTH && $length<=self::MAX_TOKEN_LENGTH) +			$this->setViewState('MaxTokenLength',$length,6); +		else +			throw new TConfigurationException('captcha_maxtokenlength_invalid',self::MIN_TOKEN_LENGTH,self::MAX_TOKEN_LENGTH); +	} + +	/** +	 * @return boolean whether the token should be treated as case-sensitive. Defaults to true. +	 */ +	public function getCaseSensitive() +	{ +		return $this->getViewState('CaseSensitive',true); +	} + +	/** +	 * @param boolean whether the token should be treated as case-sensitive. If false, only upper-case letters will appear in the token. +	 */ +	public function setCaseSensitive($value) +	{ +		$this->setViewState('CaseSensitive',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the characters that may appear in the token. Defaults to '234578adefhijmnrtABDEFGHJLMNRT'. +	 */ +	public function getTokenAlphabet() +	{ +		return $this->getViewState('TokenAlphabet','234578adefhijmnrtABDEFGHJLMNRT'); +	} + +	/** +	 * @param string the characters that may appear in the token. At least 2 characters must be specified. +	 */ +	public function setTokenAlphabet($value) +	{ +		if(strlen($value)<2) +			throw new TConfigurationException('captcha_tokenalphabet_invalid'); +		$this->setViewState('TokenAlphabet',$value,'234578adefhijmnrtABDEFGHJLMNRT'); +	} + +	/** +	 * @return integer the number of seconds that a generated token will remain valid. Defaults to 600 seconds (10 minutes). +	 */ +	public function getTokenExpiry() +	{ +		return $this->getViewState('TokenExpiry',600); +	} + +	/** +	 * @param integer the number of seconds that a generated token will remain valid. A value smaller than 1 means the token will not expire. +	 */ +	public function setTokenExpiry($value) +	{ +		$this->setViewState('TokenExpiry',TPropertyValue::ensureInteger($value),600); +	} + +	/** +	 * @return boolean whether the background of the token image should be variated during postbacks. Defaults to false. +	 */ +	public function getChangingTokenBackground() +	{ +		return $this->getViewState('ChangingTokenBackground',false); +	} + +	/** +	 * @param boolean whether the background of the token image should be variated during postbacks. +	 */ +	public function setChangingTokenBackground($value) +	{ +		$this->setViewState('ChangingTokenBackground',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return integer how many times a generated token can be tested. Defaults to 5. +	 */ +	public function getTestLimit() +	{ +		return $this->getViewState('TestLimit',5); +	} + +	/** +	 * @param integer how many times a generated token can be tested. For unlimited tests, set it to 0. +	 */ +	public function setTestLimit($value) +	{ +		$this->setViewState('TestLimit',TPropertyValue::ensureInteger($value),5); +	} + +	/** +	 * @return boolean whether the currently generated token has expired. +	 */ +	public function getIsTokenExpired() +	{ +		if(($expiry=$this->getTokenExpiry())>0 && ($start=$this->getViewState('TokenGenerated',0))>0) +			return $expiry+$start<time(); +		else +			return false; +	} + +	/** +	 * @return string the public key used for generating the token. A random one will be generated and returned if this is not set. +	 */ +	public function getPublicKey() +	{ +		if(($publicKey=$this->getViewState('PublicKey',''))==='') +		{ +			$publicKey=$this->generateRandomKey(); +			$this->setPublicKey($publicKey); +		} +		return $publicKey; +	} + +	/** +	 * @param string the public key used for generating the token. A random one will be generated if this is not set. +	 */ +	public function setPublicKey($value) +	{ +		$this->setViewState('PublicKey',$value,''); +	} + +	/** +	 * @return string the token that will be displayed +	 */ +	public function getToken() +	{ +		return $this->generateToken($this->getPublicKey(),$this->getPrivateKey(),$this->getTokenAlphabet(),$this->getTokenLength(),$this->getCaseSensitive()); +	} + +	/** +	 * @return integer the length of the token to be generated. +	 */ +	protected function getTokenLength() +	{ +		if(($tokenLength=$this->getViewState('TokenLength'))===null) +		{ +			$minLength=$this->getMinTokenLength(); +			$maxLength=$this->getMaxTokenLength(); +			if($minLength>$maxLength) +				$tokenLength=rand($maxLength,$minLength); +			else if($minLength<$maxLength) +				$tokenLength=rand($minLength,$maxLength); +			else +				$tokenLength=$minLength; +			$this->setViewState('TokenLength',$tokenLength); +		} +		return $tokenLength; +	} + +	/** +	 * @return string the private key used for generating the token. This is randomly generated and kept in a file for persistency. +	 */ +	public function getPrivateKey() +	{ +		if($this->_privateKey===null) +		{ +			$fileName=$this->generatePrivateKeyFile(); +			$content=file_get_contents($fileName); +			$matches=array(); +			if(preg_match("/privateKey='(.*?)'/ms",$content,$matches)>0) +				$this->_privateKey=$matches[1]; +			else +				throw new TConfigurationException('captcha_privatekey_unknown'); +		} +		return $this->_privateKey; +	} + +	/** +	 * Validates a user input with the token. +	 * @param string user input +	 * @return boolean if the user input is not the same as the token. +	 */ +	public function validate($input) +	{ +		$number=$this->getViewState('TestNumber',0); +		if(!$this->_validated) +		{ +			$this->setViewState('TestNumber',++$number); +			$this->_validated=true; +		} +		if($this->getIsTokenExpired() || (($limit=$this->getTestLimit())>0 && $number>$limit)) +		{ +			$this->regenerateToken(); +			return false; +		} +		return ($this->getToken()===($this->getCaseSensitive()?$input:strtoupper($input))); +	} + +	/** +	 * Regenerates the token to be displayed. +	 * By default, a token, once generated, will remain the same during the following page postbacks. +	 * Calling this method will generate a new token. +	 */ +	public function regenerateToken() +	{ +		$this->clearViewState('TokenLength'); +		$this->setPublicKey(''); +		$this->clearViewState('TokenGenerated'); +		$this->clearViewState('RandomSeed'); +		$this->clearViewState('TestNumber',0); +	} + +	/** +	 * Configures the image URL that shows the token. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		if(!self::checkRequirements()) +			throw new TConfigurationException('captcha_imagettftext_required'); +		if(!$this->getViewState('TokenGenerated',0)) +		{ +			$manager=$this->getApplication()->getAssetManager(); +			$manager->publishFilePath($this->getFontFile()); +			$url=$manager->publishFilePath($this->getCaptchaScriptFile()); +			$url.='?options='.urlencode($this->getTokenImageOptions()); +			$this->setImageUrl($url); + +			$this->setViewState('TokenGenerated',time()); +		} +	} + +	/** +	 * @return string the options to be passed to the token image generator +	 */ +	protected function getTokenImageOptions() +	{ +		$privateKey=$this->getPrivateKey();  // call this method to ensure private key is generated +		$token=$this->getToken(); +		$options=array(); +		$options['publicKey']=$this->getPublicKey(); +		$options['tokenLength']=strlen($token); +		$options['caseSensitive']=$this->getCaseSensitive(); +		$options['alphabet']=$this->getTokenAlphabet(); +		$options['fontSize']=$this->getTokenFontSize(); +		$options['theme']=$this->getTokenImageTheme(); +		if(($randomSeed=$this->getViewState('RandomSeed',0))===0) +		{ +			$randomSeed=(int)(microtime()*1000000); +			$this->setViewState('RandomSeed',$randomSeed); +		} +		$options['randomSeed']=$this->getChangingTokenBackground()?0:$randomSeed; +		$str=serialize($options); +		return base64_encode(md5($privateKey.$str).$str); +	} + +	/** +	 * @return string the file path of the PHP script generating the token image +	 */ +	protected function getCaptchaScriptFile() +	{ +		return dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'captcha.php'; +	} + +	protected function getFontFile() +	{ +		return dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'verase.ttf'; +	} + +	/** +	 * Generates a file with a randomly generated private key. +	 * @return string the path of the file keeping the private key +	 */ +	protected function generatePrivateKeyFile() +	{ +		$captchaScript=$this->getCaptchaScriptFile(); +		$path=dirname($this->getApplication()->getAssetManager()->getPublishedPath($captchaScript)); +		$fileName=$path.DIRECTORY_SEPARATOR.'captcha_key.php'; +		if(!is_file($fileName)) +		{ +			@mkdir($path); +			$key=$this->generateRandomKey(); +			$content="<?php +\$privateKey='$key'; +?>"; +			file_put_contents($fileName,$content); +		} +		return $fileName; +	} + +	/** +	 * @return string a randomly generated key +	 */ +	protected function generateRandomKey() +	{ +		return md5(rand().rand().rand().rand()); +	} + +	/** +	 * Generates the token. +	 * @param string public key +	 * @param string private key +	 * @param integer the length of the token +	 * @param boolean whether the token is case sensitive +	 * @return string the token generated. +	 */ +	protected function generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive) +	{ +		$token=substr($this->hash2string(md5($publicKey.$privateKey),$alphabet).$this->hash2string(md5($privateKey.$publicKey),$alphabet),0,$tokenLength); +		return $caseSensitive?$token:strtoupper($token); +	} + +	/** +	 * Converts a hash string into a string with characters consisting of alphanumeric characters. +	 * @param string the hexadecimal representation of the hash string +	 * @param string the alphabet used to represent the converted string. If empty, it means '234578adefhijmnrtwyABDEFGHIJLMNQRTWY', which excludes those confusing characters. +	 * @return string the converted string +	 */ +	protected function hash2string($hex,$alphabet='') +	{ +		if(strlen($alphabet)<2) +			$alphabet='234578adefhijmnrtABDEFGHJLMNQRT'; +		$hexLength=strlen($hex); +		$base=strlen($alphabet); +		$result=''; +		for($i=0;$i<$hexLength;$i+=6) +		{ +			$number=hexdec(substr($hex,$i,6)); +			while($number) +			{ +				$result.=$alphabet[$number%$base]; +				$number=floor($number/$base); +			} +		} +		return $result; +	} + +	/** +	 * Checks the requirements needed for generating CAPTCHA images. +	 * TCaptach requires GD2 with TrueType font support and PNG image support. +	 * @return boolean whether the requirements are satisfied. +	 */ +	public static function checkRequirements() +	{ +		return extension_loaded('gd') && function_exists('imagettftext') && function_exists('imagepng'); +	} +} + diff --git a/framework/Web/UI/WebControls/TCaptchaValidator.php b/framework/Web/UI/WebControls/TCaptchaValidator.php index 9eca42fb..23943971 100644 --- a/framework/Web/UI/WebControls/TCaptchaValidator.php +++ b/framework/Web/UI/WebControls/TCaptchaValidator.php @@ -1,127 +1,127 @@ -<?php
 -/**
 - * TCaptchaValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -Prado::using('System.Web.UI.WebControls.TCaptcha');
 -
 -/**
 - * TCaptchaValidator class
 - *
 - * Notice: while this class is easy to use and implement, it does not provide full security.
 - * In fact, it's easy to bypass the checks reusing old, already-validated tokens (reply attack).
 - * A better alternative is provided by {@link TReCaptchaValidator}.
 - *
 - * TCaptchaValidator validates user input against a CAPTCHA represented by
 - * a {@link TCaptcha} control. The input control fails validation if its value
 - * is not the same as the token displayed in CAPTCHA. Note, if the user does
 - * not enter any thing, it is still considered as failing the validation.
 - *
 - * To use TCaptchaValidator, specify the {@link setControlToValidate ControlToValidate}
 - * to be the ID path of the input control (usually a {@link TTextBox} control}.
 - * Also specify the {@link setCaptchaControl CaptchaControl} to be the ID path of
 - * the CAPTCHA control that the user input should be compared with.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TCaptchaValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TCaptchaValidator';
 -	}
 -
 -	/**
 -	 * @return string the ID path of the CAPTCHA control to validate
 -	 */
 -	public function getCaptchaControl()
 -	{
 -		return $this->getViewState('CaptchaControl','');
 -	}
 -
 -	/**
 -	 * Sets the ID path of the CAPTCHA control to validate.
 -	 * The ID path is the dot-connected IDs of the controls reaching from
 -	 * the validator's naming container to the target control.
 -	 * @param string the ID path
 -	 */
 -	public function setCaptchaControl($value)
 -	{
 -		$this->setViewState('CaptchaControl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input control has the same value
 -	 * as the one displayed in the corresponding CAPTCHA control.
 -	 *
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	protected function evaluateIsValid()
 -	{
 -		$value=$this->getValidationValue($this->getValidationTarget());
 -		$control=$this->findCaptchaControl();
 -		return $control->validate(trim($value));
 -	}
 -
 -	/**
 -	 * @return TCaptchaControl the CAPTCHA control to be validated against
 -	 * @throws TConfigurationException if the CAPTCHA cannot be found according to {@link setCaptchaControl CaptchaControl}
 -	 */
 -	protected function findCaptchaControl()
 -	{
 -		if(($id=$this->getCaptchaControl())==='')
 -			throw new TConfigurationException('captchavalidator_captchacontrol_required');
 -		else if(($control=$this->findControl($id))===null)
 -			throw new TConfigurationException('captchavalidator_captchacontrol_inexistent',$id);
 -		else if(!($control instanceof TCaptcha))
 -			throw new TConfigurationException('captchavalidator_captchacontrol_invalid',$id);
 -		else
 -			return $control;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options=parent::getClientScriptOptions();
 -		$control=$this->findCaptchaControl();
 -		if($control->getCaseSensitive())
 -		{
 -			$options['TokenHash']=$this->generateTokenHash($control->getToken());
 -			$options['CaseSensitive']=true;
 -		}
 -		else
 -		{
 -			$options['TokenHash']=$this->generateTokenHash(strtoupper($control->getToken()));
 -			$options['CaseSensitive']=false;
 -		}
 -		return $options;
 -	}
 -
 -	private function generateTokenHash($token)
 -	{
 -		for($h=0,$i=strlen($token)-1;$i>=0;--$i)
 -			$h+=ord($token[$i]);
 -		return $h;
 -	}
 -}
 -
 +<?php +/** + * TCaptchaValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TBaseValidator'); +Prado::using('System.Web.UI.WebControls.TCaptcha'); + +/** + * TCaptchaValidator class + * + * Notice: while this class is easy to use and implement, it does not provide full security. + * In fact, it's easy to bypass the checks reusing old, already-validated tokens (reply attack). + * A better alternative is provided by {@link TReCaptchaValidator}. + * + * TCaptchaValidator validates user input against a CAPTCHA represented by + * a {@link TCaptcha} control. The input control fails validation if its value + * is not the same as the token displayed in CAPTCHA. Note, if the user does + * not enter any thing, it is still considered as failing the validation. + * + * To use TCaptchaValidator, specify the {@link setControlToValidate ControlToValidate} + * to be the ID path of the input control (usually a {@link TTextBox} control}. + * Also specify the {@link setCaptchaControl CaptchaControl} to be the ID path of + * the CAPTCHA control that the user input should be compared with. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TCaptchaValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TCaptchaValidator'; +	} + +	/** +	 * @return string the ID path of the CAPTCHA control to validate +	 */ +	public function getCaptchaControl() +	{ +		return $this->getViewState('CaptchaControl',''); +	} + +	/** +	 * Sets the ID path of the CAPTCHA control to validate. +	 * The ID path is the dot-connected IDs of the controls reaching from +	 * the validator's naming container to the target control. +	 * @param string the ID path +	 */ +	public function setCaptchaControl($value) +	{ +		$this->setViewState('CaptchaControl',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input control has the same value +	 * as the one displayed in the corresponding CAPTCHA control. +	 * +	 * @return boolean whether the validation succeeds +	 */ +	protected function evaluateIsValid() +	{ +		$value=$this->getValidationValue($this->getValidationTarget()); +		$control=$this->findCaptchaControl(); +		return $control->validate(trim($value)); +	} + +	/** +	 * @return TCaptchaControl the CAPTCHA control to be validated against +	 * @throws TConfigurationException if the CAPTCHA cannot be found according to {@link setCaptchaControl CaptchaControl} +	 */ +	protected function findCaptchaControl() +	{ +		if(($id=$this->getCaptchaControl())==='') +			throw new TConfigurationException('captchavalidator_captchacontrol_required'); +		else if(($control=$this->findControl($id))===null) +			throw new TConfigurationException('captchavalidator_captchacontrol_inexistent',$id); +		else if(!($control instanceof TCaptcha)) +			throw new TConfigurationException('captchavalidator_captchacontrol_invalid',$id); +		else +			return $control; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options=parent::getClientScriptOptions(); +		$control=$this->findCaptchaControl(); +		if($control->getCaseSensitive()) +		{ +			$options['TokenHash']=$this->generateTokenHash($control->getToken()); +			$options['CaseSensitive']=true; +		} +		else +		{ +			$options['TokenHash']=$this->generateTokenHash(strtoupper($control->getToken())); +			$options['CaseSensitive']=false; +		} +		return $options; +	} + +	private function generateTokenHash($token) +	{ +		for($h=0,$i=strlen($token)-1;$i>=0;--$i) +			$h+=ord($token[$i]); +		return $h; +	} +} + diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php index 641497ac..fe8bfbca 100644 --- a/framework/Web/UI/WebControls/TCheckBox.php +++ b/framework/Web/UI/WebControls/TCheckBox.php @@ -1,131 +1,131 @@ -<?php
 -/**
 - * TCheckBox class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TCheckBox class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TCheckBox class
 - *
 - * TCheckBox displays a check box on the page.
 - * You can specify the caption to display beside the check box by setting
 - * the {@link setText Text} property.  The caption can appear either on the right
 - * or left of the check box, which is determined by the {@link setTextAlign TextAlign}
 - * property.
 - *
 - * To determine whether the TCheckBox component is checked, test the {@link getChecked Checked}
 - * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when
 - * the {@link getChecked Checked} state of the TCheckBox component changes
 - * between posts to the server. You can provide an event handler for
 - * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically
 - * control the actions performed when the state of the TCheckBox component changes
 - * between posts to the server.
 - *
 - * If {@link setAutoPostBack AutoPostBack} is set true, changing the check box state
 - * will cause postback action. And if {@link setCausesValidation CausesValidation}
 - * is true, validation will also be processed, which can be further restricted within
 - * a {@link setValidationGroup ValidationGroup}.
 - *
 - * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters
 - * that may bring security vulnerabilities.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer, ISurroundable
 -{
 -	private $_dataChanged=false;
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TCheckBox class + * + * TCheckBox displays a check box on the page. + * You can specify the caption to display beside the check box by setting + * the {@link setText Text} property.  The caption can appear either on the right + * or left of the check box, which is determined by the {@link setTextAlign TextAlign} + * property. + * + * To determine whether the TCheckBox component is checked, test the {@link getChecked Checked} + * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when + * the {@link getChecked Checked} state of the TCheckBox component changes + * between posts to the server. You can provide an event handler for + * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically + * control the actions performed when the state of the TCheckBox component changes + * between posts to the server. + * + * If {@link setAutoPostBack AutoPostBack} is set true, changing the check box state + * will cause postback action. And if {@link setCausesValidation CausesValidation} + * is true, validation will also be processed, which can be further restricted within + * a {@link setValidationGroup ValidationGroup}. + * + * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters + * that may bring security vulnerabilities. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer, ISurroundable +{ +	private $_dataChanged=false;  	private $_isValid=true; -
 -	/**
 -	 * @return string tag name of the button
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'input';
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the control has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		$checked=$this->getChecked();
 -		if($newChecked=isset($values[$key]))
 -			$this->setValue($values[$key]);
 -		$this->setChecked($newChecked);
 -		return $this->_dataChanged=($newChecked!==$checked);
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method raises {@link onCheckedChanged OnCheckedChanged} event.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		if($this->getAutoPostBack() && $this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onCheckedChanged(null);
 -	}
 -
 -	/**
 -	 * Raises <b>OnCheckedChanged</b> event when {@link getChecked Checked} changes value during postback.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event delegates can be invoked.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onCheckedChanged($param)
 -	{
 -		$this->raiseEvent('OnCheckedChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Registers the checkbox to receive postback data during postback.
 -	 * This is necessary because a checkbox if unchecked, when postback,
 -	 * does not have direct mapping between post data and the checkbox name.
 -	 *
 -	 * This method overrides the parent implementation and is invoked before render.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		if($this->getEnabled(true))
 -			$this->getPage()->registerRequiresPostData($this);
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Returns the value of the property that needs validation.
 -	 * @return mixed the property value to be validated
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getChecked();
 -	}
 -
 + +	/** +	 * @return string tag name of the button +	 */ +	protected function getTagName() +	{ +		return 'input'; +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the control has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		$checked=$this->getChecked(); +		if($newChecked=isset($values[$key])) +			$this->setValue($values[$key]); +		$this->setChecked($newChecked); +		return $this->_dataChanged=($newChecked!==$checked); +	} + +	/** +	 * Raises postdata changed event. +	 * This method raises {@link onCheckedChanged OnCheckedChanged} event. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		if($this->getAutoPostBack() && $this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onCheckedChanged(null); +	} + +	/** +	 * Raises <b>OnCheckedChanged</b> event when {@link getChecked Checked} changes value during postback. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event delegates can be invoked. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onCheckedChanged($param) +	{ +		$this->raiseEvent('OnCheckedChanged',$this,$param); +	} + +	/** +	 * Registers the checkbox to receive postback data during postback. +	 * This is necessary because a checkbox if unchecked, when postback, +	 * does not have direct mapping between post data and the checkbox name. +	 * +	 * This method overrides the parent implementation and is invoked before render. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		if($this->getEnabled(true)) +			$this->getPage()->registerRequiresPostData($this); +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Returns the value of the property that needs validation. +	 * @return mixed the property value to be validated +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getChecked(); +	} +  	/**  	 * Returns true if this control validated successfully.   	 * Defaults to true. @@ -143,390 +143,390 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl  	    $this->_isValid=TPropertyValue::ensureBoolean($value);  	} -	/**
 -	 * @return string the text caption of the checkbox
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text caption of the checkbox.
 -	 * @param string the text caption to be set
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the value of the checkbox. Defaults to empty.
 -	 */
 -	public function getValue()
 -	{
 -		return $this->getViewState('Value','');
 -	}
 -
 -	/**
 -	 * @param string the value of the checkbox
 -	 */
 -	public function setValue($value)
 -	{
 -		$this->setViewState('Value',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return TTextAlign the alignment (Left or Right) of the text caption, defaults to TTextAlign::Right.
 -	 */
 -	public function getTextAlign()
 -	{
 -		return $this->getViewState('TextAlign',TTextAlign::Right);
 -	}
 -
 -	/**
 -	 * @param TTextAlign the alignment of the text caption. Valid values include Left and Right.
 -	 */
 -	public function setTextAlign($value)
 -	{
 -		$this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,'TTextAlign'),TTextAlign::Right);
 -	}
 -
 -	/**
 -	 * @return boolean whether the checkbox is checked
 -	 */
 -	public function getChecked()
 -	{
 -		return $this->getViewState('Checked',false);
 -	}
 -
 -	/**
 -	 * Sets a value indicating whether the checkbox is to be checked or not.
 -	 * @param boolean whether the checkbox is to be checked or not.
 -	 */
 -	public function setChecked($value)
 -	{
 -		$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.
 -	 */
 -	public function getAutoPostBack()
 -	{
 -		return $this->getViewState('AutoPostBack',false);
 -	}
 -
 -	/**
 -	 * Sets a value indicating whether clicking on the checkbox will post the page.
 -	 * @param boolean whether clicking on the checkbox will post the page.
 -	 */
 -	public function setAutoPostBack($value)
 -	{
 -		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event triggered by this checkbox will cause input validation, default is true.
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * Sets the value indicating whether postback event trigger by this checkbox will cause input validation.
 -	 * @param boolean whether postback event trigger by this checkbox will cause input validation.
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the checkbox causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the checkbox causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the id of the surrounding tag or this clientID if no such tag needed
 -	 */
 -	public function getSurroundingTagID()
 -	{
 -        return $this->getSpanNeeded() ? $this->getClientID().'_parent' : $this->getClientID();
 -	}
 -
 -	/**
 -	 * Renders the checkbox control.
 -	 * This method overrides the parent implementation by rendering a checkbox input element
 -	 * and a span element if needed.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		$this->getPage()->ensureRenderInForm($this);
 -		if($this->getHasStyle())
 -			$this->getStyle()->addAttributesToRender($writer);
 -		if(($tooltip=$this->getToolTip())!=='')
 -			$writer->addAttribute('title',$tooltip);
 -		if($this->getHasAttributes())
 -		{
 -			$attributes=$this->getAttributes();
 -			$value=$attributes->remove('value');
 -			// onclick js should only be added to input tag
 -			if(($onclick=$attributes->remove('onclick'))===null)
 -				$onclick='';
 -			if($attributes->getCount())
 -				$writer->addAttributes($attributes);
 -			if($value!==null)
 -				$attributes->add('value',$value);
 -		}
 -		else
 -			$onclick='';
 -        if($needspan=$this->getSpanNeeded())
 -        {
 -            $writer->addAttribute('id',$this->getSurroundingTagID());
 -			$writer->renderBeginTag('span');
 -        }
 -		$clientID=$this->getClientID();
 -		if(($text=$this->getText())!=='')
 -		{
 -			if($this->getTextAlign()===TTextAlign::Left)
 -			{
 -				$this->renderLabel($writer,$clientID,$text);
 -				$this->renderInputTag($writer,$clientID,$onclick);
 -			}
 -			else
 -			{
 -				$this->renderInputTag($writer,$clientID,$onclick);
 -				$this->renderLabel($writer,$clientID,$text);
 -			}
 -		}
 -		else
 -			$this->renderInputTag($writer,$clientID,$onclick);
 -		if($needspan)
 -			$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * @return TMap list of attributes to be rendered for label beside the checkbox
 -	 */
 -	public function getLabelAttributes()
 -	{
 -		if($attributes=$this->getViewState('LabelAttributes',null))
 -			return $attributes;
 -		else
 -		{
 -			$attributes=new TAttributeCollection;
 -			$this->setViewState('LabelAttributes',$attributes,null);
 -			return $attributes;
 -		}
 -	}
 -
 -	/**
 -	 * @return TMap list of attributes to be rendered for the checkbox
 -	 */
 -	public function getInputAttributes()
 -	{
 -		if($attributes=$this->getViewState('InputAttributes',null))
 -			return $attributes;
 -		else
 -		{
 -			$attributes=new TAttributeCollection;
 -			$this->setViewState('InputAttributes',$attributes,null);
 -			return $attributes;
 -		}
 -	}
 -
 -	/**
 -	 * @return string the value attribute to be rendered
 -	 */
 -	protected function getValueAttribute()
 -	{
 -		if(($value=$this->getValue())!=='')
 -			return $value;
 -		else
 -		{
 -			$attributes=$this->getViewState('InputAttributes',null);
 -			if($attributes && $attributes->contains('value'))
 -				return $attributes->itemAt('value');
 -			else if($this->hasAttribute('value'))
 -				return $this->getAttribute('value');
 -			else
 -				return '';
 -		}
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -    /**
 -     * Check if we need a span tag to surround this control. The span tag will be created if
 -     * the Text property is set for this control. 
 -     *
 -     * @return bool wether this control needs a surrounding span tag
 -     */
 -    protected function getSpanNeeded() {
 -        return $this->getText()!=='';
 -    }
 -
 -	/**
 -	 * Renders a label beside the checkbox.
 -	 * @param THtmlWriter the writer for the rendering purpose
 -	 * @param string checkbox id
 -	 * @param string label text
 -	 */
 -	protected function renderLabel($writer,$clientID,$text)
 -	{
 -		$writer->addAttribute('for',$clientID);
 -		if($attributes=$this->getViewState('LabelAttributes',null))
 -			$writer->addAttributes($attributes);
 -		$writer->renderBeginTag('label');
 -		$writer->write($text);
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Renders a checkbox input element.
 -	 * @param THtmlWriter the writer for the rendering purpose
 -	 * @param string checkbox id
 -	 * @param string onclick js
 -	 */
 -	protected function renderInputTag($writer,$clientID,$onclick)
 -	{
 -		if($clientID!=='')
 -			$writer->addAttribute('id',$clientID);
 -		$writer->addAttribute('type','checkbox');
 -		if(($value=$this->getValueAttribute())!=='')
 -			$writer->addAttribute('value',$value);
 -		if(!empty($onclick))
 -			$writer->addAttribute('onclick',$onclick);
 -		if(($uniqueID=$this->getUniqueID())!=='')
 -			$writer->addAttribute('name',$uniqueID);
 -		if($this->getChecked())
 -			$writer->addAttribute('checked','checked');
 -		if(!$this->getEnabled(true))
 -			$writer->addAttribute('disabled','disabled');
 -
 -		$page=$this->getPage();
 -		if($this->getEnabled(true)
 -			&& $this->getEnableClientScript()
 -			&& $this->getAutoPostBack()
 -			&& $page->getClientSupportsJavaScript())
 -		{
 -			$this->renderClientControlScript($writer);
 -		}
 -
 -		if(($accesskey=$this->getAccessKey())!=='')
 -			$writer->addAttribute('accesskey',$accesskey);
 -		if(($tabindex=$this->getTabIndex())>0)
 -			$writer->addAttribute('tabindex',"$tabindex");
 -		if($attributes=$this->getViewState('InputAttributes',null))
 -			$writer->addAttributes($attributes);
 -		$writer->renderBeginTag('input');
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Renders the client-script code.
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TCheckBox';
 -	}
 -
 -	/**
 -	 * Gets the post back options for this checkbox.
 -	 * @return array
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		return $options;
 -	}
 -}
 -
 -/**
 - * TTextAlign class.
 - * TTextAlign defines the enumerable type for the possible text alignments
 - *
 - * The following enumerable values are defined:
 - * - Left: left aligned
 - * - Right: right aligned
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTextAlign extends TEnumerable
 -{
 -	const Left='Left';
 -	const Right='Right';
 -}
 -
 -?>
 +	/** +	 * @return string the text caption of the checkbox +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text caption of the checkbox. +	 * @param string the text caption to be set +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value,''); +	} + +	/** +	 * @return string the value of the checkbox. Defaults to empty. +	 */ +	public function getValue() +	{ +		return $this->getViewState('Value',''); +	} + +	/** +	 * @param string the value of the checkbox +	 */ +	public function setValue($value) +	{ +		$this->setViewState('Value',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return TTextAlign the alignment (Left or Right) of the text caption, defaults to TTextAlign::Right. +	 */ +	public function getTextAlign() +	{ +		return $this->getViewState('TextAlign',TTextAlign::Right); +	} + +	/** +	 * @param TTextAlign the alignment of the text caption. Valid values include Left and Right. +	 */ +	public function setTextAlign($value) +	{ +		$this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,'TTextAlign'),TTextAlign::Right); +	} + +	/** +	 * @return boolean whether the checkbox is checked +	 */ +	public function getChecked() +	{ +		return $this->getViewState('Checked',false); +	} + +	/** +	 * Sets a value indicating whether the checkbox is to be checked or not. +	 * @param boolean whether the checkbox is to be checked or not. +	 */ +	public function setChecked($value) +	{ +		$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. +	 */ +	public function getAutoPostBack() +	{ +		return $this->getViewState('AutoPostBack',false); +	} + +	/** +	 * Sets a value indicating whether clicking on the checkbox will post the page. +	 * @param boolean whether clicking on the checkbox will post the page. +	 */ +	public function setAutoPostBack($value) +	{ +		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether postback event triggered by this checkbox will cause input validation, default is true. +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * Sets the value indicating whether postback event trigger by this checkbox will cause input validation. +	 * @param boolean whether postback event trigger by this checkbox will cause input validation. +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the group of validators which the checkbox causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the checkbox causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * @return string the id of the surrounding tag or this clientID if no such tag needed +	 */ +	public function getSurroundingTagID() +	{ +        return $this->getSpanNeeded() ? $this->getClientID().'_parent' : $this->getClientID(); +	} + +	/** +	 * Renders the checkbox control. +	 * This method overrides the parent implementation by rendering a checkbox input element +	 * and a span element if needed. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function render($writer) +	{ +		$this->getPage()->ensureRenderInForm($this); +		if($this->getHasStyle()) +			$this->getStyle()->addAttributesToRender($writer); +		if(($tooltip=$this->getToolTip())!=='') +			$writer->addAttribute('title',$tooltip); +		if($this->getHasAttributes()) +		{ +			$attributes=$this->getAttributes(); +			$value=$attributes->remove('value'); +			// onclick js should only be added to input tag +			if(($onclick=$attributes->remove('onclick'))===null) +				$onclick=''; +			if($attributes->getCount()) +				$writer->addAttributes($attributes); +			if($value!==null) +				$attributes->add('value',$value); +		} +		else +			$onclick=''; +        if($needspan=$this->getSpanNeeded()) +        { +            $writer->addAttribute('id',$this->getSurroundingTagID()); +			$writer->renderBeginTag('span'); +        } +		$clientID=$this->getClientID(); +		if(($text=$this->getText())!=='') +		{ +			if($this->getTextAlign()===TTextAlign::Left) +			{ +				$this->renderLabel($writer,$clientID,$text); +				$this->renderInputTag($writer,$clientID,$onclick); +			} +			else +			{ +				$this->renderInputTag($writer,$clientID,$onclick); +				$this->renderLabel($writer,$clientID,$text); +			} +		} +		else +			$this->renderInputTag($writer,$clientID,$onclick); +		if($needspan) +			$writer->renderEndTag(); +	} + +	/** +	 * @return TMap list of attributes to be rendered for label beside the checkbox +	 */ +	public function getLabelAttributes() +	{ +		if($attributes=$this->getViewState('LabelAttributes',null)) +			return $attributes; +		else +		{ +			$attributes=new TAttributeCollection; +			$this->setViewState('LabelAttributes',$attributes,null); +			return $attributes; +		} +	} + +	/** +	 * @return TMap list of attributes to be rendered for the checkbox +	 */ +	public function getInputAttributes() +	{ +		if($attributes=$this->getViewState('InputAttributes',null)) +			return $attributes; +		else +		{ +			$attributes=new TAttributeCollection; +			$this->setViewState('InputAttributes',$attributes,null); +			return $attributes; +		} +	} + +	/** +	 * @return string the value attribute to be rendered +	 */ +	protected function getValueAttribute() +	{ +		if(($value=$this->getValue())!=='') +			return $value; +		else +		{ +			$attributes=$this->getViewState('InputAttributes',null); +			if($attributes && $attributes->contains('value')) +				return $attributes->itemAt('value'); +			else if($this->hasAttribute('value')) +				return $this->getAttribute('value'); +			else +				return ''; +		} +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +    /** +     * Check if we need a span tag to surround this control. The span tag will be created if +     * the Text property is set for this control.  +     * +     * @return bool wether this control needs a surrounding span tag +     */ +    protected function getSpanNeeded() { +        return $this->getText()!==''; +    } + +	/** +	 * Renders a label beside the checkbox. +	 * @param THtmlWriter the writer for the rendering purpose +	 * @param string checkbox id +	 * @param string label text +	 */ +	protected function renderLabel($writer,$clientID,$text) +	{ +		$writer->addAttribute('for',$clientID); +		if($attributes=$this->getViewState('LabelAttributes',null)) +			$writer->addAttributes($attributes); +		$writer->renderBeginTag('label'); +		$writer->write($text); +		$writer->renderEndTag(); +	} + +	/** +	 * Renders a checkbox input element. +	 * @param THtmlWriter the writer for the rendering purpose +	 * @param string checkbox id +	 * @param string onclick js +	 */ +	protected function renderInputTag($writer,$clientID,$onclick) +	{ +		if($clientID!=='') +			$writer->addAttribute('id',$clientID); +		$writer->addAttribute('type','checkbox'); +		if(($value=$this->getValueAttribute())!=='') +			$writer->addAttribute('value',$value); +		if(!empty($onclick)) +			$writer->addAttribute('onclick',$onclick); +		if(($uniqueID=$this->getUniqueID())!=='') +			$writer->addAttribute('name',$uniqueID); +		if($this->getChecked()) +			$writer->addAttribute('checked','checked'); +		if(!$this->getEnabled(true)) +			$writer->addAttribute('disabled','disabled'); + +		$page=$this->getPage(); +		if($this->getEnabled(true) +			&& $this->getEnableClientScript() +			&& $this->getAutoPostBack() +			&& $page->getClientSupportsJavaScript()) +		{ +			$this->renderClientControlScript($writer); +		} + +		if(($accesskey=$this->getAccessKey())!=='') +			$writer->addAttribute('accesskey',$accesskey); +		if(($tabindex=$this->getTabIndex())>0) +			$writer->addAttribute('tabindex',"$tabindex"); +		if($attributes=$this->getViewState('InputAttributes',null)) +			$writer->addAttributes($attributes); +		$writer->renderBeginTag('input'); +		$writer->renderEndTag(); +	} + +	/** +	 * Renders the client-script code. +	 */ +	protected function renderClientControlScript($writer) +	{ +		$cs = $this->getPage()->getClientScript(); +		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TCheckBox'; +	} + +	/** +	 * Gets the post back options for this checkbox. +	 * @return array +	 */ +	protected function getPostBackOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['EventTarget'] = $this->getUniqueID(); +		return $options; +	} +} + +/** + * TTextAlign class. + * TTextAlign defines the enumerable type for the possible text alignments + * + * The following enumerable values are defined: + * - Left: left aligned + * - Right: right aligned + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTextAlign extends TEnumerable +{ +	const Left='Left'; +	const Right='Right'; +} + +?> diff --git a/framework/Web/UI/WebControls/TCheckBoxColumn.php b/framework/Web/UI/WebControls/TCheckBoxColumn.php index 9c1db114..e1a2e178 100644 --- a/framework/Web/UI/WebControls/TCheckBoxColumn.php +++ b/framework/Web/UI/WebControls/TCheckBoxColumn.php @@ -1,123 +1,123 @@ -<?php
 -/**
 - * TCheckBoxColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TCheckBoxColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -/**
 - * TCheckBox class file
 - */
 -Prado::using('System.Web.UI.WebControls.TCheckBox');
 -
 -/**
 - * TCheckBoxColumn class
 - *
 - * TCheckBoxColumn represents a checkbox column that is bound to a field in a data source.
 - * The checked state of the checkboxes are determiend by the bound data at
 - * {@link setDataField DataField}. If {@link setReadOnly ReadOnly} is false,
 - * TCheckBoxColumn will display an enabled checkbox provided the cells are
 - * in edit mode. Otherwise, the checkboxes will be disabled to prevent from editting.
 - *
 - * The checkbox control in the TCheckBoxColumn can be accessed by one of
 - * the following two methods:
 - * <code>
 - * $datagridItem->CheckBoxColumnID->CheckBox
 - * $datagridItem->CheckBoxColumnID->Controls[0]
 - * </code>
 - * The second method is possible because the checkbox control created within the
 - * datagrid cell is the first child.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCheckBoxColumn extends TDataGridColumn
 -{
 -	/**
 -	 * @return string the field name from the data source to bind to the column
 -	 */
 -	public function getDataField()
 -	{
 -		return $this->getViewState('DataField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the column
 -	 */
 -	public function setDataField($value)
 -	{
 -		$this->setViewState('DataField',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether the items in the column can be edited. Defaults to false.
 -	 */
 -	public function getReadOnly()
 -	{
 -		return $this->getViewState('ReadOnly',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the items in the column can be edited
 -	 */
 -	public function setReadOnly($value)
 -	{
 -		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It creates a checkbox inside the cell.
 -	 * If the column is read-only or if the item is not in edit mode,
 -	 * the checkbox will be set disabled.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem)
 -		{
 -			$checkBox=new TCheckBox;
 -			if($this->getReadOnly() || $itemType!==TListItemType::EditItem)
 -				$checkBox->setEnabled(false);
 -			$cell->setHorizontalAlign('Center');
 -			$cell->getControls()->add($checkBox);
 -			$cell->registerObject('CheckBox',$checkBox);
 -			if($this->getDataField()!=='')
 -				$checkBox->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -		}
 -		else
 -			parent::initializeCell($cell,$columnIndex,$itemType);
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		$item=$sender->getNamingContainer();
 -		$data=$item->getData();
 -		if(($field=$this->getDataField())!=='')
 -			$value=TPropertyValue::ensureBoolean($this->getDataFieldValue($data,$field));
 -		else
 -			$value=TPropertyValue::ensureBoolean($data);
 -		if($sender instanceof TCheckBox)
 -			$sender->setChecked($value);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); +/** + * TCheckBox class file + */ +Prado::using('System.Web.UI.WebControls.TCheckBox'); + +/** + * TCheckBoxColumn class + * + * TCheckBoxColumn represents a checkbox column that is bound to a field in a data source. + * The checked state of the checkboxes are determiend by the bound data at + * {@link setDataField DataField}. If {@link setReadOnly ReadOnly} is false, + * TCheckBoxColumn will display an enabled checkbox provided the cells are + * in edit mode. Otherwise, the checkboxes will be disabled to prevent from editting. + * + * The checkbox control in the TCheckBoxColumn can be accessed by one of + * the following two methods: + * <code> + * $datagridItem->CheckBoxColumnID->CheckBox + * $datagridItem->CheckBoxColumnID->Controls[0] + * </code> + * The second method is possible because the checkbox control created within the + * datagrid cell is the first child. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCheckBoxColumn extends TDataGridColumn +{ +	/** +	 * @return string the field name from the data source to bind to the column +	 */ +	public function getDataField() +	{ +		return $this->getViewState('DataField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the column +	 */ +	public function setDataField($value) +	{ +		$this->setViewState('DataField',$value,''); +	} + +	/** +	 * @return boolean whether the items in the column can be edited. Defaults to false. +	 */ +	public function getReadOnly() +	{ +		return $this->getViewState('ReadOnly',false); +	} + +	/** +	 * @param boolean whether the items in the column can be edited +	 */ +	public function setReadOnly($value) +	{ +		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It creates a checkbox inside the cell. +	 * If the column is read-only or if the item is not in edit mode, +	 * the checkbox will be set disabled. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem) +		{ +			$checkBox=new TCheckBox; +			if($this->getReadOnly() || $itemType!==TListItemType::EditItem) +				$checkBox->setEnabled(false); +			$cell->setHorizontalAlign('Center'); +			$cell->getControls()->add($checkBox); +			$cell->registerObject('CheckBox',$checkBox); +			if($this->getDataField()!=='') +				$checkBox->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +		} +		else +			parent::initializeCell($cell,$columnIndex,$itemType); +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		$item=$sender->getNamingContainer(); +		$data=$item->getData(); +		if(($field=$this->getDataField())!=='') +			$value=TPropertyValue::ensureBoolean($this->getDataFieldValue($data,$field)); +		else +			$value=TPropertyValue::ensureBoolean($data); +		if($sender instanceof TCheckBox) +			$sender->setChecked($value); +	} +} + diff --git a/framework/Web/UI/WebControls/TCheckBoxList.php b/framework/Web/UI/WebControls/TCheckBoxList.php index 2f938174..3c298a02 100644 --- a/framework/Web/UI/WebControls/TCheckBoxList.php +++ b/framework/Web/UI/WebControls/TCheckBoxList.php @@ -1,499 +1,499 @@ -<?php
 -/**
 - * TCheckBoxList class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TListControl class
 - */
 -Prado::using('System.Web.UI.WebControls.TListControl');
 -/**
 - * Includes TRepeatInfo class
 - */
 -Prado::using('System.Web.UI.WebControls.TRepeatInfo');
 -/**
 - * Includes TCheckBox class
 - */
 -Prado::using('System.Web.UI.WebControls.TCheckBox');
 -
 -/**
 - * TCheckBoxList class
 - *
 - * TCheckBoxList displays a list of checkboxes on a Web page.
 - *
 - * The layout of the checkbox list is specified via {@link setRepeatLayout RepeatLayout},
 - * which can be either 'Table' (default) or 'Flow'.
 - * A table layout uses HTML table cells to organize the checkboxes while
 - * a flow layout uses line breaks to organize the checkboxes.
 - * When the layout is using 'Table', {@link setCellPadding CellPadding} and
 - * {@link setCellSpacing CellSpacing} can be used to adjust the cellpadding and
 - * cellpadding of the table.
 - *
 - * The number of columns used to display the checkboxes is specified via
 - * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection}
 - * governs the order of the items being rendered.
 - *
 - * The alignment of the text besides each checkbox can be specified via {@link setTextAlign TextAlign}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingContainer, IPostBackDataHandler,  IValidatable
 -{
 -	private $_repeatedControl;
 -	private $_isEnabled;
 -	private $_changedEventRaised=false;
 -	private $_dataChanged=false;
 -	private $_isValid=true;
 -
 -	/**
 -	 * Constructor.
 -	 * Remember to call parent implementation if you override this method
 -	 */
 -	public function __construct()
 -	{
 -		parent::__construct();
 -		$this->_repeatedControl=$this->createRepeatedControl();
 -		$this->_repeatedControl->setEnableViewState(false);
 -		$this->_repeatedControl->setID('c0');
 -		$this->getControls()->add($this->_repeatedControl);
 -	}
 -
 -	/**
 -	 * Creates a control used for repetition (used as a template).
 -	 * @return TControl the control to be repeated
 -	 */
 -	protected function createRepeatedControl()
 -	{
 -		return new TCheckBox;
 -	}
 -
 -	/**
 -	 * Finds a control by ID.
 -	 * This method overrides the parent implementation so that it always returns
 -	 * the checkbox list itself (because the checkbox list does not have child controls.)
 -	 * @param string control ID
 -	 * @return TControl control being found
 -	 */
 -	public function findControl($id)
 -	{
 -		return $this;
 -	}
 -
 -	/**
 -	 * @return boolean whether this control supports multiple selection. Always true for checkbox list.
 -	 */
 -	protected function getIsMultiSelect()
 -	{
 -		return true;
 -	}
 -
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableStyle} to be used by checkbox list.
 -	 * @return TStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableStyle;
 -	}
 -
 -	/**
 -	 * @return TTextAlign the alignment of the text caption, defaults to TTextAlign::Right.
 -	 */
 -	public function getTextAlign()
 -	{
 -		return $this->getViewState('TextAlign',TTextAlign::Right);
 -	}
 -
 -	/**
 -	 * @param TTextAlign the text alignment of the checkboxes
 -	 */
 -	public function setTextAlign($value)
 -	{
 -		$this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,'TTextAlign'),TTextAlign::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.
 -	 */
 -	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);
 -	}
 -
 -	/**
 -	 * @return integer the cellspacing for the table keeping the checkbox list. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellSpacing()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getCellSpacing();
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * Sets the cellspacing for the table keeping the checkbox list.
 -	 * @param integer the cellspacing for the table keeping the checkbox list.
 -	 */
 -	public function setCellSpacing($value)
 -	{
 -		$this->getStyle()->setCellSpacing($value);
 -	}
 -
 -	/**
 -	 * @return integer the cellpadding for the table keeping the checkbox list. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellPadding()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getCellPadding();
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * Sets the cellpadding for the table keeping the checkbox list.
 -	 * @param integer the cellpadding for the table keeping the checkbox list.
 -	 */
 -	public function setCellPadding($value)
 -	{
 -		$this->getStyle()->setCellPadding($value);
 -	}
 -
 -	/**
 -	 * 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 false;
 -	}
 -
 -	/**
 -	 * 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 false;
 -	}
 -
 -	/**
 -	 * 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 false;
 -	}
 -	
 -	/**
 -	 * @param boolean whether the control is to be enabled.
 -	 */
 -	public function setEnabled($value)
 -	{
 -		parent::setEnabled($value);
 -		$value = !TPropertyValue::ensureBoolean($value);
 -		// if this is an active control, 
 -		// and it's a callback, 
 -		// and we can update clientside,
 -		// then update the 'disabled' attribute of the items.
 -		if(($this instanceof IActiveControl) &&
 -				$this->getPage()->getIsCallBack() &&
 -				$this->getActiveControl()->canUpdateClientSide())
 -		{
 -			$items = $this->getItems();
 -			$cs = $this->getPage()->getCallbackClient();
 -			$baseClientID = $this->getClientID().'_c';
 -			foreach($items as $index=>$item)
 -			{
 -				$cs->setAttribute($baseClientID.$index, 'disabled', $value);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * 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 null
 -	 */
 -	public function generateItemStyle($itemType,$index)
 -	{
 -		return null;
 -	}
 -
 -	/**
 -	 * 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)
 -	{
 -		$repeatedControl=$this->_repeatedControl;
 -		$item=$this->getItems()->itemAt($index);
 -		if($item->getHasAttributes())
 -			$repeatedControl->getAttributes()->copyFrom($item->getAttributes());
 -		else if($repeatedControl->getHasAttributes())
 -			$repeatedControl->getAttributes()->clear();
 -		$repeatedControl->setID("c$index");
 -		$repeatedControl->setText($item->getText());
 -		$repeatedControl->setChecked($item->getSelected());
 -		$repeatedControl->setAttribute('value',$item->getValue());
 -		$repeatedControl->setEnabled($this->_isEnabled && $item->getEnabled());
 -		$repeatedControl->setEnableClientScript(false);
 -		$repeatedControl->renderControl($writer);
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the control has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		if($this->getEnabled(true))
 -		{
 -			$index=(int)substr($key,strlen($this->getUniqueID())+2);
 -			$this->ensureDataBound();
 -			if($index>=0 && $index<$this->getItemCount())
 -			{
 -				$item=$this->getItems()->itemAt($index);
 -				if($item->getEnabled())
 -				{
 -					$checked=isset($values[$key]);
 -					if($item->getSelected()!==$checked)
 -					{
 -						$item->setSelected($checked);
 -						if(!$this->_changedEventRaised)
 -						{
 -							$this->_changedEventRaised=true;
 -							return $this->_dataChanged=true;
 -						}
 -					}
 -				}
 -			}
 -		}
 -		return false;
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method is required by {@link IPostBackDataHandler} interface.
 -	 * It is invoked by the framework when {@link getSelectedIndices SelectedIndices} property
 -	 * is changed on postback.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		if($this->getAutoPostBack() && $this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onSelectedIndexChanged(null);
 -	}
 -
 -	/**
 -	 * Registers for post data on postback.
 -	 * This method overrides the parent implementation.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		$this->_repeatedControl->setAutoPostBack($this->getAutoPostBack());
 -		$this->_repeatedControl->setCausesValidation($this->getCausesValidation());
 -		$this->_repeatedControl->setValidationGroup($this->getValidationGroup());
 -		$page=$this->getPage();
 -		$n=$this->getItemCount();
 -		for($i=0;$i<$n;++$i)
 -		{
 -			$this->_repeatedControl->setID("c$i");
 -			$page->registerRequiresPostData($this->_repeatedControl);
 -		}
 -	}
 -
 -	/**
 -	 * Wether the list should be rendered inside a span or not
 -	 * 
 -	 *@return boolean true if we need a span
 -	 */
 -	protected function getSpanNeeded ()
 -	{
 -		return $this->getRepeatLayout()===TRepeatLayout::Raw;
 -	}
 -	
 -	/**
 -	 * Renders the checkbox list control.
 -	 * This method overrides the parent implementation.
 -	 * @param THtmlWriter writer for rendering purpose.
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->getItemCount()>0)
 -		{
 -			if ($needSpan=$this->getSpanNeeded())
 -			{
 -				$writer->addAttribute('id', $this->getClientId());
 -				$writer->renderBeginTag('span');
 -			}
 -			$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);
 -			if ($needSpan)
 -				$writer->renderEndTag();
 -		}
 -		//checkbox skipped the client control script in addAttributesToRender
 -		if($this->getEnabled(true)
 -			&& $this->getEnableClientScript()
 -			&& $this->getAutoPostBack()
 -			&& $this->getPage()->getClientSupportsJavaScript())
 -		{
 -			$this->renderClientControlScript($writer);
 -		}
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Returns the value to be validated.
 -	 * This methid is required by IValidatable interface.
 -	 * @return mixed the value of the property to be validated.
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getSelectedValue();
 -	}
 -
 -	/**
 -	 * Returns true if this control validated successfully. 
 -	 * Defaults to true.
 -	 * @return bool wether this control validated successfully.
 -	 */
 -	public function getIsValid()
 -	{
 -	    return $this->_isValid;
 -	}
 -	/**
 -	 * @param bool wether this control is valid.
 -	 */
 -	public function setIsValid($value)
 -	{
 -	    $this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TCheckBoxList';
 -	}
 -
 -	/**
 -	 * Gets the post back options for this checkbox.
 -	 * @return array
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ListID'] = $this->getClientID();
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['ListName'] = $this->getUniqueID();
 -		$options['ItemCount'] = $this->getItemCount();
 -		return $options;
 -	}
 -	
 -}
 -
 +<?php +/** + * TCheckBoxList class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TListControl class + */ +Prado::using('System.Web.UI.WebControls.TListControl'); +/** + * Includes TRepeatInfo class + */ +Prado::using('System.Web.UI.WebControls.TRepeatInfo'); +/** + * Includes TCheckBox class + */ +Prado::using('System.Web.UI.WebControls.TCheckBox'); + +/** + * TCheckBoxList class + * + * TCheckBoxList displays a list of checkboxes on a Web page. + * + * The layout of the checkbox list is specified via {@link setRepeatLayout RepeatLayout}, + * which can be either 'Table' (default) or 'Flow'. + * A table layout uses HTML table cells to organize the checkboxes while + * a flow layout uses line breaks to organize the checkboxes. + * When the layout is using 'Table', {@link setCellPadding CellPadding} and + * {@link setCellSpacing CellSpacing} can be used to adjust the cellpadding and + * cellpadding of the table. + * + * The number of columns used to display the checkboxes is specified via + * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection} + * governs the order of the items being rendered. + * + * The alignment of the text besides each checkbox can be specified via {@link setTextAlign TextAlign}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCheckBoxList extends TListControl implements IRepeatInfoUser, INamingContainer, IPostBackDataHandler,  IValidatable +{ +	private $_repeatedControl; +	private $_isEnabled; +	private $_changedEventRaised=false; +	private $_dataChanged=false; +	private $_isValid=true; + +	/** +	 * Constructor. +	 * Remember to call parent implementation if you override this method +	 */ +	public function __construct() +	{ +		parent::__construct(); +		$this->_repeatedControl=$this->createRepeatedControl(); +		$this->_repeatedControl->setEnableViewState(false); +		$this->_repeatedControl->setID('c0'); +		$this->getControls()->add($this->_repeatedControl); +	} + +	/** +	 * Creates a control used for repetition (used as a template). +	 * @return TControl the control to be repeated +	 */ +	protected function createRepeatedControl() +	{ +		return new TCheckBox; +	} + +	/** +	 * Finds a control by ID. +	 * This method overrides the parent implementation so that it always returns +	 * the checkbox list itself (because the checkbox list does not have child controls.) +	 * @param string control ID +	 * @return TControl control being found +	 */ +	public function findControl($id) +	{ +		return $this; +	} + +	/** +	 * @return boolean whether this control supports multiple selection. Always true for checkbox list. +	 */ +	protected function getIsMultiSelect() +	{ +		return true; +	} + +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableStyle} to be used by checkbox list. +	 * @return TStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableStyle; +	} + +	/** +	 * @return TTextAlign the alignment of the text caption, defaults to TTextAlign::Right. +	 */ +	public function getTextAlign() +	{ +		return $this->getViewState('TextAlign',TTextAlign::Right); +	} + +	/** +	 * @param TTextAlign the text alignment of the checkboxes +	 */ +	public function setTextAlign($value) +	{ +		$this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,'TTextAlign'),TTextAlign::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. +	 */ +	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); +	} + +	/** +	 * @return integer the cellspacing for the table keeping the checkbox list. Defaults to -1, meaning not set. +	 */ +	public function getCellSpacing() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getCellSpacing(); +		else +			return -1; +	} + +	/** +	 * Sets the cellspacing for the table keeping the checkbox list. +	 * @param integer the cellspacing for the table keeping the checkbox list. +	 */ +	public function setCellSpacing($value) +	{ +		$this->getStyle()->setCellSpacing($value); +	} + +	/** +	 * @return integer the cellpadding for the table keeping the checkbox list. Defaults to -1, meaning not set. +	 */ +	public function getCellPadding() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getCellPadding(); +		else +			return -1; +	} + +	/** +	 * Sets the cellpadding for the table keeping the checkbox list. +	 * @param integer the cellpadding for the table keeping the checkbox list. +	 */ +	public function setCellPadding($value) +	{ +		$this->getStyle()->setCellPadding($value); +	} + +	/** +	 * 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 false; +	} + +	/** +	 * 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 false; +	} + +	/** +	 * 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 false; +	} +	 +	/** +	 * @param boolean whether the control is to be enabled. +	 */ +	public function setEnabled($value) +	{ +		parent::setEnabled($value); +		$value = !TPropertyValue::ensureBoolean($value); +		// if this is an active control,  +		// and it's a callback,  +		// and we can update clientside, +		// then update the 'disabled' attribute of the items. +		if(($this instanceof IActiveControl) && +				$this->getPage()->getIsCallBack() && +				$this->getActiveControl()->canUpdateClientSide()) +		{ +			$items = $this->getItems(); +			$cs = $this->getPage()->getCallbackClient(); +			$baseClientID = $this->getClientID().'_c'; +			foreach($items as $index=>$item) +			{ +				$cs->setAttribute($baseClientID.$index, 'disabled', $value); +			} +		} +	} + +	/** +	 * 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 null +	 */ +	public function generateItemStyle($itemType,$index) +	{ +		return null; +	} + +	/** +	 * 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) +	{ +		$repeatedControl=$this->_repeatedControl; +		$item=$this->getItems()->itemAt($index); +		if($item->getHasAttributes()) +			$repeatedControl->getAttributes()->copyFrom($item->getAttributes()); +		else if($repeatedControl->getHasAttributes()) +			$repeatedControl->getAttributes()->clear(); +		$repeatedControl->setID("c$index"); +		$repeatedControl->setText($item->getText()); +		$repeatedControl->setChecked($item->getSelected()); +		$repeatedControl->setAttribute('value',$item->getValue()); +		$repeatedControl->setEnabled($this->_isEnabled && $item->getEnabled()); +		$repeatedControl->setEnableClientScript(false); +		$repeatedControl->renderControl($writer); +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the control has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		if($this->getEnabled(true)) +		{ +			$index=(int)substr($key,strlen($this->getUniqueID())+2); +			$this->ensureDataBound(); +			if($index>=0 && $index<$this->getItemCount()) +			{ +				$item=$this->getItems()->itemAt($index); +				if($item->getEnabled()) +				{ +					$checked=isset($values[$key]); +					if($item->getSelected()!==$checked) +					{ +						$item->setSelected($checked); +						if(!$this->_changedEventRaised) +						{ +							$this->_changedEventRaised=true; +							return $this->_dataChanged=true; +						} +					} +				} +			} +		} +		return false; +	} + +	/** +	 * Raises postdata changed event. +	 * This method is required by {@link IPostBackDataHandler} interface. +	 * It is invoked by the framework when {@link getSelectedIndices SelectedIndices} property +	 * is changed on postback. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		if($this->getAutoPostBack() && $this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onSelectedIndexChanged(null); +	} + +	/** +	 * Registers for post data on postback. +	 * This method overrides the parent implementation. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		$this->_repeatedControl->setAutoPostBack($this->getAutoPostBack()); +		$this->_repeatedControl->setCausesValidation($this->getCausesValidation()); +		$this->_repeatedControl->setValidationGroup($this->getValidationGroup()); +		$page=$this->getPage(); +		$n=$this->getItemCount(); +		for($i=0;$i<$n;++$i) +		{ +			$this->_repeatedControl->setID("c$i"); +			$page->registerRequiresPostData($this->_repeatedControl); +		} +	} + +	/** +	 * Wether the list should be rendered inside a span or not +	 *  +	 *@return boolean true if we need a span +	 */ +	protected function getSpanNeeded () +	{ +		return $this->getRepeatLayout()===TRepeatLayout::Raw; +	} +	 +	/** +	 * Renders the checkbox list control. +	 * This method overrides the parent implementation. +	 * @param THtmlWriter writer for rendering purpose. +	 */ +	public function render($writer) +	{ +		if($this->getItemCount()>0) +		{ +			if ($needSpan=$this->getSpanNeeded()) +			{ +				$writer->addAttribute('id', $this->getClientId()); +				$writer->renderBeginTag('span'); +			} +			$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); +			if ($needSpan) +				$writer->renderEndTag(); +		} +		//checkbox skipped the client control script in addAttributesToRender +		if($this->getEnabled(true) +			&& $this->getEnableClientScript() +			&& $this->getAutoPostBack() +			&& $this->getPage()->getClientSupportsJavaScript()) +		{ +			$this->renderClientControlScript($writer); +		} +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Returns the value to be validated. +	 * This methid is required by IValidatable interface. +	 * @return mixed the value of the property to be validated. +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getSelectedValue(); +	} + +	/** +	 * Returns true if this control validated successfully.  +	 * Defaults to true. +	 * @return bool wether this control validated successfully. +	 */ +	public function getIsValid() +	{ +	    return $this->_isValid; +	} +	/** +	 * @param bool wether this control is valid. +	 */ +	public function setIsValid($value) +	{ +	    $this->_isValid=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TCheckBoxList'; +	} + +	/** +	 * Gets the post back options for this checkbox. +	 * @return array +	 */ +	protected function getPostBackOptions() +	{ +		$options['ListID'] = $this->getClientID(); +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['ListName'] = $this->getUniqueID(); +		$options['ItemCount'] = $this->getItemCount(); +		return $options; +	} +	 +} + diff --git a/framework/Web/UI/WebControls/TColorPicker.php b/framework/Web/UI/WebControls/TColorPicker.php index e5b24bd0..365421a1 100644 --- a/framework/Web/UI/WebControls/TColorPicker.php +++ b/framework/Web/UI/WebControls/TColorPicker.php @@ -1,290 +1,290 @@ -<?php
 -/**
 - * TColorPicker class file
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TColorPicker class.
 - *
 - * TColorPicker displays a text box for color input purpose.
 - * Next to the textbox there's a button filled with the current chosen color.
 - * Users can write a color name directly in the text box as an hex triplet (also known as HTML notation, eg: #FF00FF).
 - * Alternatively, if the <b>ShowColorPicker</b> property is enabled (it is by default), users can click the button
 - * to have a color picker UI appear. A color chan be chosen directly by clicking on the color picker.
 - *
 - * TColorPicker has three different color picker UI <b>Mode</b>s:
 - *  # <b>Simple</b> - Grid with 12 simple colors.
 - *  # <b>Basic</b> - Grid with the most common 70 colors. This is the default mode.
 - *  # <b>Full</b> - Full-featured color picker.
 - * 
 - * The <b>CssClass</b> property can be used to override the CSS class name
 - * for the color picker panel. The <b>ColorStyle</b> property sets the packages
 - * styles available. E.g. <b>default</b>.
 - * 
 - * If the <b>Mode</b> property is set to <b>Full</b>, the color picker panel will
 - * display an "Ok" and "Cancel" buttons. You can customize the button labels setting the <b>OKButtonText</b>
 - * and <b>CancelButtonText</b> properties.
 - * 
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TColorPicker extends TTextBox
 -{
 -	const SCRIPT_PATH = 'prado/colorpicker';
 -
 -	private $_clientSide;
 -
 -	/**
 -	 * @return boolean whether the color picker should pop up when the button is clicked.
 -	 */
 -	public function getShowColorPicker()
 -	{
 -		return $this->getViewState('ShowColorPicker',true);
 -	}
 -
 -	/**
 -	 * Sets whether to pop up the color picker when the button is clicked.
 -	 * @param boolean whether to show the color picker popup
 -	 */
 -	public function setShowColorPicker($value)
 -	{
 -		$this->setViewState('ShowColorPicker',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @param TColorPickerMode color picker UI mode
 -	 */
 -	public function setMode($value)
 -	{
 -	   $this->setViewState('Mode', TPropertyValue::ensureEnum($value, 'TColorPickerMode'), TColorPickerMode::Basic);
 -	}
 -
 -	/**
 -	 * @return TColorPickerMode current color picker UI mode. Defaults to TColorPickerMode::Basic.
 -	 */
 -	public function getMode()
 -	{
 -	   return $this->getViewState('Mode', TColorPickerMode::Basic);
 -	}
 -
 -	/**
 -	 * @param string set the color picker style
 -	 */
 -	public function setColorPickerStyle($value)
 -	{
 -	   $this->setViewState('ColorStyle', $value, 'default');
 -	}
 -
 -	/**
 -	 * @return string current color picker style
 -	 */
 -	public function getColorPickerStyle()
 -	{
 -	   return $this->getViewState('ColorStyle', 'default');
 -	}
 -
 -	/**
 -	 * @return string text for the color picker OK button. Default is "OK".
 -	 */
 -	public function getOKButtonText()
 -	{
 -		return $this->getViewState('OKButtonText', 'OK');
 -	}
 -
 -	/**
 -	 * @param string text for the color picker OK button
 -	 */
 -	public function setOKButtonText($value)
 -	{
 -		$this->setViewState('OKButtonText', $value, 'OK');
 -	}
 -
 -	/**
 -	 * @return string text for the color picker Cancel button. Default is "Cancel".
 -	 */
 -	public function getCancelButtonText()
 -	{
 -		return $this->getViewState('CancelButtonText', 'Cancel');
 -	}
 -
 -	/**
 -	 * @param string text for the color picker Cancel button
 -	 */
 -	public function setCancelButtonText($value)
 -	{
 -		$this->setViewState('CancelButtonText', $value, 'Cancel');
 -	}
 -
 -	/**
 -	 * @return TColorPickerClientSide javascript event options.
 -	 */
 -	public function getClientSide()
 -	{
 -		if($this->_clientSide===null)
 -			$this->_clientSide = $this->createClientSide();
 -		return $this->_clientSide;
 -	}
 -
 -	/**
 -	 * @return TColorPickerClientSide javascript validator event options.
 -	 */
 -	protected function createClientSide()
 -	{
 -		return new TColorPickerClientSide;
 -	}
 -
 -	/**
 -	 * Get javascript color picker options.
 -	 * @return array color picker client-side options
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options = parent::getPostBackOptions();
 -		$options['ClassName'] = $this->getCssClass();
 -		$options['ShowColorPicker'] = $this->getShowColorPicker();
 -		if($options['ShowColorPicker'])
 -		{
 -			$mode = $this->getMode();
 -			if($mode == TColorPickerMode::Full) $options['Mode'] = $mode;
 -			else if($mode == TColorPickerMode::Simple) $options['Palette'] = 'Tiny';
 -			$options['OKButtonText'] = $this->getOKButtonText();
 -			$options['CancelButtonText'] = $this->getCancelButtonText();
 -		}
 -		$options = array_merge($options,$this->getClientSide()->getOptions()->toArray());
 -		return $options;
 -	}
 -
 -	/**
 -	 * @param string asset file in the self::SCRIPT_PATH directory.
 -	 * @return string asset file url.
 -	 */
 -	protected function getAssetUrl($file='')
 -	{
 -		$base = $this->getPage()->getClientScript()->getPradoScriptAssetUrl();
 -		return $base.'/'.self::SCRIPT_PATH.'/'.$file;
 -	}
 -
 -	/**
 -	 * Publish the color picker Css asset files.
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		$this->publishColorPickerAssets();
 -	}
 -
 -	/**
 -	 * Publish the color picker assets.
 -	 */
 -	protected function publishColorPickerAssets()
 -	{
 -		$cs = $this->getPage()->getClientScript();
 -		$key = "prado:".get_class($this);
 -		$imgs['button.gif'] = $this->getAssetUrl('button.gif');
 -		$imgs['background.png'] = $this->getAssetUrl('background.png');
 -		$options = TJavaScript::encode($imgs);
 -		$code = "Prado.WebUI.TColorPicker.UIImages = {$options};";
 -		$cs->registerEndScript($key, $code);
 -		$cs->registerPradoScript("colorpicker");
 -		$url = $this->getAssetUrl($this->getColorPickerStyle().'.css');
 -		if(!$cs->isStyleSheetFileRegistered($url))
 -			$cs->registerStyleSheetFile($url, $url);
 -	}
 -
 -	/**
 -	 * Renders additional body content.
 -	 * This method overrides parent implementation by adding
 -	 * additional color picker button.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function renderEndTag($writer)
 -	{
 -		parent::renderEndTag($writer);
 -
 -		$color = $this->getText();
 -		$writer->addAttribute('class', 'TColorPicker_button');
 -		$writer->renderBeginTag('span');
 -
 -		$writer->addAttribute('id', $this->getClientID().'_button');
 -		$writer->addAttribute('src', $this->getAssetUrl('button.gif'));
 -		if($color !== '')
 -			$writer->addAttribute('style', "background-color:{$color};");
 -		$writer->addAttribute('width', '20');
 -		$writer->addAttribute('height', '20');
 -		$writer->addAttribute('alt', '');
 -		$writer->renderBeginTag('img');
 -		$writer->renderEndTag();
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TColorPicker';
 -	}
 -}
 -
 -/**
 - * TColorPickerMode class.
 - * TColorPickerMode defines the enumerable type for the possible UI mode
 - * that a {@link TColorPicker} control can take.
 - *
 - * The following enumerable values are defined:
 - * # Simple - Grid with 12 simple colors.
 - * # Basic - Grid with the most common 70 colors. This is the default mode.
 - * # Full - Full-featured color picker.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TColorPickerMode extends TEnumerable
 -{
 -	const Simple='Simple';
 -	const Basic='Basic';
 -	const Full='Full';
 -}
 -
 -/**
 - * TColorPickerClientSide class.
 - *
 - * Client-side javascript code options.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1
 - */
 -class TColorPickerClientSide extends TClientSideOptions
 -{
 -	/**
 -	 * @return string javascript code for when a color is selected.
 -	 */
 -	public function getOnColorSelected()
 -	{
 -		return $this->getOption('OnColorSelected');
 -	}
 -
 -	/**
 -	 * @param string javascript code for when a color is selected.
 -	 */
 -	public function setOnColorSelected($javascript)
 -	{
 -		$this->setFunction('OnColorSelected', $javascript);
 -	}
 -}
 -
 +<?php +/** + * TColorPicker class file + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TColorPicker class. + * + * TColorPicker displays a text box for color input purpose. + * Next to the textbox there's a button filled with the current chosen color. + * Users can write a color name directly in the text box as an hex triplet (also known as HTML notation, eg: #FF00FF). + * Alternatively, if the <b>ShowColorPicker</b> property is enabled (it is by default), users can click the button + * to have a color picker UI appear. A color chan be chosen directly by clicking on the color picker. + * + * TColorPicker has three different color picker UI <b>Mode</b>s: + *  # <b>Simple</b> - Grid with 12 simple colors. + *  # <b>Basic</b> - Grid with the most common 70 colors. This is the default mode. + *  # <b>Full</b> - Full-featured color picker. + *  + * The <b>CssClass</b> property can be used to override the CSS class name + * for the color picker panel. The <b>ColorStyle</b> property sets the packages + * styles available. E.g. <b>default</b>. + *  + * If the <b>Mode</b> property is set to <b>Full</b>, the color picker panel will + * display an "Ok" and "Cancel" buttons. You can customize the button labels setting the <b>OKButtonText</b> + * and <b>CancelButtonText</b> properties. + *  + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TColorPicker extends TTextBox +{ +	const SCRIPT_PATH = 'prado/colorpicker'; + +	private $_clientSide; + +	/** +	 * @return boolean whether the color picker should pop up when the button is clicked. +	 */ +	public function getShowColorPicker() +	{ +		return $this->getViewState('ShowColorPicker',true); +	} + +	/** +	 * Sets whether to pop up the color picker when the button is clicked. +	 * @param boolean whether to show the color picker popup +	 */ +	public function setShowColorPicker($value) +	{ +		$this->setViewState('ShowColorPicker',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @param TColorPickerMode color picker UI mode +	 */ +	public function setMode($value) +	{ +	   $this->setViewState('Mode', TPropertyValue::ensureEnum($value, 'TColorPickerMode'), TColorPickerMode::Basic); +	} + +	/** +	 * @return TColorPickerMode current color picker UI mode. Defaults to TColorPickerMode::Basic. +	 */ +	public function getMode() +	{ +	   return $this->getViewState('Mode', TColorPickerMode::Basic); +	} + +	/** +	 * @param string set the color picker style +	 */ +	public function setColorPickerStyle($value) +	{ +	   $this->setViewState('ColorStyle', $value, 'default'); +	} + +	/** +	 * @return string current color picker style +	 */ +	public function getColorPickerStyle() +	{ +	   return $this->getViewState('ColorStyle', 'default'); +	} + +	/** +	 * @return string text for the color picker OK button. Default is "OK". +	 */ +	public function getOKButtonText() +	{ +		return $this->getViewState('OKButtonText', 'OK'); +	} + +	/** +	 * @param string text for the color picker OK button +	 */ +	public function setOKButtonText($value) +	{ +		$this->setViewState('OKButtonText', $value, 'OK'); +	} + +	/** +	 * @return string text for the color picker Cancel button. Default is "Cancel". +	 */ +	public function getCancelButtonText() +	{ +		return $this->getViewState('CancelButtonText', 'Cancel'); +	} + +	/** +	 * @param string text for the color picker Cancel button +	 */ +	public function setCancelButtonText($value) +	{ +		$this->setViewState('CancelButtonText', $value, 'Cancel'); +	} + +	/** +	 * @return TColorPickerClientSide javascript event options. +	 */ +	public function getClientSide() +	{ +		if($this->_clientSide===null) +			$this->_clientSide = $this->createClientSide(); +		return $this->_clientSide; +	} + +	/** +	 * @return TColorPickerClientSide javascript validator event options. +	 */ +	protected function createClientSide() +	{ +		return new TColorPickerClientSide; +	} + +	/** +	 * Get javascript color picker options. +	 * @return array color picker client-side options +	 */ +	protected function getPostBackOptions() +	{ +		$options = parent::getPostBackOptions(); +		$options['ClassName'] = $this->getCssClass(); +		$options['ShowColorPicker'] = $this->getShowColorPicker(); +		if($options['ShowColorPicker']) +		{ +			$mode = $this->getMode(); +			if($mode == TColorPickerMode::Full) $options['Mode'] = $mode; +			else if($mode == TColorPickerMode::Simple) $options['Palette'] = 'Tiny'; +			$options['OKButtonText'] = $this->getOKButtonText(); +			$options['CancelButtonText'] = $this->getCancelButtonText(); +		} +		$options = array_merge($options,$this->getClientSide()->getOptions()->toArray()); +		return $options; +	} + +	/** +	 * @param string asset file in the self::SCRIPT_PATH directory. +	 * @return string asset file url. +	 */ +	protected function getAssetUrl($file='') +	{ +		$base = $this->getPage()->getClientScript()->getPradoScriptAssetUrl(); +		return $base.'/'.self::SCRIPT_PATH.'/'.$file; +	} + +	/** +	 * Publish the color picker Css asset files. +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		$this->publishColorPickerAssets(); +	} + +	/** +	 * Publish the color picker assets. +	 */ +	protected function publishColorPickerAssets() +	{ +		$cs = $this->getPage()->getClientScript(); +		$key = "prado:".get_class($this); +		$imgs['button.gif'] = $this->getAssetUrl('button.gif'); +		$imgs['background.png'] = $this->getAssetUrl('background.png'); +		$options = TJavaScript::encode($imgs); +		$code = "Prado.WebUI.TColorPicker.UIImages = {$options};"; +		$cs->registerEndScript($key, $code); +		$cs->registerPradoScript("colorpicker"); +		$url = $this->getAssetUrl($this->getColorPickerStyle().'.css'); +		if(!$cs->isStyleSheetFileRegistered($url)) +			$cs->registerStyleSheetFile($url, $url); +	} + +	/** +	 * Renders additional body content. +	 * This method overrides parent implementation by adding +	 * additional color picker button. +	 * @param THtmlWriter writer +	 */ +	public function renderEndTag($writer) +	{ +		parent::renderEndTag($writer); + +		$color = $this->getText(); +		$writer->addAttribute('class', 'TColorPicker_button'); +		$writer->renderBeginTag('span'); + +		$writer->addAttribute('id', $this->getClientID().'_button'); +		$writer->addAttribute('src', $this->getAssetUrl('button.gif')); +		if($color !== '') +			$writer->addAttribute('style', "background-color:{$color};"); +		$writer->addAttribute('width', '20'); +		$writer->addAttribute('height', '20'); +		$writer->addAttribute('alt', ''); +		$writer->renderBeginTag('img'); +		$writer->renderEndTag(); +		$writer->renderEndTag(); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TColorPicker'; +	} +} + +/** + * TColorPickerMode class. + * TColorPickerMode defines the enumerable type for the possible UI mode + * that a {@link TColorPicker} control can take. + * + * The following enumerable values are defined: + * # Simple - Grid with 12 simple colors. + * # Basic - Grid with the most common 70 colors. This is the default mode. + * # Full - Full-featured color picker. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TColorPickerMode extends TEnumerable +{ +	const Simple='Simple'; +	const Basic='Basic'; +	const Full='Full'; +} + +/** + * TColorPickerClientSide class. + * + * Client-side javascript code options. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1 + */ +class TColorPickerClientSide extends TClientSideOptions +{ +	/** +	 * @return string javascript code for when a color is selected. +	 */ +	public function getOnColorSelected() +	{ +		return $this->getOption('OnColorSelected'); +	} + +	/** +	 * @param string javascript code for when a color is selected. +	 */ +	public function setOnColorSelected($javascript) +	{ +		$this->setFunction('OnColorSelected', $javascript); +	} +} + diff --git a/framework/Web/UI/WebControls/TCompareValidator.php b/framework/Web/UI/WebControls/TCompareValidator.php index 57b42018..c936f140 100644 --- a/framework/Web/UI/WebControls/TCompareValidator.php +++ b/framework/Web/UI/WebControls/TCompareValidator.php @@ -1,265 +1,265 @@ -<?php
 -/**
 - * TCompareValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TCompareValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TCompareValidator class
 - *
 - * TCompareValidator compares the value entered by the user into an input
 - * control with the value entered into another input control or a constant value.
 - * To compare the associated input control with another input control,
 - * set the {@link setControlToCompare ControlToCompare} property to the ID path
 - * of the control to compare with. To compare the associated input control with
 - * a constant value, specify the constant value to compare with by setting the
 - * {@link setValueToCompare ValueToCompare} property.
 - *
 - * The {@link setDataType DataType} property is used to specify the data type
 - * of both comparison values. Both values are automatically converted to this data
 - * type before the comparison operation is performed. The following value types are supported:
 - * - <b>Integer</b> A 32-bit signed integer data type.
 - * - <b>Float</b> A double-precision floating point number data type.
 - * - <b>Date</b> A date data type. The format can be specified by the
 - * {@link setDateFormat DateFormat} property
 - * - <b>String</b> A string data type.
 - *
 - * Use the {@link setOperator Operator} property to specify the type of comparison
 - * to perform. Valid operators include Equal, NotEqual, GreaterThan, GreaterThanEqual,
 - * LessThan and LessThanEqual.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCompareValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TCompareValidator';
 -	}
 -
 -	/**
 -	 * @return TValidationDataType the data type that the values being compared are converted to before the comparison is made. Defaults to TValidationDataType::String.
 -	 */
 -	public function getDataType()
 -	{
 -		return $this->getViewState('DataType',TValidationDataType::String);
 -	}
 -
 -	/**
 -	 * Sets the data type that the values being
 -	 * compared are converted to before the comparison is made.
 -	 * @param TValidationDataType the data type
 -	 */
 -	public function setDataType($value)
 -	{
 -		$this->setViewState('DataType',TPropertyValue::ensureEnum($value,'TValidationDataType'),TValidationDataType::String);
 -	}
 -
 -	/**
 -	 * @return string the input component to compare with the input control being validated.
 -	 */
 -	public function getControlToCompare()
 -	{
 -		return $this->getViewState('ControlToCompare','');
 -	}
 -
 -	/**
 -	 * Sets the input component to compare with the input control being validated.
 -	 * @param string the ID path of the component to compare with
 -	 */
 -	public function setControlToCompare($value)
 -	{
 -		$this->setViewState('ControlToCompare',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the constant value to compare with the value entered by the user into the input component being validated.
 -	 */
 -	public function getValueToCompare()
 -	{
 -		return $this->getViewState('ValueToCompare','');
 -	}
 -
 -	/**
 -	 * Sets the constant value to compare with the value entered by the user into the input component being validated.
 -	 * @param string the constant value
 -	 */
 -	public function setValueToCompare($value)
 -	{
 -		$this->setViewState('ValueToCompare',$value,'');
 -	}
 -
 -	/**
 -	 * @return TValidationCompareOperator the comparison operation to perform. Defaults to TValidationCompareOperator::Equal.
 -	 */
 -	public function getOperator()
 -	{
 -		return $this->getViewState('Operator',TValidationCompareOperator::Equal);
 -	}
 -
 -	/**
 -	 * Sets the comparison operation to perform
 -	 * @param TValidationCompareOperator the comparison operation
 -	 */
 -	public function setOperator($value)
 -	{
 -		$this->setViewState('Operator',TPropertyValue::ensureEnum($value,'TValidationCompareOperator'),TValidationCompareOperator::Equal);
 -	}
 -
 -	/**
 -     * Sets the date format for a date validation
 -     * @param string the date format value
 -     */
 -	public function setDateFormat($value)
 -	{
 -		$this->setViewState('DateFormat', $value, '');
 -	}
 -
 -	/**
 -	 * @return string the date validation date format if any
 -	 */
 -	public function getDateFormat()
 -	{
 -		return $this->getViewState('DateFormat', '');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input data compares successfully.
 -	 * The validation always succeeds if ControlToValidate is not specified
 -	 * or the input data is empty.
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	public function evaluateIsValid()
 -	{
 -		if(($value=$this->getValidationValue($this->getValidationTarget()))==='')
 -			return true;
 -
 -		if(($controlToCompare=$this->getControlToCompare())!=='')
 -		{
 -			if(($control2=$this->findControl($controlToCompare))===null)
 -				throw new TInvalidDataValueException('comparevalidator_controltocompare_invalid');
 -			if(($value2=$this->getValidationValue($control2))==='')
 -				return false;
 -		}
 -		else
 -			$value2=$this->getValueToCompare();
 -
 -		$values = $this->getComparisonValues($value, $value2);
 -		switch($this->getOperator())
 -		{
 -			case TValidationCompareOperator::Equal:
 -				return $values[0] == $values[1];
 -			case TValidationCompareOperator::NotEqual:
 -				return $values[0] != $values[1];
 -			case TValidationCompareOperator::GreaterThan:
 -				return $values[0] > $values[1];
 -			case TValidationCompareOperator::GreaterThanEqual:
 -				return $values[0] >= $values[1];
 -			case TValidationCompareOperator::LessThan:
 -				return $values[0] < $values[1];
 -			case TValidationCompareOperator::LessThanEqual:
 -				return $values[0] <= $values[1];
 -		}
 -
 -		return false;
 -	}
 -
 -	/**
 -	 * Parse the pair of values into the appropriate value type.
 -	 * @param string value one
 -	 * @param string second value
 -	 * @return array appropriate type of the value pair, array($value1, $value2);
 -	 */
 -	protected function getComparisonValues($value1, $value2)
 -	{
 -		switch($this->getDataType())
 -		{
 -			case TValidationDataType::Integer:
 -				return array(intval($value1), intval($value2));
 -			case TValidationDataType::Float:
 -				return array(floatval($value1), floatval($value2));
 -			case TValidationDataType::Date:
 -				$dateFormat = $this->getDateFormat();
 -				if($dateFormat!=='')
 -				{
 -					$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', $dateFormat);
 -					return array($formatter->parse($value1), $formatter->parse($value2));
 -				}
 -				else
 -					return array(strtotime($value1), strtotime($value2));
 -		}
 -		return array($value1, $value2);
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options = parent::getClientScriptOptions();
 -		if(($name=$this->getControlToCompare())!=='')
 -		{
 -			if(($control=$this->findControl($name))!==null)
 -				$options['ControlToCompare']=$control->getClientID();
 -		}
 -		if(($value=$this->getValueToCompare())!=='')
 -			$options['ValueToCompare']=$value;
 -		if(($operator=$this->getOperator())!==TValidationCompareOperator::Equal)
 -			$options['Operator']=$operator;
 -		$options['DataType']=$this->getDataType();
 -		if(($dateFormat=$this->getDateFormat())!=='')
 -			$options['DateFormat']=$dateFormat;
 -		return $options;
 -	}
 -}
 -
 -
 -/**
 - * TValidationCompareOperator class.
 - * TValidationCompareOperator defines the enumerable type for the comparison operations
 - * that {@link TCompareValidator} can perform validation with.
 - *
 - * The following enumerable values are defined:
 - * - Equal
 - * - NotEqual
 - * - GreaterThan
 - * - GreaterThanEqual
 - * - LessThan
 - * - LessThanEqual
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TValidationCompareOperator extends TEnumerable
 -{
 -	const Equal='Equal';
 -	const NotEqual='NotEqual';
 -	const GreaterThan='GreaterThan';
 -	const GreaterThanEqual='GreaterThanEqual';
 -	const LessThan='LessThan';
 -	const LessThanEqual='LessThanEqual';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TCompareValidator class + * + * TCompareValidator compares the value entered by the user into an input + * control with the value entered into another input control or a constant value. + * To compare the associated input control with another input control, + * set the {@link setControlToCompare ControlToCompare} property to the ID path + * of the control to compare with. To compare the associated input control with + * a constant value, specify the constant value to compare with by setting the + * {@link setValueToCompare ValueToCompare} property. + * + * The {@link setDataType DataType} property is used to specify the data type + * of both comparison values. Both values are automatically converted to this data + * type before the comparison operation is performed. The following value types are supported: + * - <b>Integer</b> A 32-bit signed integer data type. + * - <b>Float</b> A double-precision floating point number data type. + * - <b>Date</b> A date data type. The format can be specified by the + * {@link setDateFormat DateFormat} property + * - <b>String</b> A string data type. + * + * Use the {@link setOperator Operator} property to specify the type of comparison + * to perform. Valid operators include Equal, NotEqual, GreaterThan, GreaterThanEqual, + * LessThan and LessThanEqual. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCompareValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TCompareValidator'; +	} + +	/** +	 * @return TValidationDataType the data type that the values being compared are converted to before the comparison is made. Defaults to TValidationDataType::String. +	 */ +	public function getDataType() +	{ +		return $this->getViewState('DataType',TValidationDataType::String); +	} + +	/** +	 * Sets the data type that the values being +	 * compared are converted to before the comparison is made. +	 * @param TValidationDataType the data type +	 */ +	public function setDataType($value) +	{ +		$this->setViewState('DataType',TPropertyValue::ensureEnum($value,'TValidationDataType'),TValidationDataType::String); +	} + +	/** +	 * @return string the input component to compare with the input control being validated. +	 */ +	public function getControlToCompare() +	{ +		return $this->getViewState('ControlToCompare',''); +	} + +	/** +	 * Sets the input component to compare with the input control being validated. +	 * @param string the ID path of the component to compare with +	 */ +	public function setControlToCompare($value) +	{ +		$this->setViewState('ControlToCompare',$value,''); +	} + +	/** +	 * @return string the constant value to compare with the value entered by the user into the input component being validated. +	 */ +	public function getValueToCompare() +	{ +		return $this->getViewState('ValueToCompare',''); +	} + +	/** +	 * Sets the constant value to compare with the value entered by the user into the input component being validated. +	 * @param string the constant value +	 */ +	public function setValueToCompare($value) +	{ +		$this->setViewState('ValueToCompare',$value,''); +	} + +	/** +	 * @return TValidationCompareOperator the comparison operation to perform. Defaults to TValidationCompareOperator::Equal. +	 */ +	public function getOperator() +	{ +		return $this->getViewState('Operator',TValidationCompareOperator::Equal); +	} + +	/** +	 * Sets the comparison operation to perform +	 * @param TValidationCompareOperator the comparison operation +	 */ +	public function setOperator($value) +	{ +		$this->setViewState('Operator',TPropertyValue::ensureEnum($value,'TValidationCompareOperator'),TValidationCompareOperator::Equal); +	} + +	/** +     * Sets the date format for a date validation +     * @param string the date format value +     */ +	public function setDateFormat($value) +	{ +		$this->setViewState('DateFormat', $value, ''); +	} + +	/** +	 * @return string the date validation date format if any +	 */ +	public function getDateFormat() +	{ +		return $this->getViewState('DateFormat', ''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input data compares successfully. +	 * The validation always succeeds if ControlToValidate is not specified +	 * or the input data is empty. +	 * @return boolean whether the validation succeeds +	 */ +	public function evaluateIsValid() +	{ +		if(($value=$this->getValidationValue($this->getValidationTarget()))==='') +			return true; + +		if(($controlToCompare=$this->getControlToCompare())!=='') +		{ +			if(($control2=$this->findControl($controlToCompare))===null) +				throw new TInvalidDataValueException('comparevalidator_controltocompare_invalid'); +			if(($value2=$this->getValidationValue($control2))==='') +				return false; +		} +		else +			$value2=$this->getValueToCompare(); + +		$values = $this->getComparisonValues($value, $value2); +		switch($this->getOperator()) +		{ +			case TValidationCompareOperator::Equal: +				return $values[0] == $values[1]; +			case TValidationCompareOperator::NotEqual: +				return $values[0] != $values[1]; +			case TValidationCompareOperator::GreaterThan: +				return $values[0] > $values[1]; +			case TValidationCompareOperator::GreaterThanEqual: +				return $values[0] >= $values[1]; +			case TValidationCompareOperator::LessThan: +				return $values[0] < $values[1]; +			case TValidationCompareOperator::LessThanEqual: +				return $values[0] <= $values[1]; +		} + +		return false; +	} + +	/** +	 * Parse the pair of values into the appropriate value type. +	 * @param string value one +	 * @param string second value +	 * @return array appropriate type of the value pair, array($value1, $value2); +	 */ +	protected function getComparisonValues($value1, $value2) +	{ +		switch($this->getDataType()) +		{ +			case TValidationDataType::Integer: +				return array(intval($value1), intval($value2)); +			case TValidationDataType::Float: +				return array(floatval($value1), floatval($value2)); +			case TValidationDataType::Date: +				$dateFormat = $this->getDateFormat(); +				if($dateFormat!=='') +				{ +					$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', $dateFormat); +					return array($formatter->parse($value1), $formatter->parse($value2)); +				} +				else +					return array(strtotime($value1), strtotime($value2)); +		} +		return array($value1, $value2); +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options = parent::getClientScriptOptions(); +		if(($name=$this->getControlToCompare())!=='') +		{ +			if(($control=$this->findControl($name))!==null) +				$options['ControlToCompare']=$control->getClientID(); +		} +		if(($value=$this->getValueToCompare())!=='') +			$options['ValueToCompare']=$value; +		if(($operator=$this->getOperator())!==TValidationCompareOperator::Equal) +			$options['Operator']=$operator; +		$options['DataType']=$this->getDataType(); +		if(($dateFormat=$this->getDateFormat())!=='') +			$options['DateFormat']=$dateFormat; +		return $options; +	} +} + + +/** + * TValidationCompareOperator class. + * TValidationCompareOperator defines the enumerable type for the comparison operations + * that {@link TCompareValidator} can perform validation with. + * + * The following enumerable values are defined: + * - Equal + * - NotEqual + * - GreaterThan + * - GreaterThanEqual + * - LessThan + * - LessThanEqual + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TValidationCompareOperator extends TEnumerable +{ +	const Equal='Equal'; +	const NotEqual='NotEqual'; +	const GreaterThan='GreaterThan'; +	const GreaterThanEqual='GreaterThanEqual'; +	const LessThan='LessThan'; +	const LessThanEqual='LessThanEqual'; +} + diff --git a/framework/Web/UI/WebControls/TConditional.php b/framework/Web/UI/WebControls/TConditional.php index d04324f0..28af2305 100644 --- a/framework/Web/UI/WebControls/TConditional.php +++ b/framework/Web/UI/WebControls/TConditional.php @@ -1,143 +1,143 @@ -<?php
 -/**
 - * TConditional class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TConditional class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TConditional class.
 - *
 - * TConditional displays appropriate content based on the evaluation result
 - * of a PHP expression specified via {@link setCondition Condition}.
 - * If the result is true, it instantiates the template {@link getTrueTemplate TrueTemplate};
 - * otherwise, the template {@link getFalseTemplate FalseTemplate} is instantiated.
 - * The PHP expression is evaluated right before {@link onInit} stage of the control lifecycle.
 - *
 - * Since {@link setCondition Condition} is evaluated at a very early stage, it is recommended
 - * you set {@link setCondition Condition} in template and the expression should not refer to
 - * objects that are available on or after {@link onInit} lifecycle.
 - *
 - * A typical usage of TConditional is shown as following:
 - * <code>
 - * <com:TConditional Condition="$this->User->IsGuest">
 - *   <prop:TrueTemplate>
 - *     <a href="path/to/login">Login</a>
 - *   </prop:TrueTemplate>
 - *   <prop:FalseTemplate>
 - *     <a href="path/to/logout">Logout</a>
 - *   </prop:FalseTemplate>
 - * </com:TConditional>
 - * </code>
 - *
 - * TConditional is very light. It instantiates either {@link getTrueTemplate TrueTemplate}
 - * or {@link getFalseTemplate FalseTemplate}, but never both. And the condition is evaluated only once.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TConditional extends TControl
 -{
 -	private $_condition='true';
 -	private $_trueTemplate;
 -	private $_falseTemplate;
 -	private $_creatingChildren=false;
 -
 -	/**
 -	 * Processes an object that is created during parsing template.
 -	 * This method overrides the parent implementation by removing
 -	 * all contents enclosed in the template tag.
 -	 * @param string|TComponent text string or component parsed and instantiated in template
 -	 * @see createdOnTemplate
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($this->_creatingChildren)
 -			parent::addParsedObject($object);
 -	}
 -
 -	/**
 -	 * Creates child controls.
 -	 * This method overrides the parent implementation. It evaluates {@link getCondition Condition}
 -	 * and instantiate the corresponding template.
 -	 */
 -	public function createChildControls()
 -	{
 -		$this->_creatingChildren=true;
 -		$result=true;
 -		try
 -		{
 -			$result=$this->getTemplateControl()->evaluateExpression($this->_condition);
 -		}
 -		catch(Exception $e)
 -		{
 -			throw new TInvalidDataValueException('conditional_condition_invalid',$this->_condition,$e->getMessage());
 -		}
 -		if($result)
 -		{
 -			if($this->_trueTemplate)
 -				$this->_trueTemplate->instantiateIn($this->getTemplateControl(),$this);
 -		}
 -		else if($this->_falseTemplate)
 -			$this->_falseTemplate->instantiateIn($this->getTemplateControl(),$this);
 -		$this->_creatingChildren=false;
 -	}
 -
 -	/**
 -	 * @return string the PHP expression used for determining which template to use. Defaults to 'true', meaning using TrueTemplate.
 -	 */
 -	public function getCondition()
 -	{
 -		return $this->_condition;
 -	}
 -
 -	/**
 -	 * Sets the PHP expression to be evaluated for conditionally displaying content.
 -	 * The context of the expression is the template control containing TConditional.
 -	 * @param string the PHP expression used for determining which template to use.
 -	 */
 -	public function setCondition($value)
 -	{
 -		$this->_condition=TPropertyValue::ensureString($value);
 -	}
 -
 -	/**
 -	 * @return ITemplate the template applied when {@link getCondition Condition} is true.
 -	 */
 -	public function getTrueTemplate()
 -	{
 -		return $this->_trueTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template applied when {@link getCondition Condition} is true.
 -	 */
 -	public function setTrueTemplate(ITemplate $value)
 -	{
 -		$this->_trueTemplate=$value;
 -	}
 -
 -	/**
 -	 * @return ITemplate the template applied when {@link getCondition Condition} is false.
 -	 */
 -	public function getFalseTemplate()
 -	{
 -		return $this->_falseTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template applied when {@link getCondition Condition} is false.
 -	 */
 -	public function setFalseTemplate(ITemplate $value)
 -	{
 -		$this->_falseTemplate=$value;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TConditional class. + * + * TConditional displays appropriate content based on the evaluation result + * of a PHP expression specified via {@link setCondition Condition}. + * If the result is true, it instantiates the template {@link getTrueTemplate TrueTemplate}; + * otherwise, the template {@link getFalseTemplate FalseTemplate} is instantiated. + * The PHP expression is evaluated right before {@link onInit} stage of the control lifecycle. + * + * Since {@link setCondition Condition} is evaluated at a very early stage, it is recommended + * you set {@link setCondition Condition} in template and the expression should not refer to + * objects that are available on or after {@link onInit} lifecycle. + * + * A typical usage of TConditional is shown as following: + * <code> + * <com:TConditional Condition="$this->User->IsGuest"> + *   <prop:TrueTemplate> + *     <a href="path/to/login">Login</a> + *   </prop:TrueTemplate> + *   <prop:FalseTemplate> + *     <a href="path/to/logout">Logout</a> + *   </prop:FalseTemplate> + * </com:TConditional> + * </code> + * + * TConditional is very light. It instantiates either {@link getTrueTemplate TrueTemplate} + * or {@link getFalseTemplate FalseTemplate}, but never both. And the condition is evaluated only once. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TConditional extends TControl +{ +	private $_condition='true'; +	private $_trueTemplate; +	private $_falseTemplate; +	private $_creatingChildren=false; + +	/** +	 * Processes an object that is created during parsing template. +	 * This method overrides the parent implementation by removing +	 * all contents enclosed in the template tag. +	 * @param string|TComponent text string or component parsed and instantiated in template +	 * @see createdOnTemplate +	 */ +	public function addParsedObject($object) +	{ +		if($this->_creatingChildren) +			parent::addParsedObject($object); +	} + +	/** +	 * Creates child controls. +	 * This method overrides the parent implementation. It evaluates {@link getCondition Condition} +	 * and instantiate the corresponding template. +	 */ +	public function createChildControls() +	{ +		$this->_creatingChildren=true; +		$result=true; +		try +		{ +			$result=$this->getTemplateControl()->evaluateExpression($this->_condition); +		} +		catch(Exception $e) +		{ +			throw new TInvalidDataValueException('conditional_condition_invalid',$this->_condition,$e->getMessage()); +		} +		if($result) +		{ +			if($this->_trueTemplate) +				$this->_trueTemplate->instantiateIn($this->getTemplateControl(),$this); +		} +		else if($this->_falseTemplate) +			$this->_falseTemplate->instantiateIn($this->getTemplateControl(),$this); +		$this->_creatingChildren=false; +	} + +	/** +	 * @return string the PHP expression used for determining which template to use. Defaults to 'true', meaning using TrueTemplate. +	 */ +	public function getCondition() +	{ +		return $this->_condition; +	} + +	/** +	 * Sets the PHP expression to be evaluated for conditionally displaying content. +	 * The context of the expression is the template control containing TConditional. +	 * @param string the PHP expression used for determining which template to use. +	 */ +	public function setCondition($value) +	{ +		$this->_condition=TPropertyValue::ensureString($value); +	} + +	/** +	 * @return ITemplate the template applied when {@link getCondition Condition} is true. +	 */ +	public function getTrueTemplate() +	{ +		return $this->_trueTemplate; +	} + +	/** +	 * @param ITemplate the template applied when {@link getCondition Condition} is true. +	 */ +	public function setTrueTemplate(ITemplate $value) +	{ +		$this->_trueTemplate=$value; +	} + +	/** +	 * @return ITemplate the template applied when {@link getCondition Condition} is false. +	 */ +	public function getFalseTemplate() +	{ +		return $this->_falseTemplate; +	} + +	/** +	 * @param ITemplate the template applied when {@link getCondition Condition} is false. +	 */ +	public function setFalseTemplate(ITemplate $value) +	{ +		$this->_falseTemplate=$value; +	} +} + diff --git a/framework/Web/UI/WebControls/TContent.php b/framework/Web/UI/WebControls/TContent.php index 3b17c2cc..60a8e0b6 100644 --- a/framework/Web/UI/WebControls/TContent.php +++ b/framework/Web/UI/WebControls/TContent.php @@ -1,47 +1,47 @@ -<?php
 -/**
 - * TContent class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TContent class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TContent class
 - *
 - * TContent specifies a block of content on a control's template
 - * that will be injected at somewhere of the master control's template.
 - * TContentPlaceHolder and {@link TContent} together implement a decoration
 - * pattern for prado templated controls. A template control
 - * (called content control) can specify a master control
 - * whose template contains some TContentPlaceHolder controls.
 - * {@link TContent} controls on the content control's template will replace the corresponding
 - * {@link TContentPlaceHolder} controls on the master control's template.
 - * This is called content injection. It is done by matching the IDs of
 - * {@link TContent} and {@link TContentPlaceHolder} controls.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TContent extends TControl implements INamingContainer
 -{
 -	/**
 -	 * This method is invoked after the control is instantiated on a template.
 -	 * This overrides the parent implementation by registering the content control
 -	 * to the template owner control.
 -	 * @param TControl potential parent of this control
 -	 */
 -	public function createdOnTemplate($parent)
 -	{
 -		if(($id=$this->getID())==='')
 -			throw new TConfigurationException('content_id_required');
 -		$this->getTemplateControl()->registerContent($id,$this);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TContent class + * + * TContent specifies a block of content on a control's template + * that will be injected at somewhere of the master control's template. + * TContentPlaceHolder and {@link TContent} together implement a decoration + * pattern for prado templated controls. A template control + * (called content control) can specify a master control + * whose template contains some TContentPlaceHolder controls. + * {@link TContent} controls on the content control's template will replace the corresponding + * {@link TContentPlaceHolder} controls on the master control's template. + * This is called content injection. It is done by matching the IDs of + * {@link TContent} and {@link TContentPlaceHolder} controls. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TContent extends TControl implements INamingContainer +{ +	/** +	 * This method is invoked after the control is instantiated on a template. +	 * This overrides the parent implementation by registering the content control +	 * to the template owner control. +	 * @param TControl potential parent of this control +	 */ +	public function createdOnTemplate($parent) +	{ +		if(($id=$this->getID())==='') +			throw new TConfigurationException('content_id_required'); +		$this->getTemplateControl()->registerContent($id,$this); +	} +} + diff --git a/framework/Web/UI/WebControls/TContentPlaceHolder.php b/framework/Web/UI/WebControls/TContentPlaceHolder.php index ddd2b610..55ed461d 100644 --- a/framework/Web/UI/WebControls/TContentPlaceHolder.php +++ b/framework/Web/UI/WebControls/TContentPlaceHolder.php @@ -1,48 +1,48 @@ -<?php
 -/**
 - * TContentPlaceHolder class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TContentPlaceHolder class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TContentPlaceHolder class
 - *
 - * TContentPlaceHolder reserves a place on a template where a {@link TContent}
 - * control can inject itself and its children in. TContentPlaceHolder and {@link TContent}
 - * together implement a decoration pattern for prado templated controls.
 - * A template control (called content control) can specify a master control
 - * whose template contains some TContentPlaceHolder controls.
 - * {@link TContent} controls on the content control's template will replace the corresponding
 - * {@link TContentPlaceHolder} controls on the master control's template.
 - * This is called content injection. It is done by matching the IDs of
 - * {@link TContent} and {@link TContentPlaceHolder} controls.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TContentPlaceHolder extends TControl
 -{
 -	/**
 -	 * This method is invoked after the control is instantiated on a template.
 -	 * This overrides the parent implementation by registering the content placeholder
 -	 * control to the template owner control. The placeholder control will NOT
 -	 * be added to the potential parent control!
 -	 * @param TControl potential parent of this control
 -	 */
 -	public function createdOnTemplate($parent)
 -	{
 -		if(($id=$this->getID())==='')
 -			throw new TConfigurationException('contentplaceholder_id_required');
 -		$this->getTemplateControl()->registerContentPlaceHolder($id,$this);
 -		$parent->getControls()->add($this);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TContentPlaceHolder class + * + * TContentPlaceHolder reserves a place on a template where a {@link TContent} + * control can inject itself and its children in. TContentPlaceHolder and {@link TContent} + * together implement a decoration pattern for prado templated controls. + * A template control (called content control) can specify a master control + * whose template contains some TContentPlaceHolder controls. + * {@link TContent} controls on the content control's template will replace the corresponding + * {@link TContentPlaceHolder} controls on the master control's template. + * This is called content injection. It is done by matching the IDs of + * {@link TContent} and {@link TContentPlaceHolder} controls. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TContentPlaceHolder extends TControl +{ +	/** +	 * This method is invoked after the control is instantiated on a template. +	 * This overrides the parent implementation by registering the content placeholder +	 * control to the template owner control. The placeholder control will NOT +	 * be added to the potential parent control! +	 * @param TControl potential parent of this control +	 */ +	public function createdOnTemplate($parent) +	{ +		if(($id=$this->getID())==='') +			throw new TConfigurationException('contentplaceholder_id_required'); +		$this->getTemplateControl()->registerContentPlaceHolder($id,$this); +		$parent->getControls()->add($this); +	} +} + diff --git a/framework/Web/UI/WebControls/TCustomValidator.php b/framework/Web/UI/WebControls/TCustomValidator.php index 9ab75258..dcfadacd 100644 --- a/framework/Web/UI/WebControls/TCustomValidator.php +++ b/framework/Web/UI/WebControls/TCustomValidator.php @@ -1,207 +1,207 @@ -<?php
 -/**
 - * TCustomValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TCustomValidator class
 - *
 - * TCustomValidator performs user-defined validation (either
 - * server-side or client-side or both) on an input component.
 - *
 - * To create a server-side validation function, provide a handler for
 - * the {@link onServerValidate OnServerValidate} event that performs the validation.
 - * The data string of the input control to validate can be accessed
 - * by {@link TServerValidateEventParameter::getValue Value} of the event parameter.
 - * The result of the validation should be stored in the
 - * {@link TServerValidateEventParameter::getIsValid IsValid} property of the event
 - * parameter.
 - *
 - * To create a client-side validation function, add the client-side
 - * validation javascript function to the page template.
 - * The function should have the following signature:
 - * <code>
 - * <script type="text/javascript"><!--
 - * function ValidationFunctionName(sender, parameter)
 - * {
 - *    // if(parameter == ...)
 - *    //    return true;
 - *    // else
 - *    //    return false;
 - * }
 - * --></script>
 - * </code>
 - * Use the {@link setClientValidationFunction ClientValidationFunction} property
 - * to specify the name of the client-side validation script function associated
 - * with the TCustomValidator.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCustomValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TCustomValidator';
 -	}
 -
 -	/**
 -	 * @return string the name of the custom client-side script function used for validation.
 -	 */
 -	public function getClientValidationFunction()
 -	{
 -		return $this->getViewState('ClientValidationFunction','');
 -	}
 -
 -	/**
 -	 * Sets the name of the custom client-side script function used for validation.
 -	 * @param string the script function name
 -	 */
 -	public function setClientValidationFunction($value)
 -	{
 -		$this->setViewState('ClientValidationFunction',$value,'');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if {@link onServerValidate} returns true.
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	public function evaluateIsValid()
 -	{
 -		$value = '';
 -		if($this->getValidationTarget()!==null)
 -			$value=$this->getValidationValue($this->getValidationTarget());
 -		return $this->onServerValidate($value);
 -	}
 -
 -	/**
 -	 * This method is invoked when the server side validation happens.
 -	 * It will raise the <b>OnServerValidate</b> event.
 -	 * The method also allows derived classes to handle the event without attaching a delegate.
 -	 * <b>Note</b> The derived classes should call parent implementation
 -	 * to ensure the <b>OnServerValidate</b> event is raised.
 -	 * @param string the value to be validated
 -	 * @return boolean whether the value is valid
 -	 */
 -	public function onServerValidate($value)
 -	{
 -		$param=new TServerValidateEventParameter($value,true);
 -		$this->raiseEvent('OnServerValidate',$this,$param);
 -		return $param->getIsValid();
 -	}
 -
 -	/**
 -	 * @return TControl control to be validated. Null if no control is found.
 -	 */
 -	public function getValidationTarget()
 -	{
 -		if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null)
 -			return $control;
 -		else if(($id=$this->getControlToValidate())!=='')
 -			throw new TInvalidDataTypeException('basevalidator_validatable_required',get_class($this));
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options=parent::getClientScriptOptions();
 -		if(($clientJs=$this->getClientValidationFunction())!=='')
 -			$options['ClientValidationFunction']=$clientJs;
 -		return $options;
 -	}
 -
 -	/**
 -	 * Only register the client-side validator if
 -	 * {@link setClientValidationFunction ClientValidationFunction} is set.
 -	 */
 -	protected function registerClientScriptValidator()
 -	{
 -		if($this->getClientValidationFunction()!=='')
 -			parent::registerClientScriptValidator();
 -	}
 -}
 -
 -/**
 - * TServerValidateEventParameter class
 - *
 - * TServerValidateEventParameter encapsulates the parameter data for
 - * <b>OnServerValidate</b> event of TCustomValidator components.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TServerValidateEventParameter extends TEventParameter
 -{
 -	/**
 -	 * the value to be validated
 -	 * @var string
 -	 */
 -	private $_value='';
 -	/**
 -	 * whether the value is valid
 -	 * @var boolean
 -	 */
 -	private $_isValid=true;
 -
 -	/**
 -	 * Constructor.
 -	 * @param string property value to be validated
 -	 * @param boolean whether the value is valid
 -	 */
 -	public function __construct($value,$isValid)
 -	{
 -		$this->_value=$value;
 -		$this->setIsValid($isValid);
 -	}
 -
 -	/**
 -	 * @return string value to be validated
 -	 */
 -	public function getValue()
 -	{
 -		return $this->_value;
 -	}
 -
 -	/**
 -	 * @return boolean whether the value is valid
 -	 */
 -	public function getIsValid()
 -	{
 -		return $this->_isValid;
 -	}
 -
 -	/**
 -	 * @param boolean whether the value is valid
 -	 */
 -	public function setIsValid($value)
 -	{
 -		$this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -}
 +<?php +/** + * TCustomValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TCustomValidator class + * + * TCustomValidator performs user-defined validation (either + * server-side or client-side or both) on an input component. + * + * To create a server-side validation function, provide a handler for + * the {@link onServerValidate OnServerValidate} event that performs the validation. + * The data string of the input control to validate can be accessed + * by {@link TServerValidateEventParameter::getValue Value} of the event parameter. + * The result of the validation should be stored in the + * {@link TServerValidateEventParameter::getIsValid IsValid} property of the event + * parameter. + * + * To create a client-side validation function, add the client-side + * validation javascript function to the page template. + * The function should have the following signature: + * <code> + * <script type="text/javascript"><!-- + * function ValidationFunctionName(sender, parameter) + * { + *    // if(parameter == ...) + *    //    return true; + *    // else + *    //    return false; + * } + * --></script> + * </code> + * Use the {@link setClientValidationFunction ClientValidationFunction} property + * to specify the name of the client-side validation script function associated + * with the TCustomValidator. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCustomValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TCustomValidator'; +	} + +	/** +	 * @return string the name of the custom client-side script function used for validation. +	 */ +	public function getClientValidationFunction() +	{ +		return $this->getViewState('ClientValidationFunction',''); +	} + +	/** +	 * Sets the name of the custom client-side script function used for validation. +	 * @param string the script function name +	 */ +	public function setClientValidationFunction($value) +	{ +		$this->setViewState('ClientValidationFunction',$value,''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if {@link onServerValidate} returns true. +	 * @return boolean whether the validation succeeds +	 */ +	public function evaluateIsValid() +	{ +		$value = ''; +		if($this->getValidationTarget()!==null) +			$value=$this->getValidationValue($this->getValidationTarget()); +		return $this->onServerValidate($value); +	} + +	/** +	 * This method is invoked when the server side validation happens. +	 * It will raise the <b>OnServerValidate</b> event. +	 * The method also allows derived classes to handle the event without attaching a delegate. +	 * <b>Note</b> The derived classes should call parent implementation +	 * to ensure the <b>OnServerValidate</b> event is raised. +	 * @param string the value to be validated +	 * @return boolean whether the value is valid +	 */ +	public function onServerValidate($value) +	{ +		$param=new TServerValidateEventParameter($value,true); +		$this->raiseEvent('OnServerValidate',$this,$param); +		return $param->getIsValid(); +	} + +	/** +	 * @return TControl control to be validated. Null if no control is found. +	 */ +	public function getValidationTarget() +	{ +		if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null) +			return $control; +		else if(($id=$this->getControlToValidate())!=='') +			throw new TInvalidDataTypeException('basevalidator_validatable_required',get_class($this)); +		else +			return null; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options=parent::getClientScriptOptions(); +		if(($clientJs=$this->getClientValidationFunction())!=='') +			$options['ClientValidationFunction']=$clientJs; +		return $options; +	} + +	/** +	 * Only register the client-side validator if +	 * {@link setClientValidationFunction ClientValidationFunction} is set. +	 */ +	protected function registerClientScriptValidator() +	{ +		if($this->getClientValidationFunction()!=='') +			parent::registerClientScriptValidator(); +	} +} + +/** + * TServerValidateEventParameter class + * + * TServerValidateEventParameter encapsulates the parameter data for + * <b>OnServerValidate</b> event of TCustomValidator components. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TServerValidateEventParameter extends TEventParameter +{ +	/** +	 * the value to be validated +	 * @var string +	 */ +	private $_value=''; +	/** +	 * whether the value is valid +	 * @var boolean +	 */ +	private $_isValid=true; + +	/** +	 * Constructor. +	 * @param string property value to be validated +	 * @param boolean whether the value is valid +	 */ +	public function __construct($value,$isValid) +	{ +		$this->_value=$value; +		$this->setIsValid($isValid); +	} + +	/** +	 * @return string value to be validated +	 */ +	public function getValue() +	{ +		return $this->_value; +	} + +	/** +	 * @return boolean whether the value is valid +	 */ +	public function getIsValid() +	{ +		return $this->_isValid; +	} + +	/** +	 * @param boolean whether the value is valid +	 */ +	public function setIsValid($value) +	{ +		$this->_isValid=TPropertyValue::ensureBoolean($value); +	} +} diff --git a/framework/Web/UI/WebControls/TDataBoundControl.php b/framework/Web/UI/WebControls/TDataBoundControl.php index 294dd416..076179fb 100644 --- a/framework/Web/UI/WebControls/TDataBoundControl.php +++ b/framework/Web/UI/WebControls/TDataBoundControl.php @@ -1,587 +1,587 @@ -<?php
 -/**
 - * TDataBoundControl class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TDataSourceControl');
 -Prado::using('System.Web.UI.WebControls.TDataSourceView');
 -Prado::using('System.Collections.TPagedDataSource');
 -
 -/**
 - * TDataBoundControl class.
 - *
 - * TDataBoundControl is the based class for controls that need to populate
 - * data from data sources. It provides basic properties and methods that allow
 - * the derived controls to associate with data sources and retrieve data from them.
 - *
 - * TBC....
 - *
 - * TDataBoundControl is equipped with paging capabilities. By setting
 - * {@link setAllowPaging AllowPaging} to true, the input data will be paged
 - * and only one page of data is actually populated into the data-bound control.
 - * This saves a lot of memory when dealing with larget datasets.
 - *
 - * 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.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class TDataBoundControl extends TWebControl
 -{
 -	private $_initialized=false;
 -	private $_dataSource=null;
 -	private $_requiresBindToNull=false;
 -	private $_requiresDataBinding=false;
 -	private $_prerendered=false;
 -	private $_currentView=null;
 -	private $_currentDataSource=null;
 -	private $_currentViewValid=false;
 -	private $_currentDataSourceValid=false;
 -	private $_currentViewIsFromDataSourceID=false;
 -	private $_parameters=null;
 -	private $_isDataBound=false;
 -
 -	/**
 -	 * @return Traversable data source object, defaults to null.
 -	 */
 -	public function getDataSource()
 -	{
 -		return $this->_dataSource;
 -	}
 -
 -	/**
 -	 * Sets the data source object associated with the databound control.
 -	 * The data source must implement Traversable interface.
 -	 * If an array is given, it will be converted to xxx.
 -	 * If a string is given, it will be converted to xxx.
 -	 * @param Traversable|array|string data source object
 -	 */
 -	public function setDataSource($value)
 -	{
 -		$this->_dataSource=$this->validateDataSource($value);
 -		$this->onDataSourceChanged();
 -	}
 -
 -	/**
 -	 * @return string ID path to the data source control. Defaults to empty.
 -	 */
 -	public function getDataSourceID()
 -	{
 -		return $this->getViewState('DataSourceID','');
 -	}
 -
 -	/**
 -	 * @param string ID path to the data source control. The data source
 -	 * control must be locatable via {@link TControl::findControl} call.
 -	 */
 -	public function setDataSourceID($value)
 -	{
 -		$dsid=$this->getViewState('DataSourceID','');
 -		if($dsid!=='' && $value==='')
 -			$this->_requiresBindToNull=true;
 -		$this->setViewState('DataSourceID',$value,'');
 -		$this->onDataSourceChanged();
 -	}
 -
 -	/**
 -	 * @return boolean if the databound control uses the data source specified
 -	 * by {@link setDataSourceID}, or it uses the data source object specified
 -	 * by {@link setDataSource}.
 -	 */
 -	protected function getUsingDataSourceID()
 -	{
 -		return $this->getDataSourceID()!=='';
 -	}
 -
 -	/**
 -	 * Sets {@link setRequiresDataBinding RequiresDataBinding} as true if the control is initialized.
 -	 * This method is invoked when either {@link setDataSource} or {@link setDataSourceID} is changed.
 -	 */
 -	public function onDataSourceChanged()
 -	{
 -		$this->_currentViewValid=false;
 -		$this->_currentDataSourceValid=false;
 -		if($this->getInitialized())
 -			$this->setRequiresDataBinding(true);
 -	}
 -
 -	/**
 -	 * @return boolean whether the databound control has been initialized.
 -	 * By default, the control is initialized after its viewstate has been restored.
 -	 */
 -	protected function getInitialized()
 -	{
 -		return $this->_initialized;
 -	}
 -
 -	/**
 -	 * Sets a value indicating whether the databound control is initialized.
 -	 * If initialized, any modification to {@link setDataSource DataSource} or
 -	 * {@link setDataSourceID DataSourceID} will set {@link setRequiresDataBinding RequiresDataBinding}
 -	 * as true.
 -	 * @param boolean a value indicating whether the databound control is initialized.
 -	 */
 -	protected function setInitialized($value)
 -	{
 -		$this->_initialized=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * @return boolean whether databind has been invoked in the previous page request
 -	 */
 -	protected function getIsDataBound()
 -	{
 -		return $this->_isDataBound;
 -	}
 -
 -	/**
 -	 * @param boolean if databind has been invoked in this page request
 -	 */
 -	protected function setIsDataBound($value)
 -	{
 -		$this->_isDataBound=$value;
 -	}
 -
 -	/**
 -	 * @return boolean whether a databind call is required (by the data bound control)
 -	 */
 -	protected function getRequiresDataBinding()
 -	{
 -		return $this->_requiresDataBinding;
 -	}
 -
 -	/**
 -	 * @return boolean whether paging is enabled. Defaults to false.
 -	 */
 -	public function getAllowPaging()
 -	{
 -		return $this->getViewState('AllowPaging',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether paging is enabled
 -	 */
 -	public function setAllowPaging($value)
 -	{
 -		$this->setViewState('AllowPaging',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @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 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)
 -			$value=0;
 -		$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('databoundcontrol_pagesize_invalid',get_class($this));
 -		$this->setViewState('PageSize',TPropertyValue::ensureInteger($value),10);
 -	}
 -
 -	/**
 -	 * @return integer number of pages of data items available
 -	 */
 -	public function getPageCount()
 -	{
 -		return $this->getViewState('PageCount',1);
 -	}
 -
 -	/**
 -	 * @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('databoundcontrol_virtualitemcount_invalid',get_class($this));
 -		$this->setViewState('VirtualItemCount',$value,0);
 -	}
 -
 -	/**
 -	 * Sets a value indicating whether a databind call is required by the data bound control.
 -	 * If true and the control has been prerendered while it uses the data source
 -	 * specified by {@link setDataSourceID}, a databind call will be called by this method.
 -	 * @param boolean whether a databind call is required.
 -	 */
 -	protected function setRequiresDataBinding($value)
 -	{
 -		$value=TPropertyValue::ensureBoolean($value);
 -		if($value && $this->_prerendered)
 -		{
 -			$this->_requiresDataBinding=true;
 -			$this->ensureDataBound();
 -		}
 -		else
 -			$this->_requiresDataBinding=$value;
 -	}
 -
 -	/**
 -	 * Ensures any pending {@link dataBind} is called.
 -	 * This method calls {@link dataBind} if the data source is specified
 -	 * by {@link setDataSourceID} or if {@link getRequiresDataBinding RequiresDataBinding}
 -	 * is true.
 -	 */
 -	protected function ensureDataBound()
 -	{
 -		if($this->_requiresDataBinding && ($this->getUsingDataSourceID() || $this->_requiresBindToNull))
 -		{
 -			$this->dataBind();
 -			$this->_requiresBindToNull=false;
 -		}
 -	}
 -
 -	/**
 -	 * @return TPagedDataSource creates a paged data source
 -	 */
 -	protected function createPagedDataSource()
 -	{
 -		$ds=new TPagedDataSource;
 -		$ds->setCurrentPageIndex($this->getCurrentPageIndex());
 -		$ds->setPageSize($this->getPageSize());
 -		$ds->setAllowPaging($this->getAllowPaging());
 -		$ds->setAllowCustomPaging($this->getAllowCustomPaging());
 -		$ds->setVirtualItemCount($this->getVirtualItemCount());
 -		return $ds;
 -	}
 -
 -	/**
 -	 * Performs databinding.
 -	 * This method overrides the parent implementation by calling
 -	 * {@link performSelect} which fetches data from data source and does
 -	 * the actual binding work.
 -	 */
 -	public function dataBind()
 -	{
 -		$this->setRequiresDataBinding(false);
 -		$this->dataBindProperties();
 -		$this->onDataBinding(null);
 -
 -		if(($view=$this->getDataSourceView())!==null)
 -			$data=$view->select($this->getSelectParameters());
 -		else
 -			$data=null;
 -
 -		if($data instanceof Traversable)
 -		{
 -			if($this->getAllowPaging())
 -			{
 -				$ds=$this->createPagedDataSource();
 -				$ds->setDataSource($data);
 -				$this->setViewState('PageCount',$ds->getPageCount());
 -				if($ds->getCurrentPageIndex()>=$ds->getPageCount())
 -				{
 -					$ds->setCurrentPageIndex($ds->getPageCount()-1);
 -					$this->setCurrentPageIndex($ds->getCurrentPageIndex());
 -				}
 -				$this->performDataBinding($ds);
 -			}
 -			else
 -			{
 -				$this->clearViewState('PageCount');
 -				$this->performDataBinding($data);
 -			}
 -		}
 -		$this->setIsDataBound(true);
 -		$this->onDataBound(null);
 -	}
 -
 -	public function dataSourceViewChanged($sender,$param)
 -	{
 -		if(!$this->_ignoreDataSourceViewChanged)
 -			$this->setRequiresDataBinding(true);
 -	}
 -
 -	protected function getDataSourceView()
 -	{
 -		if(!$this->_currentViewValid)
 -		{
 -			if($this->_currentView && $this->_currentViewIsFromDataSourceID)
 -				$this->_currentView->detachEventHandler('DataSourceViewChanged',array($this,'dataSourceViewChanged'));
 -			if(($dataSource=$this->determineDataSource())!==null)
 -			{
 -				if(($view=$dataSource->getView($this->getDataMember()))===null)
 -					throw new TInvalidDataValueException('databoundcontrol_datamember_invalid',$this->getDataMember());
 -				if($this->_currentViewIsFromDataSourceID=$this->getUsingDataSourceID())
 -					$view->attachEventHandler('OnDataSourceViewChanged',array($this,'dataSourceViewChanged'));
 -				$this->_currentView=$view;
 -			}
 -			else
 -				$this->_currentView=null;
 -			$this->_currentViewValid=true;
 -		}
 -		return $this->_currentView;
 -	}
 -
 -	protected function determineDataSource()
 -	{
 -		if(!$this->_currentDataSourceValid)
 -		{
 -			if(($dsid=$this->getDataSourceID())!=='')
 -			{
 -				if(($dataSource=$this->getNamingContainer()->findControl($dsid))===null)
 -					throw new TInvalidDataValueException('databoundcontrol_datasourceid_inexistent',$dsid);
 -				else if(!($dataSource instanceof IDataSource))
 -					throw new TInvalidDataValueException('databoundcontrol_datasourceid_invalid',$dsid);
 -				else
 -					$this->_currentDataSource=$dataSource;
 -			}
 -			else if(($dataSource=$this->getDataSource())!==null)
 -				$this->_currentDataSource=new TReadOnlyDataSource($dataSource,$this->getDataMember());
 -			else
 -				$this->_currentDataSource=null;
 -			$this->_currentDataSourceValid=true;
 -		}
 -		return $this->_currentDataSource;
 -	}
 -
 -	abstract protected function performDataBinding($data);
 -
 -	/**
 -	 * Raises <b>OnDataBound</b> event.
 -	 * This method should be invoked after a databind is performed.
 -	 * It is mainly used by framework and component developers.
 -	 */
 -	public function onDataBound($param)
 -	{
 -		$this->raiseEvent('OnDataBound',$this,$param);
 -	}
 -
 -	/**
 -	 * Sets page's <b>OnPreLoad</b> event handler as {@link pagePreLoad}.
 -	 * If viewstate is disabled and the current request is a postback,
 -	 * {@link setRequiresDataBinding RequiresDataBinding} will be set true.
 -	 * This method overrides the parent implementation.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onInit($param)
 -	{
 -		parent::onInit($param);
 -		$page=$this->getPage();
 -		$page->attachEventHandler('OnPreLoad',array($this,'pagePreLoad'));
 -	}
 -
 -	/**
 -	 * Sets {@link getInitialized} as true.
 -	 * This method is invoked when page raises <b>PreLoad</b> event.
 -	 * @param mixed event sender
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function pagePreLoad($sender,$param)
 -	{
 -		$this->_initialized=true;
 -		$isPostBack=$this->getPage()->getIsPostBack();
 -		if(!$isPostBack || ($isPostBack && (!$this->getEnableViewState(true) || !$this->getIsDataBound())))
 -			$this->setRequiresDataBinding(true);
 -	}
 -
 -	/**
 -	 * Ensures any pending databind is performed.
 -	 * This method overrides the parent implementation.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		$this->_prerendered=true;
 -		$this->ensureDataBound();
 -		parent::onPreRender($param);
 -	}
 -
 -	/**
 -	 * Validates if the parameter is a valid data source.
 -	 * If it is a string or an array, it will be converted as a TList object.
 -	 * @param Traversable|array|string data source to be validated
 -	 * @return Traversable the data that is traversable
 -	 * @throws TInvalidDataTypeException if the data is neither null nor Traversable
 -	 */
 -	protected function validateDataSource($value)
 -	{
 -		if(is_string($value))
 -		{
 -			$list=new TList;
 -			foreach(TPropertyValue::ensureArray($value) as $key=>$value)
 -			{
 -				if(is_array($value))
 -					$list->add($value);
 -				else
 -					$list->add(array($value,is_string($key)?$key:$value));
 -			}
 -			return $list;
 -		}
 -		else if(is_array($value))
 -			return new TMap($value);
 -		else if($value instanceof TDbDataReader) {
 -			// read array from TDbDataReader since it's forward-only stream and can only be traversed once
 -			return $value->readAll();
 -		}
 -		else if(($value instanceof Traversable) || $value===null)
 -			return $value;
 -		else
 -			throw new TInvalidDataTypeException('databoundcontrol_datasource_invalid',get_class($this));
 -	}
 -
 -	public function getDataMember()
 -	{
 -		return $this->getViewState('DataMember','');
 -	}
 -
 -	public function setDataMember($value)
 -	{
 -		$this->setViewState('DataMember',$value,'');
 -	}
 -
 -	public function getSelectParameters()
 -	{
 -		if(!$this->_parameters)
 -			$this->_parameters=new TDataSourceSelectParameters;
 -		return $this->_parameters;
 -	}
 -}
 -
 -
 -/**
 - * TListItemType class.
 - * TListItemType defines the enumerable type for the possible types
 - * that databound list items could take.
 - *
 - * The following enumerable values are defined:
 - * - Header: header item
 - * - Footer: footer item
 - * - Item: content item (neither header nor footer)
 - * - Separator: separator between items
 - * - AlternatingItem: alternating content item
 - * - EditItem: content item in edit mode
 - * - SelectedItem: selected content item
 - * - Pager: pager
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TListItemType extends TEnumerable
 -{
 -	const Header='Header';
 -	const Footer='Footer';
 -	const Item='Item';
 -	const Separator='Separator';
 -	const AlternatingItem='AlternatingItem';
 -	const EditItem='EditItem';
 -	const SelectedItem='SelectedItem';
 -	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 <qiang.xue@gmail.com>
 - * @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);
 -}
 -
 -?>
 +<?php +/** + * TDataBoundControl class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataSourceControl'); +Prado::using('System.Web.UI.WebControls.TDataSourceView'); +Prado::using('System.Collections.TPagedDataSource'); + +/** + * TDataBoundControl class. + * + * TDataBoundControl is the based class for controls that need to populate + * data from data sources. It provides basic properties and methods that allow + * the derived controls to associate with data sources and retrieve data from them. + * + * TBC.... + * + * TDataBoundControl is equipped with paging capabilities. By setting + * {@link setAllowPaging AllowPaging} to true, the input data will be paged + * and only one page of data is actually populated into the data-bound control. + * This saves a lot of memory when dealing with larget datasets. + * + * 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. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TDataBoundControl extends TWebControl +{ +	private $_initialized=false; +	private $_dataSource=null; +	private $_requiresBindToNull=false; +	private $_requiresDataBinding=false; +	private $_prerendered=false; +	private $_currentView=null; +	private $_currentDataSource=null; +	private $_currentViewValid=false; +	private $_currentDataSourceValid=false; +	private $_currentViewIsFromDataSourceID=false; +	private $_parameters=null; +	private $_isDataBound=false; + +	/** +	 * @return Traversable data source object, defaults to null. +	 */ +	public function getDataSource() +	{ +		return $this->_dataSource; +	} + +	/** +	 * Sets the data source object associated with the databound control. +	 * The data source must implement Traversable interface. +	 * If an array is given, it will be converted to xxx. +	 * If a string is given, it will be converted to xxx. +	 * @param Traversable|array|string data source object +	 */ +	public function setDataSource($value) +	{ +		$this->_dataSource=$this->validateDataSource($value); +		$this->onDataSourceChanged(); +	} + +	/** +	 * @return string ID path to the data source control. Defaults to empty. +	 */ +	public function getDataSourceID() +	{ +		return $this->getViewState('DataSourceID',''); +	} + +	/** +	 * @param string ID path to the data source control. The data source +	 * control must be locatable via {@link TControl::findControl} call. +	 */ +	public function setDataSourceID($value) +	{ +		$dsid=$this->getViewState('DataSourceID',''); +		if($dsid!=='' && $value==='') +			$this->_requiresBindToNull=true; +		$this->setViewState('DataSourceID',$value,''); +		$this->onDataSourceChanged(); +	} + +	/** +	 * @return boolean if the databound control uses the data source specified +	 * by {@link setDataSourceID}, or it uses the data source object specified +	 * by {@link setDataSource}. +	 */ +	protected function getUsingDataSourceID() +	{ +		return $this->getDataSourceID()!==''; +	} + +	/** +	 * Sets {@link setRequiresDataBinding RequiresDataBinding} as true if the control is initialized. +	 * This method is invoked when either {@link setDataSource} or {@link setDataSourceID} is changed. +	 */ +	public function onDataSourceChanged() +	{ +		$this->_currentViewValid=false; +		$this->_currentDataSourceValid=false; +		if($this->getInitialized()) +			$this->setRequiresDataBinding(true); +	} + +	/** +	 * @return boolean whether the databound control has been initialized. +	 * By default, the control is initialized after its viewstate has been restored. +	 */ +	protected function getInitialized() +	{ +		return $this->_initialized; +	} + +	/** +	 * Sets a value indicating whether the databound control is initialized. +	 * If initialized, any modification to {@link setDataSource DataSource} or +	 * {@link setDataSourceID DataSourceID} will set {@link setRequiresDataBinding RequiresDataBinding} +	 * as true. +	 * @param boolean a value indicating whether the databound control is initialized. +	 */ +	protected function setInitialized($value) +	{ +		$this->_initialized=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * @return boolean whether databind has been invoked in the previous page request +	 */ +	protected function getIsDataBound() +	{ +		return $this->_isDataBound; +	} + +	/** +	 * @param boolean if databind has been invoked in this page request +	 */ +	protected function setIsDataBound($value) +	{ +		$this->_isDataBound=$value; +	} + +	/** +	 * @return boolean whether a databind call is required (by the data bound control) +	 */ +	protected function getRequiresDataBinding() +	{ +		return $this->_requiresDataBinding; +	} + +	/** +	 * @return boolean whether paging is enabled. Defaults to false. +	 */ +	public function getAllowPaging() +	{ +		return $this->getViewState('AllowPaging',false); +	} + +	/** +	 * @param boolean whether paging is enabled +	 */ +	public function setAllowPaging($value) +	{ +		$this->setViewState('AllowPaging',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @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 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) +			$value=0; +		$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('databoundcontrol_pagesize_invalid',get_class($this)); +		$this->setViewState('PageSize',TPropertyValue::ensureInteger($value),10); +	} + +	/** +	 * @return integer number of pages of data items available +	 */ +	public function getPageCount() +	{ +		return $this->getViewState('PageCount',1); +	} + +	/** +	 * @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('databoundcontrol_virtualitemcount_invalid',get_class($this)); +		$this->setViewState('VirtualItemCount',$value,0); +	} + +	/** +	 * Sets a value indicating whether a databind call is required by the data bound control. +	 * If true and the control has been prerendered while it uses the data source +	 * specified by {@link setDataSourceID}, a databind call will be called by this method. +	 * @param boolean whether a databind call is required. +	 */ +	protected function setRequiresDataBinding($value) +	{ +		$value=TPropertyValue::ensureBoolean($value); +		if($value && $this->_prerendered) +		{ +			$this->_requiresDataBinding=true; +			$this->ensureDataBound(); +		} +		else +			$this->_requiresDataBinding=$value; +	} + +	/** +	 * Ensures any pending {@link dataBind} is called. +	 * This method calls {@link dataBind} if the data source is specified +	 * by {@link setDataSourceID} or if {@link getRequiresDataBinding RequiresDataBinding} +	 * is true. +	 */ +	protected function ensureDataBound() +	{ +		if($this->_requiresDataBinding && ($this->getUsingDataSourceID() || $this->_requiresBindToNull)) +		{ +			$this->dataBind(); +			$this->_requiresBindToNull=false; +		} +	} + +	/** +	 * @return TPagedDataSource creates a paged data source +	 */ +	protected function createPagedDataSource() +	{ +		$ds=new TPagedDataSource; +		$ds->setCurrentPageIndex($this->getCurrentPageIndex()); +		$ds->setPageSize($this->getPageSize()); +		$ds->setAllowPaging($this->getAllowPaging()); +		$ds->setAllowCustomPaging($this->getAllowCustomPaging()); +		$ds->setVirtualItemCount($this->getVirtualItemCount()); +		return $ds; +	} + +	/** +	 * Performs databinding. +	 * This method overrides the parent implementation by calling +	 * {@link performSelect} which fetches data from data source and does +	 * the actual binding work. +	 */ +	public function dataBind() +	{ +		$this->setRequiresDataBinding(false); +		$this->dataBindProperties(); +		$this->onDataBinding(null); + +		if(($view=$this->getDataSourceView())!==null) +			$data=$view->select($this->getSelectParameters()); +		else +			$data=null; + +		if($data instanceof Traversable) +		{ +			if($this->getAllowPaging()) +			{ +				$ds=$this->createPagedDataSource(); +				$ds->setDataSource($data); +				$this->setViewState('PageCount',$ds->getPageCount()); +				if($ds->getCurrentPageIndex()>=$ds->getPageCount()) +				{ +					$ds->setCurrentPageIndex($ds->getPageCount()-1); +					$this->setCurrentPageIndex($ds->getCurrentPageIndex()); +				} +				$this->performDataBinding($ds); +			} +			else +			{ +				$this->clearViewState('PageCount'); +				$this->performDataBinding($data); +			} +		} +		$this->setIsDataBound(true); +		$this->onDataBound(null); +	} + +	public function dataSourceViewChanged($sender,$param) +	{ +		if(!$this->_ignoreDataSourceViewChanged) +			$this->setRequiresDataBinding(true); +	} + +	protected function getDataSourceView() +	{ +		if(!$this->_currentViewValid) +		{ +			if($this->_currentView && $this->_currentViewIsFromDataSourceID) +				$this->_currentView->detachEventHandler('DataSourceViewChanged',array($this,'dataSourceViewChanged')); +			if(($dataSource=$this->determineDataSource())!==null) +			{ +				if(($view=$dataSource->getView($this->getDataMember()))===null) +					throw new TInvalidDataValueException('databoundcontrol_datamember_invalid',$this->getDataMember()); +				if($this->_currentViewIsFromDataSourceID=$this->getUsingDataSourceID()) +					$view->attachEventHandler('OnDataSourceViewChanged',array($this,'dataSourceViewChanged')); +				$this->_currentView=$view; +			} +			else +				$this->_currentView=null; +			$this->_currentViewValid=true; +		} +		return $this->_currentView; +	} + +	protected function determineDataSource() +	{ +		if(!$this->_currentDataSourceValid) +		{ +			if(($dsid=$this->getDataSourceID())!=='') +			{ +				if(($dataSource=$this->getNamingContainer()->findControl($dsid))===null) +					throw new TInvalidDataValueException('databoundcontrol_datasourceid_inexistent',$dsid); +				else if(!($dataSource instanceof IDataSource)) +					throw new TInvalidDataValueException('databoundcontrol_datasourceid_invalid',$dsid); +				else +					$this->_currentDataSource=$dataSource; +			} +			else if(($dataSource=$this->getDataSource())!==null) +				$this->_currentDataSource=new TReadOnlyDataSource($dataSource,$this->getDataMember()); +			else +				$this->_currentDataSource=null; +			$this->_currentDataSourceValid=true; +		} +		return $this->_currentDataSource; +	} + +	abstract protected function performDataBinding($data); + +	/** +	 * Raises <b>OnDataBound</b> event. +	 * This method should be invoked after a databind is performed. +	 * It is mainly used by framework and component developers. +	 */ +	public function onDataBound($param) +	{ +		$this->raiseEvent('OnDataBound',$this,$param); +	} + +	/** +	 * Sets page's <b>OnPreLoad</b> event handler as {@link pagePreLoad}. +	 * If viewstate is disabled and the current request is a postback, +	 * {@link setRequiresDataBinding RequiresDataBinding} will be set true. +	 * This method overrides the parent implementation. +	 * @param TEventParameter event parameter +	 */ +	public function onInit($param) +	{ +		parent::onInit($param); +		$page=$this->getPage(); +		$page->attachEventHandler('OnPreLoad',array($this,'pagePreLoad')); +	} + +	/** +	 * Sets {@link getInitialized} as true. +	 * This method is invoked when page raises <b>PreLoad</b> event. +	 * @param mixed event sender +	 * @param TEventParameter event parameter +	 */ +	public function pagePreLoad($sender,$param) +	{ +		$this->_initialized=true; +		$isPostBack=$this->getPage()->getIsPostBack(); +		if(!$isPostBack || ($isPostBack && (!$this->getEnableViewState(true) || !$this->getIsDataBound()))) +			$this->setRequiresDataBinding(true); +	} + +	/** +	 * Ensures any pending databind is performed. +	 * This method overrides the parent implementation. +	 * @param TEventParameter event parameter +	 */ +	public function onPreRender($param) +	{ +		$this->_prerendered=true; +		$this->ensureDataBound(); +		parent::onPreRender($param); +	} + +	/** +	 * Validates if the parameter is a valid data source. +	 * If it is a string or an array, it will be converted as a TList object. +	 * @param Traversable|array|string data source to be validated +	 * @return Traversable the data that is traversable +	 * @throws TInvalidDataTypeException if the data is neither null nor Traversable +	 */ +	protected function validateDataSource($value) +	{ +		if(is_string($value)) +		{ +			$list=new TList; +			foreach(TPropertyValue::ensureArray($value) as $key=>$value) +			{ +				if(is_array($value)) +					$list->add($value); +				else +					$list->add(array($value,is_string($key)?$key:$value)); +			} +			return $list; +		} +		else if(is_array($value)) +			return new TMap($value); +		else if($value instanceof TDbDataReader) { +			// read array from TDbDataReader since it's forward-only stream and can only be traversed once +			return $value->readAll(); +		} +		else if(($value instanceof Traversable) || $value===null) +			return $value; +		else +			throw new TInvalidDataTypeException('databoundcontrol_datasource_invalid',get_class($this)); +	} + +	public function getDataMember() +	{ +		return $this->getViewState('DataMember',''); +	} + +	public function setDataMember($value) +	{ +		$this->setViewState('DataMember',$value,''); +	} + +	public function getSelectParameters() +	{ +		if(!$this->_parameters) +			$this->_parameters=new TDataSourceSelectParameters; +		return $this->_parameters; +	} +} + + +/** + * TListItemType class. + * TListItemType defines the enumerable type for the possible types + * that databound list items could take. + * + * The following enumerable values are defined: + * - Header: header item + * - Footer: footer item + * - Item: content item (neither header nor footer) + * - Separator: separator between items + * - AlternatingItem: alternating content item + * - EditItem: content item in edit mode + * - SelectedItem: selected content item + * - Pager: pager + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TListItemType extends TEnumerable +{ +	const Header='Header'; +	const Footer='Footer'; +	const Item='Item'; +	const Separator='Separator'; +	const AlternatingItem='AlternatingItem'; +	const EditItem='EditItem'; +	const SelectedItem='SelectedItem'; +	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 <qiang.xue@gmail.com> + * @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); +} + +?> diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php index 2af66b33..2e2c5252 100644 --- a/framework/Web/UI/WebControls/TDataGrid.php +++ b/framework/Web/UI/WebControls/TDataGrid.php @@ -1,2258 +1,2258 @@ -<?php
 -/**
 - * TDataGrid related class files.
 - * This file contains the definition of the following classes:
 - * TDataGrid, TDataGridItem, TDataGridItemCollection, TDataGridColumnCollection,
 - * TDataGridPagerStyle, TDataGridItemEventParameter,
 - * TDataGridCommandEventParameter, TDataGridSortCommandEventParameter,
 - * TDataGridPageChangedEventParameter
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TBaseList, TPagedDataSource, TDummyDataSource and TTable classes
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseDataList');
 -Prado::using('System.Collections.TPagedDataSource');
 -Prado::using('System.Collections.TDummyDataSource');
 -Prado::using('System.Web.UI.WebControls.TTable');
 -Prado::using('System.Web.UI.WebControls.TPanel');
 -Prado::using('System.Web.UI.WebControls.TDataGridPagerStyle');
 -
 -/**
 - * TDataGrid class
 - *
 - * TDataGrid represents a data bound and updatable grid control.
 - *
 - * To populate data into the datagrid, sets its {@link setDataSource DataSource}
 - * to a tabular data source and call {@link dataBind()}.
 - * Each row of data will be represented by an item in the {@link getItems Items}
 - * collection of the datagrid.
 - *
 - * An item can be at one of three states: browsing, selected and edit.
 - * The state determines how the item will be displayed. For example, if an item
 - * is in edit state, it may be displayed as a table row with input text boxes
 - * if the columns are of type {@link TBoundColumn}; and if in browsing state,
 - * they are displayed as static text.
 - *
 - * To change the state of an item, set {@link setEditItemIndex EditItemIndex}
 - * or {@link setSelectedItemIndex SelectedItemIndex} property.
 - *
 - * Each datagrid item has a {@link TDataGridItem::getItemType type}
 - * which tells the position and state of the item in the datalist. An item in the header
 - * of the repeater is of type Header. A body item may be of either
 - * Item, AlternatingItem, SelectedItem or EditItem, depending whether the item
 - * index is odd or even, whether it is being selected or edited.
 - *
 - * A datagrid is specified with a list of columns. Each column specifies how the corresponding
 - * table column will be displayed. For example, the header/footer text of that column,
 - * the cells in that column, and so on. The following column types are currently
 - * provided by the framework,
 - * - {@link TBoundColumn}, associated with a specific field in datasource and displays the corresponding data.
 - * - {@link TEditCommandColumn}, displaying edit/update/cancel command buttons
 - * - {@link TButtonColumn}, displaying generic command buttons that may be bound to specific field in datasource.
 - * - {@link TDropDownListColumn}, displaying a dropdown list when the item is in edit state
 - * - {@link THyperLinkColumn}, displaying a hyperlink that may be bound to specific field in datasource.
 - * - {@link TCheckBoxColumn}, displaying a checkbox that may be bound to specific field in datasource.
 - * - {@link TTemplateColumn}, displaying content based on templates.
 - *
 - * There are three ways to specify columns for a datagrid.
 - * <ul>
 - *  <li>Automatically generated based on data source.
 - *  By setting {@link setAutoGenerateColumns AutoGenerateColumns} to true,
 - *  a list of columns will be automatically generated based on the schema of the data source.
 - *  Each column corresponds to a column of the data.</li>
 - *  <li>Specified in template. For example,
 - *    <code>
 - *     <com:TDataGrid ...>
 - *        <com:TBoundColumn .../>
 - *        <com:TEditCommandColumn .../>
 - *     </com:TDataGrid>
 - *    </code>
 - *  </li>
 - *  <li>Manually created in code. Columns can be manipulated via
 - *  the {@link setColumns Columns} property of the datagrid. For example,
 - *  <code>
 - *    $column=new TBoundColumn;
 - *    $datagrid->Columns[]=$column;
 - *  </code>
 - *  </li>
 - * </ul>
 - * Note, automatically generated columns cannot be accessed via
 - * the {@link getColumns Columns} property.
 - *
 - * TDataGrid supports sorting. If the {@link setAllowSorting AllowSorting}
 - * is set to true, a column with nonempty {@link setSortExpression SortExpression}
 - * will have its header text displayed as a clickable link button.
 - * Clicking on the link button will raise {@link onSortCommand OnSortCommand}
 - * event. You can respond to this event, sort the data source according
 - * to the event parameter, and then invoke {@link databind()} on the datagrid
 - * to show to end users the sorted data.
 - *
 - * TDataGrid supports paging. If the {@link setAllowPaging AllowPaging}
 - * is set to true, a pager will be displayed on top and/or bottom of the table.
 - * How the pager will be displayed is determined by the {@link getPagerStyle PagerStyle}
 - * property. Clicking on a pager button will raise an {@link onPageIndexChanged OnPageIndexChanged}
 - * event. You can respond to this event, specify the page to be displayed by
 - * setting {@link setCurrentPageIndex CurrentPageIndex}</b> property,
 - * and then invoke {@link databind()} on the datagrid to show to end users
 - * a new page of data.
 - *
 - * TDataGrid supports two kinds of paging. The first one is based on the number of data items in
 - * datasource. The number of pages {@link getPageCount PageCount} is calculated based
 - * the item number and the {@link setPageSize PageSize} property.
 - * The datagrid will manage which section of the data source to be displayed
 - * based on the {@link setCurrentPageIndex CurrentPageIndex} property.
 - * The second approach calculates the page number based on the
 - * {@link setVirtualItemCount VirtualItemCount} property and
 - * the {@link setPageSize PageSize} property. The datagrid will always
 - * display from the beginning of the datasource up to the number of
 - * {@link setPageSize PageSize} data items. This approach is especially
 - * useful when the datasource may contain too many data items to be managed by
 - * the datagrid efficiently.
 - *
 - * When the datagrid contains a button control that raises an {@link onCommand OnCommand}
 - * event, the event will be bubbled up to the datagrid control.
 - * If the event's command name is recognizable by the datagrid control,
 - * a corresponding item event will be raised. The following item events will be
 - * raised upon a specific command:
 - * - OnEditCommand, if CommandName=edit
 - * - OnCancelCommand, if CommandName=cancel
 - * - OnSelectCommand, if CommandName=select
 - * - OnDeleteCommand, if CommandName=delete
 - * - OnUpdateCommand, if CommandName=update
 - * - onPageIndexChanged, if CommandName=page
 - * - OnSortCommand, if CommandName=sort
 - * Note, an {@link onItemCommand OnItemCommand} event is raised in addition to
 - * the above specific command events.
 - *
 - * TDataGrid also raises an {@link onItemCreated OnItemCreated} event for
 - * every newly created datagrid item. You can respond to this event to customize
 - * the content or style of the newly created item.
 - *
 - * Note, the data bound to the datagrid are reset to null after databinding.
 - * There are several ways to access the data associated with a datagrid row:
 - * - Access the data in {@link onItemDataBound OnItemDataBound} event
 - * - Use {@link getDataKeys DataKeys} to obtain the data key associated with
 - * the specified datagrid row 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.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGrid extends TBaseDataList implements INamingContainer
 -{
 -	/**
 -	 * datagrid item types
 -	 * @deprecated deprecated since version 3.0.4. Use TListItemType constants instead.
 -	 */
 -	const IT_HEADER='Header';
 -	const IT_FOOTER='Footer';
 -	const IT_ITEM='Item';
 -	const IT_SEPARATOR='Separator';
 -	const IT_ALTERNATINGITEM='AlternatingItem';
 -	const IT_EDITITEM='EditItem';
 -	const IT_SELECTEDITEM='SelectedItem';
 -	const IT_PAGER='Pager';
 -
 -	/**
 -	 * Command name that TDataGrid understands.
 -	 */
 -	const CMD_SELECT='Select';
 -	const CMD_EDIT='Edit';
 -	const CMD_UPDATE='Update';
 -	const CMD_DELETE='Delete';
 -	const CMD_CANCEL='Cancel';
 -	const CMD_SORT='Sort';
 -	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 TDataGridColumnCollection manually created column collection
 -	 */
 -	private $_columns=null;
 -	/**
 -	 * @var TDataGridColumnCollection automatically created column collection
 -	 */
 -	private $_autoColumns=null;
 -	/**
 -	 * @var TList all columns including both manually and automatically created columns
 -	 */
 -	private $_allColumns=null;
 -	/**
 -	 * @var TDataGridItemCollection datagrid item collection
 -	 */
 -	private $_items=null;
 -	/**
 -	 * @var TDataGridItem header item
 -	 */
 -	private $_header=null;
 -	/**
 -	 * @var TDataGridItem footer item
 -	 */
 -	private $_footer=null;
 -	/**
 -	 * @var TPagedDataSource paged data source object
 -	 */
 -	private $_pagedDataSource=null;
 -	private $_topPager=null;
 -	private $_bottomPager=null;
 -	/**
 -	 * @var ITemplate template used when empty data is bounded
 -	 */
 -	private $_emptyTemplate=null;
 -	/**
 -	 * @var boolean whether empty template is effective
 -	 */
 -	private $_useEmptyTemplate=false;
 -
 -	/**
 -	 * @return string tag name (table) of the datagrid
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'table';
 -	}
 -
 -	/**
 -	 * @return string Name of the class used in AutoGenerateColumns mode
 -	 */
 -	protected function getAutoGenerateColumnName()
 -	{
 -		return 'TBoundColumn';
 -	}
 -
 -	/**
 -	 * Adds objects parsed in template to datagrid.
 -	 * Datagrid columns are added into {@link getColumns Columns} collection.
 -	 * @param mixed object parsed in template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TDataGridColumn)
 -			$this->getColumns()->add($object);
 -		else
 -			parent::addParsedObject($object);  // this is needed by EmptyTemplate
 -	}
 -
 -	/**
 -	 * @return TDataGridColumnCollection manually specified datagrid columns
 -	 */
 -	public function getColumns()
 -	{
 -		if(!$this->_columns)
 -			$this->_columns=new TDataGridColumnCollection($this);
 -		return $this->_columns;
 -	}
 -
 -	/**
 -	 * @return TDataGridColumnCollection automatically generated datagrid columns
 -	 */
 -	public function getAutoColumns()
 -	{
 -		if(!$this->_autoColumns)
 -			$this->_autoColumns=new TDataGridColumnCollection($this);
 -		return $this->_autoColumns;
 -	}
 -
 -	/**
 -	 * @return TDataGridItemCollection datagrid item collection
 -	 */
 -	public function getItems()
 -	{
 -		if(!$this->_items)
 -			$this->_items=new TDataGridItemCollection;
 -		return $this->_items;
 -	}
 -
 -	/**
 -	 * @return integer number of items
 -	 */
 -	public function getItemCount()
 -	{
 -		return $this->_items?$this->_items->getCount():0;
 -	}
 -
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableStyle} to be used by datagrid.
 -	 * @return TTableStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableStyle;
 -	}
 -
 -	/**
 -	 * @return string the URL of the background image for the datagrid
 -	 */
 -	public function getBackImageUrl()
 -	{
 -		return $this->getStyle()->getBackImageUrl();
 -	}
 -
 -	/**
 -	 * @param string the URL of the background image for the datagrid
 -	 */
 -	public function setBackImageUrl($value)
 -	{
 -		$this->getStyle()->setBackImageUrl($value);
 -	}
 -
 -	/**
 -	 * @return TTableItemStyle the style for every item
 -	 */
 -	public function getItemStyle()
 -	{
 -		if(($style=$this->getViewState('ItemStyle',null))===null)
 -		{
 -			$style=new TTableItemStyle;
 -			$this->setViewState('ItemStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @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 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 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 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 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 TDataGridPagerStyle the style for pager
 -	 */
 -	public function getPagerStyle()
 -	{
 -		if(($style=$this->getViewState('PagerStyle',null))===null)
 -		{
 -			$style=new TDataGridPagerStyle;
 -			$this->setViewState('PagerStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TStyle the style for thead element, if any
 -	 * @since 3.1.1
 -	 */
 -	public function getTableHeadStyle()
 -	{
 -		if(($style=$this->getViewState('TableHeadStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$this->setViewState('TableHeadStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TStyle the style for tbody element, if any
 -	 * @since 3.1.1
 -	 */
 -	public function getTableBodyStyle()
 -	{
 -		if(($style=$this->getViewState('TableBodyStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$this->setViewState('TableBodyStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TStyle the style for tfoot element, if any
 -	 * @since 3.1.1
 -	 */
 -	public function getTableFootStyle()
 -	{
 -		if(($style=$this->getViewState('TableFootStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$this->setViewState('TableFootStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return string caption for the datagrid
 -	 */
 -	public function getCaption()
 -	{
 -		return $this->getViewState('Caption','');
 -	}
 -
 -	/**
 -	 * @param string caption for the datagrid
 -	 */
 -	public function setCaption($value)
 -	{
 -		$this->setViewState('Caption',$value,'');
 -	}
 -
 -	/**
 -	 * @return TTableCaptionAlign datagrid caption alignment. Defaults to TTableCaptionAlign::NotSet.
 -	 */
 -	public function getCaptionAlign()
 -	{
 -		return $this->getViewState('CaptionAlign',TTableCaptionAlign::NotSet);
 -	}
 -
 -	/**
 -	 * @param TTableCaptionAlign datagrid caption alignment. Valid values include
 -	 */
 -	public function setCaptionAlign($value)
 -	{
 -		$this->setViewState('CaptionAlign',TPropertyValue::ensureEnum($value,'TTableCaptionAlign'),TTableCaptionAlign::NotSet);
 -	}
 -
 -	/**
 -	 * @return TDataGridItem the header item
 -	 */
 -	public function getHeader()
 -	{
 -		return $this->_header;
 -	}
 -
 -	/**
 -	 * @return TDataGridItem the footer item
 -	 */
 -	public function getFooter()
 -	{
 -		return $this->_footer;
 -	}
 -
 -	/**
 -	 * @return TDataGridPager the pager displayed at the top of datagrid. It could be null if paging is disabled.
 -	 */
 -	public function getTopPager()
 -	{
 -		return $this->_topPager;
 -	}
 -
 -	/**
 -	 * @return TDataGridPager the pager displayed at the bottom of datagrid. It could be null if paging is disabled.
 -	 */
 -	public function getBottomPager()
 -	{
 -		return $this->_bottomPager;
 -	}
 -
 -	/**
 -	 * @return TDataGridItem 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 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()!==TListItemType::EditItem)
 -					$item->setItemType($current%2?TListItemType::AlternatingItem:TListItemType::Item);
 -			}
 -			if($value>=0 && $value<$itemCount)
 -			{
 -				$item=$items->itemAt($value);
 -				if($item->getItemType()!==TListItemType::EditItem)
 -					$item->setItemType(TListItemType::SelectedItem);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * @return TDataGridItem 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 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?TListItemType::AlternatingItem:TListItemType::Item);
 -			if($value>=0 && $value<$itemCount)
 -				$items->itemAt($value)->setItemType(TListItemType::EditItem);
 -		}
 -	}
 -
 -	/**
 -	 * @return boolean whether sorting is enabled. Defaults to false.
 -	 */
 -	public function getAllowSorting()
 -	{
 -		return $this->getViewState('AllowSorting',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether sorting is enabled
 -	 */
 -	public function setAllowSorting($value)
 -	{
 -		$this->setViewState('AllowSorting',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether datagrid columns should be automatically generated. Defaults to true.
 -	 */
 -	public function getAutoGenerateColumns()
 -	{
 -		return $this->getViewState('AutoGenerateColumns',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether datagrid columns should be automatically generated
 -	 */
 -	public function setAutoGenerateColumns($value)
 -	{
 -		$this->setViewState('AutoGenerateColumns',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return boolean whether the header should be displayed. Defaults to true.
 -	 */
 -	public function getShowHeader()
 -	{
 -		return $this->getViewState('ShowHeader',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether the header should be displayed
 -	 */
 -	public function setShowHeader($value)
 -	{
 -		$this->setViewState('ShowHeader',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return boolean whether the footer should be displayed. Defaults to false.
 -	 */
 -	public function getShowFooter()
 -	{
 -		return $this->getViewState('ShowFooter',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the footer should be displayed
 -	 */
 -	public function setShowFooter($value)
 -	{
 -		$this->setViewState('ShowFooter',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return ITemplate the template applied when no data is bound to the datagrid
 -	 */
 -	public function getEmptyTemplate()
 -	{
 -		return $this->_emptyTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template applied when no data is bound to the datagrid
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setEmptyTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_emptyTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datagrid_template_required','EmptyTemplate');
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation to handle
 -	 * {@link onItemCommand OnItemCommand} event which is bubbled from
 -	 * {@link TDataGridItem} child controls.
 -	 * If the event parameter is {@link TDataGridCommandEventParameter} 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 OnEditCommand}).
 -	 * 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.
 -	 */
 -	public function bubbleEvent($sender,$param)
 -	{
 -		if($param instanceof TDataGridCommandEventParameter)
 -		{
 -			$this->onItemCommand($param);
 -			$command=$param->getCommandName();
 -			if(strcasecmp($command,self::CMD_SELECT)===0)
 -			{
 -				$this->setSelectedItemIndex($param->getItem()->getItemIndex());
 -				$this->onSelectedIndexChanged($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_EDIT)===0)
 -			{
 -				$this->onEditCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_DELETE)===0)
 -			{
 -				$this->onDeleteCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_UPDATE)===0)
 -			{
 -				$this->onUpdateCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_CANCEL)===0)
 -			{
 -				$this->onCancelCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_SORT)===0)
 -			{
 -				$this->onSortCommand(new TDataGridSortCommandEventParameter($sender,$param));
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_PAGE)===0)
 -			{
 -				$p=$param->getCommandParameter();
 -				if(strcasecmp($p,self::CMD_PAGE_NEXT)===0)
 -					$pageIndex=$this->getCurrentPageIndex()+1;
 -				else if(strcasecmp($p,self::CMD_PAGE_PREV)===0)
 -					$pageIndex=$this->getCurrentPageIndex()-1;
 -				else if(strcasecmp($p,self::CMD_PAGE_FIRST)===0)
 -					$pageIndex=0;
 -				else if(strcasecmp($p,self::CMD_PAGE_LAST)===0)
 -					$pageIndex=$this->getPageCount()-1;
 -				else
 -					$pageIndex=TPropertyValue::ensureInteger($p)-1;
 -				$this->onPageIndexChanged(new TDataGridPageChangedEventParameter($sender,$pageIndex));
 -				return true;
 -			}
 -		}
 -		return false;
 -	}
 -
 -	/**
 -	 * Raises <b>OnCancelCommand</b> event.
 -	 * This method is invoked when a button control raises <b>OnCommand</b> event
 -	 * with <b>cancel</b> command name.
 -	 * @param TDataGridCommandEventParameter event parameter
 -	 */
 -	public function onCancelCommand($param)
 -	{
 -		$this->raiseEvent('OnCancelCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnDeleteCommand</b> event.
 -	 * This method is invoked when a button control raises <b>OnCommand</b> event
 -	 * with <b>delete</b> command name.
 -	 * @param TDataGridCommandEventParameter event parameter
 -	 */
 -	public function onDeleteCommand($param)
 -	{
 -		$this->raiseEvent('OnDeleteCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnEditCommand</b> event.
 -	 * This method is invoked when a button control raises <b>OnCommand</b> event
 -	 * with <b>edit</b> command name.
 -	 * @param TDataGridCommandEventParameter event parameter
 -	 */
 -	public function onEditCommand($param)
 -	{
 -		$this->raiseEvent('OnEditCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemCommand</b> event.
 -	 * This method is invoked when a button control raises <b>OnCommand</b> event.
 -	 * @param TDataGridCommandEventParameter event parameter
 -	 */
 -	public function onItemCommand($param)
 -	{
 -		$this->raiseEvent('OnItemCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnSortCommand</b> event.
 -	 * This method is invoked when a button control raises <b>OnCommand</b> event
 -	 * with <b>sort</b> command name.
 -	 * @param TDataGridSortCommandEventParameter event parameter
 -	 */
 -	public function onSortCommand($param)
 -	{
 -		$this->raiseEvent('OnSortCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnUpdateCommand</b> event.
 -	 * This method is invoked when a button control raises <b>OnCommand</b> event
 -	 * with <b>update</b> command name.
 -	 * @param TDataGridCommandEventParameter event parameter
 -	 */
 -	public function onUpdateCommand($param)
 -	{
 -		$this->raiseEvent('OnUpdateCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemCreated</b> event.
 -	 * This method is invoked right after a datagrid item is created and before
 -	 * added to page hierarchy.
 -	 * @param TDataGridItemEventParameter event parameter
 -	 */
 -	public function onItemCreated($param)
 -	{
 -		$this->raiseEvent('OnItemCreated',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnPagerCreated</b> event.
 -	 * This method is invoked right after a datagrid pager is created and before
 -	 * added to page hierarchy.
 -	 * @param TDataGridPagerEventParameter event parameter
 -	 */
 -	public function onPagerCreated($param)
 -	{
 -		$this->raiseEvent('OnPagerCreated',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemDataBound</b> event.
 -	 * This method is invoked for each datagrid item after it performs
 -	 * databinding.
 -	 * @param TDataGridItemEventParameter event parameter
 -	 */
 -	public function onItemDataBound($param)
 -	{
 -		$this->raiseEvent('OnItemDataBound',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnPageIndexChanged</b> event.
 -	 * This method is invoked when current page is changed.
 -	 * @param TDataGridPageChangedEventParameter event parameter
 -	 */
 -	public function onPageIndexChanged($param)
 -	{
 -		$this->raiseEvent('OnPageIndexChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Saves item count in viewstate.
 -	 * This method is invoked right before control state is to be saved.
 -	 */
 -	public function saveState()
 -	{
 -		parent::saveState();
 -		if(!$this->getEnableViewState(true))
 -			return;
 -		if($this->_items)
 -			$this->setViewState('ItemCount',$this->_items->getCount(),0);
 -		else
 -			$this->clearViewState('ItemCount');
 -		if($this->_autoColumns)
 -		{
 -			$state=array();
 -			foreach($this->_autoColumns as $column)
 -				$state[]=$column->saveState();
 -			$this->setViewState('AutoColumns',$state,array());
 -		}
 -		else
 -			$this->clearViewState('AutoColumns');
 -		if($this->_columns)
 -		{
 -			$state=array();
 -			foreach($this->_columns as $column)
 -				$state[]=$column->saveState();
 -			$this->setViewState('Columns',$state,array());
 -		}
 -		else
 -			$this->clearViewState('Columns');
 -	}
 -
 -	/**
 -	 * Loads item count information from viewstate.
 -	 * This method is invoked right after control state is loaded.
 -	 */
 -	public function loadState()
 -	{
 -		parent::loadState();
 -		if(!$this->getEnableViewState(true))
 -			return;
 -		if(!$this->getIsDataBound())
 -		{
 -			$state=$this->getViewState('AutoColumns',array());
 -			if(!empty($state))
 -			{
 -				$this->_autoColumns=new TDataGridColumnCollection($this);
 -				foreach($state as $st)
 -				{
 -					$column=new $this->AutoGenerateColumnName;
 -					$column->loadState($st);
 -					$this->_autoColumns->add($column);
 -				}
 -			}
 -			else
 -				$this->_autoColumns=null;
 -			$state=$this->getViewState('Columns',array());
 -			if($this->_columns && $this->_columns->getCount()===count($state))
 -			{
 -				$i=0;
 -				foreach($this->_columns as $column)
 -				{
 -					$column->loadState($state[$i]);
 -					$i++;
 -				}
 -			}
 -			$this->restoreGridFromViewState();
 -		}
 -	}
 -
 -	/**
 -	 * Clears up all items in the datagrid.
 -	 */
 -	public function reset()
 -	{
 -		$this->getControls()->clear();
 -		$this->getItems()->clear();
 -		$this->_header=null;
 -		$this->_footer=null;
 -		$this->_topPager=null;
 -		$this->_bottomPager=null;
 -		$this->_useEmptyTemplate=false;
 -	}
 -
 -	/**
 -	 * Restores datagrid content from viewstate.
 -	 */
 -	protected function restoreGridFromViewState()
 -	{
 -		$this->reset();
 -
 -		$allowPaging=$this->getAllowPaging();
 -
 -		$itemCount=$this->getViewState('ItemCount',0);
 -		$dsIndex=$this->getViewState('DataSourceIndex',0);
 -
 -		$columns=new TList($this->getColumns());
 -		$columns->mergeWith($this->_autoColumns);
 -		$this->_allColumns=$columns;
 -
 -		$items=$this->getItems();
 -
 -		if($columns->getCount())
 -		{
 -			foreach($columns as $column)
 -				$column->initialize();
 -			$selectedIndex=$this->getSelectedItemIndex();
 -			$editIndex=$this->getEditItemIndex();
 -			for($index=0;$index<$itemCount;++$index)
 -			{
 -				if($index===0)
 -				{
 -					if($allowPaging)
 -						$this->_topPager=$this->createPager();
 -					$this->_header=$this->createItemInternal(-1,-1,TListItemType::Header,false,null,$columns);
 -				}
 -				if($index===$editIndex)
 -					$itemType=TListItemType::EditItem;
 -				else if($index===$selectedIndex)
 -					$itemType=TListItemType::SelectedItem;
 -				else if($index % 2)
 -					$itemType=TListItemType::AlternatingItem;
 -				else
 -					$itemType=TListItemType::Item;
 -				$items->add($this->createItemInternal($index,$dsIndex,$itemType,false,null,$columns));
 -				$dsIndex++;
 -			}
 -			if($index>0)
 -			{
 -				$this->_footer=$this->createItemInternal(-1,-1,TListItemType::Footer,false,null,$columns);
 -				if($allowPaging)
 -					$this->_bottomPager=$this->createPager();
 -			}
 -		}
 -		if(!$dsIndex && $this->_emptyTemplate!==null)
 -		{
 -			$this->_useEmptyTemplate=true;
 -			$this->_emptyTemplate->instantiateIn($this);
 -		}
 -	}
 -
 -	/**
 -	 * 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
 -	 */
 -	protected function performDataBinding($data)
 -	{
 -		$this->reset();
 -		$keys=$this->getDataKeys();
 -		$keys->clear();
 -		$keyField=$this->getDataKeyField();
 -
 -		// get all columns
 -		if($this->getAutoGenerateColumns())
 -		{
 -			$columns=new TList($this->getColumns());
 -			$autoColumns=$this->createAutoColumns($data);
 -			$columns->mergeWith($autoColumns);
 -		}
 -		else
 -			$columns=$this->getColumns();
 -		$this->_allColumns=$columns;
 -
 -		$items=$this->getItems();
 -
 -		$index=0;
 -		$allowPaging=$this->getAllowPaging() && ($data instanceof TPagedDataSource);
 -		$dsIndex=$allowPaging?$data->getFirstIndexInPage():0;
 -		$this->setViewState('DataSourceIndex',$dsIndex,0);
 -		if($columns->getCount())
 -		{
 -			foreach($columns as $column)
 -				$column->initialize();
 -
 -			$selectedIndex=$this->getSelectedItemIndex();
 -			$editIndex=$this->getEditItemIndex();
 -			foreach($data as $key=>$row)
 -			{
 -				if($keyField!=='')
 -					$keys->add($this->getDataFieldValue($row,$keyField));
 -				else
 -					$keys->add($key);
 -				if($index===0)
 -				{
 -					if($allowPaging)
 -						$this->_topPager=$this->createPager();
 -					$this->_header=$this->createItemInternal(-1,-1,TListItemType::Header,true,null,$columns);
 -				}
 -				if($index===$editIndex)
 -					$itemType=TListItemType::EditItem;
 -				else if($index===$selectedIndex)
 -					$itemType=TListItemType::SelectedItem;
 -				else if($index % 2)
 -					$itemType=TListItemType::AlternatingItem;
 -				else
 -					$itemType=TListItemType::Item;
 -				$items->add($this->createItemInternal($index,$dsIndex,$itemType,true,$row,$columns));
 -				$index++;
 -				$dsIndex++;
 -			}
 -			if($index>0)
 -			{
 -				$this->_footer=$this->createItemInternal(-1,-1,TListItemType::Footer,true,null,$columns);
 -				if($allowPaging)
 -					$this->_bottomPager=$this->createPager();
 -			}
 -		}
 -		$this->setViewState('ItemCount',$index,0);
 -		if(!$dsIndex && $this->_emptyTemplate!==null)
 -		{
 -			$this->_useEmptyTemplate=true;
 -			$this->_emptyTemplate->instantiateIn($this);
 -			$this->dataBindChildren();
 -		}
 -	}
 -
 -	/**
 -	 * Merges consecutive cells who have the same text.
 -	 * @since 3.1.1
 -	 */
 -	private function groupCells()
 -	{
 -		if(($columns=$this->_allColumns)===null)
 -			return;
 -		$items=$this->getItems();
 -		foreach($columns as $id=>$column)
 -		{
 -			if(!$column->getEnableCellGrouping())
 -				continue;
 -			$prevCell=null;
 -			$prevCellText=null;
 -			foreach($items as $item)
 -			{
 -				$itemType=$item->getItemType();
 -				$cell=$item->getCells()->itemAt($id);
 -				if(!$cell->getVisible())
 -					continue;
 -				if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem)
 -				{
 -					if(($cellText=$this->getCellText($cell))==='')
 -					{
 -						$prevCell=null;
 -						$prevCellText=null;
 -						continue;
 -					}
 -					if($prevCell===null || $prevCellText!==$cellText)
 -					{
 -						$prevCell=$cell;
 -						$prevCellText=$cellText;
 -					}
 -					else
 -					{
 -						if(($rowSpan=$prevCell->getRowSpan())===0)
 -							$rowSpan=1;
 -						$prevCell->setRowSpan($rowSpan+1);
 -						$cell->setVisible(false);
 -					}
 -				}
 -			}
 -		}
 -	}
 -
 -	private function getCellText($cell)
 -	{
 -		if(($data=$cell->getText())==='' && $cell->getHasControls())
 -		{
 -			$controls=$cell->getControls();
 -			foreach($controls as $control)
 -			{
 -				if($control instanceof IDataRenderer)
 -					return $control->getData();
 -			}
 -		}
 -		return $data;
 -	}
 -
 -	/**
 -	 * Creates a datagrid item instance based on the item type and index.
 -	 * @param integer zero-based item index
 -	 * @param TListItemType item type
 -	 * @return TDataGridItem created data list item
 -	 */
 -	protected function createItem($itemIndex,$dataSourceIndex,$itemType)
 -	{
 -		return new TDataGridItem($itemIndex,$dataSourceIndex,$itemType);
 -	}
 -
 -	private function createItemInternal($itemIndex,$dataSourceIndex,$itemType,$dataBind,$dataItem,$columns)
 -	{
 -		$item=$this->createItem($itemIndex,$dataSourceIndex,$itemType);
 -		$this->initializeItem($item,$columns);
 -		$param=new TDataGridItemEventParameter($item);
 -		if($dataBind)
 -		{
 -			$item->setDataItem($dataItem);
 -			$this->onItemCreated($param);
 -			$this->getControls()->add($item);
 -			$item->dataBind();
 -			$this->onItemDataBound($param);
 -		}
 -		else
 -		{
 -			$this->onItemCreated($param);
 -			$this->getControls()->add($item);
 -		}
 -		return $item;
 -	}
 -
 -	/**
 -	 * Initializes a datagrid item and cells inside it
 -	 * @param TDataGrid datagrid item to be initialized
 -	 * @param TDataGridColumnCollection datagrid columns to be used to initialize the cells in the item
 -	 */
 -	protected function initializeItem($item,$columns)
 -	{
 -		$cells=$item->getCells();
 -		$itemType=$item->getItemType();
 -		$index=0;
 -		foreach($columns as $column)
 -		{
 -			if($itemType===TListItemType::Header)
 -				$cell=new TTableHeaderCell;
 -			else
 -				$cell=new TTableCell;
 -			if(($id=$column->getID())!=='')
 -				$item->registerObject($id,$cell);
 -			$cells->add($cell);
 -			$column->initializeCell($cell,$index,$itemType);
 -			$index++;
 -		}
 -	}
 -
 -	protected function createPager()
 -	{
 -		$pager=new TDataGridPager($this);
 -		$this->buildPager($pager);
 -		$this->onPagerCreated(new TDataGridPagerEventParameter($pager));
 -		$this->getControls()->add($pager);
 -		return $pager;
 -	}
 -
 -	/**
 -	 * Builds the pager content based on pager style.
 -	 * @param TDataGridPager the container for the pager
 -	 */
 -	protected function buildPager($pager)
 -	{
 -		switch($this->getPagerStyle()->getMode())
 -		{
 -			case TDataGridPagerMode::NextPrev:
 -				$this->buildNextPrevPager($pager);
 -				break;
 -			case TDataGridPagerMode::Numeric:
 -				$this->buildNumericPager($pager);
 -				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 mixed the container pager instance of TActiveDatagridPager 
 -	 * @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($pager,$buttonType,$enabled,$text,$commandName,$commandParameter)
 -	{
 -		if($buttonType===TDataGridPagerButtonType::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 TDataGridPager the container for the pager
 -	 */
 -	protected function buildNextPrevPager($pager)
 -	{
 -		$style=$this->getPagerStyle();
 -		$buttonType=$style->getButtonType();
 -		$controls=$pager->getControls();
 -		$currentPageIndex=$this->getCurrentPageIndex();
 -		if($currentPageIndex===0)
 -		{
 -			if(($text=$style->getFirstPageText())!=='')
 -			{
 -				$label=$this->createPagerButton($pager,$buttonType,false,$text,'','');
 -				$controls->add($label);
 -				$controls->add("\n");
 -			}
 -
 -			$label=$this->createPagerButton($pager,$buttonType,false,$style->getPrevPageText(),'','');
 -			$controls->add($label);
 -		}
 -		else
 -		{
 -			if(($text=$style->getFirstPageText())!=='')
 -			{
 -				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_FIRST);
 -				$controls->add($button);
 -				$controls->add("\n");
 -			}
 -
 -			$button=$this->createPagerButton($pager,$buttonType,true,$style->getPrevPageText(),self::CMD_PAGE,self::CMD_PAGE_PREV);
 -			$controls->add($button);
 -		}
 -		$controls->add("\n");
 -		if($currentPageIndex===$this->getPageCount()-1)
 -		{
 -			$label=$this->createPagerButton($pager,$buttonType,false,$style->getNextPageText(),'','');
 -			$controls->add($label);
 -			if(($text=$style->getLastPageText())!=='')
 -			{
 -				$controls->add("\n");
 -				$label=$this->createPagerButton($pager,$buttonType,false,$text,'','');
 -				$controls->add($label);
 -			}
 -		}
 -		else
 -		{
 -			$button=$this->createPagerButton($pager,$buttonType,true,$style->getNextPageText(),self::CMD_PAGE,self::CMD_PAGE_NEXT);
 -			$controls->add($button);
 -			if(($text=$style->getLastPageText())!=='')
 -			{
 -				$controls->add("\n");
 -				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_LAST);
 -				$controls->add($button);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Builds a numeric pager
 -	 * @param TDataGridPager the container for the pager
 -	 */
 -	protected function buildNumericPager($pager)
 -	{
 -		$style=$this->getPagerStyle();
 -		$buttonType=$style->getButtonType();
 -		$controls=$pager->getControls();
 -		$pageCount=$this->getPageCount();
 -		$pageIndex=$this->getCurrentPageIndex()+1;
 -		$maxButtonCount=$style->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=$style->getFirstPageText())!=='')
 -			{
 -				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_FIRST);
 -				$controls->add($button);
 -				$controls->add("\n");
 -			}
 -			$prevPageIndex=$startPageIndex-1;
 -			$button=$this->createPagerButton($pager,$buttonType,true,$style->getPrevPageText(),self::CMD_PAGE,"$prevPageIndex");
 -			$controls->add($button);
 -			$controls->add("\n");
 -		}
 -
 -		for($i=$startPageIndex;$i<=$endPageIndex;++$i)
 -		{
 -			if($i===$pageIndex)
 -			{
 -				$label=$this->createPagerButton($pager,$buttonType,false,"$i",'','');
 -				$controls->add($label);
 -			}
 -			else
 -			{
 -				$button=$this->createPagerButton($pager,$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($pager,$buttonType,true,$style->getNextPageText(),self::CMD_PAGE,"$nextPageIndex");
 -			$controls->add($button);
 -			if(($text=$style->getLastPageText())!=='')
 -			{
 -				$controls->add("\n");
 -				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_LAST);
 -				$controls->add($button);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Automatically generates datagrid columns based on datasource schema
 -	 * @param Traversable data source bound to the datagrid
 -	 * @return TDataGridColumnCollection
 -	 */
 -	protected function createAutoColumns($dataSource)
 -	{
 -		if(!$dataSource)
 -			return null;
 -		$autoColumns=$this->getAutoColumns();
 -		$autoColumns->clear();
 -		foreach($dataSource as $row)
 -		{
 -			foreach($row as $key=>$value)
 -			{
 -				$column=new $this->AutoGenerateColumnName;
 -				if(is_string($key))
 -				{
 -					$column->setHeaderText($key);
 -					$column->setDataField($key);
 -					$column->setSortExpression($key);
 -					$autoColumns->add($column);
 -				}
 -				else
 -				{
 -					$column->setHeaderText(TListItemType::Item);
 -					$column->setDataField($key);
 -					$column->setSortExpression(TListItemType::Item);
 -					$autoColumns->add($column);
 -				}
 -			}
 -			break;
 -		}
 -		return $autoColumns;
 -	}
 -
 -	/**
 -	 * Applies styles to items, header, footer and separators.
 -	 * Item styles are applied in a hierarchical way. Style in higher hierarchy
 -	 * will inherit from styles in lower hierarchy.
 -	 * Starting from the lowest hierarchy, the item styles include
 -	 * item's own style, {@link getItemStyle ItemStyle}, {@link getAlternatingItemStyle AlternatingItemStyle},
 -	 * {@link getSelectedItemStyle SelectedItemStyle}, and {@link getEditItemStyle EditItemStyle}.
 -	 * Therefore, if background color is set as red in {@link getItemStyle ItemStyle},
 -	 * {@link getEditItemStyle EditItemStyle} will also have red background color
 -	 * unless it is set to a different value explicitly.
 -	 */
 -	protected function applyItemStyles()
 -	{
 -		$itemStyle=$this->getViewState('ItemStyle',null);
 -
 -		$alternatingItemStyle=$this->getViewState('AlternatingItemStyle',null);
 -		if($itemStyle!==null)
 -		{
 -			if($alternatingItemStyle===null)
 -				$alternatingItemStyle=$itemStyle;
 -			else
 -				$alternatingItemStyle->mergeWith($itemStyle);
 -		}
 -
 -		$selectedItemStyle=$this->getViewState('SelectedItemStyle',null);
 -
 -		$editItemStyle=$this->getViewState('EditItemStyle',null);
 -		if($selectedItemStyle!==null)
 -		{
 -			if($editItemStyle===null)
 -				$editItemStyle=$selectedItemStyle;
 -			else
 -				$editItemStyle->mergeWith($selectedItemStyle);
 -		}
 -
 -		$headerStyle=$this->getViewState('HeaderStyle',null);
 -		$footerStyle=$this->getViewState('FooterStyle',null);
 -		$pagerStyle=$this->getViewState('PagerStyle',null);
 -		$separatorStyle=$this->getViewState('SeparatorStyle',null);
 -
 -		foreach($this->getControls() as $index=>$item)
 -		{
 -			if(!($item instanceof TDataGridItem) && !($item instanceof TDataGridPager))
 -				continue;
 -			$itemType=$item->getItemType();
 -			switch($itemType)
 -			{
 -				case TListItemType::Header:
 -					if($headerStyle)
 -						$item->getStyle()->mergeWith($headerStyle);
 -					if(!$this->getShowHeader())
 -						$item->setVisible(false);
 -					break;
 -				case TListItemType::Footer:
 -					if($footerStyle)
 -						$item->getStyle()->mergeWith($footerStyle);
 -					if(!$this->getShowFooter())
 -						$item->setVisible(false);
 -					break;
 -				case TListItemType::Separator:
 -					if($separatorStyle)
 -						$item->getStyle()->mergeWith($separatorStyle);
 -					break;
 -				case TListItemType::Item:
 -					if($itemStyle)
 -						$item->getStyle()->mergeWith($itemStyle);
 -					break;
 -				case TListItemType::AlternatingItem:
 -					if($alternatingItemStyle)
 -						$item->getStyle()->mergeWith($alternatingItemStyle);
 -					break;
 -				case TListItemType::SelectedItem:
 -					if($selectedItemStyle)
 -						$item->getStyle()->mergeWith($selectedItemStyle);
 -					if($index % 2==1)
 -					{
 -						if($itemStyle)
 -							$item->getStyle()->mergeWith($itemStyle);
 -					}
 -					else
 -					{
 -						if($alternatingItemStyle)
 -							$item->getStyle()->mergeWith($alternatingItemStyle);
 -					}
 -					break;
 -				case TListItemType::EditItem:
 -					if($editItemStyle)
 -						$item->getStyle()->mergeWith($editItemStyle);
 -					if($index % 2==1)
 -					{
 -						if($itemStyle)
 -							$item->getStyle()->mergeWith($itemStyle);
 -					}
 -					else
 -					{
 -						if($alternatingItemStyle)
 -							$item->getStyle()->mergeWith($alternatingItemStyle);
 -					}
 -					break;
 -				case TListItemType::Pager:
 -					if($pagerStyle)
 -					{
 -						$item->getStyle()->mergeWith($pagerStyle);
 -						if($index===0)
 -						{
 -							if($pagerStyle->getPosition()===TDataGridPagerPosition::Bottom || !$pagerStyle->getVisible())
 -								$item->setVisible(false);
 -						}
 -						else
 -						{
 -							if($pagerStyle->getPosition()===TDataGridPagerPosition::Top || !$pagerStyle->getVisible())
 -								$item->setVisible(false);
 -						}
 -					}
 -					break;
 -				default:
 -					break;
 -			}
 -			if($this->_columns && $itemType!==TListItemType::Pager)
 -			{
 -				$n=$this->_columns->getCount();
 -				$cells=$item->getCells();
 -				for($i=0;$i<$n;++$i)
 -				{
 -					$cell=$cells->itemAt($i);
 -					$column=$this->_columns->itemAt($i);
 -					if(!$column->getVisible())
 -						$cell->setVisible(false);
 -					else
 -					{
 -						if($itemType===TListItemType::Header)
 -							$style=$column->getHeaderStyle(false);
 -						else if($itemType===TListItemType::Footer)
 -							$style=$column->getFooterStyle(false);
 -						else
 -							$style=$column->getItemStyle(false);
 -						if($style!==null)
 -							$cell->getStyle()->mergeWith($style);
 -					}
 -				}
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Renders the openning tag for the datagrid control which will render table caption if present.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderBeginTag($writer)
 -	{
 -		parent::renderBeginTag($writer);
 -		if(($caption=$this->getCaption())!=='')
 -		{
 -			if(($align=$this->getCaptionAlign())!==TTableCaptionAlign::NotSet)
 -				$writer->addAttribute('align',strtolower($align));
 -			$writer->renderBeginTag('caption');
 -			$writer->write($caption);
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	/**
 -	 * Renders the datagrid.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->getHasControls())
 -		{
 -			$this->groupCells();
 -			if($this->_useEmptyTemplate)
 -			{
 -				$control=new TWebControl;
 -				$control->setID($this->getClientID());
 -				$control->copyBaseAttributes($this);
 -				if($this->getHasStyle())
 -					$control->getStyle()->copyFrom($this->getStyle());
 -				$control->renderBeginTag($writer);
 -				$this->renderContents($writer);
 -				$control->renderEndTag($writer);
 -			}
 -			else if($this->getViewState('ItemCount',0)>0)
 -			{
 -				$this->applyItemStyles();
 -				if($this->_topPager)
 -				{
 -					$this->_topPager->renderControl($writer);
 -					$writer->writeLine();
 -				}
 -				$this->renderTable($writer);
 -				if($this->_bottomPager)
 -				{
 -					$writer->writeLine();
 -					$this->_bottomPager->renderControl($writer);
 -				}
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Renders the tabular data.
 -	 * @param THtmlWriter writer
 -	 */
 -	protected function renderTable($writer)
 -	{
 -		$this->renderBeginTag($writer);
 -		if($this->_header && $this->_header->getVisible())
 -		{
 -			$writer->writeLine();
 -			if($style=$this->getViewState('TableHeadStyle',null))
 -				$style->addAttributesToRender($writer);
 -			$writer->renderBeginTag('thead');
 -			$this->_header->render($writer);
 -			$writer->renderEndTag();
 -		}
 -		$writer->writeLine();
 -		if($style=$this->getViewState('TableBodyStyle',null))
 -			$style->addAttributesToRender($writer);
 -		$writer->renderBeginTag('tbody');
 -		foreach($this->getItems() as $item)
 -			$item->renderControl($writer);
 -		$writer->renderEndTag();
 -
 -		if($this->_footer && $this->_footer->getVisible())
 -		{
 -			$writer->writeLine();
 -			if($style=$this->getViewState('TableFootStyle',null))
 -				$style->addAttributesToRender($writer);
 -			$writer->renderBeginTag('tfoot');
 -			$this->_footer->render($writer);
 -			$writer->renderEndTag();
 -		}
 -
 -		$writer->writeLine();
 -		$this->renderEndTag($writer);
 -	}
 -}
 -
 -/**
 - * TDataGridItemEventParameter class
 - *
 - * TDataGridItemEventParameter encapsulates the parameter data for
 - * {@link TDataGrid::onItemCreated OnItemCreated} event of {@link TDataGrid} controls.
 - * The {@link getItem Item} property indicates the datagrid item related with the event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridItemEventParameter extends TEventParameter
 -{
 -	/**
 -	 * The TDataGridItem control responsible for the event.
 -	 * @var TDataGridItem
 -	 */
 -	private $_item=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TDataGridItem datagrid item related with the corresponding event
 -	 */
 -	public function __construct(TDataGridItem $item)
 -	{
 -		$this->_item=$item;
 -	}
 -
 -	/**
 -	 * @return TDataGridItem datagrid item related with the corresponding event
 -	 */
 -	public function getItem()
 -	{
 -		return $this->_item;
 -	}
 -}
 -
 -/**
 - * TDataGridPagerEventParameter class
 - *
 - * TDataGridPagerEventParameter encapsulates the parameter data for
 - * {@link TDataGrid::onPagerCreated OnPagerCreated} event of {@link TDataGrid} controls.
 - * The {@link getPager Pager} property indicates the datagrid pager related with the event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridPagerEventParameter extends TEventParameter
 -{
 -	/**
 -	 * The TDataGridPager control responsible for the event.
 -	 * @var TDataGridPager
 -	 */
 -	protected $_pager=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TDataGridPager datagrid pager related with the corresponding event
 -	 */
 -	public function __construct(TDataGridPager $pager)
 -	{
 -		$this->_pager=$pager;
 -	}
 -
 -	/**
 -	 * @return TDataGridPager datagrid pager related with the corresponding event
 -	 */
 -	public function getPager()
 -	{
 -		return $this->_pager;
 -	}
 -}
 -
 -/**
 - * TDataGridCommandEventParameter class
 - *
 - * TDataGridCommandEventParameter encapsulates the parameter data for
 - * {@link TDataGrid::onItemCommand ItemCommand} event of {@link TDataGrid} controls.
 - *
 - * The {@link getItem Item} property indicates the datagrid item related with the event.
 - * The {@link getCommandSource CommandSource} refers to the control that originally
 - * raises the Command event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridCommandEventParameter extends TCommandEventParameter
 -{
 -	/**
 -	 * @var TDataGridItem the TDataGridItem control responsible for the event.
 -	 */
 -	private $_item=null;
 -	/**
 -	 * @var TControl the control originally raises the <b>Command</b> event.
 -	 */
 -	private $_source=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TDataGridItem datagrid item responsible for the event
 -	 * @param TControl original event sender
 -	 * @param TCommandEventParameter original event parameter
 -	 */
 -	public function __construct($item,$source,TCommandEventParameter $param)
 -	{
 -		$this->_item=$item;
 -		$this->_source=$source;
 -		parent::__construct($param->getCommandName(),$param->getCommandParameter());
 -	}
 -
 -	/**
 -	 * @return TDataGridItem the TDataGridItem control responsible for the event.
 -	 */
 -	public function getItem()
 -	{
 -		return $this->_item;
 -	}
 -
 -	/**
 -	 * @return TControl the control originally raises the <b>Command</b> event.
 -	 */
 -	public function getCommandSource()
 -	{
 -		return $this->_source;
 -	}
 -}
 -
 -/**
 - * TDataGridSortCommandEventParameter class
 - *
 - * TDataGridSortCommandEventParameter encapsulates the parameter data for
 - * {@link TDataGrid::onSortCommand SortCommand} event of {@link TDataGrid} controls.
 - *
 - * The {@link getCommandSource CommandSource} property refers to the control
 - * that originally raises the OnCommand event, while {@link getSortExpression SortExpression}
 - * gives the sort expression carried with the sort command.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridSortCommandEventParameter extends TEventParameter
 -{
 -	/**
 -	 * @var string sort expression
 -	 */
 -	private $_sortExpression='';
 -	/**
 -	 * @var TControl original event sender
 -	 */
 -	private $_source=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TControl the control originally raises the <b>OnCommand</b> event.
 -	 * @param TDataGridCommandEventParameter command event parameter
 -	 */
 -	public function __construct($source,TDataGridCommandEventParameter $param)
 -	{
 -		$this->_source=$source;
 -		$this->_sortExpression=$param->getCommandParameter();
 -	}
 -
 -	/**
 -	 * @return TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	public function getCommandSource()
 -	{
 -		return $this->_source;
 -	}
 -
 -	/**
 -	 * @return string sort expression
 -	 */
 -	public function getSortExpression()
 -	{
 -		return $this->_sortExpression;
 -	}
 -}
 -
 -/**
 - * TDataGridPageChangedEventParameter class
 - *
 - * TDataGridPageChangedEventParameter encapsulates the parameter data for
 - * {@link TDataGrid::onPageIndexChanged PageIndexChanged} event of {@link TDataGrid} 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 <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridPageChangedEventParameter 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 <b>OnCommand</b> event.
 -	 * @param integer new page index
 -	 */
 -	public function __construct($source,$newPageIndex)
 -	{
 -		$this->_source=$source;
 -		$this->_newIndex=$newPageIndex;
 -	}
 -
 -	/**
 -	 * @return TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	public function getCommandSource()
 -	{
 -		return $this->_source;
 -	}
 -
 -	/**
 -	 * @return integer new page index
 -	 */
 -	public function getNewPageIndex()
 -	{
 -		return $this->_newIndex;
 -	}
 -}
 -
 -/**
 - * TDataGridItem class
 - *
 - * A TDataGridItem control represents an item in the {@link TDataGrid} control,
 - * such as heading section, footer section, or a data item.
 - * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}>
 - * and {@link getDataItem DataItem} properties, respectively. The type of the item
 - * is given by {@link getItemType ItemType} property. Property {@link getDataSourceIndex DataSourceIndex}
 - * gives the index of the item from the bound data source.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridItem extends TTableRow implements INamingContainer
 -{
 -	/**
 -	 * @var integer index of the data item in the Items collection of datagrid
 -	 */
 -	private $_itemIndex='';
 -	/**
 -	 * @var integer index of the item from the bound data source
 -	 */
 -	private $_dataSourceIndex=0;
 -	/**
 -	 * type of the TDataGridItem
 -	 * @var string
 -	 */
 -	private $_itemType='';
 -	/**
 -	 * value of the data item
 -	 * @var mixed
 -	 */
 -	private $_data=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param integer zero-based index of the item in the item collection of datagrid
 -	 * @param TListItemType item type
 -	 */
 -	public function __construct($itemIndex,$dataSourceIndex,$itemType)
 -	{
 -		$this->_itemIndex=$itemIndex;
 -		$this->_dataSourceIndex=$dataSourceIndex;
 -		$this->setItemType($itemType);
 -		if($itemType===TListItemType::Header)
 -			$this->setTableSection(TTableRowSection::Header);
 -		else if($itemType===TListItemType::Footer)
 -			$this->setTableSection(TTableRowSection::Footer);
 -	}
 -
 -	/**
 -	 * @return TListItemType item type.
 -	 */
 -	public function getItemType()
 -	{
 -		return $this->_itemType;
 -	}
 -
 -	/**
 -	 * @param TListItemType item type
 -	 */
 -	public function setItemType($value)
 -	{
 -		$this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType');
 -	}
 -
 -	/**
 -	 * @return integer zero-based index of the item in the item collection of datagrid
 -	 */
 -	public function getItemIndex()
 -	{
 -		return $this->_itemIndex;
 -	}
 -
 -	/**
 -	 * @return integer the index of the datagrid item from the bound data source
 -	 */
 -	public function getDataSourceIndex()
 -	{
 -		return $this->_dataSourceIndex;
 -	}
 -
 -	/**
 -	 * @return mixed data associated with the item
 -	 * @since 3.1.0
 -	 */
 -	public function getData()
 -	{
 -		return $this->_data;
 -	}
 -
 -	/**
 -	 * @param mixed data to be associated with the item
 -	 * @since 3.1.0
 -	 */
 -	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 setDataItem($value)
 -	{
 -		return $this->setData($value);
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>OnCommand</b> 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 TDataGridCommandEventParameter($this,$sender,$param));
 -			return true;
 -		}
 -		else
 -			return false;
 -	}
 -}
 -
 -
 -/**
 - * TDataGridPager class.
 - *
 - * TDataGridPager represents a datagrid pager.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridPager extends TPanel implements INamingContainer
 -{
 -	private $_dataGrid;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TDataGrid datagrid object
 -	 */
 -	public function __construct($dataGrid)
 -	{
 -		$this->_dataGrid=$dataGrid;
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>OnCommand</b> 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 TDataGridCommandEventParameter($this,$sender,$param));
 -			return true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @return TDataGrid the datagrid owning this pager
 -	 */
 -	public function getDataGrid()
 -	{
 -		return $this->_dataGrid;
 -	}
 -
 -	/**
 -	 * @return string item type.
 -	 */
 -	public function getItemType()
 -	{
 -		return TListItemType::Pager;
 -	}
 -}
 -
 -
 -/**
 - * TDataGridItemCollection class.
 - *
 - * TDataGridItemCollection represents a collection of data grid items.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridItemCollection extends TList
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by inserting only TDataGridItem.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a TDataGridItem.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TDataGridItem)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('datagriditemcollection_datagriditem_required');
 -	}
 -}
 -
 -/**
 - * TDataGridColumnCollection class.
 - *
 - * TDataGridColumnCollection represents a collection of data grid columns.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridColumnCollection extends TList
 -{
 -	/**
 -	 * the control that owns this collection.
 -	 * @var TControl
 -	 */
 -	private $_o;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TDataGrid the control that owns this collection.
 -	 */
 -	public function __construct(TDataGrid $owner)
 -	{
 -		$this->_o=$owner;
 -	}
 -
 -	/**
 -	 * @return TDataGrid the control that owns this collection.
 -	 */
 -	protected function getOwner()
 -	{
 -		return $this->_o;
 -	}
 -
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by inserting only TDataGridColumn.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a TDataGridColumn.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TDataGridColumn)
 -		{
 -			$item->setOwner($this->_o);
 -			parent::insertAt($index,$item);
 -		}
 -		else
 -			throw new TInvalidDataTypeException('datagridcolumncollection_datagridcolumn_required');
 -	}
 -}
 -
 -/**
 - * TDataGridPagerMode class.
 - * TDataGridPagerMode defines the enumerable type for the possible modes that a datagrid pager can take.
 - *
 - * The following enumerable values are defined:
 - * - NextPrev: pager buttons are displayed as next and previous pages
 - * - Numeric: pager buttons are displayed as numeric page numbers
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDataGridPagerMode extends TEnumerable
 -{
 -	const NextPrev='NextPrev';
 -	const Numeric='Numeric';
 -}
 -
 -
 -/**
 - * TDataGridPagerButtonType class.
 - * TDataGridPagerButtonType defines the enumerable type for the possible types of datagrid pager buttons.
 - *
 - * The following enumerable values are defined:
 - * - LinkButton: link buttons
 - * - PushButton: form submit buttons
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDataGridPagerButtonType extends TEnumerable
 -{
 -	const LinkButton='LinkButton';
 -	const PushButton='PushButton';
 -}
 -
 -
 -/**
 - * TDataGridPagerPosition class.
 - * TDataGridPagerPosition defines the enumerable type for the possible positions that a datagrid pager can be located at.
 - *
 - * The following enumerable values are defined:
 - * - Bottom: pager appears only at the bottom of the data grid.
 - * - Top: pager appears only at the top of the data grid.
 - * - TopAndBottom: pager appears on both top and bottom of the data grid.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDataGridPagerPosition extends TEnumerable
 -{
 -	const Bottom='Bottom';
 -	const Top='Top';
 -	const TopAndBottom='TopAndBottom';
 -}
 -
 +<?php +/** + * TDataGrid related class files. + * This file contains the definition of the following classes: + * TDataGrid, TDataGridItem, TDataGridItemCollection, TDataGridColumnCollection, + * TDataGridPagerStyle, TDataGridItemEventParameter, + * TDataGridCommandEventParameter, TDataGridSortCommandEventParameter, + * TDataGridPageChangedEventParameter + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TBaseList, TPagedDataSource, TDummyDataSource and TTable classes + */ +Prado::using('System.Web.UI.WebControls.TBaseDataList'); +Prado::using('System.Collections.TPagedDataSource'); +Prado::using('System.Collections.TDummyDataSource'); +Prado::using('System.Web.UI.WebControls.TTable'); +Prado::using('System.Web.UI.WebControls.TPanel'); +Prado::using('System.Web.UI.WebControls.TDataGridPagerStyle'); + +/** + * TDataGrid class + * + * TDataGrid represents a data bound and updatable grid control. + * + * To populate data into the datagrid, sets its {@link setDataSource DataSource} + * to a tabular data source and call {@link dataBind()}. + * Each row of data will be represented by an item in the {@link getItems Items} + * collection of the datagrid. + * + * An item can be at one of three states: browsing, selected and edit. + * The state determines how the item will be displayed. For example, if an item + * is in edit state, it may be displayed as a table row with input text boxes + * if the columns are of type {@link TBoundColumn}; and if in browsing state, + * they are displayed as static text. + * + * To change the state of an item, set {@link setEditItemIndex EditItemIndex} + * or {@link setSelectedItemIndex SelectedItemIndex} property. + * + * Each datagrid item has a {@link TDataGridItem::getItemType type} + * which tells the position and state of the item in the datalist. An item in the header + * of the repeater is of type Header. A body item may be of either + * Item, AlternatingItem, SelectedItem or EditItem, depending whether the item + * index is odd or even, whether it is being selected or edited. + * + * A datagrid is specified with a list of columns. Each column specifies how the corresponding + * table column will be displayed. For example, the header/footer text of that column, + * the cells in that column, and so on. The following column types are currently + * provided by the framework, + * - {@link TBoundColumn}, associated with a specific field in datasource and displays the corresponding data. + * - {@link TEditCommandColumn}, displaying edit/update/cancel command buttons + * - {@link TButtonColumn}, displaying generic command buttons that may be bound to specific field in datasource. + * - {@link TDropDownListColumn}, displaying a dropdown list when the item is in edit state + * - {@link THyperLinkColumn}, displaying a hyperlink that may be bound to specific field in datasource. + * - {@link TCheckBoxColumn}, displaying a checkbox that may be bound to specific field in datasource. + * - {@link TTemplateColumn}, displaying content based on templates. + * + * There are three ways to specify columns for a datagrid. + * <ul> + *  <li>Automatically generated based on data source. + *  By setting {@link setAutoGenerateColumns AutoGenerateColumns} to true, + *  a list of columns will be automatically generated based on the schema of the data source. + *  Each column corresponds to a column of the data.</li> + *  <li>Specified in template. For example, + *    <code> + *     <com:TDataGrid ...> + *        <com:TBoundColumn .../> + *        <com:TEditCommandColumn .../> + *     </com:TDataGrid> + *    </code> + *  </li> + *  <li>Manually created in code. Columns can be manipulated via + *  the {@link setColumns Columns} property of the datagrid. For example, + *  <code> + *    $column=new TBoundColumn; + *    $datagrid->Columns[]=$column; + *  </code> + *  </li> + * </ul> + * Note, automatically generated columns cannot be accessed via + * the {@link getColumns Columns} property. + * + * TDataGrid supports sorting. If the {@link setAllowSorting AllowSorting} + * is set to true, a column with nonempty {@link setSortExpression SortExpression} + * will have its header text displayed as a clickable link button. + * Clicking on the link button will raise {@link onSortCommand OnSortCommand} + * event. You can respond to this event, sort the data source according + * to the event parameter, and then invoke {@link databind()} on the datagrid + * to show to end users the sorted data. + * + * TDataGrid supports paging. If the {@link setAllowPaging AllowPaging} + * is set to true, a pager will be displayed on top and/or bottom of the table. + * How the pager will be displayed is determined by the {@link getPagerStyle PagerStyle} + * property. Clicking on a pager button will raise an {@link onPageIndexChanged OnPageIndexChanged} + * event. You can respond to this event, specify the page to be displayed by + * setting {@link setCurrentPageIndex CurrentPageIndex}</b> property, + * and then invoke {@link databind()} on the datagrid to show to end users + * a new page of data. + * + * TDataGrid supports two kinds of paging. The first one is based on the number of data items in + * datasource. The number of pages {@link getPageCount PageCount} is calculated based + * the item number and the {@link setPageSize PageSize} property. + * The datagrid will manage which section of the data source to be displayed + * based on the {@link setCurrentPageIndex CurrentPageIndex} property. + * The second approach calculates the page number based on the + * {@link setVirtualItemCount VirtualItemCount} property and + * the {@link setPageSize PageSize} property. The datagrid will always + * display from the beginning of the datasource up to the number of + * {@link setPageSize PageSize} data items. This approach is especially + * useful when the datasource may contain too many data items to be managed by + * the datagrid efficiently. + * + * When the datagrid contains a button control that raises an {@link onCommand OnCommand} + * event, the event will be bubbled up to the datagrid control. + * If the event's command name is recognizable by the datagrid control, + * a corresponding item event will be raised. The following item events will be + * raised upon a specific command: + * - OnEditCommand, if CommandName=edit + * - OnCancelCommand, if CommandName=cancel + * - OnSelectCommand, if CommandName=select + * - OnDeleteCommand, if CommandName=delete + * - OnUpdateCommand, if CommandName=update + * - onPageIndexChanged, if CommandName=page + * - OnSortCommand, if CommandName=sort + * Note, an {@link onItemCommand OnItemCommand} event is raised in addition to + * the above specific command events. + * + * TDataGrid also raises an {@link onItemCreated OnItemCreated} event for + * every newly created datagrid item. You can respond to this event to customize + * the content or style of the newly created item. + * + * Note, the data bound to the datagrid are reset to null after databinding. + * There are several ways to access the data associated with a datagrid row: + * - Access the data in {@link onItemDataBound OnItemDataBound} event + * - Use {@link getDataKeys DataKeys} to obtain the data key associated with + * the specified datagrid row 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. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGrid extends TBaseDataList implements INamingContainer +{ +	/** +	 * datagrid item types +	 * @deprecated deprecated since version 3.0.4. Use TListItemType constants instead. +	 */ +	const IT_HEADER='Header'; +	const IT_FOOTER='Footer'; +	const IT_ITEM='Item'; +	const IT_SEPARATOR='Separator'; +	const IT_ALTERNATINGITEM='AlternatingItem'; +	const IT_EDITITEM='EditItem'; +	const IT_SELECTEDITEM='SelectedItem'; +	const IT_PAGER='Pager'; + +	/** +	 * Command name that TDataGrid understands. +	 */ +	const CMD_SELECT='Select'; +	const CMD_EDIT='Edit'; +	const CMD_UPDATE='Update'; +	const CMD_DELETE='Delete'; +	const CMD_CANCEL='Cancel'; +	const CMD_SORT='Sort'; +	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 TDataGridColumnCollection manually created column collection +	 */ +	private $_columns=null; +	/** +	 * @var TDataGridColumnCollection automatically created column collection +	 */ +	private $_autoColumns=null; +	/** +	 * @var TList all columns including both manually and automatically created columns +	 */ +	private $_allColumns=null; +	/** +	 * @var TDataGridItemCollection datagrid item collection +	 */ +	private $_items=null; +	/** +	 * @var TDataGridItem header item +	 */ +	private $_header=null; +	/** +	 * @var TDataGridItem footer item +	 */ +	private $_footer=null; +	/** +	 * @var TPagedDataSource paged data source object +	 */ +	private $_pagedDataSource=null; +	private $_topPager=null; +	private $_bottomPager=null; +	/** +	 * @var ITemplate template used when empty data is bounded +	 */ +	private $_emptyTemplate=null; +	/** +	 * @var boolean whether empty template is effective +	 */ +	private $_useEmptyTemplate=false; + +	/** +	 * @return string tag name (table) of the datagrid +	 */ +	protected function getTagName() +	{ +		return 'table'; +	} + +	/** +	 * @return string Name of the class used in AutoGenerateColumns mode +	 */ +	protected function getAutoGenerateColumnName() +	{ +		return 'TBoundColumn'; +	} + +	/** +	 * Adds objects parsed in template to datagrid. +	 * Datagrid columns are added into {@link getColumns Columns} collection. +	 * @param mixed object parsed in template +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TDataGridColumn) +			$this->getColumns()->add($object); +		else +			parent::addParsedObject($object);  // this is needed by EmptyTemplate +	} + +	/** +	 * @return TDataGridColumnCollection manually specified datagrid columns +	 */ +	public function getColumns() +	{ +		if(!$this->_columns) +			$this->_columns=new TDataGridColumnCollection($this); +		return $this->_columns; +	} + +	/** +	 * @return TDataGridColumnCollection automatically generated datagrid columns +	 */ +	public function getAutoColumns() +	{ +		if(!$this->_autoColumns) +			$this->_autoColumns=new TDataGridColumnCollection($this); +		return $this->_autoColumns; +	} + +	/** +	 * @return TDataGridItemCollection datagrid item collection +	 */ +	public function getItems() +	{ +		if(!$this->_items) +			$this->_items=new TDataGridItemCollection; +		return $this->_items; +	} + +	/** +	 * @return integer number of items +	 */ +	public function getItemCount() +	{ +		return $this->_items?$this->_items->getCount():0; +	} + +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableStyle} to be used by datagrid. +	 * @return TTableStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableStyle; +	} + +	/** +	 * @return string the URL of the background image for the datagrid +	 */ +	public function getBackImageUrl() +	{ +		return $this->getStyle()->getBackImageUrl(); +	} + +	/** +	 * @param string the URL of the background image for the datagrid +	 */ +	public function setBackImageUrl($value) +	{ +		$this->getStyle()->setBackImageUrl($value); +	} + +	/** +	 * @return TTableItemStyle the style for every item +	 */ +	public function getItemStyle() +	{ +		if(($style=$this->getViewState('ItemStyle',null))===null) +		{ +			$style=new TTableItemStyle; +			$this->setViewState('ItemStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @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 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 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 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 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 TDataGridPagerStyle the style for pager +	 */ +	public function getPagerStyle() +	{ +		if(($style=$this->getViewState('PagerStyle',null))===null) +		{ +			$style=new TDataGridPagerStyle; +			$this->setViewState('PagerStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TStyle the style for thead element, if any +	 * @since 3.1.1 +	 */ +	public function getTableHeadStyle() +	{ +		if(($style=$this->getViewState('TableHeadStyle',null))===null) +		{ +			$style=new TStyle; +			$this->setViewState('TableHeadStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TStyle the style for tbody element, if any +	 * @since 3.1.1 +	 */ +	public function getTableBodyStyle() +	{ +		if(($style=$this->getViewState('TableBodyStyle',null))===null) +		{ +			$style=new TStyle; +			$this->setViewState('TableBodyStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TStyle the style for tfoot element, if any +	 * @since 3.1.1 +	 */ +	public function getTableFootStyle() +	{ +		if(($style=$this->getViewState('TableFootStyle',null))===null) +		{ +			$style=new TStyle; +			$this->setViewState('TableFootStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return string caption for the datagrid +	 */ +	public function getCaption() +	{ +		return $this->getViewState('Caption',''); +	} + +	/** +	 * @param string caption for the datagrid +	 */ +	public function setCaption($value) +	{ +		$this->setViewState('Caption',$value,''); +	} + +	/** +	 * @return TTableCaptionAlign datagrid caption alignment. Defaults to TTableCaptionAlign::NotSet. +	 */ +	public function getCaptionAlign() +	{ +		return $this->getViewState('CaptionAlign',TTableCaptionAlign::NotSet); +	} + +	/** +	 * @param TTableCaptionAlign datagrid caption alignment. Valid values include +	 */ +	public function setCaptionAlign($value) +	{ +		$this->setViewState('CaptionAlign',TPropertyValue::ensureEnum($value,'TTableCaptionAlign'),TTableCaptionAlign::NotSet); +	} + +	/** +	 * @return TDataGridItem the header item +	 */ +	public function getHeader() +	{ +		return $this->_header; +	} + +	/** +	 * @return TDataGridItem the footer item +	 */ +	public function getFooter() +	{ +		return $this->_footer; +	} + +	/** +	 * @return TDataGridPager the pager displayed at the top of datagrid. It could be null if paging is disabled. +	 */ +	public function getTopPager() +	{ +		return $this->_topPager; +	} + +	/** +	 * @return TDataGridPager the pager displayed at the bottom of datagrid. It could be null if paging is disabled. +	 */ +	public function getBottomPager() +	{ +		return $this->_bottomPager; +	} + +	/** +	 * @return TDataGridItem 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 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()!==TListItemType::EditItem) +					$item->setItemType($current%2?TListItemType::AlternatingItem:TListItemType::Item); +			} +			if($value>=0 && $value<$itemCount) +			{ +				$item=$items->itemAt($value); +				if($item->getItemType()!==TListItemType::EditItem) +					$item->setItemType(TListItemType::SelectedItem); +			} +		} +	} + +	/** +	 * @return TDataGridItem 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 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?TListItemType::AlternatingItem:TListItemType::Item); +			if($value>=0 && $value<$itemCount) +				$items->itemAt($value)->setItemType(TListItemType::EditItem); +		} +	} + +	/** +	 * @return boolean whether sorting is enabled. Defaults to false. +	 */ +	public function getAllowSorting() +	{ +		return $this->getViewState('AllowSorting',false); +	} + +	/** +	 * @param boolean whether sorting is enabled +	 */ +	public function setAllowSorting($value) +	{ +		$this->setViewState('AllowSorting',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether datagrid columns should be automatically generated. Defaults to true. +	 */ +	public function getAutoGenerateColumns() +	{ +		return $this->getViewState('AutoGenerateColumns',true); +	} + +	/** +	 * @param boolean whether datagrid columns should be automatically generated +	 */ +	public function setAutoGenerateColumns($value) +	{ +		$this->setViewState('AutoGenerateColumns',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return boolean whether the header should be displayed. Defaults to true. +	 */ +	public function getShowHeader() +	{ +		return $this->getViewState('ShowHeader',true); +	} + +	/** +	 * @param boolean whether the header should be displayed +	 */ +	public function setShowHeader($value) +	{ +		$this->setViewState('ShowHeader',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return boolean whether the footer should be displayed. Defaults to false. +	 */ +	public function getShowFooter() +	{ +		return $this->getViewState('ShowFooter',false); +	} + +	/** +	 * @param boolean whether the footer should be displayed +	 */ +	public function setShowFooter($value) +	{ +		$this->setViewState('ShowFooter',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return ITemplate the template applied when no data is bound to the datagrid +	 */ +	public function getEmptyTemplate() +	{ +		return $this->_emptyTemplate; +	} + +	/** +	 * @param ITemplate the template applied when no data is bound to the datagrid +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setEmptyTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_emptyTemplate=$value; +		else +			throw new TInvalidDataTypeException('datagrid_template_required','EmptyTemplate'); +	} + +	/** +	 * This method overrides parent's implementation to handle +	 * {@link onItemCommand OnItemCommand} event which is bubbled from +	 * {@link TDataGridItem} child controls. +	 * If the event parameter is {@link TDataGridCommandEventParameter} 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 OnEditCommand}). +	 * 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. +	 */ +	public function bubbleEvent($sender,$param) +	{ +		if($param instanceof TDataGridCommandEventParameter) +		{ +			$this->onItemCommand($param); +			$command=$param->getCommandName(); +			if(strcasecmp($command,self::CMD_SELECT)===0) +			{ +				$this->setSelectedItemIndex($param->getItem()->getItemIndex()); +				$this->onSelectedIndexChanged($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_EDIT)===0) +			{ +				$this->onEditCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_DELETE)===0) +			{ +				$this->onDeleteCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_UPDATE)===0) +			{ +				$this->onUpdateCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_CANCEL)===0) +			{ +				$this->onCancelCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_SORT)===0) +			{ +				$this->onSortCommand(new TDataGridSortCommandEventParameter($sender,$param)); +				return true; +			} +			else if(strcasecmp($command,self::CMD_PAGE)===0) +			{ +				$p=$param->getCommandParameter(); +				if(strcasecmp($p,self::CMD_PAGE_NEXT)===0) +					$pageIndex=$this->getCurrentPageIndex()+1; +				else if(strcasecmp($p,self::CMD_PAGE_PREV)===0) +					$pageIndex=$this->getCurrentPageIndex()-1; +				else if(strcasecmp($p,self::CMD_PAGE_FIRST)===0) +					$pageIndex=0; +				else if(strcasecmp($p,self::CMD_PAGE_LAST)===0) +					$pageIndex=$this->getPageCount()-1; +				else +					$pageIndex=TPropertyValue::ensureInteger($p)-1; +				$this->onPageIndexChanged(new TDataGridPageChangedEventParameter($sender,$pageIndex)); +				return true; +			} +		} +		return false; +	} + +	/** +	 * Raises <b>OnCancelCommand</b> event. +	 * This method is invoked when a button control raises <b>OnCommand</b> event +	 * with <b>cancel</b> command name. +	 * @param TDataGridCommandEventParameter event parameter +	 */ +	public function onCancelCommand($param) +	{ +		$this->raiseEvent('OnCancelCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnDeleteCommand</b> event. +	 * This method is invoked when a button control raises <b>OnCommand</b> event +	 * with <b>delete</b> command name. +	 * @param TDataGridCommandEventParameter event parameter +	 */ +	public function onDeleteCommand($param) +	{ +		$this->raiseEvent('OnDeleteCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnEditCommand</b> event. +	 * This method is invoked when a button control raises <b>OnCommand</b> event +	 * with <b>edit</b> command name. +	 * @param TDataGridCommandEventParameter event parameter +	 */ +	public function onEditCommand($param) +	{ +		$this->raiseEvent('OnEditCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnItemCommand</b> event. +	 * This method is invoked when a button control raises <b>OnCommand</b> event. +	 * @param TDataGridCommandEventParameter event parameter +	 */ +	public function onItemCommand($param) +	{ +		$this->raiseEvent('OnItemCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnSortCommand</b> event. +	 * This method is invoked when a button control raises <b>OnCommand</b> event +	 * with <b>sort</b> command name. +	 * @param TDataGridSortCommandEventParameter event parameter +	 */ +	public function onSortCommand($param) +	{ +		$this->raiseEvent('OnSortCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnUpdateCommand</b> event. +	 * This method is invoked when a button control raises <b>OnCommand</b> event +	 * with <b>update</b> command name. +	 * @param TDataGridCommandEventParameter event parameter +	 */ +	public function onUpdateCommand($param) +	{ +		$this->raiseEvent('OnUpdateCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnItemCreated</b> event. +	 * This method is invoked right after a datagrid item is created and before +	 * added to page hierarchy. +	 * @param TDataGridItemEventParameter event parameter +	 */ +	public function onItemCreated($param) +	{ +		$this->raiseEvent('OnItemCreated',$this,$param); +	} + +	/** +	 * Raises <b>OnPagerCreated</b> event. +	 * This method is invoked right after a datagrid pager is created and before +	 * added to page hierarchy. +	 * @param TDataGridPagerEventParameter event parameter +	 */ +	public function onPagerCreated($param) +	{ +		$this->raiseEvent('OnPagerCreated',$this,$param); +	} + +	/** +	 * Raises <b>OnItemDataBound</b> event. +	 * This method is invoked for each datagrid item after it performs +	 * databinding. +	 * @param TDataGridItemEventParameter event parameter +	 */ +	public function onItemDataBound($param) +	{ +		$this->raiseEvent('OnItemDataBound',$this,$param); +	} + +	/** +	 * Raises <b>OnPageIndexChanged</b> event. +	 * This method is invoked when current page is changed. +	 * @param TDataGridPageChangedEventParameter event parameter +	 */ +	public function onPageIndexChanged($param) +	{ +		$this->raiseEvent('OnPageIndexChanged',$this,$param); +	} + +	/** +	 * Saves item count in viewstate. +	 * This method is invoked right before control state is to be saved. +	 */ +	public function saveState() +	{ +		parent::saveState(); +		if(!$this->getEnableViewState(true)) +			return; +		if($this->_items) +			$this->setViewState('ItemCount',$this->_items->getCount(),0); +		else +			$this->clearViewState('ItemCount'); +		if($this->_autoColumns) +		{ +			$state=array(); +			foreach($this->_autoColumns as $column) +				$state[]=$column->saveState(); +			$this->setViewState('AutoColumns',$state,array()); +		} +		else +			$this->clearViewState('AutoColumns'); +		if($this->_columns) +		{ +			$state=array(); +			foreach($this->_columns as $column) +				$state[]=$column->saveState(); +			$this->setViewState('Columns',$state,array()); +		} +		else +			$this->clearViewState('Columns'); +	} + +	/** +	 * Loads item count information from viewstate. +	 * This method is invoked right after control state is loaded. +	 */ +	public function loadState() +	{ +		parent::loadState(); +		if(!$this->getEnableViewState(true)) +			return; +		if(!$this->getIsDataBound()) +		{ +			$state=$this->getViewState('AutoColumns',array()); +			if(!empty($state)) +			{ +				$this->_autoColumns=new TDataGridColumnCollection($this); +				foreach($state as $st) +				{ +					$column=new $this->AutoGenerateColumnName; +					$column->loadState($st); +					$this->_autoColumns->add($column); +				} +			} +			else +				$this->_autoColumns=null; +			$state=$this->getViewState('Columns',array()); +			if($this->_columns && $this->_columns->getCount()===count($state)) +			{ +				$i=0; +				foreach($this->_columns as $column) +				{ +					$column->loadState($state[$i]); +					$i++; +				} +			} +			$this->restoreGridFromViewState(); +		} +	} + +	/** +	 * Clears up all items in the datagrid. +	 */ +	public function reset() +	{ +		$this->getControls()->clear(); +		$this->getItems()->clear(); +		$this->_header=null; +		$this->_footer=null; +		$this->_topPager=null; +		$this->_bottomPager=null; +		$this->_useEmptyTemplate=false; +	} + +	/** +	 * Restores datagrid content from viewstate. +	 */ +	protected function restoreGridFromViewState() +	{ +		$this->reset(); + +		$allowPaging=$this->getAllowPaging(); + +		$itemCount=$this->getViewState('ItemCount',0); +		$dsIndex=$this->getViewState('DataSourceIndex',0); + +		$columns=new TList($this->getColumns()); +		$columns->mergeWith($this->_autoColumns); +		$this->_allColumns=$columns; + +		$items=$this->getItems(); + +		if($columns->getCount()) +		{ +			foreach($columns as $column) +				$column->initialize(); +			$selectedIndex=$this->getSelectedItemIndex(); +			$editIndex=$this->getEditItemIndex(); +			for($index=0;$index<$itemCount;++$index) +			{ +				if($index===0) +				{ +					if($allowPaging) +						$this->_topPager=$this->createPager(); +					$this->_header=$this->createItemInternal(-1,-1,TListItemType::Header,false,null,$columns); +				} +				if($index===$editIndex) +					$itemType=TListItemType::EditItem; +				else if($index===$selectedIndex) +					$itemType=TListItemType::SelectedItem; +				else if($index % 2) +					$itemType=TListItemType::AlternatingItem; +				else +					$itemType=TListItemType::Item; +				$items->add($this->createItemInternal($index,$dsIndex,$itemType,false,null,$columns)); +				$dsIndex++; +			} +			if($index>0) +			{ +				$this->_footer=$this->createItemInternal(-1,-1,TListItemType::Footer,false,null,$columns); +				if($allowPaging) +					$this->_bottomPager=$this->createPager(); +			} +		} +		if(!$dsIndex && $this->_emptyTemplate!==null) +		{ +			$this->_useEmptyTemplate=true; +			$this->_emptyTemplate->instantiateIn($this); +		} +	} + +	/** +	 * 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 +	 */ +	protected function performDataBinding($data) +	{ +		$this->reset(); +		$keys=$this->getDataKeys(); +		$keys->clear(); +		$keyField=$this->getDataKeyField(); + +		// get all columns +		if($this->getAutoGenerateColumns()) +		{ +			$columns=new TList($this->getColumns()); +			$autoColumns=$this->createAutoColumns($data); +			$columns->mergeWith($autoColumns); +		} +		else +			$columns=$this->getColumns(); +		$this->_allColumns=$columns; + +		$items=$this->getItems(); + +		$index=0; +		$allowPaging=$this->getAllowPaging() && ($data instanceof TPagedDataSource); +		$dsIndex=$allowPaging?$data->getFirstIndexInPage():0; +		$this->setViewState('DataSourceIndex',$dsIndex,0); +		if($columns->getCount()) +		{ +			foreach($columns as $column) +				$column->initialize(); + +			$selectedIndex=$this->getSelectedItemIndex(); +			$editIndex=$this->getEditItemIndex(); +			foreach($data as $key=>$row) +			{ +				if($keyField!=='') +					$keys->add($this->getDataFieldValue($row,$keyField)); +				else +					$keys->add($key); +				if($index===0) +				{ +					if($allowPaging) +						$this->_topPager=$this->createPager(); +					$this->_header=$this->createItemInternal(-1,-1,TListItemType::Header,true,null,$columns); +				} +				if($index===$editIndex) +					$itemType=TListItemType::EditItem; +				else if($index===$selectedIndex) +					$itemType=TListItemType::SelectedItem; +				else if($index % 2) +					$itemType=TListItemType::AlternatingItem; +				else +					$itemType=TListItemType::Item; +				$items->add($this->createItemInternal($index,$dsIndex,$itemType,true,$row,$columns)); +				$index++; +				$dsIndex++; +			} +			if($index>0) +			{ +				$this->_footer=$this->createItemInternal(-1,-1,TListItemType::Footer,true,null,$columns); +				if($allowPaging) +					$this->_bottomPager=$this->createPager(); +			} +		} +		$this->setViewState('ItemCount',$index,0); +		if(!$dsIndex && $this->_emptyTemplate!==null) +		{ +			$this->_useEmptyTemplate=true; +			$this->_emptyTemplate->instantiateIn($this); +			$this->dataBindChildren(); +		} +	} + +	/** +	 * Merges consecutive cells who have the same text. +	 * @since 3.1.1 +	 */ +	private function groupCells() +	{ +		if(($columns=$this->_allColumns)===null) +			return; +		$items=$this->getItems(); +		foreach($columns as $id=>$column) +		{ +			if(!$column->getEnableCellGrouping()) +				continue; +			$prevCell=null; +			$prevCellText=null; +			foreach($items as $item) +			{ +				$itemType=$item->getItemType(); +				$cell=$item->getCells()->itemAt($id); +				if(!$cell->getVisible()) +					continue; +				if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem) +				{ +					if(($cellText=$this->getCellText($cell))==='') +					{ +						$prevCell=null; +						$prevCellText=null; +						continue; +					} +					if($prevCell===null || $prevCellText!==$cellText) +					{ +						$prevCell=$cell; +						$prevCellText=$cellText; +					} +					else +					{ +						if(($rowSpan=$prevCell->getRowSpan())===0) +							$rowSpan=1; +						$prevCell->setRowSpan($rowSpan+1); +						$cell->setVisible(false); +					} +				} +			} +		} +	} + +	private function getCellText($cell) +	{ +		if(($data=$cell->getText())==='' && $cell->getHasControls()) +		{ +			$controls=$cell->getControls(); +			foreach($controls as $control) +			{ +				if($control instanceof IDataRenderer) +					return $control->getData(); +			} +		} +		return $data; +	} + +	/** +	 * Creates a datagrid item instance based on the item type and index. +	 * @param integer zero-based item index +	 * @param TListItemType item type +	 * @return TDataGridItem created data list item +	 */ +	protected function createItem($itemIndex,$dataSourceIndex,$itemType) +	{ +		return new TDataGridItem($itemIndex,$dataSourceIndex,$itemType); +	} + +	private function createItemInternal($itemIndex,$dataSourceIndex,$itemType,$dataBind,$dataItem,$columns) +	{ +		$item=$this->createItem($itemIndex,$dataSourceIndex,$itemType); +		$this->initializeItem($item,$columns); +		$param=new TDataGridItemEventParameter($item); +		if($dataBind) +		{ +			$item->setDataItem($dataItem); +			$this->onItemCreated($param); +			$this->getControls()->add($item); +			$item->dataBind(); +			$this->onItemDataBound($param); +		} +		else +		{ +			$this->onItemCreated($param); +			$this->getControls()->add($item); +		} +		return $item; +	} + +	/** +	 * Initializes a datagrid item and cells inside it +	 * @param TDataGrid datagrid item to be initialized +	 * @param TDataGridColumnCollection datagrid columns to be used to initialize the cells in the item +	 */ +	protected function initializeItem($item,$columns) +	{ +		$cells=$item->getCells(); +		$itemType=$item->getItemType(); +		$index=0; +		foreach($columns as $column) +		{ +			if($itemType===TListItemType::Header) +				$cell=new TTableHeaderCell; +			else +				$cell=new TTableCell; +			if(($id=$column->getID())!=='') +				$item->registerObject($id,$cell); +			$cells->add($cell); +			$column->initializeCell($cell,$index,$itemType); +			$index++; +		} +	} + +	protected function createPager() +	{ +		$pager=new TDataGridPager($this); +		$this->buildPager($pager); +		$this->onPagerCreated(new TDataGridPagerEventParameter($pager)); +		$this->getControls()->add($pager); +		return $pager; +	} + +	/** +	 * Builds the pager content based on pager style. +	 * @param TDataGridPager the container for the pager +	 */ +	protected function buildPager($pager) +	{ +		switch($this->getPagerStyle()->getMode()) +		{ +			case TDataGridPagerMode::NextPrev: +				$this->buildNextPrevPager($pager); +				break; +			case TDataGridPagerMode::Numeric: +				$this->buildNumericPager($pager); +				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 mixed the container pager instance of TActiveDatagridPager  +	 * @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($pager,$buttonType,$enabled,$text,$commandName,$commandParameter) +	{ +		if($buttonType===TDataGridPagerButtonType::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 TDataGridPager the container for the pager +	 */ +	protected function buildNextPrevPager($pager) +	{ +		$style=$this->getPagerStyle(); +		$buttonType=$style->getButtonType(); +		$controls=$pager->getControls(); +		$currentPageIndex=$this->getCurrentPageIndex(); +		if($currentPageIndex===0) +		{ +			if(($text=$style->getFirstPageText())!=='') +			{ +				$label=$this->createPagerButton($pager,$buttonType,false,$text,'',''); +				$controls->add($label); +				$controls->add("\n"); +			} + +			$label=$this->createPagerButton($pager,$buttonType,false,$style->getPrevPageText(),'',''); +			$controls->add($label); +		} +		else +		{ +			if(($text=$style->getFirstPageText())!=='') +			{ +				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_FIRST); +				$controls->add($button); +				$controls->add("\n"); +			} + +			$button=$this->createPagerButton($pager,$buttonType,true,$style->getPrevPageText(),self::CMD_PAGE,self::CMD_PAGE_PREV); +			$controls->add($button); +		} +		$controls->add("\n"); +		if($currentPageIndex===$this->getPageCount()-1) +		{ +			$label=$this->createPagerButton($pager,$buttonType,false,$style->getNextPageText(),'',''); +			$controls->add($label); +			if(($text=$style->getLastPageText())!=='') +			{ +				$controls->add("\n"); +				$label=$this->createPagerButton($pager,$buttonType,false,$text,'',''); +				$controls->add($label); +			} +		} +		else +		{ +			$button=$this->createPagerButton($pager,$buttonType,true,$style->getNextPageText(),self::CMD_PAGE,self::CMD_PAGE_NEXT); +			$controls->add($button); +			if(($text=$style->getLastPageText())!=='') +			{ +				$controls->add("\n"); +				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_LAST); +				$controls->add($button); +			} +		} +	} + +	/** +	 * Builds a numeric pager +	 * @param TDataGridPager the container for the pager +	 */ +	protected function buildNumericPager($pager) +	{ +		$style=$this->getPagerStyle(); +		$buttonType=$style->getButtonType(); +		$controls=$pager->getControls(); +		$pageCount=$this->getPageCount(); +		$pageIndex=$this->getCurrentPageIndex()+1; +		$maxButtonCount=$style->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=$style->getFirstPageText())!=='') +			{ +				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_FIRST); +				$controls->add($button); +				$controls->add("\n"); +			} +			$prevPageIndex=$startPageIndex-1; +			$button=$this->createPagerButton($pager,$buttonType,true,$style->getPrevPageText(),self::CMD_PAGE,"$prevPageIndex"); +			$controls->add($button); +			$controls->add("\n"); +		} + +		for($i=$startPageIndex;$i<=$endPageIndex;++$i) +		{ +			if($i===$pageIndex) +			{ +				$label=$this->createPagerButton($pager,$buttonType,false,"$i",'',''); +				$controls->add($label); +			} +			else +			{ +				$button=$this->createPagerButton($pager,$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($pager,$buttonType,true,$style->getNextPageText(),self::CMD_PAGE,"$nextPageIndex"); +			$controls->add($button); +			if(($text=$style->getLastPageText())!=='') +			{ +				$controls->add("\n"); +				$button=$this->createPagerButton($pager,$buttonType,true,$text,self::CMD_PAGE,self::CMD_PAGE_LAST); +				$controls->add($button); +			} +		} +	} + +	/** +	 * Automatically generates datagrid columns based on datasource schema +	 * @param Traversable data source bound to the datagrid +	 * @return TDataGridColumnCollection +	 */ +	protected function createAutoColumns($dataSource) +	{ +		if(!$dataSource) +			return null; +		$autoColumns=$this->getAutoColumns(); +		$autoColumns->clear(); +		foreach($dataSource as $row) +		{ +			foreach($row as $key=>$value) +			{ +				$column=new $this->AutoGenerateColumnName; +				if(is_string($key)) +				{ +					$column->setHeaderText($key); +					$column->setDataField($key); +					$column->setSortExpression($key); +					$autoColumns->add($column); +				} +				else +				{ +					$column->setHeaderText(TListItemType::Item); +					$column->setDataField($key); +					$column->setSortExpression(TListItemType::Item); +					$autoColumns->add($column); +				} +			} +			break; +		} +		return $autoColumns; +	} + +	/** +	 * Applies styles to items, header, footer and separators. +	 * Item styles are applied in a hierarchical way. Style in higher hierarchy +	 * will inherit from styles in lower hierarchy. +	 * Starting from the lowest hierarchy, the item styles include +	 * item's own style, {@link getItemStyle ItemStyle}, {@link getAlternatingItemStyle AlternatingItemStyle}, +	 * {@link getSelectedItemStyle SelectedItemStyle}, and {@link getEditItemStyle EditItemStyle}. +	 * Therefore, if background color is set as red in {@link getItemStyle ItemStyle}, +	 * {@link getEditItemStyle EditItemStyle} will also have red background color +	 * unless it is set to a different value explicitly. +	 */ +	protected function applyItemStyles() +	{ +		$itemStyle=$this->getViewState('ItemStyle',null); + +		$alternatingItemStyle=$this->getViewState('AlternatingItemStyle',null); +		if($itemStyle!==null) +		{ +			if($alternatingItemStyle===null) +				$alternatingItemStyle=$itemStyle; +			else +				$alternatingItemStyle->mergeWith($itemStyle); +		} + +		$selectedItemStyle=$this->getViewState('SelectedItemStyle',null); + +		$editItemStyle=$this->getViewState('EditItemStyle',null); +		if($selectedItemStyle!==null) +		{ +			if($editItemStyle===null) +				$editItemStyle=$selectedItemStyle; +			else +				$editItemStyle->mergeWith($selectedItemStyle); +		} + +		$headerStyle=$this->getViewState('HeaderStyle',null); +		$footerStyle=$this->getViewState('FooterStyle',null); +		$pagerStyle=$this->getViewState('PagerStyle',null); +		$separatorStyle=$this->getViewState('SeparatorStyle',null); + +		foreach($this->getControls() as $index=>$item) +		{ +			if(!($item instanceof TDataGridItem) && !($item instanceof TDataGridPager)) +				continue; +			$itemType=$item->getItemType(); +			switch($itemType) +			{ +				case TListItemType::Header: +					if($headerStyle) +						$item->getStyle()->mergeWith($headerStyle); +					if(!$this->getShowHeader()) +						$item->setVisible(false); +					break; +				case TListItemType::Footer: +					if($footerStyle) +						$item->getStyle()->mergeWith($footerStyle); +					if(!$this->getShowFooter()) +						$item->setVisible(false); +					break; +				case TListItemType::Separator: +					if($separatorStyle) +						$item->getStyle()->mergeWith($separatorStyle); +					break; +				case TListItemType::Item: +					if($itemStyle) +						$item->getStyle()->mergeWith($itemStyle); +					break; +				case TListItemType::AlternatingItem: +					if($alternatingItemStyle) +						$item->getStyle()->mergeWith($alternatingItemStyle); +					break; +				case TListItemType::SelectedItem: +					if($selectedItemStyle) +						$item->getStyle()->mergeWith($selectedItemStyle); +					if($index % 2==1) +					{ +						if($itemStyle) +							$item->getStyle()->mergeWith($itemStyle); +					} +					else +					{ +						if($alternatingItemStyle) +							$item->getStyle()->mergeWith($alternatingItemStyle); +					} +					break; +				case TListItemType::EditItem: +					if($editItemStyle) +						$item->getStyle()->mergeWith($editItemStyle); +					if($index % 2==1) +					{ +						if($itemStyle) +							$item->getStyle()->mergeWith($itemStyle); +					} +					else +					{ +						if($alternatingItemStyle) +							$item->getStyle()->mergeWith($alternatingItemStyle); +					} +					break; +				case TListItemType::Pager: +					if($pagerStyle) +					{ +						$item->getStyle()->mergeWith($pagerStyle); +						if($index===0) +						{ +							if($pagerStyle->getPosition()===TDataGridPagerPosition::Bottom || !$pagerStyle->getVisible()) +								$item->setVisible(false); +						} +						else +						{ +							if($pagerStyle->getPosition()===TDataGridPagerPosition::Top || !$pagerStyle->getVisible()) +								$item->setVisible(false); +						} +					} +					break; +				default: +					break; +			} +			if($this->_columns && $itemType!==TListItemType::Pager) +			{ +				$n=$this->_columns->getCount(); +				$cells=$item->getCells(); +				for($i=0;$i<$n;++$i) +				{ +					$cell=$cells->itemAt($i); +					$column=$this->_columns->itemAt($i); +					if(!$column->getVisible()) +						$cell->setVisible(false); +					else +					{ +						if($itemType===TListItemType::Header) +							$style=$column->getHeaderStyle(false); +						else if($itemType===TListItemType::Footer) +							$style=$column->getFooterStyle(false); +						else +							$style=$column->getItemStyle(false); +						if($style!==null) +							$cell->getStyle()->mergeWith($style); +					} +				} +			} +		} +	} + +	/** +	 * Renders the openning tag for the datagrid control which will render table caption if present. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderBeginTag($writer) +	{ +		parent::renderBeginTag($writer); +		if(($caption=$this->getCaption())!=='') +		{ +			if(($align=$this->getCaptionAlign())!==TTableCaptionAlign::NotSet) +				$writer->addAttribute('align',strtolower($align)); +			$writer->renderBeginTag('caption'); +			$writer->write($caption); +			$writer->renderEndTag(); +		} +	} + +	/** +	 * Renders the datagrid. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function render($writer) +	{ +		if($this->getHasControls()) +		{ +			$this->groupCells(); +			if($this->_useEmptyTemplate) +			{ +				$control=new TWebControl; +				$control->setID($this->getClientID()); +				$control->copyBaseAttributes($this); +				if($this->getHasStyle()) +					$control->getStyle()->copyFrom($this->getStyle()); +				$control->renderBeginTag($writer); +				$this->renderContents($writer); +				$control->renderEndTag($writer); +			} +			else if($this->getViewState('ItemCount',0)>0) +			{ +				$this->applyItemStyles(); +				if($this->_topPager) +				{ +					$this->_topPager->renderControl($writer); +					$writer->writeLine(); +				} +				$this->renderTable($writer); +				if($this->_bottomPager) +				{ +					$writer->writeLine(); +					$this->_bottomPager->renderControl($writer); +				} +			} +		} +	} + +	/** +	 * Renders the tabular data. +	 * @param THtmlWriter writer +	 */ +	protected function renderTable($writer) +	{ +		$this->renderBeginTag($writer); +		if($this->_header && $this->_header->getVisible()) +		{ +			$writer->writeLine(); +			if($style=$this->getViewState('TableHeadStyle',null)) +				$style->addAttributesToRender($writer); +			$writer->renderBeginTag('thead'); +			$this->_header->render($writer); +			$writer->renderEndTag(); +		} +		$writer->writeLine(); +		if($style=$this->getViewState('TableBodyStyle',null)) +			$style->addAttributesToRender($writer); +		$writer->renderBeginTag('tbody'); +		foreach($this->getItems() as $item) +			$item->renderControl($writer); +		$writer->renderEndTag(); + +		if($this->_footer && $this->_footer->getVisible()) +		{ +			$writer->writeLine(); +			if($style=$this->getViewState('TableFootStyle',null)) +				$style->addAttributesToRender($writer); +			$writer->renderBeginTag('tfoot'); +			$this->_footer->render($writer); +			$writer->renderEndTag(); +		} + +		$writer->writeLine(); +		$this->renderEndTag($writer); +	} +} + +/** + * TDataGridItemEventParameter class + * + * TDataGridItemEventParameter encapsulates the parameter data for + * {@link TDataGrid::onItemCreated OnItemCreated} event of {@link TDataGrid} controls. + * The {@link getItem Item} property indicates the datagrid item related with the event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridItemEventParameter extends TEventParameter +{ +	/** +	 * The TDataGridItem control responsible for the event. +	 * @var TDataGridItem +	 */ +	private $_item=null; + +	/** +	 * Constructor. +	 * @param TDataGridItem datagrid item related with the corresponding event +	 */ +	public function __construct(TDataGridItem $item) +	{ +		$this->_item=$item; +	} + +	/** +	 * @return TDataGridItem datagrid item related with the corresponding event +	 */ +	public function getItem() +	{ +		return $this->_item; +	} +} + +/** + * TDataGridPagerEventParameter class + * + * TDataGridPagerEventParameter encapsulates the parameter data for + * {@link TDataGrid::onPagerCreated OnPagerCreated} event of {@link TDataGrid} controls. + * The {@link getPager Pager} property indicates the datagrid pager related with the event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridPagerEventParameter extends TEventParameter +{ +	/** +	 * The TDataGridPager control responsible for the event. +	 * @var TDataGridPager +	 */ +	protected $_pager=null; + +	/** +	 * Constructor. +	 * @param TDataGridPager datagrid pager related with the corresponding event +	 */ +	public function __construct(TDataGridPager $pager) +	{ +		$this->_pager=$pager; +	} + +	/** +	 * @return TDataGridPager datagrid pager related with the corresponding event +	 */ +	public function getPager() +	{ +		return $this->_pager; +	} +} + +/** + * TDataGridCommandEventParameter class + * + * TDataGridCommandEventParameter encapsulates the parameter data for + * {@link TDataGrid::onItemCommand ItemCommand} event of {@link TDataGrid} controls. + * + * The {@link getItem Item} property indicates the datagrid item related with the event. + * The {@link getCommandSource CommandSource} refers to the control that originally + * raises the Command event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridCommandEventParameter extends TCommandEventParameter +{ +	/** +	 * @var TDataGridItem the TDataGridItem control responsible for the event. +	 */ +	private $_item=null; +	/** +	 * @var TControl the control originally raises the <b>Command</b> event. +	 */ +	private $_source=null; + +	/** +	 * Constructor. +	 * @param TDataGridItem datagrid item responsible for the event +	 * @param TControl original event sender +	 * @param TCommandEventParameter original event parameter +	 */ +	public function __construct($item,$source,TCommandEventParameter $param) +	{ +		$this->_item=$item; +		$this->_source=$source; +		parent::__construct($param->getCommandName(),$param->getCommandParameter()); +	} + +	/** +	 * @return TDataGridItem the TDataGridItem control responsible for the event. +	 */ +	public function getItem() +	{ +		return $this->_item; +	} + +	/** +	 * @return TControl the control originally raises the <b>Command</b> event. +	 */ +	public function getCommandSource() +	{ +		return $this->_source; +	} +} + +/** + * TDataGridSortCommandEventParameter class + * + * TDataGridSortCommandEventParameter encapsulates the parameter data for + * {@link TDataGrid::onSortCommand SortCommand} event of {@link TDataGrid} controls. + * + * The {@link getCommandSource CommandSource} property refers to the control + * that originally raises the OnCommand event, while {@link getSortExpression SortExpression} + * gives the sort expression carried with the sort command. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridSortCommandEventParameter extends TEventParameter +{ +	/** +	 * @var string sort expression +	 */ +	private $_sortExpression=''; +	/** +	 * @var TControl original event sender +	 */ +	private $_source=null; + +	/** +	 * Constructor. +	 * @param TControl the control originally raises the <b>OnCommand</b> event. +	 * @param TDataGridCommandEventParameter command event parameter +	 */ +	public function __construct($source,TDataGridCommandEventParameter $param) +	{ +		$this->_source=$source; +		$this->_sortExpression=$param->getCommandParameter(); +	} + +	/** +	 * @return TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	public function getCommandSource() +	{ +		return $this->_source; +	} + +	/** +	 * @return string sort expression +	 */ +	public function getSortExpression() +	{ +		return $this->_sortExpression; +	} +} + +/** + * TDataGridPageChangedEventParameter class + * + * TDataGridPageChangedEventParameter encapsulates the parameter data for + * {@link TDataGrid::onPageIndexChanged PageIndexChanged} event of {@link TDataGrid} 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 <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridPageChangedEventParameter 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 <b>OnCommand</b> event. +	 * @param integer new page index +	 */ +	public function __construct($source,$newPageIndex) +	{ +		$this->_source=$source; +		$this->_newIndex=$newPageIndex; +	} + +	/** +	 * @return TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	public function getCommandSource() +	{ +		return $this->_source; +	} + +	/** +	 * @return integer new page index +	 */ +	public function getNewPageIndex() +	{ +		return $this->_newIndex; +	} +} + +/** + * TDataGridItem class + * + * A TDataGridItem control represents an item in the {@link TDataGrid} control, + * such as heading section, footer section, or a data item. + * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}> + * and {@link getDataItem DataItem} properties, respectively. The type of the item + * is given by {@link getItemType ItemType} property. Property {@link getDataSourceIndex DataSourceIndex} + * gives the index of the item from the bound data source. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridItem extends TTableRow implements INamingContainer +{ +	/** +	 * @var integer index of the data item in the Items collection of datagrid +	 */ +	private $_itemIndex=''; +	/** +	 * @var integer index of the item from the bound data source +	 */ +	private $_dataSourceIndex=0; +	/** +	 * type of the TDataGridItem +	 * @var string +	 */ +	private $_itemType=''; +	/** +	 * value of the data item +	 * @var mixed +	 */ +	private $_data=null; + +	/** +	 * Constructor. +	 * @param integer zero-based index of the item in the item collection of datagrid +	 * @param TListItemType item type +	 */ +	public function __construct($itemIndex,$dataSourceIndex,$itemType) +	{ +		$this->_itemIndex=$itemIndex; +		$this->_dataSourceIndex=$dataSourceIndex; +		$this->setItemType($itemType); +		if($itemType===TListItemType::Header) +			$this->setTableSection(TTableRowSection::Header); +		else if($itemType===TListItemType::Footer) +			$this->setTableSection(TTableRowSection::Footer); +	} + +	/** +	 * @return TListItemType item type. +	 */ +	public function getItemType() +	{ +		return $this->_itemType; +	} + +	/** +	 * @param TListItemType item type +	 */ +	public function setItemType($value) +	{ +		$this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType'); +	} + +	/** +	 * @return integer zero-based index of the item in the item collection of datagrid +	 */ +	public function getItemIndex() +	{ +		return $this->_itemIndex; +	} + +	/** +	 * @return integer the index of the datagrid item from the bound data source +	 */ +	public function getDataSourceIndex() +	{ +		return $this->_dataSourceIndex; +	} + +	/** +	 * @return mixed data associated with the item +	 * @since 3.1.0 +	 */ +	public function getData() +	{ +		return $this->_data; +	} + +	/** +	 * @param mixed data to be associated with the item +	 * @since 3.1.0 +	 */ +	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 setDataItem($value) +	{ +		return $this->setData($value); +	} + +	/** +	 * This method overrides parent's implementation by wrapping event parameter +	 * for <b>OnCommand</b> 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 TDataGridCommandEventParameter($this,$sender,$param)); +			return true; +		} +		else +			return false; +	} +} + + +/** + * TDataGridPager class. + * + * TDataGridPager represents a datagrid pager. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridPager extends TPanel implements INamingContainer +{ +	private $_dataGrid; + +	/** +	 * Constructor. +	 * @param TDataGrid datagrid object +	 */ +	public function __construct($dataGrid) +	{ +		$this->_dataGrid=$dataGrid; +	} + +	/** +	 * This method overrides parent's implementation by wrapping event parameter +	 * for <b>OnCommand</b> 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 TDataGridCommandEventParameter($this,$sender,$param)); +			return true; +		} +		else +			return false; +	} + +	/** +	 * @return TDataGrid the datagrid owning this pager +	 */ +	public function getDataGrid() +	{ +		return $this->_dataGrid; +	} + +	/** +	 * @return string item type. +	 */ +	public function getItemType() +	{ +		return TListItemType::Pager; +	} +} + + +/** + * TDataGridItemCollection class. + * + * TDataGridItemCollection represents a collection of data grid items. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridItemCollection extends TList +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by inserting only TDataGridItem. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a TDataGridItem. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TDataGridItem) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('datagriditemcollection_datagriditem_required'); +	} +} + +/** + * TDataGridColumnCollection class. + * + * TDataGridColumnCollection represents a collection of data grid columns. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridColumnCollection extends TList +{ +	/** +	 * the control that owns this collection. +	 * @var TControl +	 */ +	private $_o; + +	/** +	 * Constructor. +	 * @param TDataGrid the control that owns this collection. +	 */ +	public function __construct(TDataGrid $owner) +	{ +		$this->_o=$owner; +	} + +	/** +	 * @return TDataGrid the control that owns this collection. +	 */ +	protected function getOwner() +	{ +		return $this->_o; +	} + +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by inserting only TDataGridColumn. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a TDataGridColumn. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TDataGridColumn) +		{ +			$item->setOwner($this->_o); +			parent::insertAt($index,$item); +		} +		else +			throw new TInvalidDataTypeException('datagridcolumncollection_datagridcolumn_required'); +	} +} + +/** + * TDataGridPagerMode class. + * TDataGridPagerMode defines the enumerable type for the possible modes that a datagrid pager can take. + * + * The following enumerable values are defined: + * - NextPrev: pager buttons are displayed as next and previous pages + * - Numeric: pager buttons are displayed as numeric page numbers + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDataGridPagerMode extends TEnumerable +{ +	const NextPrev='NextPrev'; +	const Numeric='Numeric'; +} + + +/** + * TDataGridPagerButtonType class. + * TDataGridPagerButtonType defines the enumerable type for the possible types of datagrid pager buttons. + * + * The following enumerable values are defined: + * - LinkButton: link buttons + * - PushButton: form submit buttons + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDataGridPagerButtonType extends TEnumerable +{ +	const LinkButton='LinkButton'; +	const PushButton='PushButton'; +} + + +/** + * TDataGridPagerPosition class. + * TDataGridPagerPosition defines the enumerable type for the possible positions that a datagrid pager can be located at. + * + * The following enumerable values are defined: + * - Bottom: pager appears only at the bottom of the data grid. + * - Top: pager appears only at the top of the data grid. + * - TopAndBottom: pager appears on both top and bottom of the data grid. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDataGridPagerPosition extends TEnumerable +{ +	const Bottom='Bottom'; +	const Top='Top'; +	const TopAndBottom='TopAndBottom'; +} + diff --git a/framework/Web/UI/WebControls/TDataGridColumn.php b/framework/Web/UI/WebControls/TDataGridColumn.php index d37fbc40..4794fbf8 100644 --- a/framework/Web/UI/WebControls/TDataGridColumn.php +++ b/framework/Web/UI/WebControls/TDataGridColumn.php @@ -1,567 +1,567 @@ -<?php
 -/**
 - * TDataGridColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Util.TDataFieldAccessor');
 -Prado::using('System.Web.UI.WebControls.TDataGrid');
 -
 -/**
 - * TDataGridColumn class
 - *
 - * TDataGridColumn serves as the base class for the different column types of
 - * the {@link TDataGrid} control.
 - * TDataGridColumn defines the properties and methods that are common among
 - * all datagrid column types. In particular, it initializes header and footer
 - * cells according to {@link setHeaderText HeaderText} and {@link getHeaderStyle HeaderStyle}
 - * {@link setFooterText FooterText} and {@link getFooterStyle FooterStyle} properties.
 - * If {@link setHeaderImageUrl HeaderImageUrl} is specified, the image
 - * will be displayed instead in the header cell.
 - * The {@link getItemStyle ItemStyle} is applied to cells that belong to
 - * non-header and -footer datagrid items.
 - *
 - * When the datagrid enables sorting, if the {@link setSortExpression SortExpression}
 - * is not empty, the header cell will display a button (linkbutton or imagebutton)
 - * that will bubble the sort command event to the datagrid.
 - *
 - * Since v3.1.0, TDataGridColumn has introduced two new properties {@link setHeaderRenderer HeaderRenderer}
 - * and {@link setFooterRenderer FooterRenderer} which can be used to specify
 - * the layout of header and footer column cells.
 - * A renderer refers to a control class that is to be instantiated as a control.
 - * For more details, see {@link TRepeater} and {@link TDataList}.
 - *
 - * Since v3.1.1, TDataGridColumn has introduced {@link setEnableCellGrouping EnableCellGrouping}.
 - * If a column has this property set true, consecutive cells having the same content in this
 - * column will be grouped into one cell.
 - * Note, there are some limitations to cell grouping. We determine the cell content according to
 - * the cell's {@link TTableCell::getText Text} property. If the text is empty and the cell has
 - * some child controls, we will pick up the first control who implements {@link IDataRenderer}
 - * and obtain its {@link IDataRenderer::getData Data} property.
 - *
 - * The following datagrid column types are provided by the framework currently,
 - * - {@link TBoundColumn}, associated with a specific field in datasource and displays the corresponding data.
 - * - {@link TEditCommandColumn}, displaying edit/update/cancel command buttons
 - * - {@link TDropDownListColumn}, displaying a dropdown list when the item is in edit state
 - * - {@link TButtonColumn}, displaying generic command buttons that may be bound to specific field in datasource.
 - * - {@link THyperLinkColumn}, displaying a hyperlink that may be bound to specific field in datasource.
 - * - {@link TCheckBoxColumn}, displaying a checkbox that may be bound to specific field in datasource.
 - * - {@link TTemplateColumn}, displaying content based on templates.
 - *
 - * To create your own column class, simply override {@link initializeCell()} method,
 - * which is the major logic for managing the data and presentation of cells in the column.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class TDataGridColumn extends TApplicationComponent
 -{
 -	private $_id='';
 -	private $_owner=null;
 -	private $_viewState=array();
 -
 -	/**
 -	 * @return string the ID of the column.
 -	 */
 -	public function getID()
 -	{
 -		return $this->_id;
 -	}
 -
 -	/**
 -	 * Sets the ID of the column.
 -	 * By explicitly specifying the column ID, one can access the column
 -	 * by $templateControl->ColumnID.
 -	 * @param string the ID of the column.
 -	 * @throws TInvalidDataValueException if the ID is of bad format
 -	 */
 -	public function setID($value)
 -	{
 -		if(!preg_match(TControl::ID_FORMAT,$value))
 -			throw new TInvalidDataValueException('datagridcolumn_id_invalid',get_class($this),$value);
 -		$this->_id=$value;
 -	}
 -
 -	/**
 -	 * @return string the text to be displayed in the header of this column
 -	 */
 -	public function getHeaderText()
 -	{
 -		return $this->getViewState('HeaderText','');
 -	}
 -
 -	/**
 -	 * @param string text to be displayed in the header of this column
 -	 */
 -	public function setHeaderText($value)
 -	{
 -		$this->setViewState('HeaderText',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the url of the image to be displayed in header
 -	 */
 -	public function getHeaderImageUrl()
 -	{
 -		return $this->getViewState('HeaderImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the url of the image to be displayed in header
 -	 */
 -	public function setHeaderImageUrl($value)
 -	{
 -		$this->setViewState('HeaderImageUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for the column header cell renderer. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getHeaderRenderer()
 -	{
 -		return $this->getViewState('HeaderRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the column header cell renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as a child control in the column header cell.
 -	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property
 -	 * will be set as the {@link getFooterText FooterText}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @since 3.1.0
 -	 */
 -	public function setHeaderRenderer($value)
 -	{
 -		$this->setViewState('HeaderRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @param boolean whether to create a style if previously not existing
 -	 * @return TTableItemStyle the style for header
 -	 */
 -	public function getHeaderStyle($createStyle=true)
 -	{
 -		if(($style=$this->getViewState('HeaderStyle',null))===null && $createStyle)
 -		{
 -			$style=new TTableItemStyle;
 -			$this->setViewState('HeaderStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return string the text to be displayed in the footer of this column
 -	 */
 -	public function getFooterText()
 -	{
 -		return $this->getViewState('FooterText','');
 -	}
 -
 -	/**
 -	 * @param string text to be displayed in the footer of this column
 -	 */
 -	public function setFooterText($value)
 -	{
 -		$this->setViewState('FooterText',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for the column footer cell renderer. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getFooterRenderer()
 -	{
 -		return $this->getViewState('FooterRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the column footer cell renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as a child control in the column footer cell.
 -	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property
 -	 * will be set as the {@link getFooterText FooterText}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @since 3.1.0
 -	 */
 -	public function setFooterRenderer($value)
 -	{
 -		$this->setViewState('FooterRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @param boolean whether to create a style if previously not existing
 -	 * @return TTableItemStyle the style for footer
 -	 */
 -	public function getFooterStyle($createStyle=true)
 -	{
 -		if(($style=$this->getViewState('FooterStyle',null))===null && $createStyle)
 -		{
 -			$style=new TTableItemStyle;
 -			$this->setViewState('FooterStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @param boolean whether to create a style if previously not existing
 -	 * @return TTableItemStyle the style for item
 -	 */
 -	public function getItemStyle($createStyle=true)
 -	{
 -		if(($style=$this->getViewState('ItemStyle',null))===null && $createStyle)
 -		{
 -			$style=new TTableItemStyle;
 -			$this->setViewState('ItemStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return string the name of the field or expression for sorting
 -	 */
 -	public function getSortExpression()
 -	{
 -		return $this->getViewState('SortExpression','');
 -	}
 -
 -	/**
 -	 * @param string the name of the field or expression for sorting
 -	 */
 -	public function setSortExpression($value)
 -	{
 -		$this->setViewState('SortExpression',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether cells having the same content should be grouped together. Defaults to false.
 -	 * @since 3.1.1
 -	 */
 -	public function getEnableCellGrouping()
 -	{
 -		return $this->getViewState('EnableCellGrouping',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether cells having the same content should be grouped together.
 -	 * @since 3.1.1
 -	 */
 -	public function setEnableCellGrouping($value)
 -	{
 -		$this->setViewState('EnableCellGrouping',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether the column is visible. Defaults to true.
 -	 */
 -	public function getVisible($checkParents=true)
 -	{
 -		return $this->getViewState('Visible',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether the column is visible
 -	 */
 -	public function setVisible($value)
 -	{
 -		$this->setViewState('Visible',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Returns a viewstate value.
 -	 *
 -	 * @param string the name of the viewstate value to be returned
 -	 * @param mixed the default value. If $key is not found in viewstate, $defaultValue will be returned
 -	 * @return mixed the viewstate value corresponding to $key
 -	 */
 -	protected function getViewState($key,$defaultValue=null)
 -	{
 -		return isset($this->_viewState[$key])?$this->_viewState[$key]:$defaultValue;
 -	}
 -
 -	/**
 -	 * Sets a viewstate value.
 -	 *
 -	 * Make sure that the viewstate value must be serializable and unserializable.
 -	 * @param string the name of the viewstate value
 -	 * @param mixed the viewstate value to be set
 -	 * @param mixed default value. If $value===$defaultValue, the item will be cleared from the viewstate.
 -	 */
 -	protected function setViewState($key,$value,$defaultValue=null)
 -	{
 -		if($value===$defaultValue)
 -			unset($this->_viewState[$key]);
 -		else
 -			$this->_viewState[$key]=$value;
 -	}
 -
 -	/**
 -	 * Loads persistent state values.
 -	 * @param mixed state values
 -	 */
 -	public function loadState($state)
 -	{
 -		$this->_viewState=$state;
 -	}
 -
 -	/**
 -	 * Saves persistent state values.
 -	 * @return mixed values to be saved
 -	 */
 -	public function saveState()
 -	{
 -		return $this->_viewState;
 -	}
 -
 -	/**
 -	 * @return TDataGrid datagrid that owns this column
 -	 */
 -	public function getOwner()
 -	{
 -		return $this->_owner;
 -	}
 -
 -	/**
 -	 * @param TDataGrid datagrid object that owns this column
 -	 */
 -	public function setOwner(TDataGrid $value)
 -	{
 -		$this->_owner=$value;
 -	}
 -
 -	/**
 -	 * Initializes the column.
 -	 * This method is invoked by {@link TDataGrid} when the column
 -	 * is about to be used to initialize datagrid items.
 -	 * Derived classes may override this method to do additional initialization.
 -	 */
 -	public function initialize()
 -	{
 -	}
 -
 -	/**
 -	 * Fetches the value of the data at the specified field.
 -	 * If the data is an array, the field is used as an array key.
 -	 * If the data is an of {@link TMap}, {@link TList} or their derived class,
 -	 * the field is used as a key value.
 -	 * If the data is a component, the field is used as the name of a property.
 -	 * @param mixed data containing the field of value
 -	 * @param string the data field
 -	 * @return mixed data value at the specified field
 -	 * @throws TInvalidDataValueException if the data or the field is invalid.
 -	 */
 -	protected function getDataFieldValue($data,$field)
 -	{
 -		return TDataFieldAccessor::getDataFieldValue($data,$field);
 -	}
 -
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * The default implementation sets the content of header and footer cells.
 -	 * If sorting is enabled by the grid and sort expression is specified in the column,
 -	 * the header cell will show a link/image button. Otherwise, the header/footer cell
 -	 * will only show static text/image.
 -	 * This method can be overriden to provide customized intialization to column cells.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Header)
 -			$this->initializeHeaderCell($cell,$columnIndex);
 -		else if($itemType===TListItemType::Footer)
 -			$this->initializeFooterCell($cell,$columnIndex);
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether this column allows sorting.
 -	 * The column allows sorting only when {@link getSortExpression SortExpression}
 -	 * is not empty and the datagrid allows sorting.
 -	 * @return boolean whether this column allows sorting
 -	 */
 -	public function getAllowSorting()
 -	{
 -		return $this->getSortExpression()!=='' && (!$this->_owner || $this->_owner->getAllowSorting());
 -	}
 -
 -	/**
 -	 * Initializes the header cell.
 -	 *
 -	 * This method attempts to use {@link getHeaderRenderer HeaderRenderer} to
 -	 * instantiate the header cell. If that is not available, it will populate
 -	 * the cell with an image or a text string, depending on {@link getHeaderImageUrl HeaderImageUrl}
 -	 * and {@link getHeaderText HeaderText} property values.
 -	 *
 -	 * If the column allows sorting, image or text will be created as
 -	 * a button which issues <b>Sort</b> command upon user click.
 -	 *
 -	 * @param TTableCell the cell to be initialized
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 */
 -	protected function initializeHeaderCell($cell,$columnIndex)
 -	{
 -		$text=$this->getHeaderText();
 -
 -		if(($classPath=$this->getHeaderRenderer())!=='')
 -		{
 -			$control=Prado::createComponent($classPath);
 -			$cell->getControls()->add($control);
 -			if($control instanceof IDataRenderer)
 -			{
 -				if($control instanceof IItemDataRenderer)
 -				{
 -					$item=$cell->getParent();
 -					$control->setItemIndex($item->getItemIndex());
 -					$control->setItemType($item->getItemType());
 -				}
 -				$control->setData($text);
 -			}
 -		}
 -		else if($this->getAllowSorting())
 -		{
 -			$sortExpression=$this->getSortExpression();
 -			if(($url=$this->getHeaderImageUrl())!=='')
 -			{
 -				$button=Prado::createComponent('System.Web.UI.WebControls.TImageButton');
 -				$button->setImageUrl($url);
 -				$button->setCommandName(TDataGrid::CMD_SORT);
 -				$button->setCommandParameter($sortExpression);
 -				if($text!=='')
 -					$button->setAlternateText($text);
 -				$button->setCausesValidation(false);
 -				$cell->getControls()->add($button);
 -			}
 -			else if($text!=='')
 -			{
 -				$button=Prado::createComponent('System.Web.UI.WebControls.TLinkButton');
 -				$button->setText($text);
 -				$button->setCommandName(TDataGrid::CMD_SORT);
 -				$button->setCommandParameter($sortExpression);
 -				$button->setCausesValidation(false);
 -				$cell->getControls()->add($button);
 -			}
 -			else
 -				$cell->setText(' ');
 -		}
 -		else
 -		{
 -			if(($url=$this->getHeaderImageUrl())!=='')
 -			{
 -				$image=Prado::createComponent('System.Web.UI.WebControls.TImage');
 -				$image->setImageUrl($url);
 -				if($text!=='')
 -					$image->setAlternateText($text);
 -				$cell->getControls()->add($image);
 -			}
 -			else if($text!=='')
 -				$cell->setText($text);
 -			else
 -				$cell->setText(' ');
 -		}
 -	}
 -
 -	/**
 -	 * Initializes the footer cell.
 -	 *
 -	 * This method attempts to use {@link getFooterRenderer FooterRenderer} to
 -	 * instantiate the footer cell. If that is not available, it will populate
 -	 * the cell with a text string specified by {@link getFooterImageUrl FooterImageUrl}
 -	 *
 -	 * @param TTableCell the cell to be initialized
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 */
 -	protected function initializeFooterCell($cell,$columnIndex)
 -	{
 -		$text=$this->getFooterText();
 -		if(($classPath=$this->getFooterRenderer())!=='')
 -		{
 -			$control=Prado::createComponent($classPath);
 -			$cell->getControls()->add($control);
 -			if($control instanceof IDataRenderer)
 -			{
 -				if($control instanceof IItemDataRenderer)
 -				{
 -					$item=$cell->getParent();
 -					$control->setItemIndex($item->getItemIndex());
 -					$control->setItemType($item->getItemType());
 -				}
 -				$control->setData($text);
 -			}
 -		}
 -		else if($text!=='')
 -			$cell->setText($text);
 -		else
 -			$cell->setText(' ');
 -	}
 -
 -	/**
 -	 * Formats the text value according to a format string.
 -	 * If the format string is empty, the original value is converted into
 -	 * a string and returned.
 -	 * If the format string starts with '#', the string is treated as a PHP expression
 -	 * within which the token '{0}' is translated with the data value to be formated.
 -	 * Otherwise, the format string and the data value are passed
 -	 * as the first and second parameters in {@link sprintf}.
 -	 * @param string format string
 -	 * @param mixed the data to be formatted
 -	 * @return string the formatted result
 -	 */
 -	protected function formatDataValue($formatString,$value)
 -	{
 -		if($formatString==='')
 -			return TPropertyValue::ensureString($value);
 -		else if($formatString[0]==='#')
 -		{
 -			$expression=strtr(substr($formatString,1),array('{0}'=>'$value'));
 -			try
 -			{
 -				if(eval("\$result=$expression;")===false)
 -					throw new Exception('');
 -				return $result;
 -			}
 -			catch(Exception $e)
 -			{
 -				throw new TInvalidDataValueException('datagridcolumn_expression_invalid',get_class($this),$expression,$e->getMessage());
 -			}
 -		}
 -		else
 -			return sprintf($formatString,$value);
 -	}
 -}
 -
 -
 -/**
 - * TButtonColumnType class.
 - * TButtonColumnType defines the enumerable type for the possible types of buttons
 - * that can be used in a {@link TButtonColumn}.
 - *
 - * The following enumerable values are defined:
 - * - LinkButton: link buttons
 - * - PushButton: form buttons
 - * - ImageButton: image buttons
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TButtonColumnType extends TEnumerable
 -{
 -	const LinkButton='LinkButton';
 -	const PushButton='PushButton';
 -	const ImageButton='ImageButton';
 -}
 -
 +<?php +/** + * TDataGridColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Util.TDataFieldAccessor'); +Prado::using('System.Web.UI.WebControls.TDataGrid'); + +/** + * TDataGridColumn class + * + * TDataGridColumn serves as the base class for the different column types of + * the {@link TDataGrid} control. + * TDataGridColumn defines the properties and methods that are common among + * all datagrid column types. In particular, it initializes header and footer + * cells according to {@link setHeaderText HeaderText} and {@link getHeaderStyle HeaderStyle} + * {@link setFooterText FooterText} and {@link getFooterStyle FooterStyle} properties. + * If {@link setHeaderImageUrl HeaderImageUrl} is specified, the image + * will be displayed instead in the header cell. + * The {@link getItemStyle ItemStyle} is applied to cells that belong to + * non-header and -footer datagrid items. + * + * When the datagrid enables sorting, if the {@link setSortExpression SortExpression} + * is not empty, the header cell will display a button (linkbutton or imagebutton) + * that will bubble the sort command event to the datagrid. + * + * Since v3.1.0, TDataGridColumn has introduced two new properties {@link setHeaderRenderer HeaderRenderer} + * and {@link setFooterRenderer FooterRenderer} which can be used to specify + * the layout of header and footer column cells. + * A renderer refers to a control class that is to be instantiated as a control. + * For more details, see {@link TRepeater} and {@link TDataList}. + * + * Since v3.1.1, TDataGridColumn has introduced {@link setEnableCellGrouping EnableCellGrouping}. + * If a column has this property set true, consecutive cells having the same content in this + * column will be grouped into one cell. + * Note, there are some limitations to cell grouping. We determine the cell content according to + * the cell's {@link TTableCell::getText Text} property. If the text is empty and the cell has + * some child controls, we will pick up the first control who implements {@link IDataRenderer} + * and obtain its {@link IDataRenderer::getData Data} property. + * + * The following datagrid column types are provided by the framework currently, + * - {@link TBoundColumn}, associated with a specific field in datasource and displays the corresponding data. + * - {@link TEditCommandColumn}, displaying edit/update/cancel command buttons + * - {@link TDropDownListColumn}, displaying a dropdown list when the item is in edit state + * - {@link TButtonColumn}, displaying generic command buttons that may be bound to specific field in datasource. + * - {@link THyperLinkColumn}, displaying a hyperlink that may be bound to specific field in datasource. + * - {@link TCheckBoxColumn}, displaying a checkbox that may be bound to specific field in datasource. + * - {@link TTemplateColumn}, displaying content based on templates. + * + * To create your own column class, simply override {@link initializeCell()} method, + * which is the major logic for managing the data and presentation of cells in the column. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TDataGridColumn extends TApplicationComponent +{ +	private $_id=''; +	private $_owner=null; +	private $_viewState=array(); + +	/** +	 * @return string the ID of the column. +	 */ +	public function getID() +	{ +		return $this->_id; +	} + +	/** +	 * Sets the ID of the column. +	 * By explicitly specifying the column ID, one can access the column +	 * by $templateControl->ColumnID. +	 * @param string the ID of the column. +	 * @throws TInvalidDataValueException if the ID is of bad format +	 */ +	public function setID($value) +	{ +		if(!preg_match(TControl::ID_FORMAT,$value)) +			throw new TInvalidDataValueException('datagridcolumn_id_invalid',get_class($this),$value); +		$this->_id=$value; +	} + +	/** +	 * @return string the text to be displayed in the header of this column +	 */ +	public function getHeaderText() +	{ +		return $this->getViewState('HeaderText',''); +	} + +	/** +	 * @param string text to be displayed in the header of this column +	 */ +	public function setHeaderText($value) +	{ +		$this->setViewState('HeaderText',$value,''); +	} + +	/** +	 * @return string the url of the image to be displayed in header +	 */ +	public function getHeaderImageUrl() +	{ +		return $this->getViewState('HeaderImageUrl',''); +	} + +	/** +	 * @param string the url of the image to be displayed in header +	 */ +	public function setHeaderImageUrl($value) +	{ +		$this->setViewState('HeaderImageUrl',$value,''); +	} + +	/** +	 * @return string the class name for the column header cell renderer. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getHeaderRenderer() +	{ +		return $this->getViewState('HeaderRenderer',''); +	} + +	/** +	 * Sets the column header cell renderer class. +	 * +	 * If not empty, the class will be used to instantiate as a child control in the column header cell. +	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property +	 * will be set as the {@link getFooterText FooterText}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @since 3.1.0 +	 */ +	public function setHeaderRenderer($value) +	{ +		$this->setViewState('HeaderRenderer',$value,''); +	} + +	/** +	 * @param boolean whether to create a style if previously not existing +	 * @return TTableItemStyle the style for header +	 */ +	public function getHeaderStyle($createStyle=true) +	{ +		if(($style=$this->getViewState('HeaderStyle',null))===null && $createStyle) +		{ +			$style=new TTableItemStyle; +			$this->setViewState('HeaderStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return string the text to be displayed in the footer of this column +	 */ +	public function getFooterText() +	{ +		return $this->getViewState('FooterText',''); +	} + +	/** +	 * @param string text to be displayed in the footer of this column +	 */ +	public function setFooterText($value) +	{ +		$this->setViewState('FooterText',$value,''); +	} + +	/** +	 * @return string the class name for the column footer cell renderer. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getFooterRenderer() +	{ +		return $this->getViewState('FooterRenderer',''); +	} + +	/** +	 * Sets the column footer cell renderer class. +	 * +	 * If not empty, the class will be used to instantiate as a child control in the column footer cell. +	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property +	 * will be set as the {@link getFooterText FooterText}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @since 3.1.0 +	 */ +	public function setFooterRenderer($value) +	{ +		$this->setViewState('FooterRenderer',$value,''); +	} + +	/** +	 * @param boolean whether to create a style if previously not existing +	 * @return TTableItemStyle the style for footer +	 */ +	public function getFooterStyle($createStyle=true) +	{ +		if(($style=$this->getViewState('FooterStyle',null))===null && $createStyle) +		{ +			$style=new TTableItemStyle; +			$this->setViewState('FooterStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @param boolean whether to create a style if previously not existing +	 * @return TTableItemStyle the style for item +	 */ +	public function getItemStyle($createStyle=true) +	{ +		if(($style=$this->getViewState('ItemStyle',null))===null && $createStyle) +		{ +			$style=new TTableItemStyle; +			$this->setViewState('ItemStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return string the name of the field or expression for sorting +	 */ +	public function getSortExpression() +	{ +		return $this->getViewState('SortExpression',''); +	} + +	/** +	 * @param string the name of the field or expression for sorting +	 */ +	public function setSortExpression($value) +	{ +		$this->setViewState('SortExpression',$value,''); +	} + +	/** +	 * @return boolean whether cells having the same content should be grouped together. Defaults to false. +	 * @since 3.1.1 +	 */ +	public function getEnableCellGrouping() +	{ +		return $this->getViewState('EnableCellGrouping',false); +	} + +	/** +	 * @param boolean whether cells having the same content should be grouped together. +	 * @since 3.1.1 +	 */ +	public function setEnableCellGrouping($value) +	{ +		$this->setViewState('EnableCellGrouping',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether the column is visible. Defaults to true. +	 */ +	public function getVisible($checkParents=true) +	{ +		return $this->getViewState('Visible',true); +	} + +	/** +	 * @param boolean whether the column is visible +	 */ +	public function setVisible($value) +	{ +		$this->setViewState('Visible',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Returns a viewstate value. +	 * +	 * @param string the name of the viewstate value to be returned +	 * @param mixed the default value. If $key is not found in viewstate, $defaultValue will be returned +	 * @return mixed the viewstate value corresponding to $key +	 */ +	protected function getViewState($key,$defaultValue=null) +	{ +		return isset($this->_viewState[$key])?$this->_viewState[$key]:$defaultValue; +	} + +	/** +	 * Sets a viewstate value. +	 * +	 * Make sure that the viewstate value must be serializable and unserializable. +	 * @param string the name of the viewstate value +	 * @param mixed the viewstate value to be set +	 * @param mixed default value. If $value===$defaultValue, the item will be cleared from the viewstate. +	 */ +	protected function setViewState($key,$value,$defaultValue=null) +	{ +		if($value===$defaultValue) +			unset($this->_viewState[$key]); +		else +			$this->_viewState[$key]=$value; +	} + +	/** +	 * Loads persistent state values. +	 * @param mixed state values +	 */ +	public function loadState($state) +	{ +		$this->_viewState=$state; +	} + +	/** +	 * Saves persistent state values. +	 * @return mixed values to be saved +	 */ +	public function saveState() +	{ +		return $this->_viewState; +	} + +	/** +	 * @return TDataGrid datagrid that owns this column +	 */ +	public function getOwner() +	{ +		return $this->_owner; +	} + +	/** +	 * @param TDataGrid datagrid object that owns this column +	 */ +	public function setOwner(TDataGrid $value) +	{ +		$this->_owner=$value; +	} + +	/** +	 * Initializes the column. +	 * This method is invoked by {@link TDataGrid} when the column +	 * is about to be used to initialize datagrid items. +	 * Derived classes may override this method to do additional initialization. +	 */ +	public function initialize() +	{ +	} + +	/** +	 * Fetches the value of the data at the specified field. +	 * If the data is an array, the field is used as an array key. +	 * If the data is an of {@link TMap}, {@link TList} or their derived class, +	 * the field is used as a key value. +	 * If the data is a component, the field is used as the name of a property. +	 * @param mixed data containing the field of value +	 * @param string the data field +	 * @return mixed data value at the specified field +	 * @throws TInvalidDataValueException if the data or the field is invalid. +	 */ +	protected function getDataFieldValue($data,$field) +	{ +		return TDataFieldAccessor::getDataFieldValue($data,$field); +	} + + +	/** +	 * Initializes the specified cell to its initial values. +	 * The default implementation sets the content of header and footer cells. +	 * If sorting is enabled by the grid and sort expression is specified in the column, +	 * the header cell will show a link/image button. Otherwise, the header/footer cell +	 * will only show static text/image. +	 * This method can be overriden to provide customized intialization to column cells. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Header) +			$this->initializeHeaderCell($cell,$columnIndex); +		else if($itemType===TListItemType::Footer) +			$this->initializeFooterCell($cell,$columnIndex); +	} + +	/** +	 * Returns a value indicating whether this column allows sorting. +	 * The column allows sorting only when {@link getSortExpression SortExpression} +	 * is not empty and the datagrid allows sorting. +	 * @return boolean whether this column allows sorting +	 */ +	public function getAllowSorting() +	{ +		return $this->getSortExpression()!=='' && (!$this->_owner || $this->_owner->getAllowSorting()); +	} + +	/** +	 * Initializes the header cell. +	 * +	 * This method attempts to use {@link getHeaderRenderer HeaderRenderer} to +	 * instantiate the header cell. If that is not available, it will populate +	 * the cell with an image or a text string, depending on {@link getHeaderImageUrl HeaderImageUrl} +	 * and {@link getHeaderText HeaderText} property values. +	 * +	 * If the column allows sorting, image or text will be created as +	 * a button which issues <b>Sort</b> command upon user click. +	 * +	 * @param TTableCell the cell to be initialized +	 * @param integer the index to the Columns property that the cell resides in. +	 */ +	protected function initializeHeaderCell($cell,$columnIndex) +	{ +		$text=$this->getHeaderText(); + +		if(($classPath=$this->getHeaderRenderer())!=='') +		{ +			$control=Prado::createComponent($classPath); +			$cell->getControls()->add($control); +			if($control instanceof IDataRenderer) +			{ +				if($control instanceof IItemDataRenderer) +				{ +					$item=$cell->getParent(); +					$control->setItemIndex($item->getItemIndex()); +					$control->setItemType($item->getItemType()); +				} +				$control->setData($text); +			} +		} +		else if($this->getAllowSorting()) +		{ +			$sortExpression=$this->getSortExpression(); +			if(($url=$this->getHeaderImageUrl())!=='') +			{ +				$button=Prado::createComponent('System.Web.UI.WebControls.TImageButton'); +				$button->setImageUrl($url); +				$button->setCommandName(TDataGrid::CMD_SORT); +				$button->setCommandParameter($sortExpression); +				if($text!=='') +					$button->setAlternateText($text); +				$button->setCausesValidation(false); +				$cell->getControls()->add($button); +			} +			else if($text!=='') +			{ +				$button=Prado::createComponent('System.Web.UI.WebControls.TLinkButton'); +				$button->setText($text); +				$button->setCommandName(TDataGrid::CMD_SORT); +				$button->setCommandParameter($sortExpression); +				$button->setCausesValidation(false); +				$cell->getControls()->add($button); +			} +			else +				$cell->setText(' '); +		} +		else +		{ +			if(($url=$this->getHeaderImageUrl())!=='') +			{ +				$image=Prado::createComponent('System.Web.UI.WebControls.TImage'); +				$image->setImageUrl($url); +				if($text!=='') +					$image->setAlternateText($text); +				$cell->getControls()->add($image); +			} +			else if($text!=='') +				$cell->setText($text); +			else +				$cell->setText(' '); +		} +	} + +	/** +	 * Initializes the footer cell. +	 * +	 * This method attempts to use {@link getFooterRenderer FooterRenderer} to +	 * instantiate the footer cell. If that is not available, it will populate +	 * the cell with a text string specified by {@link getFooterImageUrl FooterImageUrl} +	 * +	 * @param TTableCell the cell to be initialized +	 * @param integer the index to the Columns property that the cell resides in. +	 */ +	protected function initializeFooterCell($cell,$columnIndex) +	{ +		$text=$this->getFooterText(); +		if(($classPath=$this->getFooterRenderer())!=='') +		{ +			$control=Prado::createComponent($classPath); +			$cell->getControls()->add($control); +			if($control instanceof IDataRenderer) +			{ +				if($control instanceof IItemDataRenderer) +				{ +					$item=$cell->getParent(); +					$control->setItemIndex($item->getItemIndex()); +					$control->setItemType($item->getItemType()); +				} +				$control->setData($text); +			} +		} +		else if($text!=='') +			$cell->setText($text); +		else +			$cell->setText(' '); +	} + +	/** +	 * Formats the text value according to a format string. +	 * If the format string is empty, the original value is converted into +	 * a string and returned. +	 * If the format string starts with '#', the string is treated as a PHP expression +	 * within which the token '{0}' is translated with the data value to be formated. +	 * Otherwise, the format string and the data value are passed +	 * as the first and second parameters in {@link sprintf}. +	 * @param string format string +	 * @param mixed the data to be formatted +	 * @return string the formatted result +	 */ +	protected function formatDataValue($formatString,$value) +	{ +		if($formatString==='') +			return TPropertyValue::ensureString($value); +		else if($formatString[0]==='#') +		{ +			$expression=strtr(substr($formatString,1),array('{0}'=>'$value')); +			try +			{ +				if(eval("\$result=$expression;")===false) +					throw new Exception(''); +				return $result; +			} +			catch(Exception $e) +			{ +				throw new TInvalidDataValueException('datagridcolumn_expression_invalid',get_class($this),$expression,$e->getMessage()); +			} +		} +		else +			return sprintf($formatString,$value); +	} +} + + +/** + * TButtonColumnType class. + * TButtonColumnType defines the enumerable type for the possible types of buttons + * that can be used in a {@link TButtonColumn}. + * + * The following enumerable values are defined: + * - LinkButton: link buttons + * - PushButton: form buttons + * - ImageButton: image buttons + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TButtonColumnType extends TEnumerable +{ +	const LinkButton='LinkButton'; +	const PushButton='PushButton'; +	const ImageButton='ImageButton'; +} + diff --git a/framework/Web/UI/WebControls/TDataGridItemRenderer.php b/framework/Web/UI/WebControls/TDataGridItemRenderer.php index 0e30a062..dbbbec11 100644 --- a/framework/Web/UI/WebControls/TDataGridItemRenderer.php +++ b/framework/Web/UI/WebControls/TDataGridItemRenderer.php @@ -1,30 +1,30 @@ -<?php
 -/**
 - * TDataGridItemRenderer class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDataGridItemRenderer class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TDataGrid');
 -Prado::using('System.Web.UI.WebControls.TItemDataRenderer');
 -
 -/**
 - * TDataGridItemRenderer class
 - *
 - * TDataGridItemRenderer can be used as a convenient base class to
 - * define an item renderer class specific for {@link TDataGrid}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.0
 - */
 -class TDataGridItemRenderer extends TItemDataRenderer
 -{
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataGrid'); +Prado::using('System.Web.UI.WebControls.TItemDataRenderer'); + +/** + * TDataGridItemRenderer class + * + * TDataGridItemRenderer can be used as a convenient base class to + * define an item renderer class specific for {@link TDataGrid}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.0 + */ +class TDataGridItemRenderer extends TItemDataRenderer +{ +} + diff --git a/framework/Web/UI/WebControls/TDataGridPagerStyle.php b/framework/Web/UI/WebControls/TDataGridPagerStyle.php index 12346c06..2464291a 100644 --- a/framework/Web/UI/WebControls/TDataGridPagerStyle.php +++ b/framework/Web/UI/WebControls/TDataGridPagerStyle.php @@ -1,255 +1,255 @@ -<?php
 -/**
 - * TDataGridPagerStyle class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TDataGrid');
 -
 -/**
 - * TDataGridPagerStyle class.
 - *
 - * TDataGridPagerStyle specifies the styles available for a datagrid pager.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataGridPagerStyle extends TPanelStyle
 -{
 -	private $_mode=null;
 -	private $_nextText=null;
 -	private $_prevText=null;
 -	private $_firstText=null;
 -	private $_lastText=null;
 -	private $_buttonCount=null;
 -	private $_position=null;
 -	private $_visible=null;
 -	private $_buttonType=null;
 -
 -	/**
 -	 * @return TDataGridPagerMode pager mode. Defaults to TDataGridPagerMode::NextPrev.
 -	 */
 -	public function getMode()
 -	{
 -		return $this->_mode===null?TDataGridPagerMode::NextPrev : $this->_mode;
 -	}
 -
 -	/**
 -	 * @param TDataGridPagerMode pager mode.
 -	 */
 -	public function setMode($value)
 -	{
 -		$this->_mode=TPropertyValue::ensureEnum($value,'TDataGridPagerMode');
 -	}
 -
 -	/**
 -	 * @return TDataGridPagerButtonType the type of command button. Defaults to TDataGridPagerButtonType::LinkButton.
 -	 */
 -	public function getButtonType()
 -	{
 -		return $this->_buttonType===null?TDataGridPagerButtonType::LinkButton:$this->_buttonType;
 -	}
 -
 -	/**
 -	 * @param TDataGridPagerButtonType the type of command button
 -	 */
 -	public function setButtonType($value)
 -	{
 -		$this->_buttonType=TPropertyValue::ensureEnum($value,'TDataGridPagerButtonType');
 -	}
 -
 -	/**
 -	 * @return string text for the next page button. Defaults to '>'.
 -	 */
 -	public function getNextPageText()
 -	{
 -		return $this->_nextText===null?'>':$this->_nextText;
 -	}
 -
 -	/**
 -	 * @param string text for the next page button.
 -	 */
 -	public function setNextPageText($value)
 -	{
 -		$this->_nextText=$value;
 -	}
 -
 -	/**
 -	 * @return string text for the previous page button. Defaults to '<'.
 -	 */
 -	public function getPrevPageText()
 -	{
 -		return $this->_prevText===null?'<':$this->_prevText;
 -	}
 -
 -	/**
 -	 * @param string text for the previous page button.
 -	 */
 -	public function setPrevPageText($value)
 -	{
 -		$this->_prevText=$value;
 -	}
 -
 -	/**
 -	 * @return string text for the first page button. Defaults to '<<'.
 -	 */
 -	public function getFirstPageText()
 -	{
 -		return $this->_firstText===null?'<<':$this->_firstText;
 -	}
 -
 -	/**
 -	 * @param string text for the first page button.
 -	 */
 -	public function setFirstPageText($value)
 -	{
 -		$this->_firstText=$value;
 -	}
 -
 -	/**
 -	 * @return string text for the last page button. Defaults to '>>'.
 -	 */
 -	public function getLastPageText()
 -	{
 -		return $this->_lastText===null?'>>':$this->_lastText;
 -	}
 -
 -	/**
 -	 * @param string text for the last page button.
 -	 */
 -	public function setLastPageText($value)
 -	{
 -		$this->_lastText=$value;
 -	}
 -
 -	/**
 -	 * @return integer maximum number of pager buttons to be displayed. Defaults to 10.
 -	 */
 -	public function getPageButtonCount()
 -	{
 -		return $this->_buttonCount===null?10:$this->_buttonCount;
 -	}
 -
 -	/**
 -	 * @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('datagridpagerstyle_pagebuttoncount_invalid');
 -		$this->_buttonCount=$value;
 -	}
 -
 -	/**
 -	 * @return TDataGridPagerPosition where the pager is to be displayed. Defaults to TDataGridPagerPosition::Bottom.
 -	 */
 -	public function getPosition()
 -	{
 -		return $this->_position===null?TDataGridPagerPosition::Bottom:$this->_position;
 -	}
 -
 -	/**
 -	 * @param TDataGridPagerPosition where the pager is to be displayed.
 -	 */
 -	public function setPosition($value)
 -	{
 -		$this->_position=TPropertyValue::ensureEnum($value,'TDataGridPagerPosition');
 -	}
 -
 -	/**
 -	 * @return boolean whether the pager is visible. Defaults to true.
 -	 */
 -	public function getVisible()
 -	{
 -		return $this->_visible===null?true:$this->_visible;
 -	}
 -
 -	/**
 -	 * @param boolean whether the pager is visible.
 -	 */
 -	public function setVisible($value)
 -	{
 -		$this->_visible=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * Resets the style to the original empty state.
 -	 */
 -	public function reset()
 -	{
 -		parent::reset();
 -		$this->_visible=null;
 -		$this->_position=null;
 -		$this->_buttonCount=null;
 -		$this->_prevText=null;
 -		$this->_nextText=null;
 -		$this->_mode=null;
 -		$this->_buttonType=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 TDataGridPagerStyle)
 -		{
 -			if($style->_visible!==null)
 -				$this->_visible=$style->_visible;
 -			if($style->_position!==null)
 -				$this->_position=$style->_position;
 -			if($style->_buttonCount!==null)
 -				$this->_buttonCount=$style->_buttonCount;
 -			if($style->_prevText!==null)
 -				$this->_prevText=$style->_prevText;
 -			if($style->_nextText!==null)
 -				$this->_nextText=$style->_nextText;
 -			if($style->_mode!==null)
 -				$this->_mode=$style->_mode;
 -			if($style->_buttonType!==null)
 -				$this->_buttonType=$style->_buttonType;
 -		}
 -	}
 -
 -	/**
 -	 * 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 TDataGridPagerStyle)
 -		{
 -			if($this->_visible===null)
 -				$this->_visible=$style->_visible;
 -			if($this->_position===null)
 -				$this->_position=$style->_position;
 -			if($this->_buttonCount===null)
 -				$this->_buttonCount=$style->_buttonCount;
 -			if($this->_prevText===null)
 -				$this->_prevText=$style->_prevText;
 -			if($this->_nextText===null)
 -				$this->_nextText=$style->_nextText;
 -			if($this->_mode===null)
 -				$this->_mode=$style->_mode;
 -			if($this->_buttonType===null)
 -				$this->_buttonType=$style->_buttonType;
 -		}
 -	}
 -}
 -
 +<?php +/** + * TDataGridPagerStyle class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataGrid'); + +/** + * TDataGridPagerStyle class. + * + * TDataGridPagerStyle specifies the styles available for a datagrid pager. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataGridPagerStyle extends TPanelStyle +{ +	private $_mode=null; +	private $_nextText=null; +	private $_prevText=null; +	private $_firstText=null; +	private $_lastText=null; +	private $_buttonCount=null; +	private $_position=null; +	private $_visible=null; +	private $_buttonType=null; + +	/** +	 * @return TDataGridPagerMode pager mode. Defaults to TDataGridPagerMode::NextPrev. +	 */ +	public function getMode() +	{ +		return $this->_mode===null?TDataGridPagerMode::NextPrev : $this->_mode; +	} + +	/** +	 * @param TDataGridPagerMode pager mode. +	 */ +	public function setMode($value) +	{ +		$this->_mode=TPropertyValue::ensureEnum($value,'TDataGridPagerMode'); +	} + +	/** +	 * @return TDataGridPagerButtonType the type of command button. Defaults to TDataGridPagerButtonType::LinkButton. +	 */ +	public function getButtonType() +	{ +		return $this->_buttonType===null?TDataGridPagerButtonType::LinkButton:$this->_buttonType; +	} + +	/** +	 * @param TDataGridPagerButtonType the type of command button +	 */ +	public function setButtonType($value) +	{ +		$this->_buttonType=TPropertyValue::ensureEnum($value,'TDataGridPagerButtonType'); +	} + +	/** +	 * @return string text for the next page button. Defaults to '>'. +	 */ +	public function getNextPageText() +	{ +		return $this->_nextText===null?'>':$this->_nextText; +	} + +	/** +	 * @param string text for the next page button. +	 */ +	public function setNextPageText($value) +	{ +		$this->_nextText=$value; +	} + +	/** +	 * @return string text for the previous page button. Defaults to '<'. +	 */ +	public function getPrevPageText() +	{ +		return $this->_prevText===null?'<':$this->_prevText; +	} + +	/** +	 * @param string text for the previous page button. +	 */ +	public function setPrevPageText($value) +	{ +		$this->_prevText=$value; +	} + +	/** +	 * @return string text for the first page button. Defaults to '<<'. +	 */ +	public function getFirstPageText() +	{ +		return $this->_firstText===null?'<<':$this->_firstText; +	} + +	/** +	 * @param string text for the first page button. +	 */ +	public function setFirstPageText($value) +	{ +		$this->_firstText=$value; +	} + +	/** +	 * @return string text for the last page button. Defaults to '>>'. +	 */ +	public function getLastPageText() +	{ +		return $this->_lastText===null?'>>':$this->_lastText; +	} + +	/** +	 * @param string text for the last page button. +	 */ +	public function setLastPageText($value) +	{ +		$this->_lastText=$value; +	} + +	/** +	 * @return integer maximum number of pager buttons to be displayed. Defaults to 10. +	 */ +	public function getPageButtonCount() +	{ +		return $this->_buttonCount===null?10:$this->_buttonCount; +	} + +	/** +	 * @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('datagridpagerstyle_pagebuttoncount_invalid'); +		$this->_buttonCount=$value; +	} + +	/** +	 * @return TDataGridPagerPosition where the pager is to be displayed. Defaults to TDataGridPagerPosition::Bottom. +	 */ +	public function getPosition() +	{ +		return $this->_position===null?TDataGridPagerPosition::Bottom:$this->_position; +	} + +	/** +	 * @param TDataGridPagerPosition where the pager is to be displayed. +	 */ +	public function setPosition($value) +	{ +		$this->_position=TPropertyValue::ensureEnum($value,'TDataGridPagerPosition'); +	} + +	/** +	 * @return boolean whether the pager is visible. Defaults to true. +	 */ +	public function getVisible() +	{ +		return $this->_visible===null?true:$this->_visible; +	} + +	/** +	 * @param boolean whether the pager is visible. +	 */ +	public function setVisible($value) +	{ +		$this->_visible=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * Resets the style to the original empty state. +	 */ +	public function reset() +	{ +		parent::reset(); +		$this->_visible=null; +		$this->_position=null; +		$this->_buttonCount=null; +		$this->_prevText=null; +		$this->_nextText=null; +		$this->_mode=null; +		$this->_buttonType=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 TDataGridPagerStyle) +		{ +			if($style->_visible!==null) +				$this->_visible=$style->_visible; +			if($style->_position!==null) +				$this->_position=$style->_position; +			if($style->_buttonCount!==null) +				$this->_buttonCount=$style->_buttonCount; +			if($style->_prevText!==null) +				$this->_prevText=$style->_prevText; +			if($style->_nextText!==null) +				$this->_nextText=$style->_nextText; +			if($style->_mode!==null) +				$this->_mode=$style->_mode; +			if($style->_buttonType!==null) +				$this->_buttonType=$style->_buttonType; +		} +	} + +	/** +	 * 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 TDataGridPagerStyle) +		{ +			if($this->_visible===null) +				$this->_visible=$style->_visible; +			if($this->_position===null) +				$this->_position=$style->_position; +			if($this->_buttonCount===null) +				$this->_buttonCount=$style->_buttonCount; +			if($this->_prevText===null) +				$this->_prevText=$style->_prevText; +			if($this->_nextText===null) +				$this->_nextText=$style->_nextText; +			if($this->_mode===null) +				$this->_mode=$style->_mode; +			if($this->_buttonType===null) +				$this->_buttonType=$style->_buttonType; +		} +	} +} + diff --git a/framework/Web/UI/WebControls/TDataList.php b/framework/Web/UI/WebControls/TDataList.php index 43980c0c..49e9c749 100644 --- a/framework/Web/UI/WebControls/TDataList.php +++ b/framework/Web/UI/WebControls/TDataList.php @@ -1,1766 +1,1766 @@ -<?php
 -/**
 - * TDataList class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDataList class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TBaseDataList class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseDataList');
 -/**
 - * Includes TRepeatInfo class
 - */
 -Prado::using('System.Web.UI.WebControls.TRepeatInfo');
 -
 -/**
 - * TDataList class
 - *
 - * TDataList represents a data bound and updatable list control.
 - *
 - * Like {@link TRepeater}, TDataList displays its content repeatedly based on
 - * the data fetched from {@link setDataSource DataSource}.
 - * The repeated contents in TDataList are called items, which are controls and
 - * can be accessed through {@link getItems Items}. When {@link dataBind()} is
 - * invoked, TDataList creates an item for each row of data and binds the data
 - * row to the item. Optionally, a TDataList can have a header, a footer and/or
 - * separators between items.
 - *
 - * TDataList differs from {@link TRepeater} in that it supports tiling the items
 - * in different manners and it maintains status of items to handle data update.
 - *
 - * The layout of the repeated contents are specified by inline templates.
 - * TDataList items, header, footer, etc. are being instantiated with the corresponding
 - * templates when data is being bound to the repeater.
 - *
 - * Since v3.1.0, the layout can also be by renderers. A renderer is a control class
 - * that can be instantiated as datalist items, header, etc. A renderer can thus be viewed
 - * as an external template (in fact, it can also be non-templated controls).
 - *
 - * A renderer can be any control class.
 - * - If the class implements {@link IDataRenderer}, the <b>Data</b>
 - * 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 <b>ItemIndex</b> property will be set
 - * as the zero-based index of the item in the datalist item collection, and
 - * the <b>ItemType</b> property as the item's type (such as TListItemType::Item).
 - * {@link TDataListItemRenderer} may be used as the convenient base class which
 - * already implements {@link IDataItemRenderer}.
 - *
 - * The following properties are used to specify different types of template and renderer
 - * for a datalist:
 - * - {@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 datalist header.
 - * - {@link setFooterTemplate FooterTemplate}, {@link setFooterRenderer FooterRenderer}:
 - * for the datalist 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 datalist is empty.
 - * - {@link setEditItemTemplate EditItemTemplate}, {@link setEditItemRenderer EditItemRenderer}:
 - * for the row being editted.
 - * - {@link setSelectedItemTemplate SelectedItemTemplate}, {@link setSelectedItemRenderer SelectedItemRenderer}:
 - * for the row being selected.
 - *
 - * If a content type is defined with both a template and a renderer, the latter takes precedence.
 - *
 - * When {@link dataBind()} is being called, TDataList 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}:
 - *
 - * TDataList raises an {@link onItemCommand OnItemCommand} whenever a button control
 - * within some datalist item raises a <b>OnCommand</b> event. Therefore,
 - * you can handle all sorts of <b>OnCommand</b> event in a central place by
 - * writing an event handler for {@link onItemCommand OnItemCommand}.
 - *
 - * An additional event is raised if the <b>OnCommand</b> event has one of the following
 - * command names:
 - * - edit: user wants to edit an item. <b>OnEditCommand</b> event will be raised.
 - * - update: user wants to save the change to an item. <b>OnUpdateCommand</b> event will be raised.
 - * - select: user selects an item. <b>OnSelectedIndexChanged</b> event will be raised.
 - * - delete: user deletes an item. <b>OnDeleteCommand</b> event will be raised.
 - * - cancel: user cancels previously editting action. <b>OnCancelCommand</b> event will be raised.
 - *
 - * TDataList provides a few properties to support tiling the items.
 - * The number of columns used to display the data items is specified via
 - * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection}
 - * governs the order of the items being rendered.
 - * The layout of the data items in the list is specified via {@link setRepeatLayout RepeatLayout},
 - * which can take one of the following values:
 - * - Table (default): items are organized using HTML table and cells.
 - * When using this layout, one can set {@link setCellPadding CellPadding} and
 - * {@link setCellSpacing CellSpacing} to adjust the cellpadding and cellpadding
 - * of the table, and {@link setCaption Caption} and {@link setCaptionAlign CaptionAlign}
 - * to add a table caption with the specified alignment.
 - * - Flow: items are organized using HTML spans and breaks.
 - * - Raw: TDataList does not generate any HTML tags to do the tiling.
 - *
 - * Items in TDataList can be in one of the three status: normal browsing,
 - * being editted and being selected. To change the status of a particular
 - * item, set {@link setSelectedItemIndex SelectedItemIndex} or
 - * {@link setEditItemIndex EditItemIndex}. The former will change
 - * the indicated item to selected mode, which will cause the item to
 - * use {@link setSelectedItemTemplate SelectedItemTemplate} or
 - * {@link setSelectedItemRenderer SelectedItemRenderer} for presentation.
 - * The latter will change the indicated item to edit mode and to use corresponding
 - * template or renderer.
 - * Note, if an item is in edit mode, then selecting this item will have no effect.
 - *
 - * Different styles may be applied to items in different status. The style
 - * application is performed in a hierarchical way: Style in higher hierarchy
 - * will inherit from styles in lower hierarchy.
 - * Starting from the lowest hierarchy, the item styles include
 - * - item's own style
 - * - {@link getItemStyle ItemStyle}
 - * - {@link getAlternatingItemStyle AlternatingItemStyle}
 - * - {@link getSelectedItemStyle SelectedItemStyle}
 - * - {@link getEditItemStyle EditItemStyle}.
 - * Therefore, if background color is set as red in {@link getItemStyle ItemStyle},
 - * {@link getEditItemStyle EditItemStyle} will also have red background color
 - * unless it is set to a different value explicitly.
 - *
 - * When a page containing a datalist is post back, the datalist 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 datalist item and use the key to fetch the corresponding data
 - * from some persistent storage such as DB.
 - * - 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 <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUser
 -{
 -	/**
 -	 * Command name that TDataList understands. They are case-insensitive.
 -	 */
 -	const CMD_SELECT='Select';
 -	const CMD_EDIT='Edit';
 -	const CMD_UPDATE='Update';
 -	const CMD_DELETE='Delete';
 -	const CMD_CANCEL='Cancel';
 -
 -	/**
 -	 * @var TDataListItemCollection item list
 -	 */
 -	private $_items=null;
 -	/**
 -	 * @var Itemplate various item templates
 -	 */
 -	private $_itemTemplate=null;
 -	private $_emptyTemplate=null;
 -	private $_alternatingItemTemplate=null;
 -	private $_selectedItemTemplate=null;
 -	private $_editItemTemplate=null;
 -	private $_headerTemplate=null;
 -	private $_footerTemplate=null;
 -	private $_separatorTemplate=null;
 -	/**
 -	 * @var TControl header item
 -	 */
 -	private $_header=null;
 -	/**
 -	 * @var TControl footer item
 -	 */
 -	private $_footer=null;
 -
 -	/**
 -	 * @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 class name for datalist items. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getItemRenderer()
 -	{
 -		return $this->getViewState('ItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the item renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as datalist items.
 -	 * This property takes precedence over {@link getItemTemplate ItemTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setItemTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setItemRenderer($value)
 -	{
 -		$this->setViewState('ItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for alternative datalist items. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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 datalist items.
 -	 * This property takes precedence over {@link getAlternatingItemTemplate AlternatingItemTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setAlternatingItemTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setAlternatingItemRenderer($value)
 -	{
 -		$this->setViewState('AlternatingItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for the datalist item being editted. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getEditItemRenderer()
 -	{
 -		return $this->getViewState('EditItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the renderer class for the datalist item being editted.
 -	 *
 -	 * If not empty, the class will be used to instantiate as the datalist item.
 -	 * This property takes precedence over {@link getEditItemTemplate EditItemTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setEditItemTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setEditItemRenderer($value)
 -	{
 -		$this->setViewState('EditItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for the datalist item being selected. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getSelectedItemRenderer()
 -	{
 -		return $this->getViewState('SelectedItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the renderer class for the datalist item being selected.
 -	 *
 -	 * If not empty, the class will be used to instantiate as the datalist item.
 -	 * This property takes precedence over {@link getSelectedItemTemplate SelectedItemTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setSelectedItemTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setSelectedItemRenderer($value)
 -	{
 -		$this->setViewState('SelectedItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for datalist item separators. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getSeparatorRenderer()
 -	{
 -		return $this->getViewState('SeparatorRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the datalist item separator renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as datalist item separators.
 -	 * This property takes precedence over {@link getSeparatorTemplate SeparatorTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setSeparatorTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setSeparatorRenderer($value)
 -	{
 -		$this->setViewState('SeparatorRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for datalist header item. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getHeaderRenderer()
 -	{
 -		return $this->getViewState('HeaderRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the datalist header renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as datalist header item.
 -	 * This property takes precedence over {@link getHeaderTemplate HeaderTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setHeaderTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setHeaderRenderer($value)
 -	{
 -		$this->setViewState('HeaderRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for datalist footer item. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getFooterRenderer()
 -	{
 -		return $this->getViewState('FooterRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the datalist footer renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as datalist footer item.
 -	 * This property takes precedence over {@link getFooterTemplate FooterTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setFooterTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setFooterRenderer($value)
 -	{
 -		$this->setViewState('FooterRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for empty datalist item. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getEmptyRenderer()
 -	{
 -		return $this->getViewState('EmptyRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the datalist empty renderer class.
 -	 *
 -	 * The empty renderer is created as the child of the datalist
 -	 * if data bound to the datalist is empty.
 -	 * This property takes precedence over {@link getEmptyTemplate EmptyTemplate}.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @see setEmptyTemplate
 -	 * @since 3.1.0
 -	 */
 -	public function setEmptyRenderer($value)
 -	{
 -		$this->setViewState('EmptyRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return ITemplate the template for item
 -	 */
 -	public function getItemTemplate()
 -	{
 -		return $this->_itemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template for item
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_itemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','ItemTemplate');
 -	}
 -
 -	/**
 -	 * @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 ITemplate the template for each alternating item
 -	 */
 -	public function getAlternatingItemTemplate()
 -	{
 -		return $this->_alternatingItemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template for each alternating item
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setAlternatingItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_alternatingItemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','AlternatingItemType');
 -	}
 -
 -	/**
 -	 * @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 ITemplate the selected item template
 -	 */
 -	public function getSelectedItemTemplate()
 -	{
 -		return $this->_selectedItemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the selected item template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setSelectedItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_selectedItemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','SelectedItemTemplate');
 -	}
 -
 -	/**
 -	 * @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 ITemplate the edit item template
 -	 */
 -	public function getEditItemTemplate()
 -	{
 -		return $this->_editItemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the edit item template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setEditItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_editItemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','EditItemTemplate');
 -	}
 -
 -	/**
 -	 * @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 ITemplate the header template
 -	 */
 -	public function getHeaderTemplate()
 -	{
 -		return $this->_headerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the header template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setHeaderTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_headerTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','HeaderTemplate');
 -	}
 -
 -	/**
 -	 * @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 TControl the header item
 -	 */
 -	public function getHeader()
 -	{
 -		return $this->_header;
 -	}
 -
 -	/**
 -	 * @return ITemplate the footer template
 -	 */
 -	public function getFooterTemplate()
 -	{
 -		return $this->_footerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the footer template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setFooterTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_footerTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','FooterTemplate');
 -	}
 -
 -	/**
 -	 * @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 TControl the footer item
 -	 */
 -	public function getFooter()
 -	{
 -		return $this->_footer;
 -	}
 -
 -	/**
 -	 * @return ITemplate the template applied when no data is bound to the datalist
 -	 */
 -	public function getEmptyTemplate()
 -	{
 -		return $this->_emptyTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template applied when no data is bound to the datalist
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setEmptyTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_emptyTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','EmptyTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the separator template
 -	 */
 -	public function getSeparatorTemplate()
 -	{
 -		return $this->_separatorTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the separator template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setSeparatorTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_separatorTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('datalist_template_required','SeparatorTemplate');
 -	}
 -
 -	/**
 -	 * @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 instanceof IItemDataRenderer) && $item->getItemType()!==TListItemType::EditItem)
 -					$item->setItemType($current%2?TListItemType::AlternatingItem : TListItemType::Item);
 -			}
 -			if($value>=0 && $value<$itemCount)
 -			{
 -				$item=$items->itemAt($value);
 -				if(($item instanceof IItemDataRenderer) && $item->getItemType()!==TListItemType::EditItem)
 -					$item->setItemType(TListItemType::SelectedItem);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * @return TControl 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 mixed the key value of the currently selected item
 -	 * @throws TInvalidOperationException if {@link getDataKeyField DataKeyField} is empty.
 -	 */
 -	public function getSelectedDataKey()
 -	{
 -		if($this->getDataKeyField()==='')
 -			throw new TInvalidOperationException('datalist_datakeyfield_required');
 -		$index=$this->getSelectedItemIndex();
 -		$dataKeys=$this->getDataKeys();
 -		if($index>=0 && $index<$dataKeys->getCount())
 -			return $dataKeys->itemAt($index);
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * @return integer the zero-based index of the edit item in {@link getItems Items}.
 -	 * A value -1 means no item is in edit mode.
 -	 */
 -	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?TListItemType::AlternatingItem : TListItemType::Item);
 -			if($value>=0 && $value<$itemCount)
 -				$items->itemAt($value)->setItemType(TListItemType::EditItem);
 -		}
 -	}
 -
 -	/**
 -	 * @return TControl 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 string caption of the table layout
 -	 */
 -	public function getCaption()
 -	{
 -		return $this->getRepeatInfo()->getCaption();
 -	}
 -
 -	/**
 -	 * @param string caption of the table layout
 -	 */
 -	public function setCaption($value)
 -	{
 -		$this->getRepeatInfo()->setCaption($value);
 -	}
 -
 -	/**
 -	 * @return TTableCaptionAlign alignment of the caption of the table layout. Defaults to TTableCaptionAlign::NotSet.
 -	 */
 -	public function getCaptionAlign()
 -	{
 -		return $this->getRepeatInfo()->getCaptionAlign();
 -	}
 -
 -	/**
 -	 * @return TTableCaptionAlign alignment of the caption of the table layout.
 -	 */
 -	public function setCaptionAlign($value)
 -	{
 -		$this->getRepeatInfo()->setCaptionAlign($value);
 -	}
 -
 -	/**
 -	 * @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 TRepeatDirection the direction of traversing the list, defaults to TRepeatDirection::Vertical
 -	 */
 -	public function getRepeatDirection()
 -	{
 -		return $this->getRepeatInfo()->getRepeatDirection();
 -	}
 -
 -	/**
 -	 * @param TRepeatDirection the direction of traversing the list
 -	 */
 -	public function setRepeatDirection($value)
 -	{
 -		$this->getRepeatInfo()->setRepeatDirection($value);
 -	}
 -
 -	/**
 -	 * @return TRepeatLayout how the list should be displayed, using table or using line breaks. Defaults to TRepeatLayout::Table.
 -	 */
 -	public function getRepeatLayout()
 -	{
 -		return $this->getRepeatInfo()->getRepeatLayout();
 -	}
 -
 -	/**
 -	 * @param TRepeatLayout how the list should be displayed, using table or using line breaks
 -	 */
 -	public function setRepeatLayout($value)
 -	{
 -		$this->getRepeatInfo()->setRepeatLayout($value);
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation to handle
 -	 * {@link onItemCommand OnItemCommand} event which is bubbled from
 -	 * datalist items and their 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 OnEditCommand}).
 -	 * 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.
 -	 */
 -	public function bubbleEvent($sender,$param)
 -	{
 -		if($param instanceof TDataListCommandEventParameter)
 -		{
 -			$this->onItemCommand($param);
 -			$command=$param->getCommandName();
 -			if(strcasecmp($command,self::CMD_SELECT)===0)
 -			{
 -				if(($item=$param->getItem()) instanceof IItemDataRenderer)
 -					$this->setSelectedItemIndex($item->getItemIndex());
 -				$this->onSelectedIndexChanged($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_EDIT)===0)
 -			{
 -				$this->onEditCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_DELETE)===0)
 -			{
 -				$this->onDeleteCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_UPDATE)===0)
 -			{
 -				$this->onUpdateCommand($param);
 -				return true;
 -			}
 -			else if(strcasecmp($command,self::CMD_CANCEL)===0)
 -			{
 -				$this->onCancelCommand($param);
 -				return true;
 -			}
 -		}
 -		return false;
 -	}
 -
 -
 -	/**
 -	 * Raises <b>OnItemCreated</b> event.
 -	 * This method is invoked after a data list item is created and instantiated with
 -	 * template, but before added to the page hierarchy.
 -	 * The datalist 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.
 -	 * @param TDataListItemEventParameter event parameter
 -	 */
 -	public function onItemCreated($param)
 -	{
 -		$this->raiseEvent('OnItemCreated',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemDataBound</b> event.
 -	 * This method is invoked right after an item is data bound.
 -	 * The datalist 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.
 -	 * @param TDataListItemEventParameter event parameter
 -	 */
 -	public function onItemDataBound($param)
 -	{
 -		$this->raiseEvent('OnItemDataBound',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemCommand</b> event.
 -	 * This method is invoked when a child control of the data list
 -	 * raises an <b>OnCommand</b> event.
 -	 * @param TDataListCommandEventParameter event parameter
 -	 */
 -	public function onItemCommand($param)
 -	{
 -		$this->raiseEvent('OnItemCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnEditCommand</b> event.
 -	 * This method is invoked when a child control of the data list
 -	 * raises an <b>OnCommand</b> event and the command name is 'edit' (case-insensitive).
 -	 * @param TDataListCommandEventParameter event parameter
 -	 */
 -	public function onEditCommand($param)
 -	{
 -		$this->raiseEvent('OnEditCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnDeleteCommand</b> event.
 -	 * This method is invoked when a child control of the data list
 -	 * raises an <b>OnCommand</b> event and the command name is 'delete' (case-insensitive).
 -	 * @param TDataListCommandEventParameter event parameter
 -	 */
 -	public function onDeleteCommand($param)
 -	{
 -		$this->raiseEvent('OnDeleteCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnUpdateCommand</b> event.
 -	 * This method is invoked when a child control of the data list
 -	 * raises an <b>OnCommand</b> event and the command name is 'update' (case-insensitive).
 -	 * @param TDataListCommandEventParameter event parameter
 -	 */
 -	public function onUpdateCommand($param)
 -	{
 -		$this->raiseEvent('OnUpdateCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnCancelCommand</b> event.
 -	 * This method is invoked when a child control of the data list
 -	 * raises an <b>OnCommand</b> event and the command name is 'cancel' (case-insensitive).
 -	 * @param TDataListCommandEventParameter event parameter
 -	 */
 -	public function onCancelCommand($param)
 -	{
 -		$this->raiseEvent('OnCancelCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether this control contains header item.
 -	 * This method is required by {@link IRepeatInfoUser} interface.
 -	 * @return boolean whether the datalist has header
 -	 */
 -	public function getHasHeader()
 -	{
 -		return ($this->getShowHeader() && ($this->_headerTemplate!==null || $this->getHeaderRenderer()!==''));
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether this control contains footer item.
 -	 * This method is required by {@link IRepeatInfoUser} interface.
 -	 * @return boolean whether the datalist has footer
 -	 */
 -	public function getHasFooter()
 -	{
 -		return ($this->getShowFooter() && ($this->_footerTemplate!==null || $this->getFooterRenderer()!==''));
 -	}
 -
 -	/**
 -	 * 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!==null || $this->getSeparatorRenderer()!=='';
 -	}
 -
 -	/**
 -	 * 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 instanceof IStyleable) && $item->getHasStyle())
 -		{
 -			$style=$item->getStyle();
 -			$item->clearStyle();
 -			return $style;
 -		}
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * 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->getItem($itemType,$index);
 -		if($repeatInfo->getRepeatLayout()===TRepeatLayout::Raw && get_class($item)==='TDataListItem')
 -			$item->setTagName('div');
 -		$item->renderControl($writer);
 -	}
 -
 -	/**
 -	 * @param TListItemType item type
 -	 * @param integer item index
 -	 * @return TControl data list item with the specified item type and index
 -	 */
 -	private function getItem($itemType,$index)
 -	{
 -		switch($itemType)
 -		{
 -			case TListItemType::Item:
 -			case TListItemType::AlternatingItem:
 -			case TListItemType::SelectedItem:
 -			case TListItemType::EditItem:
 -				return $this->getItems()->itemAt($index);
 -			case TListItemType::Header:
 -				return $this->getControls()->itemAt(0);
 -			case TListItemType::Footer:
 -				return $this->getControls()->itemAt($this->getControls()->getCount()-1);
 -			case TListItemType::Separator:
 -				$i=$index+$index+1;
 -				if($this->_headerTemplate!==null || $this->getHeaderRenderer()!=='')
 -					$i++;
 -				return $this->getControls()->itemAt($i);
 -		}
 -		return null;
 -	}
 -
 -	/**
 -	 * Creates a datalist item.
 -	 * This method invokes {@link createItem} to create a new datalist item.
 -	 * @param integer zero-based item index.
 -	 * @param TListItemType item type
 -	 * @return TControl the created item, null if item is not created
 -	 */
 -	private function createItemInternal($itemIndex,$itemType)
 -	{
 -		if(($item=$this->createItem($itemIndex,$itemType))!==null)
 -		{
 -			$param=new TDataListItemEventParameter($item);
 -			$this->onItemCreated($param);
 -			$this->getControls()->add($item);
 -			return $item;
 -		}
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * Creates a datalist item and performs databinding.
 -	 * This method invokes {@link createItem} to create a new datalist item.
 -	 * @param integer zero-based item index.
 -	 * @param TListItemType item type
 -	 * @param mixed data to be associated with the item
 -	 * @return TControl the created item, null if item is not created
 -	 */
 -	private function createItemWithDataInternal($itemIndex,$itemType,$dataItem)
 -	{
 -		if(($item=$this->createItem($itemIndex,$itemType))!==null)
 -		{
 -			$param=new TDataListItemEventParameter($item);
 -			if($item instanceof IDataRenderer)
 -				$item->setData($dataItem);
 -			$this->onItemCreated($param);
 -			$this->getControls()->add($item);
 -			$item->dataBind();
 -			$this->onItemDataBound($param);
 -			return $item;
 -		}
 -		else
 -			return null;
 -	}
 -
 -	private function getAlternatingItemDisplay()
 -	{
 -		if(($classPath=$this->getAlternatingItemRenderer())==='' && $this->_alternatingItemTemplate===null)
 -			return array($this->getItemRenderer(),$this->_itemTemplate);
 -		else
 -			return array($classPath,$this->_alternatingItemTemplate);
 -	}
 -
 -	private function getSelectedItemDisplay($itemIndex)
 -	{
 -		if(($classPath=$this->getSelectedItemRenderer())==='' && $this->_selectedItemTemplate===null)
 -		{
 -			if($itemIndex%2===0)
 -				return array($this->getItemRenderer(),$this->_itemTemplate);
 -			else
 -				return $this->getAlternatingItemDisplay();
 -		}
 -		else
 -			return array($classPath,$this->_selectedItemTemplate);
 -	}
 -
 -	private function getEditItemDisplay($itemIndex)
 -	{
 -		if(($classPath=$this->getEditItemRenderer())==='' && $this->_editItemTemplate===null)
 -			return $this->getSelectedItemDisplay($itemIndex);
 -		else
 -			return array($classPath,$this->_editItemTemplate);
 -	}
 -
 -	/**
 -	 * Creates a datalist item instance based on the item type and index.
 -	 * @param integer zero-based item index
 -	 * @param TListItemType item type
 -	 * @return TControl created datalist item
 -	 */
 -	protected function createItem($itemIndex,$itemType)
 -	{
 -		$template=null;
 -		$classPath=null;
 -		switch($itemType)
 -		{
 -			case TListItemType::Item :
 -				$classPath=$this->getItemRenderer();
 -				$template=$this->_itemTemplate;
 -				break;
 -			case TListItemType::AlternatingItem :
 -				list($classPath,$template)=$this->getAlternatingItemDisplay();
 -				break;
 -			case TListItemType::SelectedItem:
 -				list($classPath,$template)=$this->getSelectedItemDisplay($itemIndex);
 -				break;
 -			case TListItemType::EditItem:
 -				list($classPath,$template)=$this->getEditItemDisplay($itemIndex);
 -				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('datalist_itemtype_unknown',$itemType);
 -		}
 -		if($classPath!=='')
 -		{
 -			$item=Prado::createComponent($classPath);
 -			if($item instanceof IItemDataRenderer)
 -			{
 -				$item->setItemIndex($itemIndex);
 -				$item->setItemType($itemType);
 -			}
 -		}
 -		else if($template!==null)
 -		{
 -			$item=new TDataListItem;
 -			$item->setItemIndex($itemIndex);
 -			$item->setItemType($itemType);
 -			$template->instantiateIn($item);
 -		}
 -		else
 -			$item=null;
 -
 -		return $item;
 -	}
 -
 -	/**
 -	 * Creates empty datalist content.
 -	 */
 -	protected function createEmptyContent()
 -	{
 -		if(($classPath=$this->getEmptyRenderer())!=='')
 -			$this->getControls()->add(Prado::createComponent($classPath));
 -		else if($this->_emptyTemplate!==null)
 -			$this->_emptyTemplate->instantiateIn($this);
 -	}
 -
 -	/**
 -	 * Applies styles to items, header, footer and separators.
 -	 * Item styles are applied in a hierarchical way. Style in higher hierarchy
 -	 * will inherit from styles in lower hierarchy.
 -	 * Starting from the lowest hierarchy, the item styles include
 -	 * item's own style, {@link getItemStyle ItemStyle}, {@link getAlternatingItemStyle AlternatingItemStyle},
 -	 * {@link getSelectedItemStyle SelectedItemStyle}, and {@link getEditItemStyle EditItemStyle}.
 -	 * Therefore, if background color is set as red in {@link getItemStyle ItemStyle},
 -	 * {@link getEditItemStyle EditItemStyle} will also have red background color
 -	 * unless it is set to a different value explicitly.
 -	 */
 -	protected function applyItemStyles()
 -	{
 -		$itemStyle=$this->getViewState('ItemStyle',null);
 -
 -		$alternatingItemStyle=$this->getViewState('AlternatingItemStyle',null);
 -		if($itemStyle!==null)
 -		{
 -			if($alternatingItemStyle===null)
 -				$alternatingItemStyle=$itemStyle;
 -			else
 -				$alternatingItemStyle->mergeWith($itemStyle);
 -		}
 -
 -		$selectedItemStyle=$this->getViewState('SelectedItemStyle',null);
 -
 -		$editItemStyle=$this->getViewState('EditItemStyle',null);
 -		if($selectedItemStyle!==null)
 -		{
 -			if($editItemStyle===null)
 -				$editItemStyle=$selectedItemStyle;
 -			else
 -				$editItemStyle->mergeWith($selectedItemStyle);
 -		}
 -
 -		// apply header style if any
 -		if($this->_header!==null && $this->_header instanceof IStyleable)
 -		{
 -			if($headerStyle=$this->getViewState('HeaderStyle',null))
 -				$this->_header->getStyle()->mergeWith($headerStyle);
 -		}
 -
 -		// apply footer style if any
 -		if($this->_footer!==null && $this->_footer instanceof IStyleable)
 -		{
 -			if($footerStyle=$this->getViewState('FooterStyle',null))
 -				$this->_footer->getStyle()->mergeWith($footerStyle);
 -		}
 -
 -		$selectedIndex=$this->getSelectedItemIndex();
 -		$editIndex=$this->getEditItemIndex();
 -
 -		// apply item styles if any
 -		foreach($this->getItems() as $index=>$item)
 -		{
 -			if($index===$editIndex)
 -				$style=$editItemStyle;
 -			else if($index===$selectedIndex)
 -				$style=$selectedItemStyle;
 -			else if($index%2===0)
 -				$style=$itemStyle;
 -			else
 -				$style=$alternatingItemStyle;
 -			if($style && $item instanceof IStyleable)
 -				$item->getStyle()->mergeWith($style);
 -		}
 -
 -		// apply separator style if any
 -		if(($separatorStyle=$this->getViewState('SeparatorStyle',null))!==null && $this->getHasSeparators())
 -		{
 -			$controls=$this->getControls();
 -			$count=$controls->getCount();
 -			for($i=$this->_header?2:1;$i<$count;$i+=2)
 -			{
 -				if(($separator=$controls->itemAt($i)) instanceof IStyleable)
 -					$separator->getStyle()->mergeWith($separatorStyle);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Saves item count in viewstate.
 -	 * This method is invoked right before control state is to be saved.
 -	 */
 -	public function saveState()
 -	{
 -		parent::saveState();
 -		if($this->_items)
 -			$this->setViewState('ItemCount',$this->_items->getCount(),0);
 -		else
 -			$this->clearViewState('ItemCount');
 -	}
 -
 -	/**
 -	 * Loads item count information from viewstate.
 -	 * This method is invoked right after control state is loaded.
 -	 */
 -	public function loadState()
 -	{
 -		parent::loadState();
 -		if(!$this->getIsDataBound())
 -			$this->restoreItemsFromViewState();
 -		$this->clearViewState('ItemCount');
 -	}
 -
 -	/**
 -	 * Clears up all items in the data list.
 -	 */
 -	public function reset()
 -	{
 -		$this->getControls()->clear();
 -		$this->getItems()->clear();
 -		$this->_header=null;
 -		$this->_footer=null;
 -	}
 -
 -	/**
 -	 * Creates data list items based on viewstate information.
 -	 */
 -	protected function restoreItemsFromViewState()
 -	{
 -		$this->reset();
 -		if(($itemCount=$this->getViewState('ItemCount',0))>0)
 -		{
 -			$items=$this->getItems();
 -			$selectedIndex=$this->getSelectedItemIndex();
 -			$editIndex=$this->getEditItemIndex();
 -			$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);
 -				if($i===$editIndex)
 -					$itemType=TListItemType::EditItem;
 -				else if($i===$selectedIndex)
 -					$itemType=TListItemType::SelectedItem;
 -				else
 -					$itemType=$i%2?TListItemType::AlternatingItem : TListItemType::Item;
 -				$items->add($this->createItemInternal($i,$itemType));
 -			}
 -			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer);
 -		}
 -		else
 -			$this->createEmptyContent();
 -		$this->clearChildState();
 -	}
 -
 -	/**
 -	 * Performs databinding to populate data list items from data source.
 -	 * This method is invoked by dataBind().
 -	 * You may override this function to provide your own way of data population.
 -	 * @param Traversable the data
 -	 */
 -	protected function performDataBinding($data)
 -	{
 -		$this->reset();
 -		$keys=$this->getDataKeys();
 -		$keys->clear();
 -		$keyField=$this->getDataKeyField();
 -		$itemIndex=0;
 -		$items=$this->getItems();
 -		$hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
 -		$selectedIndex=$this->getSelectedItemIndex();
 -		$editIndex=$this->getEditItemIndex();
 -		foreach($data as $key=>$dataItem)
 -		{
 -			if($keyField!=='')
 -				$keys->add($this->getDataFieldValue($dataItem,$keyField));
 -			else
 -				$keys->add($key);
 -			if($itemIndex===0)
 -				$this->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null);
 -			if($hasSeparator && $itemIndex>0)
 -				$this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null);
 -			if($itemIndex===$editIndex)
 -				$itemType=TListItemType::EditItem;
 -			else if($itemIndex===$selectedIndex)
 -				$itemType=TListItemType::SelectedItem;
 -			else
 -				$itemType=$itemIndex%2?TListItemType::AlternatingItem : TListItemType::Item;
 -			$items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem));
 -			$itemIndex++;
 -		}
 -		if($itemIndex>0)
 -			$this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null);
 -		else
 -		{
 -			$this->createEmptyContent();
 -			$this->dataBindChildren();
 -		}
 -		$this->setViewState('ItemCount',$itemIndex,0);
 -	}
 -
 -	/**
 -	 * Renders the data list control.
 -	 * This method overrides the parent implementation.
 -	 * @param THtmlWriter writer for rendering purpose.
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->getHasControls())
 -		{
 -			if($this->getItemCount()>0)
 -			{
 -				$this->applyItemStyles();
 -				$repeatInfo=$this->getRepeatInfo();
 -				$repeatInfo->renderRepeater($writer,$this);
 -			}
 -			else if($this->_emptyTemplate!==null || $this->getEmptyRenderer()!=='')
 -				parent::render($writer);
 -		}
 -	}
 -}
 -
 -
 -/**
 - * TDataListItemEventParameter class
 - *
 - * TDataListItemEventParameter encapsulates the parameter data for
 - * {@link TDataList::onItemCreated ItemCreated} event of {@link TDataList} controls.
 - * The {@link getItem Item} property indicates the DataList item related with the event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataListItemEventParameter extends TEventParameter
 -{
 -	/**
 -	 * The datalist item control responsible for the event.
 -	 * @var TControl
 -	 */
 -	private $_item=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TControl DataList item related with the corresponding event
 -	 */
 -	public function __construct($item)
 -	{
 -		$this->_item=$item;
 -	}
 -
 -	/**
 -	 * @return TControl datalist item related with the corresponding event
 -	 */
 -	public function getItem()
 -	{
 -		return $this->_item;
 -	}
 -}
 -
 -/**
 - * TDataListCommandEventParameter class
 - *
 - * TDataListCommandEventParameter encapsulates the parameter data for
 - * {@link TDataList::onItemCommand ItemCommand} event of {@link TDataList} controls.
 - *
 - * The {@link getItem Item} property indicates the DataList item related with the event.
 - * The {@link getCommandSource CommandSource} refers to the control that originally
 - * raises the Command event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataListCommandEventParameter extends TCommandEventParameter
 -{
 -	/**
 -	 * @var TControl the datalist item control responsible for the event.
 -	 */
 -	private $_item=null;
 -	/**
 -	 * @var TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	private $_source=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TControl datalist item responsible for the event
 -	 * @param TControl original event sender
 -	 * @param TCommandEventParameter original event parameter
 -	 */
 -	public function __construct($item,$source,TCommandEventParameter $param)
 -	{
 -		$this->_item=$item;
 -		$this->_source=$source;
 -		parent::__construct($param->getCommandName(),$param->getCommandParameter());
 -	}
 -
 -	/**
 -	 * @return TControl the datalist item control responsible for the event.
 -	 */
 -	public function getItem()
 -	{
 -		return $this->_item;
 -	}
 -
 -	/**
 -	 * @return TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	public function getCommandSource()
 -	{
 -		return $this->_source;
 -	}
 -}
 -
 -/**
 - * TDataListItem class
 - *
 - * A TDataListItem control represents an item in the {@link TDataList} control,
 - * such as heading section, footer section, or a data item.
 - * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}>
 - * and {@link getDataItem DataItem} properties, respectively. The type of the item
 - * is given by {@link getItemType ItemType} property.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataListItem extends TWebControl implements INamingContainer, IItemDataRenderer
 -{
 -	/**
 -	 * index of the data item in the Items collection of DataList
 -	 */
 -	private $_itemIndex;
 -	/**
 -	 * type of the TDataListItem
 -	 * @var TListItemType
 -	 */
 -	private $_itemType;
 -	/**
 -	 * value of the data associated with this item
 -	 * @var mixed
 -	 */
 -	private $_data;
 -
 -	private $_tagName='span';
 -
 -	/**
 -	 * Returns the tag name used for this control.
 -	 * @return string tag name of the control to be rendered
 -	 */
 -	protected function getTagName()
 -	{
 -		return $this->_tagName;
 -	}
 -
 -	/**
 -	 * @param string tag name of the control to be rendered
 -	 */
 -	public function setTagName($value)
 -	{
 -		$this->_tagName=$value;
 -	}
 -
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableItemStyle} to be used by a datalist item.
 -	 * @return TStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableItemStyle;
 -	}
 -
 -	/**
 -	 * @return TListItemType item type
 -	 */
 -	public function getItemType()
 -	{
 -		return $this->_itemType;
 -	}
 -
 -	/**
 -	 * @param TListItemType item type.
 -	 */
 -	public function setItemType($value)
 -	{
 -		$this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType');
 -	}
 -
 -	/**
 -	 * @return integer zero-based index of the item in the item collection of datalist
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function getData()
 -	{
 -		return $this->_data;
 -	}
 -
 -	/**
 -	 * @param mixed data to be associated with the item
 -	 * @since 3.1.0
 -	 */
 -	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 setDataItem($value)
 -	{
 -		return $this->setData($value);
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>OnCommand</b> 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 TDataListCommandEventParameter($this,$sender,$param));
 -			return true;
 -		}
 -		else
 -			return false;
 -	}
 -}
 -
 -/**
 - * TDataListItemCollection class.
 - *
 - * TDataListItemCollection represents a collection of data list items.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataListItemCollection extends TList
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by inserting only TControl descendants.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a TControl descendant.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TControl)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('datalistitemcollection_datalistitem_required');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TBaseDataList class + */ +Prado::using('System.Web.UI.WebControls.TBaseDataList'); +/** + * Includes TRepeatInfo class + */ +Prado::using('System.Web.UI.WebControls.TRepeatInfo'); + +/** + * TDataList class + * + * TDataList represents a data bound and updatable list control. + * + * Like {@link TRepeater}, TDataList displays its content repeatedly based on + * the data fetched from {@link setDataSource DataSource}. + * The repeated contents in TDataList are called items, which are controls and + * can be accessed through {@link getItems Items}. When {@link dataBind()} is + * invoked, TDataList creates an item for each row of data and binds the data + * row to the item. Optionally, a TDataList can have a header, a footer and/or + * separators between items. + * + * TDataList differs from {@link TRepeater} in that it supports tiling the items + * in different manners and it maintains status of items to handle data update. + * + * The layout of the repeated contents are specified by inline templates. + * TDataList items, header, footer, etc. are being instantiated with the corresponding + * templates when data is being bound to the repeater. + * + * Since v3.1.0, the layout can also be by renderers. A renderer is a control class + * that can be instantiated as datalist items, header, etc. A renderer can thus be viewed + * as an external template (in fact, it can also be non-templated controls). + * + * A renderer can be any control class. + * - If the class implements {@link IDataRenderer}, the <b>Data</b> + * 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 <b>ItemIndex</b> property will be set + * as the zero-based index of the item in the datalist item collection, and + * the <b>ItemType</b> property as the item's type (such as TListItemType::Item). + * {@link TDataListItemRenderer} may be used as the convenient base class which + * already implements {@link IDataItemRenderer}. + * + * The following properties are used to specify different types of template and renderer + * for a datalist: + * - {@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 datalist header. + * - {@link setFooterTemplate FooterTemplate}, {@link setFooterRenderer FooterRenderer}: + * for the datalist 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 datalist is empty. + * - {@link setEditItemTemplate EditItemTemplate}, {@link setEditItemRenderer EditItemRenderer}: + * for the row being editted. + * - {@link setSelectedItemTemplate SelectedItemTemplate}, {@link setSelectedItemRenderer SelectedItemRenderer}: + * for the row being selected. + * + * If a content type is defined with both a template and a renderer, the latter takes precedence. + * + * When {@link dataBind()} is being called, TDataList 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}: + * + * TDataList raises an {@link onItemCommand OnItemCommand} whenever a button control + * within some datalist item raises a <b>OnCommand</b> event. Therefore, + * you can handle all sorts of <b>OnCommand</b> event in a central place by + * writing an event handler for {@link onItemCommand OnItemCommand}. + * + * An additional event is raised if the <b>OnCommand</b> event has one of the following + * command names: + * - edit: user wants to edit an item. <b>OnEditCommand</b> event will be raised. + * - update: user wants to save the change to an item. <b>OnUpdateCommand</b> event will be raised. + * - select: user selects an item. <b>OnSelectedIndexChanged</b> event will be raised. + * - delete: user deletes an item. <b>OnDeleteCommand</b> event will be raised. + * - cancel: user cancels previously editting action. <b>OnCancelCommand</b> event will be raised. + * + * TDataList provides a few properties to support tiling the items. + * The number of columns used to display the data items is specified via + * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection} + * governs the order of the items being rendered. + * The layout of the data items in the list is specified via {@link setRepeatLayout RepeatLayout}, + * which can take one of the following values: + * - Table (default): items are organized using HTML table and cells. + * When using this layout, one can set {@link setCellPadding CellPadding} and + * {@link setCellSpacing CellSpacing} to adjust the cellpadding and cellpadding + * of the table, and {@link setCaption Caption} and {@link setCaptionAlign CaptionAlign} + * to add a table caption with the specified alignment. + * - Flow: items are organized using HTML spans and breaks. + * - Raw: TDataList does not generate any HTML tags to do the tiling. + * + * Items in TDataList can be in one of the three status: normal browsing, + * being editted and being selected. To change the status of a particular + * item, set {@link setSelectedItemIndex SelectedItemIndex} or + * {@link setEditItemIndex EditItemIndex}. The former will change + * the indicated item to selected mode, which will cause the item to + * use {@link setSelectedItemTemplate SelectedItemTemplate} or + * {@link setSelectedItemRenderer SelectedItemRenderer} for presentation. + * The latter will change the indicated item to edit mode and to use corresponding + * template or renderer. + * Note, if an item is in edit mode, then selecting this item will have no effect. + * + * Different styles may be applied to items in different status. The style + * application is performed in a hierarchical way: Style in higher hierarchy + * will inherit from styles in lower hierarchy. + * Starting from the lowest hierarchy, the item styles include + * - item's own style + * - {@link getItemStyle ItemStyle} + * - {@link getAlternatingItemStyle AlternatingItemStyle} + * - {@link getSelectedItemStyle SelectedItemStyle} + * - {@link getEditItemStyle EditItemStyle}. + * Therefore, if background color is set as red in {@link getItemStyle ItemStyle}, + * {@link getEditItemStyle EditItemStyle} will also have red background color + * unless it is set to a different value explicitly. + * + * When a page containing a datalist is post back, the datalist 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 datalist item and use the key to fetch the corresponding data + * from some persistent storage such as DB. + * - 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 <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUser +{ +	/** +	 * Command name that TDataList understands. They are case-insensitive. +	 */ +	const CMD_SELECT='Select'; +	const CMD_EDIT='Edit'; +	const CMD_UPDATE='Update'; +	const CMD_DELETE='Delete'; +	const CMD_CANCEL='Cancel'; + +	/** +	 * @var TDataListItemCollection item list +	 */ +	private $_items=null; +	/** +	 * @var Itemplate various item templates +	 */ +	private $_itemTemplate=null; +	private $_emptyTemplate=null; +	private $_alternatingItemTemplate=null; +	private $_selectedItemTemplate=null; +	private $_editItemTemplate=null; +	private $_headerTemplate=null; +	private $_footerTemplate=null; +	private $_separatorTemplate=null; +	/** +	 * @var TControl header item +	 */ +	private $_header=null; +	/** +	 * @var TControl footer item +	 */ +	private $_footer=null; + +	/** +	 * @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 class name for datalist items. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getItemRenderer() +	{ +		return $this->getViewState('ItemRenderer',''); +	} + +	/** +	 * Sets the item renderer class. +	 * +	 * If not empty, the class will be used to instantiate as datalist items. +	 * This property takes precedence over {@link getItemTemplate ItemTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setItemTemplate +	 * @since 3.1.0 +	 */ +	public function setItemRenderer($value) +	{ +		$this->setViewState('ItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for alternative datalist items. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 datalist items. +	 * This property takes precedence over {@link getAlternatingItemTemplate AlternatingItemTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setAlternatingItemTemplate +	 * @since 3.1.0 +	 */ +	public function setAlternatingItemRenderer($value) +	{ +		$this->setViewState('AlternatingItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for the datalist item being editted. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getEditItemRenderer() +	{ +		return $this->getViewState('EditItemRenderer',''); +	} + +	/** +	 * Sets the renderer class for the datalist item being editted. +	 * +	 * If not empty, the class will be used to instantiate as the datalist item. +	 * This property takes precedence over {@link getEditItemTemplate EditItemTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setEditItemTemplate +	 * @since 3.1.0 +	 */ +	public function setEditItemRenderer($value) +	{ +		$this->setViewState('EditItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for the datalist item being selected. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getSelectedItemRenderer() +	{ +		return $this->getViewState('SelectedItemRenderer',''); +	} + +	/** +	 * Sets the renderer class for the datalist item being selected. +	 * +	 * If not empty, the class will be used to instantiate as the datalist item. +	 * This property takes precedence over {@link getSelectedItemTemplate SelectedItemTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setSelectedItemTemplate +	 * @since 3.1.0 +	 */ +	public function setSelectedItemRenderer($value) +	{ +		$this->setViewState('SelectedItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for datalist item separators. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getSeparatorRenderer() +	{ +		return $this->getViewState('SeparatorRenderer',''); +	} + +	/** +	 * Sets the datalist item separator renderer class. +	 * +	 * If not empty, the class will be used to instantiate as datalist item separators. +	 * This property takes precedence over {@link getSeparatorTemplate SeparatorTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setSeparatorTemplate +	 * @since 3.1.0 +	 */ +	public function setSeparatorRenderer($value) +	{ +		$this->setViewState('SeparatorRenderer',$value,''); +	} + +	/** +	 * @return string the class name for datalist header item. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getHeaderRenderer() +	{ +		return $this->getViewState('HeaderRenderer',''); +	} + +	/** +	 * Sets the datalist header renderer class. +	 * +	 * If not empty, the class will be used to instantiate as datalist header item. +	 * This property takes precedence over {@link getHeaderTemplate HeaderTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setHeaderTemplate +	 * @since 3.1.0 +	 */ +	public function setHeaderRenderer($value) +	{ +		$this->setViewState('HeaderRenderer',$value,''); +	} + +	/** +	 * @return string the class name for datalist footer item. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getFooterRenderer() +	{ +		return $this->getViewState('FooterRenderer',''); +	} + +	/** +	 * Sets the datalist footer renderer class. +	 * +	 * If not empty, the class will be used to instantiate as datalist footer item. +	 * This property takes precedence over {@link getFooterTemplate FooterTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setFooterTemplate +	 * @since 3.1.0 +	 */ +	public function setFooterRenderer($value) +	{ +		$this->setViewState('FooterRenderer',$value,''); +	} + +	/** +	 * @return string the class name for empty datalist item. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getEmptyRenderer() +	{ +		return $this->getViewState('EmptyRenderer',''); +	} + +	/** +	 * Sets the datalist empty renderer class. +	 * +	 * The empty renderer is created as the child of the datalist +	 * if data bound to the datalist is empty. +	 * This property takes precedence over {@link getEmptyTemplate EmptyTemplate}. +	 * +	 * @param string the renderer class name in namespace format. +	 * @see setEmptyTemplate +	 * @since 3.1.0 +	 */ +	public function setEmptyRenderer($value) +	{ +		$this->setViewState('EmptyRenderer',$value,''); +	} + +	/** +	 * @return ITemplate the template for item +	 */ +	public function getItemTemplate() +	{ +		return $this->_itemTemplate; +	} + +	/** +	 * @param ITemplate the template for item +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_itemTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','ItemTemplate'); +	} + +	/** +	 * @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 ITemplate the template for each alternating item +	 */ +	public function getAlternatingItemTemplate() +	{ +		return $this->_alternatingItemTemplate; +	} + +	/** +	 * @param ITemplate the template for each alternating item +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setAlternatingItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_alternatingItemTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','AlternatingItemType'); +	} + +	/** +	 * @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 ITemplate the selected item template +	 */ +	public function getSelectedItemTemplate() +	{ +		return $this->_selectedItemTemplate; +	} + +	/** +	 * @param ITemplate the selected item template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setSelectedItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_selectedItemTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','SelectedItemTemplate'); +	} + +	/** +	 * @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 ITemplate the edit item template +	 */ +	public function getEditItemTemplate() +	{ +		return $this->_editItemTemplate; +	} + +	/** +	 * @param ITemplate the edit item template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setEditItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_editItemTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','EditItemTemplate'); +	} + +	/** +	 * @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 ITemplate the header template +	 */ +	public function getHeaderTemplate() +	{ +		return $this->_headerTemplate; +	} + +	/** +	 * @param ITemplate the header template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setHeaderTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_headerTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','HeaderTemplate'); +	} + +	/** +	 * @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 TControl the header item +	 */ +	public function getHeader() +	{ +		return $this->_header; +	} + +	/** +	 * @return ITemplate the footer template +	 */ +	public function getFooterTemplate() +	{ +		return $this->_footerTemplate; +	} + +	/** +	 * @param ITemplate the footer template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setFooterTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_footerTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','FooterTemplate'); +	} + +	/** +	 * @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 TControl the footer item +	 */ +	public function getFooter() +	{ +		return $this->_footer; +	} + +	/** +	 * @return ITemplate the template applied when no data is bound to the datalist +	 */ +	public function getEmptyTemplate() +	{ +		return $this->_emptyTemplate; +	} + +	/** +	 * @param ITemplate the template applied when no data is bound to the datalist +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setEmptyTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_emptyTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','EmptyTemplate'); +	} + +	/** +	 * @return ITemplate the separator template +	 */ +	public function getSeparatorTemplate() +	{ +		return $this->_separatorTemplate; +	} + +	/** +	 * @param ITemplate the separator template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setSeparatorTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_separatorTemplate=$value; +		else +			throw new TInvalidDataTypeException('datalist_template_required','SeparatorTemplate'); +	} + +	/** +	 * @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 instanceof IItemDataRenderer) && $item->getItemType()!==TListItemType::EditItem) +					$item->setItemType($current%2?TListItemType::AlternatingItem : TListItemType::Item); +			} +			if($value>=0 && $value<$itemCount) +			{ +				$item=$items->itemAt($value); +				if(($item instanceof IItemDataRenderer) && $item->getItemType()!==TListItemType::EditItem) +					$item->setItemType(TListItemType::SelectedItem); +			} +		} +	} + +	/** +	 * @return TControl 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 mixed the key value of the currently selected item +	 * @throws TInvalidOperationException if {@link getDataKeyField DataKeyField} is empty. +	 */ +	public function getSelectedDataKey() +	{ +		if($this->getDataKeyField()==='') +			throw new TInvalidOperationException('datalist_datakeyfield_required'); +		$index=$this->getSelectedItemIndex(); +		$dataKeys=$this->getDataKeys(); +		if($index>=0 && $index<$dataKeys->getCount()) +			return $dataKeys->itemAt($index); +		else +			return null; +	} + +	/** +	 * @return integer the zero-based index of the edit item in {@link getItems Items}. +	 * A value -1 means no item is in edit mode. +	 */ +	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?TListItemType::AlternatingItem : TListItemType::Item); +			if($value>=0 && $value<$itemCount) +				$items->itemAt($value)->setItemType(TListItemType::EditItem); +		} +	} + +	/** +	 * @return TControl 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 string caption of the table layout +	 */ +	public function getCaption() +	{ +		return $this->getRepeatInfo()->getCaption(); +	} + +	/** +	 * @param string caption of the table layout +	 */ +	public function setCaption($value) +	{ +		$this->getRepeatInfo()->setCaption($value); +	} + +	/** +	 * @return TTableCaptionAlign alignment of the caption of the table layout. Defaults to TTableCaptionAlign::NotSet. +	 */ +	public function getCaptionAlign() +	{ +		return $this->getRepeatInfo()->getCaptionAlign(); +	} + +	/** +	 * @return TTableCaptionAlign alignment of the caption of the table layout. +	 */ +	public function setCaptionAlign($value) +	{ +		$this->getRepeatInfo()->setCaptionAlign($value); +	} + +	/** +	 * @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 TRepeatDirection the direction of traversing the list, defaults to TRepeatDirection::Vertical +	 */ +	public function getRepeatDirection() +	{ +		return $this->getRepeatInfo()->getRepeatDirection(); +	} + +	/** +	 * @param TRepeatDirection the direction of traversing the list +	 */ +	public function setRepeatDirection($value) +	{ +		$this->getRepeatInfo()->setRepeatDirection($value); +	} + +	/** +	 * @return TRepeatLayout how the list should be displayed, using table or using line breaks. Defaults to TRepeatLayout::Table. +	 */ +	public function getRepeatLayout() +	{ +		return $this->getRepeatInfo()->getRepeatLayout(); +	} + +	/** +	 * @param TRepeatLayout how the list should be displayed, using table or using line breaks +	 */ +	public function setRepeatLayout($value) +	{ +		$this->getRepeatInfo()->setRepeatLayout($value); +	} + +	/** +	 * This method overrides parent's implementation to handle +	 * {@link onItemCommand OnItemCommand} event which is bubbled from +	 * datalist items and their 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 OnEditCommand}). +	 * 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. +	 */ +	public function bubbleEvent($sender,$param) +	{ +		if($param instanceof TDataListCommandEventParameter) +		{ +			$this->onItemCommand($param); +			$command=$param->getCommandName(); +			if(strcasecmp($command,self::CMD_SELECT)===0) +			{ +				if(($item=$param->getItem()) instanceof IItemDataRenderer) +					$this->setSelectedItemIndex($item->getItemIndex()); +				$this->onSelectedIndexChanged($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_EDIT)===0) +			{ +				$this->onEditCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_DELETE)===0) +			{ +				$this->onDeleteCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_UPDATE)===0) +			{ +				$this->onUpdateCommand($param); +				return true; +			} +			else if(strcasecmp($command,self::CMD_CANCEL)===0) +			{ +				$this->onCancelCommand($param); +				return true; +			} +		} +		return false; +	} + + +	/** +	 * Raises <b>OnItemCreated</b> event. +	 * This method is invoked after a data list item is created and instantiated with +	 * template, but before added to the page hierarchy. +	 * The datalist 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. +	 * @param TDataListItemEventParameter event parameter +	 */ +	public function onItemCreated($param) +	{ +		$this->raiseEvent('OnItemCreated',$this,$param); +	} + +	/** +	 * Raises <b>OnItemDataBound</b> event. +	 * This method is invoked right after an item is data bound. +	 * The datalist 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. +	 * @param TDataListItemEventParameter event parameter +	 */ +	public function onItemDataBound($param) +	{ +		$this->raiseEvent('OnItemDataBound',$this,$param); +	} + +	/** +	 * Raises <b>OnItemCommand</b> event. +	 * This method is invoked when a child control of the data list +	 * raises an <b>OnCommand</b> event. +	 * @param TDataListCommandEventParameter event parameter +	 */ +	public function onItemCommand($param) +	{ +		$this->raiseEvent('OnItemCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnEditCommand</b> event. +	 * This method is invoked when a child control of the data list +	 * raises an <b>OnCommand</b> event and the command name is 'edit' (case-insensitive). +	 * @param TDataListCommandEventParameter event parameter +	 */ +	public function onEditCommand($param) +	{ +		$this->raiseEvent('OnEditCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnDeleteCommand</b> event. +	 * This method is invoked when a child control of the data list +	 * raises an <b>OnCommand</b> event and the command name is 'delete' (case-insensitive). +	 * @param TDataListCommandEventParameter event parameter +	 */ +	public function onDeleteCommand($param) +	{ +		$this->raiseEvent('OnDeleteCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnUpdateCommand</b> event. +	 * This method is invoked when a child control of the data list +	 * raises an <b>OnCommand</b> event and the command name is 'update' (case-insensitive). +	 * @param TDataListCommandEventParameter event parameter +	 */ +	public function onUpdateCommand($param) +	{ +		$this->raiseEvent('OnUpdateCommand',$this,$param); +	} + +	/** +	 * Raises <b>OnCancelCommand</b> event. +	 * This method is invoked when a child control of the data list +	 * raises an <b>OnCommand</b> event and the command name is 'cancel' (case-insensitive). +	 * @param TDataListCommandEventParameter event parameter +	 */ +	public function onCancelCommand($param) +	{ +		$this->raiseEvent('OnCancelCommand',$this,$param); +	} + +	/** +	 * Returns a value indicating whether this control contains header item. +	 * This method is required by {@link IRepeatInfoUser} interface. +	 * @return boolean whether the datalist has header +	 */ +	public function getHasHeader() +	{ +		return ($this->getShowHeader() && ($this->_headerTemplate!==null || $this->getHeaderRenderer()!=='')); +	} + +	/** +	 * Returns a value indicating whether this control contains footer item. +	 * This method is required by {@link IRepeatInfoUser} interface. +	 * @return boolean whether the datalist has footer +	 */ +	public function getHasFooter() +	{ +		return ($this->getShowFooter() && ($this->_footerTemplate!==null || $this->getFooterRenderer()!=='')); +	} + +	/** +	 * 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!==null || $this->getSeparatorRenderer()!==''; +	} + +	/** +	 * 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 instanceof IStyleable) && $item->getHasStyle()) +		{ +			$style=$item->getStyle(); +			$item->clearStyle(); +			return $style; +		} +		else +			return null; +	} + +	/** +	 * 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->getItem($itemType,$index); +		if($repeatInfo->getRepeatLayout()===TRepeatLayout::Raw && get_class($item)==='TDataListItem') +			$item->setTagName('div'); +		$item->renderControl($writer); +	} + +	/** +	 * @param TListItemType item type +	 * @param integer item index +	 * @return TControl data list item with the specified item type and index +	 */ +	private function getItem($itemType,$index) +	{ +		switch($itemType) +		{ +			case TListItemType::Item: +			case TListItemType::AlternatingItem: +			case TListItemType::SelectedItem: +			case TListItemType::EditItem: +				return $this->getItems()->itemAt($index); +			case TListItemType::Header: +				return $this->getControls()->itemAt(0); +			case TListItemType::Footer: +				return $this->getControls()->itemAt($this->getControls()->getCount()-1); +			case TListItemType::Separator: +				$i=$index+$index+1; +				if($this->_headerTemplate!==null || $this->getHeaderRenderer()!=='') +					$i++; +				return $this->getControls()->itemAt($i); +		} +		return null; +	} + +	/** +	 * Creates a datalist item. +	 * This method invokes {@link createItem} to create a new datalist item. +	 * @param integer zero-based item index. +	 * @param TListItemType item type +	 * @return TControl the created item, null if item is not created +	 */ +	private function createItemInternal($itemIndex,$itemType) +	{ +		if(($item=$this->createItem($itemIndex,$itemType))!==null) +		{ +			$param=new TDataListItemEventParameter($item); +			$this->onItemCreated($param); +			$this->getControls()->add($item); +			return $item; +		} +		else +			return null; +	} + +	/** +	 * Creates a datalist item and performs databinding. +	 * This method invokes {@link createItem} to create a new datalist item. +	 * @param integer zero-based item index. +	 * @param TListItemType item type +	 * @param mixed data to be associated with the item +	 * @return TControl the created item, null if item is not created +	 */ +	private function createItemWithDataInternal($itemIndex,$itemType,$dataItem) +	{ +		if(($item=$this->createItem($itemIndex,$itemType))!==null) +		{ +			$param=new TDataListItemEventParameter($item); +			if($item instanceof IDataRenderer) +				$item->setData($dataItem); +			$this->onItemCreated($param); +			$this->getControls()->add($item); +			$item->dataBind(); +			$this->onItemDataBound($param); +			return $item; +		} +		else +			return null; +	} + +	private function getAlternatingItemDisplay() +	{ +		if(($classPath=$this->getAlternatingItemRenderer())==='' && $this->_alternatingItemTemplate===null) +			return array($this->getItemRenderer(),$this->_itemTemplate); +		else +			return array($classPath,$this->_alternatingItemTemplate); +	} + +	private function getSelectedItemDisplay($itemIndex) +	{ +		if(($classPath=$this->getSelectedItemRenderer())==='' && $this->_selectedItemTemplate===null) +		{ +			if($itemIndex%2===0) +				return array($this->getItemRenderer(),$this->_itemTemplate); +			else +				return $this->getAlternatingItemDisplay(); +		} +		else +			return array($classPath,$this->_selectedItemTemplate); +	} + +	private function getEditItemDisplay($itemIndex) +	{ +		if(($classPath=$this->getEditItemRenderer())==='' && $this->_editItemTemplate===null) +			return $this->getSelectedItemDisplay($itemIndex); +		else +			return array($classPath,$this->_editItemTemplate); +	} + +	/** +	 * Creates a datalist item instance based on the item type and index. +	 * @param integer zero-based item index +	 * @param TListItemType item type +	 * @return TControl created datalist item +	 */ +	protected function createItem($itemIndex,$itemType) +	{ +		$template=null; +		$classPath=null; +		switch($itemType) +		{ +			case TListItemType::Item : +				$classPath=$this->getItemRenderer(); +				$template=$this->_itemTemplate; +				break; +			case TListItemType::AlternatingItem : +				list($classPath,$template)=$this->getAlternatingItemDisplay(); +				break; +			case TListItemType::SelectedItem: +				list($classPath,$template)=$this->getSelectedItemDisplay($itemIndex); +				break; +			case TListItemType::EditItem: +				list($classPath,$template)=$this->getEditItemDisplay($itemIndex); +				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('datalist_itemtype_unknown',$itemType); +		} +		if($classPath!=='') +		{ +			$item=Prado::createComponent($classPath); +			if($item instanceof IItemDataRenderer) +			{ +				$item->setItemIndex($itemIndex); +				$item->setItemType($itemType); +			} +		} +		else if($template!==null) +		{ +			$item=new TDataListItem; +			$item->setItemIndex($itemIndex); +			$item->setItemType($itemType); +			$template->instantiateIn($item); +		} +		else +			$item=null; + +		return $item; +	} + +	/** +	 * Creates empty datalist content. +	 */ +	protected function createEmptyContent() +	{ +		if(($classPath=$this->getEmptyRenderer())!=='') +			$this->getControls()->add(Prado::createComponent($classPath)); +		else if($this->_emptyTemplate!==null) +			$this->_emptyTemplate->instantiateIn($this); +	} + +	/** +	 * Applies styles to items, header, footer and separators. +	 * Item styles are applied in a hierarchical way. Style in higher hierarchy +	 * will inherit from styles in lower hierarchy. +	 * Starting from the lowest hierarchy, the item styles include +	 * item's own style, {@link getItemStyle ItemStyle}, {@link getAlternatingItemStyle AlternatingItemStyle}, +	 * {@link getSelectedItemStyle SelectedItemStyle}, and {@link getEditItemStyle EditItemStyle}. +	 * Therefore, if background color is set as red in {@link getItemStyle ItemStyle}, +	 * {@link getEditItemStyle EditItemStyle} will also have red background color +	 * unless it is set to a different value explicitly. +	 */ +	protected function applyItemStyles() +	{ +		$itemStyle=$this->getViewState('ItemStyle',null); + +		$alternatingItemStyle=$this->getViewState('AlternatingItemStyle',null); +		if($itemStyle!==null) +		{ +			if($alternatingItemStyle===null) +				$alternatingItemStyle=$itemStyle; +			else +				$alternatingItemStyle->mergeWith($itemStyle); +		} + +		$selectedItemStyle=$this->getViewState('SelectedItemStyle',null); + +		$editItemStyle=$this->getViewState('EditItemStyle',null); +		if($selectedItemStyle!==null) +		{ +			if($editItemStyle===null) +				$editItemStyle=$selectedItemStyle; +			else +				$editItemStyle->mergeWith($selectedItemStyle); +		} + +		// apply header style if any +		if($this->_header!==null && $this->_header instanceof IStyleable) +		{ +			if($headerStyle=$this->getViewState('HeaderStyle',null)) +				$this->_header->getStyle()->mergeWith($headerStyle); +		} + +		// apply footer style if any +		if($this->_footer!==null && $this->_footer instanceof IStyleable) +		{ +			if($footerStyle=$this->getViewState('FooterStyle',null)) +				$this->_footer->getStyle()->mergeWith($footerStyle); +		} + +		$selectedIndex=$this->getSelectedItemIndex(); +		$editIndex=$this->getEditItemIndex(); + +		// apply item styles if any +		foreach($this->getItems() as $index=>$item) +		{ +			if($index===$editIndex) +				$style=$editItemStyle; +			else if($index===$selectedIndex) +				$style=$selectedItemStyle; +			else if($index%2===0) +				$style=$itemStyle; +			else +				$style=$alternatingItemStyle; +			if($style && $item instanceof IStyleable) +				$item->getStyle()->mergeWith($style); +		} + +		// apply separator style if any +		if(($separatorStyle=$this->getViewState('SeparatorStyle',null))!==null && $this->getHasSeparators()) +		{ +			$controls=$this->getControls(); +			$count=$controls->getCount(); +			for($i=$this->_header?2:1;$i<$count;$i+=2) +			{ +				if(($separator=$controls->itemAt($i)) instanceof IStyleable) +					$separator->getStyle()->mergeWith($separatorStyle); +			} +		} +	} + +	/** +	 * Saves item count in viewstate. +	 * This method is invoked right before control state is to be saved. +	 */ +	public function saveState() +	{ +		parent::saveState(); +		if($this->_items) +			$this->setViewState('ItemCount',$this->_items->getCount(),0); +		else +			$this->clearViewState('ItemCount'); +	} + +	/** +	 * Loads item count information from viewstate. +	 * This method is invoked right after control state is loaded. +	 */ +	public function loadState() +	{ +		parent::loadState(); +		if(!$this->getIsDataBound()) +			$this->restoreItemsFromViewState(); +		$this->clearViewState('ItemCount'); +	} + +	/** +	 * Clears up all items in the data list. +	 */ +	public function reset() +	{ +		$this->getControls()->clear(); +		$this->getItems()->clear(); +		$this->_header=null; +		$this->_footer=null; +	} + +	/** +	 * Creates data list items based on viewstate information. +	 */ +	protected function restoreItemsFromViewState() +	{ +		$this->reset(); +		if(($itemCount=$this->getViewState('ItemCount',0))>0) +		{ +			$items=$this->getItems(); +			$selectedIndex=$this->getSelectedItemIndex(); +			$editIndex=$this->getEditItemIndex(); +			$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); +				if($i===$editIndex) +					$itemType=TListItemType::EditItem; +				else if($i===$selectedIndex) +					$itemType=TListItemType::SelectedItem; +				else +					$itemType=$i%2?TListItemType::AlternatingItem : TListItemType::Item; +				$items->add($this->createItemInternal($i,$itemType)); +			} +			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer); +		} +		else +			$this->createEmptyContent(); +		$this->clearChildState(); +	} + +	/** +	 * Performs databinding to populate data list items from data source. +	 * This method is invoked by dataBind(). +	 * You may override this function to provide your own way of data population. +	 * @param Traversable the data +	 */ +	protected function performDataBinding($data) +	{ +		$this->reset(); +		$keys=$this->getDataKeys(); +		$keys->clear(); +		$keyField=$this->getDataKeyField(); +		$itemIndex=0; +		$items=$this->getItems(); +		$hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!==''; +		$selectedIndex=$this->getSelectedItemIndex(); +		$editIndex=$this->getEditItemIndex(); +		foreach($data as $key=>$dataItem) +		{ +			if($keyField!=='') +				$keys->add($this->getDataFieldValue($dataItem,$keyField)); +			else +				$keys->add($key); +			if($itemIndex===0) +				$this->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null); +			if($hasSeparator && $itemIndex>0) +				$this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null); +			if($itemIndex===$editIndex) +				$itemType=TListItemType::EditItem; +			else if($itemIndex===$selectedIndex) +				$itemType=TListItemType::SelectedItem; +			else +				$itemType=$itemIndex%2?TListItemType::AlternatingItem : TListItemType::Item; +			$items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem)); +			$itemIndex++; +		} +		if($itemIndex>0) +			$this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null); +		else +		{ +			$this->createEmptyContent(); +			$this->dataBindChildren(); +		} +		$this->setViewState('ItemCount',$itemIndex,0); +	} + +	/** +	 * Renders the data list control. +	 * This method overrides the parent implementation. +	 * @param THtmlWriter writer for rendering purpose. +	 */ +	public function render($writer) +	{ +		if($this->getHasControls()) +		{ +			if($this->getItemCount()>0) +			{ +				$this->applyItemStyles(); +				$repeatInfo=$this->getRepeatInfo(); +				$repeatInfo->renderRepeater($writer,$this); +			} +			else if($this->_emptyTemplate!==null || $this->getEmptyRenderer()!=='') +				parent::render($writer); +		} +	} +} + + +/** + * TDataListItemEventParameter class + * + * TDataListItemEventParameter encapsulates the parameter data for + * {@link TDataList::onItemCreated ItemCreated} event of {@link TDataList} controls. + * The {@link getItem Item} property indicates the DataList item related with the event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataListItemEventParameter extends TEventParameter +{ +	/** +	 * The datalist item control responsible for the event. +	 * @var TControl +	 */ +	private $_item=null; + +	/** +	 * Constructor. +	 * @param TControl DataList item related with the corresponding event +	 */ +	public function __construct($item) +	{ +		$this->_item=$item; +	} + +	/** +	 * @return TControl datalist item related with the corresponding event +	 */ +	public function getItem() +	{ +		return $this->_item; +	} +} + +/** + * TDataListCommandEventParameter class + * + * TDataListCommandEventParameter encapsulates the parameter data for + * {@link TDataList::onItemCommand ItemCommand} event of {@link TDataList} controls. + * + * The {@link getItem Item} property indicates the DataList item related with the event. + * The {@link getCommandSource CommandSource} refers to the control that originally + * raises the Command event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataListCommandEventParameter extends TCommandEventParameter +{ +	/** +	 * @var TControl the datalist item control responsible for the event. +	 */ +	private $_item=null; +	/** +	 * @var TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	private $_source=null; + +	/** +	 * Constructor. +	 * @param TControl datalist item responsible for the event +	 * @param TControl original event sender +	 * @param TCommandEventParameter original event parameter +	 */ +	public function __construct($item,$source,TCommandEventParameter $param) +	{ +		$this->_item=$item; +		$this->_source=$source; +		parent::__construct($param->getCommandName(),$param->getCommandParameter()); +	} + +	/** +	 * @return TControl the datalist item control responsible for the event. +	 */ +	public function getItem() +	{ +		return $this->_item; +	} + +	/** +	 * @return TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	public function getCommandSource() +	{ +		return $this->_source; +	} +} + +/** + * TDataListItem class + * + * A TDataListItem control represents an item in the {@link TDataList} control, + * such as heading section, footer section, or a data item. + * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}> + * and {@link getDataItem DataItem} properties, respectively. The type of the item + * is given by {@link getItemType ItemType} property. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataListItem extends TWebControl implements INamingContainer, IItemDataRenderer +{ +	/** +	 * index of the data item in the Items collection of DataList +	 */ +	private $_itemIndex; +	/** +	 * type of the TDataListItem +	 * @var TListItemType +	 */ +	private $_itemType; +	/** +	 * value of the data associated with this item +	 * @var mixed +	 */ +	private $_data; + +	private $_tagName='span'; + +	/** +	 * Returns the tag name used for this control. +	 * @return string tag name of the control to be rendered +	 */ +	protected function getTagName() +	{ +		return $this->_tagName; +	} + +	/** +	 * @param string tag name of the control to be rendered +	 */ +	public function setTagName($value) +	{ +		$this->_tagName=$value; +	} + +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableItemStyle} to be used by a datalist item. +	 * @return TStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableItemStyle; +	} + +	/** +	 * @return TListItemType item type +	 */ +	public function getItemType() +	{ +		return $this->_itemType; +	} + +	/** +	 * @param TListItemType item type. +	 */ +	public function setItemType($value) +	{ +		$this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType'); +	} + +	/** +	 * @return integer zero-based index of the item in the item collection of datalist +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function getData() +	{ +		return $this->_data; +	} + +	/** +	 * @param mixed data to be associated with the item +	 * @since 3.1.0 +	 */ +	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 setDataItem($value) +	{ +		return $this->setData($value); +	} + +	/** +	 * This method overrides parent's implementation by wrapping event parameter +	 * for <b>OnCommand</b> 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 TDataListCommandEventParameter($this,$sender,$param)); +			return true; +		} +		else +			return false; +	} +} + +/** + * TDataListItemCollection class. + * + * TDataListItemCollection represents a collection of data list items. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataListItemCollection extends TList +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by inserting only TControl descendants. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a TControl descendant. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TControl) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('datalistitemcollection_datalistitem_required'); +	} +} + diff --git a/framework/Web/UI/WebControls/TDataListItemRenderer.php b/framework/Web/UI/WebControls/TDataListItemRenderer.php index 7065dc09..53c48b6e 100644 --- a/framework/Web/UI/WebControls/TDataListItemRenderer.php +++ b/framework/Web/UI/WebControls/TDataListItemRenderer.php @@ -1,172 +1,172 @@ -<?php
 -/**
 - * TDataListItemRenderer class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDataListItemRenderer class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TDataList');
 -Prado::using('System.Web.UI.WebControls.TItemDataRenderer');
 -
 -/**
 - * TDataListItemRenderer class
 - *
 - * TDataListItemRenderer can be used as a convenient base class to
 - * define an item renderer class specific for {@link TDataList}.
 - *
 - * TDataListItemRenderer extends {@link TItemDataRenderer} and implements
 - * the bubbling scheme for the OnCommand event of data list items.
 - *
 - * TDataListItemRenderer also implements the {@link IStyleable} interface,
 - * which allows TDataList to apply CSS styles to the renders.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.0
 - */
 -class TDataListItemRenderer extends TItemDataRenderer implements IStyleable
 -{
 -	/**
 -	 * Creates a style object to be used by the control.
 -	 * This method may be overriden by controls to provide customized style.
 -	 * @return TStyle
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableItemStyle;
 -	}
 -
 -	/**
 -	 * @return boolean whether the control has defined any style information
 -	 */
 -	public function getHasStyle()
 -	{
 -		return $this->getViewState('Style',null)!==null;
 -	}
 -
 -	/**
 -	 * @return TStyle the object representing the css style of the control
 -	 */
 -	public function getStyle()
 -	{
 -		if($style=$this->getViewState('Style',null))
 -			return $style;
 -		else
 -		{
 -			$style=$this->createStyle();
 -			$this->setViewState('Style',$style,null);
 -			return $style;
 -		}
 -	}
 -
 -	/**
 -	 * Removes all style data.
 -	 */
 -	public function clearStyle()
 -	{
 -		$this->clearViewState('Style');
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>OnCommand</b> 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 TDataListCommandEventParameter($this,$sender,$param));
 -			return true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Returns the tag name used for this control.
 -	 * By default, the tag name is 'span'.
 -	 * You can override this method to provide customized tag names.
 -	 * If the tag name is empty, the opening and closing tag will NOT be rendered.
 -	 * @return string tag name of the control to be rendered
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'span';
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * By default, this method renders the style string.
 -	 * The method can be overriden to provide customized attribute rendering.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		if($style=$this->getViewState('Style',null))
 -			$style->addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the control.
 -	 * This method overrides the parent implementation by replacing it with
 -	 * the following sequence:
 -	 * - {@link renderBeginTag}
 -	 * - {@link renderContents}
 -	 * - {@link renderEndTag}
 -	 * If the {@link getTagName TagName} is empty, only {@link renderContents} is invoked.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->getTagName()!=='')
 -		{
 -			$this->renderBeginTag($writer);
 -			$this->renderContents($writer);
 -			$this->renderEndTag($writer);
 -		}
 -		else
 -			$this->renderContents($writer);
 -	}
 -
 -	/**
 -	 * Renders the openning tag for the control (including attributes)
 -	 * This method is invoked when {@link getTagName TagName} is not empty.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderBeginTag($writer)
 -	{
 -		$this->addAttributesToRender($writer);
 -		$writer->renderBeginTag($this->getTagName());
 -	}
 -
 -	/**
 -	 * Renders the body content enclosed between the control tag.
 -	 * By default, child controls and text strings will be rendered.
 -	 * You can override this method to provide customized content rendering.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -		parent::renderChildren($writer);
 -	}
 -
 -	/**
 -	 * Renders the closing tag for the control
 -	 * This method is invoked when {@link getTagName TagName} is not empty.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderEndTag($writer)
 -	{
 -		$writer->renderEndTag();
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataList'); +Prado::using('System.Web.UI.WebControls.TItemDataRenderer'); + +/** + * TDataListItemRenderer class + * + * TDataListItemRenderer can be used as a convenient base class to + * define an item renderer class specific for {@link TDataList}. + * + * TDataListItemRenderer extends {@link TItemDataRenderer} and implements + * the bubbling scheme for the OnCommand event of data list items. + * + * TDataListItemRenderer also implements the {@link IStyleable} interface, + * which allows TDataList to apply CSS styles to the renders. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.0 + */ +class TDataListItemRenderer extends TItemDataRenderer implements IStyleable +{ +	/** +	 * Creates a style object to be used by the control. +	 * This method may be overriden by controls to provide customized style. +	 * @return TStyle +	 */ +	protected function createStyle() +	{ +		return new TTableItemStyle; +	} + +	/** +	 * @return boolean whether the control has defined any style information +	 */ +	public function getHasStyle() +	{ +		return $this->getViewState('Style',null)!==null; +	} + +	/** +	 * @return TStyle the object representing the css style of the control +	 */ +	public function getStyle() +	{ +		if($style=$this->getViewState('Style',null)) +			return $style; +		else +		{ +			$style=$this->createStyle(); +			$this->setViewState('Style',$style,null); +			return $style; +		} +	} + +	/** +	 * Removes all style data. +	 */ +	public function clearStyle() +	{ +		$this->clearViewState('Style'); +	} + +	/** +	 * This method overrides parent's implementation by wrapping event parameter +	 * for <b>OnCommand</b> 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 TDataListCommandEventParameter($this,$sender,$param)); +			return true; +		} +		else +			return false; +	} + +	/** +	 * Returns the tag name used for this control. +	 * By default, the tag name is 'span'. +	 * You can override this method to provide customized tag names. +	 * If the tag name is empty, the opening and closing tag will NOT be rendered. +	 * @return string tag name of the control to be rendered +	 */ +	protected function getTagName() +	{ +		return 'span'; +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * By default, this method renders the style string. +	 * The method can be overriden to provide customized attribute rendering. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		if($style=$this->getViewState('Style',null)) +			$style->addAttributesToRender($writer); +	} + +	/** +	 * Renders the control. +	 * This method overrides the parent implementation by replacing it with +	 * the following sequence: +	 * - {@link renderBeginTag} +	 * - {@link renderContents} +	 * - {@link renderEndTag} +	 * If the {@link getTagName TagName} is empty, only {@link renderContents} is invoked. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function render($writer) +	{ +		if($this->getTagName()!=='') +		{ +			$this->renderBeginTag($writer); +			$this->renderContents($writer); +			$this->renderEndTag($writer); +		} +		else +			$this->renderContents($writer); +	} + +	/** +	 * Renders the openning tag for the control (including attributes) +	 * This method is invoked when {@link getTagName TagName} is not empty. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderBeginTag($writer) +	{ +		$this->addAttributesToRender($writer); +		$writer->renderBeginTag($this->getTagName()); +	} + +	/** +	 * Renders the body content enclosed between the control tag. +	 * By default, child controls and text strings will be rendered. +	 * You can override this method to provide customized content rendering. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +		parent::renderChildren($writer); +	} + +	/** +	 * Renders the closing tag for the control +	 * This method is invoked when {@link getTagName TagName} is not empty. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderEndTag($writer) +	{ +		$writer->renderEndTag(); +	} +} + diff --git a/framework/Web/UI/WebControls/TDataRenderer.php b/framework/Web/UI/WebControls/TDataRenderer.php index ece9d974..44ab0b1d 100644 --- a/framework/Web/UI/WebControls/TDataRenderer.php +++ b/framework/Web/UI/WebControls/TDataRenderer.php @@ -1,52 +1,52 @@ -<?php
 -/**
 - * TDataRenderer class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDataRenderer class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.2
 - */
 -
 -/**
 - * TDataRenderer class
 - *
 - * TDataRenderer is the convenient base class for template-based renderer controls.
 - * It extends {@link TTemplateControl} and implements the methods required
 - * by the {@link IDataRenderer} interface.
 - *
 - * The following property is provided by TDataRenderer:
 - * - {@link getData Data}: data associated with this renderer.
 -
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.2
 - */
 -abstract class TDataRenderer extends TTemplateControl implements IDataRenderer
 -{
 -	/**
 -	 * @var mixed data associated with this renderer
 -	 */
 -	private $_data;
 -
 -	/**
 -	 * @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;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.2 + */ + +/** + * TDataRenderer class + * + * TDataRenderer is the convenient base class for template-based renderer controls. + * It extends {@link TTemplateControl} and implements the methods required + * by the {@link IDataRenderer} interface. + * + * The following property is provided by TDataRenderer: + * - {@link getData Data}: data associated with this renderer. + + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.2 + */ +abstract class TDataRenderer extends TTemplateControl implements IDataRenderer +{ +	/** +	 * @var mixed data associated with this renderer +	 */ +	private $_data; + +	/** +	 * @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; +	} +} + diff --git a/framework/Web/UI/WebControls/TDataSourceControl.php b/framework/Web/UI/WebControls/TDataSourceControl.php index 0b07810a..f7a224af 100644 --- a/framework/Web/UI/WebControls/TDataSourceControl.php +++ b/framework/Web/UI/WebControls/TDataSourceControl.php @@ -1,118 +1,118 @@ -<?php
 -/**
 - * IDataSource, TDataSourceControl, TReadOnlyDataSource class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * IDataSource, TDataSourceControl, TReadOnlyDataSource class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * IDataSource class
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -interface IDataSource
 -{
 -	public function getView($viewName);
 -	public function getViewNames();
 -	public function onDataSourceChanged($param);
 -}
 -
 -/**
 - * TDataSourceControl class
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class TDataSourceControl extends TControl implements IDataSource
 -{
 -	public function getView($viewName)
 -	{
 -		return null;
 -	}
 -
 -	public function getViewNames()
 -	{
 -		return array();
 -	}
 -
 -	public function onDataSourceChanged($param)
 -	{
 -		$this->raiseEvent('OnDataSourceChanged',$this,$param);
 -	}
 -
 -	public function focus()
 -	{
 -		throw new TNotSupportedException('datasourcecontrol_focus_unsupported');
 -	}
 -
 -	public function getEnableTheming()
 -	{
 -		return false;
 -	}
 -
 -	public function setEnableTheming($value)
 -	{
 -		throw new TNotSupportedException('datasourcecontrol_enabletheming_unsupported');
 -	}
 -
 -	public function getSkinID()
 -	{
 -		return '';
 -	}
 -
 -	public function setSkinID($value)
 -	{
 -		throw new TNotSupportedException('datasourcecontrol_skinid_unsupported');
 -	}
 -
 -	public function getVisible($checkParents=true)
 -	{
 -		return false;
 -	}
 -
 -	public function setVisible($value)
 -	{
 -		throw new TNotSupportedException('datasourcecontrol_visible_unsupported');
 -	}
 -}
 -
 -/**
 - * TDataSourceControl class
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TReadOnlyDataSource extends TDataSourceControl
 -{
 -	private $_dataSource;
 -	private $_dataMember;
 -
 -	public function __construct($dataSource,$dataMember)
 -	{
 -		if(!is_array($dataSource) && !($dataSource instanceof IDataSource) && !($dataSource instanceof Traversable))
 -			throw new TInvalidDataTypeException('readonlydatasource_datasource_invalid');
 -		$this->_dataSource=$dataSource;
 -		$this->_dataMember=$dataMember;
 -	}
 -
 -	public function getView($viewName)
 -	{
 -		if($this->_dataSource instanceof IDataSource)
 -			return $this->_dataSource->getView($viewName);
 -		else
 -			return new TReadOnlyDataSourceView($this,$this->_dataMember,$this->_dataSource);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * IDataSource class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +interface IDataSource +{ +	public function getView($viewName); +	public function getViewNames(); +	public function onDataSourceChanged($param); +} + +/** + * TDataSourceControl class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TDataSourceControl extends TControl implements IDataSource +{ +	public function getView($viewName) +	{ +		return null; +	} + +	public function getViewNames() +	{ +		return array(); +	} + +	public function onDataSourceChanged($param) +	{ +		$this->raiseEvent('OnDataSourceChanged',$this,$param); +	} + +	public function focus() +	{ +		throw new TNotSupportedException('datasourcecontrol_focus_unsupported'); +	} + +	public function getEnableTheming() +	{ +		return false; +	} + +	public function setEnableTheming($value) +	{ +		throw new TNotSupportedException('datasourcecontrol_enabletheming_unsupported'); +	} + +	public function getSkinID() +	{ +		return ''; +	} + +	public function setSkinID($value) +	{ +		throw new TNotSupportedException('datasourcecontrol_skinid_unsupported'); +	} + +	public function getVisible($checkParents=true) +	{ +		return false; +	} + +	public function setVisible($value) +	{ +		throw new TNotSupportedException('datasourcecontrol_visible_unsupported'); +	} +} + +/** + * TDataSourceControl class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TReadOnlyDataSource extends TDataSourceControl +{ +	private $_dataSource; +	private $_dataMember; + +	public function __construct($dataSource,$dataMember) +	{ +		if(!is_array($dataSource) && !($dataSource instanceof IDataSource) && !($dataSource instanceof Traversable)) +			throw new TInvalidDataTypeException('readonlydatasource_datasource_invalid'); +		$this->_dataSource=$dataSource; +		$this->_dataMember=$dataMember; +	} + +	public function getView($viewName) +	{ +		if($this->_dataSource instanceof IDataSource) +			return $this->_dataSource->getView($viewName); +		else +			return new TReadOnlyDataSourceView($this,$this->_dataMember,$this->_dataSource); +	} +} + diff --git a/framework/Web/UI/WebControls/TDataSourceView.php b/framework/Web/UI/WebControls/TDataSourceView.php index 9e7c0128..af817a32 100644 --- a/framework/Web/UI/WebControls/TDataSourceView.php +++ b/framework/Web/UI/WebControls/TDataSourceView.php @@ -1,206 +1,206 @@ -<?php
 -/**
 - * TDataSourceSelectParameters, TDataSourceView, TReadOnlyDataSourceView class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDataSourceSelectParameters, TDataSourceView, TReadOnlyDataSourceView class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataSourceSelectParameters class
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataSourceSelectParameters extends TComponent
 -{
 -	private $_retrieveTotalRowCount=false;
 -	private $_startRowIndex=0;
 -	private $_totalRowCount=0;
 -	private $_maximumRows=0;
 -
 -	public function getStartRowIndex()
 -	{
 -		return $this->_startRowIndex;
 -	}
 -
 -	public function setStartRowIndex($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			$value=0;
 -		$this->_startRowIndex=$value;
 -	}
 -
 -	public function getMaximumRows()
 -	{
 -		return $this->_maximumRows;
 -	}
 -
 -	public function setMaximumRows($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			$value=0;
 -		$this->_maximumRows=$value;
 -	}
 -
 -	public function getRetrieveTotalRowCount()
 -	{
 -		return $this->_retrieveTotalRowCount;
 -	}
 -
 -	public function setRetrieveTotalRowCount($value)
 -	{
 -		$this->_retrieveTotalRowCount=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	public function getTotalRowCount()
 -	{
 -		return $this->_totalRowCount;
 -	}
 -
 -	public function setTotalRowCount($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			$value=0;
 -		$this->_totalRowCount=$value;
 -	}
 -}
 -
 -/**
 - * TDataSourceView class
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class TDataSourceView extends TComponent
 -{
 -	private $_owner;
 -	private $_name;
 -
 -	public function __construct(IDataSource $owner,$viewName)
 -	{
 -		$this->_owner=$owner;
 -		$this->_name=$viewName;
 -	}
 -
 -	/**
 -	 * Performs DB selection based on specified parameters.
 -	 * @param ???
 -	 * @return Traversable
 -	 */
 -	abstract public function select($parameters);
 -
 -	/**
 -	 * Inserts a DB record.
 -	 * @param array|TMap
 -	 * @return integer affected rows
 -	 */
 -	public function insertAt($values)
 -	{
 -		throw new TNotSupportedException('datasourceview_insert_unsupported');
 -	}
 -
 -	/**
 -	 * Updates DB record(s) with the specified keys and new values
 -	 * @param array|TMap keys for specifying the records to be updated
 -	 * @param array|TMap new values
 -	 * @return integer affected rows
 -	 */
 -	public function update($keys,$values)
 -	{
 -		throw new TNotSupportedException('datasourceview_update_unsupported');
 -	}
 -
 -	/**
 -	 * Deletes DB row(s) with the specified keys.
 -	 * @param array|TMap keys for specifying the rows to be deleted
 -	 * @return integer affected rows
 -	 */
 -	public function delete($keys)
 -	{
 -		throw new TNotSupportedException('datasourceview_delete_unsupported');
 -	}
 -
 -	public function getCanDelete()
 -	{
 -		return false;
 -	}
 -
 -	public function getCanInsert()
 -	{
 -		return false;
 -	}
 -
 -	public function getCanPage()
 -	{
 -		return false;
 -	}
 -
 -	public function getCanGetRowCount()
 -	{
 -		return false;
 -	}
 -
 -	public function getCanSort()
 -	{
 -		return false;
 -	}
 -
 -	public function getCanUpdate()
 -	{
 -		return false;
 -	}
 -
 -	public function getName()
 -	{
 -		return $this->_name;
 -	}
 -
 -	public function getDataSource()
 -	{
 -		return $this->_owner;
 -	}
 -
 -	public function onDataSourceViewChanged($param)
 -	{
 -		$this->raiseEvent('OnDataSourceViewChanged',$this,$param);
 -	}
 -}
 -
 -/**
 - * TReadOnlyDataSourceView class
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TReadOnlyDataSourceView extends TDataSourceView
 -{
 -	private $_dataSource=null;
 -
 -	public function __construct(IDataSource $owner,$viewName,$dataSource)
 -	{
 -		parent::__construct($owner,$viewName);
 -		if($dataSource===null || is_array($dataSource))
 -			$this->_dataSource=new TMap($dataSource);
 -		else if($dataSource instanceof Traversable)
 -			$this->_dataSource=$dataSource;
 -		else
 -			throw new TInvalidDataTypeException('readonlydatasourceview_datasource_invalid');
 -	}
 -
 -	public function select($parameters)
 -	{
 -		return $this->_dataSource;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataSourceSelectParameters class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataSourceSelectParameters extends TComponent +{ +	private $_retrieveTotalRowCount=false; +	private $_startRowIndex=0; +	private $_totalRowCount=0; +	private $_maximumRows=0; + +	public function getStartRowIndex() +	{ +		return $this->_startRowIndex; +	} + +	public function setStartRowIndex($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			$value=0; +		$this->_startRowIndex=$value; +	} + +	public function getMaximumRows() +	{ +		return $this->_maximumRows; +	} + +	public function setMaximumRows($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			$value=0; +		$this->_maximumRows=$value; +	} + +	public function getRetrieveTotalRowCount() +	{ +		return $this->_retrieveTotalRowCount; +	} + +	public function setRetrieveTotalRowCount($value) +	{ +		$this->_retrieveTotalRowCount=TPropertyValue::ensureBoolean($value); +	} + +	public function getTotalRowCount() +	{ +		return $this->_totalRowCount; +	} + +	public function setTotalRowCount($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			$value=0; +		$this->_totalRowCount=$value; +	} +} + +/** + * TDataSourceView class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TDataSourceView extends TComponent +{ +	private $_owner; +	private $_name; + +	public function __construct(IDataSource $owner,$viewName) +	{ +		$this->_owner=$owner; +		$this->_name=$viewName; +	} + +	/** +	 * Performs DB selection based on specified parameters. +	 * @param ??? +	 * @return Traversable +	 */ +	abstract public function select($parameters); + +	/** +	 * Inserts a DB record. +	 * @param array|TMap +	 * @return integer affected rows +	 */ +	public function insertAt($values) +	{ +		throw new TNotSupportedException('datasourceview_insert_unsupported'); +	} + +	/** +	 * Updates DB record(s) with the specified keys and new values +	 * @param array|TMap keys for specifying the records to be updated +	 * @param array|TMap new values +	 * @return integer affected rows +	 */ +	public function update($keys,$values) +	{ +		throw new TNotSupportedException('datasourceview_update_unsupported'); +	} + +	/** +	 * Deletes DB row(s) with the specified keys. +	 * @param array|TMap keys for specifying the rows to be deleted +	 * @return integer affected rows +	 */ +	public function delete($keys) +	{ +		throw new TNotSupportedException('datasourceview_delete_unsupported'); +	} + +	public function getCanDelete() +	{ +		return false; +	} + +	public function getCanInsert() +	{ +		return false; +	} + +	public function getCanPage() +	{ +		return false; +	} + +	public function getCanGetRowCount() +	{ +		return false; +	} + +	public function getCanSort() +	{ +		return false; +	} + +	public function getCanUpdate() +	{ +		return false; +	} + +	public function getName() +	{ +		return $this->_name; +	} + +	public function getDataSource() +	{ +		return $this->_owner; +	} + +	public function onDataSourceViewChanged($param) +	{ +		$this->raiseEvent('OnDataSourceViewChanged',$this,$param); +	} +} + +/** + * TReadOnlyDataSourceView class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TReadOnlyDataSourceView extends TDataSourceView +{ +	private $_dataSource=null; + +	public function __construct(IDataSource $owner,$viewName,$dataSource) +	{ +		parent::__construct($owner,$viewName); +		if($dataSource===null || is_array($dataSource)) +			$this->_dataSource=new TMap($dataSource); +		else if($dataSource instanceof Traversable) +			$this->_dataSource=$dataSource; +		else +			throw new TInvalidDataTypeException('readonlydatasourceview_datasource_invalid'); +	} + +	public function select($parameters) +	{ +		return $this->_dataSource; +	} +} + diff --git a/framework/Web/UI/WebControls/TDataTypeValidator.php b/framework/Web/UI/WebControls/TDataTypeValidator.php index 24372565..0e412e24 100644 --- a/framework/Web/UI/WebControls/TDataTypeValidator.php +++ b/framework/Web/UI/WebControls/TDataTypeValidator.php @@ -1,141 +1,141 @@ -<?php
 -/**
 - * TDataTypeValidator class.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDataTypeValidator class. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TDataTypeValidator class
 - *
 - * TDataTypeValidator verifies if the input data is of the type specified
 - * by {@link setDataType DataType}.
 - * The following data types are supported:
 - * - <b>Integer</b> A 32-bit signed integer data type.
 - * - <b>Float</b> A double-precision floating point number data type.
 - * - <b>Date</b> A date data type.
 - * - <b>String</b> A string data type.
 - * For <b>Date</b> type, the property {@link setDateFormat DateFormat}
 - * will be used to determine how to parse the date string. If it is not
 - * provided, the string will be assumed to be in GNU datetime format.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDataTypeValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TDataTypeValidator';
 -	}
 -
 -	/**
 -	 * @return TValidationDataType the data type that the values being compared are converted to before the comparison is made. Defaults to TValidationDataType::String.
 -	 */
 -	public function getDataType()
 -	{
 -		return $this->getViewState('DataType','String');
 -	}
 -
 -	/**
 -	 * Sets the data type that the values being compared are converted to before the comparison is made.
 -	 * @param TValidationDataType the data type
 -	 */
 -	public function setDataType($value)
 -	{
 -		$this->setViewState('DataType',TPropertyValue::ensureEnum($value,'TValidationDataType'),TValidationDataType::String);
 -	}
 -
 -	/**
 -     * Sets the date format for a date validation
 -     * @param string the date format value
 -     */
 -	public function setDateFormat($value)
 -	{
 -		$this->setViewState('DateFormat', $value, '');
 -	}
 -
 -	/**
 -	 * @return string the date validation date format if any
 -	 */
 -	public function getDateFormat()
 -	{
 -		return $this->getViewState('DateFormat', '');
 -	}
 -
 -
 -	/**
 -	 * Determine if the given value is of a particular type using RegExp.
 -	 * @param string value to check
 -	 * @return boolean true if value fits the type expression.
 -	 */
 -	protected function evaluateDataTypeCheck($value)
 -	{
 -		if($value=='')
 -			return true;
 -
 -		switch($this->getDataType())
 -		{
 -			case TValidationDataType::Integer:
 -				return preg_match('/^[-+]?[0-9]+$/',trim($value));
 -			case TValidationDataType::Float:
 -				return preg_match('/^[-+]?([0-9]*\.)?[0-9]+([eE][-+]?[0-9]+)?$/',trim($value));
 -			case TValidationDataType::Date:
 -				$dateFormat = $this->getDateFormat();
 -				if(strlen($dateFormat))
 -				{
 -					$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$dateFormat);
 -					return $formatter->isValidDate($value);
 -				}
 -				else
 -					return strtotime($value) > 0;
 -		}
 -		return true;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options = parent::getClientScriptOptions();
 -		$options['DataType']=$this->getDataType();
 -		if(($dateFormat=$this->getDateFormat())!=='')
 -			$options['DateFormat']=$dateFormat;
 -		return $options;
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input data is of valid type.
 -	 * The validation always succeeds if ControlToValidate is not specified
 -	 * or the input data is empty.
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	public function evaluateIsValid()
 -	{
 -		if(($value=$this->getValidationValue($this->getValidationTarget()))==='')
 -			return true;
 -
 -		return $this->evaluateDataTypeCheck($value);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TDataTypeValidator class + * + * TDataTypeValidator verifies if the input data is of the type specified + * by {@link setDataType DataType}. + * The following data types are supported: + * - <b>Integer</b> A 32-bit signed integer data type. + * - <b>Float</b> A double-precision floating point number data type. + * - <b>Date</b> A date data type. + * - <b>String</b> A string data type. + * For <b>Date</b> type, the property {@link setDateFormat DateFormat} + * will be used to determine how to parse the date string. If it is not + * provided, the string will be assumed to be in GNU datetime format. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDataTypeValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TDataTypeValidator'; +	} + +	/** +	 * @return TValidationDataType the data type that the values being compared are converted to before the comparison is made. Defaults to TValidationDataType::String. +	 */ +	public function getDataType() +	{ +		return $this->getViewState('DataType','String'); +	} + +	/** +	 * Sets the data type that the values being compared are converted to before the comparison is made. +	 * @param TValidationDataType the data type +	 */ +	public function setDataType($value) +	{ +		$this->setViewState('DataType',TPropertyValue::ensureEnum($value,'TValidationDataType'),TValidationDataType::String); +	} + +	/** +     * Sets the date format for a date validation +     * @param string the date format value +     */ +	public function setDateFormat($value) +	{ +		$this->setViewState('DateFormat', $value, ''); +	} + +	/** +	 * @return string the date validation date format if any +	 */ +	public function getDateFormat() +	{ +		return $this->getViewState('DateFormat', ''); +	} + + +	/** +	 * Determine if the given value is of a particular type using RegExp. +	 * @param string value to check +	 * @return boolean true if value fits the type expression. +	 */ +	protected function evaluateDataTypeCheck($value) +	{ +		if($value=='') +			return true; + +		switch($this->getDataType()) +		{ +			case TValidationDataType::Integer: +				return preg_match('/^[-+]?[0-9]+$/',trim($value)); +			case TValidationDataType::Float: +				return preg_match('/^[-+]?([0-9]*\.)?[0-9]+([eE][-+]?[0-9]+)?$/',trim($value)); +			case TValidationDataType::Date: +				$dateFormat = $this->getDateFormat(); +				if(strlen($dateFormat)) +				{ +					$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$dateFormat); +					return $formatter->isValidDate($value); +				} +				else +					return strtotime($value) > 0; +		} +		return true; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options = parent::getClientScriptOptions(); +		$options['DataType']=$this->getDataType(); +		if(($dateFormat=$this->getDateFormat())!=='') +			$options['DateFormat']=$dateFormat; +		return $options; +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input data is of valid type. +	 * The validation always succeeds if ControlToValidate is not specified +	 * or the input data is empty. +	 * @return boolean whether the validation succeeds +	 */ +	public function evaluateIsValid() +	{ +		if(($value=$this->getValidationValue($this->getValidationTarget()))==='') +			return true; + +		return $this->evaluateDataTypeCheck($value); +	} +} + diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php index 8d1a811c..866bc585 100644 --- a/framework/Web/UI/WebControls/TDatePicker.php +++ b/framework/Web/UI/WebControls/TDatePicker.php @@ -1,993 +1,993 @@ -<?php
 -/**
 - * TDatePicker class file.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TTextBox class
 - */
 -Prado::using('System.Web.UI.WebControls.TTextBox');
 -
 -/**
 - *
 - * TDatePicker class.
 - *
 - * TDatePicker displays a text box for date input purpose.
 - * When the text box receives focus, a calendar will pop up and users can
 - * pick up from it a date that will be automatically entered into the text box.
 - * The format of the date string displayed in the text box is determined by
 - * the <b>DateFormat</b> property. Valid formats are the combination of the
 - * following tokens,
 - *
 - * <code>
 - *  Character Format Pattern (en-US)
 - *  -----------------------------------------
 - *  d          day digit
 - *  dd         padded day digit e.g. 01, 02
 - *  M          month digit
 - *  MM         padded month digit
 - *  MMMM       localized month name, e.g. March, April
 - *  yy         2 digit year
 - *  yyyy       4 digit year
 - *  -----------------------------------------
 - * </code>
 - *
 - * TDatePicker has four <b>Mode</b> to show the date picker popup.
 - *
 - *  # <b>Basic</b> -- Only shows a text input, focusing on the input shows the
 - *                    date picker. This way you can access the popup using only
 - *                    the keyboard. Note that because of this, TAB-bing through
 - *                    this control will automatically select the current date if
 - *                    no previous date was selected. If you close the popup (eg.
 - *                    pressing the ESC key) you'll need to un-focus and re-focus
 - *                    the control again for the popup to reappear.
 - *  # <b>Clickable</b> -- Only shows a text input, clicking on the input shows the
 - *                    date picker. This mode solves the two small problems of the
 - *                    Basic mode. It was first introduced in Prado 3.2.
 - *  # <b>Button</b> -- Shows a button next to the text input, clicking on the
 - *                     button shows the date, button text can be by the
 - *                     <b>ButtonText</b> property
 - *  # <b>ImageButton</b> -- Shows an image next to the text input, clicking on
 - *                          the image shows the date picker, image source can be
 - *                          change through the <b>ButtonImageUrl</b> property.
 - *
 - * The <b>CssClass</b> property can be used to override the css class name
 - * for the date picker panel. <b>CalendarStyle</b> property sets the packages
 - * styles available. E.g. <b>default</b>.
 - *
 - * The <b>InputMode</b> property can be set to "TextBox" or "DropDownList" with
 - * default as "TextBox".
 - * In <b>DropDownList</b> mode, in addition to the popup date picker, three
 - * drop down list (day, month and year) are presented to select the date .
 - *
 - * The <b>PositionMode</b> property can be set to "Top" or "Bottom" with default
 - * as "Bottom". It specifies the position of the calendar popup, relative to the
 - * input field.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @author Carl G. Mathisen <carlgmathisen@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDatePicker extends TTextBox
 -{
 -	/**
 -	 * Script path relative to the TClientScriptManager::SCRIPT_PATH
 -	 */
 -	const SCRIPT_PATH = 'prado/datepicker';
 -
 -	/**
 -	 * @var TDatePickerClientScript validator client-script options.
 -	 */
 -	private $_clientScript;
 -	/**
 -	 * AutoPostBack is not supported.
 -	 */
 -	public function setAutoPostBack($value)
 -	{
 -		throw new TNotSupportedException('tdatepicker_autopostback_unsupported',
 -			get_class($this));
 -	}
 -
 -	/**
 -	 * @return string the format of the date string
 -	 */
 -	public function getDateFormat()
 -	{
 -		return $this->getViewState('DateFormat','dd-MM-yyyy');
 -	}
 -
 -	/**
 -	 * Sets the format of the date string.
 -	 * @param string the format of the date string
 -	 */
 -	public function setDateFormat($value)
 -	{
 -		$this->setViewState('DateFormat',$value,'dd-MM-yyyy');
 -	}
 -
 -	/**
 -	 * @return boolean whether the calendar window should pop up when the control receives focus
 -	 */
 -	public function getShowCalendar()
 -	{
 -		return $this->getViewState('ShowCalendar',true);
 -	}
 -
 -	/**
 -	 * Sets whether to pop up the calendar window when the control receives focus
 -	 * @param boolean whether to show the calendar window
 -	 */
 -	public function setShowCalendar($value)
 -	{
 -		$this->setViewState('ShowCalendar',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Gets the current culture.
 -	 * @return string current culture, e.g. en_AU.
 -	 */
 -	public function getCulture()
 -	{
 -		return $this->getViewState('Culture', '');
 -	}
 -
 -	/**
 -	 * Sets the culture/language for the date picker.
 -	 * @param string a culture string, e.g. en_AU.
 -	 */
 -	public function setCulture($value)
 -	{
 -		$this->setViewState('Culture', $value, '');
 -	}
 -
 -	/**
 -	 * @param TDatePickerInputMode input method of date values
 -	 */
 -	public function setInputMode($value)
 -	{
 -		$this->setViewState('InputMode', TPropertyValue::ensureEnum($value, 'TDatePickerInputMode'), TDatePickerInputMode::TextBox);
 -	}
 -
 -	/**
 -	 * @return TDatePickerInputMode input method of date values. Defaults to TDatePickerInputMode::TextBox.
 -	 */
 -	public function getInputMode()
 -	{
 -		return $this->getViewState('InputMode', TDatePickerInputMode::TextBox);
 -	}
 -
 -	/**
 -	 * @param TDatePickerMode calendar UI mode
 -	 */
 -	public function setMode($value)
 -	{
 -	   $this->setViewState('Mode', TPropertyValue::ensureEnum($value, 'TDatePickerMode'), TDatePickerMode::Basic);
 -	}
 -
 -	/**
 -	 * @return TDatePickerMode current calendar UI mode.
 -	 */
 -	public function getMode()
 -	{
 -	   return $this->getViewState('Mode', TDatePickerMode::Basic);
 -	}
 -	/**
 -	 * @param string the image url for "Image" UI mode.
 -	 */
 -	public function setButtonImageUrl($value)
 -	{
 -	   $this->setViewState('ImageUrl', $value, '');
 -	}
 -
 -	/**
 -	 * @return string the image url for "Image" UI mode.
 -	 */
 -	public function getButtonImageUrl()
 -	{
 -	   return $this->getViewState('ImageUrl', '');
 -	}
 -
 -	/**
 -	 * @param string set the calendar style
 -	 */
 -	public function setCalendarStyle($value)
 -	{
 -	   $this->setViewState('CalendarStyle', $value, 'default');
 -	}
 -
 -	/**
 -	 * @return string current calendar style
 -	 */
 -	public function getCalendarStyle()
 -	{
 -	   return $this->getViewState('CalendarStyle', 'default');
 -	}
 -
 -	/**
 -	 * Set the first day of week, with 0 as Sunday, 1 as Monday, etc.
 -	 * @param integer 0 for Sunday, 1 for Monday, 2 for Tuesday, etc.
 -	 */
 -	public function setFirstDayOfWeek($value)
 -	{
 -		$this->setViewState('FirstDayOfWeek', TPropertyValue::ensureInteger($value), 1);
 -	}
 -
 -	/**
 -	 * @return integer first day of the week
 -	 */
 -	public function getFirstDayOfWeek()
 -	{
 -		return $this->getViewState('FirstDayOfWeek', 1);
 -	}
 -
 -	/**
 -	 * @return string text for the date picker button. Default is "...".
 -	 */
 -	public function getButtonText()
 -	{
 -		return $this->getViewState('ButtonText', '...');
 -	}
 -
 -	/**
 -	 * @param string text for the date picker button
 -	 */
 -	public function setButtonText($value)
 -	{
 -		$this->setViewState('ButtonText', $value, '...');
 -	}
 -
 -	/**
 -	 * @param integer date picker starting year, default is 2000.
 -	 */
 -	public function setFromYear($value)
 -	{
 -		$this->setViewState('FromYear', TPropertyValue::ensureInteger($value), intval(@date('Y'))-5);
 -	}
 -
 -	/**
 -	 * @return integer date picker starting year, default is -5 years
 -	 */
 -	public function getFromYear()
 -	{
 -		return $this->getViewState('FromYear', intval(@date('Y'))-5);
 -	}
 -
 -	/**
 -	 * @param integer date picker ending year, default +10 years
 -	 */
 -	public function setUpToYear($value)
 -	{
 -		$this->setViewState('UpToYear', TPropertyValue::ensureInteger($value), intval(@date('Y'))+10);
 -	}
 -
 -	/**
 -	 * @return integer date picker ending year, default +10 years
 -	 */
 -	public function getUpToYear()
 -	{
 -		return $this->getViewState('UpToYear', intval(@date('Y'))+10);
 -	}
 -	
 -	/**
 -	 * @param TDatePickerPositionMode calendar UI position
 -	 */
 -	public function setPositionMode($value)
 -	{
 -	   $this->setViewState('PositionMode', TPropertyValue::ensureEnum($value, 'TDatePickerPositionMode'), TDatePickerPositionMode::Bottom);
 -	}
 -
 -	/**
 -	 * @return TDatePickerPositionMode current calendar UI position.
 -	 */
 -	public function getPositionMode()
 -	{
 -	   return $this->getViewState('PositionMode', TDatePickerPositionMode::Bottom);
 -	}
 -
 -	/**
 -	 * @return integer current selected date from the date picker as timestamp, NULL if timestamp is not set previously.
 -	 */
 -	public function getTimeStamp()
 -	{
 -		if(trim($this->getText())==='')
 -			return null;
 -		else
 -			return $this->getTimeStampFromText();
 -	}
 -
 -	/**
 -	 * Sets the date for the date picker using timestamp.
 -	 * @param float time stamp for the date picker
 -	 */
 -	public function setTimeStamp($value)
 -	{
 -		if($value===null || (is_string($value) && trim($value)===''))
 -			$this->setText('');
 -		else
 -		{
 -			$date = TPropertyValue::ensureFloat($value);
 -			$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$this->getDateFormat());
 -			$this->setText($formatter->format($date));
 -		}
 -	}
 -
 -	/**
 -	 * Returns the timestamp selected by the user.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link getTimeStamp()}.
 -	 * @return integer the timestamp of the TDatePicker control.
 -	 * @see getTimeStamp
 -	 * @since 3.1.2
 -	 */
 -	public function getData()
 -	{
 -		return $this->getTimeStamp();
 -	}
 -
 -	/**
 -	 * Sets the timestamp represented by this control.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link setTimeStamp()}.
 -	 * @param integer the timestamp of the TDatePicker control.
 -	 * @see setTimeStamp
 -	 * @since 3.1.2
 -	 */
 -	public function setData($value)
 -	{
 -		$this->setTimeStamp($value);
 -	}
 -
 -	/**
 -	 * @return string the date string.
 -	 */
 -	public function getDate()
 -	{
 -		return $this->getText();
 -	}
 -
 -	/**
 -	 * @param string date string
 -	 */
 -	public function setDate($value)
 -	{
 -		$this->setText($value);
 -	}
 -
 -	/**
 -	 * Gets the TDatePickerClientScript to set the TDatePicker event handlers.
 -	 *
 -	 * The date picker on the client-side supports the following events.
 -	 * # <tt>OnDateChanged</tt> -- raised when the date is changed.
 -	 *
 -	 * You can attach custom javascript code to each of these events
 -	 *
 -	 * @return TDatePickerClientScript javascript validator event options.
 -	 */
 -	public function getClientSide()
 -	{
 -		if($this->_clientScript===null)
 -			$this->_clientScript = $this->createClientScript();
 -		return $this->_clientScript;
 -	}
 -
 -	/**
 -	 * @return TDatePickerClientScript javascript validator event options.
 -	 */
 -	protected function createClientScript()
 -	{
 -		return new TDatePickerClientScript;
 -	}
 -
 -	/**
 -	 * Returns the value to be validated.
 -	 * This methid is required by IValidatable interface.
 -	 * @return integer the interger timestamp if valid, otherwise the original text.
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		if(($text = $this->getText()) === '')
 -			return '';
 -		$date = $this->getTimeStamp();
 -		return $date == null ? $text : $date;
 -	}
 -
 -	/**
 -	 * Publish the date picker Css asset files.
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		if($this->getInputMode() === TDatePickerInputMode::DropDownList)
 -		{
 -			$page = $this->getPage();
 -			$uniqueID = $this->getUniqueID();
 -			$page->registerPostDataLoader($uniqueID.TControl::ID_SEPARATOR.'day');
 -			$page->registerPostDataLoader($uniqueID.TControl::ID_SEPARATOR.'month');
 -			$page->registerPostDataLoader($uniqueID.TControl::ID_SEPARATOR.'year');
 -		}
 -		$this->publishCalendarStyle();
 -		$this->registerCalendarClientScriptPre();
 -	}
 -
 -	/**
 -	 * Renders body content.
 -	 * This method overrides parent implementation by adding
 -	 * additional date picker button if Mode is Button or ImageButton.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->getInputMode() == TDatePickerInputMode::TextBox)
 -		{
 -			parent::render($writer);
 -			$this->renderDatePickerButtons($writer);
 -		}
 -		else
 -		{
 -			$this->renderDropDownListCalendar($writer);
 -			if($this->hasDayPattern())
 -			{
 -				$this->registerCalendarClientScriptPost();
 -				$this->renderDatePickerButtons($writer);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Renders the date picker popup buttons.
 -	 */
 -	protected function renderDatePickerButtons($writer)
 -	{
 -		if($this->getShowCalendar())
 -		{
 -			switch ($this->getMode())
 -			{
 -				case TDatePickerMode::Button:
 -					$this->renderButtonDatePicker($writer);
 -					break;
 -				case TDatePickerMode::ImageButton :
 -					$this->renderImageButtonDatePicker($writer);
 -					break;
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Loads user input data. Override parent implementation, when InputMode
 -	 * is DropDownList call getDateFromPostData to get date data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		if($this->getInputMode() == TDatePickerInputMode::TextBox)
 -			return parent::loadPostData($key, $values);
 -		$value = $this->getDateFromPostData($key, $values);
 -		if(!$this->getReadOnly() && $this->getText()!==$value)
 -		{
 -			$this->setText($value);
 -			return true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Loads date from drop down list data.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return array the date selected
 -	 */
 -	protected function getDateFromPostData($key, $values)
 -	{
 -		$date = @getdate();
 -
 -		if(isset($values[$key.'$day']))
 -			$day = intval($values[$key.'$day']);
 -		else
 -			$day = $date['mday'];
 -
 -		if(isset($values[$key.'$month']))
 -			$month = intval($values[$key.'$month']) + 1;
 -		else
 -			$month = $date['mon'];
 -
 -		if(isset($values[$key.'$year']))
 -			$year = intval($values[$key.'$year']);
 -		else
 -			$year = $date['year'];
 -
 -		$s = Prado::createComponent('System.Util.TDateTimeStamp');
 -		$date = $s->getTimeStamp(0, 0, 0, $month, $day, $year);
 -		//$date = @mktime(0, 0, 0, $month, $day, $year);
 -
 -		$pattern = $this->getDateFormat();
 -		$pattern = str_replace(array('MMMM', 'MMM'), array('MM','MM'), $pattern);
 -		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', $pattern);
 -		return $formatter->format($date);
 -	}
 -
 -	/**
 -	 * Get javascript date picker options.
 -	 * @return array date picker client-side options
 -	 */
 -	protected function getDatePickerOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['InputMode'] = $this->getInputMode();
 -		$options['Format'] = $this->getDateFormat();
 -		$options['FirstDayOfWeek'] = $this->getFirstDayOfWeek();
 -		if(($cssClass=$this->getCssClass())!=='')
 -			$options['ClassName'] = $cssClass;
 -		$options['CalendarStyle'] = $this->getCalendarStyle();
 -		$options['FromYear'] = $this->getFromYear();
 -		$options['UpToYear'] = $this->getUpToYear();
 -		switch($this->getMode())
 -		{
 -			case TDatePickerMode::Basic:
 -				break;
 -			case TDatePickerMode::Clickable:
 -				$options['TriggerEvent'] = "click";
 -				break;
 -			default:
 -				$options['Trigger'] = $this->getDatePickerButtonID();
 -				break;
 -		}
 -		$options['PositionMode'] = $this->getPositionMode();
 -
 -		$options = array_merge($options, $this->getCulturalOptions());
 -		if($this->_clientScript!==null)
 -			$options = array_merge($options,
 -				$this->_clientScript->getOptions()->toArray());
 -		return $options;
 -	}
 -
 -	/**
 -	 * Get javascript localization options, e.g. month and weekday names.
 -	 * @return array localization options.
 -	 */
 -	protected function getCulturalOptions()
 -	{
 -		if($this->getCurrentCulture() == 'en')
 -			return array();
 -
 -		$date = $this->getLocalizedCalendarInfo();
 -		$options['MonthNames'] = $date->getMonthNames();
 -		$options['AbbreviatedMonthNames'] = $date->getAbbreviatedMonthNames();
 -		$options['ShortWeekDayNames'] = $date->getAbbreviatedDayNames();
 -
 -		return $options;
 -	}
 -
 -	/**
 -	 * @return string the current culture, falls back to application if culture is not set.
 -	 */
 -	protected function getCurrentCulture()
 -	{
 -		$app = $this->getApplication()->getGlobalization(false);
 -		return $this->getCulture() == '' ?
 -				($app ? $app->getCulture() : 'en') : $this->getCulture();
 -	}
 -
 -	/**
 -	 * @return DateTimeFormatInfo date time format information for the current culture.
 -	 */
 -	protected function getLocalizedCalendarInfo()
 -	{
 -		//expensive operations
 -		$culture = $this->getCurrentCulture();
 -		Prado::using('System.I18N.core.DateTimeFormatInfo');
 -		$info = Prado::createComponent('System.I18N.core.CultureInfo', $culture);
 -		return $info->getDateTimeFormat();
 -	}
 -
 -	/**
 -	 * Renders the drop down list date picker.
 -	 */
 -	protected function renderDropDownListCalendar($writer)
 -	{
 -		if($this->getMode() == TDatePickerMode::Basic)
 -			$this->setMode(TDatePickerMode::ImageButton);
 -		parent::addAttributesToRender($writer);
 -		$writer->removeAttribute('name');
 -		$writer->removeAttribute('type');
 -		$writer->addAttribute('id', $this->getClientID());
 -
 -		if(strlen($class = $this->getCssClass()) > 0)
 -			$writer->addAttribute('class', $class);
 -		$writer->renderBeginTag('span');
 -
 -		$s = Prado::createComponent('System.Util.TDateTimeStamp');
 -		$date = $s->getDate($this->getTimeStampFromText());
 -		//$date = @getdate($this->getTimeStampFromText());
 -
 -		$this->renderCalendarSelections($writer, $date);
 -
 -		//render a hidden input field
 -		$writer->addAttribute('name', $this->getUniqueID());
 -		$writer->addAttribute('type', 'hidden');
 -		$writer->addAttribute('value', $this->getText());
 -		$writer->renderBeginTag('input');
 -
 -		$writer->renderEndTag();
 -		$writer->renderEndTag();
 -	}
 -
 -	protected function hasDayPattern()
 -	{
 -		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',
 -						$this->getDateFormat());
 -		return ($formatter->getDayPattern()!==null);
 -	}
 -
 -	/**
 -	 * Renders the calendar drop down list depending on the DateFormat pattern.
 -	 * @param THtmlWriter the Html writer to render the drop down lists.
 -	 * @param array the current selected date
 -	 */
 -	protected function renderCalendarSelections($writer, $date)
 -	{
 -		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',
 -						$this->getDateFormat());
 -
 -		foreach($formatter->getDayMonthYearOrdering() as $type)
 -		{
 -			if($type == 'day')
 -				$this->renderCalendarDayOptions($writer,$date['mday']);
 -			elseif($type == 'month')
 -				$this->renderCalendarMonthOptions($writer,$date['mon']);
 -			elseif($type == 'year')
 -				$this->renderCalendarYearOptions($writer,$date['year']);
 -		}
 -	}
 -
 -	/**
 -	 * Gets the date from the text input using TSimpleDateFormatter
 -	 * @return integer current selected date timestamp
 -	 */
 -	protected function getTimeStampFromText()
 -	{
 -		$pattern = $this->getDateFormat();
 -		$pattern = str_replace(array('MMMM', 'MMM'), array('MM','MM'), $pattern);
 -		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$pattern);
 -		return $formatter->parse($this->getText());
 -	}
 -
 -	/**
 -	 * Renders a drop down lists.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 * @param array list of selection options
 -	 * @param mixed selected key.
 -	 */
 -	private function renderDropDownListOptions($writer,$options,$selected=null)
 -	{
 -		foreach($options as $k => $v)
 -		{
 -			$writer->addAttribute('value', $k);
 -			if($k == $selected)
 -				$writer->addAttribute('selected', 'selected');
 -			$writer->renderBeginTag('option');
 -			$writer->write($v);
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	/**
 -	 * Renders the day drop down list options.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 * @param mixed selected day.
 -	 */
 -	protected function renderCalendarDayOptions($writer, $selected=null)
 -	{
 -		$days = $this->getDropDownDayOptions();
 -		$writer->addAttribute('id', $this->getClientID().TControl::CLIENT_ID_SEPARATOR.'day');
 -		$writer->addAttribute('name', $this->getUniqueID().TControl::ID_SEPARATOR.'day');
 -		$writer->addAttribute('class', 'datepicker_day_options');
 -		if($this->getReadOnly() || !$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');
 -		$writer->renderBeginTag('select');
 -		$this->renderDropDownListOptions($writer, $days, $selected);
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * @return array list of day options for a drop down list.
 -	 */
 -	protected function getDropDownDayOptions()
 -	{
 -		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',
 -						$this->getDateFormat());
 -		$days = array();
 -		$requiresPadding = $formatter->getDayPattern() === 'dd';
 -		for($i=1;$i<=31;$i++)
 -		{
 -			$days[$i] = $requiresPadding ? str_pad($i, 2, '0', STR_PAD_LEFT) : $i;
 -		}
 -		return $days;
 -	}
 -
 -	/**
 -	 * Renders the month drop down list options.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 * @param mixed selected month.
 -	 */
 -	protected function renderCalendarMonthOptions($writer, $selected=null)
 -	{
 -		$info = $this->getLocalizedCalendarInfo();
 -		$writer->addAttribute('id', $this->getClientID().TControl::CLIENT_ID_SEPARATOR.'month');
 -		$writer->addAttribute('name', $this->getUniqueID().TControl::ID_SEPARATOR.'month');
 -		$writer->addAttribute('class', 'datepicker_month_options');
 -		if($this->getReadOnly() || !$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');
 -		$writer->renderBeginTag('select');
 -		$this->renderDropDownListOptions($writer,
 -					$this->getLocalizedMonthNames($info), $selected-1);
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Returns the localized month names that depends on the month format pattern.
 -	 * "MMMM" will return the month names, "MM" or "MMM" return abbr. month names
 -	 * and "M" return month digits.
 -	 * @param DateTimeFormatInfo localized date format information.
 -	 * @return array localized month names.
 -	 */
 -	protected function getLocalizedMonthNames($info)
 -	{
 -		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',
 -						$this->getDateFormat());
 -		switch($formatter->getMonthPattern())
 -		{
 -			case 'MMM': return $info->getAbbreviatedMonthNames();
 -			case 'MM':
 -				$array = array();
 -				for($i=1;$i<=12;$i++)
 -						$array[$i-1] = $i < 10 ? '0'.$i : $i;
 -				return $array;
 -			case 'M':
 -				$array = array(); for($i=1;$i<=12;$i++) $array[$i-1] = $i;
 -				return $array;
 -			default :	return $info->getMonthNames();
 -		}
 -	}
 -
 -	/**
 -	 * Renders the year drop down list options.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 * @param mixed selected year.
 -	 */
 -	protected function renderCalendarYearOptions($writer, $selected=null)
 -	{
 -		$years = array();
 -		for($i = $this->getFromYear(); $i <= $this->getUpToYear(); $i++)
 -			$years[$i] = $i;
 -		$writer->addAttribute('id', $this->getClientID().TControl::CLIENT_ID_SEPARATOR.'year');
 -		$writer->addAttribute('name', $this->getUniqueID().TControl::ID_SEPARATOR.'year');
 -		if($this->getReadOnly() || !$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');
 -		$writer->renderBeginTag('select');
 -		$writer->addAttribute('class', 'datepicker_year_options');
 -		$this->renderDropDownListOptions($writer, $years, $selected);
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Gets the ID for the date picker trigger button.
 -	 * @return string unique button ID
 -	 */
 -	protected function getDatePickerButtonID()
 -	{
 -		return $this->getClientID().'button';
 -	}
 -
 -	/**
 -	 * Adds an additional button such that when clicked it shows the date picker.
 -	 * @return THtmlWriter writer
 -	 */
 -	protected function renderButtonDatePicker($writer)
 -	{
 -		$writer->addAttribute('id', $this->getDatePickerButtonID());
 -		$writer->addAttribute('type', 'button');
 -		$writer->addAttribute('class', $this->getCssClass().' TDatePickerButton');
 -		$writer->addAttribute('value',$this->getButtonText());
 -		if(!$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');
 -		$writer->renderBeginTag("input");
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Adds an additional image button such that when clicked it shows the date picker.
 -	 * @return THtmlWriter writer
 -	 */
 -	 protected function renderImageButtonDatePicker($writer)
 -	{
 -		$url = $this->getButtonImageUrl();
 -		$url = empty($url) ? $this->getAssetUrl('calendar.png') : $url;
 -		$writer->addAttribute('id', $this->getDatePickerButtonID());
 -		$writer->addAttribute('src', $url);
 -		$writer->addAttribute('alt', ' ');
 -		$writer->addAttribute('class', $this->getCssClass().' TDatePickerImageButton');
 -		if(!$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');
 -		$writer->addAttribute('type', 'image');
 -		$writer->addAttribute('onclick', 'return false;');
 -		$writer->renderBeginTag('input');
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * @param string date picker asset file in the self::SCRIPT_PATH directory.
 -	 * @return string date picker asset url.
 -	 */
 -	protected function getAssetUrl($file='')
 -	{
 -		$base = $this->getPage()->getClientScript()->getPradoScriptAssetUrl();
 -		return $base.'/'.self::SCRIPT_PATH.'/'.$file;
 -	}
 -
 -	/**
 -	 * Publish the calendar style Css asset file.
 -	 * @return string Css file url.
 -	 */
 -	protected function publishCalendarStyle()
 -	{
 -		$url = $this->getAssetUrl($this->getCalendarStyle().'.css');
 -		$cs = $this->getPage()->getClientScript();
 -		if(!$cs->isStyleSheetFileRegistered($url))
 -			$cs->registerStyleSheetFile($url, $url);
 -		return $url;
 -	}
 -
 -	/**
 -	 * Add the client id to the input textbox, and register the client scripts.
 -	 * @param THtmlWriter writer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		$writer->addAttribute('id',$this->getClientID());
 -		$this->registerCalendarClientScriptPost();
 -	}
 -
 -
 -	/**
 -	 * Registers the javascript code to initialize the date picker.
 -	 */
 -	protected function registerCalendarClientScriptPre()
 -	{
 -		if($this->getShowCalendar())
 -		{
 -			$cs = $this->getPage()->getClientScript();
 -			$cs->registerPradoScript("datepicker");
 -		}
 -	}
 -
 -	protected function registerCalendarClientScriptPost()
 -	{
 -		if($this->getShowCalendar())
 -		{
 -			$cs = $this->getPage()->getClientScript();
 -			if(!$cs->isEndScriptRegistered('TDatePicker.spacer'))
 -			{
 -				$spacer = $this->getAssetUrl('spacer.gif');
 -				$code = "Prado.WebUI.TDatePicker.spacer = '$spacer';";
 -				$cs->registerEndScript('TDatePicker.spacer', $code);
 -			}
 -
 -			$options = TJavaScript::encode($this->getDatePickerOptions());
 -			$code = "new Prado.WebUI.TDatePicker($options);";
 -			$cs->registerEndScript("prado:".$this->getClientID(), $code);
 -		}
 -	}
 -}
 -
 -/**
 - * TDatePickerClientScript class.
 - *
 - * Client-side date picker event {@link setOnDateChanged OnDateChanged}
 - * can be modified through the {@link TDatePicker::getClientSide ClientSide}
 - * property of a date picker.
 - *
 - * The <tt>OnDateChanged</tt> event is raise when the date picker's date
 - * is changed.
 - * The formatted date according to {@link TDatePicker::getDateFormat DateFormat} is sent
 - * as parameter to this event
 - * 
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDatePickerClientScript extends TClientSideOptions
 -{
 -	/**
 -	 * Javascript code to execute when the date picker's date is changed.
 -	 * @param string javascript code
 -	 */
 -	public function setOnDateChanged($javascript)
 -	{
 -		$this->setFunction('OnDateChanged', $javascript);
 -	}
 -
 -	/**
 -	 * @return string javascript code to execute when the date picker's date is changed.
 -	 */
 -	public function getOnDateChanged()
 -	{
 -		return $this->getOption('OnDateChanged');
 -	}
 -}
 -
 -
 -/**
 - * TDatePickerInputMode class.
 - * TDatePickerInputMode defines the enumerable type for the possible datepicker input methods.
 - *
 - * The following enumerable values are defined:
 - * - TextBox: text boxes are used to input date values
 - * - DropDownList: dropdown lists are used to pick up date values
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDatePickerInputMode extends TEnumerable
 -{
 -	const TextBox='TextBox';
 -	const DropDownList='DropDownList';
 -}
 -
 -/**
 - * TDatePickerMode class.
 - * TDatePickerMode defines the enumerable type for the possible UI mode
 - * that a {@link TDatePicker} control can take.
 - *
 - * The following enumerable values are defined:
 - * - Basic: Only shows a text input, focusing on the input shows the date picker
 - * - Clickable: Only shows a text input, clicking on the input shows the date picker (since 3.2)
 - * - Button: Shows a button next to the text input, clicking on the button shows the date, button text can be by the
 - * - ImageButton: Shows an image next to the text input, clicking on the image shows the date picker,
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDatePickerMode extends TEnumerable
 -{
 -	const Basic='Basic';
 -	const Clickable='Clickable';
 -	const Button='Button';
 -	const ImageButton='ImageButton';
 -}
 -
 -/**
 - * TDatePickerPositionMode class.
 - * TDatePickerPositionMode defines the positions available for the calendar popup, relative to the corresponding input.
 - *
 - * The following enumerable values are defined:
 - * - Top: the date picker is placed above the input field
 - * - Bottom: the date picker is placed below the input field
 - *
 - * @author Carl G. Mathisen <carlgmathisen@gmail.com>
 - * @package System.Web.UI.WebControls
 - * @since 3.1.4
 - */
 -class TDatePickerPositionMode extends TEnumerable
 -{
 -	const Top='Top';
 -	const Bottom='Bottom';
 -}
 +<?php +/** + * TDatePicker class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TTextBox class + */ +Prado::using('System.Web.UI.WebControls.TTextBox'); + +/** + * + * TDatePicker class. + * + * TDatePicker displays a text box for date input purpose. + * When the text box receives focus, a calendar will pop up and users can + * pick up from it a date that will be automatically entered into the text box. + * The format of the date string displayed in the text box is determined by + * the <b>DateFormat</b> property. Valid formats are the combination of the + * following tokens, + * + * <code> + *  Character Format Pattern (en-US) + *  ----------------------------------------- + *  d          day digit + *  dd         padded day digit e.g. 01, 02 + *  M          month digit + *  MM         padded month digit + *  MMMM       localized month name, e.g. March, April + *  yy         2 digit year + *  yyyy       4 digit year + *  ----------------------------------------- + * </code> + * + * TDatePicker has four <b>Mode</b> to show the date picker popup. + * + *  # <b>Basic</b> -- Only shows a text input, focusing on the input shows the + *                    date picker. This way you can access the popup using only + *                    the keyboard. Note that because of this, TAB-bing through + *                    this control will automatically select the current date if + *                    no previous date was selected. If you close the popup (eg. + *                    pressing the ESC key) you'll need to un-focus and re-focus + *                    the control again for the popup to reappear. + *  # <b>Clickable</b> -- Only shows a text input, clicking on the input shows the + *                    date picker. This mode solves the two small problems of the + *                    Basic mode. It was first introduced in Prado 3.2. + *  # <b>Button</b> -- Shows a button next to the text input, clicking on the + *                     button shows the date, button text can be by the + *                     <b>ButtonText</b> property + *  # <b>ImageButton</b> -- Shows an image next to the text input, clicking on + *                          the image shows the date picker, image source can be + *                          change through the <b>ButtonImageUrl</b> property. + * + * The <b>CssClass</b> property can be used to override the css class name + * for the date picker panel. <b>CalendarStyle</b> property sets the packages + * styles available. E.g. <b>default</b>. + * + * The <b>InputMode</b> property can be set to "TextBox" or "DropDownList" with + * default as "TextBox". + * In <b>DropDownList</b> mode, in addition to the popup date picker, three + * drop down list (day, month and year) are presented to select the date . + * + * The <b>PositionMode</b> property can be set to "Top" or "Bottom" with default + * as "Bottom". It specifies the position of the calendar popup, relative to the + * input field. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @author Carl G. Mathisen <carlgmathisen@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDatePicker extends TTextBox +{ +	/** +	 * Script path relative to the TClientScriptManager::SCRIPT_PATH +	 */ +	const SCRIPT_PATH = 'prado/datepicker'; + +	/** +	 * @var TDatePickerClientScript validator client-script options. +	 */ +	private $_clientScript; +	/** +	 * AutoPostBack is not supported. +	 */ +	public function setAutoPostBack($value) +	{ +		throw new TNotSupportedException('tdatepicker_autopostback_unsupported', +			get_class($this)); +	} + +	/** +	 * @return string the format of the date string +	 */ +	public function getDateFormat() +	{ +		return $this->getViewState('DateFormat','dd-MM-yyyy'); +	} + +	/** +	 * Sets the format of the date string. +	 * @param string the format of the date string +	 */ +	public function setDateFormat($value) +	{ +		$this->setViewState('DateFormat',$value,'dd-MM-yyyy'); +	} + +	/** +	 * @return boolean whether the calendar window should pop up when the control receives focus +	 */ +	public function getShowCalendar() +	{ +		return $this->getViewState('ShowCalendar',true); +	} + +	/** +	 * Sets whether to pop up the calendar window when the control receives focus +	 * @param boolean whether to show the calendar window +	 */ +	public function setShowCalendar($value) +	{ +		$this->setViewState('ShowCalendar',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Gets the current culture. +	 * @return string current culture, e.g. en_AU. +	 */ +	public function getCulture() +	{ +		return $this->getViewState('Culture', ''); +	} + +	/** +	 * Sets the culture/language for the date picker. +	 * @param string a culture string, e.g. en_AU. +	 */ +	public function setCulture($value) +	{ +		$this->setViewState('Culture', $value, ''); +	} + +	/** +	 * @param TDatePickerInputMode input method of date values +	 */ +	public function setInputMode($value) +	{ +		$this->setViewState('InputMode', TPropertyValue::ensureEnum($value, 'TDatePickerInputMode'), TDatePickerInputMode::TextBox); +	} + +	/** +	 * @return TDatePickerInputMode input method of date values. Defaults to TDatePickerInputMode::TextBox. +	 */ +	public function getInputMode() +	{ +		return $this->getViewState('InputMode', TDatePickerInputMode::TextBox); +	} + +	/** +	 * @param TDatePickerMode calendar UI mode +	 */ +	public function setMode($value) +	{ +	   $this->setViewState('Mode', TPropertyValue::ensureEnum($value, 'TDatePickerMode'), TDatePickerMode::Basic); +	} + +	/** +	 * @return TDatePickerMode current calendar UI mode. +	 */ +	public function getMode() +	{ +	   return $this->getViewState('Mode', TDatePickerMode::Basic); +	} +	/** +	 * @param string the image url for "Image" UI mode. +	 */ +	public function setButtonImageUrl($value) +	{ +	   $this->setViewState('ImageUrl', $value, ''); +	} + +	/** +	 * @return string the image url for "Image" UI mode. +	 */ +	public function getButtonImageUrl() +	{ +	   return $this->getViewState('ImageUrl', ''); +	} + +	/** +	 * @param string set the calendar style +	 */ +	public function setCalendarStyle($value) +	{ +	   $this->setViewState('CalendarStyle', $value, 'default'); +	} + +	/** +	 * @return string current calendar style +	 */ +	public function getCalendarStyle() +	{ +	   return $this->getViewState('CalendarStyle', 'default'); +	} + +	/** +	 * Set the first day of week, with 0 as Sunday, 1 as Monday, etc. +	 * @param integer 0 for Sunday, 1 for Monday, 2 for Tuesday, etc. +	 */ +	public function setFirstDayOfWeek($value) +	{ +		$this->setViewState('FirstDayOfWeek', TPropertyValue::ensureInteger($value), 1); +	} + +	/** +	 * @return integer first day of the week +	 */ +	public function getFirstDayOfWeek() +	{ +		return $this->getViewState('FirstDayOfWeek', 1); +	} + +	/** +	 * @return string text for the date picker button. Default is "...". +	 */ +	public function getButtonText() +	{ +		return $this->getViewState('ButtonText', '...'); +	} + +	/** +	 * @param string text for the date picker button +	 */ +	public function setButtonText($value) +	{ +		$this->setViewState('ButtonText', $value, '...'); +	} + +	/** +	 * @param integer date picker starting year, default is 2000. +	 */ +	public function setFromYear($value) +	{ +		$this->setViewState('FromYear', TPropertyValue::ensureInteger($value), intval(@date('Y'))-5); +	} + +	/** +	 * @return integer date picker starting year, default is -5 years +	 */ +	public function getFromYear() +	{ +		return $this->getViewState('FromYear', intval(@date('Y'))-5); +	} + +	/** +	 * @param integer date picker ending year, default +10 years +	 */ +	public function setUpToYear($value) +	{ +		$this->setViewState('UpToYear', TPropertyValue::ensureInteger($value), intval(@date('Y'))+10); +	} + +	/** +	 * @return integer date picker ending year, default +10 years +	 */ +	public function getUpToYear() +	{ +		return $this->getViewState('UpToYear', intval(@date('Y'))+10); +	} +	 +	/** +	 * @param TDatePickerPositionMode calendar UI position +	 */ +	public function setPositionMode($value) +	{ +	   $this->setViewState('PositionMode', TPropertyValue::ensureEnum($value, 'TDatePickerPositionMode'), TDatePickerPositionMode::Bottom); +	} + +	/** +	 * @return TDatePickerPositionMode current calendar UI position. +	 */ +	public function getPositionMode() +	{ +	   return $this->getViewState('PositionMode', TDatePickerPositionMode::Bottom); +	} + +	/** +	 * @return integer current selected date from the date picker as timestamp, NULL if timestamp is not set previously. +	 */ +	public function getTimeStamp() +	{ +		if(trim($this->getText())==='') +			return null; +		else +			return $this->getTimeStampFromText(); +	} + +	/** +	 * Sets the date for the date picker using timestamp. +	 * @param float time stamp for the date picker +	 */ +	public function setTimeStamp($value) +	{ +		if($value===null || (is_string($value) && trim($value)==='')) +			$this->setText(''); +		else +		{ +			$date = TPropertyValue::ensureFloat($value); +			$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$this->getDateFormat()); +			$this->setText($formatter->format($date)); +		} +	} + +	/** +	 * Returns the timestamp selected by the user. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link getTimeStamp()}. +	 * @return integer the timestamp of the TDatePicker control. +	 * @see getTimeStamp +	 * @since 3.1.2 +	 */ +	public function getData() +	{ +		return $this->getTimeStamp(); +	} + +	/** +	 * Sets the timestamp represented by this control. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link setTimeStamp()}. +	 * @param integer the timestamp of the TDatePicker control. +	 * @see setTimeStamp +	 * @since 3.1.2 +	 */ +	public function setData($value) +	{ +		$this->setTimeStamp($value); +	} + +	/** +	 * @return string the date string. +	 */ +	public function getDate() +	{ +		return $this->getText(); +	} + +	/** +	 * @param string date string +	 */ +	public function setDate($value) +	{ +		$this->setText($value); +	} + +	/** +	 * Gets the TDatePickerClientScript to set the TDatePicker event handlers. +	 * +	 * The date picker on the client-side supports the following events. +	 * # <tt>OnDateChanged</tt> -- raised when the date is changed. +	 * +	 * You can attach custom javascript code to each of these events +	 * +	 * @return TDatePickerClientScript javascript validator event options. +	 */ +	public function getClientSide() +	{ +		if($this->_clientScript===null) +			$this->_clientScript = $this->createClientScript(); +		return $this->_clientScript; +	} + +	/** +	 * @return TDatePickerClientScript javascript validator event options. +	 */ +	protected function createClientScript() +	{ +		return new TDatePickerClientScript; +	} + +	/** +	 * Returns the value to be validated. +	 * This methid is required by IValidatable interface. +	 * @return integer the interger timestamp if valid, otherwise the original text. +	 */ +	public function getValidationPropertyValue() +	{ +		if(($text = $this->getText()) === '') +			return ''; +		$date = $this->getTimeStamp(); +		return $date == null ? $text : $date; +	} + +	/** +	 * Publish the date picker Css asset files. +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		if($this->getInputMode() === TDatePickerInputMode::DropDownList) +		{ +			$page = $this->getPage(); +			$uniqueID = $this->getUniqueID(); +			$page->registerPostDataLoader($uniqueID.TControl::ID_SEPARATOR.'day'); +			$page->registerPostDataLoader($uniqueID.TControl::ID_SEPARATOR.'month'); +			$page->registerPostDataLoader($uniqueID.TControl::ID_SEPARATOR.'year'); +		} +		$this->publishCalendarStyle(); +		$this->registerCalendarClientScriptPre(); +	} + +	/** +	 * Renders body content. +	 * This method overrides parent implementation by adding +	 * additional date picker button if Mode is Button or ImageButton. +	 * @param THtmlWriter writer +	 */ +	public function render($writer) +	{ +		if($this->getInputMode() == TDatePickerInputMode::TextBox) +		{ +			parent::render($writer); +			$this->renderDatePickerButtons($writer); +		} +		else +		{ +			$this->renderDropDownListCalendar($writer); +			if($this->hasDayPattern()) +			{ +				$this->registerCalendarClientScriptPost(); +				$this->renderDatePickerButtons($writer); +			} +		} +	} + +	/** +	 * Renders the date picker popup buttons. +	 */ +	protected function renderDatePickerButtons($writer) +	{ +		if($this->getShowCalendar()) +		{ +			switch ($this->getMode()) +			{ +				case TDatePickerMode::Button: +					$this->renderButtonDatePicker($writer); +					break; +				case TDatePickerMode::ImageButton : +					$this->renderImageButtonDatePicker($writer); +					break; +			} +		} +	} + +	/** +	 * Loads user input data. Override parent implementation, when InputMode +	 * is DropDownList call getDateFromPostData to get date data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		if($this->getInputMode() == TDatePickerInputMode::TextBox) +			return parent::loadPostData($key, $values); +		$value = $this->getDateFromPostData($key, $values); +		if(!$this->getReadOnly() && $this->getText()!==$value) +		{ +			$this->setText($value); +			return true; +		} +		else +			return false; +	} + +	/** +	 * Loads date from drop down list data. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return array the date selected +	 */ +	protected function getDateFromPostData($key, $values) +	{ +		$date = @getdate(); + +		if(isset($values[$key.'$day'])) +			$day = intval($values[$key.'$day']); +		else +			$day = $date['mday']; + +		if(isset($values[$key.'$month'])) +			$month = intval($values[$key.'$month']) + 1; +		else +			$month = $date['mon']; + +		if(isset($values[$key.'$year'])) +			$year = intval($values[$key.'$year']); +		else +			$year = $date['year']; + +		$s = Prado::createComponent('System.Util.TDateTimeStamp'); +		$date = $s->getTimeStamp(0, 0, 0, $month, $day, $year); +		//$date = @mktime(0, 0, 0, $month, $day, $year); + +		$pattern = $this->getDateFormat(); +		$pattern = str_replace(array('MMMM', 'MMM'), array('MM','MM'), $pattern); +		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', $pattern); +		return $formatter->format($date); +	} + +	/** +	 * Get javascript date picker options. +	 * @return array date picker client-side options +	 */ +	protected function getDatePickerOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['InputMode'] = $this->getInputMode(); +		$options['Format'] = $this->getDateFormat(); +		$options['FirstDayOfWeek'] = $this->getFirstDayOfWeek(); +		if(($cssClass=$this->getCssClass())!=='') +			$options['ClassName'] = $cssClass; +		$options['CalendarStyle'] = $this->getCalendarStyle(); +		$options['FromYear'] = $this->getFromYear(); +		$options['UpToYear'] = $this->getUpToYear(); +		switch($this->getMode()) +		{ +			case TDatePickerMode::Basic: +				break; +			case TDatePickerMode::Clickable: +				$options['TriggerEvent'] = "click"; +				break; +			default: +				$options['Trigger'] = $this->getDatePickerButtonID(); +				break; +		} +		$options['PositionMode'] = $this->getPositionMode(); + +		$options = array_merge($options, $this->getCulturalOptions()); +		if($this->_clientScript!==null) +			$options = array_merge($options, +				$this->_clientScript->getOptions()->toArray()); +		return $options; +	} + +	/** +	 * Get javascript localization options, e.g. month and weekday names. +	 * @return array localization options. +	 */ +	protected function getCulturalOptions() +	{ +		if($this->getCurrentCulture() == 'en') +			return array(); + +		$date = $this->getLocalizedCalendarInfo(); +		$options['MonthNames'] = $date->getMonthNames(); +		$options['AbbreviatedMonthNames'] = $date->getAbbreviatedMonthNames(); +		$options['ShortWeekDayNames'] = $date->getAbbreviatedDayNames(); + +		return $options; +	} + +	/** +	 * @return string the current culture, falls back to application if culture is not set. +	 */ +	protected function getCurrentCulture() +	{ +		$app = $this->getApplication()->getGlobalization(false); +		return $this->getCulture() == '' ? +				($app ? $app->getCulture() : 'en') : $this->getCulture(); +	} + +	/** +	 * @return DateTimeFormatInfo date time format information for the current culture. +	 */ +	protected function getLocalizedCalendarInfo() +	{ +		//expensive operations +		$culture = $this->getCurrentCulture(); +		Prado::using('System.I18N.core.DateTimeFormatInfo'); +		$info = Prado::createComponent('System.I18N.core.CultureInfo', $culture); +		return $info->getDateTimeFormat(); +	} + +	/** +	 * Renders the drop down list date picker. +	 */ +	protected function renderDropDownListCalendar($writer) +	{ +		if($this->getMode() == TDatePickerMode::Basic) +			$this->setMode(TDatePickerMode::ImageButton); +		parent::addAttributesToRender($writer); +		$writer->removeAttribute('name'); +		$writer->removeAttribute('type'); +		$writer->addAttribute('id', $this->getClientID()); + +		if(strlen($class = $this->getCssClass()) > 0) +			$writer->addAttribute('class', $class); +		$writer->renderBeginTag('span'); + +		$s = Prado::createComponent('System.Util.TDateTimeStamp'); +		$date = $s->getDate($this->getTimeStampFromText()); +		//$date = @getdate($this->getTimeStampFromText()); + +		$this->renderCalendarSelections($writer, $date); + +		//render a hidden input field +		$writer->addAttribute('name', $this->getUniqueID()); +		$writer->addAttribute('type', 'hidden'); +		$writer->addAttribute('value', $this->getText()); +		$writer->renderBeginTag('input'); + +		$writer->renderEndTag(); +		$writer->renderEndTag(); +	} + +	protected function hasDayPattern() +	{ +		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', +						$this->getDateFormat()); +		return ($formatter->getDayPattern()!==null); +	} + +	/** +	 * Renders the calendar drop down list depending on the DateFormat pattern. +	 * @param THtmlWriter the Html writer to render the drop down lists. +	 * @param array the current selected date +	 */ +	protected function renderCalendarSelections($writer, $date) +	{ +		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', +						$this->getDateFormat()); + +		foreach($formatter->getDayMonthYearOrdering() as $type) +		{ +			if($type == 'day') +				$this->renderCalendarDayOptions($writer,$date['mday']); +			elseif($type == 'month') +				$this->renderCalendarMonthOptions($writer,$date['mon']); +			elseif($type == 'year') +				$this->renderCalendarYearOptions($writer,$date['year']); +		} +	} + +	/** +	 * Gets the date from the text input using TSimpleDateFormatter +	 * @return integer current selected date timestamp +	 */ +	protected function getTimeStampFromText() +	{ +		$pattern = $this->getDateFormat(); +		$pattern = str_replace(array('MMMM', 'MMM'), array('MM','MM'), $pattern); +		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$pattern); +		return $formatter->parse($this->getText()); +	} + +	/** +	 * Renders a drop down lists. +	 * @param THtmlWriter the writer used for the rendering purpose +	 * @param array list of selection options +	 * @param mixed selected key. +	 */ +	private function renderDropDownListOptions($writer,$options,$selected=null) +	{ +		foreach($options as $k => $v) +		{ +			$writer->addAttribute('value', $k); +			if($k == $selected) +				$writer->addAttribute('selected', 'selected'); +			$writer->renderBeginTag('option'); +			$writer->write($v); +			$writer->renderEndTag(); +		} +	} + +	/** +	 * Renders the day drop down list options. +	 * @param THtmlWriter the writer used for the rendering purpose +	 * @param mixed selected day. +	 */ +	protected function renderCalendarDayOptions($writer, $selected=null) +	{ +		$days = $this->getDropDownDayOptions(); +		$writer->addAttribute('id', $this->getClientID().TControl::CLIENT_ID_SEPARATOR.'day'); +		$writer->addAttribute('name', $this->getUniqueID().TControl::ID_SEPARATOR.'day'); +		$writer->addAttribute('class', 'datepicker_day_options'); +		if($this->getReadOnly() || !$this->getEnabled(true)) +			$writer->addAttribute('disabled', 'disabled'); +		$writer->renderBeginTag('select'); +		$this->renderDropDownListOptions($writer, $days, $selected); +		$writer->renderEndTag(); +	} + +	/** +	 * @return array list of day options for a drop down list. +	 */ +	protected function getDropDownDayOptions() +	{ +		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', +						$this->getDateFormat()); +		$days = array(); +		$requiresPadding = $formatter->getDayPattern() === 'dd'; +		for($i=1;$i<=31;$i++) +		{ +			$days[$i] = $requiresPadding ? str_pad($i, 2, '0', STR_PAD_LEFT) : $i; +		} +		return $days; +	} + +	/** +	 * Renders the month drop down list options. +	 * @param THtmlWriter the writer used for the rendering purpose +	 * @param mixed selected month. +	 */ +	protected function renderCalendarMonthOptions($writer, $selected=null) +	{ +		$info = $this->getLocalizedCalendarInfo(); +		$writer->addAttribute('id', $this->getClientID().TControl::CLIENT_ID_SEPARATOR.'month'); +		$writer->addAttribute('name', $this->getUniqueID().TControl::ID_SEPARATOR.'month'); +		$writer->addAttribute('class', 'datepicker_month_options'); +		if($this->getReadOnly() || !$this->getEnabled(true)) +			$writer->addAttribute('disabled', 'disabled'); +		$writer->renderBeginTag('select'); +		$this->renderDropDownListOptions($writer, +					$this->getLocalizedMonthNames($info), $selected-1); +		$writer->renderEndTag(); +	} + +	/** +	 * Returns the localized month names that depends on the month format pattern. +	 * "MMMM" will return the month names, "MM" or "MMM" return abbr. month names +	 * and "M" return month digits. +	 * @param DateTimeFormatInfo localized date format information. +	 * @return array localized month names. +	 */ +	protected function getLocalizedMonthNames($info) +	{ +		$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter', +						$this->getDateFormat()); +		switch($formatter->getMonthPattern()) +		{ +			case 'MMM': return $info->getAbbreviatedMonthNames(); +			case 'MM': +				$array = array(); +				for($i=1;$i<=12;$i++) +						$array[$i-1] = $i < 10 ? '0'.$i : $i; +				return $array; +			case 'M': +				$array = array(); for($i=1;$i<=12;$i++) $array[$i-1] = $i; +				return $array; +			default :	return $info->getMonthNames(); +		} +	} + +	/** +	 * Renders the year drop down list options. +	 * @param THtmlWriter the writer used for the rendering purpose +	 * @param mixed selected year. +	 */ +	protected function renderCalendarYearOptions($writer, $selected=null) +	{ +		$years = array(); +		for($i = $this->getFromYear(); $i <= $this->getUpToYear(); $i++) +			$years[$i] = $i; +		$writer->addAttribute('id', $this->getClientID().TControl::CLIENT_ID_SEPARATOR.'year'); +		$writer->addAttribute('name', $this->getUniqueID().TControl::ID_SEPARATOR.'year'); +		if($this->getReadOnly() || !$this->getEnabled(true)) +			$writer->addAttribute('disabled', 'disabled'); +		$writer->renderBeginTag('select'); +		$writer->addAttribute('class', 'datepicker_year_options'); +		$this->renderDropDownListOptions($writer, $years, $selected); +		$writer->renderEndTag(); +	} + +	/** +	 * Gets the ID for the date picker trigger button. +	 * @return string unique button ID +	 */ +	protected function getDatePickerButtonID() +	{ +		return $this->getClientID().'button'; +	} + +	/** +	 * Adds an additional button such that when clicked it shows the date picker. +	 * @return THtmlWriter writer +	 */ +	protected function renderButtonDatePicker($writer) +	{ +		$writer->addAttribute('id', $this->getDatePickerButtonID()); +		$writer->addAttribute('type', 'button'); +		$writer->addAttribute('class', $this->getCssClass().' TDatePickerButton'); +		$writer->addAttribute('value',$this->getButtonText()); +		if(!$this->getEnabled(true)) +			$writer->addAttribute('disabled', 'disabled'); +		$writer->renderBeginTag("input"); +		$writer->renderEndTag(); +	} + +	/** +	 * Adds an additional image button such that when clicked it shows the date picker. +	 * @return THtmlWriter writer +	 */ +	 protected function renderImageButtonDatePicker($writer) +	{ +		$url = $this->getButtonImageUrl(); +		$url = empty($url) ? $this->getAssetUrl('calendar.png') : $url; +		$writer->addAttribute('id', $this->getDatePickerButtonID()); +		$writer->addAttribute('src', $url); +		$writer->addAttribute('alt', ' '); +		$writer->addAttribute('class', $this->getCssClass().' TDatePickerImageButton'); +		if(!$this->getEnabled(true)) +			$writer->addAttribute('disabled', 'disabled'); +		$writer->addAttribute('type', 'image'); +		$writer->addAttribute('onclick', 'return false;'); +		$writer->renderBeginTag('input'); +		$writer->renderEndTag(); +	} + +	/** +	 * @param string date picker asset file in the self::SCRIPT_PATH directory. +	 * @return string date picker asset url. +	 */ +	protected function getAssetUrl($file='') +	{ +		$base = $this->getPage()->getClientScript()->getPradoScriptAssetUrl(); +		return $base.'/'.self::SCRIPT_PATH.'/'.$file; +	} + +	/** +	 * Publish the calendar style Css asset file. +	 * @return string Css file url. +	 */ +	protected function publishCalendarStyle() +	{ +		$url = $this->getAssetUrl($this->getCalendarStyle().'.css'); +		$cs = $this->getPage()->getClientScript(); +		if(!$cs->isStyleSheetFileRegistered($url)) +			$cs->registerStyleSheetFile($url, $url); +		return $url; +	} + +	/** +	 * Add the client id to the input textbox, and register the client scripts. +	 * @param THtmlWriter writer +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		$writer->addAttribute('id',$this->getClientID()); +		$this->registerCalendarClientScriptPost(); +	} + + +	/** +	 * Registers the javascript code to initialize the date picker. +	 */ +	protected function registerCalendarClientScriptPre() +	{ +		if($this->getShowCalendar()) +		{ +			$cs = $this->getPage()->getClientScript(); +			$cs->registerPradoScript("datepicker"); +		} +	} + +	protected function registerCalendarClientScriptPost() +	{ +		if($this->getShowCalendar()) +		{ +			$cs = $this->getPage()->getClientScript(); +			if(!$cs->isEndScriptRegistered('TDatePicker.spacer')) +			{ +				$spacer = $this->getAssetUrl('spacer.gif'); +				$code = "Prado.WebUI.TDatePicker.spacer = '$spacer';"; +				$cs->registerEndScript('TDatePicker.spacer', $code); +			} + +			$options = TJavaScript::encode($this->getDatePickerOptions()); +			$code = "new Prado.WebUI.TDatePicker($options);"; +			$cs->registerEndScript("prado:".$this->getClientID(), $code); +		} +	} +} + +/** + * TDatePickerClientScript class. + * + * Client-side date picker event {@link setOnDateChanged OnDateChanged} + * can be modified through the {@link TDatePicker::getClientSide ClientSide} + * property of a date picker. + * + * The <tt>OnDateChanged</tt> event is raise when the date picker's date + * is changed. + * The formatted date according to {@link TDatePicker::getDateFormat DateFormat} is sent + * as parameter to this event + *  + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDatePickerClientScript extends TClientSideOptions +{ +	/** +	 * Javascript code to execute when the date picker's date is changed. +	 * @param string javascript code +	 */ +	public function setOnDateChanged($javascript) +	{ +		$this->setFunction('OnDateChanged', $javascript); +	} + +	/** +	 * @return string javascript code to execute when the date picker's date is changed. +	 */ +	public function getOnDateChanged() +	{ +		return $this->getOption('OnDateChanged'); +	} +} + + +/** + * TDatePickerInputMode class. + * TDatePickerInputMode defines the enumerable type for the possible datepicker input methods. + * + * The following enumerable values are defined: + * - TextBox: text boxes are used to input date values + * - DropDownList: dropdown lists are used to pick up date values + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDatePickerInputMode extends TEnumerable +{ +	const TextBox='TextBox'; +	const DropDownList='DropDownList'; +} + +/** + * TDatePickerMode class. + * TDatePickerMode defines the enumerable type for the possible UI mode + * that a {@link TDatePicker} control can take. + * + * The following enumerable values are defined: + * - Basic: Only shows a text input, focusing on the input shows the date picker + * - Clickable: Only shows a text input, clicking on the input shows the date picker (since 3.2) + * - Button: Shows a button next to the text input, clicking on the button shows the date, button text can be by the + * - ImageButton: Shows an image next to the text input, clicking on the image shows the date picker, + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDatePickerMode extends TEnumerable +{ +	const Basic='Basic'; +	const Clickable='Clickable'; +	const Button='Button'; +	const ImageButton='ImageButton'; +} + +/** + * TDatePickerPositionMode class. + * TDatePickerPositionMode defines the positions available for the calendar popup, relative to the corresponding input. + * + * The following enumerable values are defined: + * - Top: the date picker is placed above the input field + * - Bottom: the date picker is placed below the input field + * + * @author Carl G. Mathisen <carlgmathisen@gmail.com> + * @package System.Web.UI.WebControls + * @since 3.1.4 + */ +class TDatePickerPositionMode extends TEnumerable +{ +	const Top='Top'; +	const Bottom='Bottom'; +} diff --git a/framework/Web/UI/WebControls/TDropDownList.php b/framework/Web/UI/WebControls/TDropDownList.php index 0eba6285..57f1f165 100644 --- a/framework/Web/UI/WebControls/TDropDownList.php +++ b/framework/Web/UI/WebControls/TDropDownList.php @@ -1,154 +1,154 @@ -<?php
 -/**
 - * TDropDownList class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TListControl class
 - */
 -Prado::using('System.Web.UI.WebControls.TListControl');
 -
 -/**
 - * TDropDownList class
 - *
 - * TDropDownList displays a dropdown list on a Web page.
 - * It inherits all properties and events from {@link TListControl}.
 - *
 - * Since v3.0.3, TDropDownList starts to support optgroup. To specify an option group for
 - * a list item, set a Group attribute with it,
 - * <code>
 - *  $listitem->Attributes->Group="Group Name";
 - *  // or <com:TListItem Attributes.Group="Group Name" .../> in template
 - * </code>
 - *
 - * Since v3.1.1, TDropDownList starts to support prompt text. That is, a prompt item can be
 - * displayed as the first list item by specifying either {@link setPromptText PromptText} or
 - * {@link setPromptValue PromptValue}, or both. Choosing the prompt item will unselect the TDropDownList.
 - *
 - * When a prompt item is set, its index in the list is set to -1. So, the {@link getSelectedIndex SelectedIndex}
 - * property is not affected by a prompt item: the items list will still be zero-based.
 - *
 - * The {@link clearSelection clearSelection} method will select the prompt item if existing, otherway the first
 - * available item in the dropdown list will be selected.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TDropDownList extends TListControl implements IPostBackDataHandler, IValidatable
 -{
 -	private $_dataChanged=false;
 -	private $_isValid=true;
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$writer->addAttribute('name',$this->getUniqueID());
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TDropDownList';
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		if(!$this->getEnabled(true))
 -			return false;
 -		$this->ensureDataBound();
 -		$selection=isset($values[$key])?$values[$key]:null;
 -		if($selection!==null)
 -		{
 -			$index=$this->getItems()->findIndexByValue($selection,false);
 -			if($this->getSelectedIndex()!==$index)
 -			{
 -				$this->setSelectedIndex($index);
 -				return $this->_dataChanged=true;
 -			}
 -		}
 -		return false;
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method is required by {@link IPostBackDataHandler} interface.
 -	 * It is invoked by the framework when {@link getSelectedIndex SelectedIndex} property
 -	 * is changed on postback.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		if($this->getAutoPostBack() && $this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onSelectedIndexChanged(null);
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * @throws TNotSupportedException if this method is invoked
 -	 */
 -	public function setSelectedIndices($indices)
 -	{
 -		throw new TNotSupportedException('dropdownlist_selectedindices_unsupported');
 -	}
 -
 -	/**
 -	 * Returns the value to be validated.
 -	 * This methid is required by IValidatable interface.
 -	 * @return mixed the value of the property to be validated.
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getSelectedValue();
 -	}
 -
 -	/**
 -	 * Returns true if this control validated successfully. 
 -	 * Defaults to true.
 -	 * @return bool wether this control validated successfully.
 -	 */
 -	public function getIsValid()
 -	{
 -	    return $this->_isValid;
 -	}
 -	/**
 -	 * @param bool wether this control is valid.
 -	 */
 -	public function setIsValid($value)
 -	{
 -	    $this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -}
 +<?php +/** + * TDropDownList class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TListControl class + */ +Prado::using('System.Web.UI.WebControls.TListControl'); + +/** + * TDropDownList class + * + * TDropDownList displays a dropdown list on a Web page. + * It inherits all properties and events from {@link TListControl}. + * + * Since v3.0.3, TDropDownList starts to support optgroup. To specify an option group for + * a list item, set a Group attribute with it, + * <code> + *  $listitem->Attributes->Group="Group Name"; + *  // or <com:TListItem Attributes.Group="Group Name" .../> in template + * </code> + * + * Since v3.1.1, TDropDownList starts to support prompt text. That is, a prompt item can be + * displayed as the first list item by specifying either {@link setPromptText PromptText} or + * {@link setPromptValue PromptValue}, or both. Choosing the prompt item will unselect the TDropDownList. + * + * When a prompt item is set, its index in the list is set to -1. So, the {@link getSelectedIndex SelectedIndex} + * property is not affected by a prompt item: the items list will still be zero-based. + * + * The {@link clearSelection clearSelection} method will select the prompt item if existing, otherway the first + * available item in the dropdown list will be selected. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TDropDownList extends TListControl implements IPostBackDataHandler, IValidatable +{ +	private $_dataChanged=false; +	private $_isValid=true; + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 */ +	protected function addAttributesToRender($writer) +	{ +		$writer->addAttribute('name',$this->getUniqueID()); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TDropDownList'; +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		if(!$this->getEnabled(true)) +			return false; +		$this->ensureDataBound(); +		$selection=isset($values[$key])?$values[$key]:null; +		if($selection!==null) +		{ +			$index=$this->getItems()->findIndexByValue($selection,false); +			if($this->getSelectedIndex()!==$index) +			{ +				$this->setSelectedIndex($index); +				return $this->_dataChanged=true; +			} +		} +		return false; +	} + +	/** +	 * Raises postdata changed event. +	 * This method is required by {@link IPostBackDataHandler} interface. +	 * It is invoked by the framework when {@link getSelectedIndex SelectedIndex} property +	 * is changed on postback. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		if($this->getAutoPostBack() && $this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onSelectedIndexChanged(null); +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * @throws TNotSupportedException if this method is invoked +	 */ +	public function setSelectedIndices($indices) +	{ +		throw new TNotSupportedException('dropdownlist_selectedindices_unsupported'); +	} + +	/** +	 * Returns the value to be validated. +	 * This methid is required by IValidatable interface. +	 * @return mixed the value of the property to be validated. +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getSelectedValue(); +	} + +	/** +	 * Returns true if this control validated successfully.  +	 * Defaults to true. +	 * @return bool wether this control validated successfully. +	 */ +	public function getIsValid() +	{ +	    return $this->_isValid; +	} +	/** +	 * @param bool wether this control is valid. +	 */ +	public function setIsValid($value) +	{ +	    $this->_isValid=TPropertyValue::ensureBoolean($value); +	} +} diff --git a/framework/Web/UI/WebControls/TDropDownListColumn.php b/framework/Web/UI/WebControls/TDropDownListColumn.php index ffbe8f70..941a9be1 100644 --- a/framework/Web/UI/WebControls/TDropDownListColumn.php +++ b/framework/Web/UI/WebControls/TDropDownListColumn.php @@ -1,321 +1,321 @@ -<?php
 -/**
 - * TDropDownListColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TDropDownListColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -Prado::using('System.Web.UI.WebControls.TDropDownList');
 -
 -/**
 - * TDropDownListColumn class
 - *
 - * TDropDownListColumn represents a column that is bound to a field in a data source.
 - * The cells in the column will be displayed using the data indexed by
 - * {@link setDataTextField DataTextField}. You can customize the display by
 - * setting {@link setDataTextFormatString DataTextFormatString}.
 - *
 - * If {@link setReadOnly ReadOnly} is false, TDropDownListColumn will display cells in edit mode
 - * with dropdown lists. Otherwise, a static text is displayed.
 - * The currently selected dropndown list item is specified by the data indexed with
 - * {@link setDataValueField DataValueField}.
 - *
 - * There are two approaches to specify the list items available for selection.
 - * The first approach uses template syntax as follows,
 - * <code>
 - *   <com:TDropDownListColumn ....>
 - *     <com:TListItem Value="1" Text="first item" />
 - *     <com:TListItem Value="2" Text="second item" />
 - *     <com:TListItem Value="3" Text="third item" />
 - *   </com:TDropDownListColumn>
 - * </code>
 - * The second approach specifies a data source to be bound to the dropdown lists
 - * by setting {@link setListDataSource ListDataSource}. Like generic list controls,
 - * you may also want to specify which data fields are used for item values and texts
 - * by setting {@link setListValueField ListValueField} and
 - * {@link setListTextField ListTextField}, respectively.
 - * Furthermore, the item texts may be formatted by using {@link setListTextFormatString ListTextFormatString}.
 - * Note, if you specify {@link setListDataSource ListDataSource}, do it before
 - * calling the datagrid's dataBind().
 - *
 - * The dropdown list control in the TDropDownListColumn can be accessed by one of
 - * the following two methods:
 - * <code>
 - * $datagridItem->DropDownListColumnID->DropDownList
 - * $datagridItem->DropDownListColumnID->Controls[0]
 - * </code>
 - * The second method is possible because the dropdown list control created within the
 - * datagrid cell is the first child.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TDropDownListColumn extends TDataGridColumn
 -{
 -	private $_stateLoaded=false;
 -	private $_dataBound=false;
 -	private $_listControl=null;
 -
 -	public function __construct()
 -	{
 -		$this->_listControl=new TDropDownList;
 -	}
 -
 -	/**
 -	 * Loads items from viewstate.
 -	 * This method overrides the parent implementation by loading list items
 -	 * @param mixed state values
 -	 */
 -	public function loadState($state)
 -	{
 -		parent::loadState($state);
 -		$this->_stateLoaded=true;
 -		if(!$this->_dataBound)
 -			$this->_listControl->getItems()->loadState($this->getViewState('Items',null));
 -	}
 -
 -	/**
 -	 * Saves items into viewstate.
 -	 * This method overrides the parent implementation by saving list items
 -	 */
 -	public function saveState()
 -	{
 -		$this->setViewState('Items',$this->_listControl->getItems()->saveState(),null);
 -		return parent::saveState();
 -	}
 -
 -	/**
 -	 * Adds object parsed from template to the control.
 -	 * This method adds only {@link TListItem} objects into the {@link getItems Items} collection.
 -	 * All other objects are ignored.
 -	 * @param mixed object parsed from template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		// Do not add items from template if items are loaded from viewstate
 -		if(!$this->_stateLoaded && ($object instanceof TListItem))
 -		{
 -			$object->setSelected(false);
 -			$index=$this->_listControl->getItems()->add($object);
 -		}
 -	}
 -
 -	/**
 -	 * @return string the field of the data source that provides the text content of the column.
 -	 */
 -	public function getDataTextField()
 -	{
 -		return $this->getViewState('DataTextField','');
 -	}
 -
 -	/**
 -	 * Sets the field of the data source that provides the text content of the column.
 -	 * If this is not set, the data specified via {@link getDataValueField DataValueField}
 -	 * will be displayed in the column.
 -	 * @param string the field of the data source that provides the text content of the column.
 -	 */
 -	public function setDataTextField($value)
 -	{
 -		$this->setViewState('DataTextField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the bound data will be displayed.
 -	 */
 -	public function getDataTextFormatString()
 -	{
 -		return $this->getViewState('DataTextFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the bound data will be displayed.
 -	 */
 -	public function setDataTextFormatString($value)
 -	{
 -		$this->setViewState('DataTextFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field of the data source that provides the key selecting an item in dropdown list.
 -	 */
 -	public function getDataValueField()
 -	{
 -		return $this->getViewState('DataValueField','');
 -	}
 -
 -	/**
 -	 * Sets the field of the data source that provides the key selecting an item in dropdown list.
 -	 * If this is not present, the data specified via {@link getDataTextField DataTextField} (without
 -	 * applying the formatting string) will be used for selection, instead.
 -	 * @param string the field of the data source that provides the key selecting an item in dropdown list.
 -	 */
 -	public function setDataValueField($value)
 -	{
 -		$this->setViewState('DataValueField',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether the items in the column can be edited. Defaults to false.
 -	 */
 -	public function getReadOnly()
 -	{
 -		return $this->getViewState('ReadOnly',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the items in the column can be edited
 -	 */
 -	public function setReadOnly($value)
 -	{
 -		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return Traversable data source to be bound to the dropdown list boxes.
 -	 */
 -	public function getListDataSource()
 -	{
 -		return $this->_listControl->getDataSource();
 -	}
 -
 -	/**
 -	 * @param Traversable|array|string data source to be bound to the dropdown list boxes.
 -	 */
 -	public function setListDataSource($value)
 -	{
 -		$this->_listControl->setDataSource($value);
 -	}
 -
 -	/**
 -	 * @return string the data field used to populate the values of the dropdown list items. Defaults to empty.
 -	 */
 -	public function getListValueField()
 -	{
 -		return $this->getViewState('ListValueField','');
 -	}
 -
 -	/**
 -	 * @param string the data field used to populate the values of the dropdown list items
 -	 */
 -	public function setListValueField($value)
 -	{
 -		$this->setViewState('ListValueField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the data field used to populate the texts of the dropdown list items. Defaults to empty.
 -	 */
 -	public function getListTextField()
 -	{
 -		return $this->getViewState('ListTextField','');
 -	}
 -
 -	/**
 -	 * @param string the data field used to populate the texts of the dropdown list items
 -	 */
 -	public function setListTextField($value)
 -	{
 -		$this->setViewState('ListTextField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the list item texts will be displayed.
 -	 */
 -	public function getListTextFormatString()
 -	{
 -		return $this->getViewState('ListTextFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the list item texts will be displayed.
 -	 */
 -	public function setListTextFormatString($value)
 -	{
 -		$this->setViewState('ListTextFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It creates a textbox for item in edit mode and the column is not read-only.
 -	 * Otherwise it displays a static text.
 -	 * The caption of the button and the static text are retrieved
 -	 * from the datasource.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if(!$this->_dataBound && $this->_listControl->getDataSource()!==null)
 -		{
 -			$this->_listControl->setDataTextField($this->getListTextField());
 -			$this->_listControl->setDataValueField($this->getListValueField());
 -			$this->_listControl->setDataTextFormatString($this->getListTextFormatString());
 -			$this->_listControl->dataBind();
 -			$this->_dataBound=true;
 -		}
 -		switch($itemType)
 -		{
 -			case TListItemType::EditItem:
 -				if(!$this->getReadOnly())
 -				{
 -					$listControl=clone $this->_listControl;
 -					$cell->getControls()->add($listControl);
 -					$cell->registerObject('DropDownList',$listControl);
 -					$control=$listControl;
 -				}
 -				else
 -					$control=$cell;
 -				$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -				break;
 -			case TListItemType::Item:
 -			case TListItemType::AlternatingItem:
 -			case TListItemType::SelectedItem:
 -				if($this->getDataTextField()!=='' || $this->getDataValueField()!=='')
 -					$cell->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -				break;
 -			default:
 -				parent::initializeCell($cell,$columnIndex,$itemType);
 -				break;
 -		}
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		$item=$sender->getNamingContainer();
 -		$data=$item->getData();
 -		if(($valueField=$this->getDataValueField())!=='')
 -			$value=$this->getDataFieldValue($data,$valueField);
 -		else
 -			$value='';
 -		if(($textField=$this->getDataTextField())!=='')
 -		{
 -			$text=$this->getDataFieldValue($data,$textField);
 -			if($valueField==='')
 -				$value=$text;
 -			$formatString=$this->getDataTextFormatString();
 -			$text=$this->formatDataValue($formatString,$text);
 -		}
 -		else
 -			$text=$value;
 -		if($sender instanceof TTableCell)
 -			$sender->setText($text);
 -		else if($sender instanceof TDropDownList)
 -			$sender->setSelectedValue($value);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); +Prado::using('System.Web.UI.WebControls.TDropDownList'); + +/** + * TDropDownListColumn class + * + * TDropDownListColumn represents a column that is bound to a field in a data source. + * The cells in the column will be displayed using the data indexed by + * {@link setDataTextField DataTextField}. You can customize the display by + * setting {@link setDataTextFormatString DataTextFormatString}. + * + * If {@link setReadOnly ReadOnly} is false, TDropDownListColumn will display cells in edit mode + * with dropdown lists. Otherwise, a static text is displayed. + * The currently selected dropndown list item is specified by the data indexed with + * {@link setDataValueField DataValueField}. + * + * There are two approaches to specify the list items available for selection. + * The first approach uses template syntax as follows, + * <code> + *   <com:TDropDownListColumn ....> + *     <com:TListItem Value="1" Text="first item" /> + *     <com:TListItem Value="2" Text="second item" /> + *     <com:TListItem Value="3" Text="third item" /> + *   </com:TDropDownListColumn> + * </code> + * The second approach specifies a data source to be bound to the dropdown lists + * by setting {@link setListDataSource ListDataSource}. Like generic list controls, + * you may also want to specify which data fields are used for item values and texts + * by setting {@link setListValueField ListValueField} and + * {@link setListTextField ListTextField}, respectively. + * Furthermore, the item texts may be formatted by using {@link setListTextFormatString ListTextFormatString}. + * Note, if you specify {@link setListDataSource ListDataSource}, do it before + * calling the datagrid's dataBind(). + * + * The dropdown list control in the TDropDownListColumn can be accessed by one of + * the following two methods: + * <code> + * $datagridItem->DropDownListColumnID->DropDownList + * $datagridItem->DropDownListColumnID->Controls[0] + * </code> + * The second method is possible because the dropdown list control created within the + * datagrid cell is the first child. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TDropDownListColumn extends TDataGridColumn +{ +	private $_stateLoaded=false; +	private $_dataBound=false; +	private $_listControl=null; + +	public function __construct() +	{ +		$this->_listControl=new TDropDownList; +	} + +	/** +	 * Loads items from viewstate. +	 * This method overrides the parent implementation by loading list items +	 * @param mixed state values +	 */ +	public function loadState($state) +	{ +		parent::loadState($state); +		$this->_stateLoaded=true; +		if(!$this->_dataBound) +			$this->_listControl->getItems()->loadState($this->getViewState('Items',null)); +	} + +	/** +	 * Saves items into viewstate. +	 * This method overrides the parent implementation by saving list items +	 */ +	public function saveState() +	{ +		$this->setViewState('Items',$this->_listControl->getItems()->saveState(),null); +		return parent::saveState(); +	} + +	/** +	 * Adds object parsed from template to the control. +	 * This method adds only {@link TListItem} objects into the {@link getItems Items} collection. +	 * All other objects are ignored. +	 * @param mixed object parsed from template +	 */ +	public function addParsedObject($object) +	{ +		// Do not add items from template if items are loaded from viewstate +		if(!$this->_stateLoaded && ($object instanceof TListItem)) +		{ +			$object->setSelected(false); +			$index=$this->_listControl->getItems()->add($object); +		} +	} + +	/** +	 * @return string the field of the data source that provides the text content of the column. +	 */ +	public function getDataTextField() +	{ +		return $this->getViewState('DataTextField',''); +	} + +	/** +	 * Sets the field of the data source that provides the text content of the column. +	 * If this is not set, the data specified via {@link getDataValueField DataValueField} +	 * will be displayed in the column. +	 * @param string the field of the data source that provides the text content of the column. +	 */ +	public function setDataTextField($value) +	{ +		$this->setViewState('DataTextField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the bound data will be displayed. +	 */ +	public function getDataTextFormatString() +	{ +		return $this->getViewState('DataTextFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the bound data will be displayed. +	 */ +	public function setDataTextFormatString($value) +	{ +		$this->setViewState('DataTextFormatString',$value,''); +	} + +	/** +	 * @return string the field of the data source that provides the key selecting an item in dropdown list. +	 */ +	public function getDataValueField() +	{ +		return $this->getViewState('DataValueField',''); +	} + +	/** +	 * Sets the field of the data source that provides the key selecting an item in dropdown list. +	 * If this is not present, the data specified via {@link getDataTextField DataTextField} (without +	 * applying the formatting string) will be used for selection, instead. +	 * @param string the field of the data source that provides the key selecting an item in dropdown list. +	 */ +	public function setDataValueField($value) +	{ +		$this->setViewState('DataValueField',$value,''); +	} + +	/** +	 * @return boolean whether the items in the column can be edited. Defaults to false. +	 */ +	public function getReadOnly() +	{ +		return $this->getViewState('ReadOnly',false); +	} + +	/** +	 * @param boolean whether the items in the column can be edited +	 */ +	public function setReadOnly($value) +	{ +		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return Traversable data source to be bound to the dropdown list boxes. +	 */ +	public function getListDataSource() +	{ +		return $this->_listControl->getDataSource(); +	} + +	/** +	 * @param Traversable|array|string data source to be bound to the dropdown list boxes. +	 */ +	public function setListDataSource($value) +	{ +		$this->_listControl->setDataSource($value); +	} + +	/** +	 * @return string the data field used to populate the values of the dropdown list items. Defaults to empty. +	 */ +	public function getListValueField() +	{ +		return $this->getViewState('ListValueField',''); +	} + +	/** +	 * @param string the data field used to populate the values of the dropdown list items +	 */ +	public function setListValueField($value) +	{ +		$this->setViewState('ListValueField',$value,''); +	} + +	/** +	 * @return string the data field used to populate the texts of the dropdown list items. Defaults to empty. +	 */ +	public function getListTextField() +	{ +		return $this->getViewState('ListTextField',''); +	} + +	/** +	 * @param string the data field used to populate the texts of the dropdown list items +	 */ +	public function setListTextField($value) +	{ +		$this->setViewState('ListTextField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the list item texts will be displayed. +	 */ +	public function getListTextFormatString() +	{ +		return $this->getViewState('ListTextFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the list item texts will be displayed. +	 */ +	public function setListTextFormatString($value) +	{ +		$this->setViewState('ListTextFormatString',$value,''); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It creates a textbox for item in edit mode and the column is not read-only. +	 * Otherwise it displays a static text. +	 * The caption of the button and the static text are retrieved +	 * from the datasource. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if(!$this->_dataBound && $this->_listControl->getDataSource()!==null) +		{ +			$this->_listControl->setDataTextField($this->getListTextField()); +			$this->_listControl->setDataValueField($this->getListValueField()); +			$this->_listControl->setDataTextFormatString($this->getListTextFormatString()); +			$this->_listControl->dataBind(); +			$this->_dataBound=true; +		} +		switch($itemType) +		{ +			case TListItemType::EditItem: +				if(!$this->getReadOnly()) +				{ +					$listControl=clone $this->_listControl; +					$cell->getControls()->add($listControl); +					$cell->registerObject('DropDownList',$listControl); +					$control=$listControl; +				} +				else +					$control=$cell; +				$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +				break; +			case TListItemType::Item: +			case TListItemType::AlternatingItem: +			case TListItemType::SelectedItem: +				if($this->getDataTextField()!=='' || $this->getDataValueField()!=='') +					$cell->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +				break; +			default: +				parent::initializeCell($cell,$columnIndex,$itemType); +				break; +		} +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		$item=$sender->getNamingContainer(); +		$data=$item->getData(); +		if(($valueField=$this->getDataValueField())!=='') +			$value=$this->getDataFieldValue($data,$valueField); +		else +			$value=''; +		if(($textField=$this->getDataTextField())!=='') +		{ +			$text=$this->getDataFieldValue($data,$textField); +			if($valueField==='') +				$value=$text; +			$formatString=$this->getDataTextFormatString(); +			$text=$this->formatDataValue($formatString,$text); +		} +		else +			$text=$value; +		if($sender instanceof TTableCell) +			$sender->setText($text); +		else if($sender instanceof TDropDownList) +			$sender->setSelectedValue($value); +	} +} + diff --git a/framework/Web/UI/WebControls/TEditCommandColumn.php b/framework/Web/UI/WebControls/TEditCommandColumn.php index 44004807..b10c6880 100644 --- a/framework/Web/UI/WebControls/TEditCommandColumn.php +++ b/framework/Web/UI/WebControls/TEditCommandColumn.php @@ -1,265 +1,265 @@ -<?php
 -/**
 - * TEditCommandColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TEditCommandColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -
 -/**
 - * TEditCommandColumn class
 - *
 - * TEditCommandColumn contains the Edit command buttons for editing data items in each row.
 - *
 - * TEditCommandColumn will create an edit button if a cell is not in edit mode.
 - * Otherwise an update button and a cancel button will be created within the cell.
 - * The button captions are specified using {@link setEditText EditText},
 - * {@link setUpdateText UpdateText}, and {@link setCancelText CancelText}.
 - *
 - * The buttons in the column can be set to display as hyperlinks, push or image buttons
 - * by setting the {@link setButtonType ButtonType} property.
 - *
 - * When an edit button is clicked, the datagrid will generate an
 - * {@link onEditCommand OnEditCommand} event. When an update/cancel button
 - * is clicked, the datagrid will generate an
 - * {@link onUpdateCommand OnUpdateCommand} or an {@link onCancelCommand OnCancelCommand}
 - * You can write these event handlers to change the state of specific datagrid item.
 - *
 - * The {@link setCausesValidation CausesValidation} and {@link setValidationGroup ValidationGroup}
 - * properties affect the corresponding properties of the edit and update buttons.
 - * The cancel button does not cause validation by default.
 - *
 - * The command buttons in the column can be accessed by one of the following methods:
 - * <code>
 - * $datagridItem->ButtonColumnID->EditButton (or UpdateButton, CancelButton)
 - * $datagridItem->ButtonColumnID->Controls[0]
 - * </code>
 - * The second method is possible because the button control created within the
 - * datagrid cell is the first child.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TEditCommandColumn extends TDataGridColumn
 -{
 -	/**
 -	 * @return TButtonColumnType the type of command button. Defaults to TButtonColumnType::LinkButton.
 -	 */
 -	public function getButtonType()
 -	{
 -		return $this->getViewState('ButtonType',TButtonColumnType::LinkButton);
 -	}
 -
 -	/**
 -	 * @param TButtonColumnType the type of command button.
 -	 */
 -	public function setButtonType($value)
 -	{
 -		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TButtonColumnType'),TButtonColumnType::LinkButton);
 -	}
 -
 -	/**
 -	 * @return string the caption of the edit button. Defaults to 'Edit'.
 -	 */
 -	public function getEditText()
 -	{
 -		return $this->getViewState('EditText','Edit');
 -	}
 -
 -	/**
 -	 * @param string the caption of the edit button
 -	 */
 -	public function setEditText($value)
 -	{
 -		$this->setViewState('EditText',$value,'Edit');
 -	}
 -
 -	/**
 -	 * @return string the URL of the image file for edit image buttons
 -	 */
 -	public function getEditImageUrl()
 -	{
 -		return $this->getViewState('EditImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL of the image file for edit image buttons
 -	 */
 -	public function setEditImageUrl($value)
 -	{
 -		$this->setViewState('EditImageUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the caption of the update button. Defaults to 'Update'.
 -	 */
 -	public function getUpdateText()
 -	{
 -		return $this->getViewState('UpdateText','Update');
 -	}
 -
 -	/**
 -	 * @param string the caption of the update button
 -	 */
 -	public function setUpdateText($value)
 -	{
 -		$this->setViewState('UpdateText',$value,'Update');
 -	}
 -
 -	/**
 -	 * @return string the URL of the image file for update image buttons
 -	 */
 -	public function getUpdateImageUrl()
 -	{
 -		return $this->getViewState('UpdateImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL of the image file for update image buttons
 -	 */
 -	public function setUpdateImageUrl($value)
 -	{
 -		$this->setViewState('UpdateImageUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the caption of the cancel button. Defaults to 'Cancel'.
 -	 */
 -	public function getCancelText()
 -	{
 -		return $this->getViewState('CancelText','Cancel');
 -	}
 -
 -	/**
 -	 * @param string the caption of the cancel button
 -	 */
 -	public function setCancelText($value)
 -	{
 -		$this->setViewState('CancelText',$value,'Cancel');
 -	}
 -
 -	/**
 -	 * @return string the URL of the image file for cancel image buttons
 -	 */
 -	public function getCancelImageUrl()
 -	{
 -		return $this->getViewState('CancelImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL of the image file for cancel image buttons
 -	 */
 -	public function setCancelImageUrl($value)
 -	{
 -		$this->setViewState('CancelImageUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by edit or update button will cause input validation, default is true
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by edit or update button will cause input validation
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the edit or update button causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the edit or update button causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It creates an update and a cancel button for cell in edit mode.
 -	 * Otherwise it creates an edit button.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem)
 -		{
 -			$button=$this->createButton('Edit',$this->getEditText(),false,'');
 -			$cell->getControls()->add($button);
 -			$cell->registerObject('EditButton',$button);
 -		}
 -		else if($itemType===TListItemType::EditItem)
 -		{
 -			$controls=$cell->getControls();
 -			$button=$this->createButton('Update',$this->getUpdateText(),$this->getCausesValidation(),$this->getValidationGroup());
 -			$controls->add($button);
 -			$cell->registerObject('UpdateButton',$button);
 -			$controls->add(' ');
 -			$button=$this->createButton('Cancel',$this->getCancelText(),false,'');
 -			$controls->add($button);
 -			$cell->registerObject('CancelButton',$button);
 -		}
 -		else
 -			parent::initializeCell($cell,$columnIndex,$itemType);
 -	}
 -
 -	/**
 -	 * Creates a button and initializes its properties.
 -	 * The button type is determined by {@link getButtonType ButtonType}.
 -	 * @param string command name associated with the button
 -	 * @param string button caption
 -	 * @param boolean whether the button should cause validation
 -	 * @param string the validation group that the button belongs to
 -	 * @return mixed the newly created button.
 -	 */
 -	protected function createButton($commandName,$text,$causesValidation,$validationGroup)
 -	{
 -		if($this->getButtonType()===TButtonColumnType::LinkButton)
 -			$button=Prado::createComponent('System.Web.UI.WebControls.TLinkButton');
 -		else if($this->getButtonType()===TButtonColumnType::PushButton)
 -			$button=Prado::createComponent('System.Web.UI.WebControls.TButton');
 -		else	// image buttons
 -		{
 -			$button=Prado::createComponent('System.Web.UI.WebControls.TImageButton');
 -			if(strcasecmp($commandName,'Update')===0)
 -				$url=$this->getUpdateImageUrl();
 -			else if(strcasecmp($commandName,'Cancel')===0)
 -				$url=$this->getCancelImageUrl();
 -			else
 -				$url=$this->getEditImageUrl();
 -			$button->setImageUrl($url);
 -		}
 -		$button->setText($text);
 -		$button->setCommandName($commandName);
 -		$button->setCausesValidation($causesValidation);
 -		$button->setValidationGroup($validationGroup);
 -		return $button;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); + +/** + * TEditCommandColumn class + * + * TEditCommandColumn contains the Edit command buttons for editing data items in each row. + * + * TEditCommandColumn will create an edit button if a cell is not in edit mode. + * Otherwise an update button and a cancel button will be created within the cell. + * The button captions are specified using {@link setEditText EditText}, + * {@link setUpdateText UpdateText}, and {@link setCancelText CancelText}. + * + * The buttons in the column can be set to display as hyperlinks, push or image buttons + * by setting the {@link setButtonType ButtonType} property. + * + * When an edit button is clicked, the datagrid will generate an + * {@link onEditCommand OnEditCommand} event. When an update/cancel button + * is clicked, the datagrid will generate an + * {@link onUpdateCommand OnUpdateCommand} or an {@link onCancelCommand OnCancelCommand} + * You can write these event handlers to change the state of specific datagrid item. + * + * The {@link setCausesValidation CausesValidation} and {@link setValidationGroup ValidationGroup} + * properties affect the corresponding properties of the edit and update buttons. + * The cancel button does not cause validation by default. + * + * The command buttons in the column can be accessed by one of the following methods: + * <code> + * $datagridItem->ButtonColumnID->EditButton (or UpdateButton, CancelButton) + * $datagridItem->ButtonColumnID->Controls[0] + * </code> + * The second method is possible because the button control created within the + * datagrid cell is the first child. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TEditCommandColumn extends TDataGridColumn +{ +	/** +	 * @return TButtonColumnType the type of command button. Defaults to TButtonColumnType::LinkButton. +	 */ +	public function getButtonType() +	{ +		return $this->getViewState('ButtonType',TButtonColumnType::LinkButton); +	} + +	/** +	 * @param TButtonColumnType the type of command button. +	 */ +	public function setButtonType($value) +	{ +		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TButtonColumnType'),TButtonColumnType::LinkButton); +	} + +	/** +	 * @return string the caption of the edit button. Defaults to 'Edit'. +	 */ +	public function getEditText() +	{ +		return $this->getViewState('EditText','Edit'); +	} + +	/** +	 * @param string the caption of the edit button +	 */ +	public function setEditText($value) +	{ +		$this->setViewState('EditText',$value,'Edit'); +	} + +	/** +	 * @return string the URL of the image file for edit image buttons +	 */ +	public function getEditImageUrl() +	{ +		return $this->getViewState('EditImageUrl',''); +	} + +	/** +	 * @param string the URL of the image file for edit image buttons +	 */ +	public function setEditImageUrl($value) +	{ +		$this->setViewState('EditImageUrl',$value,''); +	} + +	/** +	 * @return string the caption of the update button. Defaults to 'Update'. +	 */ +	public function getUpdateText() +	{ +		return $this->getViewState('UpdateText','Update'); +	} + +	/** +	 * @param string the caption of the update button +	 */ +	public function setUpdateText($value) +	{ +		$this->setViewState('UpdateText',$value,'Update'); +	} + +	/** +	 * @return string the URL of the image file for update image buttons +	 */ +	public function getUpdateImageUrl() +	{ +		return $this->getViewState('UpdateImageUrl',''); +	} + +	/** +	 * @param string the URL of the image file for update image buttons +	 */ +	public function setUpdateImageUrl($value) +	{ +		$this->setViewState('UpdateImageUrl',$value,''); +	} + +	/** +	 * @return string the caption of the cancel button. Defaults to 'Cancel'. +	 */ +	public function getCancelText() +	{ +		return $this->getViewState('CancelText','Cancel'); +	} + +	/** +	 * @param string the caption of the cancel button +	 */ +	public function setCancelText($value) +	{ +		$this->setViewState('CancelText',$value,'Cancel'); +	} + +	/** +	 * @return string the URL of the image file for cancel image buttons +	 */ +	public function getCancelImageUrl() +	{ +		return $this->getViewState('CancelImageUrl',''); +	} + +	/** +	 * @param string the URL of the image file for cancel image buttons +	 */ +	public function setCancelImageUrl($value) +	{ +		$this->setViewState('CancelImageUrl',$value,''); +	} + +	/** +	 * @return boolean whether postback event trigger by edit or update button will cause input validation, default is true +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by edit or update button will cause input validation +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the group of validators which the edit or update button causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the edit or update button causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It creates an update and a cancel button for cell in edit mode. +	 * Otherwise it creates an edit button. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem) +		{ +			$button=$this->createButton('Edit',$this->getEditText(),false,''); +			$cell->getControls()->add($button); +			$cell->registerObject('EditButton',$button); +		} +		else if($itemType===TListItemType::EditItem) +		{ +			$controls=$cell->getControls(); +			$button=$this->createButton('Update',$this->getUpdateText(),$this->getCausesValidation(),$this->getValidationGroup()); +			$controls->add($button); +			$cell->registerObject('UpdateButton',$button); +			$controls->add(' '); +			$button=$this->createButton('Cancel',$this->getCancelText(),false,''); +			$controls->add($button); +			$cell->registerObject('CancelButton',$button); +		} +		else +			parent::initializeCell($cell,$columnIndex,$itemType); +	} + +	/** +	 * Creates a button and initializes its properties. +	 * The button type is determined by {@link getButtonType ButtonType}. +	 * @param string command name associated with the button +	 * @param string button caption +	 * @param boolean whether the button should cause validation +	 * @param string the validation group that the button belongs to +	 * @return mixed the newly created button. +	 */ +	protected function createButton($commandName,$text,$causesValidation,$validationGroup) +	{ +		if($this->getButtonType()===TButtonColumnType::LinkButton) +			$button=Prado::createComponent('System.Web.UI.WebControls.TLinkButton'); +		else if($this->getButtonType()===TButtonColumnType::PushButton) +			$button=Prado::createComponent('System.Web.UI.WebControls.TButton'); +		else	// image buttons +		{ +			$button=Prado::createComponent('System.Web.UI.WebControls.TImageButton'); +			if(strcasecmp($commandName,'Update')===0) +				$url=$this->getUpdateImageUrl(); +			else if(strcasecmp($commandName,'Cancel')===0) +				$url=$this->getCancelImageUrl(); +			else +				$url=$this->getEditImageUrl(); +			$button->setImageUrl($url); +		} +		$button->setText($text); +		$button->setCommandName($commandName); +		$button->setCausesValidation($causesValidation); +		$button->setValidationGroup($validationGroup); +		return $button; +	} +} + diff --git a/framework/Web/UI/WebControls/TEmailAddressValidator.php b/framework/Web/UI/WebControls/TEmailAddressValidator.php index a198ffc4..b0b51208 100644 --- a/framework/Web/UI/WebControls/TEmailAddressValidator.php +++ b/framework/Web/UI/WebControls/TEmailAddressValidator.php @@ -1,97 +1,97 @@ -<?php
 -/**
 - * TEmailAddressValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TEmailAddressValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TRegularExpressionValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TRegularExpressionValidator');
 -
 -/**
 - * TEmailAddressValidator class
 - *
 - * TEmailAddressValidator validates whether the value of an associated
 - * input component is a valid email address. If {@link getCheckMXRecord CheckMXRecord}
 - * is true, it will check MX record for the email adress, provided
 - * checkdnsrr() is available in the installed PHP.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TEmailAddressValidator extends TRegularExpressionValidator
 -{
 -	/**
 -	 * Regular expression used to validate the email address
 -	 */
 -	const EMAIL_REGEXP="\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TEmailAddressValidator';
 -	}
 -
 -	/**
 -	 * @return string the regular expression that determines the pattern used to validate a field.
 -	 */
 -	public function getRegularExpression()
 -	{
 -		$regex=parent::getRegularExpression();
 -		return $regex===''?self::EMAIL_REGEXP:$regex;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	public function evaluateIsValid()
 -	{
 -		$valid=parent::evaluateIsValid();
 -		if($valid && $this->getCheckMXRecord() && function_exists('checkdnsrr'))
 -		{
 -			if(($value=$this->getValidationValue($this->getValidationTarget()))!=='')
 -			{
 -				if(($pos=strpos($value,'@'))!==false)
 -				{
 -					$domain=substr($value,$pos+1);
 -					return $domain===''?false:checkdnsrr($domain,'MX');
 -				}
 -				else
 -					return false;
 -			}
 -		}
 -		return $valid;
 -	}
 -
 -	/**
 -	 * @return boolean whether to check MX record for the email address being validated. Defaults to true.
 -	 */
 -	public function getCheckMXRecord()
 -	{
 -		return $this->getViewState('CheckMXRecord',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to check MX record for the email address being validated.
 -	 * Note, if {@link checkdnsrr} is not available, this check will not be performed.
 -	 */
 -	public function setCheckMXRecord($value)
 -	{
 -		$this->setViewState('CheckMXRecord',TPropertyValue::ensureBoolean($value),true);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TRegularExpressionValidator class + */ +Prado::using('System.Web.UI.WebControls.TRegularExpressionValidator'); + +/** + * TEmailAddressValidator class + * + * TEmailAddressValidator validates whether the value of an associated + * input component is a valid email address. If {@link getCheckMXRecord CheckMXRecord} + * is true, it will check MX record for the email adress, provided + * checkdnsrr() is available in the installed PHP. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TEmailAddressValidator extends TRegularExpressionValidator +{ +	/** +	 * Regular expression used to validate the email address +	 */ +	const EMAIL_REGEXP="\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"; + +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TEmailAddressValidator'; +	} + +	/** +	 * @return string the regular expression that determines the pattern used to validate a field. +	 */ +	public function getRegularExpression() +	{ +		$regex=parent::getRegularExpression(); +		return $regex===''?self::EMAIL_REGEXP:$regex; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	public function evaluateIsValid() +	{ +		$valid=parent::evaluateIsValid(); +		if($valid && $this->getCheckMXRecord() && function_exists('checkdnsrr')) +		{ +			if(($value=$this->getValidationValue($this->getValidationTarget()))!=='') +			{ +				if(($pos=strpos($value,'@'))!==false) +				{ +					$domain=substr($value,$pos+1); +					return $domain===''?false:checkdnsrr($domain,'MX'); +				} +				else +					return false; +			} +		} +		return $valid; +	} + +	/** +	 * @return boolean whether to check MX record for the email address being validated. Defaults to true. +	 */ +	public function getCheckMXRecord() +	{ +		return $this->getViewState('CheckMXRecord',true); +	} + +	/** +	 * @param boolean whether to check MX record for the email address being validated. +	 * Note, if {@link checkdnsrr} is not available, this check will not be performed. +	 */ +	public function setCheckMXRecord($value) +	{ +		$this->setViewState('CheckMXRecord',TPropertyValue::ensureBoolean($value),true); +	} +} + diff --git a/framework/Web/UI/WebControls/TExpression.php b/framework/Web/UI/WebControls/TExpression.php index 9b8eb7e7..cf38df70 100644 --- a/framework/Web/UI/WebControls/TExpression.php +++ b/framework/Web/UI/WebControls/TExpression.php @@ -1,62 +1,62 @@ -<?php
 -/**
 - * TExpression class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TExpression class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TExpression class
 - *
 - * TExpression evaluates a PHP expression and renders the result.
 - * The expression is evaluated during the rendering stage. The expression being
 - * evaluated can be set via the property {@link setExpression Expression}.
 - * The context of the expression evaluated is the TExpression object itself.
 - *
 - * Note, since TExpression allows evaluation of arbitrary PHP expression,
 - * make sure {@link setExpression Expression} does not come directly from user input.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TExpression extends TControl
 -{
 -	/**
 -	 * @var string PHP expression to be evaluated
 -	 */
 -	private $_e='';
 -
 -	/**
 -	 * @return string the expression to be evaluated
 -	 */
 -	public function getExpression()
 -	{
 -		return $this->_e;
 -	}
 -
 -	/**
 -	 * @param string the expression to be evaluated
 -	 */
 -	public function setExpression($value)
 -	{
 -		$this->_e=$value;
 -	}
 -
 -	/**
 -	 * Renders the evaluation result of the expression.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->_e!=='')
 -			$writer->write($this->evaluateExpression($this->_e));
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TExpression class + * + * TExpression evaluates a PHP expression and renders the result. + * The expression is evaluated during the rendering stage. The expression being + * evaluated can be set via the property {@link setExpression Expression}. + * The context of the expression evaluated is the TExpression object itself. + * + * Note, since TExpression allows evaluation of arbitrary PHP expression, + * make sure {@link setExpression Expression} does not come directly from user input. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TExpression extends TControl +{ +	/** +	 * @var string PHP expression to be evaluated +	 */ +	private $_e=''; + +	/** +	 * @return string the expression to be evaluated +	 */ +	public function getExpression() +	{ +		return $this->_e; +	} + +	/** +	 * @param string the expression to be evaluated +	 */ +	public function setExpression($value) +	{ +		$this->_e=$value; +	} + +	/** +	 * Renders the evaluation result of the expression. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function render($writer) +	{ +		if($this->_e!=='') +			$writer->write($this->evaluateExpression($this->_e)); +	} +} + diff --git a/framework/Web/UI/WebControls/TFileUpload.php b/framework/Web/UI/WebControls/TFileUpload.php index 0f7d226d..051e3e0b 100644 --- a/framework/Web/UI/WebControls/TFileUpload.php +++ b/framework/Web/UI/WebControls/TFileUpload.php @@ -1,281 +1,281 @@ -<?php
 -/**
 - * TFileUpload class file
 - *
 - * @author Marcus Nyeholt <tanus@users.sourceforge.net>, Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TFileUpload class
 - *
 - * TFileUpload displays a file upload field on a page. Upon postback,
 - * the text entered into the field will be treated as the name of the file
 - * that will be uploaded to the server. The property {@link getHasFile HasFile}
 - * indicates whether the file upload is successful. If successful, the file
 - * may be obtained by calling {@link saveAs} to save it at a specified place.
 - * You can use {@link getFileName FileName}, {@link getFileType FileType},
 - * {@link getFileSize FileSize} to get the original client-side file name,
 - * the file mime type, and the file size information. If the upload is not
 - * successful, {@link getErrorCode ErrorCode} contains the error code
 - * describing the cause of failure.
 - *
 - * TFileUpload raises {@link onFileUpload OnFileUpload} event if a file is uploaded
 - * (whether it succeeds or not).
 - *
 - * @author Marcus Nyeholt <tanus@users.sourceforge.net>, Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TFileUpload extends TWebControl implements IPostBackDataHandler, IValidatable
 -{
 -	/**
 -	 * Maximum file size (in bytes) allowed to be uploaded, defaults to 1MB.
 -	 */
 -	const MAX_FILE_SIZE=1048576;
 -	/**
 -	 * @var integer the size of the uploaded file (in bytes)
 -	 */
 -	private $_fileSize=0;
 -	/**
 -	 * @var string The original name of the file on the client machine
 -	 */
 -	private $_fileName='';
 -	/**
 -	 * @var string the name of the temporary file storing the uploaded file
 -	 */
 -	private $_localName='';
 -	/**
 -	 * @var string the uploaded file mime type
 -	 */
 -	private $_fileType='';
 -	/**
 -	 * @var integer error code of the current file upload
 -	 */
 -	protected $_errorCode=UPLOAD_ERR_NO_FILE;
 -	private $_dataChanged=false;
 -	private $_isValid=true;
 -
 -	/**
 -	 * @return string tag name of the file upload control
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'input';
 -	}
 -
 -	/**
 -	 * Sets name attribute to the unique ID of the control.
 -	 * This method overrides the parent implementation with additional file update control specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$this->getPage()->ensureRenderInForm($this);
 -		parent::addAttributesToRender($writer);
 -		$writer->addAttribute('type','file');
 -		$writer->addAttribute('name',$this->getUniqueID());
 -		$isEnabled=$this->getEnabled(true);
 -		if(!$isEnabled && $this->getEnabled())  // in this case parent will not render 'disabled'
 -			$writer->addAttribute('disabled','disabled');
 -	}
 -
 -	/**
 -	 * Sets Enctype of the form on the page.
 -	 * This method overrides the parent implementation and is invoked before render.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		if(($form=$this->getPage()->getForm())!==null)
 -			$form->setEnctype('multipart/form-data');
 -		$this->getPage()->getClientScript()->registerHiddenField('MAX_FILE_SIZE',$this->getMaxFileSize());
 -		if($this->getEnabled(true))
 -			$this->getPage()->registerRequiresPostData($this);
 -	}
 -
 -	/**
 -	 * @return integer the maximum file size, defaults to 1MB (1048576 bytes).
 -	 * @see setMaxFileSize
 -	 */
 -	public function getMaxFileSize()
 -	{
 -		return $this->getViewState('MaxFileSize',self::MAX_FILE_SIZE);
 -	}
 -
 -	/**
 -	 * Sets the maximum size that a file can be uploaded.
 -	 * Note, this is an advisory value to the browser. Sets this property with
 -	 * a reasonably large size to save users the trouble of waiting
 -	 * for a big file being transferred only to find that it was too big
 -	 * and the transfer failed.
 -	 * @param int the maximum upload size allowed for a file.
 -	 */
 -	public function setMaxFileSize($size)
 -	{
 -		$this->setViewState('MaxFileSize',TPropertyValue::ensureInteger($size),self::MAX_FILE_SIZE);
 -	}
 -
 -	/**
 -	 * @return string the original full path name of the file on the client machine
 -	 */
 -	public function getFileName()
 -	{
 -		return $this->_fileName;
 -	}
 -
 -	/**
 -	 * @return integer the actual size of the uploaded file in bytes
 -	 */
 -	public function getFileSize()
 -	{
 -		return $this->_fileSize;
 -	}
 -
 -	/**
 -	 * @return string the MIME-type of the uploaded file (such as "image/gif").
 -	 * This mime type is not checked on the server side and do not take its value for granted.
 -	 */
 -	public function getFileType()
 -	{
 -		return $this->_fileType;
 -	}
 -
 -	/**
 -	 * @return string the local name of the file (where it is after being uploaded).
 -	 * Note, PHP will delete this file automatically after finishing this round of request.
 -	 */
 -	public function getLocalName()
 -	{
 -		return $this->_localName;
 -	}
 -
 -	/**
 -	 * Returns an error code describing the status of this file uploading.
 -	 * @return integer the error code
 -	 * @see http://www.php.net/manual/en/features.file-upload.errors.php
 -	 */
 -	public function getErrorCode()
 -	{
 -		return $this->_errorCode;
 -	}
 -
 -	/**
 -	 * @return boolean whether the file is uploaded successfully
 -	 */
 -	public function getHasFile()
 -	{
 -		return $this->_errorCode===UPLOAD_ERR_OK;
 -	}
 -
 -	/**
 -	 * Saves the uploaded file.
 -	 * @param string the file name used to save the uploaded file
 -	 * @param boolean whether to delete the temporary file after saving.
 -	 * If true, you will not be able to save the uploaded file again.
 -	 * @return boolean true if the file saving is successful
 -	 */
 -	public function saveAs($fileName,$deleteTempFile=true)
 -	{
 -		if($this->_errorCode===UPLOAD_ERR_OK)
 -		{
 -			if($deleteTempFile)
 -				return move_uploaded_file($this->_localName,$fileName);
 -			else if(is_uploaded_file($this->_localName))
 -				return file_put_contents($fileName,file_get_contents($this->_localName))!==false;
 -			else
 -				return false;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the control has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		if(isset($_FILES[$key]))
 -		{
 -			$this->_fileName=$_FILES[$key]['name'];
 -			$this->_fileSize=$_FILES[$key]['size'];
 -			$this->_fileType=$_FILES[$key]['type'];
 -			$this->_errorCode=$_FILES[$key]['error'];
 -			$this->_localName=$_FILES[$key]['tmp_name'];
 -			return $this->_dataChanged=true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method calls {@link onFileUpload} method.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		$this->onFileUpload(null);
 -	}
 -
 -	/**
 -	 * This method is invoked when a file is uploaded during a postback.
 -	 * The method raises <b>OnFileUpload</b> event to fire up the event handler.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event delegates can be invoked.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onFileUpload($param)
 -	{
 -		$this->raiseEvent('OnFileUpload',$this,$param);
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Returns the original file name as the property value to be validated.
 -	 * This method is required by IValidatable property.
 -	 * @return mixed the property value to be validated
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getFileName();
 -	}
 -
 -	/**
 -	 * Returns true if this control validated successfully. 
 -	 * Defaults to true.
 -	 * @return bool wether this control validated successfully.
 -	 */
 -	public function getIsValid()
 -	{
 -	    return $this->_isValid;
 -	}
 -	/**
 -	 * @param bool wether this control is valid.
 -	 */
 -	public function setIsValid($value)
 -	{
 -	    $this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -}
 -
 +<?php +/** + * TFileUpload class file + * + * @author Marcus Nyeholt <tanus@users.sourceforge.net>, Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TFileUpload class + * + * TFileUpload displays a file upload field on a page. Upon postback, + * the text entered into the field will be treated as the name of the file + * that will be uploaded to the server. The property {@link getHasFile HasFile} + * indicates whether the file upload is successful. If successful, the file + * may be obtained by calling {@link saveAs} to save it at a specified place. + * You can use {@link getFileName FileName}, {@link getFileType FileType}, + * {@link getFileSize FileSize} to get the original client-side file name, + * the file mime type, and the file size information. If the upload is not + * successful, {@link getErrorCode ErrorCode} contains the error code + * describing the cause of failure. + * + * TFileUpload raises {@link onFileUpload OnFileUpload} event if a file is uploaded + * (whether it succeeds or not). + * + * @author Marcus Nyeholt <tanus@users.sourceforge.net>, Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TFileUpload extends TWebControl implements IPostBackDataHandler, IValidatable +{ +	/** +	 * Maximum file size (in bytes) allowed to be uploaded, defaults to 1MB. +	 */ +	const MAX_FILE_SIZE=1048576; +	/** +	 * @var integer the size of the uploaded file (in bytes) +	 */ +	private $_fileSize=0; +	/** +	 * @var string The original name of the file on the client machine +	 */ +	private $_fileName=''; +	/** +	 * @var string the name of the temporary file storing the uploaded file +	 */ +	private $_localName=''; +	/** +	 * @var string the uploaded file mime type +	 */ +	private $_fileType=''; +	/** +	 * @var integer error code of the current file upload +	 */ +	protected $_errorCode=UPLOAD_ERR_NO_FILE; +	private $_dataChanged=false; +	private $_isValid=true; + +	/** +	 * @return string tag name of the file upload control +	 */ +	protected function getTagName() +	{ +		return 'input'; +	} + +	/** +	 * Sets name attribute to the unique ID of the control. +	 * This method overrides the parent implementation with additional file update control specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$this->getPage()->ensureRenderInForm($this); +		parent::addAttributesToRender($writer); +		$writer->addAttribute('type','file'); +		$writer->addAttribute('name',$this->getUniqueID()); +		$isEnabled=$this->getEnabled(true); +		if(!$isEnabled && $this->getEnabled())  // in this case parent will not render 'disabled' +			$writer->addAttribute('disabled','disabled'); +	} + +	/** +	 * Sets Enctype of the form on the page. +	 * This method overrides the parent implementation and is invoked before render. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		if(($form=$this->getPage()->getForm())!==null) +			$form->setEnctype('multipart/form-data'); +		$this->getPage()->getClientScript()->registerHiddenField('MAX_FILE_SIZE',$this->getMaxFileSize()); +		if($this->getEnabled(true)) +			$this->getPage()->registerRequiresPostData($this); +	} + +	/** +	 * @return integer the maximum file size, defaults to 1MB (1048576 bytes). +	 * @see setMaxFileSize +	 */ +	public function getMaxFileSize() +	{ +		return $this->getViewState('MaxFileSize',self::MAX_FILE_SIZE); +	} + +	/** +	 * Sets the maximum size that a file can be uploaded. +	 * Note, this is an advisory value to the browser. Sets this property with +	 * a reasonably large size to save users the trouble of waiting +	 * for a big file being transferred only to find that it was too big +	 * and the transfer failed. +	 * @param int the maximum upload size allowed for a file. +	 */ +	public function setMaxFileSize($size) +	{ +		$this->setViewState('MaxFileSize',TPropertyValue::ensureInteger($size),self::MAX_FILE_SIZE); +	} + +	/** +	 * @return string the original full path name of the file on the client machine +	 */ +	public function getFileName() +	{ +		return $this->_fileName; +	} + +	/** +	 * @return integer the actual size of the uploaded file in bytes +	 */ +	public function getFileSize() +	{ +		return $this->_fileSize; +	} + +	/** +	 * @return string the MIME-type of the uploaded file (such as "image/gif"). +	 * This mime type is not checked on the server side and do not take its value for granted. +	 */ +	public function getFileType() +	{ +		return $this->_fileType; +	} + +	/** +	 * @return string the local name of the file (where it is after being uploaded). +	 * Note, PHP will delete this file automatically after finishing this round of request. +	 */ +	public function getLocalName() +	{ +		return $this->_localName; +	} + +	/** +	 * Returns an error code describing the status of this file uploading. +	 * @return integer the error code +	 * @see http://www.php.net/manual/en/features.file-upload.errors.php +	 */ +	public function getErrorCode() +	{ +		return $this->_errorCode; +	} + +	/** +	 * @return boolean whether the file is uploaded successfully +	 */ +	public function getHasFile() +	{ +		return $this->_errorCode===UPLOAD_ERR_OK; +	} + +	/** +	 * Saves the uploaded file. +	 * @param string the file name used to save the uploaded file +	 * @param boolean whether to delete the temporary file after saving. +	 * If true, you will not be able to save the uploaded file again. +	 * @return boolean true if the file saving is successful +	 */ +	public function saveAs($fileName,$deleteTempFile=true) +	{ +		if($this->_errorCode===UPLOAD_ERR_OK) +		{ +			if($deleteTempFile) +				return move_uploaded_file($this->_localName,$fileName); +			else if(is_uploaded_file($this->_localName)) +				return file_put_contents($fileName,file_get_contents($this->_localName))!==false; +			else +				return false; +		} +		else +			return false; +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the control has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		if(isset($_FILES[$key])) +		{ +			$this->_fileName=$_FILES[$key]['name']; +			$this->_fileSize=$_FILES[$key]['size']; +			$this->_fileType=$_FILES[$key]['type']; +			$this->_errorCode=$_FILES[$key]['error']; +			$this->_localName=$_FILES[$key]['tmp_name']; +			return $this->_dataChanged=true; +		} +		else +			return false; +	} + +	/** +	 * Raises postdata changed event. +	 * This method calls {@link onFileUpload} method. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		$this->onFileUpload(null); +	} + +	/** +	 * This method is invoked when a file is uploaded during a postback. +	 * The method raises <b>OnFileUpload</b> event to fire up the event handler. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event delegates can be invoked. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onFileUpload($param) +	{ +		$this->raiseEvent('OnFileUpload',$this,$param); +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Returns the original file name as the property value to be validated. +	 * This method is required by IValidatable property. +	 * @return mixed the property value to be validated +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getFileName(); +	} + +	/** +	 * Returns true if this control validated successfully.  +	 * Defaults to true. +	 * @return bool wether this control validated successfully. +	 */ +	public function getIsValid() +	{ +	    return $this->_isValid; +	} +	/** +	 * @param bool wether this control is valid. +	 */ +	public function setIsValid($value) +	{ +	    $this->_isValid=TPropertyValue::ensureBoolean($value); +	} + +} + diff --git a/framework/Web/UI/WebControls/TFlushOutput.php b/framework/Web/UI/WebControls/TFlushOutput.php index cc55646d..0ea9b389 100644 --- a/framework/Web/UI/WebControls/TFlushOutput.php +++ b/framework/Web/UI/WebControls/TFlushOutput.php @@ -1,86 +1,86 @@ -<?php
 -/**
 - * TFlushOutput class file
 - *
 - * @author Berczi Gabor <gabor.berczi@devworx.hu>
 - * @link http://www.pradosoft.com/
 - * @license http://www.pradosoft.com/license/
 - * @version $Id: TFlushOutput.php $
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TFlushOutput class.
 - *
 - * TFlushOutput enables forced flushing of the current output buffer
 - * at (a) certain point(s) in the page, after rendering of all previous
 - * controls has been completed.
 - *
 - * To use TFlushOutput, simply place it in a template where you want
 - * the have the output buffered between the start of the page or the
 - * last TFlushOutput to be sent to the client immediately
 - * <code>
 - * <com:TFlushOutput />
 - * </code>
 - *
 - * You can specify whether you want to keep buffering of the output 
 - * (if it was enabled) till the next occourence of a <com: TFlushOutput />
 - * or the end of the page rendering, or stop buffering, by using the 
 - * {@link setContinueBuffering ContinueBuffering}.
 - *
 - * @author Berczi Gabor <gabor.berczi@devworx.hu>
 - * @version $Id: TFlushOutput.php  $
 - * @package System.Web.UI.WebControls
 - * @since 3.1
 - */
 -class TFlushOutput extends TControl 
 -{
 -	/**
 -	 * @var boolean whether to continue buffering of output
 -	 */
 -	private $_continueBuffering=true;
 -
 -
 -	/**
 -	 * Constructor.
 -	 */
 -	public function __construct()
 -	{
 -		parent::__construct();
 -		$this->EnableViewState = false;
 -	}
 -
 -	/**
 -	 * @return Tells whether buffering of output can continue after this point
 -	 */
 -	public function getContinueBuffering()
 -	{
 -		return $this->_continueBuffering;
 -	}
 -
 -	/**
 -	 * @param boolean sets whether buffering of output can continue after this point
 -	 */
 -	public function setContinueBuffering($value)
 -	{
 -		$this->_continueBuffering = TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * Flushes the output of all completely rendered controls to the client.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -//$writer->write('<!-- flush -->');
 -		// ajax responses can't be parsed by the client side before loaded and returned completely, 
 -		// so don't bother with flushing output somewhere mid-page if refreshing in a callback
 -		if (!$this->Page->IsCallback)
 -		{
 -			$this->Page->flushWriter();
 -//			$this->Application->flushOutput($this->ContinueBuffering);
 -		}
 -	}
 -}
 -
 +<?php +/** + * TFlushOutput class file + * + * @author Berczi Gabor <gabor.berczi@devworx.hu> + * @link http://www.pradosoft.com/ + * @license http://www.pradosoft.com/license/ + * @version $Id: TFlushOutput.php $ + * @package System.Web.UI.WebControls + */ + +/** + * TFlushOutput class. + * + * TFlushOutput enables forced flushing of the current output buffer + * at (a) certain point(s) in the page, after rendering of all previous + * controls has been completed. + * + * To use TFlushOutput, simply place it in a template where you want + * the have the output buffered between the start of the page or the + * last TFlushOutput to be sent to the client immediately + * <code> + * <com:TFlushOutput /> + * </code> + * + * You can specify whether you want to keep buffering of the output  + * (if it was enabled) till the next occourence of a <com: TFlushOutput /> + * or the end of the page rendering, or stop buffering, by using the  + * {@link setContinueBuffering ContinueBuffering}. + * + * @author Berczi Gabor <gabor.berczi@devworx.hu> + * @version $Id: TFlushOutput.php  $ + * @package System.Web.UI.WebControls + * @since 3.1 + */ +class TFlushOutput extends TControl  +{ +	/** +	 * @var boolean whether to continue buffering of output +	 */ +	private $_continueBuffering=true; + + +	/** +	 * Constructor. +	 */ +	public function __construct() +	{ +		parent::__construct(); +		$this->EnableViewState = false; +	} + +	/** +	 * @return Tells whether buffering of output can continue after this point +	 */ +	public function getContinueBuffering() +	{ +		return $this->_continueBuffering; +	} + +	/** +	 * @param boolean sets whether buffering of output can continue after this point +	 */ +	public function setContinueBuffering($value) +	{ +		$this->_continueBuffering = TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * Flushes the output of all completely rendered controls to the client. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function render($writer) +	{ +//$writer->write('<!-- flush -->'); +		// ajax responses can't be parsed by the client side before loaded and returned completely,  +		// so don't bother with flushing output somewhere mid-page if refreshing in a callback +		if (!$this->Page->IsCallback) +		{ +			$this->Page->flushWriter(); +//			$this->Application->flushOutput($this->ContinueBuffering); +		} +	} +} +  ?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TFont.php b/framework/Web/UI/WebControls/TFont.php index 4da42508..771b6a4e 100644 --- a/framework/Web/UI/WebControls/TFont.php +++ b/framework/Web/UI/WebControls/TFont.php @@ -1,318 +1,318 @@ -<?php
 -/**
 - * TFont class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TFont class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TFont class
 - *
 - * TFont encapsulates the CSS style fields related with font settings.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TFont extends TComponent
 -{
 -	/**
 -	 * Bits indicating the font states.
 -	 */
 -	const IS_BOLD=0x01;
 -	const IS_ITALIC=0x02;
 -	const IS_OVERLINE=0x04;
 -	const IS_STRIKEOUT=0x08;
 -	const IS_UNDERLINE=0x10;
 -
 -	/**
 -	 * Bits indicating whether particular font states are changed.
 -	 */
 -	const IS_SET_BOLD=0x01000;
 -	const IS_SET_ITALIC=0x02000;
 -	const IS_SET_OVERLINE=0x04000;
 -	const IS_SET_STRIKEOUT=0x08000;
 -	const IS_SET_UNDERLINE=0x10000;
 -	const IS_SET_SIZE=0x20000;
 -	const IS_SET_NAME=0x40000;
 -
 -	/**
 -	 * @var integer bits representing various states
 -	 */
 -	private $_flags=0;
 -	/**
 -	 * @var string font name
 -	 */
 -	private $_name='';
 -	/**
 -	 * @var string font size
 -	 */
 -	private $_size='';
 -
 -	/**
 -	 * @return boolean whether the font is in bold face. Defaults to false.
 -	 */
 -	public function getBold()
 -	{
 -		return ($this->_flags & self::IS_BOLD)!==0;
 -	}
 -
 -	/**
 -	 * @param boolean whether the font is in bold face
 -	 */
 -	public function setBold($value)
 -	{
 -		$this->_flags |= self::IS_SET_BOLD;
 -		if(TPropertyValue::ensureBoolean($value))
 -			$this->_flags |= self::IS_BOLD;
 -		else
 -			$this->_flags &= ~self::IS_BOLD;
 -	}
 -
 -	/**
 -	 * @return boolean whether the font is in italic face. Defaults to false.
 -	 */
 -	public function getItalic()
 -	{
 -		return ($this->_flags & self::IS_ITALIC)!==0;
 -	}
 -
 -	/**
 -	 * @param boolean whether the font is italic
 -	 */
 -	public function setItalic($value)
 -	{
 -		$this->_flags |= self::IS_SET_ITALIC;
 -		if(TPropertyValue::ensureBoolean($value))
 -			$this->_flags |= self::IS_ITALIC;
 -		else
 -			$this->_flags &= ~self::IS_ITALIC;
 -	}
 -
 -	/**
 -	 * @return boolean whether the font is overlined. Defaults to false.
 -	 */
 -	public function getOverline()
 -	{
 -		return ($this->_flags & self::IS_OVERLINE)!==0;
 -	}
 -
 -	/**
 -	 * @param boolean whether the font is overlined
 -	 */
 -	public function setOverline($value)
 -	{
 -		$this->_flags |= self::IS_SET_OVERLINE;
 -		if(TPropertyValue::ensureBoolean($value))
 -			$this->_flags |= self::IS_OVERLINE;
 -		else
 -			$this->_flags &= ~self::IS_OVERLINE;
 -	}
 -
 -	/**
 -	 * @return string the font size
 -	 */
 -	public function getSize()
 -	{
 -		return $this->_size;
 -	}
 -
 -	/**
 -	 * @param string the font size
 -	 */
 -	public function setSize($value)
 -	{
 -		$this->_flags |= self::IS_SET_SIZE;
 -		$this->_size=$value;
 -	}
 -
 -	/**
 -	 * @return boolean whether the font is strikeout. Defaults to false.
 -	 */
 -	public function getStrikeout()
 -	{
 -		return ($this->_flags & self::IS_STRIKEOUT)!==0;
 -	}
 -
 -	/**
 -	 * @param boolean whether the font is strikeout
 -	 */
 -	public function setStrikeout($value)
 -	{
 -		$this->_flags |= self::IS_SET_STRIKEOUT;
 -		if(TPropertyValue::ensureBoolean($value))
 -			$this->_flags |= self::IS_STRIKEOUT;
 -		else
 -			$this->_flags &= ~self::IS_STRIKEOUT;
 -	}
 -
 -	/**
 -	 * @return boolean whether the font is underlined. Defaults to false.
 -	 */
 -	public function getUnderline()
 -	{
 -		return ($this->_flags & self::IS_UNDERLINE)!==0;
 -	}
 -
 -	/**
 -	 * @param boolean whether the font is underlined
 -	 */
 -	public function setUnderline($value)
 -	{
 -		$this->_flags |= self::IS_SET_UNDERLINE;
 -		if(TPropertyValue::ensureBoolean($value))
 -			$this->_flags |= self::IS_UNDERLINE;
 -		else
 -			$this->_flags &= ~self::IS_UNDERLINE;
 -	}
 -
 -	/**
 -	 * @return string the font name (family)
 -	 */
 -	public function getName()
 -	{
 -		return $this->_name;
 -	}
 -
 -	/**
 -	 * @param string the font name (family)
 -	 */
 -	public function setName($value)
 -	{
 -		$this->_flags |= self::IS_SET_NAME;
 -		$this->_name=$value;
 -	}
 -
 -	/**
 -	 * @return boolean whether the font is empty
 -	 */
 -	public function getIsEmpty()
 -	{
 -		return !$this->_flags;
 -	}
 -
 -	/**
 -	 * Clears up the font.
 -	 */
 -	public function reset()
 -	{
 -		$this->_flags=0;
 -		$this->_name='';
 -		$this->_size='';
 -	}
 -
 -	/**
 -	 * Merges the font with a new one.
 -	 * If a font field is not set in the font, it will be overwritten with
 -	 * the new one.
 -	 * @param TFont the new font
 -	 */
 -	public function mergeWith($font)
 -	{
 -		if($font===null || $font->_flags===0)
 -			return;
 -		if(!($this->_flags & self::IS_SET_BOLD) && ($font->_flags & self::IS_SET_BOLD))
 -			$this->setBold($font->getBold());
 -		if(!($this->_flags & self::IS_SET_ITALIC) && ($font->_flags & self::IS_SET_ITALIC))
 -			$this->setItalic($font->getItalic());
 -		if(!($this->_flags & self::IS_SET_OVERLINE) && ($font->_flags & self::IS_SET_OVERLINE))
 -			$this->setOverline($font->getOverline());
 -		if(!($this->_flags & self::IS_SET_STRIKEOUT) && ($font->_flags & self::IS_SET_STRIKEOUT))
 -			$this->setStrikeout($font->getStrikeout());
 -		if(!($this->_flags & self::IS_SET_UNDERLINE) && ($font->_flags & self::IS_SET_UNDERLINE))
 -			$this->setUnderline($font->getUnderline());
 -		if(!($this->_flags & self::IS_SET_SIZE) && ($font->_flags & self::IS_SET_SIZE))
 -			$this->setSize($font->getSize());
 -		if(!($this->_flags & self::IS_SET_NAME) && ($font->_flags & self::IS_SET_NAME))
 -			$this->setName($font->getName());
 -	}
 -
 -	/**
 -	 * Copies the fields in a new font to this font.
 -	 * If a font field is set in the new font, the corresponding field
 -	 * in this font will be overwritten.
 -	 * @param TFont the new font
 -	 */
 -	public function copyFrom($font)
 -	{
 -		if($font===null || $font->_flags===0)
 -			return;
 -		if($font->_flags & self::IS_SET_BOLD)
 -			$this->setBold($font->getBold());
 -		if($font->_flags & self::IS_SET_ITALIC)
 -			$this->setItalic($font->getItalic());
 -		if($font->_flags & self::IS_SET_OVERLINE)
 -			$this->setOverline($font->getOverline());
 -		if($font->_flags & self::IS_SET_STRIKEOUT)
 -			$this->setStrikeout($font->getStrikeout());
 -		if($font->_flags & self::IS_SET_UNDERLINE)
 -			$this->setUnderline($font->getUnderline());
 -		if($font->_flags & self::IS_SET_SIZE)
 -			$this->setSize($font->getSize());
 -		if($font->_flags & self::IS_SET_NAME)
 -			$this->setName($font->getName());
 -	}
 -
 -	/**
 -	 * @return string the font in a css style string representation.
 -	 */
 -	public function toString()
 -	{
 -		if($this->_flags===0)
 -			return '';
 -		$str='';
 -		if($this->_flags & self::IS_SET_BOLD)
 -			$str.='font-weight:'.(($this->_flags & self::IS_BOLD)?'bold;':'normal;');
 -		if($this->_flags & self::IS_SET_ITALIC)
 -			$str.='font-style:'.(($this->_flags & self::IS_ITALIC)?'italic;':'normal;');
 -		$textDec='';
 -		if($this->_flags & self::IS_UNDERLINE)
 -			$textDec.='underline';
 -		if($this->_flags & self::IS_OVERLINE)
 -			$textDec.=' overline';
 -		if($this->_flags & self::IS_STRIKEOUT)
 -			$textDec.=' line-through';
 -		$textDec=ltrim($textDec);
 -		if($textDec!=='')
 -			$str.='text-decoration:'.$textDec.';';
 -		if($this->_size!=='')
 -			$str.='font-size:'.$this->_size.';';
 -		if($this->_name!=='')
 -			$str.='font-family:'.$this->_name.';';
 -		return $str;
 -	}
 -
 -	/**
 -	 * Adds attributes related to CSS styles to renderer.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function addAttributesToRender($writer)
 -	{
 -		if($this->_flags===0)
 -			return;
 -		if($this->_flags & self::IS_SET_BOLD)
 -			$writer->addStyleAttribute('font-weight',(($this->_flags & self::IS_BOLD)?'bold':'normal'));
 -		if($this->_flags & self::IS_SET_ITALIC)
 -			$writer->addStyleAttribute('font-style',(($this->_flags & self::IS_ITALIC)?'italic':'normal'));
 -		$textDec='';
 -		if($this->_flags & self::IS_UNDERLINE)
 -			$textDec.='underline';
 -		if($this->_flags & self::IS_OVERLINE)
 -			$textDec.=' overline';
 -		if($this->_flags & self::IS_STRIKEOUT)
 -			$textDec.=' line-through';
 -		$textDec=ltrim($textDec);
 -		if($textDec!=='')
 -			$writer->addStyleAttribute('text-decoration',$textDec);
 -		if($this->_size!=='')
 -			$writer->addStyleAttribute('font-size',$this->_size);
 -		if($this->_name!=='')
 -			$writer->addStyleAttribute('font-family',$this->_name);
 -	}
 -}
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TFont class + * + * TFont encapsulates the CSS style fields related with font settings. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TFont extends TComponent +{ +	/** +	 * Bits indicating the font states. +	 */ +	const IS_BOLD=0x01; +	const IS_ITALIC=0x02; +	const IS_OVERLINE=0x04; +	const IS_STRIKEOUT=0x08; +	const IS_UNDERLINE=0x10; + +	/** +	 * Bits indicating whether particular font states are changed. +	 */ +	const IS_SET_BOLD=0x01000; +	const IS_SET_ITALIC=0x02000; +	const IS_SET_OVERLINE=0x04000; +	const IS_SET_STRIKEOUT=0x08000; +	const IS_SET_UNDERLINE=0x10000; +	const IS_SET_SIZE=0x20000; +	const IS_SET_NAME=0x40000; + +	/** +	 * @var integer bits representing various states +	 */ +	private $_flags=0; +	/** +	 * @var string font name +	 */ +	private $_name=''; +	/** +	 * @var string font size +	 */ +	private $_size=''; + +	/** +	 * @return boolean whether the font is in bold face. Defaults to false. +	 */ +	public function getBold() +	{ +		return ($this->_flags & self::IS_BOLD)!==0; +	} + +	/** +	 * @param boolean whether the font is in bold face +	 */ +	public function setBold($value) +	{ +		$this->_flags |= self::IS_SET_BOLD; +		if(TPropertyValue::ensureBoolean($value)) +			$this->_flags |= self::IS_BOLD; +		else +			$this->_flags &= ~self::IS_BOLD; +	} + +	/** +	 * @return boolean whether the font is in italic face. Defaults to false. +	 */ +	public function getItalic() +	{ +		return ($this->_flags & self::IS_ITALIC)!==0; +	} + +	/** +	 * @param boolean whether the font is italic +	 */ +	public function setItalic($value) +	{ +		$this->_flags |= self::IS_SET_ITALIC; +		if(TPropertyValue::ensureBoolean($value)) +			$this->_flags |= self::IS_ITALIC; +		else +			$this->_flags &= ~self::IS_ITALIC; +	} + +	/** +	 * @return boolean whether the font is overlined. Defaults to false. +	 */ +	public function getOverline() +	{ +		return ($this->_flags & self::IS_OVERLINE)!==0; +	} + +	/** +	 * @param boolean whether the font is overlined +	 */ +	public function setOverline($value) +	{ +		$this->_flags |= self::IS_SET_OVERLINE; +		if(TPropertyValue::ensureBoolean($value)) +			$this->_flags |= self::IS_OVERLINE; +		else +			$this->_flags &= ~self::IS_OVERLINE; +	} + +	/** +	 * @return string the font size +	 */ +	public function getSize() +	{ +		return $this->_size; +	} + +	/** +	 * @param string the font size +	 */ +	public function setSize($value) +	{ +		$this->_flags |= self::IS_SET_SIZE; +		$this->_size=$value; +	} + +	/** +	 * @return boolean whether the font is strikeout. Defaults to false. +	 */ +	public function getStrikeout() +	{ +		return ($this->_flags & self::IS_STRIKEOUT)!==0; +	} + +	/** +	 * @param boolean whether the font is strikeout +	 */ +	public function setStrikeout($value) +	{ +		$this->_flags |= self::IS_SET_STRIKEOUT; +		if(TPropertyValue::ensureBoolean($value)) +			$this->_flags |= self::IS_STRIKEOUT; +		else +			$this->_flags &= ~self::IS_STRIKEOUT; +	} + +	/** +	 * @return boolean whether the font is underlined. Defaults to false. +	 */ +	public function getUnderline() +	{ +		return ($this->_flags & self::IS_UNDERLINE)!==0; +	} + +	/** +	 * @param boolean whether the font is underlined +	 */ +	public function setUnderline($value) +	{ +		$this->_flags |= self::IS_SET_UNDERLINE; +		if(TPropertyValue::ensureBoolean($value)) +			$this->_flags |= self::IS_UNDERLINE; +		else +			$this->_flags &= ~self::IS_UNDERLINE; +	} + +	/** +	 * @return string the font name (family) +	 */ +	public function getName() +	{ +		return $this->_name; +	} + +	/** +	 * @param string the font name (family) +	 */ +	public function setName($value) +	{ +		$this->_flags |= self::IS_SET_NAME; +		$this->_name=$value; +	} + +	/** +	 * @return boolean whether the font is empty +	 */ +	public function getIsEmpty() +	{ +		return !$this->_flags; +	} + +	/** +	 * Clears up the font. +	 */ +	public function reset() +	{ +		$this->_flags=0; +		$this->_name=''; +		$this->_size=''; +	} + +	/** +	 * Merges the font with a new one. +	 * If a font field is not set in the font, it will be overwritten with +	 * the new one. +	 * @param TFont the new font +	 */ +	public function mergeWith($font) +	{ +		if($font===null || $font->_flags===0) +			return; +		if(!($this->_flags & self::IS_SET_BOLD) && ($font->_flags & self::IS_SET_BOLD)) +			$this->setBold($font->getBold()); +		if(!($this->_flags & self::IS_SET_ITALIC) && ($font->_flags & self::IS_SET_ITALIC)) +			$this->setItalic($font->getItalic()); +		if(!($this->_flags & self::IS_SET_OVERLINE) && ($font->_flags & self::IS_SET_OVERLINE)) +			$this->setOverline($font->getOverline()); +		if(!($this->_flags & self::IS_SET_STRIKEOUT) && ($font->_flags & self::IS_SET_STRIKEOUT)) +			$this->setStrikeout($font->getStrikeout()); +		if(!($this->_flags & self::IS_SET_UNDERLINE) && ($font->_flags & self::IS_SET_UNDERLINE)) +			$this->setUnderline($font->getUnderline()); +		if(!($this->_flags & self::IS_SET_SIZE) && ($font->_flags & self::IS_SET_SIZE)) +			$this->setSize($font->getSize()); +		if(!($this->_flags & self::IS_SET_NAME) && ($font->_flags & self::IS_SET_NAME)) +			$this->setName($font->getName()); +	} + +	/** +	 * Copies the fields in a new font to this font. +	 * If a font field is set in the new font, the corresponding field +	 * in this font will be overwritten. +	 * @param TFont the new font +	 */ +	public function copyFrom($font) +	{ +		if($font===null || $font->_flags===0) +			return; +		if($font->_flags & self::IS_SET_BOLD) +			$this->setBold($font->getBold()); +		if($font->_flags & self::IS_SET_ITALIC) +			$this->setItalic($font->getItalic()); +		if($font->_flags & self::IS_SET_OVERLINE) +			$this->setOverline($font->getOverline()); +		if($font->_flags & self::IS_SET_STRIKEOUT) +			$this->setStrikeout($font->getStrikeout()); +		if($font->_flags & self::IS_SET_UNDERLINE) +			$this->setUnderline($font->getUnderline()); +		if($font->_flags & self::IS_SET_SIZE) +			$this->setSize($font->getSize()); +		if($font->_flags & self::IS_SET_NAME) +			$this->setName($font->getName()); +	} + +	/** +	 * @return string the font in a css style string representation. +	 */ +	public function toString() +	{ +		if($this->_flags===0) +			return ''; +		$str=''; +		if($this->_flags & self::IS_SET_BOLD) +			$str.='font-weight:'.(($this->_flags & self::IS_BOLD)?'bold;':'normal;'); +		if($this->_flags & self::IS_SET_ITALIC) +			$str.='font-style:'.(($this->_flags & self::IS_ITALIC)?'italic;':'normal;'); +		$textDec=''; +		if($this->_flags & self::IS_UNDERLINE) +			$textDec.='underline'; +		if($this->_flags & self::IS_OVERLINE) +			$textDec.=' overline'; +		if($this->_flags & self::IS_STRIKEOUT) +			$textDec.=' line-through'; +		$textDec=ltrim($textDec); +		if($textDec!=='') +			$str.='text-decoration:'.$textDec.';'; +		if($this->_size!=='') +			$str.='font-size:'.$this->_size.';'; +		if($this->_name!=='') +			$str.='font-family:'.$this->_name.';'; +		return $str; +	} + +	/** +	 * Adds attributes related to CSS styles to renderer. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function addAttributesToRender($writer) +	{ +		if($this->_flags===0) +			return; +		if($this->_flags & self::IS_SET_BOLD) +			$writer->addStyleAttribute('font-weight',(($this->_flags & self::IS_BOLD)?'bold':'normal')); +		if($this->_flags & self::IS_SET_ITALIC) +			$writer->addStyleAttribute('font-style',(($this->_flags & self::IS_ITALIC)?'italic':'normal')); +		$textDec=''; +		if($this->_flags & self::IS_UNDERLINE) +			$textDec.='underline'; +		if($this->_flags & self::IS_OVERLINE) +			$textDec.=' overline'; +		if($this->_flags & self::IS_STRIKEOUT) +			$textDec.=' line-through'; +		$textDec=ltrim($textDec); +		if($textDec!=='') +			$writer->addStyleAttribute('text-decoration',$textDec); +		if($this->_size!=='') +			$writer->addStyleAttribute('font-size',$this->_size); +		if($this->_name!=='') +			$writer->addStyleAttribute('font-family',$this->_name); +	} +} diff --git a/framework/Web/UI/WebControls/THead.php b/framework/Web/UI/WebControls/THead.php index c0042c22..7966f2d3 100644 --- a/framework/Web/UI/WebControls/THead.php +++ b/framework/Web/UI/WebControls/THead.php @@ -1,377 +1,377 @@ -<?php
 -/**
 - * THead class file
 - *
 - * @author Marcus Nyeholt <tanus@users.sourceforge.net> and Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI
 - */
 -
 -/**
 - * THead class
 - *
 - * THead displays a head element on a page. It displays the content
 - * enclosed in its body and the page title set by the
 - * {@link setTitle Title} property. In addition, stylesheets and JavaScripts registered via
 - * {@link TClientScriptManager::registerStyleSheet}, {@link TClientScriptManager::registerStyleSheetFile}
 - * {@link TClientScriptManager::registerHeadJavaScript}, and
 - * {@link TClientScriptManager::registerHeadJavaScriptFile} will also be displayed
 - * in the head.
 - * THead also manages and displays meta tags through its {@link getMetaTags MetaTags}
 - * property. You can add a meta object to the collection in code dynamically,
 - * or add it in template using the following syntax,
 - * <code>
 - * <com:THead>
 - *   <com:TMetaTag HttpEquiv="Pragma" Content="no-cache" />
 - *   <com:TMetaTag Name="keywords" Content="Prado" />
 - * </com:THead>
 - * </code>
 - *
 - * Note, {@link TPage} has a property {@link TPage::getHead Head} that refers to
 - * the THead control currently on the page. A page can have at most one THead
 - * control. Although not required, it is recommended to place a THead on your page.
 - * Without a THead on the page, stylesheets and javascripts in the current page
 - * theme will not be rendered.
 - *
 - * @author Marcus Nyeholt <tanus@users.sourceforge.net> and Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI
 - * @since 3.0
 - */
 -class THead extends TControl
 -{
 -	/**
 -	 * @var TList list of meta name tags to be loaded by {@link THead}
 -	 */
 -	private $_metaTags=null;
 -
 -	/**
 -	 * Registers the head control with the current page.
 -	 * This method is invoked when the control enters 'Init' stage.
 -	 * The method raises 'Init' event.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handlers can be invoked.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onInit($param)
 -	{
 -		parent::onInit($param);
 -		$this->getPage()->setHead($this);
 -	}
 -
 -	/**
 -	 * Processes an object that is created during parsing template.
 -	 * This method adds TMetaTag components into the {@link getMetaTags MetaTags}
 -	 * collection of the head control.
 -	 * @param string|TComponent text string or component parsed and instantiated in template
 -	 * @see createdOnTemplate
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TMetaTag)
 -			$this->getMetaTags()->add($object);
 -		else
 -			parent::addParsedObject($object);
 -	}
 -
 -	/**
 -	 * @return string the page title.
 -	 */
 -	public function getTitle()
 -	{
 -		return $this->getViewState('Title','');
 -	}
 -
 -	/**
 -	 * Sets the page title.
 -	 * This title will be rendered only if the {@link TPage::getTitle Title} property
 -	 * of the page is empty.
 -	 * @param string the page title.
 -	 */
 -	public function setTitle($value)
 -	{
 -		$this->setViewState('Title',$value,'');
 -	}
 -
 -	/**
 -	 * @return string base URL of the page. This URL is rendered as the 'href' attribute of <base> tag. Defaults to ''.
 -	 */
 -	public function getBaseUrl()
 -	{
 -		return $this->getViewState('BaseUrl','');
 -	}
 -
 -	/**
 -	 * @param string base URL of the page. This URL is rendered as the 'href' attribute of <base> tag.
 -	 */
 -	public function setBaseUrl($url)
 -	{
 -		$this->setViewState('BaseUrl',$url,'');
 -	}
 -
 -	/**
 -	 * @return string the URL for the shortcut icon of the page. Defaults to ''.
 -	 */
 -	public function getShortcutIcon()
 -	{
 -		return $this->getViewState('ShortcutIcon','');
 -	}
 -
 -	/**
 -	 * @param string the URL for the shortcut icon of the page.
 -	 */
 -	public function setShortcutIcon($url)
 -	{
 -		$this->setViewState('ShortcutIcon',$url,'');
 -	}
 -
 -	/**
 -	 * @return TMetaTagCollection meta tag collection
 -	 */
 -	public function getMetaTags()
 -	{
 -		if(($metaTags=$this->getViewState('MetaTags',null))===null)
 -		{
 -			$metaTags=new TMetaTagCollection;
 -			$this->setViewState('MetaTags',$metaTags,null);
 -		}
 -		return $metaTags;
 -	}
 -
 -	/**
 -	 * Renders the head control.
 -	 * @param THtmlWriter the writer for rendering purpose.
 -	 */
 -	public function render($writer)
 -	{
 -		$page=$this->getPage();
 -		$title=$this->getTitle();
 -		$writer->write("<head>\n<title>".THttpUtility::htmlEncode($title)."</title>\n");
 -		if(($baseUrl=$this->getBaseUrl())!=='')
 -			$writer->write('<base href="'.$baseUrl."\" />\n");
 -		if(($icon=$this->getShortcutIcon())!=='')
 -			$writer->write('<link rel="shortcut icon" href="'.$icon."\" />\n");
 -
 -		if(($metaTags=$this->getMetaTags())!==null)
 -		{
 -			foreach($metaTags as $metaTag)
 -			{
 -				$metaTag->render($writer);
 -				$writer->writeLine();
 -			}
 -		}
 -		$cs=$page->getClientScript();
 -		$cs->renderStyleSheetFiles($writer);
 -		$cs->renderStyleSheets($writer);
 -		if($page->getClientSupportsJavaScript())
 -		{
 -			$cs->renderHeadScriptFiles($writer);
 -			$cs->renderHeadScripts($writer);
 -		}
 -		parent::render($writer);
 -		$writer->write("</head>\n");
 -	}
 -}
 -
 -/**
 - * TMetaTag class.
 - *
 - * TMetaTag represents a meta tag appearing in a page head section.
 - * You can set its {@link setID ID}, {@link setHttpEquiv HttpEquiv},
 - * {@link setName Name}, {@link setContent Content}, {@link setScheme Scheme}
 - * properties, which correspond to id, http-equiv, name, content, and scheme
 - * attributes for a meta tag, respectively.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TMetaTag extends TComponent
 -{
 -	/**
 -	 * @var string id of the meta tag
 -	 */
 -	private $_id='';
 -	/**
 -	 * @var string http-equiv attribute of the meta tag
 -	 */
 -	private $_httpEquiv='';
 -	/**
 -	 * @var string name attribute of the meta tag
 -	 */
 -	private $_name='';
 -	/**
 -	 * @var string content attribute of the meta tag
 -	 */
 -	private $_content='';
 -	/**
 -	 * @var string scheme attribute of the meta tag
 -	 */
 -	private $_scheme='';
 -
 -	/**
 -	 * @return string id of the meta tag
 -	 */
 -	public function getID()
 -	{
 -		return $this->_id;
 -	}
 -
 -	/**
 -	 * @param string id of the meta tag
 -	 */
 -	public function setID($value)
 -	{
 -		$this->_id=$value;
 -	}
 -
 -	/**
 -	 * @return string http-equiv attribute of the meta tag
 -	 */
 -	public function getHttpEquiv()
 -	{
 -		return $this->_httpEquiv;
 -	}
 -
 -	/**
 -	 * @param string http-equiv attribute of the meta tag
 -	 */
 -	public function setHttpEquiv($value)
 -	{
 -		$this->_httpEquiv=$value;
 -	}
 -
 -	/**
 -	 * @return string name attribute of the meta tag
 -	 */
 -	public function getName()
 -	{
 -		return $this->_name;
 -	}
 -
 -	/**
 -	 * @param string name attribute of the meta tag
 -	 */
 -	public function setName($value)
 -	{
 -		$this->_name=$value;
 -	}
 -
 -	/**
 -	 * @return string content attribute of the meta tag
 -	 */
 -	public function getContent()
 -	{
 -		return $this->_content;
 -	}
 -
 -	/**
 -	 * @param string content attribute of the meta tag
 -	 */
 -	public function setContent($value)
 -	{
 -		$this->_content=$value;
 -	}
 -
 -	/**
 -	 * @return string scheme attribute of the meta tag
 -	 */
 -	public function getScheme()
 -	{
 -		return $this->_scheme;
 -	}
 -
 -	/**
 -	 * @param string scheme attribute of the meta tag
 -	 */
 -	public function setScheme($value)
 -	{
 -		$this->_scheme=$value;
 -	}
 -
 -	/**
 -	 * Renders the meta tag.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->_id!=='')
 -			$writer->addAttribute('id',$this->_id);
 -		if($this->_name!=='')
 -			$writer->addAttribute('name',$this->_name);
 -		if($this->_httpEquiv!=='')
 -			$writer->addAttribute('http-equiv',$this->_httpEquiv);
 -		if($this->_scheme!=='')
 -			$writer->addAttribute('scheme',$this->_scheme);
 -		$writer->addAttribute('content',$this->_content);
 -		$writer->renderBeginTag('meta');
 -		$writer->renderEndTag();
 -	}
 -}
 -
 -
 -/**
 - * TMetaTagCollection class
 - *
 - * TMetaTagCollection represents a collection of meta tags
 - * contained in a {@link THead} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TMetaTagCollection extends TList
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by performing type
 -	 * check on the item being added.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a {@link TMetaTag}
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TMetaTag)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('metatagcollection_metatag_invalid');
 -	}
 -
 -	/**
 -	 * Finds the lowest cardinal index of the meta tag whose id is the one being looked for.
 -	 * @param string the ID of the meta tag to be looked for
 -	 * @return integer the index of the meta tag found, -1 if not found.
 -	 */
 -	public function findIndexByID($id)
 -	{
 -		$index=0;
 -		foreach($this as $item)
 -		{
 -			if($item->getID()===$id)
 -				return $index;
 -			$index++;
 -		}
 -		return -1;
 -	}
 -
 -	/**
 -	 * Finds the item whose value is the one being looked for.
 -	 * @param string the id of the meta tag to be looked for
 -	 * @return TMetaTag the meta tag found, null if not found.
 -	 */
 -	public function findMetaTagByID($id)
 -	{
 -		if(($index=$this->findIndexByID($id))>=0)
 -			return $this->itemAt($index);
 -		else
 -			return null;
 -	}
 -}
 -
 -?>
 +<?php +/** + * THead class file + * + * @author Marcus Nyeholt <tanus@users.sourceforge.net> and Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI + */ + +/** + * THead class + * + * THead displays a head element on a page. It displays the content + * enclosed in its body and the page title set by the + * {@link setTitle Title} property. In addition, stylesheets and JavaScripts registered via + * {@link TClientScriptManager::registerStyleSheet}, {@link TClientScriptManager::registerStyleSheetFile} + * {@link TClientScriptManager::registerHeadJavaScript}, and + * {@link TClientScriptManager::registerHeadJavaScriptFile} will also be displayed + * in the head. + * THead also manages and displays meta tags through its {@link getMetaTags MetaTags} + * property. You can add a meta object to the collection in code dynamically, + * or add it in template using the following syntax, + * <code> + * <com:THead> + *   <com:TMetaTag HttpEquiv="Pragma" Content="no-cache" /> + *   <com:TMetaTag Name="keywords" Content="Prado" /> + * </com:THead> + * </code> + * + * Note, {@link TPage} has a property {@link TPage::getHead Head} that refers to + * the THead control currently on the page. A page can have at most one THead + * control. Although not required, it is recommended to place a THead on your page. + * Without a THead on the page, stylesheets and javascripts in the current page + * theme will not be rendered. + * + * @author Marcus Nyeholt <tanus@users.sourceforge.net> and Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI + * @since 3.0 + */ +class THead extends TControl +{ +	/** +	 * @var TList list of meta name tags to be loaded by {@link THead} +	 */ +	private $_metaTags=null; + +	/** +	 * Registers the head control with the current page. +	 * This method is invoked when the control enters 'Init' stage. +	 * The method raises 'Init' event. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handlers can be invoked. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onInit($param) +	{ +		parent::onInit($param); +		$this->getPage()->setHead($this); +	} + +	/** +	 * Processes an object that is created during parsing template. +	 * This method adds TMetaTag components into the {@link getMetaTags MetaTags} +	 * collection of the head control. +	 * @param string|TComponent text string or component parsed and instantiated in template +	 * @see createdOnTemplate +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TMetaTag) +			$this->getMetaTags()->add($object); +		else +			parent::addParsedObject($object); +	} + +	/** +	 * @return string the page title. +	 */ +	public function getTitle() +	{ +		return $this->getViewState('Title',''); +	} + +	/** +	 * Sets the page title. +	 * This title will be rendered only if the {@link TPage::getTitle Title} property +	 * of the page is empty. +	 * @param string the page title. +	 */ +	public function setTitle($value) +	{ +		$this->setViewState('Title',$value,''); +	} + +	/** +	 * @return string base URL of the page. This URL is rendered as the 'href' attribute of <base> tag. Defaults to ''. +	 */ +	public function getBaseUrl() +	{ +		return $this->getViewState('BaseUrl',''); +	} + +	/** +	 * @param string base URL of the page. This URL is rendered as the 'href' attribute of <base> tag. +	 */ +	public function setBaseUrl($url) +	{ +		$this->setViewState('BaseUrl',$url,''); +	} + +	/** +	 * @return string the URL for the shortcut icon of the page. Defaults to ''. +	 */ +	public function getShortcutIcon() +	{ +		return $this->getViewState('ShortcutIcon',''); +	} + +	/** +	 * @param string the URL for the shortcut icon of the page. +	 */ +	public function setShortcutIcon($url) +	{ +		$this->setViewState('ShortcutIcon',$url,''); +	} + +	/** +	 * @return TMetaTagCollection meta tag collection +	 */ +	public function getMetaTags() +	{ +		if(($metaTags=$this->getViewState('MetaTags',null))===null) +		{ +			$metaTags=new TMetaTagCollection; +			$this->setViewState('MetaTags',$metaTags,null); +		} +		return $metaTags; +	} + +	/** +	 * Renders the head control. +	 * @param THtmlWriter the writer for rendering purpose. +	 */ +	public function render($writer) +	{ +		$page=$this->getPage(); +		$title=$this->getTitle(); +		$writer->write("<head>\n<title>".THttpUtility::htmlEncode($title)."</title>\n"); +		if(($baseUrl=$this->getBaseUrl())!=='') +			$writer->write('<base href="'.$baseUrl."\" />\n"); +		if(($icon=$this->getShortcutIcon())!=='') +			$writer->write('<link rel="shortcut icon" href="'.$icon."\" />\n"); + +		if(($metaTags=$this->getMetaTags())!==null) +		{ +			foreach($metaTags as $metaTag) +			{ +				$metaTag->render($writer); +				$writer->writeLine(); +			} +		} +		$cs=$page->getClientScript(); +		$cs->renderStyleSheetFiles($writer); +		$cs->renderStyleSheets($writer); +		if($page->getClientSupportsJavaScript()) +		{ +			$cs->renderHeadScriptFiles($writer); +			$cs->renderHeadScripts($writer); +		} +		parent::render($writer); +		$writer->write("</head>\n"); +	} +} + +/** + * TMetaTag class. + * + * TMetaTag represents a meta tag appearing in a page head section. + * You can set its {@link setID ID}, {@link setHttpEquiv HttpEquiv}, + * {@link setName Name}, {@link setContent Content}, {@link setScheme Scheme} + * properties, which correspond to id, http-equiv, name, content, and scheme + * attributes for a meta tag, respectively. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TMetaTag extends TComponent +{ +	/** +	 * @var string id of the meta tag +	 */ +	private $_id=''; +	/** +	 * @var string http-equiv attribute of the meta tag +	 */ +	private $_httpEquiv=''; +	/** +	 * @var string name attribute of the meta tag +	 */ +	private $_name=''; +	/** +	 * @var string content attribute of the meta tag +	 */ +	private $_content=''; +	/** +	 * @var string scheme attribute of the meta tag +	 */ +	private $_scheme=''; + +	/** +	 * @return string id of the meta tag +	 */ +	public function getID() +	{ +		return $this->_id; +	} + +	/** +	 * @param string id of the meta tag +	 */ +	public function setID($value) +	{ +		$this->_id=$value; +	} + +	/** +	 * @return string http-equiv attribute of the meta tag +	 */ +	public function getHttpEquiv() +	{ +		return $this->_httpEquiv; +	} + +	/** +	 * @param string http-equiv attribute of the meta tag +	 */ +	public function setHttpEquiv($value) +	{ +		$this->_httpEquiv=$value; +	} + +	/** +	 * @return string name attribute of the meta tag +	 */ +	public function getName() +	{ +		return $this->_name; +	} + +	/** +	 * @param string name attribute of the meta tag +	 */ +	public function setName($value) +	{ +		$this->_name=$value; +	} + +	/** +	 * @return string content attribute of the meta tag +	 */ +	public function getContent() +	{ +		return $this->_content; +	} + +	/** +	 * @param string content attribute of the meta tag +	 */ +	public function setContent($value) +	{ +		$this->_content=$value; +	} + +	/** +	 * @return string scheme attribute of the meta tag +	 */ +	public function getScheme() +	{ +		return $this->_scheme; +	} + +	/** +	 * @param string scheme attribute of the meta tag +	 */ +	public function setScheme($value) +	{ +		$this->_scheme=$value; +	} + +	/** +	 * Renders the meta tag. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function render($writer) +	{ +		if($this->_id!=='') +			$writer->addAttribute('id',$this->_id); +		if($this->_name!=='') +			$writer->addAttribute('name',$this->_name); +		if($this->_httpEquiv!=='') +			$writer->addAttribute('http-equiv',$this->_httpEquiv); +		if($this->_scheme!=='') +			$writer->addAttribute('scheme',$this->_scheme); +		$writer->addAttribute('content',$this->_content); +		$writer->renderBeginTag('meta'); +		$writer->renderEndTag(); +	} +} + + +/** + * TMetaTagCollection class + * + * TMetaTagCollection represents a collection of meta tags + * contained in a {@link THead} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TMetaTagCollection extends TList +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by performing type +	 * check on the item being added. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a {@link TMetaTag} +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TMetaTag) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('metatagcollection_metatag_invalid'); +	} + +	/** +	 * Finds the lowest cardinal index of the meta tag whose id is the one being looked for. +	 * @param string the ID of the meta tag to be looked for +	 * @return integer the index of the meta tag found, -1 if not found. +	 */ +	public function findIndexByID($id) +	{ +		$index=0; +		foreach($this as $item) +		{ +			if($item->getID()===$id) +				return $index; +			$index++; +		} +		return -1; +	} + +	/** +	 * Finds the item whose value is the one being looked for. +	 * @param string the id of the meta tag to be looked for +	 * @return TMetaTag the meta tag found, null if not found. +	 */ +	public function findMetaTagByID($id) +	{ +		if(($index=$this->findIndexByID($id))>=0) +			return $this->itemAt($index); +		else +			return null; +	} +} + +?> diff --git a/framework/Web/UI/WebControls/THiddenField.php b/framework/Web/UI/WebControls/THiddenField.php index ac8ddfff..ec330d54 100644 --- a/framework/Web/UI/WebControls/THiddenField.php +++ b/framework/Web/UI/WebControls/THiddenField.php @@ -1,117 +1,117 @@ -<?php
 -/**
 - * THiddenField class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.xisc.com/
 +<?php +/** + * THiddenField class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.xisc.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.opensource.org/licenses/bsd-license.php BSD License
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * THiddenField class
 - *
 - * THiddenField displays a hidden input field on a Web page.
 - * The value of the input field can be accessed via {@link getValue Value} property.
 - * If upon postback the value is changed, a {@link onValueChanged OnValueChanged}
 - * event will be raised.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class THiddenField extends TControl implements IPostBackDataHandler, IValidatable, IDataRenderer
 -{
 -	private $_dataChanged=false;
 + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * THiddenField class + * + * THiddenField displays a hidden input field on a Web page. + * The value of the input field can be accessed via {@link getValue Value} property. + * If upon postback the value is changed, a {@link onValueChanged OnValueChanged} + * event will be raised. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class THiddenField extends TControl implements IPostBackDataHandler, IValidatable, IDataRenderer +{ +	private $_dataChanged=false;  	private $_isValid=true; -
 -	/**
 -	 * @return string tag name of the hidden field.
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'input';
 -	}
 -
 -	/**
 -	 * Sets focus to this control.
 -	 * This method overrides the parent implementation by forbidding setting focus to this control.
 -	 */
 -	public function focus()
 -	{
 -		throw new TNotSupportedException('hiddenfield_focus_unsupported');
 -	}
 -
 -	/**
 -	 * Renders the control.
 -	 * This method overrides the parent implementation by rendering
 -	 * the hidden field input element.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		$uniqueID=$this->getUniqueID();
 -		$this->getPage()->ensureRenderInForm($this);
 -		$writer->addAttribute('type','hidden');
 -		if($uniqueID!=='')
 -			$writer->addAttribute('name',$uniqueID);
 -		if($this->getID()!=='')
 -			$writer->addAttribute('id',$this->getClientID());
 -		if(($value=$this->getValue())!=='')
 -			$writer->addAttribute('value',$value);
 -
 -		if($this->getHasAttributes())
 -		{
 -			foreach($this->getAttributes() as $name=>$value)
 -				$writer->addAttribute($name,$value);
 -		}
 -
 -		$writer->renderBeginTag('input');
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Loads hidden field data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		$value=$values[$key];
 -		if($value===$this->getValue())
 -			return false;
 -		else
 -		{
 -			$this->setValue($value);
 -			return $this->_dataChanged=true;
 -		}
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Returns the value to be validated.
 -	 * This methid is required by IValidatable interface.
 -	 * @return mixed the value of the property to be validated.
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getValue();
 -	}
 -
 + +	/** +	 * @return string tag name of the hidden field. +	 */ +	protected function getTagName() +	{ +		return 'input'; +	} + +	/** +	 * Sets focus to this control. +	 * This method overrides the parent implementation by forbidding setting focus to this control. +	 */ +	public function focus() +	{ +		throw new TNotSupportedException('hiddenfield_focus_unsupported'); +	} + +	/** +	 * Renders the control. +	 * This method overrides the parent implementation by rendering +	 * the hidden field input element. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function render($writer) +	{ +		$uniqueID=$this->getUniqueID(); +		$this->getPage()->ensureRenderInForm($this); +		$writer->addAttribute('type','hidden'); +		if($uniqueID!=='') +			$writer->addAttribute('name',$uniqueID); +		if($this->getID()!=='') +			$writer->addAttribute('id',$this->getClientID()); +		if(($value=$this->getValue())!=='') +			$writer->addAttribute('value',$value); + +		if($this->getHasAttributes()) +		{ +			foreach($this->getAttributes() as $name=>$value) +				$writer->addAttribute($name,$value); +		} + +		$writer->renderBeginTag('input'); +		$writer->renderEndTag(); +	} + +	/** +	 * Loads hidden field data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		$value=$values[$key]; +		if($value===$this->getValue()) +			return false; +		else +		{ +			$this->setValue($value); +			return $this->_dataChanged=true; +		} +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Returns the value to be validated. +	 * This methid is required by IValidatable interface. +	 * @return mixed the value of the property to be validated. +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getValue(); +	} +  	/**  	 * Returns true if this control validated successfully.   	 * Defaults to true. @@ -129,96 +129,96 @@ class THiddenField extends TControl implements IPostBackDataHandler, IValidatabl  	    $this->_isValid=TPropertyValue::ensureBoolean($value);  	} -	/**
 -	 * Raises postdata changed event.
 -	 * This method calls {@link onValueChanged} method.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		$this->onValueChanged(null);
 -	}
 -
 -	/**
 -	 * This method is invoked when the value of the {@link getValue Value} property changes between posts to the server.
 -	 * The method raises 'OnValueChanged' event to fire up the event delegates.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the attached event handlers can be invoked.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onValueChanged($param)
 -	{
 -		$this->raiseEvent('OnValueChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * @return string the value of the THiddenField
 -	 */
 -	public function getValue()
 -	{
 -		return $this->getViewState('Value','');
 -	}
 -
 -	/**
 -	 * Sets the value of the THiddenField
 -	 * @param string the value to be set
 -	 */
 -	public function setValue($value)
 -	{
 -		$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.
 -	 */
 -	public function getEnableTheming()
 -	{
 -		return false;
 -	}
 -
 -	/**
 -	 * @param boolean whether theming is enabled for this control.
 -	 * @throws TNotSupportedException This method is always thrown when calling this method.
 -	 */
 -	public function setEnableTheming($value)
 -	{
 -		throw new TNotSupportedException('hiddenfield_theming_unsupported');
 -	}
 -
 -	/**
 -	 * @param string Skin ID
 -	 * @throws TNotSupportedException This method is always thrown when calling this method.
 -	 */
 -	public function setSkinID($value)
 -	{
 -		throw new TNotSupportedException('hiddenfield_skinid_unsupported');
 -	}
 -}
 -
 +	/** +	 * Raises postdata changed event. +	 * This method calls {@link onValueChanged} method. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		$this->onValueChanged(null); +	} + +	/** +	 * This method is invoked when the value of the {@link getValue Value} property changes between posts to the server. +	 * The method raises 'OnValueChanged' event to fire up the event delegates. +	 * If you override this method, be sure to call the parent implementation +	 * so that the attached event handlers can be invoked. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onValueChanged($param) +	{ +		$this->raiseEvent('OnValueChanged',$this,$param); +	} + +	/** +	 * @return string the value of the THiddenField +	 */ +	public function getValue() +	{ +		return $this->getViewState('Value',''); +	} + +	/** +	 * Sets the value of the THiddenField +	 * @param string the value to be set +	 */ +	public function setValue($value) +	{ +		$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. +	 */ +	public function getEnableTheming() +	{ +		return false; +	} + +	/** +	 * @param boolean whether theming is enabled for this control. +	 * @throws TNotSupportedException This method is always thrown when calling this method. +	 */ +	public function setEnableTheming($value) +	{ +		throw new TNotSupportedException('hiddenfield_theming_unsupported'); +	} + +	/** +	 * @param string Skin ID +	 * @throws TNotSupportedException This method is always thrown when calling this method. +	 */ +	public function setSkinID($value) +	{ +		throw new TNotSupportedException('hiddenfield_skinid_unsupported'); +	} +} + diff --git a/framework/Web/UI/WebControls/THtmlElement.php b/framework/Web/UI/WebControls/THtmlElement.php index 3889ee50..29cd0057 100644 --- a/framework/Web/UI/WebControls/THtmlElement.php +++ b/framework/Web/UI/WebControls/THtmlElement.php @@ -1,68 +1,68 @@ -<?php
 -/**
 - * THtmlElement class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TWebControl');
 -
 -/**
 - * THtmlElement class.
 - *
 - * THtmlElement represents a generic HTML element whose tag name is specified
 - * via {@link setTagName TagName} property. Because THtmlElement extends from
 - * {@link TWebControl}, it enjoys all its functionalities.
 - *
 - * To change the default tag your subclass should override {@link getDefaultTagName}
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @author Brad Anderson <javalizard@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.2
 - */
 -class THtmlElement extends TWebControl
 -{
 -	/**
 -	 * @var the tag of this element
 -	 */
 -	private $_tagName=null;
 -
 -	/**
 -	 * @return string the tag name of this control. Defaults to 'span'.
 -	 */
 -	public function getTagName()
 -	{
 -		return ($this->_tagName !== null) ? $this->_tagName : ($this->_tagName = $this->getDefaultTagName());
 -	}
 -
 -	/**
 -	 * @param string the tag name of this control.
 -	 */
 -	public function setTagName($value)
 -	{
 -		$this->_tagName=TPropertyValue::ensureString($value);
 -	}
 -	
 -	/**
 -	 *	This is the default tag when no other is specified
 -	 * @return string the default tag 
 -	 */
 -	public function getDefaultTagName() {
 -		return 'span';
 -	}
 -	
 -	/**
 -	 * This tells you if this TagName has deviated from the original
 -	 * @return boolean true if TagName has deviated from the default. 
 -	 */
 -	public function getIsMutated() {
 -		return $this->_tagName !== null && $this->_tagName != $this->getDefaultTagName();
 -	}
 -}
 +<?php +/** + * THtmlElement class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TWebControl'); + +/** + * THtmlElement class. + * + * THtmlElement represents a generic HTML element whose tag name is specified + * via {@link setTagName TagName} property. Because THtmlElement extends from + * {@link TWebControl}, it enjoys all its functionalities. + * + * To change the default tag your subclass should override {@link getDefaultTagName} + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @author Brad Anderson <javalizard@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.2 + */ +class THtmlElement extends TWebControl +{ +	/** +	 * @var the tag of this element +	 */ +	private $_tagName=null; + +	/** +	 * @return string the tag name of this control. Defaults to 'span'. +	 */ +	public function getTagName() +	{ +		return ($this->_tagName !== null) ? $this->_tagName : ($this->_tagName = $this->getDefaultTagName()); +	} + +	/** +	 * @param string the tag name of this control. +	 */ +	public function setTagName($value) +	{ +		$this->_tagName=TPropertyValue::ensureString($value); +	} +	 +	/** +	 *	This is the default tag when no other is specified +	 * @return string the default tag  +	 */ +	public function getDefaultTagName() { +		return 'span'; +	} +	 +	/** +	 * This tells you if this TagName has deviated from the original +	 * @return boolean true if TagName has deviated from the default.  +	 */ +	public function getIsMutated() { +		return $this->_tagName !== null && $this->_tagName != $this->getDefaultTagName(); +	} +} diff --git a/framework/Web/UI/WebControls/THyperLink.php b/framework/Web/UI/WebControls/THyperLink.php index 1e32d6c9..b745f7b0 100644 --- a/framework/Web/UI/WebControls/THyperLink.php +++ b/framework/Web/UI/WebControls/THyperLink.php @@ -1,227 +1,227 @@ -<?php
 -/**
 - * THyperLink class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.xisc.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.opensource.org/licenses/bsd-license.php BSD License
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * THyperLink class
 - *
 - * THyperLink displays a hyperlink on a page. The hyperlink URL is specified
 - * via the {@link setNavigateUrl NavigateUrl} property, and link text is via
 - * the {@link setText Text} property. It is also possible to display an image
 - * by setting the {@link setImageUrl ImageUrl} property. In this case,
 - * {@link getText Text} is displayed as the alternate text of the image.
 - * The link target is specified via the {@link setTarget Target} property.
 - * If both {@link getImageUrl ImageUrl} and {@link getText Text} are empty,
 - * the content enclosed within the control tag will be rendered.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class THyperLink extends TWebControl implements IDataRenderer
 -{
 -	/**
 -	 * @return string tag name of the hyperlink
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'a';
 -	}
 -
 -	/**
 -	 * Adds attributes related to a hyperlink element to renderer.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$isEnabled=$this->getEnabled(true);
 -		if($this->getEnabled() && !$isEnabled)
 -			$writer->addAttribute('disabled','disabled');
 -		parent::addAttributesToRender($writer);
 -		if(($url=$this->getNavigateUrl())!=='' && $isEnabled)
 -			$writer->addAttribute('href',$url);
 -		if(($target=$this->getTarget())!=='')
 -			$writer->addAttribute('target',$target);
 -	}
 -
 -	/**
 -	 * Renders the body content of the hyperlink.
 -	 * @param THtmlWriter the writer for rendering
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if(($imageUrl=$this->getImageUrl())==='')
 -		{
 -			if(($text=$this->getText())!=='')
 -				$writer->write(THttpUtility::htmlEncode($text));
 -			else if($this->getHasControls())
 -				parent::renderContents($writer);
 -			else
 -				$writer->write(THttpUtility::htmlEncode($this->getNavigateUrl()));
 -		}
 -		else
 -		{
 -			$this->createImage($imageUrl)->renderControl($writer);
 -		}
 -	}
 -
 -	/**
 -	 * Gets the TImage for rendering the ImageUrl property. This is not for
 -	 * creating dynamic images.
 -	 * @param string image url.
 -	 * @return TImage image control for rendering.
 -	 */
 -	protected function createImage($imageUrl)
 -	{
 -		$image=Prado::createComponent('System.Web.UI.WebControls.TImage');
 -		$image->setImageUrl($imageUrl);
 -		if(($width=$this->getImageWidth())!=='')
 -			$image->setWidth($width);
 -		if(($height=$this->getImageHeight())!=='')
 -			$image->setHeight($height);
 -		if(($toolTip=$this->getToolTip())!=='')
 -			$image->setToolTip($toolTip);
 -		if(($text=$this->getText())!=='')
 -			$image->setAlternateText($text);
 -		$image->setBorderWidth('0');
 -		return $image;
 -	}
 -
 -	/**
 -	 * @return string the text caption of the THyperLink
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text caption of the THyperLink.
 -	 * @param string the text caption to be set
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value,'');
 -	}
 -
 -	/**
 -	 * @return string height of the image in the THyperLink
 -	 */
 -	public function getImageHeight()
 -	{
 -		return $this->getViewState('ImageHeight','');
 -	}
 -	
 -	/**
 -	 * Sets the height of the image in the THyperLink
 -	 * @param string height of the image in the THyperLink
 -	 */
 -	public function setImageHeight($value)
 -	{
 -		$this->setViewSTate('ImageHeight',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the location of the image file for the THyperLink
 -	 */
 -	public function getImageUrl()
 -	{
 -		return $this->getViewState('ImageUrl','');
 -	}
 -
 -	/**
 -	 * Sets the location of image file of the THyperLink.
 -	 * @param string the image file location
 -	 */
 -	public function setImageUrl($value)
 -	{
 -		$this->setViewState('ImageUrl',$value,'');
 -	}
 -	
 -	/**
 -	 * @return string width of the image in the THyperLink
 -	 */
 -	public function getImageWidth()
 -	{
 -		return $this->getViewState('ImageWidth','');
 -	}
 -	
 -	/**
 -	 * Sets the width of the image in the THyperLink
 -	 * @param string width of the image
 -	 */
 -	public function setImageWidth($value)
 -	{
 -		$this->setViewState('ImageWidth',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the URL to link to when the THyperLink component is clicked.
 -	 */
 -	public function getNavigateUrl()
 -	{
 -		return $this->getViewState('NavigateUrl','');
 -	}
 -
 -	/**
 -	 * Sets the URL to link to when the THyperLink component is clicked.
 -	 * @param string the URL
 -	 */
 -	public function setNavigateUrl($value)
 -	{
 -		$this->setViewState('NavigateUrl',$value,'');
 -	}
 -
 -	/**
 -	 * Returns the URL to link to when the THyperLink component is clicked.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link getText()}.
 -	 * @return string the text caption
 -	 * @see getText
 -	 * @since 3.1.0
 -	 */
 -	public function getData()
 -	{
 -		return $this->getText();
 -	}
 -
 -	/**
 -	 * Sets the URL to link to when the THyperLink component is clicked.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link setText()}.
 -	 * @param string the text caption to be set
 -	 * @see setText
 -	 * @since 3.1.0
 -	 */
 -	public function setData($value)
 -	{
 -		$this->setText($value);
 -	}
 -
 -	/**
 -	 * @return string the target window or frame to display the Web page content linked to when the THyperLink component is clicked.
 -	 */
 -	public function getTarget()
 -	{
 -		return $this->getViewState('Target','');
 -	}
 -
 -	/**
 -	 * Sets the target window or frame to display the Web page content linked to when the THyperLink component is clicked.
 -	 * @param string the target window, valid values include '_blank', '_parent', '_self', '_top' and empty string.
 -	 */
 -	public function setTarget($value)
 -	{
 -		$this->setViewState('Target',$value,'');
 -	}
 -}
 -
 +<?php +/** + * THyperLink class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.xisc.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * THyperLink class + * + * THyperLink displays a hyperlink on a page. The hyperlink URL is specified + * via the {@link setNavigateUrl NavigateUrl} property, and link text is via + * the {@link setText Text} property. It is also possible to display an image + * by setting the {@link setImageUrl ImageUrl} property. In this case, + * {@link getText Text} is displayed as the alternate text of the image. + * The link target is specified via the {@link setTarget Target} property. + * If both {@link getImageUrl ImageUrl} and {@link getText Text} are empty, + * the content enclosed within the control tag will be rendered. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class THyperLink extends TWebControl implements IDataRenderer +{ +	/** +	 * @return string tag name of the hyperlink +	 */ +	protected function getTagName() +	{ +		return 'a'; +	} + +	/** +	 * Adds attributes related to a hyperlink element to renderer. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$isEnabled=$this->getEnabled(true); +		if($this->getEnabled() && !$isEnabled) +			$writer->addAttribute('disabled','disabled'); +		parent::addAttributesToRender($writer); +		if(($url=$this->getNavigateUrl())!=='' && $isEnabled) +			$writer->addAttribute('href',$url); +		if(($target=$this->getTarget())!=='') +			$writer->addAttribute('target',$target); +	} + +	/** +	 * Renders the body content of the hyperlink. +	 * @param THtmlWriter the writer for rendering +	 */ +	public function renderContents($writer) +	{ +		if(($imageUrl=$this->getImageUrl())==='') +		{ +			if(($text=$this->getText())!=='') +				$writer->write(THttpUtility::htmlEncode($text)); +			else if($this->getHasControls()) +				parent::renderContents($writer); +			else +				$writer->write(THttpUtility::htmlEncode($this->getNavigateUrl())); +		} +		else +		{ +			$this->createImage($imageUrl)->renderControl($writer); +		} +	} + +	/** +	 * Gets the TImage for rendering the ImageUrl property. This is not for +	 * creating dynamic images. +	 * @param string image url. +	 * @return TImage image control for rendering. +	 */ +	protected function createImage($imageUrl) +	{ +		$image=Prado::createComponent('System.Web.UI.WebControls.TImage'); +		$image->setImageUrl($imageUrl); +		if(($width=$this->getImageWidth())!=='') +			$image->setWidth($width); +		if(($height=$this->getImageHeight())!=='') +			$image->setHeight($height); +		if(($toolTip=$this->getToolTip())!=='') +			$image->setToolTip($toolTip); +		if(($text=$this->getText())!=='') +			$image->setAlternateText($text); +		$image->setBorderWidth('0'); +		return $image; +	} + +	/** +	 * @return string the text caption of the THyperLink +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text caption of the THyperLink. +	 * @param string the text caption to be set +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value,''); +	} + +	/** +	 * @return string height of the image in the THyperLink +	 */ +	public function getImageHeight() +	{ +		return $this->getViewState('ImageHeight',''); +	} +	 +	/** +	 * Sets the height of the image in the THyperLink +	 * @param string height of the image in the THyperLink +	 */ +	public function setImageHeight($value) +	{ +		$this->setViewSTate('ImageHeight',$value,''); +	} + +	/** +	 * @return string the location of the image file for the THyperLink +	 */ +	public function getImageUrl() +	{ +		return $this->getViewState('ImageUrl',''); +	} + +	/** +	 * Sets the location of image file of the THyperLink. +	 * @param string the image file location +	 */ +	public function setImageUrl($value) +	{ +		$this->setViewState('ImageUrl',$value,''); +	} +	 +	/** +	 * @return string width of the image in the THyperLink +	 */ +	public function getImageWidth() +	{ +		return $this->getViewState('ImageWidth',''); +	} +	 +	/** +	 * Sets the width of the image in the THyperLink +	 * @param string width of the image +	 */ +	public function setImageWidth($value) +	{ +		$this->setViewState('ImageWidth',$value,''); +	} + +	/** +	 * @return string the URL to link to when the THyperLink component is clicked. +	 */ +	public function getNavigateUrl() +	{ +		return $this->getViewState('NavigateUrl',''); +	} + +	/** +	 * Sets the URL to link to when the THyperLink component is clicked. +	 * @param string the URL +	 */ +	public function setNavigateUrl($value) +	{ +		$this->setViewState('NavigateUrl',$value,''); +	} + +	/** +	 * Returns the URL to link to when the THyperLink component is clicked. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link getText()}. +	 * @return string the text caption +	 * @see getText +	 * @since 3.1.0 +	 */ +	public function getData() +	{ +		return $this->getText(); +	} + +	/** +	 * Sets the URL to link to when the THyperLink component is clicked. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link setText()}. +	 * @param string the text caption to be set +	 * @see setText +	 * @since 3.1.0 +	 */ +	public function setData($value) +	{ +		$this->setText($value); +	} + +	/** +	 * @return string the target window or frame to display the Web page content linked to when the THyperLink component is clicked. +	 */ +	public function getTarget() +	{ +		return $this->getViewState('Target',''); +	} + +	/** +	 * Sets the target window or frame to display the Web page content linked to when the THyperLink component is clicked. +	 * @param string the target window, valid values include '_blank', '_parent', '_self', '_top' and empty string. +	 */ +	public function setTarget($value) +	{ +		$this->setViewState('Target',$value,''); +	} +} + diff --git a/framework/Web/UI/WebControls/THyperLinkColumn.php b/framework/Web/UI/WebControls/THyperLinkColumn.php index a73880f1..faa4ce42 100644 --- a/framework/Web/UI/WebControls/THyperLinkColumn.php +++ b/framework/Web/UI/WebControls/THyperLinkColumn.php @@ -1,273 +1,273 @@ -<?php
 -/**
 - * THyperLinkColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -/**
 - * THyperLink class file
 - */
 -Prado::using('System.Web.UI.WebControls.THyperLink');
 -
 -/**
 - * THyperLinkColumn class
 - *
 - * THyperLinkColumn contains a hyperlink for each item in the column.
 - * You can set the text and the url of the hyperlink by {@link setText Text}
 - * and {@link setNavigateUrl NavigateUrl} properties, respectively.
 - * You can also bind the text and url to specific data field in datasource
 - * by setting {@link setDataTextField DataTextField} and
 - * {@link setDataNavigateUrlField DataNavigateUrlField}.
 - * Both can be formatted before rendering according to the
 - * {@link setDataTextFormatString DataTextFormatString} and
 - * and {@link setDataNavigateUrlFormatString DataNavigateUrlFormatString}
 - * properties, respectively. If both {@link setText Text} and {@link setDataTextField DataTextField}
 - * are present, the latter takes precedence.
 - * The same rule applies to {@link setNavigateUrl NavigateUrl} and
 - * {@link setDataNavigateUrlField DataNavigateUrlField} properties.
 - *
 - * The hyperlinks in the column can be accessed by one of the following two methods:
 - * <code>
 - * $datagridItem->HyperLinkColumnID->HyperLink
 - * $datagridItem->HyperLinkColumnID->Controls[0]
 - * </code>
 - * The second method is possible because the hyperlink control created within the
 - * datagrid cell is the first child.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class THyperLinkColumn extends TDataGridColumn
 -{
 -	/**
 -	 * @return string the text caption of the hyperlink
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text caption of the hyperlink.
 -	 * @param string the text caption to be set
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field name from the data source to bind to the hyperlink caption
 -	 */
 -	public function getDataTextField()
 -	{
 -		return $this->getViewState('DataTextField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the hyperlink caption
 -	 */
 -	public function setDataTextField($value)
 -	{
 -		$this->setViewState('DataTextField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the hyperlink caption will be displayed.
 -	 */
 -	public function getDataTextFormatString()
 -	{
 -		return $this->getViewState('DataTextFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the hyperlink caption will be displayed.
 -	 */
 -	public function setDataTextFormatString($value)
 -	{
 -		$this->setViewState('DataTextFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return string height of the image in the THyperLink
 -	 */
 -	public function getImageHeight()
 -	{
 -		return $this->getViewState('ImageHeight','');
 -	}
 -	
 -	/**
 -	 * @param string height of the image in the THyperLink
 -	 */
 -	public function setImageHeight($value)
 -	{
 -		$this->setViewState('ImageHeight',$value,'');
 -	}
 -
 -	/**
 -	 * @return string url of the image in the THyperLink
 -	 */
 -	public function getImageUrl()
 -	{
 -		return $this->getViewState('ImageUrl','');
 -	}
 -	
 -	/**
 -	 * @param string url of the image in the THyperLink
 -	 */
 -	public function setImageUrl($value)
 -	{
 -		$this->setViewState('ImageUrl',$value,'');
 -	}
 -	
 -	/**
 -	 * @return string width of the image in the THyperLink
 -	 */
 -	public function getImageWidth()
 -	{
 -		return $this->getViewState('ImageWidth','');
 -	}
 -	
 -	/**
 -	 * @param string width of the image in the THyperLink
 -	 */
 -	public function setImageWidth($value)
 -	{
 -		$this->setViewState('ImageWidth',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the URL to link to when the hyperlink is clicked.
 -	 */
 -	public function getNavigateUrl()
 -	{
 -		return $this->getViewState('NavigateUrl','');
 -	}
 -
 -	/**
 -	 * Sets the URL to link to when the hyperlink is clicked.
 -	 * @param string the URL
 -	 */
 -	public function setNavigateUrl($value)
 -	{
 -		$this->setViewState('NavigateUrl',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field name from the data source to bind to the navigate url of hyperlink
 -	 */
 -	public function getDataNavigateUrlField()
 -	{
 -		return $this->getViewState('DataNavigateUrlField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the navigate url of hyperlink
 -	 */
 -	public function setDataNavigateUrlField($value)
 -	{
 -		$this->setViewState('DataNavigateUrlField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the navigate url of hyperlink will be displayed.
 -	 */
 -	public function getDataNavigateUrlFormatString()
 -	{
 -		return $this->getViewState('DataNavigateUrlFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the navigate url of hyperlink will be displayed.
 -	 */
 -	public function setDataNavigateUrlFormatString($value)
 -	{
 -		$this->setViewState('DataNavigateUrlFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the target window or frame to display the Web page content linked to when the hyperlink is clicked.
 -	 */
 -	public function getTarget()
 -	{
 -		return $this->getViewState('Target','');
 -	}
 -
 -	/**
 -	 * Sets the target window or frame to display the Web page content linked to when the hyperlink is clicked.
 -	 * @param string the target window, valid values include '_blank', '_parent', '_self', '_top' and empty string.
 -	 */
 -	public function setTarget($value)
 -	{
 -		$this->setViewState('Target',$value,'');
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It creates a hyperlink within the cell.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem)
 -		{
 -			$link=new THyperLink;
 -			if(($url = $this->getImageUrl())!=='')
 -			{
 -				$link->setImageUrl($url);
 -				if(($width=$this->getImageWidth())!=='')
 -					$link->setImageWidth($width);
 -				if(($height=$this->getImageHeight())!=='')
 -					$link->setImageHeight($height);
 -			}
 -			$link->setText($this->getText());
 -			$link->setNavigateUrl($this->getNavigateUrl());
 -			$link->setTarget($this->getTarget());
 -			if($this->getDataTextField()!=='' || $this->getDataNavigateUrlField()!=='')
 -				$link->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -			$cell->getControls()->add($link);
 -			$cell->registerObject('HyperLink',$link);
 -		}
 -		else
 -			parent::initializeCell($cell,$columnIndex,$itemType);
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		$item=$sender->getNamingContainer();
 -		$data=$item->getData();
 -		if(($field=$this->getDataTextField())!=='')
 -		{
 -			$value=$this->getDataFieldValue($data,$field);
 -			$text=$this->formatDataValue($this->getDataTextFormatString(),$value);
 -			$sender->setText($text);
 -		}
 -		if(($field=$this->getDataNavigateUrlField())!=='')
 -		{
 -			$value=$this->getDataFieldValue($data,$field);
 -			$url=$this->formatDataValue($this->getDataNavigateUrlFormatString(),$value);
 -			$sender->setNavigateUrl($url);
 -		}
 -	}
 -}
 -
 +<?php +/** + * THyperLinkColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); +/** + * THyperLink class file + */ +Prado::using('System.Web.UI.WebControls.THyperLink'); + +/** + * THyperLinkColumn class + * + * THyperLinkColumn contains a hyperlink for each item in the column. + * You can set the text and the url of the hyperlink by {@link setText Text} + * and {@link setNavigateUrl NavigateUrl} properties, respectively. + * You can also bind the text and url to specific data field in datasource + * by setting {@link setDataTextField DataTextField} and + * {@link setDataNavigateUrlField DataNavigateUrlField}. + * Both can be formatted before rendering according to the + * {@link setDataTextFormatString DataTextFormatString} and + * and {@link setDataNavigateUrlFormatString DataNavigateUrlFormatString} + * properties, respectively. If both {@link setText Text} and {@link setDataTextField DataTextField} + * are present, the latter takes precedence. + * The same rule applies to {@link setNavigateUrl NavigateUrl} and + * {@link setDataNavigateUrlField DataNavigateUrlField} properties. + * + * The hyperlinks in the column can be accessed by one of the following two methods: + * <code> + * $datagridItem->HyperLinkColumnID->HyperLink + * $datagridItem->HyperLinkColumnID->Controls[0] + * </code> + * The second method is possible because the hyperlink control created within the + * datagrid cell is the first child. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class THyperLinkColumn extends TDataGridColumn +{ +	/** +	 * @return string the text caption of the hyperlink +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text caption of the hyperlink. +	 * @param string the text caption to be set +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value,''); +	} + +	/** +	 * @return string the field name from the data source to bind to the hyperlink caption +	 */ +	public function getDataTextField() +	{ +		return $this->getViewState('DataTextField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the hyperlink caption +	 */ +	public function setDataTextField($value) +	{ +		$this->setViewState('DataTextField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the hyperlink caption will be displayed. +	 */ +	public function getDataTextFormatString() +	{ +		return $this->getViewState('DataTextFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the hyperlink caption will be displayed. +	 */ +	public function setDataTextFormatString($value) +	{ +		$this->setViewState('DataTextFormatString',$value,''); +	} + +	/** +	 * @return string height of the image in the THyperLink +	 */ +	public function getImageHeight() +	{ +		return $this->getViewState('ImageHeight',''); +	} +	 +	/** +	 * @param string height of the image in the THyperLink +	 */ +	public function setImageHeight($value) +	{ +		$this->setViewState('ImageHeight',$value,''); +	} + +	/** +	 * @return string url of the image in the THyperLink +	 */ +	public function getImageUrl() +	{ +		return $this->getViewState('ImageUrl',''); +	} +	 +	/** +	 * @param string url of the image in the THyperLink +	 */ +	public function setImageUrl($value) +	{ +		$this->setViewState('ImageUrl',$value,''); +	} +	 +	/** +	 * @return string width of the image in the THyperLink +	 */ +	public function getImageWidth() +	{ +		return $this->getViewState('ImageWidth',''); +	} +	 +	/** +	 * @param string width of the image in the THyperLink +	 */ +	public function setImageWidth($value) +	{ +		$this->setViewState('ImageWidth',$value,''); +	} + +	/** +	 * @return string the URL to link to when the hyperlink is clicked. +	 */ +	public function getNavigateUrl() +	{ +		return $this->getViewState('NavigateUrl',''); +	} + +	/** +	 * Sets the URL to link to when the hyperlink is clicked. +	 * @param string the URL +	 */ +	public function setNavigateUrl($value) +	{ +		$this->setViewState('NavigateUrl',$value,''); +	} + +	/** +	 * @return string the field name from the data source to bind to the navigate url of hyperlink +	 */ +	public function getDataNavigateUrlField() +	{ +		return $this->getViewState('DataNavigateUrlField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the navigate url of hyperlink +	 */ +	public function setDataNavigateUrlField($value) +	{ +		$this->setViewState('DataNavigateUrlField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the navigate url of hyperlink will be displayed. +	 */ +	public function getDataNavigateUrlFormatString() +	{ +		return $this->getViewState('DataNavigateUrlFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the navigate url of hyperlink will be displayed. +	 */ +	public function setDataNavigateUrlFormatString($value) +	{ +		$this->setViewState('DataNavigateUrlFormatString',$value,''); +	} + +	/** +	 * @return string the target window or frame to display the Web page content linked to when the hyperlink is clicked. +	 */ +	public function getTarget() +	{ +		return $this->getViewState('Target',''); +	} + +	/** +	 * Sets the target window or frame to display the Web page content linked to when the hyperlink is clicked. +	 * @param string the target window, valid values include '_blank', '_parent', '_self', '_top' and empty string. +	 */ +	public function setTarget($value) +	{ +		$this->setViewState('Target',$value,''); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It creates a hyperlink within the cell. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem) +		{ +			$link=new THyperLink; +			if(($url = $this->getImageUrl())!=='') +			{ +				$link->setImageUrl($url); +				if(($width=$this->getImageWidth())!=='') +					$link->setImageWidth($width); +				if(($height=$this->getImageHeight())!=='') +					$link->setImageHeight($height); +			} +			$link->setText($this->getText()); +			$link->setNavigateUrl($this->getNavigateUrl()); +			$link->setTarget($this->getTarget()); +			if($this->getDataTextField()!=='' || $this->getDataNavigateUrlField()!=='') +				$link->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +			$cell->getControls()->add($link); +			$cell->registerObject('HyperLink',$link); +		} +		else +			parent::initializeCell($cell,$columnIndex,$itemType); +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		$item=$sender->getNamingContainer(); +		$data=$item->getData(); +		if(($field=$this->getDataTextField())!=='') +		{ +			$value=$this->getDataFieldValue($data,$field); +			$text=$this->formatDataValue($this->getDataTextFormatString(),$value); +			$sender->setText($text); +		} +		if(($field=$this->getDataNavigateUrlField())!=='') +		{ +			$value=$this->getDataFieldValue($data,$field); +			$url=$this->formatDataValue($this->getDataNavigateUrlFormatString(),$value); +			$sender->setNavigateUrl($url); +		} +	} +} + diff --git a/framework/Web/UI/WebControls/TImage.php b/framework/Web/UI/WebControls/TImage.php index 37f9a050..c8dde281 100644 --- a/framework/Web/UI/WebControls/TImage.php +++ b/framework/Web/UI/WebControls/TImage.php @@ -1,157 +1,157 @@ -<?php
 -/**
 - * TImage class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TImage class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TImage class
 - *
 - * TImage displays an image on a page. The image is specified via the
 - * {@link setImageUrl ImageUrl} property which takes a relative or absolute
 - * URL to the image file. The alignment of the image displayed is set by
 - * the {@link setImageAlign ImageAlign} property. To set alternative texts
 - * or long description of the image, use {@link setAlternateText AlternateText}
 - * or {@link setDescriptionUrl DescriptionUrl} property, respectively.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TImage extends TWebControl implements IDataRenderer
 -{
 -	/**
 -	 * @return string tag name of image control
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'img';
 -	}
 -
 -	/**
 -	 * Adds attributes related to an HTML image element to renderer.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$writer->addAttribute('src',$this->getImageUrl());
 -		$writer->addAttribute('alt',$this->getAlternateText());
 -		if(($desc=$this->getDescriptionUrl())!=='')
 -			$writer->addAttribute('longdesc',$desc);
 -		if(($align=$this->getImageAlign())!=='')
 -			$writer->addAttribute('align',$align);
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the body content of the image.
 -	 * Nothing to be rendered within image tags.
 -	 * @param THtmlWriter the writer for rendering
 -	 */
 -	public function renderContents($writer)
 -	{
 -	}
 -
 -	/**
 -	 * @return string the alternative text displayed in the TImage component when the image is unavailable.
 -	 */
 -	public function getAlternateText()
 -	{
 -		return $this->getViewState('AlternateText','');
 -	}
 -
 -	/**
 -	 * Sets the alternative text to be displayed in the TImage when the image is unavailable.
 -	 * @param string the alternative text
 -	 */
 -	public function setAlternateText($value)
 -	{
 -		$this->setViewState('AlternateText',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the alignment of the image with respective to other elements on the page, defaults to empty.
 -	 */
 -	public function getImageAlign()
 -	{
 -		return $this->getViewState('ImageAlign','');
 -	}
 -
 -	/**
 -	 * Sets the alignment of the image with respective to other elements on the page.
 -	 * Possible values include: absbottom, absmiddle, baseline, bottom, left,
 -	 * middle, right, texttop, and top. If an empty string is passed in,
 -	 * imagealign attribute will not be rendered.
 -	 * @param string the alignment of the image
 -	 */
 -	public function setImageAlign($value)
 -	{
 -		$this->setViewState('ImageAlign',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the URL of the image file
 -	 */
 -	public function getImageUrl()
 -	{
 -		return $this->getViewState('ImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL of the image file
 -	 */
 -	public function setImageUrl($value)
 -	{
 -		$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
 -	 */
 -	public function getDescriptionUrl()
 -	{
 -		return $this->getViewState('DescriptionUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL to the long description of the image.
 -	 */
 -	public function setDescriptionUrl($value)
 -	{
 -		$this->setViewState('DescriptionUrl',$value,'');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TImage class + * + * TImage displays an image on a page. The image is specified via the + * {@link setImageUrl ImageUrl} property which takes a relative or absolute + * URL to the image file. The alignment of the image displayed is set by + * the {@link setImageAlign ImageAlign} property. To set alternative texts + * or long description of the image, use {@link setAlternateText AlternateText} + * or {@link setDescriptionUrl DescriptionUrl} property, respectively. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TImage extends TWebControl implements IDataRenderer +{ +	/** +	 * @return string tag name of image control +	 */ +	protected function getTagName() +	{ +		return 'img'; +	} + +	/** +	 * Adds attributes related to an HTML image element to renderer. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$writer->addAttribute('src',$this->getImageUrl()); +		$writer->addAttribute('alt',$this->getAlternateText()); +		if(($desc=$this->getDescriptionUrl())!=='') +			$writer->addAttribute('longdesc',$desc); +		if(($align=$this->getImageAlign())!=='') +			$writer->addAttribute('align',$align); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Renders the body content of the image. +	 * Nothing to be rendered within image tags. +	 * @param THtmlWriter the writer for rendering +	 */ +	public function renderContents($writer) +	{ +	} + +	/** +	 * @return string the alternative text displayed in the TImage component when the image is unavailable. +	 */ +	public function getAlternateText() +	{ +		return $this->getViewState('AlternateText',''); +	} + +	/** +	 * Sets the alternative text to be displayed in the TImage when the image is unavailable. +	 * @param string the alternative text +	 */ +	public function setAlternateText($value) +	{ +		$this->setViewState('AlternateText',$value,''); +	} + +	/** +	 * @return string the alignment of the image with respective to other elements on the page, defaults to empty. +	 */ +	public function getImageAlign() +	{ +		return $this->getViewState('ImageAlign',''); +	} + +	/** +	 * Sets the alignment of the image with respective to other elements on the page. +	 * Possible values include: absbottom, absmiddle, baseline, bottom, left, +	 * middle, right, texttop, and top. If an empty string is passed in, +	 * imagealign attribute will not be rendered. +	 * @param string the alignment of the image +	 */ +	public function setImageAlign($value) +	{ +		$this->setViewState('ImageAlign',$value,''); +	} + +	/** +	 * @return string the URL of the image file +	 */ +	public function getImageUrl() +	{ +		return $this->getViewState('ImageUrl',''); +	} + +	/** +	 * @param string the URL of the image file +	 */ +	public function setImageUrl($value) +	{ +		$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 +	 */ +	public function getDescriptionUrl() +	{ +		return $this->getViewState('DescriptionUrl',''); +	} + +	/** +	 * @param string the URL to the long description of the image. +	 */ +	public function setDescriptionUrl($value) +	{ +		$this->setViewState('DescriptionUrl',$value,''); +	} +} + diff --git a/framework/Web/UI/WebControls/TImageButton.php b/framework/Web/UI/WebControls/TImageButton.php index 350c84d4..a92a9df8 100644 --- a/framework/Web/UI/WebControls/TImageButton.php +++ b/framework/Web/UI/WebControls/TImageButton.php @@ -1,442 +1,442 @@ -<?php
 -/**
 - * TImageButton class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TImageButton class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TImage class file
 - */
 -Prado::using('System.Web.UI.WebControls.TImage');
 -
 -/**
 - * TImageButton class
 - *
 - * TImageButton creates an image button on the page. It is used to submit data to a page.
 - * You can create either a <b>submit</b> button or a <b>command</b> button.
 - *
 - * A <b>command</b> button has a command name (specified by
 - * the {@link setCommandName CommandName} property) and and a command parameter
 - * (specified by {@link setCommandParameter CommandParameter} property)
 - * associated with the button. This allows you to create multiple TLinkButton
 - * components on a Web page and programmatically determine which one is clicked
 - * with what parameter. You can provide an event handler for
 - * {@link onCommand OnCommand} event to programmatically control the actions performed
 - * when the command button is clicked. In the event handler, you can determine
 - * the {@link setCommandName CommandName} property value and
 - * the {@link setCommandParameter CommandParameter} property value
 - * through the {@link TCommandParameter::getName Name} and
 - * {@link TCommandParameter::getParameter Parameter} properties of the event
 - * parameter which is of type {@link TCommandEventParameter}.
 - *
 - * A <b>submit</b> button does not have a command name associated with the button
 - * and clicking on it simply posts the Web page back to the server.
 - * By default, a TImageButton control is a submit button.
 - * You can provide an event handler for the {@link onClick OnClick} event
 - * to programmatically control the actions performed when the submit button is clicked.
 - * The coordinates of the clicking point can be obtained from the {@link onClick OnClick}
 - * event parameter, which is of type {@link TImageClickEventParameter}.
 - *
 - * Clicking on button can trigger form validation, if
 - * {@link setCausesValidation CausesValidation} is true.
 - * And the validation may be restricted within a certain group of validator
 - * controls by setting {@link setValidationGroup ValidationGroup} property.
 - * If validation is successful, the data will be post back to the same page.
 - *
 - * TImageButton displays the {@link setText Text} property as the hint text to the displayed image.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEventHandler, IButtonControl
 -{
 -	/**
 -	 * @var integer x coordinate that the image is being clicked at
 -	 */
 -	private $_x=0;
 -	/**
 -	 * @var integer y coordinate that the image is being clicked at
 -	 */
 -	private $_y=0;
 -	private $_dataChanged=false;
 -
 -	/**
 -	 * @return string tag name of the button
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'input';
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This overrides the parent implementation with additional button specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$page=$this->getPage();
 -		$page->ensureRenderInForm($this);
 -		$writer->addAttribute('type','image');
 -		if(($uniqueID=$this->getUniqueID())!=='')
 -			$writer->addAttribute('name',$uniqueID);
 -		if($this->getEnabled(true))
 -		{
 -			if($this->getEnableClientScript() && $this->needPostBackScript())
 -				$this->renderClientControlScript($writer);
 -		}
 -		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
 -			$writer->addAttribute('disabled','disabled');
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the client-script code.
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$writer->addAttribute('id',$this->getClientID());
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TImageButton';
 -	}
 -
 -	/**
 -	 * @return boolean whether to perform validation if the button is clicked
 -	 */
 -	protected function canCauseValidation()
 -	{
 -		if($this->getCausesValidation())
 -		{
 -			$group=$this->getValidationGroup();
 -			return $this->getPage()->getValidators($group)->getCount()>0;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @param boolean set by a panel to register this button as the default button for the panel.
 -	 */
 -	public function setIsDefaultButton($value)
 -	{
 -		$this->setViewState('IsDefaultButton', TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean true if this button is registered as a default button for a panel.
 -	 */
 -	public function getIsDefaultButton()
 -	{
 -		return $this->getViewState('IsDefaultButton', false);
 -	}
 -
 -	/**
 -	 * @return boolean whether the button needs javascript to do postback
 -	 */
 -	protected function needPostBackScript()
 -	{
 -		return $this->canCauseValidation() || $this->getIsDefaultButton();
 -	}
 -
 -	/**
 -	 * Returns postback specifications for the button.
 -	 * This method is used by framework and control developers.
 -	 * @return array parameters about how the button defines its postback behavior.
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['EventTarget'] = $this->getUniqueID();
 -
 -		return $options;
 -	}
 -
 -	/**
 -	 * This method checks if the TImageButton is clicked and loads the coordinates of the clicking position.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		$uid=$this->getUniqueID();
 -		if(isset($values["{$uid}_x"]) && isset($values["{$uid}_y"]))
 -		{
 -			$this->_x=intval($values["{$uid}_x"]);
 -			$this->_y=intval($values["{$uid}_y"]);
 -			if($this->getPage()->getPostBackEventTarget()===null)
 -				$this->getPage()->setPostBackEventTarget($this);
 -			$this->_dataChanged=true;
 -		}
 -		return false;
 -	}
 -
 -	/**
 -	 * A dummy implementation for the IPostBackDataHandler interface.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		// no post data to handle
 -	}
 -
 -	/**
 -	 * This method is invoked when the button is clicked.
 -	 * The method raises 'OnClick' event to fire up the event handlers.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handler can be invoked.
 -	 * @param TImageClickEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onClick($param)
 -	{
 -		$this->raiseEvent('OnClick',$this,$param);
 -	}
 -
 -	/**
 -	 * This method is invoked when the button is clicked.
 -	 * The method raises 'OnCommand' event to fire up the event handlers.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handlers can be invoked.
 -	 * @param TCommandEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onCommand($param)
 -	{
 -		$this->raiseEvent('OnCommand',$this,$param);
 -		$this->raiseBubbleEvent($this,$param);
 -	}
 -
 -	/**
 -	 * Raises the postback event.
 -	 * This method is required by {@link IPostBackEventHandler} interface.
 -	 * If {@link getCausesValidation CausesValidation} is true, it will
 -	 * invoke the page's {@link TPage::validate validate} method first.
 -	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
 -	 * This method is mainly used by framework and control developers.
 -	 * @param TEventParameter the event parameter
 -	 */
 -	public function raisePostBackEvent($param)
 -	{
 -		if($this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onClick(new TImageClickEventParameter($this->_x,$this->_y));
 -		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by this button will cause input validation
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the command name associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function getCommandName()
 -	{
 -		return $this->getViewState('CommandName','');
 -	}
 -
 -	/**
 -	 * @param string the command name associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function setCommandName($value)
 -	{
 -		$this->setViewState('CommandName',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the parameter associated with the {@link onCommand OnCommand} event
 -	 */
 -	public function getCommandParameter()
 -	{
 -		return $this->getViewState('CommandParameter','');
 -	}
 -
 -	/**
 -	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function setCommandParameter($value)
 -	{
 -		$this->setViewState('CommandParameter',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the button causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the button causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * @return string caption of the button
 -	 */
 -	public function getText()
 -	{
 -		return $this->getAlternateText();
 -	}
 -
 -	/**
 -	 * @param string caption of the button
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setAlternateText($value);
 -	}
 -
 -	/**
 -	 * Registers the image button to receive postback data during postback.
 -	 * This is necessary because an image button, when postback, does not have
 -	 * direct mapping between post data and the image button name.
 -	 * This method overrides the parent implementation and is invoked before render.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		$this->getPage()->registerRequiresPostData($this);
 -	}
 -
 -	/**
 -	 * Renders the body content enclosed between the control tag.
 -	 * This overrides the parent implementation with nothing to be rendered.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -	}
 -}
 -
 -/**
 - * TImageClickEventParameter class
 - *
 - * TImageClickEventParameter encapsulates the parameter data for
 - * {@link TImageButton::onClick Click} event of {@link TImageButton} controls.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TImageClickEventParameter extends TEventParameter
 -{
 -	/**
 -	 * the X coordinate of the clicking point
 -	 * @var integer
 -	 */
 -	private $_x=0;
 -	/**
 -	 * the Y coordinate of the clicking point
 -	 * @var integer
 -	 */
 -	private $_y=0;
 -
 -	/**
 -	 * Constructor.
 -	 * @param integer X coordinate of the clicking point
 -	 * @param integer Y coordinate of the clicking point
 -	 */
 -	public function __construct($x,$y)
 -	{
 -		$this->_x=$x;
 -		$this->_y=$y;
 -	}
 -
 -	/**
 -	 * @return integer X coordinate of the clicking point, defaults to 0
 -	 */
 -	public function getX()
 -	{
 -		return $this->_x;
 -	}
 -
 -	/**
 -	 * @param integer X coordinate of the clicking point
 -	 */
 -	public function setX($value)
 -	{
 -		$this->_x=TPropertyValue::ensureInteger($value);
 -	}
 -
 -	/**
 -	 * @return integer Y coordinate of the clicking point, defaults to 0
 -	 */
 -	public function getY()
 -	{
 -		return $this->_y;
 -	}
 -
 -	/**
 -	 * @param integer Y coordinate of the clicking point
 -	 */
 -	public function setY($value)
 -	{
 -		$this->_y=TPropertyValue::ensureInteger($value);
 -	}
 -}
 -
 -?>
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TImage class file + */ +Prado::using('System.Web.UI.WebControls.TImage'); + +/** + * TImageButton class + * + * TImageButton creates an image button on the page. It is used to submit data to a page. + * You can create either a <b>submit</b> button or a <b>command</b> button. + * + * A <b>command</b> button has a command name (specified by + * the {@link setCommandName CommandName} property) and and a command parameter + * (specified by {@link setCommandParameter CommandParameter} property) + * associated with the button. This allows you to create multiple TLinkButton + * components on a Web page and programmatically determine which one is clicked + * with what parameter. You can provide an event handler for + * {@link onCommand OnCommand} event to programmatically control the actions performed + * when the command button is clicked. In the event handler, you can determine + * the {@link setCommandName CommandName} property value and + * the {@link setCommandParameter CommandParameter} property value + * through the {@link TCommandParameter::getName Name} and + * {@link TCommandParameter::getParameter Parameter} properties of the event + * parameter which is of type {@link TCommandEventParameter}. + * + * A <b>submit</b> button does not have a command name associated with the button + * and clicking on it simply posts the Web page back to the server. + * By default, a TImageButton control is a submit button. + * You can provide an event handler for the {@link onClick OnClick} event + * to programmatically control the actions performed when the submit button is clicked. + * The coordinates of the clicking point can be obtained from the {@link onClick OnClick} + * event parameter, which is of type {@link TImageClickEventParameter}. + * + * Clicking on button can trigger form validation, if + * {@link setCausesValidation CausesValidation} is true. + * And the validation may be restricted within a certain group of validator + * controls by setting {@link setValidationGroup ValidationGroup} property. + * If validation is successful, the data will be post back to the same page. + * + * TImageButton displays the {@link setText Text} property as the hint text to the displayed image. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEventHandler, IButtonControl +{ +	/** +	 * @var integer x coordinate that the image is being clicked at +	 */ +	private $_x=0; +	/** +	 * @var integer y coordinate that the image is being clicked at +	 */ +	private $_y=0; +	private $_dataChanged=false; + +	/** +	 * @return string tag name of the button +	 */ +	protected function getTagName() +	{ +		return 'input'; +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This overrides the parent implementation with additional button specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$page=$this->getPage(); +		$page->ensureRenderInForm($this); +		$writer->addAttribute('type','image'); +		if(($uniqueID=$this->getUniqueID())!=='') +			$writer->addAttribute('name',$uniqueID); +		if($this->getEnabled(true)) +		{ +			if($this->getEnableClientScript() && $this->needPostBackScript()) +				$this->renderClientControlScript($writer); +		} +		else if($this->getEnabled()) // in this case, parent will not render 'disabled' +			$writer->addAttribute('disabled','disabled'); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Renders the client-script code. +	 */ +	protected function renderClientControlScript($writer) +	{ +		$writer->addAttribute('id',$this->getClientID()); +		$cs = $this->getPage()->getClientScript(); +		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TImageButton'; +	} + +	/** +	 * @return boolean whether to perform validation if the button is clicked +	 */ +	protected function canCauseValidation() +	{ +		if($this->getCausesValidation()) +		{ +			$group=$this->getValidationGroup(); +			return $this->getPage()->getValidators($group)->getCount()>0; +		} +		else +			return false; +	} + +	/** +	 * @param boolean set by a panel to register this button as the default button for the panel. +	 */ +	public function setIsDefaultButton($value) +	{ +		$this->setViewState('IsDefaultButton', TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean true if this button is registered as a default button for a panel. +	 */ +	public function getIsDefaultButton() +	{ +		return $this->getViewState('IsDefaultButton', false); +	} + +	/** +	 * @return boolean whether the button needs javascript to do postback +	 */ +	protected function needPostBackScript() +	{ +		return $this->canCauseValidation() || $this->getIsDefaultButton(); +	} + +	/** +	 * Returns postback specifications for the button. +	 * This method is used by framework and control developers. +	 * @return array parameters about how the button defines its postback behavior. +	 */ +	protected function getPostBackOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['EventTarget'] = $this->getUniqueID(); + +		return $options; +	} + +	/** +	 * This method checks if the TImageButton is clicked and loads the coordinates of the clicking position. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		$uid=$this->getUniqueID(); +		if(isset($values["{$uid}_x"]) && isset($values["{$uid}_y"])) +		{ +			$this->_x=intval($values["{$uid}_x"]); +			$this->_y=intval($values["{$uid}_y"]); +			if($this->getPage()->getPostBackEventTarget()===null) +				$this->getPage()->setPostBackEventTarget($this); +			$this->_dataChanged=true; +		} +		return false; +	} + +	/** +	 * A dummy implementation for the IPostBackDataHandler interface. +	 */ +	public function raisePostDataChangedEvent() +	{ +		// no post data to handle +	} + +	/** +	 * This method is invoked when the button is clicked. +	 * The method raises 'OnClick' event to fire up the event handlers. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handler can be invoked. +	 * @param TImageClickEventParameter event parameter to be passed to the event handlers +	 */ +	public function onClick($param) +	{ +		$this->raiseEvent('OnClick',$this,$param); +	} + +	/** +	 * This method is invoked when the button is clicked. +	 * The method raises 'OnCommand' event to fire up the event handlers. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handlers can be invoked. +	 * @param TCommandEventParameter event parameter to be passed to the event handlers +	 */ +	public function onCommand($param) +	{ +		$this->raiseEvent('OnCommand',$this,$param); +		$this->raiseBubbleEvent($this,$param); +	} + +	/** +	 * Raises the postback event. +	 * This method is required by {@link IPostBackEventHandler} interface. +	 * If {@link getCausesValidation CausesValidation} is true, it will +	 * invoke the page's {@link TPage::validate validate} method first. +	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events. +	 * This method is mainly used by framework and control developers. +	 * @param TEventParameter the event parameter +	 */ +	public function raisePostBackEvent($param) +	{ +		if($this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onClick(new TImageClickEventParameter($this->_x,$this->_y)); +		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter())); +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * @return boolean whether postback event trigger by this button will cause input validation, default is true +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by this button will cause input validation +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the command name associated with the {@link onCommand OnCommand} event. +	 */ +	public function getCommandName() +	{ +		return $this->getViewState('CommandName',''); +	} + +	/** +	 * @param string the command name associated with the {@link onCommand OnCommand} event. +	 */ +	public function setCommandName($value) +	{ +		$this->setViewState('CommandName',$value,''); +	} + +	/** +	 * @return string the parameter associated with the {@link onCommand OnCommand} event +	 */ +	public function getCommandParameter() +	{ +		return $this->getViewState('CommandParameter',''); +	} + +	/** +	 * @param string the parameter associated with the {@link onCommand OnCommand} event. +	 */ +	public function setCommandParameter($value) +	{ +		$this->setViewState('CommandParameter',$value,''); +	} + +	/** +	 * @return string the group of validators which the button causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the button causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * @return string caption of the button +	 */ +	public function getText() +	{ +		return $this->getAlternateText(); +	} + +	/** +	 * @param string caption of the button +	 */ +	public function setText($value) +	{ +		$this->setAlternateText($value); +	} + +	/** +	 * Registers the image button to receive postback data during postback. +	 * This is necessary because an image button, when postback, does not have +	 * direct mapping between post data and the image button name. +	 * This method overrides the parent implementation and is invoked before render. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		$this->getPage()->registerRequiresPostData($this); +	} + +	/** +	 * Renders the body content enclosed between the control tag. +	 * This overrides the parent implementation with nothing to be rendered. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +	} +} + +/** + * TImageClickEventParameter class + * + * TImageClickEventParameter encapsulates the parameter data for + * {@link TImageButton::onClick Click} event of {@link TImageButton} controls. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TImageClickEventParameter extends TEventParameter +{ +	/** +	 * the X coordinate of the clicking point +	 * @var integer +	 */ +	private $_x=0; +	/** +	 * the Y coordinate of the clicking point +	 * @var integer +	 */ +	private $_y=0; + +	/** +	 * Constructor. +	 * @param integer X coordinate of the clicking point +	 * @param integer Y coordinate of the clicking point +	 */ +	public function __construct($x,$y) +	{ +		$this->_x=$x; +		$this->_y=$y; +	} + +	/** +	 * @return integer X coordinate of the clicking point, defaults to 0 +	 */ +	public function getX() +	{ +		return $this->_x; +	} + +	/** +	 * @param integer X coordinate of the clicking point +	 */ +	public function setX($value) +	{ +		$this->_x=TPropertyValue::ensureInteger($value); +	} + +	/** +	 * @return integer Y coordinate of the clicking point, defaults to 0 +	 */ +	public function getY() +	{ +		return $this->_y; +	} + +	/** +	 * @param integer Y coordinate of the clicking point +	 */ +	public function setY($value) +	{ +		$this->_y=TPropertyValue::ensureInteger($value); +	} +} + +?> diff --git a/framework/Web/UI/WebControls/TImageMap.php b/framework/Web/UI/WebControls/TImageMap.php index 5907d03d..718a3414 100644 --- a/framework/Web/UI/WebControls/TImageMap.php +++ b/framework/Web/UI/WebControls/TImageMap.php @@ -1,837 +1,837 @@ -<?php
 -/**
 - * TImageMap and related class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TImageMap and related class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TImage class file
 - */
 -Prado::using('System.Web.UI.WebControls.TImage');
 -
 -/**
 - * TImageMap class
 - *
 - * TImageMap represents an image on a page. Hotspot regions can be defined
 - * within the image. Depending on the {@link setHotSpotMode HotSpotMode},
 - * clicking on the hotspots may trigger a postback or navigate to a specified
 - * URL. The hotspots defined may be accessed via {@link getHotSpots HotSpots}.
 - * Each hotspot is described as a {@link THotSpot}, which can be a circle,
 - * rectangle, polygon, etc. To add hotspot in a template, use the following,
 - * <code>
 - *  <com:TImageMap>
 - *    <com:TCircleHotSpot ... />
 - *    <com:TRectangleHotSpot ... />
 - *    <com:TPolygonHotSpot ... />
 - *  </com:TImageMap>
 - * </code>
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TImageMap extends TImage implements IPostBackEventHandler
 -{
 -	const MAP_NAME_PREFIX='ImageMap';
 -
 -	/**
 -	 * Processes an object that is created during parsing template.
 -	 * This method adds {@link THotSpot} objects into the hotspot collection
 -	 * of the imagemap.
 -	 * @param string|TComponent text string or component parsed and instantiated in template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof THotSpot)
 -			$this->getHotSpots()->add($object);
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This overrides the parent implementation with additional imagemap specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		if($this->getHotSpots()->getCount()>0)
 -		{
 -			$writer->addAttribute('usemap','#'.self::MAP_NAME_PREFIX.$this->getClientID());
 -			$writer->addAttribute('id',$this->getUniqueID());
 -		}
 -		if($this->getEnabled() && !$this->getEnabled(true))
 -			$writer->addAttribute('disabled','disabled');
 -	}
 -
 -	/**
 -	 * Renders this imagemap.
 -	 * @param THtmlWriter
 -	 */
 -	public function render($writer)
 -	{
 -		parent::render($writer);
 -
 -		$hotspots=$this->getHotSpots();
 -
 -		if($hotspots->getCount()>0)
 -		{
 -			$clientID=$this->getClientID();
 -			$cs=$this->getPage()->getClientScript();
 -			$writer->writeLine();
 -			$writer->addAttribute('name',self::MAP_NAME_PREFIX.$clientID);
 -			$writer->renderBeginTag('map');
 -			$writer->writeLine();
 -			if(($mode=$this->getHotSpotMode())===THotSpotMode::NotSet)
 -				$mode=THotSpotMode::Navigate;
 -			$target=$this->getTarget();
 -			$i=0;
 -			$options['EventTarget'] = $this->getUniqueID();
 -			$options['StopEvent'] = true;
 -			$cs=$this->getPage()->getClientScript();
 -			foreach($hotspots as $hotspot)
 -			{
 -				if($hotspot->getHotSpotMode()===THotSpotMode::NotSet)
 -					$hotspot->setHotSpotMode($mode);
 -				if($target!=='' && $hotspot->getTarget()==='')
 -					$hotspot->setTarget($target);
 -				if($hotspot->getHotSpotMode()===THotSpotMode::PostBack)
 -				{
 -					$id=$clientID.'_'.$i;
 -					$writer->addAttribute('id',$id);
 -					$writer->addAttribute('href','#'.$id); //create unique no-op url references
 -					$options['ID']=$id;
 -					$options['EventParameter']="$i";
 -					$options['CausesValidation']=$hotspot->getCausesValidation();
 -					$options['ValidationGroup']=$hotspot->getValidationGroup();
 -					$cs->registerPostBackControl($this->getClientClassName(),$options);
 -				}
 -				$hotspot->render($writer);
 -				$writer->writeLine();
 -				$i++;
 -			}
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TImageMap';
 -	}
 -
 -	/**
 -	 * Raises the postback event.
 -	 * This method is required by {@link IPostBackEventHandler} interface.
 -	 * This method is mainly used by framework and control developers.
 -	 * @param TEventParameter the event parameter
 -	 */
 -	public function raisePostBackEvent($param)
 -	{
 -		$postBackValue=null;
 -		if($param!=='')
 -		{
 -			$index=TPropertyValue::ensureInteger($param);
 -			$hotspots=$this->getHotSpots();
 -			if($index>=0 && $index<$hotspots->getCount())
 -			{
 -				$hotspot=$hotspots->itemAt($index);
 -				if(($mode=$hotspot->getHotSpotMode())===THotSpotMode::NotSet)
 -					$mode=$this->getHotSpotMode();
 -				if($mode===THotSpotMode::PostBack)
 -				{
 -					$postBackValue=$hotspot->getPostBackValue();
 -					if($hotspot->getCausesValidation())
 -						$this->getPage()->validate($hotspot->getValidationGroup());
 -				}
 -			}
 -		}
 -		if($postBackValue!==null)
 -			$this->onClick(new TImageMapEventParameter($postBackValue));
 -	}
 -
 -	/**
 -	 * @return THotSpotMode the behavior of hotspot regions in this imagemap when they are clicked. Defaults to THotSpotMode::NotSet.
 -	 */
 -	public function getHotSpotMode()
 -	{
 -		return $this->getViewState('HotSpotMode',THotSpotMode::NotSet);
 -	}
 -
 -	/**
 -	 * Sets the behavior of hotspot regions in this imagemap when they are clicked.
 -	 * If an individual hotspot has a mode other than 'NotSet', the mode set in this
 -	 * imagemap will be ignored. By default, 'NotSet' is equivalent to 'Navigate'.
 -	 * @param THotSpotMode the behavior of hotspot regions in this imagemap when they are clicked.
 -	 */
 -	public function setHotSpotMode($value)
 -	{
 -		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'THotSpotMode'),THotSpotMode::NotSet);
 -	}
 -
 -	/**
 -	 * @return THotSpotCollection collection of hotspots defined in this imagemap.
 -	 */
 -	public function getHotSpots()
 -	{
 -		if(($hotspots=$this->getViewState('HotSpots',null))===null)
 -		{
 -			$hotspots=new THotSpotCollection;
 -			$this->setViewState('HotSpots',$hotspots);
 -		}
 -		return $hotspots;
 -	}
 -
 -	/**
 -	 * @return string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap. Defaults to ''.
 -	 */
 -	public function getTarget()
 -	{
 -		return $this->getViewState('Target','');
 -	}
 -
 -	/**
 -	 * @param string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap.
 -	 */
 -	public function setTarget($value)
 -	{
 -		$this->setViewState('Target',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * Raises <b>OnClick</b> event.
 -	 * This method is invoked when a hotspot region is clicked within the imagemap.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handler can be invoked.
 -	 * @param TImageMapEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onClick($param)
 -	{
 -		$this->raiseEvent('OnClick',$this,$param);
 -	}
 -}
 -
 -/**
 - * TImageMapEventParameter class.
 - *
 - * TImageMapEventParameter represents a postback event parameter
 - * when a hotspot is clicked and posts back in a {@link TImageMap}.
 - * To retrieve the post back value associated with the hotspot being clicked,
 - * access {@link getPostBackValue PostBackValue}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TImageMapEventParameter extends TEventParameter
 -{
 -	private $_postBackValue;
 -
 -	/**
 -	 * Constructor.
 -	 * @param string post back value associated with the hotspot clicked
 -	 */
 -	public function __construct($postBackValue)
 -	{
 -		$this->_postBackValue=$postBackValue;
 -	}
 -
 -	/**
 -	 * @return string post back value associated with the hotspot clicked
 -	 */
 -	public function getPostBackValue()
 -	{
 -		return $this->_postBackValue;
 -	}
 -}
 -
 -/**
 - * THotSpotCollection class.
 - *
 - * THotSpotCollection represents a collection of hotspots in an imagemap.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class THotSpotCollection extends TList
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by inserting only {@link THotSpot}.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a THotSpot.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof THotSpot)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('hotspotcollection_hotspot_required');
 -	}
 -}
 -
 -
 -/**
 - * THotSpot class.
 - *
 - * THotSpot implements the basic functionality common to all hot spot shapes.
 - * Derived classes include {@link TCircleHotSpot}, {@link TPolygonHotSpot}
 - * and {@link TRectangleHotSpot}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class THotSpot extends TComponent
 -{
 -	private $_viewState=array();
 -
 -	/**
 -	 * Returns a viewstate value.
 -	 *
 -	 * This function is very useful in defining getter functions for component properties
 -	 * that must be kept in viewstate.
 -	 * @param string the name of the viewstate value to be returned
 -	 * @param mixed the default value. If $key is not found in viewstate, $defaultValue will be returned
 -	 * @return mixed the viewstate value corresponding to $key
 -	 */
 -	protected function getViewState($key,$defaultValue=null)
 -	{
 -		return isset($this->_viewState[$key])?$this->_viewState[$key]:$defaultValue;
 -	}
 -
 -	/**
 -	 * Sets a viewstate value.
 -	 *
 -	 * This function is very useful in defining setter functions for control properties
 -	 * that must be kept in viewstate.
 -	 * Make sure that the viewstate value must be serializable and unserializable.
 -	 * @param string the name of the viewstate value
 -	 * @param mixed the viewstate value to be set
 -	 * @param mixed default value. If $value===$defaultValue, the item will be cleared from the viewstate.
 -	 */
 -	protected function setViewState($key,$value,$defaultValue=null)
 -	{
 -		if($value===$defaultValue)
 -			unset($this->_viewState[$key]);
 -		else
 -			$this->_viewState[$key]=$value;
 -	}
 -
 -	/**
 -	 * @return string shape of the hotspot, can be 'circle', 'rect', 'poly', etc.
 -	 */
 -	abstract public function getShape();
 -	/**
 -	 * @return string coordinates defining the hotspot shape.
 -	 */
 -	abstract public function getCoordinates();
 -
 -	/**
 -	 * @return string the access key that allows you to quickly navigate to the HotSpot region. Defaults to ''.
 -	 */
 -	public function getAccessKey()
 -	{
 -		return $this->getViewState('AccessKey','');
 -	}
 -
 -	/**
 -	 * @param string the access key that allows you to quickly navigate to the HotSpot region.
 -	 */
 -	public function setAccessKey($value)
 -	{
 -		$this->setViewState('AccessKey',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string the alternate text to display for a HotSpot object. Defaults to ''.
 -	 */
 -	public function getAlternateText()
 -	{
 -		return $this->getViewState('AlternateText','');
 -	}
 -
 -	/**
 -	 * @param string the alternate text to display for a HotSpot object.
 -	 */
 -	public function setAlternateText($value)
 -	{
 -		$this->setViewState('AlternateText',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return THotSpotMode the behavior of a HotSpot object when it is clicked. Defaults to THotSpotMode::NotSet.
 -	 */
 -	public function getHotSpotMode()
 -	{
 -		return $this->getViewState('HotSpotMode',THotSpotMode::NotSet);
 -	}
 -
 -	/**
 -	 * @param THotSpotMode the behavior of a HotSpot object when it is clicked.
 -	 */
 -	public function setHotSpotMode($value)
 -	{
 -		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'THotSpotMode'),THotSpotMode::NotSet);
 -	}
 -
 -	/**
 -	 * @return string the URL to navigate to when a HotSpot object is clicked. Defaults to ''.
 -	 */
 -	public function getNavigateUrl()
 -	{
 -		return $this->getViewState('NavigateUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL to navigate to when a HotSpot object is clicked.
 -	 */
 -	public function setNavigateUrl($value)
 -	{
 -		$this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string a value that is post back when the HotSpot is clicked. Defaults to ''.
 -	 */
 -	public function getPostBackValue()
 -	{
 -		return $this->getViewState('PostBackValue','');
 -	}
 -
 -	/**
 -	 * @param string a value that is post back when the HotSpot is clicked.
 -	 */
 -	public function setPostBackValue($value)
 -	{
 -		$this->setViewState('PostBackValue',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return integer the tab index of the HotSpot region. Defaults to 0.
 -	 */
 -	public function getTabIndex()
 -	{
 -		return $this->getViewState('TabIndex',0);
 -	}
 -
 -	/**
 -	 * @param integer the tab index of the HotSpot region.
 -	 */
 -	public function setTabIndex($value)
 -	{
 -		$this->setViewState('TabIndex',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by this hotspot will cause input validation, default is true
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by this hotspot will cause input validation
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the hotspot causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the hotspot causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * @return string  the target window or frame to display the new page when the HotSpot region
 -	 * is clicked. Defaults to ''.
 -	 */
 -	public function getTarget()
 -	{
 -		return $this->getViewState('Target','');
 -	}
 -
 -	/**
 -	 * @param string  the target window or frame to display the new page when the HotSpot region
 -	 * is clicked.
 -	 */
 -	public function setTarget($value)
 -	{
 -		$this->setViewState('Target',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return boolean whether the hotspot has custom attributes
 -	 */
 -	public function getHasAttributes()
 -	{
 -		if($attributes=$this->getViewState('Attributes',null))
 -			return $attributes->getCount()>0;
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Returns the list of custom attributes.
 -	 * Custom attributes are name-value pairs that may be rendered
 -	 * as HTML tags' attributes.
 -	 * @return TAttributeCollection the list of custom attributes
 -	 */
 -	public function getAttributes()
 -	{
 -		if($attributes=$this->getViewState('Attributes',null))
 -			return $attributes;
 -		else
 -		{
 -			$attributes=new TAttributeCollection;
 -			$this->setViewState('Attributes',$attributes,null);
 -			return $attributes;
 -		}
 -	}
 -
 -	/**
 -	 * @return boolean whether the named attribute exists
 -	 */
 -	public function hasAttribute($name)
 -	{
 -		if($attributes=$this->getViewState('Attributes',null))
 -			return $attributes->contains($name);
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @return string attribute value, null if attribute does not exist
 -	 */
 -	public function getAttribute($name)
 -	{
 -		if($attributes=$this->getViewState('Attributes',null))
 -			return $attributes->itemAt($name);
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * Sets a custom hotspot attribute.
 -	 * @param string attribute name
 -	 * @param string value of the attribute
 -	 */
 -	public function setAttribute($name,$value)
 -	{
 -		$this->getAttributes()->add($name,$value);
 -	}
 -
 -	/**
 -	 * Removes the named attribute.
 -	 * @param string the name of the attribute to be removed.
 -	 * @return string attribute value removed, null if attribute does not exist.
 -	 */
 -	public function removeAttribute($name)
 -	{
 -		if($attributes=$this->getViewState('Attributes',null))
 -			return $attributes->remove($name);
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * Renders this hotspot.
 -	 * @param THtmlWriter
 -	 */
 -	public function render($writer)
 -	{
 -		$writer->addAttribute('shape',$this->getShape());
 -		$writer->addAttribute('coords',$this->getCoordinates());
 -		if(($mode=$this->getHotSpotMode())===THotSpotMode::NotSet)
 -			$mode=THotSpotMode::Navigate;
 -		if($mode===THotSpotMode::Navigate)
 -		{
 -			$writer->addAttribute('href',$this->getNavigateUrl());
 -			if(($target=$this->getTarget())!=='')
 -				$writer->addAttribute('target',$target);
 -		}
 -		else if($mode===THotSpotMode::Inactive)
 -			$writer->addAttribute('nohref','true');
 -		$text=$this->getAlternateText();
 -		$writer->addAttribute('title',$text);
 -		$writer->addAttribute('alt',$text);
 -		if(($accessKey=$this->getAccessKey())!=='')
 -			$writer->addAttribute('accesskey',$accessKey);
 -		if(($tabIndex=$this->getTabIndex())!==0)
 -			$writer->addAttribute('tabindex',"$tabIndex");
 -		if($this->getHasAttributes())
 -		{
 -			foreach($this->getAttributes() as $name=>$value)
 -				$writer->addAttribute($name,$value);
 -		}
 -		$writer->renderBeginTag('area');
 -		$writer->renderEndTag();
 -	}
 -}
 -
 -/**
 - * Class TCircleHotSpot.
 - *
 - * TCircleHotSpot defines a circular hot spot region in a {@link TImageMap}
 - * control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCircleHotSpot extends THotSpot
 -{
 -	/**
 -	 * @return string shape of this hotspot.
 -	 */
 -	public function getShape()
 -	{
 -		return 'circle';
 -	}
 -
 -	/**
 -	 * @return string coordinates defining this hotspot shape
 -	 */
 -	public function getCoordinates()
 -	{
 -		return $this->getX().','.$this->getY().','.$this->getRadius();
 -	}
 -
 -	/**
 -	 * @return integer radius of the circular HotSpot region. Defaults to 0.
 -	 */
 -	public function getRadius()
 -	{
 -		return $this->getViewState('Radius',0);
 -	}
 -
 -	/**
 -	 * @param integer radius of the circular HotSpot region.
 -	 */
 -	public function setRadius($value)
 -	{
 -		$this->setViewState('Radius',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return integer the X coordinate of the center of the circular HotSpot region. Defaults to 0.
 -	 */
 -	public function getX()
 -	{
 -		return $this->getViewState('X',0);
 -	}
 -
 -	/**
 -	 * @param integer the X coordinate of the center of the circular HotSpot region.
 -	 */
 -	public function setX($value)
 -	{
 -		$this->setViewState('X',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return integer the Y coordinate of the center of the circular HotSpot region. Defaults to 0.
 -	 */
 -	public function getY()
 -	{
 -		return $this->getViewState('Y',0);
 -	}
 -
 -	/**
 -	 * @param integer the Y coordinate of the center of the circular HotSpot region.
 -	 */
 -	public function setY($value)
 -	{
 -		$this->setViewState('Y',TPropertyValue::ensureInteger($value),0);
 -	}
 -}
 -
 -/**
 - * Class TRectangleHotSpot.
 - *
 - * TRectangleHotSpot defines a rectangle hot spot region in a {@link
 - * TImageMap} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRectangleHotSpot extends THotSpot
 -{
 -	/**
 -	 * @return string shape of this hotspot.
 -	 */
 -	public function getShape()
 -	{
 -		return 'rect';
 -	}
 -
 -	/**
 -	 * @return string coordinates defining this hotspot shape
 -	 */
 -	public function getCoordinates()
 -	{
 -		return $this->getLeft().','.$this->getTop().','.$this->getRight().','.$this->getBottom();
 -	}
 -
 -	/**
 -	 * @return integer the Y coordinate of the bottom side of the rectangle HotSpot region. Defaults to 0.
 -	 */
 -	public function getBottom()
 -	{
 -		return $this->getViewState('Bottom',0);
 -	}
 -
 -	/**
 -	 * @param integer the Y coordinate of the bottom side of the rectangle HotSpot region.
 -	 */
 -	public function setBottom($value)
 -	{
 -		$this->setViewState('Bottom',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0.
 -	 */
 -	public function getLeft()
 -	{
 -		return $this->getViewState('Left',0);
 -	}
 -
 -	/**
 -	 * @param integer the X coordinate of the right side of the rectangle HotSpot region.
 -	 */
 -	public function setLeft($value)
 -	{
 -		$this->setViewState('Left',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0.
 -	 */
 -	public function getRight()
 -	{
 -		return $this->getViewState('Right',0);
 -	}
 -
 -	/**
 -	 * @param integer the X coordinate of the right side of the rectangle HotSpot region.
 -	 */
 -	public function setRight($value)
 -	{
 -		$this->setViewState('Right',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return integer the Y coordinate of the top side of the rectangle HotSpot region. Defaults to 0.
 -	 */
 -	public function getTop()
 -	{
 -		return $this->getViewState('Top',0);
 -	}
 -
 -	/**
 -	 * @param integer the Y coordinate of the top side of the rectangle HotSpot region.
 -	 */
 -	public function setTop($value)
 -	{
 -		$this->setViewState('Top',TPropertyValue::ensureInteger($value),0);
 -	}
 -}
 -
 -/**
 - * Class TPolygonHotSpot.
 - *
 - * TPolygonHotSpot defines a polygon hot spot region in a {@link
 - * TImageMap} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TPolygonHotSpot extends THotSpot
 -{
 -	/**
 -	 * @return string shape of this hotspot.
 -	 */
 -	public function getShape()
 -	{
 -		return 'poly';
 -	}
 -
 -	/**
 -	 * @return string coordinates of the vertices defining the polygon.
 -	 * Coordinates are concatenated together with comma ','. Each pair
 -	 * represents (x,y) of a vertex.
 -	 */
 -	public function getCoordinates()
 -	{
 -		return $this->getViewState('Coordinates','');
 -	}
 -
 -	/**
 -	 * @param string coordinates of the vertices defining the polygon.
 -	 * Coordinates are concatenated together with comma ','. Each pair
 -	 * represents (x,y) of a vertex.
 -	 */
 -	public function setCoordinates($value)
 -	{
 -		$this->setViewState('Coordinates',$value,'');
 -	}
 -}
 -
 -
 -/**
 - * THotSpotMode class.
 - * THotSpotMode defines the enumerable type for the possible hot spot modes.
 - *
 - * The following enumerable values are defined:
 - * - NotSet: the mode is not specified
 - * - Navigate: clicking on the hotspot will redirect the browser to a different page
 - * - PostBack: clicking on the hotspot will cause a postback
 - * - Inactive: the hotspot is inactive (not clickable)
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class THotSpotMode extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const Navigate='Navigate';
 -	const PostBack='PostBack';
 -	const Inactive='Inactive';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TImage class file + */ +Prado::using('System.Web.UI.WebControls.TImage'); + +/** + * TImageMap class + * + * TImageMap represents an image on a page. Hotspot regions can be defined + * within the image. Depending on the {@link setHotSpotMode HotSpotMode}, + * clicking on the hotspots may trigger a postback or navigate to a specified + * URL. The hotspots defined may be accessed via {@link getHotSpots HotSpots}. + * Each hotspot is described as a {@link THotSpot}, which can be a circle, + * rectangle, polygon, etc. To add hotspot in a template, use the following, + * <code> + *  <com:TImageMap> + *    <com:TCircleHotSpot ... /> + *    <com:TRectangleHotSpot ... /> + *    <com:TPolygonHotSpot ... /> + *  </com:TImageMap> + * </code> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TImageMap extends TImage implements IPostBackEventHandler +{ +	const MAP_NAME_PREFIX='ImageMap'; + +	/** +	 * Processes an object that is created during parsing template. +	 * This method adds {@link THotSpot} objects into the hotspot collection +	 * of the imagemap. +	 * @param string|TComponent text string or component parsed and instantiated in template +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof THotSpot) +			$this->getHotSpots()->add($object); +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This overrides the parent implementation with additional imagemap specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		if($this->getHotSpots()->getCount()>0) +		{ +			$writer->addAttribute('usemap','#'.self::MAP_NAME_PREFIX.$this->getClientID()); +			$writer->addAttribute('id',$this->getUniqueID()); +		} +		if($this->getEnabled() && !$this->getEnabled(true)) +			$writer->addAttribute('disabled','disabled'); +	} + +	/** +	 * Renders this imagemap. +	 * @param THtmlWriter +	 */ +	public function render($writer) +	{ +		parent::render($writer); + +		$hotspots=$this->getHotSpots(); + +		if($hotspots->getCount()>0) +		{ +			$clientID=$this->getClientID(); +			$cs=$this->getPage()->getClientScript(); +			$writer->writeLine(); +			$writer->addAttribute('name',self::MAP_NAME_PREFIX.$clientID); +			$writer->renderBeginTag('map'); +			$writer->writeLine(); +			if(($mode=$this->getHotSpotMode())===THotSpotMode::NotSet) +				$mode=THotSpotMode::Navigate; +			$target=$this->getTarget(); +			$i=0; +			$options['EventTarget'] = $this->getUniqueID(); +			$options['StopEvent'] = true; +			$cs=$this->getPage()->getClientScript(); +			foreach($hotspots as $hotspot) +			{ +				if($hotspot->getHotSpotMode()===THotSpotMode::NotSet) +					$hotspot->setHotSpotMode($mode); +				if($target!=='' && $hotspot->getTarget()==='') +					$hotspot->setTarget($target); +				if($hotspot->getHotSpotMode()===THotSpotMode::PostBack) +				{ +					$id=$clientID.'_'.$i; +					$writer->addAttribute('id',$id); +					$writer->addAttribute('href','#'.$id); //create unique no-op url references +					$options['ID']=$id; +					$options['EventParameter']="$i"; +					$options['CausesValidation']=$hotspot->getCausesValidation(); +					$options['ValidationGroup']=$hotspot->getValidationGroup(); +					$cs->registerPostBackControl($this->getClientClassName(),$options); +				} +				$hotspot->render($writer); +				$writer->writeLine(); +				$i++; +			} +			$writer->renderEndTag(); +		} +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TImageMap'; +	} + +	/** +	 * Raises the postback event. +	 * This method is required by {@link IPostBackEventHandler} interface. +	 * This method is mainly used by framework and control developers. +	 * @param TEventParameter the event parameter +	 */ +	public function raisePostBackEvent($param) +	{ +		$postBackValue=null; +		if($param!=='') +		{ +			$index=TPropertyValue::ensureInteger($param); +			$hotspots=$this->getHotSpots(); +			if($index>=0 && $index<$hotspots->getCount()) +			{ +				$hotspot=$hotspots->itemAt($index); +				if(($mode=$hotspot->getHotSpotMode())===THotSpotMode::NotSet) +					$mode=$this->getHotSpotMode(); +				if($mode===THotSpotMode::PostBack) +				{ +					$postBackValue=$hotspot->getPostBackValue(); +					if($hotspot->getCausesValidation()) +						$this->getPage()->validate($hotspot->getValidationGroup()); +				} +			} +		} +		if($postBackValue!==null) +			$this->onClick(new TImageMapEventParameter($postBackValue)); +	} + +	/** +	 * @return THotSpotMode the behavior of hotspot regions in this imagemap when they are clicked. Defaults to THotSpotMode::NotSet. +	 */ +	public function getHotSpotMode() +	{ +		return $this->getViewState('HotSpotMode',THotSpotMode::NotSet); +	} + +	/** +	 * Sets the behavior of hotspot regions in this imagemap when they are clicked. +	 * If an individual hotspot has a mode other than 'NotSet', the mode set in this +	 * imagemap will be ignored. By default, 'NotSet' is equivalent to 'Navigate'. +	 * @param THotSpotMode the behavior of hotspot regions in this imagemap when they are clicked. +	 */ +	public function setHotSpotMode($value) +	{ +		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'THotSpotMode'),THotSpotMode::NotSet); +	} + +	/** +	 * @return THotSpotCollection collection of hotspots defined in this imagemap. +	 */ +	public function getHotSpots() +	{ +		if(($hotspots=$this->getViewState('HotSpots',null))===null) +		{ +			$hotspots=new THotSpotCollection; +			$this->setViewState('HotSpots',$hotspots); +		} +		return $hotspots; +	} + +	/** +	 * @return string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap. Defaults to ''. +	 */ +	public function getTarget() +	{ +		return $this->getViewState('Target',''); +	} + +	/** +	 * @param string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap. +	 */ +	public function setTarget($value) +	{ +		$this->setViewState('Target',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * Raises <b>OnClick</b> event. +	 * This method is invoked when a hotspot region is clicked within the imagemap. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handler can be invoked. +	 * @param TImageMapEventParameter event parameter to be passed to the event handlers +	 */ +	public function onClick($param) +	{ +		$this->raiseEvent('OnClick',$this,$param); +	} +} + +/** + * TImageMapEventParameter class. + * + * TImageMapEventParameter represents a postback event parameter + * when a hotspot is clicked and posts back in a {@link TImageMap}. + * To retrieve the post back value associated with the hotspot being clicked, + * access {@link getPostBackValue PostBackValue}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TImageMapEventParameter extends TEventParameter +{ +	private $_postBackValue; + +	/** +	 * Constructor. +	 * @param string post back value associated with the hotspot clicked +	 */ +	public function __construct($postBackValue) +	{ +		$this->_postBackValue=$postBackValue; +	} + +	/** +	 * @return string post back value associated with the hotspot clicked +	 */ +	public function getPostBackValue() +	{ +		return $this->_postBackValue; +	} +} + +/** + * THotSpotCollection class. + * + * THotSpotCollection represents a collection of hotspots in an imagemap. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class THotSpotCollection extends TList +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by inserting only {@link THotSpot}. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a THotSpot. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof THotSpot) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('hotspotcollection_hotspot_required'); +	} +} + + +/** + * THotSpot class. + * + * THotSpot implements the basic functionality common to all hot spot shapes. + * Derived classes include {@link TCircleHotSpot}, {@link TPolygonHotSpot} + * and {@link TRectangleHotSpot}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class THotSpot extends TComponent +{ +	private $_viewState=array(); + +	/** +	 * Returns a viewstate value. +	 * +	 * This function is very useful in defining getter functions for component properties +	 * that must be kept in viewstate. +	 * @param string the name of the viewstate value to be returned +	 * @param mixed the default value. If $key is not found in viewstate, $defaultValue will be returned +	 * @return mixed the viewstate value corresponding to $key +	 */ +	protected function getViewState($key,$defaultValue=null) +	{ +		return isset($this->_viewState[$key])?$this->_viewState[$key]:$defaultValue; +	} + +	/** +	 * Sets a viewstate value. +	 * +	 * This function is very useful in defining setter functions for control properties +	 * that must be kept in viewstate. +	 * Make sure that the viewstate value must be serializable and unserializable. +	 * @param string the name of the viewstate value +	 * @param mixed the viewstate value to be set +	 * @param mixed default value. If $value===$defaultValue, the item will be cleared from the viewstate. +	 */ +	protected function setViewState($key,$value,$defaultValue=null) +	{ +		if($value===$defaultValue) +			unset($this->_viewState[$key]); +		else +			$this->_viewState[$key]=$value; +	} + +	/** +	 * @return string shape of the hotspot, can be 'circle', 'rect', 'poly', etc. +	 */ +	abstract public function getShape(); +	/** +	 * @return string coordinates defining the hotspot shape. +	 */ +	abstract public function getCoordinates(); + +	/** +	 * @return string the access key that allows you to quickly navigate to the HotSpot region. Defaults to ''. +	 */ +	public function getAccessKey() +	{ +		return $this->getViewState('AccessKey',''); +	} + +	/** +	 * @param string the access key that allows you to quickly navigate to the HotSpot region. +	 */ +	public function setAccessKey($value) +	{ +		$this->setViewState('AccessKey',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string the alternate text to display for a HotSpot object. Defaults to ''. +	 */ +	public function getAlternateText() +	{ +		return $this->getViewState('AlternateText',''); +	} + +	/** +	 * @param string the alternate text to display for a HotSpot object. +	 */ +	public function setAlternateText($value) +	{ +		$this->setViewState('AlternateText',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return THotSpotMode the behavior of a HotSpot object when it is clicked. Defaults to THotSpotMode::NotSet. +	 */ +	public function getHotSpotMode() +	{ +		return $this->getViewState('HotSpotMode',THotSpotMode::NotSet); +	} + +	/** +	 * @param THotSpotMode the behavior of a HotSpot object when it is clicked. +	 */ +	public function setHotSpotMode($value) +	{ +		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'THotSpotMode'),THotSpotMode::NotSet); +	} + +	/** +	 * @return string the URL to navigate to when a HotSpot object is clicked. Defaults to ''. +	 */ +	public function getNavigateUrl() +	{ +		return $this->getViewState('NavigateUrl',''); +	} + +	/** +	 * @param string the URL to navigate to when a HotSpot object is clicked. +	 */ +	public function setNavigateUrl($value) +	{ +		$this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string a value that is post back when the HotSpot is clicked. Defaults to ''. +	 */ +	public function getPostBackValue() +	{ +		return $this->getViewState('PostBackValue',''); +	} + +	/** +	 * @param string a value that is post back when the HotSpot is clicked. +	 */ +	public function setPostBackValue($value) +	{ +		$this->setViewState('PostBackValue',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return integer the tab index of the HotSpot region. Defaults to 0. +	 */ +	public function getTabIndex() +	{ +		return $this->getViewState('TabIndex',0); +	} + +	/** +	 * @param integer the tab index of the HotSpot region. +	 */ +	public function setTabIndex($value) +	{ +		$this->setViewState('TabIndex',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return boolean whether postback event trigger by this hotspot will cause input validation, default is true +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by this hotspot will cause input validation +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the group of validators which the hotspot causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the hotspot causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * @return string  the target window or frame to display the new page when the HotSpot region +	 * is clicked. Defaults to ''. +	 */ +	public function getTarget() +	{ +		return $this->getViewState('Target',''); +	} + +	/** +	 * @param string  the target window or frame to display the new page when the HotSpot region +	 * is clicked. +	 */ +	public function setTarget($value) +	{ +		$this->setViewState('Target',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return boolean whether the hotspot has custom attributes +	 */ +	public function getHasAttributes() +	{ +		if($attributes=$this->getViewState('Attributes',null)) +			return $attributes->getCount()>0; +		else +			return false; +	} + +	/** +	 * Returns the list of custom attributes. +	 * Custom attributes are name-value pairs that may be rendered +	 * as HTML tags' attributes. +	 * @return TAttributeCollection the list of custom attributes +	 */ +	public function getAttributes() +	{ +		if($attributes=$this->getViewState('Attributes',null)) +			return $attributes; +		else +		{ +			$attributes=new TAttributeCollection; +			$this->setViewState('Attributes',$attributes,null); +			return $attributes; +		} +	} + +	/** +	 * @return boolean whether the named attribute exists +	 */ +	public function hasAttribute($name) +	{ +		if($attributes=$this->getViewState('Attributes',null)) +			return $attributes->contains($name); +		else +			return false; +	} + +	/** +	 * @return string attribute value, null if attribute does not exist +	 */ +	public function getAttribute($name) +	{ +		if($attributes=$this->getViewState('Attributes',null)) +			return $attributes->itemAt($name); +		else +			return null; +	} + +	/** +	 * Sets a custom hotspot attribute. +	 * @param string attribute name +	 * @param string value of the attribute +	 */ +	public function setAttribute($name,$value) +	{ +		$this->getAttributes()->add($name,$value); +	} + +	/** +	 * Removes the named attribute. +	 * @param string the name of the attribute to be removed. +	 * @return string attribute value removed, null if attribute does not exist. +	 */ +	public function removeAttribute($name) +	{ +		if($attributes=$this->getViewState('Attributes',null)) +			return $attributes->remove($name); +		else +			return null; +	} + +	/** +	 * Renders this hotspot. +	 * @param THtmlWriter +	 */ +	public function render($writer) +	{ +		$writer->addAttribute('shape',$this->getShape()); +		$writer->addAttribute('coords',$this->getCoordinates()); +		if(($mode=$this->getHotSpotMode())===THotSpotMode::NotSet) +			$mode=THotSpotMode::Navigate; +		if($mode===THotSpotMode::Navigate) +		{ +			$writer->addAttribute('href',$this->getNavigateUrl()); +			if(($target=$this->getTarget())!=='') +				$writer->addAttribute('target',$target); +		} +		else if($mode===THotSpotMode::Inactive) +			$writer->addAttribute('nohref','true'); +		$text=$this->getAlternateText(); +		$writer->addAttribute('title',$text); +		$writer->addAttribute('alt',$text); +		if(($accessKey=$this->getAccessKey())!=='') +			$writer->addAttribute('accesskey',$accessKey); +		if(($tabIndex=$this->getTabIndex())!==0) +			$writer->addAttribute('tabindex',"$tabIndex"); +		if($this->getHasAttributes()) +		{ +			foreach($this->getAttributes() as $name=>$value) +				$writer->addAttribute($name,$value); +		} +		$writer->renderBeginTag('area'); +		$writer->renderEndTag(); +	} +} + +/** + * Class TCircleHotSpot. + * + * TCircleHotSpot defines a circular hot spot region in a {@link TImageMap} + * control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCircleHotSpot extends THotSpot +{ +	/** +	 * @return string shape of this hotspot. +	 */ +	public function getShape() +	{ +		return 'circle'; +	} + +	/** +	 * @return string coordinates defining this hotspot shape +	 */ +	public function getCoordinates() +	{ +		return $this->getX().','.$this->getY().','.$this->getRadius(); +	} + +	/** +	 * @return integer radius of the circular HotSpot region. Defaults to 0. +	 */ +	public function getRadius() +	{ +		return $this->getViewState('Radius',0); +	} + +	/** +	 * @param integer radius of the circular HotSpot region. +	 */ +	public function setRadius($value) +	{ +		$this->setViewState('Radius',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return integer the X coordinate of the center of the circular HotSpot region. Defaults to 0. +	 */ +	public function getX() +	{ +		return $this->getViewState('X',0); +	} + +	/** +	 * @param integer the X coordinate of the center of the circular HotSpot region. +	 */ +	public function setX($value) +	{ +		$this->setViewState('X',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return integer the Y coordinate of the center of the circular HotSpot region. Defaults to 0. +	 */ +	public function getY() +	{ +		return $this->getViewState('Y',0); +	} + +	/** +	 * @param integer the Y coordinate of the center of the circular HotSpot region. +	 */ +	public function setY($value) +	{ +		$this->setViewState('Y',TPropertyValue::ensureInteger($value),0); +	} +} + +/** + * Class TRectangleHotSpot. + * + * TRectangleHotSpot defines a rectangle hot spot region in a {@link + * TImageMap} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRectangleHotSpot extends THotSpot +{ +	/** +	 * @return string shape of this hotspot. +	 */ +	public function getShape() +	{ +		return 'rect'; +	} + +	/** +	 * @return string coordinates defining this hotspot shape +	 */ +	public function getCoordinates() +	{ +		return $this->getLeft().','.$this->getTop().','.$this->getRight().','.$this->getBottom(); +	} + +	/** +	 * @return integer the Y coordinate of the bottom side of the rectangle HotSpot region. Defaults to 0. +	 */ +	public function getBottom() +	{ +		return $this->getViewState('Bottom',0); +	} + +	/** +	 * @param integer the Y coordinate of the bottom side of the rectangle HotSpot region. +	 */ +	public function setBottom($value) +	{ +		$this->setViewState('Bottom',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0. +	 */ +	public function getLeft() +	{ +		return $this->getViewState('Left',0); +	} + +	/** +	 * @param integer the X coordinate of the right side of the rectangle HotSpot region. +	 */ +	public function setLeft($value) +	{ +		$this->setViewState('Left',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0. +	 */ +	public function getRight() +	{ +		return $this->getViewState('Right',0); +	} + +	/** +	 * @param integer the X coordinate of the right side of the rectangle HotSpot region. +	 */ +	public function setRight($value) +	{ +		$this->setViewState('Right',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return integer the Y coordinate of the top side of the rectangle HotSpot region. Defaults to 0. +	 */ +	public function getTop() +	{ +		return $this->getViewState('Top',0); +	} + +	/** +	 * @param integer the Y coordinate of the top side of the rectangle HotSpot region. +	 */ +	public function setTop($value) +	{ +		$this->setViewState('Top',TPropertyValue::ensureInteger($value),0); +	} +} + +/** + * Class TPolygonHotSpot. + * + * TPolygonHotSpot defines a polygon hot spot region in a {@link + * TImageMap} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TPolygonHotSpot extends THotSpot +{ +	/** +	 * @return string shape of this hotspot. +	 */ +	public function getShape() +	{ +		return 'poly'; +	} + +	/** +	 * @return string coordinates of the vertices defining the polygon. +	 * Coordinates are concatenated together with comma ','. Each pair +	 * represents (x,y) of a vertex. +	 */ +	public function getCoordinates() +	{ +		return $this->getViewState('Coordinates',''); +	} + +	/** +	 * @param string coordinates of the vertices defining the polygon. +	 * Coordinates are concatenated together with comma ','. Each pair +	 * represents (x,y) of a vertex. +	 */ +	public function setCoordinates($value) +	{ +		$this->setViewState('Coordinates',$value,''); +	} +} + + +/** + * THotSpotMode class. + * THotSpotMode defines the enumerable type for the possible hot spot modes. + * + * The following enumerable values are defined: + * - NotSet: the mode is not specified + * - Navigate: clicking on the hotspot will redirect the browser to a different page + * - PostBack: clicking on the hotspot will cause a postback + * - Inactive: the hotspot is inactive (not clickable) + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class THotSpotMode extends TEnumerable +{ +	const NotSet='NotSet'; +	const Navigate='Navigate'; +	const PostBack='PostBack'; +	const Inactive='Inactive'; +} + diff --git a/framework/Web/UI/WebControls/TItemDataRenderer.php b/framework/Web/UI/WebControls/TItemDataRenderer.php index 60b34873..80d7f418 100644 --- a/framework/Web/UI/WebControls/TItemDataRenderer.php +++ b/framework/Web/UI/WebControls/TItemDataRenderer.php @@ -1,83 +1,83 @@ -<?php
 -/**
 - * TItemDataRenderer class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TItemDataRenderer class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.2
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TDataBoundControl');
 -Prado::using('System.Web.UI.WebControls.TDataRenderer');
 -
 -/**
 - * TItemDataRenderer class
 - *
 - * TItemDataRenderer is the convient base class for template-based item data renderers.
 - * It implements the {@link IItemDataRenderer} interface, and because
 - * TItemDataRenderer extends from {@link TTemplateControl}, derived child
 - * classes can have templates to define their presentational layout.
 - *
 - * The following properties are provided by TItemDataRenderer:
 - * - {@link getItemIndex ItemIndex}: zero-based index of this renderer in the item list collection.
 - * - {@link getItemType ItemType}: item type of this renderer, such as TListItemType::AlternatingItem
 - * - {@link getData Data}: data associated with this renderer
 -
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.2
 - */
 -abstract class TItemDataRenderer extends TDataRenderer implements IItemDataRenderer
 -{
 -	/**
 -	 * index of the data item in the Items collection of repeater
 -	 */
 -	private $_itemIndex;
 -	/**
 -	 * type of the TRepeaterItem
 -	 * @var TListItemType
 -	 */
 -	private $_itemType;
 -
 -	/**
 -	 * @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);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.2 + */ + +Prado::using('System.Web.UI.WebControls.TDataBoundControl'); +Prado::using('System.Web.UI.WebControls.TDataRenderer'); + +/** + * TItemDataRenderer class + * + * TItemDataRenderer is the convient base class for template-based item data renderers. + * It implements the {@link IItemDataRenderer} interface, and because + * TItemDataRenderer extends from {@link TTemplateControl}, derived child + * classes can have templates to define their presentational layout. + * + * The following properties are provided by TItemDataRenderer: + * - {@link getItemIndex ItemIndex}: zero-based index of this renderer in the item list collection. + * - {@link getItemType ItemType}: item type of this renderer, such as TListItemType::AlternatingItem + * - {@link getData Data}: data associated with this renderer + + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.2 + */ +abstract class TItemDataRenderer extends TDataRenderer implements IItemDataRenderer +{ +	/** +	 * index of the data item in the Items collection of repeater +	 */ +	private $_itemIndex; +	/** +	 * type of the TRepeaterItem +	 * @var TListItemType +	 */ +	private $_itemType; + +	/** +	 * @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); +	} +} + diff --git a/framework/Web/UI/WebControls/TJavascriptLogger.php b/framework/Web/UI/WebControls/TJavascriptLogger.php index e0d695f4..3b430357 100644 --- a/framework/Web/UI/WebControls/TJavascriptLogger.php +++ b/framework/Web/UI/WebControls/TJavascriptLogger.php @@ -1,93 +1,93 @@ -<?php
 -/**
 - * TJavascriptLogger class file.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TJavascriptLogger class.
 - *
 - * Provides logging for client-side javascript. Example: template code
 - * <code><com:TJavascriptLogger /></code>
 - *
 - * Client-side javascript code to log info, error, warn, debug
 - * <code>Logger.warn('A warning');
 - * Logger.info('something happend');
 - * </code>
 - *
 - * To see the logger and console, press ALT-D (or CTRL-D on OS X).
 - * More information on the logger can be found at
 - * http://web.archive.org/web/20060512041505/gleepglop.com/javascripts/logger/
 - *
 - * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TJavascriptLogger extends TWebControl
 -{
 -	private static $_keyCodes = array(
 -		'0'=>48, '1'=>49, '2'=>50, '3'=>51, '4'=>52, '5'=>53, '6'=>54, '7'=>55, '8'=>56, '9'=>57, 
 -		'a'=>65, 'b'=>66, 'c'=>67, 'd'=>68, 'e'=>69, 'f'=>70, 'g'=>71, 'h'=>72,
 -		'i'=>73, 'j'=>74, 'k'=>75, 'l'=>76, 'm'=>77, 'n'=>78, 'o'=>79, 'p'=>80,
 -		'q'=>81, 'r'=>82, 's'=>83, 't'=>84, 'u'=>85, 'v'=>86, 'w'=>87, 'x'=>88, 'y'=>89, 'z'=>90);
 -
 -	/**
 -	 * @return string tag name of the panel
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'div';
 -	}
 -
 -	/**
 -	 * @param string keyboard key for toggling the console, default is J.
 -	 */
 -	public function setToggleKey($value)
 -	{
 -		$this->setViewState('ToggleKey', $value, 'j');
 -	}
 -
 -	/**
 -	 * @return string keyboard key for toggling the console.
 -	 */
 -	public function getToggleKey()
 -	{
 -		return $this->getViewState('ToggleKey', 'j');
 -	}
 -
 -	/**
 -	 * Registers the required logger javascript.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		$key = strtolower($this->getToggleKey());
 -		$code = isset(self::$_keyCodes[$key]) ? self::$_keyCodes[$key] : 74;
 -		$js = "var logConsole; Event.OnLoad(function() { logConsole = new LogConsole($code)}); ";
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerBeginScript($this->getClientID(),$js);
 -		$cs->registerPradoScript('logger');
 -	}
 -
 -	/**
 -	 * Register the required javascript libraries and
 -	 * display some general usage information.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -		$code = strtoupper($this->getToggleKey());
 -		$info = '(<a href="http://web.archive.org/web/20060512041505/gleepglop.com/javascripts/logger/" target="_blank">more info</a>).';
 -		$link = '<a href="javascript:if(logConsole)logConsole.toggle()">toggle the javascript log console.</a>';
 -		$usage = 'Press ALT-'.$code.' (Or CTRL-'.$code.' on OS X) to';
 -		$writer->write("{$usage} {$link} {$info}");
 -	}
 -}
 -
 +<?php +/** + * TJavascriptLogger class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TJavascriptLogger class. + * + * Provides logging for client-side javascript. Example: template code + * <code><com:TJavascriptLogger /></code> + * + * Client-side javascript code to log info, error, warn, debug + * <code>Logger.warn('A warning'); + * Logger.info('something happend'); + * </code> + * + * To see the logger and console, press ALT-D (or CTRL-D on OS X). + * More information on the logger can be found at + * http://web.archive.org/web/20060512041505/gleepglop.com/javascripts/logger/ + * + * @author Wei Zhuo<weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TJavascriptLogger extends TWebControl +{ +	private static $_keyCodes = array( +		'0'=>48, '1'=>49, '2'=>50, '3'=>51, '4'=>52, '5'=>53, '6'=>54, '7'=>55, '8'=>56, '9'=>57,  +		'a'=>65, 'b'=>66, 'c'=>67, 'd'=>68, 'e'=>69, 'f'=>70, 'g'=>71, 'h'=>72, +		'i'=>73, 'j'=>74, 'k'=>75, 'l'=>76, 'm'=>77, 'n'=>78, 'o'=>79, 'p'=>80, +		'q'=>81, 'r'=>82, 's'=>83, 't'=>84, 'u'=>85, 'v'=>86, 'w'=>87, 'x'=>88, 'y'=>89, 'z'=>90); + +	/** +	 * @return string tag name of the panel +	 */ +	protected function getTagName() +	{ +		return 'div'; +	} + +	/** +	 * @param string keyboard key for toggling the console, default is J. +	 */ +	public function setToggleKey($value) +	{ +		$this->setViewState('ToggleKey', $value, 'j'); +	} + +	/** +	 * @return string keyboard key for toggling the console. +	 */ +	public function getToggleKey() +	{ +		return $this->getViewState('ToggleKey', 'j'); +	} + +	/** +	 * Registers the required logger javascript. +	 * @param TEventParameter event parameter +	 */ +	public function onPreRender($param) +	{ +		$key = strtolower($this->getToggleKey()); +		$code = isset(self::$_keyCodes[$key]) ? self::$_keyCodes[$key] : 74; +		$js = "var logConsole; Event.OnLoad(function() { logConsole = new LogConsole($code)}); "; +		$cs = $this->getPage()->getClientScript(); +		$cs->registerBeginScript($this->getClientID(),$js); +		$cs->registerPradoScript('logger'); +	} + +	/** +	 * Register the required javascript libraries and +	 * display some general usage information. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +		$code = strtoupper($this->getToggleKey()); +		$info = '(<a href="http://web.archive.org/web/20060512041505/gleepglop.com/javascripts/logger/" target="_blank">more info</a>).'; +		$link = '<a href="javascript:if(logConsole)logConsole.toggle()">toggle the javascript log console.</a>'; +		$usage = 'Press ALT-'.$code.' (Or CTRL-'.$code.' on OS X) to'; +		$writer->write("{$usage} {$link} {$info}"); +	} +} + diff --git a/framework/Web/UI/WebControls/TKeyboard.php b/framework/Web/UI/WebControls/TKeyboard.php index 27cb55c5..58c80e26 100644 --- a/framework/Web/UI/WebControls/TKeyboard.php +++ b/framework/Web/UI/WebControls/TKeyboard.php @@ -1,189 +1,189 @@ -<?php
 -/**
 - * TKeyboard class file.
 - *
 - * @author Sergey Morkovkin <sergeymorkovkin@mail.ru> and Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -
 -/**
 - * Class TKeyboard.
 - *
 - * TKeyboard displays a virtual keyboard that users can click on to enter input in
 - * an associated text box. It helps to reduce the keyboard recording hacking.
 - *
 - * To use TKeyboard, write a template like following:
 - * <code>
 - * <com:TTextBox ID="PasswordInput" />
 - * <com:TKeyboard ForControl="PasswordInput" />
 - * </code>
 - *
 - * A TKeyboard control is associated with a {@link TTextBox} control by specifying {@link setForControl ForControl}
 - * to be the ID of that control. When the textbox is in focus, a virtual keyboard will pop up; and when
 - * the text box is losing focus, the keyboard will hide automatically. Set {@link setAutoHide AutoHide} to
 - * false to keep the keyboard showing all the time.
 - *
 - * The appearance of the keyboard can also be changed by specifying a customized CSS file via
 - * {@link setCssUrl CssUrl}. By default, the CSS class name for the keyboard is 'Keyboard'. This may
 - * also be changed by specifying {@link setKeyboardCssClass KeyboardCssClass}.
 - *
 - * @author Sergey Morkovkin <sergeymorkovkin@mail.ru> and Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TKeyboard extends TWebControl
 -{
 -	/**
 -	 * @return string the ID path of the {@link TTextBox} control
 -	 */
 -	public function getForControl()
 -	{
 -		return $this->getViewState('ForControl','');
 -	}
 -
 -	/**
 -	 * Sets the ID path of the {@link TTextBox} control.
 -	 * The ID path is the dot-connected IDs of the controls reaching from
 -	 * the keyboard's naming container to the target control.
 -	 * @param string the ID path
 -	 */
 -	public function setForControl($value)
 -	{
 -		$this->setViewState('ForControl', TPropertyValue::ensureString($value));
 -	}
 -
 -	/**
 -	 * @return boolean whether the keyboard should be hidden when the textbox is not in focus. Defaults to true.
 -	 */
 -	public function getAutoHide()
 -	{
 -		return $this->getViewState('AutoHide', true);
 -	}
 -
 -	/**
 -	 * @param boolean whether the keyboard should be hidden when the textbox is not in focus.
 -	 */
 -	public function setAutoHide($value)
 -	{
 -		$this->setViewState('AutoHide', TPropertyValue::ensureBoolean($value), true);
 -	}
 -
 -	/**
 -	 * @return string the CSS class name for the keyboard <div> element. Defaults to 'Keyboard'.
 -	 */
 -	public function getKeyboardCssClass()
 -	{
 -		return $this->getViewState('KeyboardCssClass', 'Keyboard');
 -	}
 -
 -	/**
 -	 * Sets a value indicating the CSS class name for the keyboard <div> element.
 -	 * Note, if you change this property, make sure you also supply a customized CSS file
 -	 * by specifying {@link setCssUrl CssUrl} which uses the new CSS class name for styling.
 -	 * @param string the CSS class name for the keyboard <div> element.
 -	 */
 -	public function setKeyboardCssClass($value)
 -	{
 -		$this->setViewState('KeyboardCssClass', $value, 'Keyboard');
 -	}
 -
 -	/**
 -	 * @return string the URL for the CSS file to customize the appearance of the keyboard.
 -	 */
 -	public function getCssUrl()
 -	{
 -		return $this->getViewState('CssUrl', '');
 -	}
 -
 -	/**
 -	 * @param string the URL for the CSS file to customize the appearance of the keyboard.
 -	 */
 -	public function setCssUrl($value)
 -	{
 -		$this->setViewState('CssUrl', $value, '');
 -	}
 -
 -	/**
 -	 * Registers CSS and JS.
 -	 * This method is invoked right before the control rendering, if the control is visible.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		if($this->getPage()->getClientSupportsJavaScript())
 -		{
 -			$this->registerStyleSheet();
 -			$this->registerClientScript();
 -		}
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This method overrides the parent implementation with additional TKeyboard specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		if($this->getPage()->getClientSupportsJavaScript())
 -			$writer->addAttribute('id',$this->getClientID());
 -	}
 -
 -	/**
 -	 * Registers the CSS relevant to the TKeyboard.
 -	 * It will register the CSS file specified by {@link getCssUrl CssUrl}.
 -	 * If that is not set, it will use the default CSS.
 -	 */
 -	protected function registerStyleSheet()
 -	{
 -		if(($url=$this->getCssUrl())==='')
 -			$url=$this->getApplication()->getAssetManager()->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'keyboard.css');
 -		$this->getPage()->getClientScript()->registerStyleSheetFile($url,$url);
 -	}
 -
 -	/**
 -	 * Registers the relevant JavaScript.
 -	 */
 -	protected function registerClientScript()
 -	{
 -		$options=TJavaScript::encode($this->getClientOptions());
 -		$className=$this->getClientClassName();
 -		$cs=$this->getPage()->getClientScript();
 -		$cs->registerPradoScript('keyboard');
 -		$cs->registerEndScript('prado:'.$this->getClientID(), "new $className($options);");
 -	}
 -
 -	/**
 -	 * @return string the Javascript class name for this control
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TKeyboard';
 -	}
 -
 -	/**
 -	 * @return array the JavaScript options for this control
 -	 */
 -	protected function getClientOptions()
 -	{
 -		if(($forControl=$this->getForControl())==='')
 -			throw new TConfigurationException('keyboard_forcontrol_required');
 -	    if(($target=$this->findControl($forControl))===null)
 -	        throw new TConfigurationException('keyboard_forcontrol_invalid',$forControl);
 -
 -	    $options['ID'] = $this->getClientID();
 -	    $options['ForControl'] = $target->getClientID();
 -	    $options['AutoHide'] = $this->getAutoHide();
 -	    $options['CssClass'] = $this->getKeyboardCssClass();
 -
 -	    return $options;
 -	}
 -}
 -
 +<?php +/** + * TKeyboard class file. + * + * @author Sergey Morkovkin <sergeymorkovkin@mail.ru> and Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ + +/** + * Class TKeyboard. + * + * TKeyboard displays a virtual keyboard that users can click on to enter input in + * an associated text box. It helps to reduce the keyboard recording hacking. + * + * To use TKeyboard, write a template like following: + * <code> + * <com:TTextBox ID="PasswordInput" /> + * <com:TKeyboard ForControl="PasswordInput" /> + * </code> + * + * A TKeyboard control is associated with a {@link TTextBox} control by specifying {@link setForControl ForControl} + * to be the ID of that control. When the textbox is in focus, a virtual keyboard will pop up; and when + * the text box is losing focus, the keyboard will hide automatically. Set {@link setAutoHide AutoHide} to + * false to keep the keyboard showing all the time. + * + * The appearance of the keyboard can also be changed by specifying a customized CSS file via + * {@link setCssUrl CssUrl}. By default, the CSS class name for the keyboard is 'Keyboard'. This may + * also be changed by specifying {@link setKeyboardCssClass KeyboardCssClass}. + * + * @author Sergey Morkovkin <sergeymorkovkin@mail.ru> and Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TKeyboard extends TWebControl +{ +	/** +	 * @return string the ID path of the {@link TTextBox} control +	 */ +	public function getForControl() +	{ +		return $this->getViewState('ForControl',''); +	} + +	/** +	 * Sets the ID path of the {@link TTextBox} control. +	 * The ID path is the dot-connected IDs of the controls reaching from +	 * the keyboard's naming container to the target control. +	 * @param string the ID path +	 */ +	public function setForControl($value) +	{ +		$this->setViewState('ForControl', TPropertyValue::ensureString($value)); +	} + +	/** +	 * @return boolean whether the keyboard should be hidden when the textbox is not in focus. Defaults to true. +	 */ +	public function getAutoHide() +	{ +		return $this->getViewState('AutoHide', true); +	} + +	/** +	 * @param boolean whether the keyboard should be hidden when the textbox is not in focus. +	 */ +	public function setAutoHide($value) +	{ +		$this->setViewState('AutoHide', TPropertyValue::ensureBoolean($value), true); +	} + +	/** +	 * @return string the CSS class name for the keyboard <div> element. Defaults to 'Keyboard'. +	 */ +	public function getKeyboardCssClass() +	{ +		return $this->getViewState('KeyboardCssClass', 'Keyboard'); +	} + +	/** +	 * Sets a value indicating the CSS class name for the keyboard <div> element. +	 * Note, if you change this property, make sure you also supply a customized CSS file +	 * by specifying {@link setCssUrl CssUrl} which uses the new CSS class name for styling. +	 * @param string the CSS class name for the keyboard <div> element. +	 */ +	public function setKeyboardCssClass($value) +	{ +		$this->setViewState('KeyboardCssClass', $value, 'Keyboard'); +	} + +	/** +	 * @return string the URL for the CSS file to customize the appearance of the keyboard. +	 */ +	public function getCssUrl() +	{ +		return $this->getViewState('CssUrl', ''); +	} + +	/** +	 * @param string the URL for the CSS file to customize the appearance of the keyboard. +	 */ +	public function setCssUrl($value) +	{ +		$this->setViewState('CssUrl', $value, ''); +	} + +	/** +	 * Registers CSS and JS. +	 * This method is invoked right before the control rendering, if the control is visible. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		if($this->getPage()->getClientSupportsJavaScript()) +		{ +			$this->registerStyleSheet(); +			$this->registerClientScript(); +		} +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This method overrides the parent implementation with additional TKeyboard specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		if($this->getPage()->getClientSupportsJavaScript()) +			$writer->addAttribute('id',$this->getClientID()); +	} + +	/** +	 * Registers the CSS relevant to the TKeyboard. +	 * It will register the CSS file specified by {@link getCssUrl CssUrl}. +	 * If that is not set, it will use the default CSS. +	 */ +	protected function registerStyleSheet() +	{ +		if(($url=$this->getCssUrl())==='') +			$url=$this->getApplication()->getAssetManager()->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'keyboard.css'); +		$this->getPage()->getClientScript()->registerStyleSheetFile($url,$url); +	} + +	/** +	 * Registers the relevant JavaScript. +	 */ +	protected function registerClientScript() +	{ +		$options=TJavaScript::encode($this->getClientOptions()); +		$className=$this->getClientClassName(); +		$cs=$this->getPage()->getClientScript(); +		$cs->registerPradoScript('keyboard'); +		$cs->registerEndScript('prado:'.$this->getClientID(), "new $className($options);"); +	} + +	/** +	 * @return string the Javascript class name for this control +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TKeyboard'; +	} + +	/** +	 * @return array the JavaScript options for this control +	 */ +	protected function getClientOptions() +	{ +		if(($forControl=$this->getForControl())==='') +			throw new TConfigurationException('keyboard_forcontrol_required'); +	    if(($target=$this->findControl($forControl))===null) +	        throw new TConfigurationException('keyboard_forcontrol_invalid',$forControl); + +	    $options['ID'] = $this->getClientID(); +	    $options['ForControl'] = $target->getClientID(); +	    $options['AutoHide'] = $this->getAutoHide(); +	    $options['CssClass'] = $this->getKeyboardCssClass(); + +	    return $options; +	} +} + diff --git a/framework/Web/UI/WebControls/TLabel.php b/framework/Web/UI/WebControls/TLabel.php index 31e424e5..7228d588 100644 --- a/framework/Web/UI/WebControls/TLabel.php +++ b/framework/Web/UI/WebControls/TLabel.php @@ -1,154 +1,154 @@ -<?php
 -/**
 - * TLabel class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TLabel class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TLabel class
 - *
 - * TLabel displays a piece of text on a Web page.
 - * Use {@link setText Text} property to set the text to be displayed.
 - * TLabel will render the contents enclosed within its component tag
 - * if {@link setText Text} is empty.
 - * To use TLabel as a form label, associate it with a control by setting the
 - * {@link setForControl ForControl} property.
 - * The associated control must be locatable within the label's naming container.
 - * If the associated control is not visible, the label will not be rendered, either.
 - *
 - * Note, {@link setText Text} will NOT be encoded for rendering.
 - * Make sure it does not contain dangerous characters that you want to avoid.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TLabel extends TWebControl implements IDataRenderer
 -{
 -	private $_forControl='';
 -
 -	/**
 -	 * @return string tag name of the label, returns 'label' if there is an associated control, 'span' otherwise.
 -	 */
 -	protected function getTagName()
 -	{
 -		return ($this->getForControl()==='')?'span':'label';
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 * @throws TInvalidDataValueException if associated control cannot be found using the ID
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		if($this->_forControl!=='')
 -			$writer->addAttribute('for',$this->_forControl);
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the label.
 -	 * It overrides the parent implementation by checking if an associated
 -	 * control is visible or not. If not, the label will not be rendered.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function render($writer)
 -	{
 -		if(($aid=$this->getForControl())!=='')
 -		{
 -			if($control=$this->findControl($aid))
 -			{
 -				if($control->getVisible(true))
 -				{
 -					$this->_forControl=$control->getClientID();
 -					parent::render($writer);
 -				}
 -			}
 -			else
 -				throw new TInvalidDataValueException('label_associatedcontrol_invalid',$aid);
 -		}
 -		else
 -			parent::render($writer);
 -	}
 -
 -	/**
 -	 * Renders the body content of the label.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if(($text=$this->getText())==='')
 -			parent::renderContents($writer);
 -		else
 -			$writer->write($text);
 -	}
 -
 -	/**
 -	 * @return string the text value of the label
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * @param string the text value of the label
 -	 */
 -	public function setText($value)
 -	{
 -		$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
 -	 */
 -	public function getForControl()
 -	{
 -		return $this->getViewState('ForControl','');
 -	}
 -
 -	/**
 -	 * Sets the ID of the control that the label is associated with.
 -	 * The control must be locatable via {@link TControl::findControl} using the ID.
 -	 * @param string the associated control ID
 -	 */
 -	public function setForControl($value)
 -	{
 -		$this->setViewState('ForControl',$value,'');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TLabel class + * + * TLabel displays a piece of text on a Web page. + * Use {@link setText Text} property to set the text to be displayed. + * TLabel will render the contents enclosed within its component tag + * if {@link setText Text} is empty. + * To use TLabel as a form label, associate it with a control by setting the + * {@link setForControl ForControl} property. + * The associated control must be locatable within the label's naming container. + * If the associated control is not visible, the label will not be rendered, either. + * + * Note, {@link setText Text} will NOT be encoded for rendering. + * Make sure it does not contain dangerous characters that you want to avoid. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TLabel extends TWebControl implements IDataRenderer +{ +	private $_forControl=''; + +	/** +	 * @return string tag name of the label, returns 'label' if there is an associated control, 'span' otherwise. +	 */ +	protected function getTagName() +	{ +		return ($this->getForControl()==='')?'span':'label'; +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 * @throws TInvalidDataValueException if associated control cannot be found using the ID +	 */ +	protected function addAttributesToRender($writer) +	{ +		if($this->_forControl!=='') +			$writer->addAttribute('for',$this->_forControl); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Renders the label. +	 * It overrides the parent implementation by checking if an associated +	 * control is visible or not. If not, the label will not be rendered. +	 * @param THtmlWriter writer +	 */ +	public function render($writer) +	{ +		if(($aid=$this->getForControl())!=='') +		{ +			if($control=$this->findControl($aid)) +			{ +				if($control->getVisible(true)) +				{ +					$this->_forControl=$control->getClientID(); +					parent::render($writer); +				} +			} +			else +				throw new TInvalidDataValueException('label_associatedcontrol_invalid',$aid); +		} +		else +			parent::render($writer); +	} + +	/** +	 * Renders the body content of the label. +	 * @param THtmlWriter the renderer +	 */ +	public function renderContents($writer) +	{ +		if(($text=$this->getText())==='') +			parent::renderContents($writer); +		else +			$writer->write($text); +	} + +	/** +	 * @return string the text value of the label +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * @param string the text value of the label +	 */ +	public function setText($value) +	{ +		$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 +	 */ +	public function getForControl() +	{ +		return $this->getViewState('ForControl',''); +	} + +	/** +	 * Sets the ID of the control that the label is associated with. +	 * The control must be locatable via {@link TControl::findControl} using the ID. +	 * @param string the associated control ID +	 */ +	public function setForControl($value) +	{ +		$this->setViewState('ForControl',$value,''); +	} +} + diff --git a/framework/Web/UI/WebControls/TLinkButton.php b/framework/Web/UI/WebControls/TLinkButton.php index 9da5ec59..f03f9098 100644 --- a/framework/Web/UI/WebControls/TLinkButton.php +++ b/framework/Web/UI/WebControls/TLinkButton.php @@ -1,334 +1,334 @@ -<?php
 -/**
 - * TLinkButton class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TLinkButton class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TLinkButton class
 - *
 - * TLinkButton creates a hyperlink style button on the page.
 - * TLinkButton has the same appearance as a hyperlink. However, it is mainly
 - * used to submit data to a page. Like {@link TButton}, you can create either
 - * a <b>submit</b> button or a <b>command</b> button.
 - *
 - * A <b>command</b> button has a command name (specified by
 - * the {@link setCommandName CommandName} property) and and a command parameter
 - * (specified by {@link setCommandParameter CommandParameter} property)
 - * associated with the button. This allows you to create multiple TLinkButton
 - * components on a Web page and programmatically determine which one is clicked
 - * with what parameter. You can provide an event handler for
 - * {@link onCommand OnCommand} event to programmatically control the actions performed
 - * when the command button is clicked. In the event handler, you can determine
 - * the {@link setCommandName CommandName} property value and
 - * the {@link setCommandParameter CommandParameter} property value
 - * through the {@link TCommandParameter::getName Name} and
 - * {@link TCommandParameter::getParameter Parameter} properties of the event
 - * parameter which is of type {@link TCommandEventParameter}.
 - *
 - * A <b>submit</b> button does not have a command name associated with the button
 - * and clicking on it simply posts the Web page back to the server.
 - * By default, a TLinkButton component is a submit button.
 - * You can provide an event handler for the {@link onClick OnClick} event
 - * to programmatically control the actions performed when the submit button is clicked.
 - *
 - * Clicking on button can trigger form validation, if
 - * {@link setCausesValidation CausesValidation} is true.
 - * And the validation may be restricted within a certain group of validator
 - * controls by setting {@link setValidationGroup ValidationGroup} property.
 - * If validation is successful, the data will be post back to the same page.
 - *
 - * TLinkButton will display the {@link setText Text} property value
 - * as the hyperlink text. If {@link setText Text} is empty, the body content
 - * of TLinkButton will be displayed. Therefore, you can use TLinkButton
 - * as an image button by enclosing an <img> tag as the body of TLinkButton.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer
 -{
 -	/**
 -	 * @return string tag name of the button
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'a';
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This overrides the parent implementation with additional button specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$page=$this->getPage();
 -		$page->ensureRenderInForm($this);
 -
 -		$writer->addAttribute('id',$this->getClientID());
 -
 -		// We call parent implementation here because some attributes
 -		// may be overwritten in the following
 -		parent::addAttributesToRender($writer);
 -
 -		if($this->getEnabled(true) && $this->getEnableClientScript())
 -		{
 -			$this->renderLinkButtonHref($writer);
 -			$this->renderClientControlScript($writer);
 -		}
 -		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
 -			$writer->addAttribute('disabled','disabled');
 -	}
 -
 -	/**
 -	 * Renders the client-script code.
 -	 * @param THtmlWriter renderer
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * @param boolean set by a panel to register this button as the default button for the panel.
 -	 */
 -	public function setIsDefaultButton($value)
 -	{
 -		$this->setViewState('IsDefaultButton', TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean true if this button is registered as a default button for a panel.
 -	 */
 -	public function getIsDefaultButton()
 -	{
 -		return $this->getViewState('IsDefaultButton', false);
 -	}
 -
 -	/**
 -	 * Renders the Href for link button.
 -	 * @param THtmlWriter renderer
 -	 */
 -	protected function renderLinkButtonHref($writer)
 -	{
 -		//create unique no-op url references
 -		$nop = "javascript:;//".$this->getClientID();
 -		$writer->addAttribute('href', $nop);
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TLinkButton';
 -	}
 -
 -	/**
 -	 * Returns postback specifications for the button.
 -	 * This method is used by framework and control developers.
 -	 * @return array parameters about how the button defines its postback behavior.
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['StopEvent'] = true;
 -
 -		return $options;
 -	}
 -
 -	/**
 -	 * Renders the body content enclosed between the control tag.
 -	 * If {@link getText Text} is not empty, it will be rendered. Otherwise,
 -	 * the body content enclosed in the control tag will be rendered.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if(($text=$this->getText())==='')
 -			parent::renderContents($writer);
 -		else
 -			$writer->write($text);
 -	}
 -
 -	/**
 -	 * @return string the text caption of the button
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * @param string the text caption to be set
 -	 */
 -	public function setText($value)
 -	{
 -		$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.
 -	 */
 -	public function getCommandName()
 -	{
 -		return $this->getViewState('CommandName','');
 -	}
 -
 -	/**
 -	 * @param string the command name associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function setCommandName($value)
 -	{
 -		$this->setViewState('CommandName',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the parameter associated with the {@link onCommand OnCommand} event
 -	 */
 -	public function getCommandParameter()
 -	{
 -		return $this->getViewState('CommandParameter','');
 -	}
 -
 -	/**
 -	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
 -	 */
 -	public function setCommandParameter($value)
 -	{
 -		$this->setViewState('CommandParameter',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by this button will cause input validation
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * Sets the value indicating whether postback event trigger by this button will cause input validation.
 -	 * @param string the text caption to be set
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the button causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the button causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * Raises the postback event.
 -	 * This method is required by {@link IPostBackEventHandler} interface.
 -	 * If {@link getCausesValidation CausesValidation} is true, it will
 -	 * invoke the page's {@link TPage::validate validate} method first.
 -	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
 -	 * This method is mainly used by framework and control developers.
 -	 * @param TEventParameter the event parameter
 -	 */
 -	public function raisePostBackEvent($param)
 -	{
 -		if($this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onClick(null);
 -		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
 -	}
 -
 -	/**
 -	 * This method is invoked when the button is clicked.
 -	 * The method raises 'OnClick' event to fire up the event handlers.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handler can be invoked.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onClick($param)
 -	{
 -		$this->raiseEvent('OnClick',$this,$param);
 -	}
 -
 -	/**
 -	 * This method is invoked when the button is clicked.
 -	 * The method raises 'OnCommand' event to fire up the event handlers.
 -	 * If you override this method, be sure to call the parent implementation
 -	 * so that the event handlers can be invoked.
 -	 * @param TCommandEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onCommand($param)
 -	{
 -		$this->raiseEvent('OnCommand',$this,$param);
 -		$this->raiseBubbleEvent($this,$param);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TLinkButton class + * + * TLinkButton creates a hyperlink style button on the page. + * TLinkButton has the same appearance as a hyperlink. However, it is mainly + * used to submit data to a page. Like {@link TButton}, you can create either + * a <b>submit</b> button or a <b>command</b> button. + * + * A <b>command</b> button has a command name (specified by + * the {@link setCommandName CommandName} property) and and a command parameter + * (specified by {@link setCommandParameter CommandParameter} property) + * associated with the button. This allows you to create multiple TLinkButton + * components on a Web page and programmatically determine which one is clicked + * with what parameter. You can provide an event handler for + * {@link onCommand OnCommand} event to programmatically control the actions performed + * when the command button is clicked. In the event handler, you can determine + * the {@link setCommandName CommandName} property value and + * the {@link setCommandParameter CommandParameter} property value + * through the {@link TCommandParameter::getName Name} and + * {@link TCommandParameter::getParameter Parameter} properties of the event + * parameter which is of type {@link TCommandEventParameter}. + * + * A <b>submit</b> button does not have a command name associated with the button + * and clicking on it simply posts the Web page back to the server. + * By default, a TLinkButton component is a submit button. + * You can provide an event handler for the {@link onClick OnClick} event + * to programmatically control the actions performed when the submit button is clicked. + * + * Clicking on button can trigger form validation, if + * {@link setCausesValidation CausesValidation} is true. + * And the validation may be restricted within a certain group of validator + * controls by setting {@link setValidationGroup ValidationGroup} property. + * If validation is successful, the data will be post back to the same page. + * + * TLinkButton will display the {@link setText Text} property value + * as the hyperlink text. If {@link setText Text} is empty, the body content + * of TLinkButton will be displayed. Therefore, you can use TLinkButton + * as an image button by enclosing an <img> tag as the body of TLinkButton. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl, IDataRenderer +{ +	/** +	 * @return string tag name of the button +	 */ +	protected function getTagName() +	{ +		return 'a'; +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This overrides the parent implementation with additional button specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$page=$this->getPage(); +		$page->ensureRenderInForm($this); + +		$writer->addAttribute('id',$this->getClientID()); + +		// We call parent implementation here because some attributes +		// may be overwritten in the following +		parent::addAttributesToRender($writer); + +		if($this->getEnabled(true) && $this->getEnableClientScript()) +		{ +			$this->renderLinkButtonHref($writer); +			$this->renderClientControlScript($writer); +		} +		else if($this->getEnabled()) // in this case, parent will not render 'disabled' +			$writer->addAttribute('disabled','disabled'); +	} + +	/** +	 * Renders the client-script code. +	 * @param THtmlWriter renderer +	 */ +	protected function renderClientControlScript($writer) +	{ +		$cs = $this->getPage()->getClientScript(); +		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * @param boolean set by a panel to register this button as the default button for the panel. +	 */ +	public function setIsDefaultButton($value) +	{ +		$this->setViewState('IsDefaultButton', TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean true if this button is registered as a default button for a panel. +	 */ +	public function getIsDefaultButton() +	{ +		return $this->getViewState('IsDefaultButton', false); +	} + +	/** +	 * Renders the Href for link button. +	 * @param THtmlWriter renderer +	 */ +	protected function renderLinkButtonHref($writer) +	{ +		//create unique no-op url references +		$nop = "javascript:;//".$this->getClientID(); +		$writer->addAttribute('href', $nop); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TLinkButton'; +	} + +	/** +	 * Returns postback specifications for the button. +	 * This method is used by framework and control developers. +	 * @return array parameters about how the button defines its postback behavior. +	 */ +	protected function getPostBackOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['EventTarget'] = $this->getUniqueID(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['StopEvent'] = true; + +		return $options; +	} + +	/** +	 * Renders the body content enclosed between the control tag. +	 * If {@link getText Text} is not empty, it will be rendered. Otherwise, +	 * the body content enclosed in the control tag will be rendered. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +		if(($text=$this->getText())==='') +			parent::renderContents($writer); +		else +			$writer->write($text); +	} + +	/** +	 * @return string the text caption of the button +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * @param string the text caption to be set +	 */ +	public function setText($value) +	{ +		$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. +	 */ +	public function getCommandName() +	{ +		return $this->getViewState('CommandName',''); +	} + +	/** +	 * @param string the command name associated with the {@link onCommand OnCommand} event. +	 */ +	public function setCommandName($value) +	{ +		$this->setViewState('CommandName',$value,''); +	} + +	/** +	 * @return string the parameter associated with the {@link onCommand OnCommand} event +	 */ +	public function getCommandParameter() +	{ +		return $this->getViewState('CommandParameter',''); +	} + +	/** +	 * @param string the parameter associated with the {@link onCommand OnCommand} event. +	 */ +	public function setCommandParameter($value) +	{ +		$this->setViewState('CommandParameter',$value,''); +	} + +	/** +	 * @return boolean whether postback event trigger by this button will cause input validation +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * Sets the value indicating whether postback event trigger by this button will cause input validation. +	 * @param string the text caption to be set +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the group of validators which the button causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the button causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * Raises the postback event. +	 * This method is required by {@link IPostBackEventHandler} interface. +	 * If {@link getCausesValidation CausesValidation} is true, it will +	 * invoke the page's {@link TPage::validate validate} method first. +	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events. +	 * This method is mainly used by framework and control developers. +	 * @param TEventParameter the event parameter +	 */ +	public function raisePostBackEvent($param) +	{ +		if($this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onClick(null); +		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter())); +	} + +	/** +	 * This method is invoked when the button is clicked. +	 * The method raises 'OnClick' event to fire up the event handlers. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handler can be invoked. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onClick($param) +	{ +		$this->raiseEvent('OnClick',$this,$param); +	} + +	/** +	 * This method is invoked when the button is clicked. +	 * The method raises 'OnCommand' event to fire up the event handlers. +	 * If you override this method, be sure to call the parent implementation +	 * so that the event handlers can be invoked. +	 * @param TCommandEventParameter event parameter to be passed to the event handlers +	 */ +	public function onCommand($param) +	{ +		$this->raiseEvent('OnCommand',$this,$param); +		$this->raiseBubbleEvent($this,$param); +	} +} + diff --git a/framework/Web/UI/WebControls/TListBox.php b/framework/Web/UI/WebControls/TListBox.php index 8e996b6e..f7ab4791 100644 --- a/framework/Web/UI/WebControls/TListBox.php +++ b/framework/Web/UI/WebControls/TListBox.php @@ -1,226 +1,226 @@ -<?php
 -/**
 - * TListBox class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TListBox class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TListControl class
 - */
 -Prado::using('System.Web.UI.WebControls.TListControl');
 -
 -/**
 - * TListBox class
 - *
 - * TListBox displays a list box on a Web page that allows single or multiple selection.
 - * The list box allows multiple selections if {@link setSelectionMode SelectionMode}
 - * is TListSelectionMode::Multiple. It takes single selection only if Single.
 - * The property {@link setRows Rows} specifies how many rows of options are visible
 - * at a time. See {@link TListControl} for inherited properties.
 - *
 - * Since v3.0.3, TListBox starts to support optgroup. To specify an option group for
 - * a list item, set a Group attribute with it,
 - * <code>
 - *  $listitem->Attributes->Group="Group Name";
 - *  // or <com:TListItem Attributes.Group="Group Name" .../> in template
 - * </code>
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TListBox extends TListControl implements IPostBackDataHandler, IValidatable
 -{
 -	private $_dataChanged=false;
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TListControl class + */ +Prado::using('System.Web.UI.WebControls.TListControl'); + +/** + * TListBox class + * + * TListBox displays a list box on a Web page that allows single or multiple selection. + * The list box allows multiple selections if {@link setSelectionMode SelectionMode} + * is TListSelectionMode::Multiple. It takes single selection only if Single. + * The property {@link setRows Rows} specifies how many rows of options are visible + * at a time. See {@link TListControl} for inherited properties. + * + * Since v3.0.3, TListBox starts to support optgroup. To specify an option group for + * a list item, set a Group attribute with it, + * <code> + *  $listitem->Attributes->Group="Group Name"; + *  // or <com:TListItem Attributes.Group="Group Name" .../> in template + * </code> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TListBox extends TListControl implements IPostBackDataHandler, IValidatable +{ +	private $_dataChanged=false;  	private $_isValid=true; -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This method overrides the parent implementation with additional list box specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$rows=$this->getRows();
 -		$writer->addAttribute('size',"$rows");
 -		if($this->getSelectionMode()===TListSelectionMode::Multiple)
 -			$writer->addAttribute('name',$this->getUniqueID().'[]');
 -		else
 -			$writer->addAttribute('name',$this->getUniqueID());
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TListBox';
 -	}
 -
 -	/**
 -	 * Registers the list control to load post data on postback.
 -	 * This method overrides the parent implementation.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -		if($this->getEnabled(true))
 -			$this->getPage()->registerRequiresPostData($this);
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		if(!$this->getEnabled(true))
 -			return false;
 -		$this->ensureDataBound();
 -		$selections=isset($values[$key])?$values[$key]:null;
 -		if($selections!==null)
 -		{
 -			$items=$this->getItems();
 -			if($this->getSelectionMode()===TListSelectionMode::Single)
 -			{
 -				$selection=is_array($selections)?$selections[0]:$selections;
 -				$index=$items->findIndexByValue($selection,false);
 -				if($this->getSelectedIndex()!==$index)
 -				{
 -					$this->setSelectedIndex($index);
 -					return $this->_dataChanged=true;
 -				}
 -				else
 -					return false;
 -			}
 -			if(!is_array($selections))
 -				$selections=array($selections);
 -			$list=array();
 -			foreach($selections as $selection)
 -				$list[]=$items->findIndexByValue($selection,false);
 -			$list2=$this->getSelectedIndices();
 -			$n=count($list);
 -			$flag=false;
 -			if($n===count($list2))
 -			{
 -				sort($list,SORT_NUMERIC);
 -				for($i=0;$i<$n;++$i)
 -				{
 -					if($list[$i]!==$list2[$i])
 -					{
 -						$flag=true;
 -						break;
 -					}
 -				}
 -			}
 -			else
 -				$flag=true;
 -			if($flag)
 -			{
 -				$this->setSelectedIndices($list);
 -				$this->_dataChanged=true;
 -			}
 -			return $flag;
 -		}
 -		else if($this->getSelectedIndex()!==-1)
 -		{
 -			$this->clearSelection();
 -			return $this->_dataChanged=true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method is required by {@link IPostBackDataHandler} interface.
 -	 * It is invoked by the framework when {@link getSelectedIndices SelectedIndices} property
 -	 * is changed on postback.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		if($this->getAutoPostBack() && $this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onSelectedIndexChanged(null);
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * @return boolean whether this control allows multiple selection
 -	 */
 -	protected function getIsMultiSelect()
 -	{
 -		return $this->getSelectionMode()===TListSelectionMode::Multiple;
 -	}
 -
 -	/**
 -	 * @return integer the number of rows to be displayed in the list control
 -	 */
 -	public function getRows()
 -	{
 -		return $this->getViewState('Rows', 4);
 -	}
 -
 -	/**
 -	 * @param integer the number of rows to be displayed in the list control
 -	 */
 -	public function setRows($value)
 -	{
 -		$value=TPropertyValue::ensureInteger($value);
 -		if($value<=0)
 -			$value=4;
 -		$this->setViewState('Rows', $value, 4);
 -	}
 -
 -	/**
 -	 * @return TListSelectionMode the selection mode (Single, Multiple). Defaults to TListSelectionMode::Single.
 -	 */
 -	public function getSelectionMode()
 -	{
 -		return $this->getViewState('SelectionMode', TListSelectionMode::Single);
 -	}
 -
 -	/**
 -	 * @param TListSelectionMode the selection mode
 -	 */
 -	public function setSelectionMode($value)
 -	{
 -		$this->setViewState('SelectionMode',TPropertyValue::ensureEnum($value,'TListSelectionMode'),TListSelectionMode::Single);
 -	}
 -
 -	/**
 -	 * Returns the value to be validated.
 -	 * This methid is required by IValidatable interface.
 -	 * @return mixed the value of the property to be validated.
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getSelectedValue();
 -	}
 + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This method overrides the parent implementation with additional list box specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$rows=$this->getRows(); +		$writer->addAttribute('size',"$rows"); +		if($this->getSelectionMode()===TListSelectionMode::Multiple) +			$writer->addAttribute('name',$this->getUniqueID().'[]'); +		else +			$writer->addAttribute('name',$this->getUniqueID()); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TListBox'; +	} + +	/** +	 * Registers the list control to load post data on postback. +	 * This method overrides the parent implementation. +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); +		if($this->getEnabled(true)) +			$this->getPage()->registerRequiresPostData($this); +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		if(!$this->getEnabled(true)) +			return false; +		$this->ensureDataBound(); +		$selections=isset($values[$key])?$values[$key]:null; +		if($selections!==null) +		{ +			$items=$this->getItems(); +			if($this->getSelectionMode()===TListSelectionMode::Single) +			{ +				$selection=is_array($selections)?$selections[0]:$selections; +				$index=$items->findIndexByValue($selection,false); +				if($this->getSelectedIndex()!==$index) +				{ +					$this->setSelectedIndex($index); +					return $this->_dataChanged=true; +				} +				else +					return false; +			} +			if(!is_array($selections)) +				$selections=array($selections); +			$list=array(); +			foreach($selections as $selection) +				$list[]=$items->findIndexByValue($selection,false); +			$list2=$this->getSelectedIndices(); +			$n=count($list); +			$flag=false; +			if($n===count($list2)) +			{ +				sort($list,SORT_NUMERIC); +				for($i=0;$i<$n;++$i) +				{ +					if($list[$i]!==$list2[$i]) +					{ +						$flag=true; +						break; +					} +				} +			} +			else +				$flag=true; +			if($flag) +			{ +				$this->setSelectedIndices($list); +				$this->_dataChanged=true; +			} +			return $flag; +		} +		else if($this->getSelectedIndex()!==-1) +		{ +			$this->clearSelection(); +			return $this->_dataChanged=true; +		} +		else +			return false; +	} + +	/** +	 * Raises postdata changed event. +	 * This method is required by {@link IPostBackDataHandler} interface. +	 * It is invoked by the framework when {@link getSelectedIndices SelectedIndices} property +	 * is changed on postback. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		if($this->getAutoPostBack() && $this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onSelectedIndexChanged(null); +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * @return boolean whether this control allows multiple selection +	 */ +	protected function getIsMultiSelect() +	{ +		return $this->getSelectionMode()===TListSelectionMode::Multiple; +	} + +	/** +	 * @return integer the number of rows to be displayed in the list control +	 */ +	public function getRows() +	{ +		return $this->getViewState('Rows', 4); +	} + +	/** +	 * @param integer the number of rows to be displayed in the list control +	 */ +	public function setRows($value) +	{ +		$value=TPropertyValue::ensureInteger($value); +		if($value<=0) +			$value=4; +		$this->setViewState('Rows', $value, 4); +	} + +	/** +	 * @return TListSelectionMode the selection mode (Single, Multiple). Defaults to TListSelectionMode::Single. +	 */ +	public function getSelectionMode() +	{ +		return $this->getViewState('SelectionMode', TListSelectionMode::Single); +	} + +	/** +	 * @param TListSelectionMode the selection mode +	 */ +	public function setSelectionMode($value) +	{ +		$this->setViewState('SelectionMode',TPropertyValue::ensureEnum($value,'TListSelectionMode'),TListSelectionMode::Single); +	} + +	/** +	 * Returns the value to be validated. +	 * This methid is required by IValidatable interface. +	 * @return mixed the value of the property to be validated. +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getSelectedValue(); +	}  	/**  	 * Returns true if this control validated successfully.  @@ -238,25 +238,25 @@ class TListBox extends TListControl implements IPostBackDataHandler, IValidatabl  	{  	    $this->_isValid=TPropertyValue::ensureBoolean($value);  	} -}
 -
 -
 -/**
 - * TListSelectionMode class.
 - * TListSelectionMode defines the enumerable type for the possible selection modes of a {@link TListBox}.
 - *
 - * The following enumerable values are defined:
 - * - Single: single selection
 - * - Multiple: allow multiple selection
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TListSelectionMode extends TEnumerable
 -{
 -	const Single='Single';
 -	const Multiple='Multiple';
 -}
 -
 +} + + +/** + * TListSelectionMode class. + * TListSelectionMode defines the enumerable type for the possible selection modes of a {@link TListBox}. + * + * The following enumerable values are defined: + * - Single: single selection + * - Multiple: allow multiple selection + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TListSelectionMode extends TEnumerable +{ +	const Single='Single'; +	const Multiple='Multiple'; +} + diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 1a07a292..4d388d45 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -1,923 +1,923 @@ -<?php
 -
 -/**
 - * TListControl class file
 - *
 - * @author Robin J. Rogge <rojaro@gmail.com>
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes the supporting classes
 - */
 -Prado::using('System.Web.UI.WebControls.TDataBoundControl');
 -Prado::using('System.Web.UI.WebControls.TListItem');
 -Prado::using('System.Collections.TListItemCollection');
 -Prado::using('System.Collections.TAttributeCollection');
 -Prado::using('System.Util.TDataFieldAccessor');
 -
 -/**
 - * TListControl class
 - *
 - * TListControl is a base class for list controls, such as {@link TListBox},
 - * {@link TDropDownList}, {@link TCheckBoxList}, etc.
 - * It manages the items and their status in a list control.
 - * It also implements how the items can be populated from template and
 - * data source.
 - *
 - * The property {@link getItems} returns a list of the items in the control.
 - * To specify or determine which item is selected, use the
 - * {@link getSelectedIndex SelectedIndex} property that indicates the zero-based
 - * index of the selected item in the item list. You may also use
 - * {@link getSelectedItem SelectedItem} and {@link getSelectedValue SelectedValue}
 - * to get the selected item and its value. For multiple selection lists
 - * (such as {@link TCheckBoxList} and {@link TListBox}), property
 - * {@link getSelectedIndices SelectedIndices} is useful.
 - *
 - * TListControl implements {@link setAutoPostBack AutoPostBack} which allows
 - * a list control to postback the page if the selections of the list items are changed.
 - * The {@link setCausesValidation CausesValidation} and {@link setValidationGroup ValidationGroup}
 - * properties may be used to specify that validation be performed when auto postback occurs.
 - *
 - * There are three ways to populate the items in a list control: from template,
 - * using {@link setDataSource DataSource} and using {@link setDataSourceID DataSourceID}.
 - * The latter two are covered in {@link TDataBoundControl}. To specify items via
 - * template, using the following template syntax:
 - * <code>
 - * <com:TListControl>
 - *   <com:TListItem Value="xxx" Text="yyy" >
 - *   <com:TListItem Value="xxx" Text="yyy" Selected="true" >
 - *   <com:TListItem Value="xxx" Text="yyy" >
 - * </com:TListControl>
 - * </code>
 - *
 - * When {@link setDataSource DataSource} or {@link setDataSourceID DataSourceID}
 - * is used to populate list items, the {@link setDataTextField DataTextField} and
 - * {@link setDataValueField DataValueField} properties are used to specify which
 - * columns of the data will be used to populate the text and value of the items.
 - * For example, if a data source is as follows,
 - * <code>
 - * $dataSource=array(
 - *    array('name'=>'John', 'age'=>31),
 - *    array('name'=>'Cary', 'age'=>28),
 - *    array('name'=>'Rose', 'age'=>35),
 - * );
 - * </code>
 - * setting {@link setDataTextField DataTextField} and {@link setDataValueField DataValueField}
 - * to 'name' and 'age' will make the first item's text be 'John', value be 31,
 - * the second item's text be 'Cary', value be 28, and so on.
 - * The {@link setDataTextFormatString DataTextFormatString} property may be further
 - * used to format how the item should be displayed. See {@link formatDataValue()}
 - * for an explanation of the format string.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -abstract class TListControl extends TDataBoundControl implements IDataRenderer
 -{
 -	/**
 -	 * @var TListItemCollection item list
 -	 */
 -	private $_items=null;
 -	/**
 -	 * @var boolean whether items are restored from viewstate
 -	 */
 -	private $_stateLoaded=false;
 -	/**
 -	 * @var mixed the following selection variables are used
 -	 * to keep selections when Items are not available
 -	 */
 -	private $_cachedSelectedIndex=-1;
 -	private $_cachedSelectedValue=null;
 -	private $_cachedSelectedIndices=null;
 -	private $_cachedSelectedValues=null;
 -
 -	/**
 -	 * @return string tag name of the list control
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'select';
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$page=$this->getPage();
 -		$page->ensureRenderInForm($this);
 -		if($this->getIsMultiSelect())
 -			$writer->addAttribute('multiple','multiple');
 -		if($this->getEnabled(true))
 -		{
 -			if($this->getAutoPostBack()
 -				&& $this->getEnableClientScript()
 -				&& $page->getClientSupportsJavaScript())
 -			{
 -				$this->renderClientControlScript($writer);
 -			}
 -		}
 -		else if($this->getEnabled())
 -			$writer->addAttribute('disabled','disabled');
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the javascript for list control.
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$writer->addAttribute('id',$this->getClientID());
 -		$this->getPage()->getClientScript()->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * Derived classes may override this method and return customized js class names.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TListControl';
 -	}
 -
 -	/**
 -	 * @return array postback options for JS postback code
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		return $options;
 -	}
 -
 -	/**
 -	 * Adds object parsed from template to the control.
 -	 * This method adds only {@link TListItem} objects into the {@link getItems Items} collection.
 -	 * All other objects are ignored.
 -	 * @param mixed object parsed from template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		// Do not add items from template if items are loaded from viewstate
 -		if(!$this->_stateLoaded && ($object instanceof TListItem))
 -		{
 -			$index=$this->getItems()->add($object);
 -			if(($this->_cachedSelectedValue!==null && $this->_cachedSelectedValue===$object->getValue()) || ($this->_cachedSelectedIndex===$index))
 -			{
 -				$object->setSelected(true);
 -				$this->_cachedSelectedValue=null;
 -				$this->_cachedSelectedIndex=-1;
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Performs databinding to populate list items from data source.
 -	 * This method is invoked by dataBind().
 -	 * You may override this function to provide your own way of data population.
 -	 * @param Traversable the data
 -	 */
 -	protected function performDataBinding($data)
 -	{
 -		$items=$this->getItems();
 -		if(!$this->getAppendDataBoundItems())
 -			$items->clear();
 -		$textField=$this->getDataTextField();
 -		if($textField==='')
 -			$textField=0;
 -		$valueField=$this->getDataValueField();
 -		if($valueField==='')
 -			$valueField=1;
 -		$textFormat=$this->getDataTextFormatString();
 -		$groupField=$this->getDataGroupField();
 -		foreach($data as $key=>$object)
 -		{
 -			$item=$items->createListItem();
 -			if(is_array($object) || is_object($object))
 -			{
 -				$text=TDataFieldAccessor::getDataFieldValue($object,$textField);
 -				$value=TDataFieldAccessor::getDataFieldValue($object,$valueField);
 -				$item->setValue($value);
 -				if($groupField!=='')
 -					$item->setAttribute('Group',TDataFieldAccessor::getDataFieldValue($object,$groupField));
 -			}
 -			else
 -			{
 -				$text=$object;
 -				$item->setValue("$key");
 -			}
 -			$item->setText($this->formatDataValue($textFormat,$text));
 -		}
 -		// SelectedValue or SelectedIndex may be set before databinding
 -		// so we make them be effective now
 -		if($this->_cachedSelectedValue!==null)
 -		{
 -			$this->setSelectedValue($this->_cachedSelectedValue);
 -			$this->resetCachedSelections();
 -		}
 -		else if($this->_cachedSelectedIndex!==-1)
 -		{
 -			$this->setSelectedIndex($this->_cachedSelectedIndex);
 -			$this->resetCachedSelections();
 -		}
 -		else if($this->_cachedSelectedValues!==null)
 -		{
 -			$this->setSelectedValues($this->_cachedSelectedValues);
 -			$this->resetCachedSelections();
 -		}
 -		else if($this->_cachedSelectedIndices!==null)
 -		{
 -			$this->setSelectedIndices($this->_cachedSelectedIndices);
 -			$this->resetCachedSelections();
 -		}
 -	}
 -
 -	private function resetCachedSelections()
 -	{
 -		$this->_cachedSelectedValue=null;
 -		$this->_cachedSelectedIndex=-1;
 -		$this->_cachedSelectedValues=null;
 -		$this->_cachedSelectedIndices=null;
 -	}
 -
 -	/**
 -	 * Creates a collection object to hold list items.
 -	 * This method may be overriden to create a customized collection.
 -	 * @return TListItemCollection the collection object
 -	 */
 -	protected function createListItemCollection()
 -	{
 -		return new TListItemCollection;
 -	}
 -
 -	/**
 -	 * Saves items into viewstate.
 -	 * This method is invoked right before control state is to be saved.
 -	 */
 -	public function saveState()
 -	{
 -		parent::saveState();
 -		if($this->_items)
 -			$this->setViewState('Items',$this->_items->saveState(),null);
 -		else
 -			$this->clearViewState('Items');
 -	}
 -
 -	/**
 -	 * Loads items from viewstate.
 -	 * This method is invoked right after control state is loaded.
 -	 */
 -	public function loadState()
 -	{
 -		parent::loadState();
 -		$this->_stateLoaded=true;
 -		if(!$this->getIsDataBound())
 -		{
 -			$this->_items=$this->createListItemCollection();
 -			$this->_items->loadState($this->getViewState('Items',null));
 -		}
 -		$this->clearViewState('Items');
 -	}
 -
 -	/**
 -	 * @return boolean whether this is a multiselect control. Defaults to false.
 -	 */
 -	protected function getIsMultiSelect()
 -	{
 -		return false;
 -	}
 -
 -	/**
 -	 * @return boolean whether performing databind should append items or clear the existing ones. Defaults to false.
 -	 */
 -	public function getAppendDataBoundItems()
 -	{
 -		return $this->getViewState('AppendDataBoundItems',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether performing databind should append items or clear the existing ones.
 -	 */
 -	public function setAppendDataBoundItems($value)
 -	{
 -		$this->setViewState('AppendDataBoundItems',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean a value indicating whether an automatic postback to the server
 -     * will occur whenever the user makes change to the list control and then tabs out of it.
 -     * Defaults to false.
 -	 */
 -	public function getAutoPostBack()
 -	{
 -		return $this->getViewState('AutoPostBack',false);
 -	}
 -
 -	/**
 -	 * Sets the value indicating if postback automatically.
 -	 * An automatic postback to the server will occur whenever the user
 -	 * makes change to the list control and then tabs out of it.
 -	 * @param boolean the value indicating if postback automatically
 -	 */
 -	public function setAutoPostBack($value)
 -	{
 -		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by this list control will cause input validation, default is true.
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by this list control will cause input validation.
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return string the field of the data source that provides the text content of the list items.
 -	 */
 -	public function getDataTextField()
 -	{
 -		return $this->getViewState('DataTextField','');
 -	}
 -
 -	/**
 -	 * @param string the field of the data source that provides the text content of the list items.
 -	 */
 -	public function setDataTextField($value)
 -	{
 -		$this->setViewState('DataTextField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how data bound to the list control is displayed.
 -	 */
 -	public function getDataTextFormatString()
 -	{
 -		return $this->getViewState('DataTextFormatString','');
 -	}
 -
 -	/**
 -	 * Sets data text format string.
 -	 * The format string is used in {@link TDataValueFormatter::format()} to format the Text property value
 -	 * of each item in the list control.
 -	 * @param string the formatting string used to control how data bound to the list control is displayed.
 -	 * @see TDataValueFormatter::format()
 -	 */
 -	public function setDataTextFormatString($value)
 -	{
 -		$this->setViewState('DataTextFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field of the data source that provides the value of each list item.
 -	 */
 -	public function getDataValueField()
 -	{
 -		return $this->getViewState('DataValueField','');
 -	}
 -
 -	/**
 -	 * @param string the field of the data source that provides the value of each list item.
 -	 */
 -	public function setDataValueField($value)
 -	{
 -		$this->setViewState('DataValueField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the field of the data source that provides the label of the list item groups
 -	 */
 -	public function getDataGroupField()
 -	{
 -		return $this->getViewState('DataGroupField','');
 -	}
 -
 -	/**
 -	 * @param string the field of the data source that provides the label of the list item groups
 -	 */
 -	public function setDataGroupField($value)
 -	{
 -		$this->setViewState('DataGroupField',$value,'');
 -	}
 -
 -	/**
 -	 * @return integer the number of items in the list control
 -	 */
 -	public function getItemCount()
 -	{
 -		return $this->_items?$this->_items->getCount():0;
 -	}
 -
 -	/**
 -	 * @return boolean whether the list control contains any items.
 -	 */
 -	public function getHasItems()
 -	{
 -		return ($this->_items && $this->_items->getCount()>0);
 -	}
 -
 -	/**
 -	 * @return TListItemCollection the item collection
 -	 */
 -	public function getItems()
 -	{
 -		if(!$this->_items)
 -			$this->_items=$this->createListItemCollection();
 -		return $this->_items;
 -	}
 -
 -	/**
 -	 * @return integer the index (zero-based) of the item being selected, -1 if no item is selected.
 -	 */
 -	public function getSelectedIndex()
 -	{
 -		if($this->_items)
 -		{
 -			$n=$this->_items->getCount();
 -			for($i=0;$i<$n;++$i)
 -				if($this->_items->itemAt($i)->getSelected())
 -					return $i;
 -		}
 -		return -1;
 -	}
 -
 -	/**
 -	 * @param integer the index (zero-based) of the item to be selected
 -	 */
 -	public function setSelectedIndex($index)
 -	{
 -		if(($index=TPropertyValue::ensureInteger($index))<0)
 -			$index=-1;
 -		if($this->_items)
 -		{
 -			$this->clearSelection();
 -			if($index>=0 && $index<$this->_items->getCount())
 -				$this->_items->itemAt($index)->setSelected(true);
 -		}
 -		$this->_cachedSelectedIndex=$index;
 -		if($this->getAdapter() instanceof IListControlAdapter)
 -			$this->getAdapter()->setSelectedIndex($index);
 -	}
 -
 -	/**
 -	 * @return array list of index of items that are selected
 -	 */
 -	public function getSelectedIndices()
 -	{
 -		$selections=array();
 -		if($this->_items)
 -		{
 -			$n=$this->_items->getCount();
 -			for($i=0;$i<$n;++$i)
 -				if($this->_items->itemAt($i)->getSelected())
 -					$selections[]=$i;
 -		}
 -		return $selections;
 -	}
 -
 -	/**
 -	 * @param array list of index of items to be selected
 -	 */
 -	public function setSelectedIndices($indices)
 -	{
 -		if($this->getIsMultiSelect())
 -		{
 -			if($this->_items)
 -			{
 -				$this->clearSelection();
 -				$n=$this->_items->getCount();
 -				foreach($indices as $index)
 -				{
 -					if($index>=0 && $index<$n)
 -						$this->_items->itemAt($index)->setSelected(true);
 -				}
 -			}
 -			$this->_cachedSelectedIndices=$indices;
 -		}
 -		else
 -			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this));
 -
 -		if($this->getAdapter() instanceof IListControlAdapter)
 -			$this->getAdapter()->setSelectedIndices($indices);
 -	}
 -
 -	/**
 -	 * @return TListItem|null the selected item with the lowest cardinal index, null if no item is selected.
 -	 */
 -	public function getSelectedItem()
 -	{
 -		if(($index=$this->getSelectedIndex())>=0)
 -			return $this->_items->itemAt($index);
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * Returns the value of the selected item with the lowest cardinal index.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link getSelectedValue()}.
 -	 * @return string the value of the selected item with the lowest cardinal index, empty if no selection.
 -	 * @see getSelectedValue
 -	 * @since 3.1.0
 -	 */
 -	public function getData()
 -	{
 -		return $this->getSelectedValue();
 -	}
 -
 -	/**
 -	 * Selects an item by the specified value.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link setSelectedValue()}.
 -	 * @param string the value of the item to be selected.
 -	 * @see setSelectedValue
 -	 * @since 3.1.0
 -	 */
 -	public function setData($value)
 -	{
 -		$this->setSelectedValue($value);
 -	}
 -
 -	/**
 -	 * @return string the value of the selected item with the lowest cardinal index, empty if no selection
 -	 */
 -	public function getSelectedValue()
 -	{
 -		$index=$this->getSelectedIndex();
 -		return $index>=0?$this->getItems()->itemAt($index)->getValue():'';
 -	}
 -
 -	/**
 -	 * Sets selection by item value.
 -	 * Existing selections will be cleared if the item value is found in the item collection.
 -	 * Note, if the value is null, existing selections will also be cleared.
 -	 * @param string the value of the item to be selected.
 -	 */
 -	public function setSelectedValue($value)
 -    {
 -	    if($this->_items)
 -	    {
 -		    if($value===null)
 -		    	$this->clearSelection();
 -		    else if(($item=$this->_items->findItemByValue($value))!==null)
 -	    	{
 -		    	$this->clearSelection();
 -		    	$item->setSelected(true);
 -	    	}
 -	    	else
 -				$this->clearSelection();
 -    	}
 -    	$this->_cachedSelectedValue=$value;
 -		if($this->getAdapter() instanceof IListControlAdapter)
 -			$this->getAdapter()->setSelectedValue($value);
 -    }
 -
 -
 -	/**
 -	 * @return array list of the selected item values (strings)
 -	 */
 -	public function getSelectedValues()
 -	{
 -		$values=array();
 -		if($this->_items)
 -		{
 -			foreach($this->_items as $item)
 -			{
 -				if($item->getSelected())
 -					$values[]=$item->getValue();
 -			}
 -		}
 -		return $values;
 -	}
 -
 -	/**
 -	 * @param array list of the selected item values
 -	 */
 -	public function setSelectedValues($values)
 -	{
 -		if($this->getIsMultiSelect())
 -		{
 -			if($this->_items)
 -			{
 -				$this->clearSelection();
 -				$lookup=array();
 -				foreach($this->_items as $item)
 -					$lookup[$item->getValue()]=$item;
 -				foreach($values as $value)
 -				{
 -					if(isset($lookup["$value"]))
 -						$lookup["$value"]->setSelected(true);
 -				}
 -			}
 -			$this->_cachedSelectedValues=$values;
 -		}
 -		else
 -			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this));
 -
 -		if($this->getAdapter() instanceof IListControlAdapter)
 -			$this->getAdapter()->setSelectedValues($values);
 -	}
 -
 -    /**
 -     * @return string selected value
 -     */
 -    public function getText()
 -    {
 -	    return $this->getSelectedValue();
 -    }
 -
 -    /**
 -     * @param string value to be selected
 -     */
 -    public function setText($value)
 -    {
 -	    $this->setSelectedValue($value);
 -    }
 -
 -    /**
 -     * Clears all existing selections.
 -     */
 -    public function clearSelection()
 -    {
 -	    if($this->_items)
 -	    {
 -		    foreach($this->_items as $item)
 -		    	$item->setSelected(false);
 -	    }
 -
 -		if($this->getAdapter() instanceof IListControlAdapter)
 -			$this->getAdapter()->clearSelection();
 -    }
 -
 -	/**
 -	 * @return string the group of validators which the list control causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the list control causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the prompt text which is to be displayed as the first list item.
 -	 * @since 3.1.1
 -	 */
 -	public function getPromptText()
 -	{
 -		return $this->getViewState('PromptText','');
 -	}
 -
 -	/**
 -	 * @param string the prompt text which is to be displayed as the first list item.
 -	 * @since 3.1.1
 -	 */
 -	public function setPromptText($value)
 -	{
 -		$this->setViewState('PromptText',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the prompt selection value.
 -	 * @see getPromptText
 -	 * @since 3.1.1
 -	 */
 -	public function getPromptValue()
 -	{
 -		return $this->getViewState('PromptValue','');
 -	}
 -
 -	/**
 -	 * @param string the prompt selection value. If empty, {@link getPromptText PromptText} will be used as the value.
 -	 * @see setPromptText
 -	 * @since 3.1.1
 -	 */
 -	public function setPromptValue($value)
 -	{
 -		$this->setViewState('PromptValue',(string)$value,'');
 -	}
 -
 -	/**
 -	 * Raises OnSelectedIndexChanged event when selection is changed.
 -	 * This method is invoked when the list control has its selection changed
 -	 * by end-users.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onSelectedIndexChanged($param)
 -	{
 -		$this->raiseEvent('OnSelectedIndexChanged',$this,$param);
 -		$this->onTextChanged($param);
 -	}
 -
 -	/**
 -	 * Raises OnTextChanged event when selection is changed.
 -	 * This method is invoked when the list control has its selection changed
 -	 * by end-users.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onTextChanged($param)
 -	{
 -		$this->raiseEvent('OnTextChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Renders the prompt text, if any.
 -	 * @param THtmlWriter writer
 -	 * @since 3.1.1
 -	 */
 -	protected function renderPrompt($writer)
 -	{
 -		$text=$this->getPromptText();
 -		$value=$this->getPromptValue();
 -		if($value==='')
 -			$value=$text;
 -		if($value!=='')
 -		{
 -			$writer->addAttribute('value',$value);
 -			$writer->renderBeginTag('option');
 -			$writer->write(THttpUtility::htmlEncode($text));
 -			$writer->renderEndTag();
 -			$writer->writeLine();
 -		}
 -	}
 -
 -	/**
 -	 * Renders body content of the list control.
 -	 * This method renders items contained in the list control as the body content.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function renderContents($writer)
 -	{
 -		$this->renderPrompt($writer);
 -		
 -		if($this->_items)
 -		{
 -			$writer->writeLine();
 -			$previousGroup=null;
 -			foreach($this->_items as $item)
 -			{
 -				if($item->getEnabled())
 -				{
 -					if($item->getHasAttributes())
 -					{
 -						$group=$item->getAttributes()->remove('Group');
 -						if($group!==$previousGroup)
 -						{
 -							if($previousGroup!==null)
 -							{
 -								$writer->renderEndTag();
 -								$writer->writeLine();
 -								$previousGroup=null;
 -							}
 -							if($group!==null)
 -							{
 -								$writer->addAttribute('label',$group);
 -								$writer->renderBeginTag('optgroup');
 -								$writer->writeLine();
 -								$previousGroup=$group;
 -							}
 -						}
 -						foreach($item->getAttributes() as $name=>$value)
 -							$writer->addAttribute($name,$value);
 -					}
 -					else if($previousGroup!==null)
 -					{
 -						$writer->renderEndTag();
 -						$writer->writeLine();
 -						$previousGroup=null;
 -					}
 -					if($item->getSelected())
 -						$writer->addAttribute('selected','selected');
 -					$writer->addAttribute('value',$item->getValue());
 -					$writer->renderBeginTag('option');
 -					$writer->write(THttpUtility::htmlEncode($item->getText()));
 -					$writer->renderEndTag();
 -					$writer->writeLine();
 -				}
 -			}
 -			if($previousGroup!==null)
 -			{
 -				$writer->renderEndTag();
 -				$writer->writeLine();
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Formats the text value according to a format string.
 -	 * If the format string is empty, the original value is converted into
 -	 * a string and returned.
 -	 * If the format string starts with '#', the string is treated as a PHP expression
 -	 * within which the token '{0}' is translated with the data value to be formated.
 -	 * Otherwise, the format string and the data value are passed
 -	 * as the first and second parameters in {@link sprintf}.
 -	 * @param string format string
 -	 * @param mixed the data to be formatted
 -	 * @return string the formatted result
 -	 */
 -	protected function formatDataValue($formatString,$value)
 -	{
 -		if($formatString==='')
 -			return TPropertyValue::ensureString($value);
 -		else if($formatString[0]==='#')
 -		{
 -			$expression=strtr(substr($formatString,1),array('{0}'=>'$value'));
 -			try
 -			{
 -				if(eval("\$result=$expression;")===false)
 -					throw new Exception('');
 -				return $result;
 -			}
 -			catch(Exception $e)
 -			{
 -				throw new TInvalidDataValueException('listcontrol_expression_invalid',get_class($this),$expression,$e->getMessage());
 -			}
 -		}
 -		else
 -			return sprintf($formatString,$value);
 -	}
 -}
 -
 -/**
 - * IListControlAdapter interface
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Revision: $  Sun Jun 25 04:53:43 EST 2006 $
 - * @package System.Web.UI.ActiveControls
 - * @since 3.0
 - */
 -interface IListControlAdapter
 -{
 -	/**
 -	 * 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.
 -	 * @param array list of index of items to be selected
 -	 */
 -	public function setSelectedIndices($indices);
 -
 -	/**
 -	 * Sets selection by item value on the client side.
 -	 * @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.
 -     */
 -    public function clearSelection();
 -}
 -
 -
 -?>
 +<?php + +/** + * TListControl class file + * + * @author Robin J. Rogge <rojaro@gmail.com> + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes the supporting classes + */ +Prado::using('System.Web.UI.WebControls.TDataBoundControl'); +Prado::using('System.Web.UI.WebControls.TListItem'); +Prado::using('System.Collections.TListItemCollection'); +Prado::using('System.Collections.TAttributeCollection'); +Prado::using('System.Util.TDataFieldAccessor'); + +/** + * TListControl class + * + * TListControl is a base class for list controls, such as {@link TListBox}, + * {@link TDropDownList}, {@link TCheckBoxList}, etc. + * It manages the items and their status in a list control. + * It also implements how the items can be populated from template and + * data source. + * + * The property {@link getItems} returns a list of the items in the control. + * To specify or determine which item is selected, use the + * {@link getSelectedIndex SelectedIndex} property that indicates the zero-based + * index of the selected item in the item list. You may also use + * {@link getSelectedItem SelectedItem} and {@link getSelectedValue SelectedValue} + * to get the selected item and its value. For multiple selection lists + * (such as {@link TCheckBoxList} and {@link TListBox}), property + * {@link getSelectedIndices SelectedIndices} is useful. + * + * TListControl implements {@link setAutoPostBack AutoPostBack} which allows + * a list control to postback the page if the selections of the list items are changed. + * The {@link setCausesValidation CausesValidation} and {@link setValidationGroup ValidationGroup} + * properties may be used to specify that validation be performed when auto postback occurs. + * + * There are three ways to populate the items in a list control: from template, + * using {@link setDataSource DataSource} and using {@link setDataSourceID DataSourceID}. + * The latter two are covered in {@link TDataBoundControl}. To specify items via + * template, using the following template syntax: + * <code> + * <com:TListControl> + *   <com:TListItem Value="xxx" Text="yyy" > + *   <com:TListItem Value="xxx" Text="yyy" Selected="true" > + *   <com:TListItem Value="xxx" Text="yyy" > + * </com:TListControl> + * </code> + * + * When {@link setDataSource DataSource} or {@link setDataSourceID DataSourceID} + * is used to populate list items, the {@link setDataTextField DataTextField} and + * {@link setDataValueField DataValueField} properties are used to specify which + * columns of the data will be used to populate the text and value of the items. + * For example, if a data source is as follows, + * <code> + * $dataSource=array( + *    array('name'=>'John', 'age'=>31), + *    array('name'=>'Cary', 'age'=>28), + *    array('name'=>'Rose', 'age'=>35), + * ); + * </code> + * setting {@link setDataTextField DataTextField} and {@link setDataValueField DataValueField} + * to 'name' and 'age' will make the first item's text be 'John', value be 31, + * the second item's text be 'Cary', value be 28, and so on. + * The {@link setDataTextFormatString DataTextFormatString} property may be further + * used to format how the item should be displayed. See {@link formatDataValue()} + * for an explanation of the format string. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +abstract class TListControl extends TDataBoundControl implements IDataRenderer +{ +	/** +	 * @var TListItemCollection item list +	 */ +	private $_items=null; +	/** +	 * @var boolean whether items are restored from viewstate +	 */ +	private $_stateLoaded=false; +	/** +	 * @var mixed the following selection variables are used +	 * to keep selections when Items are not available +	 */ +	private $_cachedSelectedIndex=-1; +	private $_cachedSelectedValue=null; +	private $_cachedSelectedIndices=null; +	private $_cachedSelectedValues=null; + +	/** +	 * @return string tag name of the list control +	 */ +	protected function getTagName() +	{ +		return 'select'; +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 */ +	protected function addAttributesToRender($writer) +	{ +		$page=$this->getPage(); +		$page->ensureRenderInForm($this); +		if($this->getIsMultiSelect()) +			$writer->addAttribute('multiple','multiple'); +		if($this->getEnabled(true)) +		{ +			if($this->getAutoPostBack() +				&& $this->getEnableClientScript() +				&& $page->getClientSupportsJavaScript()) +			{ +				$this->renderClientControlScript($writer); +			} +		} +		else if($this->getEnabled()) +			$writer->addAttribute('disabled','disabled'); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Renders the javascript for list control. +	 */ +	protected function renderClientControlScript($writer) +	{ +		$writer->addAttribute('id',$this->getClientID()); +		$this->getPage()->getClientScript()->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * Derived classes may override this method and return customized js class names. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TListControl'; +	} + +	/** +	 * @return array postback options for JS postback code +	 */ +	protected function getPostBackOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['EventTarget'] = $this->getUniqueID(); +		return $options; +	} + +	/** +	 * Adds object parsed from template to the control. +	 * This method adds only {@link TListItem} objects into the {@link getItems Items} collection. +	 * All other objects are ignored. +	 * @param mixed object parsed from template +	 */ +	public function addParsedObject($object) +	{ +		// Do not add items from template if items are loaded from viewstate +		if(!$this->_stateLoaded && ($object instanceof TListItem)) +		{ +			$index=$this->getItems()->add($object); +			if(($this->_cachedSelectedValue!==null && $this->_cachedSelectedValue===$object->getValue()) || ($this->_cachedSelectedIndex===$index)) +			{ +				$object->setSelected(true); +				$this->_cachedSelectedValue=null; +				$this->_cachedSelectedIndex=-1; +			} +		} +	} + +	/** +	 * Performs databinding to populate list items from data source. +	 * This method is invoked by dataBind(). +	 * You may override this function to provide your own way of data population. +	 * @param Traversable the data +	 */ +	protected function performDataBinding($data) +	{ +		$items=$this->getItems(); +		if(!$this->getAppendDataBoundItems()) +			$items->clear(); +		$textField=$this->getDataTextField(); +		if($textField==='') +			$textField=0; +		$valueField=$this->getDataValueField(); +		if($valueField==='') +			$valueField=1; +		$textFormat=$this->getDataTextFormatString(); +		$groupField=$this->getDataGroupField(); +		foreach($data as $key=>$object) +		{ +			$item=$items->createListItem(); +			if(is_array($object) || is_object($object)) +			{ +				$text=TDataFieldAccessor::getDataFieldValue($object,$textField); +				$value=TDataFieldAccessor::getDataFieldValue($object,$valueField); +				$item->setValue($value); +				if($groupField!=='') +					$item->setAttribute('Group',TDataFieldAccessor::getDataFieldValue($object,$groupField)); +			} +			else +			{ +				$text=$object; +				$item->setValue("$key"); +			} +			$item->setText($this->formatDataValue($textFormat,$text)); +		} +		// SelectedValue or SelectedIndex may be set before databinding +		// so we make them be effective now +		if($this->_cachedSelectedValue!==null) +		{ +			$this->setSelectedValue($this->_cachedSelectedValue); +			$this->resetCachedSelections(); +		} +		else if($this->_cachedSelectedIndex!==-1) +		{ +			$this->setSelectedIndex($this->_cachedSelectedIndex); +			$this->resetCachedSelections(); +		} +		else if($this->_cachedSelectedValues!==null) +		{ +			$this->setSelectedValues($this->_cachedSelectedValues); +			$this->resetCachedSelections(); +		} +		else if($this->_cachedSelectedIndices!==null) +		{ +			$this->setSelectedIndices($this->_cachedSelectedIndices); +			$this->resetCachedSelections(); +		} +	} + +	private function resetCachedSelections() +	{ +		$this->_cachedSelectedValue=null; +		$this->_cachedSelectedIndex=-1; +		$this->_cachedSelectedValues=null; +		$this->_cachedSelectedIndices=null; +	} + +	/** +	 * Creates a collection object to hold list items. +	 * This method may be overriden to create a customized collection. +	 * @return TListItemCollection the collection object +	 */ +	protected function createListItemCollection() +	{ +		return new TListItemCollection; +	} + +	/** +	 * Saves items into viewstate. +	 * This method is invoked right before control state is to be saved. +	 */ +	public function saveState() +	{ +		parent::saveState(); +		if($this->_items) +			$this->setViewState('Items',$this->_items->saveState(),null); +		else +			$this->clearViewState('Items'); +	} + +	/** +	 * Loads items from viewstate. +	 * This method is invoked right after control state is loaded. +	 */ +	public function loadState() +	{ +		parent::loadState(); +		$this->_stateLoaded=true; +		if(!$this->getIsDataBound()) +		{ +			$this->_items=$this->createListItemCollection(); +			$this->_items->loadState($this->getViewState('Items',null)); +		} +		$this->clearViewState('Items'); +	} + +	/** +	 * @return boolean whether this is a multiselect control. Defaults to false. +	 */ +	protected function getIsMultiSelect() +	{ +		return false; +	} + +	/** +	 * @return boolean whether performing databind should append items or clear the existing ones. Defaults to false. +	 */ +	public function getAppendDataBoundItems() +	{ +		return $this->getViewState('AppendDataBoundItems',false); +	} + +	/** +	 * @param boolean whether performing databind should append items or clear the existing ones. +	 */ +	public function setAppendDataBoundItems($value) +	{ +		$this->setViewState('AppendDataBoundItems',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean a value indicating whether an automatic postback to the server +     * will occur whenever the user makes change to the list control and then tabs out of it. +     * Defaults to false. +	 */ +	public function getAutoPostBack() +	{ +		return $this->getViewState('AutoPostBack',false); +	} + +	/** +	 * Sets the value indicating if postback automatically. +	 * An automatic postback to the server will occur whenever the user +	 * makes change to the list control and then tabs out of it. +	 * @param boolean the value indicating if postback automatically +	 */ +	public function setAutoPostBack($value) +	{ +		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether postback event trigger by this list control will cause input validation, default is true. +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by this list control will cause input validation. +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return string the field of the data source that provides the text content of the list items. +	 */ +	public function getDataTextField() +	{ +		return $this->getViewState('DataTextField',''); +	} + +	/** +	 * @param string the field of the data source that provides the text content of the list items. +	 */ +	public function setDataTextField($value) +	{ +		$this->setViewState('DataTextField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how data bound to the list control is displayed. +	 */ +	public function getDataTextFormatString() +	{ +		return $this->getViewState('DataTextFormatString',''); +	} + +	/** +	 * Sets data text format string. +	 * The format string is used in {@link TDataValueFormatter::format()} to format the Text property value +	 * of each item in the list control. +	 * @param string the formatting string used to control how data bound to the list control is displayed. +	 * @see TDataValueFormatter::format() +	 */ +	public function setDataTextFormatString($value) +	{ +		$this->setViewState('DataTextFormatString',$value,''); +	} + +	/** +	 * @return string the field of the data source that provides the value of each list item. +	 */ +	public function getDataValueField() +	{ +		return $this->getViewState('DataValueField',''); +	} + +	/** +	 * @param string the field of the data source that provides the value of each list item. +	 */ +	public function setDataValueField($value) +	{ +		$this->setViewState('DataValueField',$value,''); +	} + +	/** +	 * @return string the field of the data source that provides the label of the list item groups +	 */ +	public function getDataGroupField() +	{ +		return $this->getViewState('DataGroupField',''); +	} + +	/** +	 * @param string the field of the data source that provides the label of the list item groups +	 */ +	public function setDataGroupField($value) +	{ +		$this->setViewState('DataGroupField',$value,''); +	} + +	/** +	 * @return integer the number of items in the list control +	 */ +	public function getItemCount() +	{ +		return $this->_items?$this->_items->getCount():0; +	} + +	/** +	 * @return boolean whether the list control contains any items. +	 */ +	public function getHasItems() +	{ +		return ($this->_items && $this->_items->getCount()>0); +	} + +	/** +	 * @return TListItemCollection the item collection +	 */ +	public function getItems() +	{ +		if(!$this->_items) +			$this->_items=$this->createListItemCollection(); +		return $this->_items; +	} + +	/** +	 * @return integer the index (zero-based) of the item being selected, -1 if no item is selected. +	 */ +	public function getSelectedIndex() +	{ +		if($this->_items) +		{ +			$n=$this->_items->getCount(); +			for($i=0;$i<$n;++$i) +				if($this->_items->itemAt($i)->getSelected()) +					return $i; +		} +		return -1; +	} + +	/** +	 * @param integer the index (zero-based) of the item to be selected +	 */ +	public function setSelectedIndex($index) +	{ +		if(($index=TPropertyValue::ensureInteger($index))<0) +			$index=-1; +		if($this->_items) +		{ +			$this->clearSelection(); +			if($index>=0 && $index<$this->_items->getCount()) +				$this->_items->itemAt($index)->setSelected(true); +		} +		$this->_cachedSelectedIndex=$index; +		if($this->getAdapter() instanceof IListControlAdapter) +			$this->getAdapter()->setSelectedIndex($index); +	} + +	/** +	 * @return array list of index of items that are selected +	 */ +	public function getSelectedIndices() +	{ +		$selections=array(); +		if($this->_items) +		{ +			$n=$this->_items->getCount(); +			for($i=0;$i<$n;++$i) +				if($this->_items->itemAt($i)->getSelected()) +					$selections[]=$i; +		} +		return $selections; +	} + +	/** +	 * @param array list of index of items to be selected +	 */ +	public function setSelectedIndices($indices) +	{ +		if($this->getIsMultiSelect()) +		{ +			if($this->_items) +			{ +				$this->clearSelection(); +				$n=$this->_items->getCount(); +				foreach($indices as $index) +				{ +					if($index>=0 && $index<$n) +						$this->_items->itemAt($index)->setSelected(true); +				} +			} +			$this->_cachedSelectedIndices=$indices; +		} +		else +			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this)); + +		if($this->getAdapter() instanceof IListControlAdapter) +			$this->getAdapter()->setSelectedIndices($indices); +	} + +	/** +	 * @return TListItem|null the selected item with the lowest cardinal index, null if no item is selected. +	 */ +	public function getSelectedItem() +	{ +		if(($index=$this->getSelectedIndex())>=0) +			return $this->_items->itemAt($index); +		else +			return null; +	} + +	/** +	 * Returns the value of the selected item with the lowest cardinal index. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link getSelectedValue()}. +	 * @return string the value of the selected item with the lowest cardinal index, empty if no selection. +	 * @see getSelectedValue +	 * @since 3.1.0 +	 */ +	public function getData() +	{ +		return $this->getSelectedValue(); +	} + +	/** +	 * Selects an item by the specified value. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link setSelectedValue()}. +	 * @param string the value of the item to be selected. +	 * @see setSelectedValue +	 * @since 3.1.0 +	 */ +	public function setData($value) +	{ +		$this->setSelectedValue($value); +	} + +	/** +	 * @return string the value of the selected item with the lowest cardinal index, empty if no selection +	 */ +	public function getSelectedValue() +	{ +		$index=$this->getSelectedIndex(); +		return $index>=0?$this->getItems()->itemAt($index)->getValue():''; +	} + +	/** +	 * Sets selection by item value. +	 * Existing selections will be cleared if the item value is found in the item collection. +	 * Note, if the value is null, existing selections will also be cleared. +	 * @param string the value of the item to be selected. +	 */ +	public function setSelectedValue($value) +    { +	    if($this->_items) +	    { +		    if($value===null) +		    	$this->clearSelection(); +		    else if(($item=$this->_items->findItemByValue($value))!==null) +	    	{ +		    	$this->clearSelection(); +		    	$item->setSelected(true); +	    	} +	    	else +				$this->clearSelection(); +    	} +    	$this->_cachedSelectedValue=$value; +		if($this->getAdapter() instanceof IListControlAdapter) +			$this->getAdapter()->setSelectedValue($value); +    } + + +	/** +	 * @return array list of the selected item values (strings) +	 */ +	public function getSelectedValues() +	{ +		$values=array(); +		if($this->_items) +		{ +			foreach($this->_items as $item) +			{ +				if($item->getSelected()) +					$values[]=$item->getValue(); +			} +		} +		return $values; +	} + +	/** +	 * @param array list of the selected item values +	 */ +	public function setSelectedValues($values) +	{ +		if($this->getIsMultiSelect()) +		{ +			if($this->_items) +			{ +				$this->clearSelection(); +				$lookup=array(); +				foreach($this->_items as $item) +					$lookup[$item->getValue()]=$item; +				foreach($values as $value) +				{ +					if(isset($lookup["$value"])) +						$lookup["$value"]->setSelected(true); +				} +			} +			$this->_cachedSelectedValues=$values; +		} +		else +			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this)); + +		if($this->getAdapter() instanceof IListControlAdapter) +			$this->getAdapter()->setSelectedValues($values); +	} + +    /** +     * @return string selected value +     */ +    public function getText() +    { +	    return $this->getSelectedValue(); +    } + +    /** +     * @param string value to be selected +     */ +    public function setText($value) +    { +	    $this->setSelectedValue($value); +    } + +    /** +     * Clears all existing selections. +     */ +    public function clearSelection() +    { +	    if($this->_items) +	    { +		    foreach($this->_items as $item) +		    	$item->setSelected(false); +	    } + +		if($this->getAdapter() instanceof IListControlAdapter) +			$this->getAdapter()->clearSelection(); +    } + +	/** +	 * @return string the group of validators which the list control causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the list control causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * @return string the prompt text which is to be displayed as the first list item. +	 * @since 3.1.1 +	 */ +	public function getPromptText() +	{ +		return $this->getViewState('PromptText',''); +	} + +	/** +	 * @param string the prompt text which is to be displayed as the first list item. +	 * @since 3.1.1 +	 */ +	public function setPromptText($value) +	{ +		$this->setViewState('PromptText',$value,''); +	} + +	/** +	 * @return string the prompt selection value. +	 * @see getPromptText +	 * @since 3.1.1 +	 */ +	public function getPromptValue() +	{ +		return $this->getViewState('PromptValue',''); +	} + +	/** +	 * @param string the prompt selection value. If empty, {@link getPromptText PromptText} will be used as the value. +	 * @see setPromptText +	 * @since 3.1.1 +	 */ +	public function setPromptValue($value) +	{ +		$this->setViewState('PromptValue',(string)$value,''); +	} + +	/** +	 * Raises OnSelectedIndexChanged event when selection is changed. +	 * This method is invoked when the list control has its selection changed +	 * by end-users. +	 * @param TEventParameter event parameter +	 */ +	public function onSelectedIndexChanged($param) +	{ +		$this->raiseEvent('OnSelectedIndexChanged',$this,$param); +		$this->onTextChanged($param); +	} + +	/** +	 * Raises OnTextChanged event when selection is changed. +	 * This method is invoked when the list control has its selection changed +	 * by end-users. +	 * @param TEventParameter event parameter +	 */ +	public function onTextChanged($param) +	{ +		$this->raiseEvent('OnTextChanged',$this,$param); +	} + +	/** +	 * Renders the prompt text, if any. +	 * @param THtmlWriter writer +	 * @since 3.1.1 +	 */ +	protected function renderPrompt($writer) +	{ +		$text=$this->getPromptText(); +		$value=$this->getPromptValue(); +		if($value==='') +			$value=$text; +		if($value!=='') +		{ +			$writer->addAttribute('value',$value); +			$writer->renderBeginTag('option'); +			$writer->write(THttpUtility::htmlEncode($text)); +			$writer->renderEndTag(); +			$writer->writeLine(); +		} +	} + +	/** +	 * Renders body content of the list control. +	 * This method renders items contained in the list control as the body content. +	 * @param THtmlWriter writer +	 */ +	public function renderContents($writer) +	{ +		$this->renderPrompt($writer); +		 +		if($this->_items) +		{ +			$writer->writeLine(); +			$previousGroup=null; +			foreach($this->_items as $item) +			{ +				if($item->getEnabled()) +				{ +					if($item->getHasAttributes()) +					{ +						$group=$item->getAttributes()->remove('Group'); +						if($group!==$previousGroup) +						{ +							if($previousGroup!==null) +							{ +								$writer->renderEndTag(); +								$writer->writeLine(); +								$previousGroup=null; +							} +							if($group!==null) +							{ +								$writer->addAttribute('label',$group); +								$writer->renderBeginTag('optgroup'); +								$writer->writeLine(); +								$previousGroup=$group; +							} +						} +						foreach($item->getAttributes() as $name=>$value) +							$writer->addAttribute($name,$value); +					} +					else if($previousGroup!==null) +					{ +						$writer->renderEndTag(); +						$writer->writeLine(); +						$previousGroup=null; +					} +					if($item->getSelected()) +						$writer->addAttribute('selected','selected'); +					$writer->addAttribute('value',$item->getValue()); +					$writer->renderBeginTag('option'); +					$writer->write(THttpUtility::htmlEncode($item->getText())); +					$writer->renderEndTag(); +					$writer->writeLine(); +				} +			} +			if($previousGroup!==null) +			{ +				$writer->renderEndTag(); +				$writer->writeLine(); +			} +		} +	} + +	/** +	 * Formats the text value according to a format string. +	 * If the format string is empty, the original value is converted into +	 * a string and returned. +	 * If the format string starts with '#', the string is treated as a PHP expression +	 * within which the token '{0}' is translated with the data value to be formated. +	 * Otherwise, the format string and the data value are passed +	 * as the first and second parameters in {@link sprintf}. +	 * @param string format string +	 * @param mixed the data to be formatted +	 * @return string the formatted result +	 */ +	protected function formatDataValue($formatString,$value) +	{ +		if($formatString==='') +			return TPropertyValue::ensureString($value); +		else if($formatString[0]==='#') +		{ +			$expression=strtr(substr($formatString,1),array('{0}'=>'$value')); +			try +			{ +				if(eval("\$result=$expression;")===false) +					throw new Exception(''); +				return $result; +			} +			catch(Exception $e) +			{ +				throw new TInvalidDataValueException('listcontrol_expression_invalid',get_class($this),$expression,$e->getMessage()); +			} +		} +		else +			return sprintf($formatString,$value); +	} +} + +/** + * IListControlAdapter interface + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Revision: $  Sun Jun 25 04:53:43 EST 2006 $ + * @package System.Web.UI.ActiveControls + * @since 3.0 + */ +interface IListControlAdapter +{ +	/** +	 * 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. +	 * @param array list of index of items to be selected +	 */ +	public function setSelectedIndices($indices); + +	/** +	 * Sets selection by item value on the client side. +	 * @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. +     */ +    public function clearSelection(); +} + + +?> diff --git a/framework/Web/UI/WebControls/TListControlValidator.php b/framework/Web/UI/WebControls/TListControlValidator.php index a5be67b3..75a0510c 100644 --- a/framework/Web/UI/WebControls/TListControlValidator.php +++ b/framework/Web/UI/WebControls/TListControlValidator.php @@ -1,225 +1,225 @@ -<?php
 -/**
 - * TListControlValidator class file
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TListControlValidator class file + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TListControlValidator class.
 - *
 - * TListControlValidator checks the number of selection and their values
 - * for a <b>TListControl that allows multiple selection</b>.
 - *
 - * You can specify the minimum or maximum (or both) number of selections
 - * required using the {@link setMinSelection MinSelection} and
 - * {@link setMaxSelection MaxSelection} properties, respectively. In addition,
 - * you can specify a comma separated list of required selected values via the
 - * {@link setRequiredSelections RequiredSelections} property.
 - *
 - * Examples
 - * - At least two selections
 - * <code>
 - *	<com:TListBox ID="listbox" SelectionMode="Multiple">
 - *		<com:TListItem Text="item1" Value="value1" />
 - *		<com:TListItem Text="item2" Value="value2" />
 - *		<com:TListItem Text="item3" Value="value3" />
 - *	</com:TListBox>
 - *
 - *	<com:TListControlValidator
 - *		ControlToValidate="listbox"
 - *		MinSelection="2"
 - *		ErrorMessage="Please select at least 2" />
 - * </code>
 - * - "value1" must be selected <b>and</b> at least 1 other
 - * <code>
 - *	<com:TCheckBoxList ID="checkboxes">
 - *		<com:TListItem Text="item1" Value="value1" />
 - *		<com:TListItem Text="item2" Value="value2" />
 - *		<com:TListItem Text="item3" Value="value3" />
 - *	</com:TCheckBoxList>
 - *
 - *	<com:TListControlValidator
 - *		ControlToValidate="checkboxes"
 - *		RequiredSelections="value1"
 - *		MinSelection="2"
 - *		ErrorMessage="Please select 'item1' and at least 1 other" />
 - * </code>
 - *
 - * @author Xiang Wei Zhuo <weizhuo[at]gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TListControlValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TListControlValidator';
 -	}
 -
 -	/**
 -	 * @return integer min number of selections. Defaults to -1, meaning not set.
 -	 */
 -	public function getMinSelection()
 -	{
 -		return $this->getViewState('MinSelection',-1);
 -	}
 -
 -	/**
 -	 * @param integer minimum number of selections.
 -	 */
 -	public function setMinSelection($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			$value=-1;
 -		$this->setViewState('MinSelection',$value,-1);
 -	}
 -
 -	/**
 -	 * @return integer max number of selections.  Defaults to -1, meaning not set.
 -	 */
 -	public function getMaxSelection()
 -	{
 -		return $this->getViewState('MaxSelection',-1);
 -	}
 -
 -	/**
 -	 * @param integer max number of selections.
 -	 */
 -	public function setMaxSelection($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			$value=-1;
 -		$this->setViewState('MaxSelection',$value,-1);
 -	}
 -
 -	/**
 -	 * Get a comma separated list of required selected values.
 -	 * @return string comma separated list of required values.
 -	 */
 -	public function getRequiredSelections()
 -	{
 -		return $this->getViewState('RequiredSelections','');
 -	}
 -
 -	/**
 -	 * Set the list of required values, using aa comma separated list.
 -	 * @param string comma separated list of required values.
 -	 */
 -	public function setRequiredSelections($value)
 -	{
 -		$this->setViewState('RequiredSelections',$value,'');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input component changes its data
 -	 * from the InitialValue or the input component is not given.
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	protected function evaluateIsValid()
 -	{
 -		$control=$this->getValidationTarget();
 -
 -		$exists = true;
 -		$values = $this->getSelection($control);
 -		$count = count($values);
 -		$required = $this->getRequiredValues();
 -
 -		//if required, check the values
 -		if(!empty($required))
 -		{
 -			if($count < count($required) )
 -				return false;
 -			foreach($required as $require)
 -				$exists = $exists && in_array($require, $values);
 -		}
 -
 -		$min = $this->getMinSelection();
 -		$max = $this->getMaxSelection();
 -
 -		if($min !== -1 && $max !== -1)
 -			return $exists && $count >= $min && $count <= $max;
 -		else if($min === -1 && $max !== -1)
 -			return $exists && $count <= $max;
 -		else if($min !== -1 && $max === -1)
 -			return $exists && $count >= $min;
 -		else
 -			return $exists;
 -	}
 -
 -	/**
 -	 * @param TListControl control to validate
 -	 * @return array number of selected values and its values.
 -	 */
 -	protected function getSelection($control)
 -	{
 -		$values = array();
 -
 -		//get the data
 -		foreach($control->getItems() as $item)
 -		{
 -			if($item->getSelected())
 -				$values[] = $item->getValue();
 -		}
 -		return $values;
 -	}
 -
 -	/**
 -	 * @return array list of required values.
 -	 */
 -	protected function getRequiredValues()
 -	{
 -		$required = array();
 -		$string = $this->getRequiredSelections();
 -		if(!empty($string))
 -			$required = preg_split('/,\s*/', $string);
 -		return $required;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options = parent::getClientScriptOptions();
 -		$control = $this->getValidationTarget();
 -
 -		if(!$control instanceof TListControl)
 -		{
 -			throw new TConfigurationException(
 -				'listcontrolvalidator_invalid_control',
 -				$this->getID(),$this->getControlToValidate(), get_class($control));
 -		}
 -
 -		$min = $this->getMinSelection();
 -		$max = $this->getMaxSelection();
 -		if($min !== -1)
 -			$options['Min']= $min;
 -		if($max !== -1)
 -			$options['Max']= $max;
 -		$required = $this->getRequiredSelections();
 -		if(strlen($required) > 0)
 -			$options['Required']= $required;
 -		$options['TotalItems'] = $control->getItemCount();
 -
 -		return $options;
 -	}
 -}
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TListControlValidator class. + * + * TListControlValidator checks the number of selection and their values + * for a <b>TListControl that allows multiple selection</b>. + * + * You can specify the minimum or maximum (or both) number of selections + * required using the {@link setMinSelection MinSelection} and + * {@link setMaxSelection MaxSelection} properties, respectively. In addition, + * you can specify a comma separated list of required selected values via the + * {@link setRequiredSelections RequiredSelections} property. + * + * Examples + * - At least two selections + * <code> + *	<com:TListBox ID="listbox" SelectionMode="Multiple"> + *		<com:TListItem Text="item1" Value="value1" /> + *		<com:TListItem Text="item2" Value="value2" /> + *		<com:TListItem Text="item3" Value="value3" /> + *	</com:TListBox> + * + *	<com:TListControlValidator + *		ControlToValidate="listbox" + *		MinSelection="2" + *		ErrorMessage="Please select at least 2" /> + * </code> + * - "value1" must be selected <b>and</b> at least 1 other + * <code> + *	<com:TCheckBoxList ID="checkboxes"> + *		<com:TListItem Text="item1" Value="value1" /> + *		<com:TListItem Text="item2" Value="value2" /> + *		<com:TListItem Text="item3" Value="value3" /> + *	</com:TCheckBoxList> + * + *	<com:TListControlValidator + *		ControlToValidate="checkboxes" + *		RequiredSelections="value1" + *		MinSelection="2" + *		ErrorMessage="Please select 'item1' and at least 1 other" /> + * </code> + * + * @author Xiang Wei Zhuo <weizhuo[at]gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TListControlValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TListControlValidator'; +	} + +	/** +	 * @return integer min number of selections. Defaults to -1, meaning not set. +	 */ +	public function getMinSelection() +	{ +		return $this->getViewState('MinSelection',-1); +	} + +	/** +	 * @param integer minimum number of selections. +	 */ +	public function setMinSelection($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			$value=-1; +		$this->setViewState('MinSelection',$value,-1); +	} + +	/** +	 * @return integer max number of selections.  Defaults to -1, meaning not set. +	 */ +	public function getMaxSelection() +	{ +		return $this->getViewState('MaxSelection',-1); +	} + +	/** +	 * @param integer max number of selections. +	 */ +	public function setMaxSelection($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			$value=-1; +		$this->setViewState('MaxSelection',$value,-1); +	} + +	/** +	 * Get a comma separated list of required selected values. +	 * @return string comma separated list of required values. +	 */ +	public function getRequiredSelections() +	{ +		return $this->getViewState('RequiredSelections',''); +	} + +	/** +	 * Set the list of required values, using aa comma separated list. +	 * @param string comma separated list of required values. +	 */ +	public function setRequiredSelections($value) +	{ +		$this->setViewState('RequiredSelections',$value,''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input component changes its data +	 * from the InitialValue or the input component is not given. +	 * @return boolean whether the validation succeeds +	 */ +	protected function evaluateIsValid() +	{ +		$control=$this->getValidationTarget(); + +		$exists = true; +		$values = $this->getSelection($control); +		$count = count($values); +		$required = $this->getRequiredValues(); + +		//if required, check the values +		if(!empty($required)) +		{ +			if($count < count($required) ) +				return false; +			foreach($required as $require) +				$exists = $exists && in_array($require, $values); +		} + +		$min = $this->getMinSelection(); +		$max = $this->getMaxSelection(); + +		if($min !== -1 && $max !== -1) +			return $exists && $count >= $min && $count <= $max; +		else if($min === -1 && $max !== -1) +			return $exists && $count <= $max; +		else if($min !== -1 && $max === -1) +			return $exists && $count >= $min; +		else +			return $exists; +	} + +	/** +	 * @param TListControl control to validate +	 * @return array number of selected values and its values. +	 */ +	protected function getSelection($control) +	{ +		$values = array(); + +		//get the data +		foreach($control->getItems() as $item) +		{ +			if($item->getSelected()) +				$values[] = $item->getValue(); +		} +		return $values; +	} + +	/** +	 * @return array list of required values. +	 */ +	protected function getRequiredValues() +	{ +		$required = array(); +		$string = $this->getRequiredSelections(); +		if(!empty($string)) +			$required = preg_split('/,\s*/', $string); +		return $required; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options = parent::getClientScriptOptions(); +		$control = $this->getValidationTarget(); + +		if(!$control instanceof TListControl) +		{ +			throw new TConfigurationException( +				'listcontrolvalidator_invalid_control', +				$this->getID(),$this->getControlToValidate(), get_class($control)); +		} + +		$min = $this->getMinSelection(); +		$max = $this->getMaxSelection(); +		if($min !== -1) +			$options['Min']= $min; +		if($max !== -1) +			$options['Max']= $max; +		$required = $this->getRequiredSelections(); +		if(strlen($required) > 0) +			$options['Required']= $required; +		$options['TotalItems'] = $control->getItemCount(); + +		return $options; +	} +} diff --git a/framework/Web/UI/WebControls/TListItem.php b/framework/Web/UI/WebControls/TListItem.php index 354aa62a..e80bcafd 100644 --- a/framework/Web/UI/WebControls/TListItem.php +++ b/framework/Web/UI/WebControls/TListItem.php @@ -1,184 +1,184 @@ -<?php
 -/**
 - * TListItem class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TListItem class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TListItem class.
 - *
 - * TListItem represents an item in a list control. Each item has a {@link setText Text}
 - * property and a {@link setValue Value} property. If either one of them is not set,
 - * it will take the value of the other property.
 - * An item can be {@link setSelected Selected} or {@link setEnabled Enabled},
 - * and it can have additional {@link getAttributes Attributes} which may be rendered
 - * if the list control supports so.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TListItem extends TComponent
 -{
 -	/**
 -	 * @var TMap list of custom attributes
 -	 */
 -	private $_attributes=null;
 -	/**
 -	 * @var string text of the item
 -	 */
 -	private $_text;
 -	/**
 -	 * @var string value of the item
 -	 */
 -	private $_value;
 -	/**
 -	 * @var boolean whether the item is enabled
 -	 */
 -	private $_enabled;
 -	/**
 -	 * @var boolean whether the item is selected
 -	 */
 -	private $_selected;
 -
 -	/**
 -	 * Constructor.
 -	 * @param string text of the item
 -	 * @param string value of the item
 -	 * @param boolean whether the item is enabled
 -	 * @param boolean whether the item is selected
 -	 */
 -	public function __construct($text='',$value='',$enabled=true,$selected=false)
 -	{
 -		$this->setText($text);
 -		$this->setValue($value);
 -		$this->setEnabled($enabled);
 -		$this->setSelected($selected);
 -	}
 -
 -	/**
 -	 * @return boolean whether the item is enabled
 -	 */
 -	public function getEnabled()
 -	{
 -		return $this->_enabled;
 -	}
 -
 -	/**
 -	 * @param boolean whether the item is enabled
 -	 */
 -	public function setEnabled($value)
 -	{
 -		$this->_enabled=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * @return boolean whether the item is selected
 -	 */
 -	public function getSelected()
 -	{
 -		return $this->_selected;
 -	}
 -
 -	/**
 -	 * @param boolean whether the item is selected
 -	 */
 -	public function setSelected($value)
 -	{
 -		$this->_selected=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * @return string text of the item
 -	 */
 -	public function getText()
 -	{
 -		return $this->_text===''?$this->_value:$this->_text;
 -	}
 -
 -	/**
 -	 * @param string text of the item
 -	 */
 -	public function setText($value)
 -	{
 -		$this->_text=TPropertyValue::ensureString($value);
 -	}
 -
 -	/**
 -	 * @return string value of the item
 -	 */
 -	public function getValue()
 -	{
 -		return $this->_value===''?$this->_text:$this->_value;
 -	}
 -
 -	/**
 -	 * @param string value of the item
 -	 */
 -	public function setValue($value)
 -	{
 -		$this->_value=TPropertyValue::ensureString($value);
 -	}
 -
 -	/**
 -	 * @return TAttributeCollection custom attributes
 -	 */
 -	public function getAttributes()
 -	{
 -		if(!$this->_attributes)
 -			$this->_attributes=new TAttributeCollection;
 -		return $this->_attributes;
 -	}
 -
 -	/**
 -	 * @return boolean whether the item has any custom attribute
 -	 */
 -	public function getHasAttributes()
 -	{
 -		return $this->_attributes && $this->_attributes->getCount()>0;
 -	}
 -
 -	/**
 -	 * @param string name of the attribute
 -	 * @return boolean whether the named attribute exists
 -	 */
 -	public function hasAttribute($name)
 -	{
 -		return $this->_attributes?$this->_attributes->contains($name):false;
 -	}
 -
 -	/**
 -	 * @return string the named attribute value, null if attribute does not exist
 -	 */
 -	public function getAttribute($name)
 -	{
 -		return $this->_attributes?$this->_attributes->itemAt($name):null;
 -	}
 -
 -	/**
 -	 * @param string attribute name
 -	 * @param string value of the attribute
 -	 */
 -	public function setAttribute($name,$value)
 -	{
 -		$this->getAttributes()->add($name,$value);
 -	}
 -
 -	/**
 -	 * Removes the named attribute.
 -	 * @param string the name of the attribute to be removed.
 -	 * @return string attribute value removed, empty string if attribute does not exist.
 -	 */
 -	public function removeAttribute($name)
 -	{
 -		return $this->_attributes?$this->_attributes->remove($name):null;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TListItem class. + * + * TListItem represents an item in a list control. Each item has a {@link setText Text} + * property and a {@link setValue Value} property. If either one of them is not set, + * it will take the value of the other property. + * An item can be {@link setSelected Selected} or {@link setEnabled Enabled}, + * and it can have additional {@link getAttributes Attributes} which may be rendered + * if the list control supports so. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TListItem extends TComponent +{ +	/** +	 * @var TMap list of custom attributes +	 */ +	private $_attributes=null; +	/** +	 * @var string text of the item +	 */ +	private $_text; +	/** +	 * @var string value of the item +	 */ +	private $_value; +	/** +	 * @var boolean whether the item is enabled +	 */ +	private $_enabled; +	/** +	 * @var boolean whether the item is selected +	 */ +	private $_selected; + +	/** +	 * Constructor. +	 * @param string text of the item +	 * @param string value of the item +	 * @param boolean whether the item is enabled +	 * @param boolean whether the item is selected +	 */ +	public function __construct($text='',$value='',$enabled=true,$selected=false) +	{ +		$this->setText($text); +		$this->setValue($value); +		$this->setEnabled($enabled); +		$this->setSelected($selected); +	} + +	/** +	 * @return boolean whether the item is enabled +	 */ +	public function getEnabled() +	{ +		return $this->_enabled; +	} + +	/** +	 * @param boolean whether the item is enabled +	 */ +	public function setEnabled($value) +	{ +		$this->_enabled=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * @return boolean whether the item is selected +	 */ +	public function getSelected() +	{ +		return $this->_selected; +	} + +	/** +	 * @param boolean whether the item is selected +	 */ +	public function setSelected($value) +	{ +		$this->_selected=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * @return string text of the item +	 */ +	public function getText() +	{ +		return $this->_text===''?$this->_value:$this->_text; +	} + +	/** +	 * @param string text of the item +	 */ +	public function setText($value) +	{ +		$this->_text=TPropertyValue::ensureString($value); +	} + +	/** +	 * @return string value of the item +	 */ +	public function getValue() +	{ +		return $this->_value===''?$this->_text:$this->_value; +	} + +	/** +	 * @param string value of the item +	 */ +	public function setValue($value) +	{ +		$this->_value=TPropertyValue::ensureString($value); +	} + +	/** +	 * @return TAttributeCollection custom attributes +	 */ +	public function getAttributes() +	{ +		if(!$this->_attributes) +			$this->_attributes=new TAttributeCollection; +		return $this->_attributes; +	} + +	/** +	 * @return boolean whether the item has any custom attribute +	 */ +	public function getHasAttributes() +	{ +		return $this->_attributes && $this->_attributes->getCount()>0; +	} + +	/** +	 * @param string name of the attribute +	 * @return boolean whether the named attribute exists +	 */ +	public function hasAttribute($name) +	{ +		return $this->_attributes?$this->_attributes->contains($name):false; +	} + +	/** +	 * @return string the named attribute value, null if attribute does not exist +	 */ +	public function getAttribute($name) +	{ +		return $this->_attributes?$this->_attributes->itemAt($name):null; +	} + +	/** +	 * @param string attribute name +	 * @param string value of the attribute +	 */ +	public function setAttribute($name,$value) +	{ +		$this->getAttributes()->add($name,$value); +	} + +	/** +	 * Removes the named attribute. +	 * @param string the name of the attribute to be removed. +	 * @return string attribute value removed, empty string if attribute does not exist. +	 */ +	public function removeAttribute($name) +	{ +		return $this->_attributes?$this->_attributes->remove($name):null; +	} +} + diff --git a/framework/Web/UI/WebControls/TLiteral.php b/framework/Web/UI/WebControls/TLiteral.php index 423e2d8e..e98d56bb 100644 --- a/framework/Web/UI/WebControls/TLiteral.php +++ b/framework/Web/UI/WebControls/TLiteral.php @@ -1,112 +1,112 @@ -<?php
 -/**
 - * TLiteral class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TLiteral class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TLiteral class
 - *
 - * TLiteral displays a static text on the Web page.
 - * TLiteral is similar to the TLabel control, except that the TLiteral
 - * control does not have style properties (e.g. BackColor, Font, etc.)
 - * You can programmatically control the text displayed in the control by setting
 - * the {@link setText Text} property. The text displayed may be HTML-encoded
 - * if the {@link setEncode Encode} property is set true (defaults to false).
 - *
 - * TLiteral will render the contents enclosed within its component tag
 - * if {@link setText Text} is empty.
 - *
 - * Note, if {@link setEncode Encode} is false, make sure {@link setText Text}
 - * does not contain unwanted characters that may bring security vulnerabilities.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TLiteral extends TControl implements IDataRenderer
 -{
 -	/**
 -	 * @return string the static text of the TLiteral
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the static text of the TLiteral
 -	 * @param string the text to be set
 -	 */
 -	public function setText($value)
 -	{
 -		$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.
 -	 */
 -	public function getEncode()
 -	{
 -		return $this->getViewState('Encode',false);
 -	}
 -
 -	/**
 -	 * @param boolean  whether the rendered text should be HTML-encoded.
 -	 */
 -	public function setEncode($value)
 -	{
 -		$this->setViewState('Encode',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Renders the literal control.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		if(($text=$this->getText())!=='')
 -		{
 -			if($this->getEncode())
 -				$writer->write(THttpUtility::htmlEncode($text));
 -			else
 -				$writer->write($text);
 -		}
 -		else
 -			parent::render($writer);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TLiteral class + * + * TLiteral displays a static text on the Web page. + * TLiteral is similar to the TLabel control, except that the TLiteral + * control does not have style properties (e.g. BackColor, Font, etc.) + * You can programmatically control the text displayed in the control by setting + * the {@link setText Text} property. The text displayed may be HTML-encoded + * if the {@link setEncode Encode} property is set true (defaults to false). + * + * TLiteral will render the contents enclosed within its component tag + * if {@link setText Text} is empty. + * + * Note, if {@link setEncode Encode} is false, make sure {@link setText Text} + * does not contain unwanted characters that may bring security vulnerabilities. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TLiteral extends TControl implements IDataRenderer +{ +	/** +	 * @return string the static text of the TLiteral +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the static text of the TLiteral +	 * @param string the text to be set +	 */ +	public function setText($value) +	{ +		$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. +	 */ +	public function getEncode() +	{ +		return $this->getViewState('Encode',false); +	} + +	/** +	 * @param boolean  whether the rendered text should be HTML-encoded. +	 */ +	public function setEncode($value) +	{ +		$this->setViewState('Encode',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Renders the literal control. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function render($writer) +	{ +		if(($text=$this->getText())!=='') +		{ +			if($this->getEncode()) +				$writer->write(THttpUtility::htmlEncode($text)); +			else +				$writer->write($text); +		} +		else +			parent::render($writer); +	} +} + diff --git a/framework/Web/UI/WebControls/TLiteralColumn.php b/framework/Web/UI/WebControls/TLiteralColumn.php index 5b1353fc..48cbe013 100644 --- a/framework/Web/UI/WebControls/TLiteralColumn.php +++ b/framework/Web/UI/WebControls/TLiteralColumn.php @@ -1,154 +1,154 @@ -<?php
 -/**
 - * TLiteralColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TLiteralColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id: TLiteralColumn.php 1397 2006-09-07 07:55:53Z wei $
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -
 -/**
 - * TLiteralColumn class
 - *
 - * TLiteralColumn represents a static text column that is bound to a field in a data source.
 - * The cells in the column will be displayed with static texts using the data indexed by
 - * {@link setDataField DataField}. You can customize the display by
 - * setting {@link setDataFormatString DataFormatString}.
 - *
 - * If {@link setDataField DataField} is not specified, the cells will be filled
 - * with {@link setText Text}.
 - *
 - * If {@link setEncode Encode} is true, the static texts will be HTML-encoded.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id: TLiteralColumn.php 1397 2006-09-07 07:55:53Z wei $
 - * @package System.Web.UI.WebControls
 - * @since 3.0.5
 - */
 -class TLiteralColumn extends TDataGridColumn
 -{
 -	/**
 -	 * @return string the field name from the data source to bind to the column
 -	 */
 -	public function getDataField()
 -	{
 -		return $this->getViewState('DataField','');
 -	}
 -
 -	/**
 -	 * @param string the field name from the data source to bind to the column
 -	 */
 -	public function setDataField($value)
 -	{
 -		$this->setViewState('DataField',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the formatting string used to control how the bound data will be displayed.
 -	 */
 -	public function getDataFormatString()
 -	{
 -		return $this->getViewState('DataFormatString','');
 -	}
 -
 -	/**
 -	 * @param string the formatting string used to control how the bound data will be displayed.
 -	 */
 -	public function setDataFormatString($value)
 -	{
 -		$this->setViewState('DataFormatString',$value,'');
 -	}
 -
 -	/**
 -	 * @return string static text to be displayed in the column. Defaults to empty.
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * @param string static text to be displayed in the column.
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether the rendered text should be HTML-encoded. Defaults to false.
 -	 */
 -	public function getEncode()
 -	{
 -		return $this->getViewState('Encode',false);
 -	}
 -
 -	/**
 -	 * @param boolean  whether the rendered text should be HTML-encoded.
 -	 */
 -	public function setEncode($value)
 -	{
 -		$this->setViewState('Encode',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::EditItem || $itemType===TListItemType::SelectedItem)
 -		{
 -			if($this->getDataField()!=='')
 -				$cell->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -			else
 -			{
 -				if(($dataField=$this->getDataField())!=='')
 -					$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -				else
 -				{
 -					$text=$this->getText();
 -					if($this->getEncode())
 -						$text=THttpUtility::htmlEncode($text);
 -					$cell->setText($text);
 -				}
 -			}
 -		}
 -		else
 -			parent::initializeCell($cell,$columnIndex,$itemType);
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		$item=$sender->getNamingContainer();
 -		$data=$item->getData();
 -		$formatString=$this->getDataFormatString();
 -		if(($field=$this->getDataField())!=='')
 -			$value=$this->formatDataValue($formatString,$this->getDataFieldValue($data,$field));
 -		else
 -			$value=$this->formatDataValue($formatString,$data);
 -		if($sender instanceof TTableCell)
 -		{
 -			if($this->getEncode())
 -				$value=THttpUtility::htmlEncode($value);
 -			$sender->setText($value);
 -		}
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id: TLiteralColumn.php 1397 2006-09-07 07:55:53Z wei $ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); + +/** + * TLiteralColumn class + * + * TLiteralColumn represents a static text column that is bound to a field in a data source. + * The cells in the column will be displayed with static texts using the data indexed by + * {@link setDataField DataField}. You can customize the display by + * setting {@link setDataFormatString DataFormatString}. + * + * If {@link setDataField DataField} is not specified, the cells will be filled + * with {@link setText Text}. + * + * If {@link setEncode Encode} is true, the static texts will be HTML-encoded. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: TLiteralColumn.php 1397 2006-09-07 07:55:53Z wei $ + * @package System.Web.UI.WebControls + * @since 3.0.5 + */ +class TLiteralColumn extends TDataGridColumn +{ +	/** +	 * @return string the field name from the data source to bind to the column +	 */ +	public function getDataField() +	{ +		return $this->getViewState('DataField',''); +	} + +	/** +	 * @param string the field name from the data source to bind to the column +	 */ +	public function setDataField($value) +	{ +		$this->setViewState('DataField',$value,''); +	} + +	/** +	 * @return string the formatting string used to control how the bound data will be displayed. +	 */ +	public function getDataFormatString() +	{ +		return $this->getViewState('DataFormatString',''); +	} + +	/** +	 * @param string the formatting string used to control how the bound data will be displayed. +	 */ +	public function setDataFormatString($value) +	{ +		$this->setViewState('DataFormatString',$value,''); +	} + +	/** +	 * @return string static text to be displayed in the column. Defaults to empty. +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * @param string static text to be displayed in the column. +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value,''); +	} + +	/** +	 * @return boolean whether the rendered text should be HTML-encoded. Defaults to false. +	 */ +	public function getEncode() +	{ +		return $this->getViewState('Encode',false); +	} + +	/** +	 * @param boolean  whether the rendered text should be HTML-encoded. +	 */ +	public function setEncode($value) +	{ +		$this->setViewState('Encode',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::EditItem || $itemType===TListItemType::SelectedItem) +		{ +			if($this->getDataField()!=='') +				$cell->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +			else +			{ +				if(($dataField=$this->getDataField())!=='') +					$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +				else +				{ +					$text=$this->getText(); +					if($this->getEncode()) +						$text=THttpUtility::htmlEncode($text); +					$cell->setText($text); +				} +			} +		} +		else +			parent::initializeCell($cell,$columnIndex,$itemType); +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		$item=$sender->getNamingContainer(); +		$data=$item->getData(); +		$formatString=$this->getDataFormatString(); +		if(($field=$this->getDataField())!=='') +			$value=$this->formatDataValue($formatString,$this->getDataFieldValue($data,$field)); +		else +			$value=$this->formatDataValue($formatString,$data); +		if($sender instanceof TTableCell) +		{ +			if($this->getEncode()) +				$value=THttpUtility::htmlEncode($value); +			$sender->setText($value); +		} +	} +} + diff --git a/framework/Web/UI/WebControls/TMarkdown.php b/framework/Web/UI/WebControls/TMarkdown.php index 3aa1c9be..726a1ebe 100644 --- a/framework/Web/UI/WebControls/TMarkdown.php +++ b/framework/Web/UI/WebControls/TMarkdown.php @@ -1,75 +1,75 @@ -<?php
 -/**
 - * TMarkdown class file
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TMarkdown class file + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TTextHighlighter and MarkdownParser classes
 - */
 -Prado::using('System.Web.UI.WebControls.TTextHighlighter');
 -Prado::using('System.3rdParty.Markdown.MarkdownParser');
 -
 -/**
 - * TMarkdown class
 - *
 - * TMarkdown is a control that produces HTML from code with markdown syntax.
 - *
 - * Markdown is a text-to-HTML conversion tool for web writers. Markdown allows
 - * you to write using an easy-to-read, easy-to-write plain text format, then
 - * convert it to structurally valid XHTML (or HTML).
 - * Further documentation regarding Markdown can be found at
 - * http://daringfireball.net/projects/markdown/
 - *
 - * To use TMarkdown, simply enclose the content to be rendered within
 - * the body of TMarkdown in a template.
 - *
 - * See http://www.pradosoft.com/demos/quickstart/?page=Markdown for
 - * details on the Markdown syntax usage.
 - *
 - * TMarkdown also performs syntax highlighting for code blocks whose language
 - * is recognized by {@link TTextHighlighter}.
 - * The language of a code block must be specified in the first line of the block
 - * and enclosed within a pair of square brackets (e.g. [php]).
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.1
 - */
 -class TMarkdown extends TTextHighlighter
 -{
 -	/**
 -	 * Processes a text string.
 -	 * This method is required by the parent class.
 -	 * @param string text string to be processed
 -	 * @return string the processed text result
 -	 */
 -	public function processText($text)
 -	{
 -		$renderer = new MarkdownParser;
 -		$result = $renderer->parse($text);
 -		return preg_replace_callback(
 -				'/<pre><code>\[\s*(\w+)\s*\]\n+((.|\n)*?)\s*<\\/code><\\/pre>/im',
 -				array($this, 'highlightCode'), $result);
 -	}
 -
 -	/**
 -	 * Highlights source code using TTextHighlighter
 -	 * @param array matches of code blocks
 -	 * @return string highlighted code.
 -	 */
 -	protected function highlightCode($matches)
 -	{
 -		$text = html_entity_decode($matches[2],ENT_QUOTES,'UTF-8');
 -		$this->setLanguage($matches[1]);
 -		return parent::processText($text);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TTextHighlighter and MarkdownParser classes + */ +Prado::using('System.Web.UI.WebControls.TTextHighlighter'); +Prado::using('System.3rdParty.Markdown.MarkdownParser'); + +/** + * TMarkdown class + * + * TMarkdown is a control that produces HTML from code with markdown syntax. + * + * Markdown is a text-to-HTML conversion tool for web writers. Markdown allows + * you to write using an easy-to-read, easy-to-write plain text format, then + * convert it to structurally valid XHTML (or HTML). + * Further documentation regarding Markdown can be found at + * http://daringfireball.net/projects/markdown/ + * + * To use TMarkdown, simply enclose the content to be rendered within + * the body of TMarkdown in a template. + * + * See http://www.pradosoft.com/demos/quickstart/?page=Markdown for + * details on the Markdown syntax usage. + * + * TMarkdown also performs syntax highlighting for code blocks whose language + * is recognized by {@link TTextHighlighter}. + * The language of a code block must be specified in the first line of the block + * and enclosed within a pair of square brackets (e.g. [php]). + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.1 + */ +class TMarkdown extends TTextHighlighter +{ +	/** +	 * Processes a text string. +	 * This method is required by the parent class. +	 * @param string text string to be processed +	 * @return string the processed text result +	 */ +	public function processText($text) +	{ +		$renderer = new MarkdownParser; +		$result = $renderer->parse($text); +		return preg_replace_callback( +				'/<pre><code>\[\s*(\w+)\s*\]\n+((.|\n)*?)\s*<\\/code><\\/pre>/im', +				array($this, 'highlightCode'), $result); +	} + +	/** +	 * Highlights source code using TTextHighlighter +	 * @param array matches of code blocks +	 * @return string highlighted code. +	 */ +	protected function highlightCode($matches) +	{ +		$text = html_entity_decode($matches[2],ENT_QUOTES,'UTF-8'); +		$this->setLanguage($matches[1]); +		return parent::processText($text); +	} +} + diff --git a/framework/Web/UI/WebControls/TMultiView.php b/framework/Web/UI/WebControls/TMultiView.php index 81d404b2..0c40cd06 100644 --- a/framework/Web/UI/WebControls/TMultiView.php +++ b/framework/Web/UI/WebControls/TMultiView.php @@ -1,378 +1,378 @@ -<?php
 -/**
 - * TMultiView and TView class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TMultiView class
 - *
 - * TMultiView serves as a container for a group of {@link TView} controls.
 - * The view collection can be retrieved by {@link getViews Views}.
 - * Each view contains child controls. TMultiView determines which view and its
 - * child controls are visible. At any time, at most one view is visible (called
 - * active). To make a view active, set {@link setActiveView ActiveView} or
 - * {@link setActiveViewIndex ActiveViewIndex}.
 - *
 - * TMultiView also responds to specific command events raised from button controls
 - * contained in current active view. A command event with name 'NextView'
 - * will cause TMultiView to make the next available view active.
 - * Other command names recognized by TMultiView include
 - * - PreviousView : switch to previous view
 - * - SwitchViewID : switch to a view by its ID path
 - * - SwitchViewIndex : switch to a view by its index in the {@link getViews Views} collection.
 - *
 - * TMultiView raises {@link OnActiveViewChanged OnActiveViewChanged} event
 - * when its active view is changed during a postback.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TMultiView extends TControl
 -{
 -	const CMD_NEXTVIEW='NextView';
 -	const CMD_PREVIOUSVIEW='PreviousView';
 -	const CMD_SWITCHVIEWID='SwitchViewID';
 -	const CMD_SWITCHVIEWINDEX='SwitchViewIndex';
 -	private $_cachedActiveViewIndex=-1;
 -	private $_ignoreBubbleEvents=false;
 -
 -	/**
 -	 * Processes an object that is created during parsing template.
 -	 * This method overrides the parent implementation by adding only {@link TView}
 -	 * controls as children.
 -	 * @param string|TComponent text string or component parsed and instantiated in template
 -	 * @see createdOnTemplate
 -	 * @throws TConfigurationException if controls other than {@link TView} is being added
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TView)
 -			$this->getControls()->add($object);
 -		else if(!is_string($object))
 -			throw new TConfigurationException('multiview_view_required');
 -	}
 -
 -	/**
 -	 * Creates a control collection object that is to be used to hold child controls
 -	 * @return TViewCollection control collection
 -	 */
 -	protected function createControlCollection()
 -	{
 -		return new TViewCollection($this);
 -	}
 -
 -	/**
 -	 * @return integer the zero-based index of the current view in the view collection. -1 if no active view. Default is -1.
 -	 */
 -	public function getActiveViewIndex()
 -	{
 -		if($this->_cachedActiveViewIndex>-1)
 -			return $this->_cachedActiveViewIndex;
 -		else
 -			return $this->getControlState('ActiveViewIndex',-1);
 -	}
 -
 -	/**
 -	 * @param integer the zero-based index of the current view in the view collection. -1 if no active view.
 -	 * @throws TInvalidDataValueException if the view index is invalid
 -	 */
 -	public function setActiveViewIndex($value)
 -	{
 -		if(($index=TPropertyValue::ensureInteger($value))<0)
 -			$index=-1;
 -		$views=$this->getViews();
 -		$count=$views->getCount();
 -		if($count===0 && $this->getControlStage()<TControl::CS_CHILD_INITIALIZED)
 -			$this->_cachedActiveViewIndex=$index;
 -		else if($index<$count)
 -		{
 -			$this->setControlState('ActiveViewIndex',$index,-1);
 -			$this->_cachedActiveViewIndex=-1;
 -			if($index>=0)
 -				$this->activateView($views->itemAt($index),true);
 -		}
 -		else
 -			throw new TInvalidDataValueException('multiview_activeviewindex_invalid',$index);
 -	}
 -
 -	/**
 -	 * @return TView the currently active view, null if no active view
 -	 * @throws TInvalidDataValueException if the current active view index is invalid
 -	 */
 -	public function getActiveView()
 -	{
 -		$index=$this->getActiveViewIndex();
 -		$views=$this->getViews();
 -		if($index>=$views->getCount())
 -			throw new TInvalidDataValueException('multiview_activeviewindex_invalid',$index);
 -		if($index<0)
 -			return null;
 -		$view=$views->itemAt($index);
 -		if(!$view->getActive())
 -			$this->activateView($view,false);
 -		return $view;
 -	}
 -
 -	/**
 -	 * @param TView the view to be activated
 -	 * @throws TInvalidOperationException if the view is not in the view collection
 -	 */
 -	public function setActiveView($view)
 -	{
 -		if(($index=$this->getViews()->indexOf($view))>=0)
 -			$this->setActiveViewIndex($index);
 -		else
 -			throw new TInvalidOperationException('multiview_view_inexistent');
 -	}
 -
 -	/**
 -	 * Activates the specified view.
 -	 * If there is any view currently active, it will be deactivated.
 -	 * @param TView the view to be activated
 -	 * @param boolean whether to trigger OnActiveViewChanged event.
 -	 */
 -	protected function activateView($view,$triggerViewChangedEvent=true)
 -	{
 -		if($view->getActive())
 -			return;
 -		$triggerEvent=$triggerViewChangedEvent && ($this->getControlStage()>=TControl::CS_STATE_LOADED || ($this->getPage() && !$this->getPage()->getIsPostBack()));
 -		foreach($this->getViews() as $v)
 -		{
 -			if($v===$view)
 -			{
 -				$view->setActive(true);
 -				if($triggerEvent)
 -				{
 -					$view->onActivate(null);
 -					$this->onActiveViewChanged(null);
 -				}
 -			}
 -			else if($v->getActive())
 -			{
 -				$v->setActive(false);
 -				if($triggerEvent)
 -					$v->onDeactivate(null);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * @return TViewCollection the view collection
 -	 */
 -	public function getViews()
 -	{
 -		return $this->getControls();
 -	}
 -
 -	/**
 -	 * Makes the multiview ignore all bubbled events.
 -	 * This is method is used internally by framework and control
 -	 * developers.
 -	 */
 -	public function ignoreBubbleEvents()
 -	{
 -		$this->_ignoreBubbleEvents=true;
 -	}
 -
 -	/**
 -	 * Initializes the active view if any.
 -	 * This method overrides the parent implementation.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onInit($param)
 -	{
 -		parent::onInit($param);
 -		if($this->_cachedActiveViewIndex>=0)
 -			$this->setActiveViewIndex($this->_cachedActiveViewIndex);
 -	}
 -
 -	/**
 -	 * Raises <b>OnActiveViewChanged</b> event.
 -	 * The event is raised when the currently active view is changed to a new one
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onActiveViewChanged($param)
 -	{
 -		$this->raiseEvent('OnActiveViewChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Processes the events bubbled from child controls.
 -	 * The method handles view-related command events.
 -	 * @param TControl sender of the event
 -	 * @param mixed event parameter
 -	 * @return boolean whether this event is handled
 -	 */
 -	public function bubbleEvent($sender,$param)
 -	{
 -		if(!$this->_ignoreBubbleEvents && ($param instanceof TCommandEventParameter))
 -		{
 -			switch($param->getCommandName())
 -			{
 -				case self::CMD_NEXTVIEW:
 -					if(($index=$this->getActiveViewIndex())<$this->getViews()->getCount()-1)
 -						$this->setActiveViewIndex($index+1);
 -					else
 -						$this->setActiveViewIndex(-1);
 -					return true;
 -				case self::CMD_PREVIOUSVIEW:
 -					if(($index=$this->getActiveViewIndex())>=0)
 -						$this->setActiveViewIndex($index-1);
 -					return true;
 -				case self::CMD_SWITCHVIEWID:
 -					$view=$this->findControl($viewID=$param->getCommandParameter());
 -					if($view!==null && $view->getParent()===$this)
 -					{
 -						$this->setActiveView($view);
 -						return true;
 -					}
 -					else
 -						throw new TInvalidDataValueException('multiview_viewid_invalid', $viewID);
 -				case self::CMD_SWITCHVIEWINDEX:
 -					$index=TPropertyValue::ensureInteger($param->getCommandParameter());
 -					$this->setActiveViewIndex($index);
 -					return true;
 -			}
 -		}
 -		return false;
 -	}
 -
 -	/**
 -	 * Loads state into the wizard.
 -	 * This method is invoked by the framework when the control state is being saved.
 -	 */
 -	public function loadState()
 -	{
 -		// a dummy call to ensure the view is activated
 -		$this->getActiveView();
 -	}
 -
 -	/**
 -	 * Renders the currently active view.
 -	 * @param THtmlWriter the writer for the rendering purpose.
 -	 */
 -	public function render($writer)
 -	{
 -		if(($view=$this->getActiveView())!==null)
 -			$view->renderControl($writer);
 -	}
 -}
 -
 -/**
 - * TViewCollection class.
 - * TViewCollection represents a collection that only takes {@link TView} instances
 - * as collection elements.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TViewCollection extends TControlCollection
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by ensuring only {@link TView}
 -	 * controls be added into the collection.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is neither a string nor a TControl.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TView)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('viewcollection_view_required');
 -	}
 -}
 -
 -/**
 - * TView class
 - *
 - * TView is a container for a group of controls. TView must be contained
 - * within a {@link TMultiView} control in which only one view can be active
 - * at one time.
 - *
 - * To activate a view, set {@link setActive Active} to true.
 - * When a view is activated, it raises {@link onActivate OnActivate} event;
 - * and when a view is deactivated, it raises {@link onDeactivate OnDeactivate}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TView extends TControl
 -{
 -	private $_active=false;
 -
 -	/**
 -	 * Raises <b>OnActivate</b> event.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onActivate($param)
 -	{
 -		$this->raiseEvent('OnActivate',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnDeactivate</b> event.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onDeactivate($param)
 -	{
 -		$this->raiseEvent('OnDeactivate',$this,$param);
 -	}
 -
 -	/**
 -	 * @return boolean whether this view is active. Defaults to false.
 -	 */
 -	public function getActive()
 -	{
 -		return $this->_active;
 -	}
 -
 -	/**
 -	 * @param boolean whether this view is active.
 -	 */
 -	public function setActive($value)
 -	{
 -		$value=TPropertyValue::ensureBoolean($value);
 -		$this->_active=$value;
 -		parent::setVisible($value);
 -	}
 -
 -	/**
 -	 * @param boolean whether the parents should also be checked if visible
 -	 * @return boolean whether this view is visible.
 -	 * The view is visible if it is active and its parent is visible.
 -	 */
 -	public function getVisible($checkParents=true)
 -	{
 -		if(($parent=$this->getParent())===null)
 -			return $this->getActive();
 -		else if($this->getActive())
 -			return $parent->getVisible($checkParents);
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @param boolean
 -	 * @throws TInvalidOperationException whenever this method is invoked.
 -	 */
 -	public function setVisible($value)
 -	{
 -		throw new TInvalidOperationException('view_visible_readonly');
 -	}
 -}
 -
 +<?php +/** + * TMultiView and TView class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TMultiView class + * + * TMultiView serves as a container for a group of {@link TView} controls. + * The view collection can be retrieved by {@link getViews Views}. + * Each view contains child controls. TMultiView determines which view and its + * child controls are visible. At any time, at most one view is visible (called + * active). To make a view active, set {@link setActiveView ActiveView} or + * {@link setActiveViewIndex ActiveViewIndex}. + * + * TMultiView also responds to specific command events raised from button controls + * contained in current active view. A command event with name 'NextView' + * will cause TMultiView to make the next available view active. + * Other command names recognized by TMultiView include + * - PreviousView : switch to previous view + * - SwitchViewID : switch to a view by its ID path + * - SwitchViewIndex : switch to a view by its index in the {@link getViews Views} collection. + * + * TMultiView raises {@link OnActiveViewChanged OnActiveViewChanged} event + * when its active view is changed during a postback. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TMultiView extends TControl +{ +	const CMD_NEXTVIEW='NextView'; +	const CMD_PREVIOUSVIEW='PreviousView'; +	const CMD_SWITCHVIEWID='SwitchViewID'; +	const CMD_SWITCHVIEWINDEX='SwitchViewIndex'; +	private $_cachedActiveViewIndex=-1; +	private $_ignoreBubbleEvents=false; + +	/** +	 * Processes an object that is created during parsing template. +	 * This method overrides the parent implementation by adding only {@link TView} +	 * controls as children. +	 * @param string|TComponent text string or component parsed and instantiated in template +	 * @see createdOnTemplate +	 * @throws TConfigurationException if controls other than {@link TView} is being added +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TView) +			$this->getControls()->add($object); +		else if(!is_string($object)) +			throw new TConfigurationException('multiview_view_required'); +	} + +	/** +	 * Creates a control collection object that is to be used to hold child controls +	 * @return TViewCollection control collection +	 */ +	protected function createControlCollection() +	{ +		return new TViewCollection($this); +	} + +	/** +	 * @return integer the zero-based index of the current view in the view collection. -1 if no active view. Default is -1. +	 */ +	public function getActiveViewIndex() +	{ +		if($this->_cachedActiveViewIndex>-1) +			return $this->_cachedActiveViewIndex; +		else +			return $this->getControlState('ActiveViewIndex',-1); +	} + +	/** +	 * @param integer the zero-based index of the current view in the view collection. -1 if no active view. +	 * @throws TInvalidDataValueException if the view index is invalid +	 */ +	public function setActiveViewIndex($value) +	{ +		if(($index=TPropertyValue::ensureInteger($value))<0) +			$index=-1; +		$views=$this->getViews(); +		$count=$views->getCount(); +		if($count===0 && $this->getControlStage()<TControl::CS_CHILD_INITIALIZED) +			$this->_cachedActiveViewIndex=$index; +		else if($index<$count) +		{ +			$this->setControlState('ActiveViewIndex',$index,-1); +			$this->_cachedActiveViewIndex=-1; +			if($index>=0) +				$this->activateView($views->itemAt($index),true); +		} +		else +			throw new TInvalidDataValueException('multiview_activeviewindex_invalid',$index); +	} + +	/** +	 * @return TView the currently active view, null if no active view +	 * @throws TInvalidDataValueException if the current active view index is invalid +	 */ +	public function getActiveView() +	{ +		$index=$this->getActiveViewIndex(); +		$views=$this->getViews(); +		if($index>=$views->getCount()) +			throw new TInvalidDataValueException('multiview_activeviewindex_invalid',$index); +		if($index<0) +			return null; +		$view=$views->itemAt($index); +		if(!$view->getActive()) +			$this->activateView($view,false); +		return $view; +	} + +	/** +	 * @param TView the view to be activated +	 * @throws TInvalidOperationException if the view is not in the view collection +	 */ +	public function setActiveView($view) +	{ +		if(($index=$this->getViews()->indexOf($view))>=0) +			$this->setActiveViewIndex($index); +		else +			throw new TInvalidOperationException('multiview_view_inexistent'); +	} + +	/** +	 * Activates the specified view. +	 * If there is any view currently active, it will be deactivated. +	 * @param TView the view to be activated +	 * @param boolean whether to trigger OnActiveViewChanged event. +	 */ +	protected function activateView($view,$triggerViewChangedEvent=true) +	{ +		if($view->getActive()) +			return; +		$triggerEvent=$triggerViewChangedEvent && ($this->getControlStage()>=TControl::CS_STATE_LOADED || ($this->getPage() && !$this->getPage()->getIsPostBack())); +		foreach($this->getViews() as $v) +		{ +			if($v===$view) +			{ +				$view->setActive(true); +				if($triggerEvent) +				{ +					$view->onActivate(null); +					$this->onActiveViewChanged(null); +				} +			} +			else if($v->getActive()) +			{ +				$v->setActive(false); +				if($triggerEvent) +					$v->onDeactivate(null); +			} +		} +	} + +	/** +	 * @return TViewCollection the view collection +	 */ +	public function getViews() +	{ +		return $this->getControls(); +	} + +	/** +	 * Makes the multiview ignore all bubbled events. +	 * This is method is used internally by framework and control +	 * developers. +	 */ +	public function ignoreBubbleEvents() +	{ +		$this->_ignoreBubbleEvents=true; +	} + +	/** +	 * Initializes the active view if any. +	 * This method overrides the parent implementation. +	 * @param TEventParameter event parameter +	 */ +	public function onInit($param) +	{ +		parent::onInit($param); +		if($this->_cachedActiveViewIndex>=0) +			$this->setActiveViewIndex($this->_cachedActiveViewIndex); +	} + +	/** +	 * Raises <b>OnActiveViewChanged</b> event. +	 * The event is raised when the currently active view is changed to a new one +	 * @param TEventParameter event parameter +	 */ +	public function onActiveViewChanged($param) +	{ +		$this->raiseEvent('OnActiveViewChanged',$this,$param); +	} + +	/** +	 * Processes the events bubbled from child controls. +	 * The method handles view-related command events. +	 * @param TControl sender of the event +	 * @param mixed event parameter +	 * @return boolean whether this event is handled +	 */ +	public function bubbleEvent($sender,$param) +	{ +		if(!$this->_ignoreBubbleEvents && ($param instanceof TCommandEventParameter)) +		{ +			switch($param->getCommandName()) +			{ +				case self::CMD_NEXTVIEW: +					if(($index=$this->getActiveViewIndex())<$this->getViews()->getCount()-1) +						$this->setActiveViewIndex($index+1); +					else +						$this->setActiveViewIndex(-1); +					return true; +				case self::CMD_PREVIOUSVIEW: +					if(($index=$this->getActiveViewIndex())>=0) +						$this->setActiveViewIndex($index-1); +					return true; +				case self::CMD_SWITCHVIEWID: +					$view=$this->findControl($viewID=$param->getCommandParameter()); +					if($view!==null && $view->getParent()===$this) +					{ +						$this->setActiveView($view); +						return true; +					} +					else +						throw new TInvalidDataValueException('multiview_viewid_invalid', $viewID); +				case self::CMD_SWITCHVIEWINDEX: +					$index=TPropertyValue::ensureInteger($param->getCommandParameter()); +					$this->setActiveViewIndex($index); +					return true; +			} +		} +		return false; +	} + +	/** +	 * Loads state into the wizard. +	 * This method is invoked by the framework when the control state is being saved. +	 */ +	public function loadState() +	{ +		// a dummy call to ensure the view is activated +		$this->getActiveView(); +	} + +	/** +	 * Renders the currently active view. +	 * @param THtmlWriter the writer for the rendering purpose. +	 */ +	public function render($writer) +	{ +		if(($view=$this->getActiveView())!==null) +			$view->renderControl($writer); +	} +} + +/** + * TViewCollection class. + * TViewCollection represents a collection that only takes {@link TView} instances + * as collection elements. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TViewCollection extends TControlCollection +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by ensuring only {@link TView} +	 * controls be added into the collection. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is neither a string nor a TControl. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TView) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('viewcollection_view_required'); +	} +} + +/** + * TView class + * + * TView is a container for a group of controls. TView must be contained + * within a {@link TMultiView} control in which only one view can be active + * at one time. + * + * To activate a view, set {@link setActive Active} to true. + * When a view is activated, it raises {@link onActivate OnActivate} event; + * and when a view is deactivated, it raises {@link onDeactivate OnDeactivate}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TView extends TControl +{ +	private $_active=false; + +	/** +	 * Raises <b>OnActivate</b> event. +	 * @param TEventParameter event parameter +	 */ +	public function onActivate($param) +	{ +		$this->raiseEvent('OnActivate',$this,$param); +	} + +	/** +	 * Raises <b>OnDeactivate</b> event. +	 * @param TEventParameter event parameter +	 */ +	public function onDeactivate($param) +	{ +		$this->raiseEvent('OnDeactivate',$this,$param); +	} + +	/** +	 * @return boolean whether this view is active. Defaults to false. +	 */ +	public function getActive() +	{ +		return $this->_active; +	} + +	/** +	 * @param boolean whether this view is active. +	 */ +	public function setActive($value) +	{ +		$value=TPropertyValue::ensureBoolean($value); +		$this->_active=$value; +		parent::setVisible($value); +	} + +	/** +	 * @param boolean whether the parents should also be checked if visible +	 * @return boolean whether this view is visible. +	 * The view is visible if it is active and its parent is visible. +	 */ +	public function getVisible($checkParents=true) +	{ +		if(($parent=$this->getParent())===null) +			return $this->getActive(); +		else if($this->getActive()) +			return $parent->getVisible($checkParents); +		else +			return false; +	} + +	/** +	 * @param boolean +	 * @throws TInvalidOperationException whenever this method is invoked. +	 */ +	public function setVisible($value) +	{ +		throw new TInvalidOperationException('view_visible_readonly'); +	} +} + diff --git a/framework/Web/UI/WebControls/TOutputCache.php b/framework/Web/UI/WebControls/TOutputCache.php index 64e4ff42..cc79e76f 100644 --- a/framework/Web/UI/WebControls/TOutputCache.php +++ b/framework/Web/UI/WebControls/TOutputCache.php @@ -1,621 +1,621 @@ -<?php
 -/**
 - * TOutputCache class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TOutputCache class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TOutputCache class.
 - *
 - * TOutputCache enables caching a portion of a Web page, also known as
 - * partial caching. The content being cached can be either static or
 - * dynamic.
 - *
 - * To use TOutputCache, simply enclose the content to be cached
 - * within the TOutputCache component tag on a template, e.g.,
 - * <code>
 - * <com:TOutputCache>
 - *   content to be cached
 - * </com:TOutputCache>
 - * </code>
 - * where content to be cached can be static text and/or component tags.
 - *
 - * The validity of the cached content is determined based on two factors:
 - * the {@link setDuration Duration} and the cache dependency.
 - * The former specifies the number of seconds that the data can remain
 - * valid in cache (defaults to 60s), while the latter specifies conditions
 - * that the cached data depends on. If a dependency changes,
 - * (e.g. relevant data in DB are updated), the cached data will be invalidated.
 - *
 - * There are two ways to specify cache dependency. One may write event handlers
 - * to respond to the {@link onCheckDependency OnCheckDependency} event and set
 - * the event parameter's {@link TOutputCacheCheckDependencyEventParameter::getIsValid IsValid}
 - * property to indicate whether the cached data remains valid or not.
 - * One can also extend TOutputCache and override its {@link getCacheDependency}
 - * function. While the former is easier to use, the latter offers more extensibility.
 - *
 - * The content fetched from cache may be variated with respect to
 - * some parameters. It supports variation with respect to request parameters,
 - * which is specified by {@link setVaryByParam VaryByParam} property.
 - * If a specified request parameter is different, a different version of
 - * cached content is used. This is extremely useful if a page's content
 - * may be variated according to some GET parameters.
 - * The content being cached may also be variated with user sessions if
 - * {@link setVaryBySession VaryBySession} is set true.
 - * To variate the cached content by other factors, override {@link calculateCacheKey()} method.
 - *
 - * Output caches can be nested. An outer cache takes precedence over an
 - * inner cache. This means, if the content cached by the inner cache expires
 - * or is invalidated, while that by the outer cache not, the outer cached
 - * content will be used.
 - *
 - * Note, TOutputCache is effective only for non-postback page requests
 - * and when cache module is enabled.
 - *
 - * Do not attempt to address child controls of TOutputCache when the cached
 - * content is to be used. Use {@link getContentCached ContentCached} property
 - * to determine whether the content is cached or not.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1
 - */
 -class TOutputCache extends TControl implements INamingContainer
 -{
 -	const CACHE_ID_PREFIX='prado:outputcache';
 -	private $_cacheModuleID='';
 -	private $_dataCached=false;
 -	private $_cacheAvailable=false;
 -	private $_cacheChecked=false;
 -	private $_cacheKey=null;
 -	private $_duration=60;
 -	private $_cache=null;
 -	private $_contents;
 -	private $_state;
 -	private $_actions=array();
 -	private $_varyByParam='';
 -	private $_keyPrefix='';
 -	private $_varyBySession=false;
 -	private $_cachePostBack=false;
 -	private $_cacheTime=0;
 -
 -	/**
 -	 * Returns a value indicating whether body contents are allowed for this control.
 -	 * This method overrides the parent implementation by checking if cached
 -	 * content is available or not. If yes, it returns false, otherwise true.
 -	 * @param boolean whether body contents are allowed for this control.
 -	 */
 -	public function getAllowChildControls()
 -	{
 -		$this->determineCacheability();
 -		return !$this->_dataCached;
 -	}
 -
 -	private function determineCacheability()
 -	{
 -		if(!$this->_cacheChecked)
 -		{
 -			$this->_cacheChecked=true;
 -			if($this->_duration>0 && ($this->_cachePostBack || !$this->getPage()->getIsPostBack()))
 -			{
 -				if($this->_cacheModuleID!=='')
 -				{
 -					$this->_cache=$this->getApplication()->getModule($this->_cacheModuleID);
 -					if(!($this->_cache instanceof ICache))
 -						throw new TConfigurationException('outputcache_cachemoduleid_invalid',$this->_cacheModuleID);
 -				}
 -				else
 -					$this->_cache=$this->getApplication()->getCache();
 -				if($this->_cache!==null)
 -				{
 -					$this->_cacheAvailable=true;
 -					$data=$this->_cache->get($this->getCacheKey());
 -					if(is_array($data))
 -					{
 -						$param=new TOutputCacheCheckDependencyEventParameter;
 -						$param->setCacheTime(isset($data[3])?$data[3]:0);
 -						$this->onCheckDependency($param);
 -						$this->_dataCached=$param->getIsValid();
 -					}
 -					else
 -						$this->_dataCached=false;
 -					if($this->_dataCached)
 -						list($this->_contents,$this->_state,$this->_actions,$this->_cacheTime)=$data;
 -				}
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Performs the Init step for the control and all its child controls.
 -	 * This method overrides the parent implementation by setting up
 -	 * the stack of the output cache in the page.
 -	 * Only framework developers should use this method.
 -	 * @param TControl the naming container control
 -	 */
 -	protected function initRecursive($namingContainer=null)
 -	{
 -		if($this->_cacheAvailable && !$this->_dataCached)
 -		{
 -			$stack=$this->getPage()->getCachingStack();
 -			$stack->push($this);
 -			parent::initRecursive($namingContainer);
 -			$stack->pop();
 -		}
 -		else
 -			parent::initRecursive($namingContainer);
 -	}
 -
 -	/**
 -	 * Performs the Load step for the control and all its child controls.
 -	 * This method overrides the parent implementation by setting up
 -	 * the stack of the output cache in the page. If the data is restored
 -	 * from cache, it also recovers the actions associated with the cached data.
 -	 * Only framework developers should use this method.
 -	 * @param TControl the naming container control
 -	 */
 -	protected function loadRecursive()
 -	{
 -		if($this->_cacheAvailable && !$this->_dataCached)
 -		{
 -			$stack=$this->getPage()->getCachingStack();
 -			$stack->push($this);
 -			parent::loadRecursive();
 -			$stack->pop();
 -		}
 -		else
 -		{
 -			if($this->_dataCached)
 -				$this->performActions();
 -			parent::loadRecursive();
 -		}
 -	}
 -
 -	private function performActions()
 -	{
 -		$page=$this->getPage();
 -		$cs=$page->getClientScript();
 -		foreach($this->_actions as $action)
 -		{
 -			if($action[0]==='Page.ClientScript')
 -				call_user_func_array(array($cs,$action[1]),$action[2]);
 -			else if($action[0]==='Page')
 -				call_user_func_array(array($page,$action[1]),$action[2]);
 -			else
 -				call_user_func_array(array($this->getSubProperty($action[0]),$action[1]),$action[2]);
 -		}
 -	}
 -
 -	/**
 -	 * Performs the PreRender step for the control and all its child controls.
 -	 * This method overrides the parent implementation by setting up
 -	 * the stack of the output cache in the page.
 -	 * Only framework developers should use this method.
 -	 * @param TControl the naming container control
 -	 */
 -	protected function preRenderRecursive()
 -	{
 -		if($this->_cacheAvailable && !$this->_dataCached)
 -		{
 -			$stack=$this->getPage()->getCachingStack();
 -			$stack->push($this);
 -			parent::preRenderRecursive();
 -			$stack->pop();
 -		}
 -		else
 -			parent::preRenderRecursive();
 -	}
 -
 -	/**
 -	 * Loads state (viewstate and controlstate) into a control and its children.
 -	 * This method overrides the parent implementation by loading
 -	 * cached state if available.
 -	 * This method should only be used by framework developers.
 -	 * @param array the collection of the state
 -	 * @param boolean whether the viewstate should be loaded
 -	 */
 -	protected function loadStateRecursive(&$state,$needViewState=true)
 -	{
 -		$st=unserialize($state);
 -		parent::loadStateRecursive($st,$needViewState);
 -	}
 -
 -	/**
 -	 * Saves all control state (viewstate and controlstate) as a collection.
 -	 * This method overrides the parent implementation by saving state
 -	 * into cache if needed.
 -	 * This method should only be used by framework developers.
 -	 * @param boolean whether the viewstate should be saved
 -	 * @return array the collection of the control state (including its children's state).
 -	 */
 -	protected function &saveStateRecursive($needViewState=true)
 -	{
 -		if($this->_dataCached)
 -			return $this->_state;
 -		else
 -		{
 -			$st=parent::saveStateRecursive($needViewState);
 -			// serialization is needed to avoid undefined classes when loading state
 -			$this->_state=serialize($st);
 -			return $this->_state;
 -		}
 -	}
 -
 -	/**
 -	 * Registers an action associated with the content being cached.
 -	 * The registered action will be replayed if the content stored
 -	 * in the cache is served to end-users.
 -	 * @param string context of the action method. This is a property-path
 -	 * referring to the context object (e.g. Page, Page.ClientScript)
 -	 * @param string method name of the context object
 -	 * @param array list of parameters to be passed to the action method
 -	 */
 -	public function registerAction($context,$funcName,$funcParams)
 -	{
 -		$this->_actions[]=array($context,$funcName,$funcParams);
 -	}
 -
 -	public function getCacheKey()
 -	{
 -		if($this->_cacheKey===null)
 -			$this->_cacheKey=$this->calculateCacheKey();
 -		return $this->_cacheKey;
 -	}
 -
 -	/**
 -	 * Calculates the cache key.
 -	 * The key is calculated based on the unique ID of this control
 -	 * and the request parameters specified via {@link setVaryByParam VaryByParam}.
 -	 * If {@link getVaryBySession VaryBySession} is true, the session ID
 -	 * will also participate in the key calculation.
 -	 * This method may be overriden to support other variations in
 -	 * the calculated cache key.
 -	 * @return string cache key
 -	 */
 -	protected function calculateCacheKey()
 -	{
 -		$key=$this->getBaseCacheKey();
 -		if($this->_varyBySession)
 -			$key.=$this->getSession()->getSessionID();
 -		if($this->_varyByParam!=='')
 -		{
 -			$params=array();
 -			$request=$this->getRequest();
 -			foreach(explode(',',$this->_varyByParam) as $name)
 -			{
 -				$name=trim($name);
 -				$params[$name]=$request->itemAt($name);
 -			}
 -			$key.=serialize($params);
 -		}
 -		$param=new TOutputCacheCalculateKeyEventParameter;
 -		$this->onCalculateKey($param);
 -		$key.=$param->getCacheKey();
 -		return $key;
 -	}
 -
 -	/**
 -	 * @return string basic cache key without variations
 -	 */
 -	protected function getBaseCacheKey()
 -	{
 -		return self::CACHE_ID_PREFIX.$this->_keyPrefix.$this->getPage()->getPagePath().$this->getUniqueID();
 -	}
 -
 -	/**
 -	 * @return string the ID of the cache module. Defaults to '', meaning the primary cache module is used.
 -	 */
 -	public function getCacheModuleID()
 -	{
 -		return $this->_cacheModuleID;
 -	}
 -
 -	/**
 -	 * @param string the ID of the cache module. If empty, the primary cache module will be used.
 -	 */
 -	public function setCacheModuleID($value)
 -	{
 -		$this->_cacheModuleID=$value;
 -	}
 -
 -	/**
 -	 * Sets the prefix of the cache key.
 -	 * This method is used internally by {@link TTemplate}.
 -	 * @param string key prefix
 -	 */
 -	public function setCacheKeyPrefix($value)
 -	{
 -		$this->_keyPrefix=$value;
 -	}
 -
 -	/**
 -	 * @return integer the timestamp of the cached content. This is only valid if the content is being cached.
 -	 * @since 3.1.1
 -	 */
 -	public function getCacheTime()
 -	{
 -		return $this->_cacheTime;
 -	}
 -
 -	/**
 -	 * Returns the dependency of the data to be cached.
 -	 * The default implementation simply returns null, meaning no specific dependency.
 -	 * This method may be overriden to associate the data to be cached
 -	 * with additional dependencies.
 -	 * @return ICacheDependency
 -	 */
 -	protected function getCacheDependency()
 -	{
 -		return null;
 -	}
 -
 -	/**
 -	 * @return boolean whether content enclosed is cached or not
 -	 */
 -	public function getContentCached()
 -	{
 -		return $this->_dataCached;
 -	}
 -
 -	/**
 -	 * @return integer number of seconds that the data can remain in cache. Defaults to 60 seconds.
 -	 * Note, if cache dependency changes or cache space is limited,
 -	 * the data may be purged out of cache earlier.
 -	 */
 -	public function getDuration()
 -	{
 -		return $this->_duration;
 -	}
 -
 -	/**
 -	 * @param integer number of seconds that the data can remain in cache. If 0, it means data is not cached.
 -	 * @throws TInvalidDataValueException if the value is smaller than 0.
 -	 */
 -	public function setDuration($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			throw new TInvalidDataValueException('outputcache_duration_invalid',get_class($this));
 -		$this->_duration=$value;
 -	}
 -
 -	/**
 -	 * @return string a semicolon-separated list of strings used to vary the output cache. Defaults to ''.
 -	 */
 -	public function getVaryByParam()
 -	{
 -		return $this->_varyByParam;
 -	}
 -
 -	/**
 -	 * Sets the names of the request parameters that should be used in calculating the cache key.
 -	 * The names should be concatenated by semicolons.
 -	 * By setting this value, the output cache will use different cached data
 -	 * for each different set of request parameter values.
 -	 * @return string a semicolon-separated list of strings used to vary the output cache.
 -	 */
 -	public function setVaryByParam($value)
 -	{
 -		$this->_varyByParam=trim($value);
 -	}
 -
 -	/**
 -	 * @return boolean whether the content being cached should be differentiated according to user sessions. Defaults to false.
 -	 */
 -	public function getVaryBySession()
 -	{
 -		return $this->_varyBySession;
 -	}
 -
 -	/**
 -	 * @param boolean whether the content being cached should be differentiated according to user sessions.
 -	 */
 -	public function setVaryBySession($value)
 -	{
 -		$this->_varyBySession=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * @return boolean whether cached output will be used on postback requests. Defaults to false.
 -	 */
 -	public function getCachingPostBack()
 -	{
 -		return $this->_cachePostBack;
 -	}
 -
 -	/**
 -	 * Sets a value indicating whether cached output will be used on postback requests.
 -	 * By default, this is disabled. Be very cautious when enabling it.
 -	 * If the cached content including interactive user controls such as
 -	 * TTextBox, TDropDownList, your page may fail to render on postbacks.
 -	 * @param boolean whether cached output will be used on postback requests.
 -	 */
 -	public function setCachingPostBack($value)
 -	{
 -		$this->_cachePostBack=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * This event is raised when the output cache is checking cache dependency.
 -	 * An event handler may be written to check customized dependency conditions.
 -	 * The checking result should be saved by setting {@link TOutputCacheCheckDependencyEventParameter::setIsValid IsValid}
 -	 * property of the event parameter (which defaults to true).
 -	 * @param TOutputCacheCheckDependencyEventParameter event parameter
 -	 */
 -	public function onCheckDependency($param)
 -	{
 -		$this->raiseEvent('OnCheckDependency',$this,$param);
 -	}
 -
 -	/**
 -	 * This event is raised when the output cache is calculating cache key.
 -	 * By varying cache keys, one can obtain different versions of cached content.
 -	 * An event handler may be written to add variety of the key calculation.
 -	 * The value set in {@link TOutputCacheCalculateKeyEventParameter::setCacheKey CacheKey} of
 -	 * this event parameter will be appended to the default key calculation scheme.
 -	 * @param TOutputCacheCalculateKeyEventParameter event parameter
 -	 */
 -	public function onCalculateKey($param)
 -	{
 -		$this->raiseEvent('OnCalculateKey',$this,$param);
 -	}
 -
 -	/**
 -	 * Renders the output cache control.
 -	 * This method overrides the parent implementation by capturing the output
 -	 * from its child controls and saving it into cache, if output cache is needed.
 -	 * @param THtmlWriter
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->_dataCached)
 -			$writer->write($this->_contents);
 -		else if($this->_cacheAvailable)
 -		{
 -			$textwriter = new TTextWriter();
 -			$multiwriter = new TOutputCacheTextWriterMulti(array($writer->getWriter(),$textwriter));
 -			$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), $multiwriter);
 -			
 -			$stack=$this->getPage()->getCachingStack();
 -			$stack->push($this);
 -			parent::render($htmlWriter);
 -			$stack->pop();
 -
 -			$content=$textwriter->flush();
 -			$data=array($content,$this->_state,$this->_actions,time());
 -			$this->_cache->set($this->getCacheKey(),$data,$this->getDuration(),$this->getCacheDependency());
 -		}
 -		else
 -			parent::render($writer);
 -	}
 -}
 -
 -/**
 - * TOutputCacheCheckDependencyEventParameter class
 - *
 - * TOutputCacheCheckDependencyEventParameter encapsulates the parameter data for
 - * <b>OnCheckDependency</b> event of {@link TOutputCache} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TOutputCacheCheckDependencyEventParameter extends TEventParameter
 -{
 -	private $_isValid=true;
 -	private $_cacheTime=0;
 -
 -	/**
 -	 * @return boolean whether the dependency remains valid. Defaults to true.
 -	 */
 -	public function getIsValid()
 -	{
 -		return $this->_isValid;
 -	}
 -
 -	/**
 -	 * @param boolean whether the dependency remains valid
 -	 */
 -	public function setIsValid($value)
 -	{
 -		$this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * @return integer the timestamp of the cached result. You may use this to help determine any dependency is changed.
 -	 * @since 3.1.1
 -	 */
 -	public function getCacheTime()
 -	{
 -		return $this->_cacheTime;
 -	}
 -
 -	/**
 -	 * @param integer the timestamp of the cached result. This is used internally.
 -	 * @since 3.1.1
 -	 */
 -	public function setCacheTime($value)
 -	{
 -		$this->_cacheTime=TPropertyValue::ensureInteger($value);
 -	}
 -}
 -
 -
 -/**
 - * TOutputCacheCalculateKeyEventParameter class
 - *
 - * TOutputCacheCalculateKeyEventParameter encapsulates the parameter data for
 - * <b>OnCalculateKey</b> event of {@link TOutputCache} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TOutputCacheCalculateKeyEventParameter extends TEventParameter
 -{
 -	/**
 -	 * @var string cache key to be appended to the default calculation scheme.
 -	 */
 -	private $_cacheKey='';
 -
 -	/**
 -	 * @return string cache key to be appended to the default calculation scheme.
 -	 */
 -	public function getCacheKey()
 -	{
 -		return $this->_cacheKey;
 -	}
 -
 -	/**
 -	 * @param string cache key to be appended to the default calculation scheme
 -	 */
 -	public function setCacheKey($value)
 -	{
 -		$this->_cacheKey=TPropertyValue::ensureString($value);
 -	}
 -}
 -
 -/**
 - * TOutputCacheTextWriterMulti class
 - *
 - * TOutputCacheTextWriterMulti is an internal class used by
 - * TOutputCache to write simultaneously to multiple writers.
 - *
 - * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu>
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -class TOutputCacheTextWriterMulti extends TTextWriter
 -{
 -	protected $_writers;
 -
 -	public function __construct(Array $writers)
 -	{
 -		//parent::__construct();
 -		$this->_writers = $writers;
 -	}
 -	
 -	public function write($s)
 -	{
 -		foreach($this->_writers as $writer)
 -			$writer->write($s);
 -	}
 -
 -	public function flush()
 -	{
 -		foreach($this->_writers as $writer)
 -			$s = $writer->flush();
 -		return $s;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TOutputCache class. + * + * TOutputCache enables caching a portion of a Web page, also known as + * partial caching. The content being cached can be either static or + * dynamic. + * + * To use TOutputCache, simply enclose the content to be cached + * within the TOutputCache component tag on a template, e.g., + * <code> + * <com:TOutputCache> + *   content to be cached + * </com:TOutputCache> + * </code> + * where content to be cached can be static text and/or component tags. + * + * The validity of the cached content is determined based on two factors: + * the {@link setDuration Duration} and the cache dependency. + * The former specifies the number of seconds that the data can remain + * valid in cache (defaults to 60s), while the latter specifies conditions + * that the cached data depends on. If a dependency changes, + * (e.g. relevant data in DB are updated), the cached data will be invalidated. + * + * There are two ways to specify cache dependency. One may write event handlers + * to respond to the {@link onCheckDependency OnCheckDependency} event and set + * the event parameter's {@link TOutputCacheCheckDependencyEventParameter::getIsValid IsValid} + * property to indicate whether the cached data remains valid or not. + * One can also extend TOutputCache and override its {@link getCacheDependency} + * function. While the former is easier to use, the latter offers more extensibility. + * + * The content fetched from cache may be variated with respect to + * some parameters. It supports variation with respect to request parameters, + * which is specified by {@link setVaryByParam VaryByParam} property. + * If a specified request parameter is different, a different version of + * cached content is used. This is extremely useful if a page's content + * may be variated according to some GET parameters. + * The content being cached may also be variated with user sessions if + * {@link setVaryBySession VaryBySession} is set true. + * To variate the cached content by other factors, override {@link calculateCacheKey()} method. + * + * Output caches can be nested. An outer cache takes precedence over an + * inner cache. This means, if the content cached by the inner cache expires + * or is invalidated, while that by the outer cache not, the outer cached + * content will be used. + * + * Note, TOutputCache is effective only for non-postback page requests + * and when cache module is enabled. + * + * Do not attempt to address child controls of TOutputCache when the cached + * content is to be used. Use {@link getContentCached ContentCached} property + * to determine whether the content is cached or not. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1 + */ +class TOutputCache extends TControl implements INamingContainer +{ +	const CACHE_ID_PREFIX='prado:outputcache'; +	private $_cacheModuleID=''; +	private $_dataCached=false; +	private $_cacheAvailable=false; +	private $_cacheChecked=false; +	private $_cacheKey=null; +	private $_duration=60; +	private $_cache=null; +	private $_contents; +	private $_state; +	private $_actions=array(); +	private $_varyByParam=''; +	private $_keyPrefix=''; +	private $_varyBySession=false; +	private $_cachePostBack=false; +	private $_cacheTime=0; + +	/** +	 * Returns a value indicating whether body contents are allowed for this control. +	 * This method overrides the parent implementation by checking if cached +	 * content is available or not. If yes, it returns false, otherwise true. +	 * @param boolean whether body contents are allowed for this control. +	 */ +	public function getAllowChildControls() +	{ +		$this->determineCacheability(); +		return !$this->_dataCached; +	} + +	private function determineCacheability() +	{ +		if(!$this->_cacheChecked) +		{ +			$this->_cacheChecked=true; +			if($this->_duration>0 && ($this->_cachePostBack || !$this->getPage()->getIsPostBack())) +			{ +				if($this->_cacheModuleID!=='') +				{ +					$this->_cache=$this->getApplication()->getModule($this->_cacheModuleID); +					if(!($this->_cache instanceof ICache)) +						throw new TConfigurationException('outputcache_cachemoduleid_invalid',$this->_cacheModuleID); +				} +				else +					$this->_cache=$this->getApplication()->getCache(); +				if($this->_cache!==null) +				{ +					$this->_cacheAvailable=true; +					$data=$this->_cache->get($this->getCacheKey()); +					if(is_array($data)) +					{ +						$param=new TOutputCacheCheckDependencyEventParameter; +						$param->setCacheTime(isset($data[3])?$data[3]:0); +						$this->onCheckDependency($param); +						$this->_dataCached=$param->getIsValid(); +					} +					else +						$this->_dataCached=false; +					if($this->_dataCached) +						list($this->_contents,$this->_state,$this->_actions,$this->_cacheTime)=$data; +				} +			} +		} +	} + +	/** +	 * Performs the Init step for the control and all its child controls. +	 * This method overrides the parent implementation by setting up +	 * the stack of the output cache in the page. +	 * Only framework developers should use this method. +	 * @param TControl the naming container control +	 */ +	protected function initRecursive($namingContainer=null) +	{ +		if($this->_cacheAvailable && !$this->_dataCached) +		{ +			$stack=$this->getPage()->getCachingStack(); +			$stack->push($this); +			parent::initRecursive($namingContainer); +			$stack->pop(); +		} +		else +			parent::initRecursive($namingContainer); +	} + +	/** +	 * Performs the Load step for the control and all its child controls. +	 * This method overrides the parent implementation by setting up +	 * the stack of the output cache in the page. If the data is restored +	 * from cache, it also recovers the actions associated with the cached data. +	 * Only framework developers should use this method. +	 * @param TControl the naming container control +	 */ +	protected function loadRecursive() +	{ +		if($this->_cacheAvailable && !$this->_dataCached) +		{ +			$stack=$this->getPage()->getCachingStack(); +			$stack->push($this); +			parent::loadRecursive(); +			$stack->pop(); +		} +		else +		{ +			if($this->_dataCached) +				$this->performActions(); +			parent::loadRecursive(); +		} +	} + +	private function performActions() +	{ +		$page=$this->getPage(); +		$cs=$page->getClientScript(); +		foreach($this->_actions as $action) +		{ +			if($action[0]==='Page.ClientScript') +				call_user_func_array(array($cs,$action[1]),$action[2]); +			else if($action[0]==='Page') +				call_user_func_array(array($page,$action[1]),$action[2]); +			else +				call_user_func_array(array($this->getSubProperty($action[0]),$action[1]),$action[2]); +		} +	} + +	/** +	 * Performs the PreRender step for the control and all its child controls. +	 * This method overrides the parent implementation by setting up +	 * the stack of the output cache in the page. +	 * Only framework developers should use this method. +	 * @param TControl the naming container control +	 */ +	protected function preRenderRecursive() +	{ +		if($this->_cacheAvailable && !$this->_dataCached) +		{ +			$stack=$this->getPage()->getCachingStack(); +			$stack->push($this); +			parent::preRenderRecursive(); +			$stack->pop(); +		} +		else +			parent::preRenderRecursive(); +	} + +	/** +	 * Loads state (viewstate and controlstate) into a control and its children. +	 * This method overrides the parent implementation by loading +	 * cached state if available. +	 * This method should only be used by framework developers. +	 * @param array the collection of the state +	 * @param boolean whether the viewstate should be loaded +	 */ +	protected function loadStateRecursive(&$state,$needViewState=true) +	{ +		$st=unserialize($state); +		parent::loadStateRecursive($st,$needViewState); +	} + +	/** +	 * Saves all control state (viewstate and controlstate) as a collection. +	 * This method overrides the parent implementation by saving state +	 * into cache if needed. +	 * This method should only be used by framework developers. +	 * @param boolean whether the viewstate should be saved +	 * @return array the collection of the control state (including its children's state). +	 */ +	protected function &saveStateRecursive($needViewState=true) +	{ +		if($this->_dataCached) +			return $this->_state; +		else +		{ +			$st=parent::saveStateRecursive($needViewState); +			// serialization is needed to avoid undefined classes when loading state +			$this->_state=serialize($st); +			return $this->_state; +		} +	} + +	/** +	 * Registers an action associated with the content being cached. +	 * The registered action will be replayed if the content stored +	 * in the cache is served to end-users. +	 * @param string context of the action method. This is a property-path +	 * referring to the context object (e.g. Page, Page.ClientScript) +	 * @param string method name of the context object +	 * @param array list of parameters to be passed to the action method +	 */ +	public function registerAction($context,$funcName,$funcParams) +	{ +		$this->_actions[]=array($context,$funcName,$funcParams); +	} + +	public function getCacheKey() +	{ +		if($this->_cacheKey===null) +			$this->_cacheKey=$this->calculateCacheKey(); +		return $this->_cacheKey; +	} + +	/** +	 * Calculates the cache key. +	 * The key is calculated based on the unique ID of this control +	 * and the request parameters specified via {@link setVaryByParam VaryByParam}. +	 * If {@link getVaryBySession VaryBySession} is true, the session ID +	 * will also participate in the key calculation. +	 * This method may be overriden to support other variations in +	 * the calculated cache key. +	 * @return string cache key +	 */ +	protected function calculateCacheKey() +	{ +		$key=$this->getBaseCacheKey(); +		if($this->_varyBySession) +			$key.=$this->getSession()->getSessionID(); +		if($this->_varyByParam!=='') +		{ +			$params=array(); +			$request=$this->getRequest(); +			foreach(explode(',',$this->_varyByParam) as $name) +			{ +				$name=trim($name); +				$params[$name]=$request->itemAt($name); +			} +			$key.=serialize($params); +		} +		$param=new TOutputCacheCalculateKeyEventParameter; +		$this->onCalculateKey($param); +		$key.=$param->getCacheKey(); +		return $key; +	} + +	/** +	 * @return string basic cache key without variations +	 */ +	protected function getBaseCacheKey() +	{ +		return self::CACHE_ID_PREFIX.$this->_keyPrefix.$this->getPage()->getPagePath().$this->getUniqueID(); +	} + +	/** +	 * @return string the ID of the cache module. Defaults to '', meaning the primary cache module is used. +	 */ +	public function getCacheModuleID() +	{ +		return $this->_cacheModuleID; +	} + +	/** +	 * @param string the ID of the cache module. If empty, the primary cache module will be used. +	 */ +	public function setCacheModuleID($value) +	{ +		$this->_cacheModuleID=$value; +	} + +	/** +	 * Sets the prefix of the cache key. +	 * This method is used internally by {@link TTemplate}. +	 * @param string key prefix +	 */ +	public function setCacheKeyPrefix($value) +	{ +		$this->_keyPrefix=$value; +	} + +	/** +	 * @return integer the timestamp of the cached content. This is only valid if the content is being cached. +	 * @since 3.1.1 +	 */ +	public function getCacheTime() +	{ +		return $this->_cacheTime; +	} + +	/** +	 * Returns the dependency of the data to be cached. +	 * The default implementation simply returns null, meaning no specific dependency. +	 * This method may be overriden to associate the data to be cached +	 * with additional dependencies. +	 * @return ICacheDependency +	 */ +	protected function getCacheDependency() +	{ +		return null; +	} + +	/** +	 * @return boolean whether content enclosed is cached or not +	 */ +	public function getContentCached() +	{ +		return $this->_dataCached; +	} + +	/** +	 * @return integer number of seconds that the data can remain in cache. Defaults to 60 seconds. +	 * Note, if cache dependency changes or cache space is limited, +	 * the data may be purged out of cache earlier. +	 */ +	public function getDuration() +	{ +		return $this->_duration; +	} + +	/** +	 * @param integer number of seconds that the data can remain in cache. If 0, it means data is not cached. +	 * @throws TInvalidDataValueException if the value is smaller than 0. +	 */ +	public function setDuration($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			throw new TInvalidDataValueException('outputcache_duration_invalid',get_class($this)); +		$this->_duration=$value; +	} + +	/** +	 * @return string a semicolon-separated list of strings used to vary the output cache. Defaults to ''. +	 */ +	public function getVaryByParam() +	{ +		return $this->_varyByParam; +	} + +	/** +	 * Sets the names of the request parameters that should be used in calculating the cache key. +	 * The names should be concatenated by semicolons. +	 * By setting this value, the output cache will use different cached data +	 * for each different set of request parameter values. +	 * @return string a semicolon-separated list of strings used to vary the output cache. +	 */ +	public function setVaryByParam($value) +	{ +		$this->_varyByParam=trim($value); +	} + +	/** +	 * @return boolean whether the content being cached should be differentiated according to user sessions. Defaults to false. +	 */ +	public function getVaryBySession() +	{ +		return $this->_varyBySession; +	} + +	/** +	 * @param boolean whether the content being cached should be differentiated according to user sessions. +	 */ +	public function setVaryBySession($value) +	{ +		$this->_varyBySession=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * @return boolean whether cached output will be used on postback requests. Defaults to false. +	 */ +	public function getCachingPostBack() +	{ +		return $this->_cachePostBack; +	} + +	/** +	 * Sets a value indicating whether cached output will be used on postback requests. +	 * By default, this is disabled. Be very cautious when enabling it. +	 * If the cached content including interactive user controls such as +	 * TTextBox, TDropDownList, your page may fail to render on postbacks. +	 * @param boolean whether cached output will be used on postback requests. +	 */ +	public function setCachingPostBack($value) +	{ +		$this->_cachePostBack=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * This event is raised when the output cache is checking cache dependency. +	 * An event handler may be written to check customized dependency conditions. +	 * The checking result should be saved by setting {@link TOutputCacheCheckDependencyEventParameter::setIsValid IsValid} +	 * property of the event parameter (which defaults to true). +	 * @param TOutputCacheCheckDependencyEventParameter event parameter +	 */ +	public function onCheckDependency($param) +	{ +		$this->raiseEvent('OnCheckDependency',$this,$param); +	} + +	/** +	 * This event is raised when the output cache is calculating cache key. +	 * By varying cache keys, one can obtain different versions of cached content. +	 * An event handler may be written to add variety of the key calculation. +	 * The value set in {@link TOutputCacheCalculateKeyEventParameter::setCacheKey CacheKey} of +	 * this event parameter will be appended to the default key calculation scheme. +	 * @param TOutputCacheCalculateKeyEventParameter event parameter +	 */ +	public function onCalculateKey($param) +	{ +		$this->raiseEvent('OnCalculateKey',$this,$param); +	} + +	/** +	 * Renders the output cache control. +	 * This method overrides the parent implementation by capturing the output +	 * from its child controls and saving it into cache, if output cache is needed. +	 * @param THtmlWriter +	 */ +	public function render($writer) +	{ +		if($this->_dataCached) +			$writer->write($this->_contents); +		else if($this->_cacheAvailable) +		{ +			$textwriter = new TTextWriter(); +			$multiwriter = new TOutputCacheTextWriterMulti(array($writer->getWriter(),$textwriter)); +			$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), $multiwriter); +			 +			$stack=$this->getPage()->getCachingStack(); +			$stack->push($this); +			parent::render($htmlWriter); +			$stack->pop(); + +			$content=$textwriter->flush(); +			$data=array($content,$this->_state,$this->_actions,time()); +			$this->_cache->set($this->getCacheKey(),$data,$this->getDuration(),$this->getCacheDependency()); +		} +		else +			parent::render($writer); +	} +} + +/** + * TOutputCacheCheckDependencyEventParameter class + * + * TOutputCacheCheckDependencyEventParameter encapsulates the parameter data for + * <b>OnCheckDependency</b> event of {@link TOutputCache} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TOutputCacheCheckDependencyEventParameter extends TEventParameter +{ +	private $_isValid=true; +	private $_cacheTime=0; + +	/** +	 * @return boolean whether the dependency remains valid. Defaults to true. +	 */ +	public function getIsValid() +	{ +		return $this->_isValid; +	} + +	/** +	 * @param boolean whether the dependency remains valid +	 */ +	public function setIsValid($value) +	{ +		$this->_isValid=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * @return integer the timestamp of the cached result. You may use this to help determine any dependency is changed. +	 * @since 3.1.1 +	 */ +	public function getCacheTime() +	{ +		return $this->_cacheTime; +	} + +	/** +	 * @param integer the timestamp of the cached result. This is used internally. +	 * @since 3.1.1 +	 */ +	public function setCacheTime($value) +	{ +		$this->_cacheTime=TPropertyValue::ensureInteger($value); +	} +} + + +/** + * TOutputCacheCalculateKeyEventParameter class + * + * TOutputCacheCalculateKeyEventParameter encapsulates the parameter data for + * <b>OnCalculateKey</b> event of {@link TOutputCache} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TOutputCacheCalculateKeyEventParameter extends TEventParameter +{ +	/** +	 * @var string cache key to be appended to the default calculation scheme. +	 */ +	private $_cacheKey=''; + +	/** +	 * @return string cache key to be appended to the default calculation scheme. +	 */ +	public function getCacheKey() +	{ +		return $this->_cacheKey; +	} + +	/** +	 * @param string cache key to be appended to the default calculation scheme +	 */ +	public function setCacheKey($value) +	{ +		$this->_cacheKey=TPropertyValue::ensureString($value); +	} +} + +/** + * TOutputCacheTextWriterMulti class + * + * TOutputCacheTextWriterMulti is an internal class used by + * TOutputCache to write simultaneously to multiple writers. + * + * @author Gabor Berczi, DevWorx Hungary <gabor.berczi@devworx.hu> + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.2 + */ +class TOutputCacheTextWriterMulti extends TTextWriter +{ +	protected $_writers; + +	public function __construct(Array $writers) +	{ +		//parent::__construct(); +		$this->_writers = $writers; +	} +	 +	public function write($s) +	{ +		foreach($this->_writers as $writer) +			$writer->write($s); +	} + +	public function flush() +	{ +		foreach($this->_writers as $writer) +			$s = $writer->flush(); +		return $s; +	} +} + diff --git a/framework/Web/UI/WebControls/TPager.php b/framework/Web/UI/WebControls/TPager.php index 8e4bf2b0..11de5233 100644 --- a/framework/Web/UI/WebControls/TPager.php +++ b/framework/Web/UI/WebControls/TPager.php @@ -1,792 +1,792 @@ -<?php
 -/**
 - * TPager class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TPager class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TPager class.
 - *
 - * TPager creates a pager that provides UI for end-users to interactively
 - * specify which page of data to be rendered in a {@link TDataBoundControl}-derived control,
 - * such as {@link TDataList}, {@link TRepeater}, {@link TCheckBoxList}, etc.
 - * The target data-bound control is specified by {@link setControlToPaginate ControlToPaginate},
 - * which must be the ID path of the target control reaching from the pager's
 - * naming container. Note, the target control must have its {@link TDataBoundControl::setAllowPaging AllowPaging}
 - * set to true.
 - *
 - * TPager can display three different UIs, specified via {@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.
 - *
 - * When the pager mode is either NextPrev or Numeric, the paging buttons may be displayed
 - * in three types by setting {@link setButtonType ButtonType}:
 - * - LinkButton: a hyperlink button
 - * - PushButton: a normal button
 - * - ImageButton: an image button (please set XXXPageImageUrl properties accordingly to specify the button images.)
 - *
 - * 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}.
 - * Normally, in the event handler, one can set the {@link TDataBoundControl::getCurrentPageIndex CurrentPageIndex}
 - * to this new page index so that the new page of data is rendered.
 - *
 - * Multiple pagers can be associated with the same data-bound control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.2
 - */
 -class TPager extends TWebControl 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';
 -
 -	private $_pageCount=0;
 -
 -	/**
 -	 * 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))
 -		{
 -			$this->getControls()->clear();
 -			$this->buildPager();
 -		}
 -	}
 -
 -	/**
 -	 * @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 TPagerMode pager mode. Defaults to TPagerMode::NextPrev.
 -	 */
 -	public function getMode()
 -	{
 -		return $this->getViewState('Mode',TPagerMode::NextPrev);
 -	}
 -
 -	/**
 -	 * @param TPagerMode pager mode.
 -	 */
 -	public function setMode($value)
 -	{
 -		$this->setViewState('Mode',TPropertyValue::ensureEnum($value,'TPagerMode'),TPagerMode::NextPrev);
 -	}
 -
 -	/**
 -	 * @return TPagerButtonType the type of command button for paging. Defaults to TPagerButtonType::LinkButton.
 -	 */
 -	public function getButtonType()
 -	{
 -		return $this->getViewState('ButtonType',TPagerButtonType::LinkButton);
 -	}
 -
 -	/**
 -	 * @param TPagerButtonType the type of command button for paging.
 -	 */
 -	public function setButtonType($value)
 -	{
 -		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TPagerButtonType'),TPagerButtonType::LinkButton);
 -	}
 -
 -	/**
 -	 * @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 string the image URL for the first page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function getFirstPageImageUrl()
 -	{
 -		return $this->getViewState('FirstPageImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the image URL for the first page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function setFirstPageImageUrl($value)
 -	{
 -		$this->setViewState('FirstPageImageUrl',$value);
 -	}
 -
 -	/**
 -	 * @return string the image URL for the last page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function getLastPageImageUrl()
 -	{
 -		return $this->getViewState('LastPageImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the image URL for the last page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function setLastPageImageUrl($value)
 -	{
 -		$this->setViewState('LastPageImageUrl',$value);
 -	}
 -
 -	/**
 -	 * @return string the image URL for the next page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function getNextPageImageUrl()
 -	{
 -		return $this->getViewState('NextPageImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the image URL for the next page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function setNextPageImageUrl($value)
 -	{
 -		$this->setViewState('NextPageImageUrl',$value);
 -	}
 -
 -	/**
 -	 * @return string the image URL for the previous page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function getPrevPageImageUrl()
 -	{
 -		return $this->getViewState('PrevPageImageUrl','');
 -	}
 -
 -	/**
 -	 * @param string the image URL for the previous page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'.
 -	 * @since 3.1.1
 -	 */
 -	public function setPrevPageImageUrl($value)
 -	{
 -		$this->setViewState('PrevPageImageUrl',$value);
 -	}
 -
 -	/**
 -	 * @return string the image URL for the numeric page buttons. This is only used when {@link getButtonType ButtonType} is 'ImageButton' and {@link getMode Mode} is 'Numeric'.
 -	 * @see setNumericPageImageUrl
 -	 * @since 3.1.1
 -	 */
 -	public function getNumericPageImageUrl()
 -	{
 -		return $this->getViewState('NumericPageImageUrl','');
 -	}
 -
 -	/**
 -	 * Sets the image URL for the numeric page buttons.
 -	 * This is actually a template for generating a set of URLs corresponding to numeric button 1, 2, 3, .., etc.
 -	 * Use {0} as the placeholder for the numbers.
 -	 * For example, the image URL http://example.com/images/button{0}.gif
 -	 * will be replaced as http://example.com/images/button1.gif, http://example.com/images/button2.gif, etc.
 -	 * @param string the image URL for the numeric page buttons. This is only used when {@link getButtonType ButtonType} is 'ImageButton' and {@link getMode Mode} is 'Numeric'.
 -	 * @since 3.1.1
 -	 */
 -	public function setNumericPageImageUrl($value)
 -	{
 -		$this->setViewState('NumericPageImageUrl',$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 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
 -	 */
 -	protected function setCurrentPageIndex($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			throw new TInvalidDataValueException('pager_currentpageindex_invalid');
 -		$this->setViewState('CurrentPageIndex',$value,0);
 -	}
 -
 -	/**
 -	 * @return integer number of pages of data items available
 -	 */
 -	public function getPageCount()
 -	{
 -		return $this->getViewState('PageCount',0);
 -	}
 -
 -	/**
 -	 * @param integer number of pages of data items available
 -	 * @throws TInvalidDataValueException if the value is less than 0
 -	 */
 -	protected function setPageCount($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			throw new TInvalidDataValueException('pager_pagecount_invalid');
 -		$this->setViewState('PageCount',$value,0);
 -	}
 -
 -	/**
 -	 * @return boolean whether the current page is the first page Defaults to false.
 -	 */
 -	public function getIsFirstPage()
 -	{
 -		return $this->getCurrentPageIndex()===0;
 -	}
 -
 -	/**
 -	 * @return boolean whether the current page is the last page
 -	 */
 -	public function getIsLastPage()
 -	{
 -		return $this->getCurrentPageIndex()===$this->getPageCount()-1;
 -	}
 -
 -	/**
 -	 * 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
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -
 -		$controlID=$this->getControlToPaginate();
 -		if(($targetControl=$this->getNamingContainer()->findControl($controlID))===null || !($targetControl instanceof TDataBoundControl))
 -			throw new TConfigurationException('pager_controltopaginate_invalid',$controlID);
 -
 -		if($targetControl->getAllowPaging())
 -		{
 -	 		$this->_pageCount=$targetControl->getPageCount();
 -			$this->getControls()->clear();
 -			$this->setPageCount($targetControl->getPageCount());
 -			$this->setCurrentPageIndex($targetControl->getCurrentPageIndex());
 -			$this->buildPager();
 -		}
 -		else
 -			$this->_pageCount=0;
 -	}
 -
 -	/**
 -	 * Renders the control.
 -	 * The method overrides the parent implementation by rendering
 -	 * the pager only when there are two or more pages.
 -	 * @param THtmlWriter the writer
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->_pageCount>1)
 -			parent::render($writer);
 -	}
 -
 -	/**
 -	 * Builds the pager content based on the pager mode.
 -	 * Current implementation includes building 'NextPrev', 'Numeric' and 'DropDownList' pagers.
 -	 * Derived classes may override this method to provide additional pagers.
 -	 */
 -	protected function buildPager()
 -	{
 -		switch($this->getMode())
 -		{
 -			case TPagerMode::NextPrev:
 -				$this->buildNextPrevPager();
 -				break;
 -			case TPagerMode::Numeric:
 -				$this->buildNumericPager();
 -				break;
 -			case TPagerMode::DropDownList:
 -				$this->buildListPager();
 -				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===TPagerButtonType::LinkButton)
 -		{
 -			if($enabled)
 -				$button=new TLinkButton;
 -			else
 -			{
 -				$button=new TLabel;
 -				$button->setText($text);
 -				return $button;
 -			}
 -		}
 -		else
 -		{
 -			if($buttonType===TPagerButtonType::ImageButton)
 -			{
 -				$button=new TImageButton;
 -				$button->setImageUrl($this->getPageImageUrl($text,$commandName));
 -			}
 -			else
 -				$button=new TButton;
 -			if(!$enabled)
 -				$button->setEnabled(false);
 -		}
 -		$button->setText($text);
 -		$button->setCommandName($commandName);
 -		$button->setCommandParameter($commandParameter);
 -		$button->setCausesValidation(false);
 -		return $button;
 -	}
 -
 -	/**
 -	 * @param string the caption of the image button
 -	 * @param string the command name associated with the image button
 -	 * @since 3.1.1
 -	 */
 -	protected function getPageImageUrl($text,$commandName)
 -	{
 -		switch($commandName)
 -		{
 -			case self::CMD_PAGE:
 -				$url=$this->getNumericPageImageUrl();
 -				return str_replace('{0}',$text,$url);
 -			case self::CMD_PAGE_NEXT:
 -				return $this->getNextPageImageUrl();
 -			case self::CMD_PAGE_PREV:
 -				return $this->getPrevPageImageUrl();
 -			case self::CMD_PAGE_FIRST:
 -				return $this->getFirstPageImageUrl();
 -			case self::CMD_PAGE_LAST:
 -				return $this->getLastPageImageUrl();
 -			default:
 -				return '';
 -		}
 -	}
 -
 -	/**
 -	 * Builds a next-prev pager
 -	 */
 -	protected function buildNextPrevPager()
 -	{
 -		$buttonType=$this->getButtonType();
 -		$controls=$this->getControls();
 -		if($this->getIsFirstPage())
 -		{
 -			if(($text=$this->getFirstPageText())!=='')
 -			{
 -				$label=$this->createPagerButton($buttonType,false,$text,self::CMD_PAGE_FIRST,'');
 -				$controls->add($label);
 -				$controls->add("\n");
 -			}
 -			$label=$this->createPagerButton($buttonType,false,$this->getPrevPageText(),self::CMD_PAGE_PREV,'');
 -			$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($this->getIsLastPage())
 -		{
 -			$label=$this->createPagerButton($buttonType,false,$this->getNextPageText(),self::CMD_PAGE_NEXT,'');
 -			$controls->add($label);
 -			if(($text=$this->getLastPageText())!=='')
 -			{
 -				$controls->add("\n");
 -				$label=$this->createPagerButton($buttonType,false,$text,self::CMD_PAGE_LAST,'');
 -				$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
 -	 */
 -	protected function buildNumericPager()
 -	{
 -		$buttonType=$this->getButtonType();
 -		$controls=$this->getControls();
 -		$pageCount=$this->getPageCount();
 -		$pageIndex=$this->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",self::CMD_PAGE,'');
 -				$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
 -	 */
 -	protected function buildListPager()
 -	{
 -		$list=new TDropDownList;
 -		$this->getControls()->add($list);
 -		$list->setDataSource(range(1,$this->getPageCount()));
 -		$list->dataBind();
 -		$list->setSelectedIndex($this->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 <b>OnCommand</b> 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 <qiang.xue@gmail.com>
 - * @version $Id$
 - * @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 <b>OnCommand</b> event.
 -	 * @param integer new page index
 -	 */
 -	public function __construct($source,$newPageIndex)
 -	{
 -		$this->_source=$source;
 -		$this->_newIndex=$newPageIndex;
 -	}
 -
 -	/**
 -	 * @return TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	public function getCommandSource()
 -	{
 -		return $this->_source;
 -	}
 -
 -	/**
 -	 * @return integer new page index
 -	 */
 -	public function getNewPageIndex()
 -	{
 -		return $this->_newIndex;
 -	}
 -}
 -
 -
 -/**
 - * TPagerMode class.
 - * TPagerMode defines the enumerable type for the possible modes that a {@link TPager} control can take.
 - *
 - * The following enumerable values are defined:
 - * - NextPrev: pager buttons are displayed as next and previous pages
 - * - Numeric: pager buttons are displayed as numeric page numbers
 - * - DropDownList: a dropdown list is used to select pages
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TPagerMode extends TEnumerable
 -{
 -	const NextPrev='NextPrev';
 -	const Numeric='Numeric';
 -	const DropDownList='DropDownList';
 -}
 -
 -
 -/**
 - * TPagerButtonType class.
 - * TPagerButtonType defines the enumerable type for the possible types of pager buttons.
 - *
 - * The following enumerable values are defined:
 - * - LinkButton: link buttons
 - * - PushButton: form submit buttons
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TPagerButtonType extends TEnumerable
 -{
 -	const LinkButton='LinkButton';
 -	const PushButton='PushButton';
 -	const ImageButton='ImageButton';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TPager class. + * + * TPager creates a pager that provides UI for end-users to interactively + * specify which page of data to be rendered in a {@link TDataBoundControl}-derived control, + * such as {@link TDataList}, {@link TRepeater}, {@link TCheckBoxList}, etc. + * The target data-bound control is specified by {@link setControlToPaginate ControlToPaginate}, + * which must be the ID path of the target control reaching from the pager's + * naming container. Note, the target control must have its {@link TDataBoundControl::setAllowPaging AllowPaging} + * set to true. + * + * TPager can display three different UIs, specified via {@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. + * + * When the pager mode is either NextPrev or Numeric, the paging buttons may be displayed + * in three types by setting {@link setButtonType ButtonType}: + * - LinkButton: a hyperlink button + * - PushButton: a normal button + * - ImageButton: an image button (please set XXXPageImageUrl properties accordingly to specify the button images.) + * + * 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}. + * Normally, in the event handler, one can set the {@link TDataBoundControl::getCurrentPageIndex CurrentPageIndex} + * to this new page index so that the new page of data is rendered. + * + * Multiple pagers can be associated with the same data-bound control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.2 + */ +class TPager extends TWebControl 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'; + +	private $_pageCount=0; + +	/** +	 * 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)) +		{ +			$this->getControls()->clear(); +			$this->buildPager(); +		} +	} + +	/** +	 * @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 TPagerMode pager mode. Defaults to TPagerMode::NextPrev. +	 */ +	public function getMode() +	{ +		return $this->getViewState('Mode',TPagerMode::NextPrev); +	} + +	/** +	 * @param TPagerMode pager mode. +	 */ +	public function setMode($value) +	{ +		$this->setViewState('Mode',TPropertyValue::ensureEnum($value,'TPagerMode'),TPagerMode::NextPrev); +	} + +	/** +	 * @return TPagerButtonType the type of command button for paging. Defaults to TPagerButtonType::LinkButton. +	 */ +	public function getButtonType() +	{ +		return $this->getViewState('ButtonType',TPagerButtonType::LinkButton); +	} + +	/** +	 * @param TPagerButtonType the type of command button for paging. +	 */ +	public function setButtonType($value) +	{ +		$this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'TPagerButtonType'),TPagerButtonType::LinkButton); +	} + +	/** +	 * @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 string the image URL for the first page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function getFirstPageImageUrl() +	{ +		return $this->getViewState('FirstPageImageUrl',''); +	} + +	/** +	 * @param string the image URL for the first page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function setFirstPageImageUrl($value) +	{ +		$this->setViewState('FirstPageImageUrl',$value); +	} + +	/** +	 * @return string the image URL for the last page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function getLastPageImageUrl() +	{ +		return $this->getViewState('LastPageImageUrl',''); +	} + +	/** +	 * @param string the image URL for the last page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function setLastPageImageUrl($value) +	{ +		$this->setViewState('LastPageImageUrl',$value); +	} + +	/** +	 * @return string the image URL for the next page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function getNextPageImageUrl() +	{ +		return $this->getViewState('NextPageImageUrl',''); +	} + +	/** +	 * @param string the image URL for the next page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function setNextPageImageUrl($value) +	{ +		$this->setViewState('NextPageImageUrl',$value); +	} + +	/** +	 * @return string the image URL for the previous page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function getPrevPageImageUrl() +	{ +		return $this->getViewState('PrevPageImageUrl',''); +	} + +	/** +	 * @param string the image URL for the previous page button. This is only used when {@link getButtonType ButtonType} is 'ImageButton'. +	 * @since 3.1.1 +	 */ +	public function setPrevPageImageUrl($value) +	{ +		$this->setViewState('PrevPageImageUrl',$value); +	} + +	/** +	 * @return string the image URL for the numeric page buttons. This is only used when {@link getButtonType ButtonType} is 'ImageButton' and {@link getMode Mode} is 'Numeric'. +	 * @see setNumericPageImageUrl +	 * @since 3.1.1 +	 */ +	public function getNumericPageImageUrl() +	{ +		return $this->getViewState('NumericPageImageUrl',''); +	} + +	/** +	 * Sets the image URL for the numeric page buttons. +	 * This is actually a template for generating a set of URLs corresponding to numeric button 1, 2, 3, .., etc. +	 * Use {0} as the placeholder for the numbers. +	 * For example, the image URL http://example.com/images/button{0}.gif +	 * will be replaced as http://example.com/images/button1.gif, http://example.com/images/button2.gif, etc. +	 * @param string the image URL for the numeric page buttons. This is only used when {@link getButtonType ButtonType} is 'ImageButton' and {@link getMode Mode} is 'Numeric'. +	 * @since 3.1.1 +	 */ +	public function setNumericPageImageUrl($value) +	{ +		$this->setViewState('NumericPageImageUrl',$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 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 +	 */ +	protected function setCurrentPageIndex($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			throw new TInvalidDataValueException('pager_currentpageindex_invalid'); +		$this->setViewState('CurrentPageIndex',$value,0); +	} + +	/** +	 * @return integer number of pages of data items available +	 */ +	public function getPageCount() +	{ +		return $this->getViewState('PageCount',0); +	} + +	/** +	 * @param integer number of pages of data items available +	 * @throws TInvalidDataValueException if the value is less than 0 +	 */ +	protected function setPageCount($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			throw new TInvalidDataValueException('pager_pagecount_invalid'); +		$this->setViewState('PageCount',$value,0); +	} + +	/** +	 * @return boolean whether the current page is the first page Defaults to false. +	 */ +	public function getIsFirstPage() +	{ +		return $this->getCurrentPageIndex()===0; +	} + +	/** +	 * @return boolean whether the current page is the last page +	 */ +	public function getIsLastPage() +	{ +		return $this->getCurrentPageIndex()===$this->getPageCount()-1; +	} + +	/** +	 * 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 +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); + +		$controlID=$this->getControlToPaginate(); +		if(($targetControl=$this->getNamingContainer()->findControl($controlID))===null || !($targetControl instanceof TDataBoundControl)) +			throw new TConfigurationException('pager_controltopaginate_invalid',$controlID); + +		if($targetControl->getAllowPaging()) +		{ +	 		$this->_pageCount=$targetControl->getPageCount(); +			$this->getControls()->clear(); +			$this->setPageCount($targetControl->getPageCount()); +			$this->setCurrentPageIndex($targetControl->getCurrentPageIndex()); +			$this->buildPager(); +		} +		else +			$this->_pageCount=0; +	} + +	/** +	 * Renders the control. +	 * The method overrides the parent implementation by rendering +	 * the pager only when there are two or more pages. +	 * @param THtmlWriter the writer +	 */ +	public function render($writer) +	{ +		if($this->_pageCount>1) +			parent::render($writer); +	} + +	/** +	 * Builds the pager content based on the pager mode. +	 * Current implementation includes building 'NextPrev', 'Numeric' and 'DropDownList' pagers. +	 * Derived classes may override this method to provide additional pagers. +	 */ +	protected function buildPager() +	{ +		switch($this->getMode()) +		{ +			case TPagerMode::NextPrev: +				$this->buildNextPrevPager(); +				break; +			case TPagerMode::Numeric: +				$this->buildNumericPager(); +				break; +			case TPagerMode::DropDownList: +				$this->buildListPager(); +				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===TPagerButtonType::LinkButton) +		{ +			if($enabled) +				$button=new TLinkButton; +			else +			{ +				$button=new TLabel; +				$button->setText($text); +				return $button; +			} +		} +		else +		{ +			if($buttonType===TPagerButtonType::ImageButton) +			{ +				$button=new TImageButton; +				$button->setImageUrl($this->getPageImageUrl($text,$commandName)); +			} +			else +				$button=new TButton; +			if(!$enabled) +				$button->setEnabled(false); +		} +		$button->setText($text); +		$button->setCommandName($commandName); +		$button->setCommandParameter($commandParameter); +		$button->setCausesValidation(false); +		return $button; +	} + +	/** +	 * @param string the caption of the image button +	 * @param string the command name associated with the image button +	 * @since 3.1.1 +	 */ +	protected function getPageImageUrl($text,$commandName) +	{ +		switch($commandName) +		{ +			case self::CMD_PAGE: +				$url=$this->getNumericPageImageUrl(); +				return str_replace('{0}',$text,$url); +			case self::CMD_PAGE_NEXT: +				return $this->getNextPageImageUrl(); +			case self::CMD_PAGE_PREV: +				return $this->getPrevPageImageUrl(); +			case self::CMD_PAGE_FIRST: +				return $this->getFirstPageImageUrl(); +			case self::CMD_PAGE_LAST: +				return $this->getLastPageImageUrl(); +			default: +				return ''; +		} +	} + +	/** +	 * Builds a next-prev pager +	 */ +	protected function buildNextPrevPager() +	{ +		$buttonType=$this->getButtonType(); +		$controls=$this->getControls(); +		if($this->getIsFirstPage()) +		{ +			if(($text=$this->getFirstPageText())!=='') +			{ +				$label=$this->createPagerButton($buttonType,false,$text,self::CMD_PAGE_FIRST,''); +				$controls->add($label); +				$controls->add("\n"); +			} +			$label=$this->createPagerButton($buttonType,false,$this->getPrevPageText(),self::CMD_PAGE_PREV,''); +			$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($this->getIsLastPage()) +		{ +			$label=$this->createPagerButton($buttonType,false,$this->getNextPageText(),self::CMD_PAGE_NEXT,''); +			$controls->add($label); +			if(($text=$this->getLastPageText())!=='') +			{ +				$controls->add("\n"); +				$label=$this->createPagerButton($buttonType,false,$text,self::CMD_PAGE_LAST,''); +				$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 +	 */ +	protected function buildNumericPager() +	{ +		$buttonType=$this->getButtonType(); +		$controls=$this->getControls(); +		$pageCount=$this->getPageCount(); +		$pageIndex=$this->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",self::CMD_PAGE,''); +				$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 +	 */ +	protected function buildListPager() +	{ +		$list=new TDropDownList; +		$this->getControls()->add($list); +		$list->setDataSource(range(1,$this->getPageCount())); +		$list->dataBind(); +		$list->setSelectedIndex($this->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 <b>OnCommand</b> 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 <qiang.xue@gmail.com> + * @version $Id$ + * @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 <b>OnCommand</b> event. +	 * @param integer new page index +	 */ +	public function __construct($source,$newPageIndex) +	{ +		$this->_source=$source; +		$this->_newIndex=$newPageIndex; +	} + +	/** +	 * @return TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	public function getCommandSource() +	{ +		return $this->_source; +	} + +	/** +	 * @return integer new page index +	 */ +	public function getNewPageIndex() +	{ +		return $this->_newIndex; +	} +} + + +/** + * TPagerMode class. + * TPagerMode defines the enumerable type for the possible modes that a {@link TPager} control can take. + * + * The following enumerable values are defined: + * - NextPrev: pager buttons are displayed as next and previous pages + * - Numeric: pager buttons are displayed as numeric page numbers + * - DropDownList: a dropdown list is used to select pages + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TPagerMode extends TEnumerable +{ +	const NextPrev='NextPrev'; +	const Numeric='Numeric'; +	const DropDownList='DropDownList'; +} + + +/** + * TPagerButtonType class. + * TPagerButtonType defines the enumerable type for the possible types of pager buttons. + * + * The following enumerable values are defined: + * - LinkButton: link buttons + * - PushButton: form submit buttons + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TPagerButtonType extends TEnumerable +{ +	const LinkButton='LinkButton'; +	const PushButton='PushButton'; +	const ImageButton='ImageButton'; +} + diff --git a/framework/Web/UI/WebControls/TPanel.php b/framework/Web/UI/WebControls/TPanel.php index 5d651679..d4e05136 100644 --- a/framework/Web/UI/WebControls/TPanel.php +++ b/framework/Web/UI/WebControls/TPanel.php @@ -1,246 +1,246 @@ -<?php
 -/**
 - * TPanel class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TPanelStyle class file
 - */
 -Prado::using('System.Web.UI.WebControls.TPanelStyle');
 -
 -/**
 - * TPanel class
 - *
 - * TPanel represents a component that acts as a container for other component.
 - * It is especially useful when you want to generate components programmatically
 - * or hide/show a group of components.
 - *
 - * By default, TPanel displays a <div> element on a page.
 - * Children of TPanel are displayed as the body content of the element.
 - * The property {@link setWrap Wrap} can be used to set whether the body content
 - * should wrap or not. {@link setHorizontalAlign HorizontalAlign} governs how
 - * the content is aligned horizontally, and {@link getDirection Direction} indicates
 - * the content direction (left to right or right to left). You can set
 - * {@link setBackImageUrl BackImageUrl} to give a background image to the panel,
 - * and you can ste {@link setGroupingText GroupingText} so that the panel is
 - * displayed as a field set with a legend text. Finally, you can specify
 - * a default button to be fired when users press 'return' key within the panel
 - * by setting the {@link setDefaultButton DefaultButton} property.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TPanel extends TWebControl
 -{
 -	/**
 -	 * @var string ID path to the default button
 -	 */
 -	private $_defaultButton='';
 -
 -	/**
 -	 * @return string tag name of the panel
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'div';
 -	}
 -
 -	/**
 -	 * 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()
 -	{
 -		return new TPanelStyle;
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 * @throws TInvalidDataValueException if default button is not right.
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		if(($butt=$this->getDefaultButton())!=='')
 -			$writer->addAttribute('id',$this->getClientID());
 -	}
 -
 -	/**
 -	 * @return boolean whether the content wraps within the panel. Defaults to true.
 -	 */
 -	public function getWrap()
 -	{
 -		return $this->getStyle()->getWrap();
 -	}
 -
 -	/**
 -	 * 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->getStyle()->setWrap($value);
 -	}
 -
 -	/**
 -	 * @return string the horizontal alignment of the contents within the panel, defaults to 'NotSet'.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		return $this->getStyle()->getHorizontalAlign();
 -	}
 -
 -	/**
 -	 * 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->getStyle()->setHorizontalAlign($value);
 -	}
 -
 -	/**
 -	 * @return string the URL of the background image for the panel component.
 -	 */
 -	public function getBackImageUrl()
 -	{
 -		return $this->getStyle()->getBackImageUrl();
 -	}
 -
 -	/**
 -	 * Sets the URL of the background image for the panel component.
 -	 * @param string the URL
 -	 */
 -	public function setBackImageUrl($value)
 -	{
 -		$this->getStyle()->setBackImageUrl($value);
 -	}
 -
 -	/**
 -	 * @return string alignment of the content in the panel. Defaults to 'NotSet'.
 -	 */
 -	public function getDirection()
 -	{
 -		return $this->getStyle()->getDirection();
 -	}
 -
 -	/**
 -	 * @param string alignment of the content in the panel.
 -	 * Valid values include 'NotSet', 'LeftToRight', 'RightToLeft'.
 -	 */
 -	public function setDirection($value)
 -	{
 -		$this->getStyle()->setDirection($value);
 -	}
 -
 -	/**
 -	 * @return string the ID path to the default button. Defaults to empty.
 -	 */
 -	public function getDefaultButton()
 -	{
 -		return $this->_defaultButton;
 -	}
 -
 -	/**
 -	 * Specifies the default button for the panel.
 -	 * The default button will be fired (clicked) whenever a user enters 'return'
 -	 * key within the panel.
 -	 * The button must be locatable via the function call {@link TControl::findControl findControl}.
 -	 * @param string the ID path to the default button.
 -	 */
 -	public function setDefaultButton($value)
 -	{
 -		$this->_defaultButton=$value;
 -	}
 -
 -	/**
 -	 * @return string the legend text when the panel is used as a fieldset. Defaults to empty.
 -	 */
 -	public function getGroupingText()
 -	{
 -		return $this->getViewState('GroupingText','');
 -	}
 -
 -	/**
 -	 * @param string the legend text. If this value is not empty, the panel will be rendered as a fieldset.
 -	 */
 -	public function setGroupingText($value)
 -	{
 -		$this->setViewState('GroupingText',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the visibility and position of scroll bars in a panel control, defaults to None.
 -	 */
 -	public function getScrollBars()
 -	{
 -		return $this->getStyle()->getScrollBars();
 -	}
 -
 -	/**
 -	 * @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->getStyle()->setScrollBars($value);
 -	}
 -
 -	/**
 -	 * Renders the openning tag for the control (including attributes)
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderBeginTag($writer)
 -	{
 -		parent::renderBeginTag($writer);
 -		if(($text=$this->getGroupingText())!=='')
 -		{
 -			$writer->renderBeginTag('fieldset');
 -			$writer->renderBeginTag('legend');
 -			$writer->write($text);
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	/**
 -	 * Renders the closing tag for the control
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderEndTag($writer)
 -	{
 -		if($this->getGroupingText()!=='')
 -			$writer->renderEndTag();
 -		parent::renderEndTag($writer);
 -	}
 -
 -	public function render($writer)
 -	{
 -		parent::render($writer);
 -
 -		if(($butt=$this->getDefaultButton())!=='')
 -		{
 -			$buttons = $this->findControlsByID($butt);
 -			if (count($buttons)>0)
 -				$button = reset($buttons);
 -			else
 -				$button = null;
 -			if($button===null)
 -				throw new TInvalidDataValueException('panel_defaultbutton_invalid',$butt);
 -			else
 -				$this->getPage()->getClientScript()->registerDefaultButton($this, $button);
 -		}
 -	}
 -}
 -
 +<?php +/** + * TPanel class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TPanelStyle class file + */ +Prado::using('System.Web.UI.WebControls.TPanelStyle'); + +/** + * TPanel class + * + * TPanel represents a component that acts as a container for other component. + * It is especially useful when you want to generate components programmatically + * or hide/show a group of components. + * + * By default, TPanel displays a <div> element on a page. + * Children of TPanel are displayed as the body content of the element. + * The property {@link setWrap Wrap} can be used to set whether the body content + * should wrap or not. {@link setHorizontalAlign HorizontalAlign} governs how + * the content is aligned horizontally, and {@link getDirection Direction} indicates + * the content direction (left to right or right to left). You can set + * {@link setBackImageUrl BackImageUrl} to give a background image to the panel, + * and you can ste {@link setGroupingText GroupingText} so that the panel is + * displayed as a field set with a legend text. Finally, you can specify + * a default button to be fired when users press 'return' key within the panel + * by setting the {@link setDefaultButton DefaultButton} property. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TPanel extends TWebControl +{ +	/** +	 * @var string ID path to the default button +	 */ +	private $_defaultButton=''; + +	/** +	 * @return string tag name of the panel +	 */ +	protected function getTagName() +	{ +		return 'div'; +	} + +	/** +	 * 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() +	{ +		return new TPanelStyle; +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 * @throws TInvalidDataValueException if default button is not right. +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		if(($butt=$this->getDefaultButton())!=='') +			$writer->addAttribute('id',$this->getClientID()); +	} + +	/** +	 * @return boolean whether the content wraps within the panel. Defaults to true. +	 */ +	public function getWrap() +	{ +		return $this->getStyle()->getWrap(); +	} + +	/** +	 * 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->getStyle()->setWrap($value); +	} + +	/** +	 * @return string the horizontal alignment of the contents within the panel, defaults to 'NotSet'. +	 */ +	public function getHorizontalAlign() +	{ +		return $this->getStyle()->getHorizontalAlign(); +	} + +	/** +	 * 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->getStyle()->setHorizontalAlign($value); +	} + +	/** +	 * @return string the URL of the background image for the panel component. +	 */ +	public function getBackImageUrl() +	{ +		return $this->getStyle()->getBackImageUrl(); +	} + +	/** +	 * Sets the URL of the background image for the panel component. +	 * @param string the URL +	 */ +	public function setBackImageUrl($value) +	{ +		$this->getStyle()->setBackImageUrl($value); +	} + +	/** +	 * @return string alignment of the content in the panel. Defaults to 'NotSet'. +	 */ +	public function getDirection() +	{ +		return $this->getStyle()->getDirection(); +	} + +	/** +	 * @param string alignment of the content in the panel. +	 * Valid values include 'NotSet', 'LeftToRight', 'RightToLeft'. +	 */ +	public function setDirection($value) +	{ +		$this->getStyle()->setDirection($value); +	} + +	/** +	 * @return string the ID path to the default button. Defaults to empty. +	 */ +	public function getDefaultButton() +	{ +		return $this->_defaultButton; +	} + +	/** +	 * Specifies the default button for the panel. +	 * The default button will be fired (clicked) whenever a user enters 'return' +	 * key within the panel. +	 * The button must be locatable via the function call {@link TControl::findControl findControl}. +	 * @param string the ID path to the default button. +	 */ +	public function setDefaultButton($value) +	{ +		$this->_defaultButton=$value; +	} + +	/** +	 * @return string the legend text when the panel is used as a fieldset. Defaults to empty. +	 */ +	public function getGroupingText() +	{ +		return $this->getViewState('GroupingText',''); +	} + +	/** +	 * @param string the legend text. If this value is not empty, the panel will be rendered as a fieldset. +	 */ +	public function setGroupingText($value) +	{ +		$this->setViewState('GroupingText',$value,''); +	} + +	/** +	 * @return string the visibility and position of scroll bars in a panel control, defaults to None. +	 */ +	public function getScrollBars() +	{ +		return $this->getStyle()->getScrollBars(); +	} + +	/** +	 * @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->getStyle()->setScrollBars($value); +	} + +	/** +	 * Renders the openning tag for the control (including attributes) +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderBeginTag($writer) +	{ +		parent::renderBeginTag($writer); +		if(($text=$this->getGroupingText())!=='') +		{ +			$writer->renderBeginTag('fieldset'); +			$writer->renderBeginTag('legend'); +			$writer->write($text); +			$writer->renderEndTag(); +		} +	} + +	/** +	 * Renders the closing tag for the control +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderEndTag($writer) +	{ +		if($this->getGroupingText()!=='') +			$writer->renderEndTag(); +		parent::renderEndTag($writer); +	} + +	public function render($writer) +	{ +		parent::render($writer); + +		if(($butt=$this->getDefaultButton())!=='') +		{ +			$buttons = $this->findControlsByID($butt); +			if (count($buttons)>0) +				$button = reset($buttons); +			else +				$button = null; +			if($button===null) +				throw new TInvalidDataValueException('panel_defaultbutton_invalid',$butt); +			else +				$this->getPage()->getClientScript()->registerDefaultButton($this, $button); +		} +	} +} + diff --git a/framework/Web/UI/WebControls/TPanelStyle.php b/framework/Web/UI/WebControls/TPanelStyle.php index 16169749..5e5db6e4 100644 --- a/framework/Web/UI/WebControls/TPanelStyle.php +++ b/framework/Web/UI/WebControls/TPanelStyle.php @@ -1,278 +1,278 @@ -<?php
 -/**
 - * TPanelStyle class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TPanelStyle class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @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 <qiang.xue@gmail.com>
 - * @version $Id$
 - * @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 TScrollBars::Horizontal: $this->setStyleField('overflow-x','scroll'); break;
 -			case TScrollBars::Vertical: $this->setStyleField('overflow-y','scroll'); break;
 -			case TScrollBars::Both: $this->setStyleField('overflow','scroll'); break;
 -			case TScrollBars::Auto: $this->setStyleField('overflow','auto'); break;
 -		}
 -
 -		if(($align=$this->getHorizontalAlign())!==THorizontalAlign::NotSet)
 -			$this->setStyleField('text-align',strtolower($align));
 -
 -		if(!$this->getWrap())
 -			$this->setStyleField('white-space','nowrap');
 -
 -		if(($direction=$this->getDirection())!==TContentDirection::NotSet)
 -		{
 -			if($direction===TContentDirection::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 TContentDirection alignment of the content in the panel. Defaults to TContentDirection::NotSet.
 -	 */
 -	public function getDirection()
 -	{
 -		return $this->_direction===null?TContentDirection::NotSet:$this->_direction;
 -	}
 -
 -	/**
 -	 * @param TContentDirection alignment of the content in the panel.
 -	 */
 -	public function setDirection($value)
 -	{
 -		$this->_direction=TPropertyValue::ensureEnum($value,'TContentDirection');
 -	}
 -
 -	/**
 -	 * @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 THorizontalAlign the horizontal alignment of the contents within the panel, defaults to THorizontalAlign::NotSet.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign;
 -	}
 -
 -	/**
 -	 * Sets the horizontal alignment of the contents within the panel.
 -	 * @param THorizontalAlign the horizontal alignment
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign');
 -	}
 -
 -	/**
 -	 * @return TScrollBars the visibility and position of scroll bars in a panel control, defaults to TScrollBars::None.
 -	 */
 -	public function getScrollBars()
 -	{
 -		return $this->_scrollBars===null?TScrollBars::None:$this->_scrollBars;
 -	}
 -
 -	/**
 -	 * @param TScrollBars the visibility and position of scroll bars in a panel control.
 -	 */
 -	public function setScrollBars($value)
 -	{
 -		$this->_scrollBars=TPropertyValue::ensureEnum($value,'TScrollBars');
 -	}
 -
 -	/**
 -	 * Sets the style attributes to default values.
 -	 * This method overrides the parent implementation by
 -	 * resetting additional TPanelStyle 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;
 -		}
 -	}
 -}
 -
 -/**
 - * TContentDirection class.
 - * TContentDirection defines the enumerable type for the possible directions that a panel can be at.
 - *
 - * The following enumerable values are defined:
 - * - NotSet: the direction is not specified
 - * - LeftToRight: content in a panel is left to right
 - * - RightToLeft: content in a panel is right to left
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TContentDirection extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const LeftToRight='LeftToRight';
 -	const RightToLeft='RightToLeft';
 -}
 -
 -/**
 - * TScrollBars class.
 - * TScrollBars defines the enumerable type for the possible scroll bar mode
 - * that a {@link TPanel} control could use.
 - *
 - * The following enumerable values are defined:
 - * - None: no scroll bars.
 - * - Auto: scroll bars automatically appeared when needed.
 - * - Both: show both horizontal and vertical scroll bars all the time.
 - * - Horizontal: horizontal scroll bar only
 - * - Vertical: vertical scroll bar only
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TScrollBars extends TEnumerable
 -{
 -	const None='None';
 -	const Auto='Auto';
 -	const Both='Both';
 -	const Horizontal='Horizontal';
 -	const Vertical='Vertical';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @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 <qiang.xue@gmail.com> + * @version $Id$ + * @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 TScrollBars::Horizontal: $this->setStyleField('overflow-x','scroll'); break; +			case TScrollBars::Vertical: $this->setStyleField('overflow-y','scroll'); break; +			case TScrollBars::Both: $this->setStyleField('overflow','scroll'); break; +			case TScrollBars::Auto: $this->setStyleField('overflow','auto'); break; +		} + +		if(($align=$this->getHorizontalAlign())!==THorizontalAlign::NotSet) +			$this->setStyleField('text-align',strtolower($align)); + +		if(!$this->getWrap()) +			$this->setStyleField('white-space','nowrap'); + +		if(($direction=$this->getDirection())!==TContentDirection::NotSet) +		{ +			if($direction===TContentDirection::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 TContentDirection alignment of the content in the panel. Defaults to TContentDirection::NotSet. +	 */ +	public function getDirection() +	{ +		return $this->_direction===null?TContentDirection::NotSet:$this->_direction; +	} + +	/** +	 * @param TContentDirection alignment of the content in the panel. +	 */ +	public function setDirection($value) +	{ +		$this->_direction=TPropertyValue::ensureEnum($value,'TContentDirection'); +	} + +	/** +	 * @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 THorizontalAlign the horizontal alignment of the contents within the panel, defaults to THorizontalAlign::NotSet. +	 */ +	public function getHorizontalAlign() +	{ +		return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign; +	} + +	/** +	 * Sets the horizontal alignment of the contents within the panel. +	 * @param THorizontalAlign the horizontal alignment +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign'); +	} + +	/** +	 * @return TScrollBars the visibility and position of scroll bars in a panel control, defaults to TScrollBars::None. +	 */ +	public function getScrollBars() +	{ +		return $this->_scrollBars===null?TScrollBars::None:$this->_scrollBars; +	} + +	/** +	 * @param TScrollBars the visibility and position of scroll bars in a panel control. +	 */ +	public function setScrollBars($value) +	{ +		$this->_scrollBars=TPropertyValue::ensureEnum($value,'TScrollBars'); +	} + +	/** +	 * Sets the style attributes to default values. +	 * This method overrides the parent implementation by +	 * resetting additional TPanelStyle 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; +		} +	} +} + +/** + * TContentDirection class. + * TContentDirection defines the enumerable type for the possible directions that a panel can be at. + * + * The following enumerable values are defined: + * - NotSet: the direction is not specified + * - LeftToRight: content in a panel is left to right + * - RightToLeft: content in a panel is right to left + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TContentDirection extends TEnumerable +{ +	const NotSet='NotSet'; +	const LeftToRight='LeftToRight'; +	const RightToLeft='RightToLeft'; +} + +/** + * TScrollBars class. + * TScrollBars defines the enumerable type for the possible scroll bar mode + * that a {@link TPanel} control could use. + * + * The following enumerable values are defined: + * - None: no scroll bars. + * - Auto: scroll bars automatically appeared when needed. + * - Both: show both horizontal and vertical scroll bars all the time. + * - Horizontal: horizontal scroll bar only + * - Vertical: vertical scroll bar only + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TScrollBars extends TEnumerable +{ +	const None='None'; +	const Auto='Auto'; +	const Both='Both'; +	const Horizontal='Horizontal'; +	const Vertical='Vertical'; +} + diff --git a/framework/Web/UI/WebControls/TPlaceHolder.php b/framework/Web/UI/WebControls/TPlaceHolder.php index ac67cef7..585e9e99 100644 --- a/framework/Web/UI/WebControls/TPlaceHolder.php +++ b/framework/Web/UI/WebControls/TPlaceHolder.php @@ -1,28 +1,28 @@ -<?php
 -/**
 - * TPlaceHolder class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TPlaceHolder class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TPlaceHolder class
 - *
 - * TPlaceHolder reserves a place on a template, where static texts or controls
 - * may be inserted. You may add or remove texts or child controls of TPlaceHolder
 - * by manipulating the {@link TControl::getControls Controls} property.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TPlaceHolder extends TControl
 -{
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TPlaceHolder class + * + * TPlaceHolder reserves a place on a template, where static texts or controls + * may be inserted. You may add or remove texts or child controls of TPlaceHolder + * by manipulating the {@link TControl::getControls Controls} property. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TPlaceHolder extends TControl +{ +} + diff --git a/framework/Web/UI/WebControls/TRadioButton.php b/framework/Web/UI/WebControls/TRadioButton.php index b90cfcf5..6a2347f4 100644 --- a/framework/Web/UI/WebControls/TRadioButton.php +++ b/framework/Web/UI/WebControls/TRadioButton.php @@ -1,320 +1,320 @@ -<?php
 -/**
 - * TRadioButton class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TRadioButton class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TCheckBox parent class
 - */
 -Prado::using('System.Web.UI.WebControls.TCheckBox');
 -/**
 - * Using TRadioButtonList class
 - */
 -Prado::using('System.Web.UI.WebControls.TRadioButtonList');
 -
 -/**
 - * TRadioButton class
 - *
 - * TRadioButton displays a radio button on the page.
 - * You can specify the caption to display beside the radio buttonby setting
 - * the {@link setText Text} property.  The caption can appear either on the right
 - * or left of the radio button, which is determined by the {@link setTextAlign TextAlign}
 - * property.
 - *
 - * To determine whether the TRadioButton component is checked, test the {@link getChecked Checked}
 - * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when
 - * the {@link getChecked Checked} state of the TRadioButton component changes
 - * between posts to the server. You can provide an event handler for
 - * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically
 - * control the actions performed when the state of the TRadioButton component changes
 - * between posts to the server.
 - *
 - * TRadioButton uses {@link setGroupName GroupName} to group together a set of radio buttons.
 - * Once the {@link setGroupName GroupName} is set, you can use the {@link getRadioButtonsInGroup}
 - * method to get an array of TRadioButtons having the same group name.
 - *
 - * If {@link setAutoPostBack AutoPostBack} is set true, changing the radio button state
 - * will cause postback action. And if {@link setCausesValidation CausesValidation}
 - * is true, validation will also be processed, which can be further restricted within
 - * a {@link setValidationGroup ValidationGroup}.
 - *
 - * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters
 - * that may bring security vulnerabilities.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRadioButton extends TCheckBox
 -{
 -	/**
 -	 * @param array list of radio buttons that are on the current page hierarchy
 -	 */
 -	private static $_activeButtons=array();
 -	/**
 -	 * @var integer number of radio buttons created
 -	 */
 -	private static $_buttonCount=0;
 -	/**
 -	 * @var integer global ID of this radiobutton
 -	 */
 -	private $_globalID;
 -	/**
 -	 * @var string previous UniqueID (used to calculate UniqueGroup)
 -	 */
 -	private $_previousUniqueID=null;
 -	/**
 -	 * @var string the name used to fetch radiobutton post data
 -	 */
 -	private $_uniqueGroupName=null;
 -
 -	/**
 -	 * Constructor.
 -	 * Registers the radiobutton in a global radiobutton collection.
 -	 * If overridden, the parent implementation must be invoked first.
 -	 */
 -	public function __construct()
 -	{
 -		parent::__construct();
 -		$this->_globalID = self::$_buttonCount++;
 -	}
 -
 -	/**
 -	 * Registers the radio button groupings. If overriding onInit method,
 -	 * ensure to call parent implemenation.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onInit($param)
 -	{
 -		parent::onInit($param);
 -		self::$_activeButtons[$this->_globalID]=$this;
 -	}
 -
 -	/**
 -	 * Unregisters the radio button groupings. If overriding onInit method,
 -	 * ensure to call parent implemenation.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onUnLoad($param)
 -	{
 -		unset(self::$_activeButtons[$this->_globalID]);
 -		parent::onUnLoad($param);
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the control has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		$uniqueGroupName=$this->getUniqueGroupName();
 -		$value=isset($values[$uniqueGroupName])?$values[$uniqueGroupName]:null;
 -		if($value!==null && $value===$this->getValueAttribute())
 -		{
 -			if(!$this->getChecked())
 -			{
 -				$this->setChecked(true);
 -				return true;
 -			}
 -			else
 -				return false;
 -		}
 -		else if($this->getChecked())
 -			$this->setChecked(false);
 -		return false;
 -	}
 -
 -	/**
 -	 * @return string the name of the group that the radio button belongs to. Defaults to empty.
 -	 */
 -	public function getGroupName()
 -	{
 -		return $this->getViewState('GroupName','');
 -	}
 -
 -	/**
 -	 * Sets the name of the group that the radio button belongs to.
 -	 * The group is unique among the control's naming container.
 -	 * @param string the group name
 -	 * @see setUniqueGroupName
 -	 */
 -	public function setGroupName($value)
 -	{
 -		$this->setViewState('GroupName',$value,'');
 -		$this->_uniqueGroupName=null;
 -	}
 -
 -	/**
 -	 * Add the group name as post data loader if group name is set.
 -	 */
 -	protected function addToPostDataLoader()
 -	{
 -		parent::addToPostDataLoader();
 -		$group = $this->getGroupName();
 -		if(!empty($group) || $this->getViewState('UniqueGroupName','') !== '')
 -			$this->getPage()->registerPostDataLoader($this->getUniqueGroupName());
 -	}
 -	/**
 -	 * @return string the name used to fetch radiobutton post data
 -	 */
 -	public function getUniqueGroupName()
 -	{
 -		if(($groupName=$this->getViewState('UniqueGroupName',''))!=='')
 -			return $groupName;
 -		else if(($uniqueID=$this->getUniqueID())!==$this->_previousUniqueID || $this->_uniqueGroupName===null)
 -		{
 -			$groupName=$this->getGroupName();
 -			$this->_previousUniqueID=$uniqueID;
 -			if($uniqueID!=='')
 -			{
 -				if(($pos=strrpos($uniqueID,TControl::ID_SEPARATOR))!==false)
 -				{
 -					if($groupName!=='')
 -						$groupName=substr($uniqueID,0,$pos+1).$groupName;
 -					else if($this->getNamingContainer() instanceof TRadioButtonList)
 -						$groupName=substr($uniqueID,0,$pos);
 -				}
 -				if($groupName==='')
 -					$groupName=$uniqueID;
 -			}
 -			$this->_uniqueGroupName=$groupName;
 -		}
 -		return $this->_uniqueGroupName;
 -	}
 -
 -	/**
 -	 * Sets the unique group name that the radio button belongs to.
 -	 * A unique group is a radiobutton group unique among the whole page hierarchy,
 -	 * while the {@link setGroupName GroupName} specifies a group that is unique
 -	 * among the control's naming container only.
 -	 * For example, each cell of a {@link TDataGrid} is a naming container.
 -	 * If you specify {@link setGroupName GroupName} for a radiobutton in a cell,
 -	 * it groups together radiobutton within a cell, but not the other, even though
 -	 * they have the same {@link setGroupName GroupName}.
 -	 * On the contratry, if {@link setUniqueGroupName UniqueGroupName} is used instead,
 -	 * it will group all appropriate radio buttons on the whole page hierarchy.
 -	 * Note, when both {@link setUniqueGroupName UniqueGroupName} and
 -	 * {@link setGroupName GroupName}, the former takes precedence.
 -	 * @param string the group name
 -	 * @see setGroupName
 -	 */
 -	public function setUniqueGroupName($value)
 -	{
 -		$this->setViewState('UniqueGroupName',$value,'');
 -	}
 -
 -	/**
 -	 * Gets an array of radiobuttons whose group name is the same as this radiobutton's.
 -	 * Note, only those radiobuttons that are on the current page hierarchy may be
 -	 * returned in the result.
 -	 * @return array list of TRadioButton with the same group
 -	 */
 -	public function getRadioButtonsInGroup()
 -	{
 -		$group = $this->getUniqueGroupName();
 -		$buttons = array();
 -		foreach(self::$_activeButtons as $control)
 -		{
 -			if($control->getUniqueGroupName() === $group)
 -				$buttons[] = $control;
 -		}
 -		return $buttons;
 -	}
 -
 -	/**
 -	 * @return string the value attribute to be rendered
 -	 */
 -	protected function getValueAttribute()
 -	{
 -		if(($value=parent::getValueAttribute())==='')
 -			return $this->getUniqueID();
 -		else
 -			return $value;
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Renders a radiobutton input element.
 -	 * @param THtmlWriter the writer for the rendering purpose
 -	 * @param string checkbox id
 -	 * @param string onclick js
 -	 */
 -	protected function renderInputTag($writer,$clientID,$onclick)
 -	{
 -		if($clientID!=='')
 -			$writer->addAttribute('id',$clientID);
 -		$writer->addAttribute('type','radio');
 -		$writer->addAttribute('name',$this->getUniqueGroupName());
 -		$writer->addAttribute('value',$this->getValueAttribute());
 -		if(!empty($onclick))
 -			$writer->addAttribute('onclick',$onclick);
 -		if($this->getChecked())
 -			$writer->addAttribute('checked','checked');
 -		if(!$this->getEnabled(true))
 -			$writer->addAttribute('disabled','disabled');
 -
 -		$page=$this->getPage();
 -		if($this->getEnabled(true)
 -			&& $this->getEnableClientScript()
 -			&& $this->getAutoPostBack()
 -			&& $page->getClientSupportsJavaScript())
 -		{
 -			$this->renderClientControlScript($writer);
 -		}
 -
 -		if(($accesskey=$this->getAccessKey())!=='')
 -			$writer->addAttribute('accesskey',$accesskey);
 -		if(($tabindex=$this->getTabIndex())>0)
 -			$writer->addAttribute('tabindex',"$tabindex");
 -		if($attributes=$this->getViewState('InputAttributes',null))
 -			$writer->addAttributes($attributes);
 -		$writer->renderBeginTag('input');
 -		$writer->renderEndTag();
 -	}
 -
 -	/**
 -	 * Renders the client-script code.
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TRadioButton';
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TCheckBox parent class + */ +Prado::using('System.Web.UI.WebControls.TCheckBox'); +/** + * Using TRadioButtonList class + */ +Prado::using('System.Web.UI.WebControls.TRadioButtonList'); + +/** + * TRadioButton class + * + * TRadioButton displays a radio button on the page. + * You can specify the caption to display beside the radio buttonby setting + * the {@link setText Text} property.  The caption can appear either on the right + * or left of the radio button, which is determined by the {@link setTextAlign TextAlign} + * property. + * + * To determine whether the TRadioButton component is checked, test the {@link getChecked Checked} + * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when + * the {@link getChecked Checked} state of the TRadioButton component changes + * between posts to the server. You can provide an event handler for + * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically + * control the actions performed when the state of the TRadioButton component changes + * between posts to the server. + * + * TRadioButton uses {@link setGroupName GroupName} to group together a set of radio buttons. + * Once the {@link setGroupName GroupName} is set, you can use the {@link getRadioButtonsInGroup} + * method to get an array of TRadioButtons having the same group name. + * + * If {@link setAutoPostBack AutoPostBack} is set true, changing the radio button state + * will cause postback action. And if {@link setCausesValidation CausesValidation} + * is true, validation will also be processed, which can be further restricted within + * a {@link setValidationGroup ValidationGroup}. + * + * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters + * that may bring security vulnerabilities. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRadioButton extends TCheckBox +{ +	/** +	 * @param array list of radio buttons that are on the current page hierarchy +	 */ +	private static $_activeButtons=array(); +	/** +	 * @var integer number of radio buttons created +	 */ +	private static $_buttonCount=0; +	/** +	 * @var integer global ID of this radiobutton +	 */ +	private $_globalID; +	/** +	 * @var string previous UniqueID (used to calculate UniqueGroup) +	 */ +	private $_previousUniqueID=null; +	/** +	 * @var string the name used to fetch radiobutton post data +	 */ +	private $_uniqueGroupName=null; + +	/** +	 * Constructor. +	 * Registers the radiobutton in a global radiobutton collection. +	 * If overridden, the parent implementation must be invoked first. +	 */ +	public function __construct() +	{ +		parent::__construct(); +		$this->_globalID = self::$_buttonCount++; +	} + +	/** +	 * Registers the radio button groupings. If overriding onInit method, +	 * ensure to call parent implemenation. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onInit($param) +	{ +		parent::onInit($param); +		self::$_activeButtons[$this->_globalID]=$this; +	} + +	/** +	 * Unregisters the radio button groupings. If overriding onInit method, +	 * ensure to call parent implemenation. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onUnLoad($param) +	{ +		unset(self::$_activeButtons[$this->_globalID]); +		parent::onUnLoad($param); +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the control has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		$uniqueGroupName=$this->getUniqueGroupName(); +		$value=isset($values[$uniqueGroupName])?$values[$uniqueGroupName]:null; +		if($value!==null && $value===$this->getValueAttribute()) +		{ +			if(!$this->getChecked()) +			{ +				$this->setChecked(true); +				return true; +			} +			else +				return false; +		} +		else if($this->getChecked()) +			$this->setChecked(false); +		return false; +	} + +	/** +	 * @return string the name of the group that the radio button belongs to. Defaults to empty. +	 */ +	public function getGroupName() +	{ +		return $this->getViewState('GroupName',''); +	} + +	/** +	 * Sets the name of the group that the radio button belongs to. +	 * The group is unique among the control's naming container. +	 * @param string the group name +	 * @see setUniqueGroupName +	 */ +	public function setGroupName($value) +	{ +		$this->setViewState('GroupName',$value,''); +		$this->_uniqueGroupName=null; +	} + +	/** +	 * Add the group name as post data loader if group name is set. +	 */ +	protected function addToPostDataLoader() +	{ +		parent::addToPostDataLoader(); +		$group = $this->getGroupName(); +		if(!empty($group) || $this->getViewState('UniqueGroupName','') !== '') +			$this->getPage()->registerPostDataLoader($this->getUniqueGroupName()); +	} +	/** +	 * @return string the name used to fetch radiobutton post data +	 */ +	public function getUniqueGroupName() +	{ +		if(($groupName=$this->getViewState('UniqueGroupName',''))!=='') +			return $groupName; +		else if(($uniqueID=$this->getUniqueID())!==$this->_previousUniqueID || $this->_uniqueGroupName===null) +		{ +			$groupName=$this->getGroupName(); +			$this->_previousUniqueID=$uniqueID; +			if($uniqueID!=='') +			{ +				if(($pos=strrpos($uniqueID,TControl::ID_SEPARATOR))!==false) +				{ +					if($groupName!=='') +						$groupName=substr($uniqueID,0,$pos+1).$groupName; +					else if($this->getNamingContainer() instanceof TRadioButtonList) +						$groupName=substr($uniqueID,0,$pos); +				} +				if($groupName==='') +					$groupName=$uniqueID; +			} +			$this->_uniqueGroupName=$groupName; +		} +		return $this->_uniqueGroupName; +	} + +	/** +	 * Sets the unique group name that the radio button belongs to. +	 * A unique group is a radiobutton group unique among the whole page hierarchy, +	 * while the {@link setGroupName GroupName} specifies a group that is unique +	 * among the control's naming container only. +	 * For example, each cell of a {@link TDataGrid} is a naming container. +	 * If you specify {@link setGroupName GroupName} for a radiobutton in a cell, +	 * it groups together radiobutton within a cell, but not the other, even though +	 * they have the same {@link setGroupName GroupName}. +	 * On the contratry, if {@link setUniqueGroupName UniqueGroupName} is used instead, +	 * it will group all appropriate radio buttons on the whole page hierarchy. +	 * Note, when both {@link setUniqueGroupName UniqueGroupName} and +	 * {@link setGroupName GroupName}, the former takes precedence. +	 * @param string the group name +	 * @see setGroupName +	 */ +	public function setUniqueGroupName($value) +	{ +		$this->setViewState('UniqueGroupName',$value,''); +	} + +	/** +	 * Gets an array of radiobuttons whose group name is the same as this radiobutton's. +	 * Note, only those radiobuttons that are on the current page hierarchy may be +	 * returned in the result. +	 * @return array list of TRadioButton with the same group +	 */ +	public function getRadioButtonsInGroup() +	{ +		$group = $this->getUniqueGroupName(); +		$buttons = array(); +		foreach(self::$_activeButtons as $control) +		{ +			if($control->getUniqueGroupName() === $group) +				$buttons[] = $control; +		} +		return $buttons; +	} + +	/** +	 * @return string the value attribute to be rendered +	 */ +	protected function getValueAttribute() +	{ +		if(($value=parent::getValueAttribute())==='') +			return $this->getUniqueID(); +		else +			return $value; +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Renders a radiobutton input element. +	 * @param THtmlWriter the writer for the rendering purpose +	 * @param string checkbox id +	 * @param string onclick js +	 */ +	protected function renderInputTag($writer,$clientID,$onclick) +	{ +		if($clientID!=='') +			$writer->addAttribute('id',$clientID); +		$writer->addAttribute('type','radio'); +		$writer->addAttribute('name',$this->getUniqueGroupName()); +		$writer->addAttribute('value',$this->getValueAttribute()); +		if(!empty($onclick)) +			$writer->addAttribute('onclick',$onclick); +		if($this->getChecked()) +			$writer->addAttribute('checked','checked'); +		if(!$this->getEnabled(true)) +			$writer->addAttribute('disabled','disabled'); + +		$page=$this->getPage(); +		if($this->getEnabled(true) +			&& $this->getEnableClientScript() +			&& $this->getAutoPostBack() +			&& $page->getClientSupportsJavaScript()) +		{ +			$this->renderClientControlScript($writer); +		} + +		if(($accesskey=$this->getAccessKey())!=='') +			$writer->addAttribute('accesskey',$accesskey); +		if(($tabindex=$this->getTabIndex())>0) +			$writer->addAttribute('tabindex',"$tabindex"); +		if($attributes=$this->getViewState('InputAttributes',null)) +			$writer->addAttributes($attributes); +		$writer->renderBeginTag('input'); +		$writer->renderEndTag(); +	} + +	/** +	 * Renders the client-script code. +	 */ +	protected function renderClientControlScript($writer) +	{ +		$cs = $this->getPage()->getClientScript(); +		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TRadioButton'; +	} +} + diff --git a/framework/Web/UI/WebControls/TRangeValidator.php b/framework/Web/UI/WebControls/TRangeValidator.php index d8d2d20d..57538e88 100644 --- a/framework/Web/UI/WebControls/TRangeValidator.php +++ b/framework/Web/UI/WebControls/TRangeValidator.php @@ -1,360 +1,360 @@ -<?php
 -/**
 - * TRangeValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TRangeValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TRangeValidator class
 - *
 - * TRangeValidator tests whether an input value is within a specified range.
 - *
 - * TRangeValidator uses three key properties to perform its validation.
 - * The {@link setMinValue MinValue} and {@link setMaxValue MaxValue}
 - * properties specify the minimum and maximum values of the valid range.
 - * The {@link setDataType DataType} property is used to specify the
 - * data type of the value and the minimum and maximum range values.
 - * These values are converted to this data type before the validation
 - * operation is performed. The following value types are supported:
 - * - <b>Integer</b> A 32-bit signed integer data type.
 - * - <b>Float</b> A double-precision floating point number data type.
 - * - <b>Date</b> A date data type. The date format can be specified by
 - *   setting {@link setDateFormat DateFormat} property, which must be recognizable
 - *   by {@link TSimpleDateFormatter}. If the property is not set,
 - *   the GNU date syntax is assumed.
 - * - <b>String</b> A string data type.
 - * - <b>StringLength</b> check for string length.
 - *
 - * If {@link setStrictComparison StrictComparison} is true, then the ranges
 - * are compared as strictly less than the max value and/or strictly greater than the min value.
 - *
 - * The TRangeValidator allows a special DataType "StringLength" that
 - * can be used to verify minimum and maximum string length. The
 - * {@link setCharset Charset} property can be used to force a particular
 - * charset for comparison. Otherwise, the application charset is used and is
 - * defaulted as UTF-8.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRangeValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TRangeValidator';
 -	}
 -
 -	/**
 -	 * @return string the minimum value of the validation range.
 -	 */
 -	public function getMinValue()
 -	{
 -		return $this->getViewState('MinValue','');
 -	}
 -
 -	/**
 -	 * Sets the minimum value of the validation range.
 -	 * @param string the minimum value
 -	 */
 -	public function setMinValue($value)
 -	{
 -		$this->setViewState('MinValue',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string the maximum value of the validation range.
 -	 */
 -	public function getMaxValue()
 -	{
 -		return $this->getViewState('MaxValue','');
 -	}
 -
 -	/**
 -	 * Sets the maximum value of the validation range.
 -	 * @param string the maximum value
 -	 */
 -	public function setMaxValue($value)
 -	{
 -		$this->setViewState('MaxValue',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @param boolean true to perform strict comparison (i.e. strictly less than max and/or strictly greater than min).
 -	 */
 -	public function setStrictComparison($value)
 -	{
 -		$this->setViewState('StrictComparison', TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean true to perform strict comparison.
 -	 */
 -	public function getStrictComparison()
 -	{
 -		return $this->getViewState('StrictComparison', false);
 -	}
 -
 -	/**
 -	 * @return TRangeValidationDataType the data type that the values being compared are
 -	 * converted to before the comparison is made. Defaults to TRangeValidationDataType::String.
 -	 */
 -	public function getDataType()
 -	{
 -		return $this->getViewState('DataType',TRangeValidationDataType::String);
 -	}
 -
 -	/**
 -	 * Sets the data type that the values being compared are converted to before the comparison is made.
 -	 * @param TRangeValidationDataType the data type
 -	 */
 -	public function setDataType($value)
 -	{
 -		$this->setViewState('DataType',TPropertyValue::ensureEnum($value,'TRangeValidationDataType'),TRangeValidationDataType::String);
 -	}
 -
 -	/**
 -     * Sets the date format for a date validation
 -     * @param string the date format value
 -     */
 -	public function setDateFormat($value)
 -	{
 -		$this->setViewState('DateFormat', $value, '');
 -	}
 -
 -	/**
 -	 * @return string the date validation date format if any
 -	 */
 -	public function getDateFormat()
 -	{
 -		return $this->getViewState('DateFormat', '');
 -	}
 -
 -	/**
 -	 * @param string charset for string length comparison.
 -	 */
 -	public function setCharset($value)
 -	{
 -		$this->setViewState('Charset', $value, '');
 -	}
 -
 -	/**
 -	 * @return string charset for string length comparison.
 -	 */
 -	public function getCharset()
 -	{
 -		return $this->getViewState('Charset', '');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input data is within the range.
 -	 * The validation always succeeds if the input data is empty.
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	protected function evaluateIsValid()
 -	{
 -		$value=$this->getValidationValue($this->getValidationTarget());
 -		if($value==='')
 -			return true;
 -
 -		switch($this->getDataType())
 -		{
 -			case TRangeValidationDataType::Integer:
 -				return $this->isValidInteger($value);
 -			case TRangeValidationDataType::Float:
 -				return $this->isValidFloat($value);
 -			case TRangeValidationDataType::Date:
 -				return $this->isValidDate($value);
 -			case TRangeValidationDataType::StringLength:
 -				return $this->isValidStringLength($value);
 -			default:
 -				return $this->isValidString($value);
 -		}
 -	}
 -
 -	/**
 -	* Determine if the value is within the integer range.
 -	* @param string value to validate true
 -	* @return boolean true if within integer range.
 -	*/
 -	protected function isValidInteger($value)
 -	{
 -		$minValue=$this->getMinValue();
 -		$maxValue=$this->getMaxValue();
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TRangeValidator class + * + * TRangeValidator tests whether an input value is within a specified range. + * + * TRangeValidator uses three key properties to perform its validation. + * The {@link setMinValue MinValue} and {@link setMaxValue MaxValue} + * properties specify the minimum and maximum values of the valid range. + * The {@link setDataType DataType} property is used to specify the + * data type of the value and the minimum and maximum range values. + * These values are converted to this data type before the validation + * operation is performed. The following value types are supported: + * - <b>Integer</b> A 32-bit signed integer data type. + * - <b>Float</b> A double-precision floating point number data type. + * - <b>Date</b> A date data type. The date format can be specified by + *   setting {@link setDateFormat DateFormat} property, which must be recognizable + *   by {@link TSimpleDateFormatter}. If the property is not set, + *   the GNU date syntax is assumed. + * - <b>String</b> A string data type. + * - <b>StringLength</b> check for string length. + * + * If {@link setStrictComparison StrictComparison} is true, then the ranges + * are compared as strictly less than the max value and/or strictly greater than the min value. + * + * The TRangeValidator allows a special DataType "StringLength" that + * can be used to verify minimum and maximum string length. The + * {@link setCharset Charset} property can be used to force a particular + * charset for comparison. Otherwise, the application charset is used and is + * defaulted as UTF-8. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRangeValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TRangeValidator'; +	} + +	/** +	 * @return string the minimum value of the validation range. +	 */ +	public function getMinValue() +	{ +		return $this->getViewState('MinValue',''); +	} + +	/** +	 * Sets the minimum value of the validation range. +	 * @param string the minimum value +	 */ +	public function setMinValue($value) +	{ +		$this->setViewState('MinValue',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string the maximum value of the validation range. +	 */ +	public function getMaxValue() +	{ +		return $this->getViewState('MaxValue',''); +	} + +	/** +	 * Sets the maximum value of the validation range. +	 * @param string the maximum value +	 */ +	public function setMaxValue($value) +	{ +		$this->setViewState('MaxValue',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @param boolean true to perform strict comparison (i.e. strictly less than max and/or strictly greater than min). +	 */ +	public function setStrictComparison($value) +	{ +		$this->setViewState('StrictComparison', TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean true to perform strict comparison. +	 */ +	public function getStrictComparison() +	{ +		return $this->getViewState('StrictComparison', false); +	} + +	/** +	 * @return TRangeValidationDataType the data type that the values being compared are +	 * converted to before the comparison is made. Defaults to TRangeValidationDataType::String. +	 */ +	public function getDataType() +	{ +		return $this->getViewState('DataType',TRangeValidationDataType::String); +	} + +	/** +	 * Sets the data type that the values being compared are converted to before the comparison is made. +	 * @param TRangeValidationDataType the data type +	 */ +	public function setDataType($value) +	{ +		$this->setViewState('DataType',TPropertyValue::ensureEnum($value,'TRangeValidationDataType'),TRangeValidationDataType::String); +	} + +	/** +     * Sets the date format for a date validation +     * @param string the date format value +     */ +	public function setDateFormat($value) +	{ +		$this->setViewState('DateFormat', $value, ''); +	} + +	/** +	 * @return string the date validation date format if any +	 */ +	public function getDateFormat() +	{ +		return $this->getViewState('DateFormat', ''); +	} + +	/** +	 * @param string charset for string length comparison. +	 */ +	public function setCharset($value) +	{ +		$this->setViewState('Charset', $value, ''); +	} + +	/** +	 * @return string charset for string length comparison. +	 */ +	public function getCharset() +	{ +		return $this->getViewState('Charset', ''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input data is within the range. +	 * The validation always succeeds if the input data is empty. +	 * @return boolean whether the validation succeeds +	 */ +	protected function evaluateIsValid() +	{ +		$value=$this->getValidationValue($this->getValidationTarget()); +		if($value==='') +			return true; + +		switch($this->getDataType()) +		{ +			case TRangeValidationDataType::Integer: +				return $this->isValidInteger($value); +			case TRangeValidationDataType::Float: +				return $this->isValidFloat($value); +			case TRangeValidationDataType::Date: +				return $this->isValidDate($value); +			case TRangeValidationDataType::StringLength: +				return $this->isValidStringLength($value); +			default: +				return $this->isValidString($value); +		} +	} + +	/** +	* Determine if the value is within the integer range. +	* @param string value to validate true +	* @return boolean true if within integer range. +	*/ +	protected function isValidInteger($value) +	{ +		$minValue=$this->getMinValue(); +		$maxValue=$this->getMaxValue(); +  		$valid=preg_match('/^[-+]?[0-9]+$/',trim($value)); -		$value=intval($value);
 -		if($minValue!=='')
 -			$valid=$valid && $this->isGreaterThan($value, intval($minValue));
 -		if($maxValue!=='')
 -			$valid=$valid && $this->isLessThan($value,intval($maxValue));
 -		return $valid;
 -	}
 -
 -	protected function isLessThan($left,$right)
 -	{
 -		return $this->getStrictComparison() ? $left < $right : $left <= $right;
 -	}
 -
 -	protected function isGreaterThan($left, $right)
 -	{
 -		return $this->getStrictComparison() ? $left > $right : $left >= $right;
 -	}
 -
 -	/**
 -	 * Determine if the value is within the specified float range.
 -	 * @param string value to validate
 -	 * @return boolean true if within range.
 -	 */
 -	protected function isValidFloat($value)
 -	{
 -		$minValue=$this->getMinValue();
 -		$maxValue=$this->getMaxValue();
 +		$value=intval($value); +		if($minValue!=='') +			$valid=$valid && $this->isGreaterThan($value, intval($minValue)); +		if($maxValue!=='') +			$valid=$valid && $this->isLessThan($value,intval($maxValue)); +		return $valid; +	} + +	protected function isLessThan($left,$right) +	{ +		return $this->getStrictComparison() ? $left < $right : $left <= $right; +	} + +	protected function isGreaterThan($left, $right) +	{ +		return $this->getStrictComparison() ? $left > $right : $left >= $right; +	} + +	/** +	 * Determine if the value is within the specified float range. +	 * @param string value to validate +	 * @return boolean true if within range. +	 */ +	protected function isValidFloat($value) +	{ +		$minValue=$this->getMinValue(); +		$maxValue=$this->getMaxValue(); + +		$valid=preg_match('/^[-+]?([0-9]*\.)?[0-9]+([eE][-+]?[0-9]+)?$/',trim($value)); +		$value=floatval($value); +		if($minValue!=='') +			$valid=$valid && $this->isGreaterThan($value,floatval($minValue)); +		if($maxValue!=='') +			$valid=$valid && $this->isLessThan($value,floatval($maxValue)); +		return $valid; +	} + +	/** +	 * Determine if the date is within the specified range. +	 * Uses pradoParseDate and strtotime to get the date from string. +	 * @param string date as string to validate +	 * @return boolean true if within range. +	 */ +	protected function isValidDate($value) +	{ +		$minValue=$this->getMinValue(); +		$maxValue=$this->getMaxValue(); + +		$valid=true; + +		$dateFormat = $this->getDateFormat(); +		if($dateFormat!=='') +		{ +			$formatter=Prado::createComponent('System.Util.TSimpleDateFormatter', $dateFormat); +			$value = $formatter->parse($value, $dateFormat); +			if($minValue!=='') +				$valid=$valid && $this->isGreaterThan($value,$formatter->parse($minValue)); +			if($maxValue!=='') +				$valid=$valid && $this->isLessThan($value,$formatter->parse($maxValue)); +			return $valid; +		} +		else +		{ +			$value=strtotime($value); +			if($minValue!=='') +				$valid=$valid && $this->isGreaterThan($value,strtotime($minValue)); +			if($maxValue!=='') +				$valid=$valid && $this->isLessThan($value,strtotime($maxValue)); +			return $valid; +		} +	} + +	/** +	 * Compare the string with a minimum and a maxiumum value. +	 * Uses strcmp for comparision. +	 * @param string value to compare with. +	 * @return boolean true if the string is within range. +	 */ +	protected function isValidString($value) +	{ +		$minValue=$this->getMinValue(); +		$maxValue=$this->getMaxValue(); + +		$valid=true; +		if($minValue!=='') +			$valid=$valid && $this->isGreaterThan(strcmp($value,$minValue),0); +		if($maxValue!=='') +			$valid=$valid && $this->isLessThan(strcmp($value,$maxValue),0); +		return $valid; +	} + +	/** +	 * @param string string for comparision +	 * @return boolean true if min and max string length are satisfied. +	 */ +	protected function isValidStringLength($value) +	{ +		$minValue=$this->getMinValue(); +		$maxValue=$this->getMaxValue(); + +		$valid=true; +		$charset = $this->getCharset(); +		if($charset==='') +		{ +			$app= $this->getApplication()->getGlobalization(); +			$charset = $app ? $app->getCharset() : null; +			if(!$charset) +				$charset = 'UTF-8'; +		} + +		$length = iconv_strlen($value, $charset); +		if($minValue!=='') +			$valid = $valid && $this->isGreaterThan($length,intval($minValue)); +		if($maxValue!=='') +			$valid = $valid && $this->isLessThan($length,intval($maxValue)); +		return $valid; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options=parent::getClientScriptOptions(); +		$options['MinValue']=$this->getMinValue(); +		$options['MaxValue']=$this->getMaxValue(); +		$options['DataType']=$this->getDataType(); +		$options['StrictComparison']=$this->getStrictComparison(); +		if(($dateFormat=$this->getDateFormat())!=='') +			$options['DateFormat']=$dateFormat; +		return $options; +	} +} + -		$valid=preg_match('/^[-+]?([0-9]*\.)?[0-9]+([eE][-+]?[0-9]+)?$/',trim($value));
 -		$value=floatval($value);
 -		if($minValue!=='')
 -			$valid=$valid && $this->isGreaterThan($value,floatval($minValue));
 -		if($maxValue!=='')
 -			$valid=$valid && $this->isLessThan($value,floatval($maxValue));
 -		return $valid;
 -	}
 -
 -	/**
 -	 * Determine if the date is within the specified range.
 -	 * Uses pradoParseDate and strtotime to get the date from string.
 -	 * @param string date as string to validate
 -	 * @return boolean true if within range.
 -	 */
 -	protected function isValidDate($value)
 -	{
 -		$minValue=$this->getMinValue();
 -		$maxValue=$this->getMaxValue();
 -
 -		$valid=true;
 -
 -		$dateFormat = $this->getDateFormat();
 -		if($dateFormat!=='')
 -		{
 -			$formatter=Prado::createComponent('System.Util.TSimpleDateFormatter', $dateFormat);
 -			$value = $formatter->parse($value, $dateFormat);
 -			if($minValue!=='')
 -				$valid=$valid && $this->isGreaterThan($value,$formatter->parse($minValue));
 -			if($maxValue!=='')
 -				$valid=$valid && $this->isLessThan($value,$formatter->parse($maxValue));
 -			return $valid;
 -		}
 -		else
 -		{
 -			$value=strtotime($value);
 -			if($minValue!=='')
 -				$valid=$valid && $this->isGreaterThan($value,strtotime($minValue));
 -			if($maxValue!=='')
 -				$valid=$valid && $this->isLessThan($value,strtotime($maxValue));
 -			return $valid;
 -		}
 -	}
 -
 -	/**
 -	 * Compare the string with a minimum and a maxiumum value.
 -	 * Uses strcmp for comparision.
 -	 * @param string value to compare with.
 -	 * @return boolean true if the string is within range.
 -	 */
 -	protected function isValidString($value)
 -	{
 -		$minValue=$this->getMinValue();
 -		$maxValue=$this->getMaxValue();
 -
 -		$valid=true;
 -		if($minValue!=='')
 -			$valid=$valid && $this->isGreaterThan(strcmp($value,$minValue),0);
 -		if($maxValue!=='')
 -			$valid=$valid && $this->isLessThan(strcmp($value,$maxValue),0);
 -		return $valid;
 -	}
 -
 -	/**
 -	 * @param string string for comparision
 -	 * @return boolean true if min and max string length are satisfied.
 -	 */
 -	protected function isValidStringLength($value)
 -	{
 -		$minValue=$this->getMinValue();
 -		$maxValue=$this->getMaxValue();
 -
 -		$valid=true;
 -		$charset = $this->getCharset();
 -		if($charset==='')
 -		{
 -			$app= $this->getApplication()->getGlobalization();
 -			$charset = $app ? $app->getCharset() : null;
 -			if(!$charset)
 -				$charset = 'UTF-8';
 -		}
 -
 -		$length = iconv_strlen($value, $charset);
 -		if($minValue!=='')
 -			$valid = $valid && $this->isGreaterThan($length,intval($minValue));
 -		if($maxValue!=='')
 -			$valid = $valid && $this->isLessThan($length,intval($maxValue));
 -		return $valid;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options=parent::getClientScriptOptions();
 -		$options['MinValue']=$this->getMinValue();
 -		$options['MaxValue']=$this->getMaxValue();
 -		$options['DataType']=$this->getDataType();
 -		$options['StrictComparison']=$this->getStrictComparison();
 -		if(($dateFormat=$this->getDateFormat())!=='')
 -			$options['DateFormat']=$dateFormat;
 -		return $options;
 -	}
 -}
 -
 -
 -/**
 - * TRangeValidationDataType class.
 - * TRangeValidationDataType defines the enumerable type for the possible data types that
 - * a range validator can validate upon.
 - *
 - * The following enumerable values are defined:
 - * - Integer
 - * - Float
 - * - Date
 - * - String
 - * - StringLength
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TRangeValidationDataType extends TValidationDataType
 -{
 -	const StringLength='StringLength';
 -}
 +/** + * TRangeValidationDataType class. + * TRangeValidationDataType defines the enumerable type for the possible data types that + * a range validator can validate upon. + * + * The following enumerable values are defined: + * - Integer + * - Float + * - Date + * - String + * - StringLength + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TRangeValidationDataType extends TValidationDataType +{ +	const StringLength='StringLength'; +} diff --git a/framework/Web/UI/WebControls/TRatingList.php b/framework/Web/UI/WebControls/TRatingList.php index dfb11371..cc813755 100644 --- a/framework/Web/UI/WebControls/TRatingList.php +++ b/framework/Web/UI/WebControls/TRatingList.php @@ -1,359 +1,359 @@ -<?php
 -/**
 - * TRatingList class file.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TRadioButtonList class
 - */
 -Prado::using('System.Web.UI.WebControls.TRadioButtonList');
 -
 -/**
 - * TRatingList class.
 - *
 - * This class is EXPERIMENTAL.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @author Bradley Booms <bradley[dot]booms[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRatingList extends TRadioButtonList
 -{
 -	/**
 -	 * Script path relative to the TClientScriptManager::SCRIPT_PATH
 -	 */
 -	const SCRIPT_PATH='prado/ratings';
 -
 -	/**
 -	 * @var array list of published rating images.
 -	 */
 -	private $_ratingImages = array();
 -
 -	/**
 -	 * Sets the default repeat direction to horizontal.
 -	 */
 -	public function __construct()
 -	{
 -		parent::__construct();
 -		$this->setRepeatDirection(TRepeatDirection::Horizontal);
 -	}
 -
 -	/**
 -	 * @return boolean whether the items in the column can be edited. Defaults to false.
 -	 */
 -	public function getReadOnly()
 -	{
 -		return $this->getViewState('ReadOnly',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the items in the column can be edited
 -	 */
 -	public function setReadOnly($value)
 -	{
 -		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Wrapper for {@link setReadOnly ReadOnly} property.
 -	 * @return boolean whether the rating list can be edited. Defaults to true.
 -	 */
 -	public function getAllowInput()
 -	{
 -		return !$this->getReadOnly();
 -	}
 -
 -	/**
 -	 * Wrapper for {@link setReadOnly ReadOnly} property.
 -	 * @param boolean whether the rating list can be edited
 -	 */
 -	public function setAllowInput($value)
 -	{
 -		$this->setReadOnly(!TPropertyValue::ensureBoolean($value));
 -	}
 -
 -	/**
 -	 * Wrapper for {@link setReadOnly ReadOnly} property.
 -	 * @param boolean whether the rating list can be edited
 -	 */
 -	public function setEnabled($value)
 -	{
 -		$this->setReadOnly(!TPropertyValue::ensureBoolean($value));
 -	}
 -
 -	/**
 -	 * The repeat layout must be Table.
 -	 * @param string repeat layout type
 -	 * @throws TInvaliddataValueException when repeat layout is not Table.
 -	 */
 -	public function setRepeatLayout($value)
 -	{
 -		if($value!==TRepeatLayout::Table)
 -			throw new TInvalidDataValueException('ratinglist_table_layout_only');
 -		else
 -			parent::setRepeatLayout($value);
 -	}
 -
 -	/**
 -	 * @return float rating value.
 -	 */
 -	public function getRating()
 -	{
 -		$rating = $this->getViewState('Rating', null);
 -		if ($rating === null)
 -			return $this->getSelectedIndex()+1;
 -		else
 -			return $rating;
 -	}
 -
 -	/**
 -	 * @param float rating value, also sets the selected Index
 -	 */
 -	public function setRating($value)
 -	{
 -		$value = TPropertyValue::ensureFloat($value);
 -		$this->setViewState('Rating', $value, null);
 -		$index = $this->getRatingIndex($value);
 -		parent::setSelectedIndex($index);
 -	}
 -	
 -	public function setSelectedIndex($value)
 -	{
 -		$this->setRating($value+1);
 -		parent::setSelectedIndex($value);
 -	}
 -
 -	/**
 -	 * @param float rating value
 -	 * @return int rating as integer
 -	 */
 -	protected function getRatingIndex($rating)
 -	{
 -		$interval = $this->getHalfRatingInterval();
 -		$base = intval($rating)-1;
 -		$remainder = $rating-$base-1;
 -		return $remainder > $interval[1] ? $base+1 : $base;
 -	}
 -
 -	/**
 -	 * @param int change the rating selection index
 -	 */
 -	public function onSelectedIndexChanged($param)
 -	{
 -		$value = $this->getRating();
 -		$value = TPropertyValue::ensureInteger($value);
 -		$this->setRating($value);
 -		parent::onSelectedIndexChanged($param);
 -	}
 -
 -	/**
 -	 * @return string control or html element ID for displaying a caption.
 -	 */
 -	public function getCaptionID()
 -	{
 -		return $this->getViewState('CaptionID', '');
 -	}
 -
 -	/**
 -	 * @param string control or html element ID for displaying a caption.
 -	 */
 -	public function setCaptionID($value)
 -	{
 -		$this->setViewState('CaptionID', $value, '');
 -	}
 -
 -	protected function getCaptionControl()
 -	{
 -		if(($id=$this->getCaptionID())!=='')
 -		{
 -			if($control=$this->getParent()->findControl($id))
 -				return $control;
 -		}
 -		throw new TInvalidDataValueException(
 -			'ratinglist_invalid_caption_id',$id,$this->getID());
 -	}
 -
 -	/**
 -	 * @return string caption text. Default is "Rate It:".
 -	 */
 -	public function getCaption()
 -	{
 -		return $this->getCaptionControl()->getText();
 -	}
 -
 -	/**
 -	 * @return TRatingListStyle current rating style
 -	 */
 - 	public function setCaption($value)
 - 	{
 -		$this->getCaptionControl()->setText($value);
 - 	}
 -
 -	/**
 -	 * @param string set the rating style, default is "default"
 -	 */
 -	public function setRatingStyle($value)
 - 	{
 -	   $this->setViewState('RatingStyle', $value, 'default');
 - 	}
 -
 -	/**
 -	 * @return TRatingListStyle current rating style
 -	 */
 -	public function getRatingStyle()
 - 	{
 -	   return $this->getViewState('RatingStyle', 'default');
 - 	}
 - 
 - 	/**
 -	 * @return string rating style css class name.
 - 	 */
 -	protected function getRatingStyleCssClass()
 - 	{
 -		return 'TRatingList_'.$this->getRatingStyle();
 - 	}
 -
 -	/**
 -	 * Sets the interval such that those rating values within the interval
 -	 * will be considered as a half star rating.
 -	 * @param array rating display half value interval, default is array(0.3, 0.7);
 -	 */
 -	public function setHalfRatingInterval($value)
 - 	{
 -		$this->setViewState('HalfRating',
 -				TPropertyValue::ensureArray($value), array(0.3, 0.7));
 - 	}
 -
 -	/**
 -	 * @return array rating display half value interval, default is array(0.3, 0.7);
 -	 */
 -	public function getHalfRatingInterval()
 - 	{
 -		return $this->getViewState('HalfRating', array(0.3, 0.7));
 - 	}
 -
 -	/**
 -	 * @return array list of post back options.
 -	 */
 -	protected function getPostBackOptions()
 - 	{
 -		$options = parent::getPostBackOptions();
 -		$options['AutoPostBack'] = $this->getAutoPostBack();
 -		$options['ReadOnly'] = $this->getReadOnly();
 -		$options['Style'] = $this->getRatingStyleCssClass();
 -		$options['CaptionID'] = $this->getCaptionControlID();
 -		$options['SelectedIndex'] = $this->getSelectedIndex();
 -		$options['Rating'] = $this->getRating();
 -		$options['HalfRating'] = $this->getHalfRatingInterval();
 -		return $options;
 - 	}
 -
 - 	/**
 -	 * @return string find the client ID of the caption control.
 - 	 */
 -	protected function getCaptionControlID()
 - 	{
 -		if(($id=$this->getCaptionID())!=='')
 - 		{
 -			if($control=$this->getParent()->findControl($id))
 -			{
 -				if($control->getVisible(true))
 -					return $control->getClientID();
 -			}
 -			else
 -				return $id;
 - 		}
 -		return '';
 - 	}
 -
 -	/**
 -	 * Publish the the rating style css file and rating image files.
 -	 */
 -	public function onPreRender($param)
 - 	{
 -		parent::onPreRender($param);
 -		$this->publishStyle($this->getRatingStyle());
 -		$this->_ratingImages = $this->publishImages($this->getRatingStyle());
 - 		$this->registerClientScript();
 -	}
 -
 -	/**
 -	 * @param string rating style name
 -	 * @return string URL of the css style file
 -	 */
 -	protected function publishStyle($style)
 - 	{
 -		$cs = $this->getPage()->getClientScript();
 -		$url = $this->getAssetUrl($style.'.css');
 -		if(!$cs->isStyleSheetFileRegistered($url))
 -			$cs->registerStyleSheetFile($url, $url);
 -		return $url;
 - 	}
 -
 -	/**
 -	 * @param string rating style name
 -	 * @param string rating image file extension, default is '.gif'
 -	 * @return array URL of publish the rating images
 -	 */
 -	protected function publishImages($style, $fileExt='.gif')
 - 	{
 -		$types = array('blank', 'selected', 'half', 'combined');
 -		$files = array();
 -		foreach($types as $type)
 -			$files[$type] = $this->getAssetUrl("{$style}_{$type}{$fileExt}");
 -		return $files;
 - 	}
 -
 -	/**
 -	 * Registers the relevant JavaScript.
 -	 */
 -	protected function registerClientScript()
 -	{
 -		$cs=$this->getPage()->getClientScript();
 -		$cs->registerPradoScript('ratings');
 -	}
 -
 -	/**
 -	 * @param string asset file in the self::SCRIPT_PATH directory.
 -	 * @return string asset file url.
 -	 */
 -	protected function getAssetUrl($file='')
 - 	{
 -		$base = $this->getPage()->getClientScript()->getPradoScriptAssetUrl();
 -		return $base.'/'.self::SCRIPT_PATH.'/'.$file;
 - 	}
 -
 -	/**
 -	 * Add rating style class name to the class attribute
 -	 * when {@link setReadOnly ReadOnly} property is true and when the
 -	 * {@link setCssClass CssClass} property is empty.
 -	 * @param THtmlWriter renderer
 -	 */
 -	public function render($writer)
 - 	{
 -		$writer->addAttribute('id',$this->getClientID());
 -		$this->getPage()->getClientScript()->registerPostBackControl(
 -			$this->getClientClassName(), $this->getPostBackOptions());
 -		parent::render($writer);
 - 	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TRatingList';
 -	}
 -}
 -
 +<?php +/** + * TRatingList class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TRadioButtonList class + */ +Prado::using('System.Web.UI.WebControls.TRadioButtonList'); + +/** + * TRatingList class. + * + * This class is EXPERIMENTAL. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @author Bradley Booms <bradley[dot]booms[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRatingList extends TRadioButtonList +{ +	/** +	 * Script path relative to the TClientScriptManager::SCRIPT_PATH +	 */ +	const SCRIPT_PATH='prado/ratings'; + +	/** +	 * @var array list of published rating images. +	 */ +	private $_ratingImages = array(); + +	/** +	 * Sets the default repeat direction to horizontal. +	 */ +	public function __construct() +	{ +		parent::__construct(); +		$this->setRepeatDirection(TRepeatDirection::Horizontal); +	} + +	/** +	 * @return boolean whether the items in the column can be edited. Defaults to false. +	 */ +	public function getReadOnly() +	{ +		return $this->getViewState('ReadOnly',false); +	} + +	/** +	 * @param boolean whether the items in the column can be edited +	 */ +	public function setReadOnly($value) +	{ +		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Wrapper for {@link setReadOnly ReadOnly} property. +	 * @return boolean whether the rating list can be edited. Defaults to true. +	 */ +	public function getAllowInput() +	{ +		return !$this->getReadOnly(); +	} + +	/** +	 * Wrapper for {@link setReadOnly ReadOnly} property. +	 * @param boolean whether the rating list can be edited +	 */ +	public function setAllowInput($value) +	{ +		$this->setReadOnly(!TPropertyValue::ensureBoolean($value)); +	} + +	/** +	 * Wrapper for {@link setReadOnly ReadOnly} property. +	 * @param boolean whether the rating list can be edited +	 */ +	public function setEnabled($value) +	{ +		$this->setReadOnly(!TPropertyValue::ensureBoolean($value)); +	} + +	/** +	 * The repeat layout must be Table. +	 * @param string repeat layout type +	 * @throws TInvaliddataValueException when repeat layout is not Table. +	 */ +	public function setRepeatLayout($value) +	{ +		if($value!==TRepeatLayout::Table) +			throw new TInvalidDataValueException('ratinglist_table_layout_only'); +		else +			parent::setRepeatLayout($value); +	} + +	/** +	 * @return float rating value. +	 */ +	public function getRating() +	{ +		$rating = $this->getViewState('Rating', null); +		if ($rating === null) +			return $this->getSelectedIndex()+1; +		else +			return $rating; +	} + +	/** +	 * @param float rating value, also sets the selected Index +	 */ +	public function setRating($value) +	{ +		$value = TPropertyValue::ensureFloat($value); +		$this->setViewState('Rating', $value, null); +		$index = $this->getRatingIndex($value); +		parent::setSelectedIndex($index); +	} +	 +	public function setSelectedIndex($value) +	{ +		$this->setRating($value+1); +		parent::setSelectedIndex($value); +	} + +	/** +	 * @param float rating value +	 * @return int rating as integer +	 */ +	protected function getRatingIndex($rating) +	{ +		$interval = $this->getHalfRatingInterval(); +		$base = intval($rating)-1; +		$remainder = $rating-$base-1; +		return $remainder > $interval[1] ? $base+1 : $base; +	} + +	/** +	 * @param int change the rating selection index +	 */ +	public function onSelectedIndexChanged($param) +	{ +		$value = $this->getRating(); +		$value = TPropertyValue::ensureInteger($value); +		$this->setRating($value); +		parent::onSelectedIndexChanged($param); +	} + +	/** +	 * @return string control or html element ID for displaying a caption. +	 */ +	public function getCaptionID() +	{ +		return $this->getViewState('CaptionID', ''); +	} + +	/** +	 * @param string control or html element ID for displaying a caption. +	 */ +	public function setCaptionID($value) +	{ +		$this->setViewState('CaptionID', $value, ''); +	} + +	protected function getCaptionControl() +	{ +		if(($id=$this->getCaptionID())!=='') +		{ +			if($control=$this->getParent()->findControl($id)) +				return $control; +		} +		throw new TInvalidDataValueException( +			'ratinglist_invalid_caption_id',$id,$this->getID()); +	} + +	/** +	 * @return string caption text. Default is "Rate It:". +	 */ +	public function getCaption() +	{ +		return $this->getCaptionControl()->getText(); +	} + +	/** +	 * @return TRatingListStyle current rating style +	 */ + 	public function setCaption($value) + 	{ +		$this->getCaptionControl()->setText($value); + 	} + +	/** +	 * @param string set the rating style, default is "default" +	 */ +	public function setRatingStyle($value) + 	{ +	   $this->setViewState('RatingStyle', $value, 'default'); + 	} + +	/** +	 * @return TRatingListStyle current rating style +	 */ +	public function getRatingStyle() + 	{ +	   return $this->getViewState('RatingStyle', 'default'); + 	} +  + 	/** +	 * @return string rating style css class name. + 	 */ +	protected function getRatingStyleCssClass() + 	{ +		return 'TRatingList_'.$this->getRatingStyle(); + 	} + +	/** +	 * Sets the interval such that those rating values within the interval +	 * will be considered as a half star rating. +	 * @param array rating display half value interval, default is array(0.3, 0.7); +	 */ +	public function setHalfRatingInterval($value) + 	{ +		$this->setViewState('HalfRating', +				TPropertyValue::ensureArray($value), array(0.3, 0.7)); + 	} + +	/** +	 * @return array rating display half value interval, default is array(0.3, 0.7); +	 */ +	public function getHalfRatingInterval() + 	{ +		return $this->getViewState('HalfRating', array(0.3, 0.7)); + 	} + +	/** +	 * @return array list of post back options. +	 */ +	protected function getPostBackOptions() + 	{ +		$options = parent::getPostBackOptions(); +		$options['AutoPostBack'] = $this->getAutoPostBack(); +		$options['ReadOnly'] = $this->getReadOnly(); +		$options['Style'] = $this->getRatingStyleCssClass(); +		$options['CaptionID'] = $this->getCaptionControlID(); +		$options['SelectedIndex'] = $this->getSelectedIndex(); +		$options['Rating'] = $this->getRating(); +		$options['HalfRating'] = $this->getHalfRatingInterval(); +		return $options; + 	} + + 	/** +	 * @return string find the client ID of the caption control. + 	 */ +	protected function getCaptionControlID() + 	{ +		if(($id=$this->getCaptionID())!=='') + 		{ +			if($control=$this->getParent()->findControl($id)) +			{ +				if($control->getVisible(true)) +					return $control->getClientID(); +			} +			else +				return $id; + 		} +		return ''; + 	} + +	/** +	 * Publish the the rating style css file and rating image files. +	 */ +	public function onPreRender($param) + 	{ +		parent::onPreRender($param); +		$this->publishStyle($this->getRatingStyle()); +		$this->_ratingImages = $this->publishImages($this->getRatingStyle()); + 		$this->registerClientScript(); +	} + +	/** +	 * @param string rating style name +	 * @return string URL of the css style file +	 */ +	protected function publishStyle($style) + 	{ +		$cs = $this->getPage()->getClientScript(); +		$url = $this->getAssetUrl($style.'.css'); +		if(!$cs->isStyleSheetFileRegistered($url)) +			$cs->registerStyleSheetFile($url, $url); +		return $url; + 	} + +	/** +	 * @param string rating style name +	 * @param string rating image file extension, default is '.gif' +	 * @return array URL of publish the rating images +	 */ +	protected function publishImages($style, $fileExt='.gif') + 	{ +		$types = array('blank', 'selected', 'half', 'combined'); +		$files = array(); +		foreach($types as $type) +			$files[$type] = $this->getAssetUrl("{$style}_{$type}{$fileExt}"); +		return $files; + 	} + +	/** +	 * Registers the relevant JavaScript. +	 */ +	protected function registerClientScript() +	{ +		$cs=$this->getPage()->getClientScript(); +		$cs->registerPradoScript('ratings'); +	} + +	/** +	 * @param string asset file in the self::SCRIPT_PATH directory. +	 * @return string asset file url. +	 */ +	protected function getAssetUrl($file='') + 	{ +		$base = $this->getPage()->getClientScript()->getPradoScriptAssetUrl(); +		return $base.'/'.self::SCRIPT_PATH.'/'.$file; + 	} + +	/** +	 * Add rating style class name to the class attribute +	 * when {@link setReadOnly ReadOnly} property is true and when the +	 * {@link setCssClass CssClass} property is empty. +	 * @param THtmlWriter renderer +	 */ +	public function render($writer) + 	{ +		$writer->addAttribute('id',$this->getClientID()); +		$this->getPage()->getClientScript()->registerPostBackControl( +			$this->getClientClassName(), $this->getPostBackOptions()); +		parent::render($writer); + 	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TRatingList'; +	} +} + diff --git a/framework/Web/UI/WebControls/TReCaptcha.php b/framework/Web/UI/WebControls/TReCaptcha.php index b9ba0070..cbdc2e36 100644 --- a/framework/Web/UI/WebControls/TReCaptcha.php +++ b/framework/Web/UI/WebControls/TReCaptcha.php @@ -1,233 +1,233 @@ -<?php
 -
 -/**
 - * TReCaptcha class file
 - *
 - * @author Bérczi Gábor <gabor.berczi@devworx.hu>
 - * @link http://www.devworx.hu/
 - * @copyright Copyright © 2011 DevWorx
 - * @license http://www.pradosoft.com/license/
 - * @package System.Web.UI.WebControls
 - */
 -
 -	Prado::using('System.3rdParty.ReCaptcha.recaptchalib');
 -
 -/**
 - * TReCaptcha class.
 - *
 - * TReCaptcha displays a reCAPTCHA (a token displayed as an image) that can be used
 - * to determine if the input is entered by a real user instead of some program. It can
 - * also prevent multiple submits of the same form either by accident, or on purpose (ie. spamming).
 - *
 - * The reCAPTCHA to solve (a string consisting of two separate words) displayed is automatically
 - * generated by the reCAPTCHA system at recaptcha.net. However, in order to use the services
 - * of the site you will need to register and get a public and a private API key pair, and 
 - * supply those to the reCAPTCHA control through setting the {@link setPrivateKey PrivateKey} 
 - * and {@link setPublicKey PublicKey} properties. 
 - *
 - * Currently the reCAPTCHA API supports only one reCAPTCHA field per page, so you MUST make sure that all 
 - * your input is protected and validated by a single reCAPTCHA control. Placing more than one reCAPTCHA
 - * control on the page will lead to unpredictable results, and the user will most likely unable to solve 
 - * any of them successfully.
 - *
 - * Upon postback, user input can be validated by calling {@link validate()}.
 - * The {@link TReCaptchaValidator} control can also be used to do validation, which provides
 - * server-side validation. Calling (@link validate()) will invalidate the token supplied, so all consecutive
 - * calls to the method - without solving a new captcha - will return false. Therefore if implementing a multi-stage
 - * input process, you must make sure that you call validate() only once, either at the end of the input process, or 
 - * you store the result till the end of the processing.
 - *
 - * The following template shows a typical use of TReCaptcha control:
 - * <code>
 - * <com:TReCaptcha ID="Captcha"
 - *                 PublicKey="..."
 - *                 PrivateKey="..."
 - * />
 - * <com:TReCaptchaValidator ControlToValidate="Captcha"
 - *                          ErrorMessage="You are challenged!" />
 - * </code>
 - *
 - * @author Bérczi Gábor <gabor.berczi@devworx.hu>
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -class TReCaptcha extends TWebControl implements IValidatable
 -{
 -	private $_isValid=true;
 -
 -	const ChallengeFieldName = 'recaptcha_challenge_field';
 -	const ResponseFieldName = 'recaptcha_response_field';
 -
 -	public function getTagName()
 -	{
 -		return 'span';
 -	}
 -	
 -	/**
 -	 * Returns true if this control validated successfully. 
 -	 * Defaults to true.
 -	 * @return bool wether this control validated successfully.
 -	 */
 -	public function getIsValid()
 -	{
 -		return $this->_isValid;
 -	}
 -	/**
 -	 * @param bool wether this control is valid.
 -	 */
 -	public function setIsValid($value)
 -	{
 -		$this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -	
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->Request[$this->getChallengeFieldName()];
 -	}
 -
 -	public function getPublicKey()
 -	{
 -		return $this->getViewState('PublicKey');
 -	}
 -
 -	public function setPublicKey($value)
 -	{
 -		return $this->setViewState('PublicKey', TPropertyValue::ensureString($value));
 -	}
 -
 -	public function getPrivateKey()
 -	{
 -		return $this->getViewState('PrivateKey');
 -	}
 -
 -	public function setPrivateKey($value)
 -	{
 -		return $this->setViewState('PrivateKey', TPropertyValue::ensureString($value));
 -	}
 -	
 -	public function getThemeName()
 -	{
 -		return $this->getViewState('ThemeName');
 -	}
 -
 -	public function setThemeName($value)
 -	{
 -		return $this->setViewState('ThemeName', TPropertyValue::ensureString($value));
 -	}
 -
 -	public function getCustomTranslations()
 -	{
 -		return TPropertyValue::ensureArray($this->getViewState('CustomTranslations'));
 -	}
 -
 -	public function setCustomTranslations($value)
 -	{
 -		return $this->setViewState('CustomTranslations', TPropertyValue::ensureArray($value));
 -	}
 -
 -	public function getLanguage()
 -	{
 -		return $this->getViewState('Language');
 -	}
 -
 -	public function setLanguage($value)
 -	{
 -		return $this->setViewState('Language', TPropertyValue::ensureString($value));
 -	}
 -
 -	protected function getChallengeFieldName()
 -	{
 -		return /*$this->ClientID.'_'.*/self::ChallengeFieldName;
 -	}
 -	
 -	public function getResponseFieldName()
 -	{
 -		return /*$this->ClientID.'_'.*/self::ResponseFieldName;
 -	}
 -	
 -	public function getClientSideOptions()
 -	{
 -		$options = array();
 -		if ($theme = $this->getThemeName())
 -			$options['theme'] = $theme;
 -		if ($lang = $this->getLanguage())
 -			$options['lang'] = $lang;
 -		if ($trans = $this->getCustomTranslations())
 -			$options['custom_translations'] = $trans;
 -		return $options;
 -	}
 -
 -	public function validate()
 -	{
 -		if (!
 -		      (
 -			($challenge = @$_POST[$this->getChallengeFieldName()])
 -			and
 -			($response = @$_POST[$this->getResponseFieldName()])
 -		      )
 -                   )
 -		   return false;
 -
 -		$resp = recaptcha_check_answer(
 -			$this->getPrivateKey(),
 -			$_SERVER["REMOTE_ADDR"],
 -			$challenge,
 -			$response
 -		); 
 -		return ($resp->is_valid==1);
 -	}
 -
 -	/**
 -	 * Checks for API keys
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -
 -		if("" == $this->getPublicKey())
 -			throw new TConfigurationException('recaptcha_publickey_unknown');
 -		if("" == $this->getPrivateKey())
 -			throw new TConfigurationException('recaptcha_privatekey_unknown');
 -
 -		// need to register captcha fields so they will be sent back also in callbacks 
 -		$page = $this->getPage();
 -		$page->registerRequiresPostData($this->getChallengeFieldName());
 -		$page->registerRequiresPostData($this->getResponseFieldName());
 -	}
 -
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		$writer->addAttribute('id',$this->getClientID());
 -	}
 -
 -	public function regenerateToken()
 -	{
 -		// if we're in a callback, then schedule re-rendering of the control 
 -		// if not, don't do anything, because a new challenge will be rendered anyway
 -		if ($this->Page->IsCallback)
 -			$this->Page->ClientScript->registerEndScript($this->getClientID().'::refresh','Recaptcha.reload();');
 -	}
 -
 -	public function renderContents($writer)
 -	{
 -		$writer->write(TJavaScript::renderScriptBlock(
 -			'var RecaptchaOptions = '.TJavaScript::jsonEncode($this->getClientSideOptions()).';'
 -		));
 -
 -		$html = recaptcha_get_html($this->getPublicKey());
 -		/*
 -		reCAPTCHA currently does not support multiple validations per page
 -		$html = str_replace(
 -			array(self::ChallengeFieldName,self::ResponseFieldName),
 -			array($this->getChallengeFieldName(),$this->getResponseFieldName()),
 -			$html
 -		);
 -		*/
 -		$writer->write($html);
 -	}
 -
 -}
 -
 +<?php + +/** + * TReCaptcha class file + * + * @author Bérczi Gábor <gabor.berczi@devworx.hu> + * @link http://www.devworx.hu/ + * @copyright Copyright © 2011 DevWorx + * @license http://www.pradosoft.com/license/ + * @package System.Web.UI.WebControls + */ + +	Prado::using('System.3rdParty.ReCaptcha.recaptchalib'); + +/** + * TReCaptcha class. + * + * TReCaptcha displays a reCAPTCHA (a token displayed as an image) that can be used + * to determine if the input is entered by a real user instead of some program. It can + * also prevent multiple submits of the same form either by accident, or on purpose (ie. spamming). + * + * The reCAPTCHA to solve (a string consisting of two separate words) displayed is automatically + * generated by the reCAPTCHA system at recaptcha.net. However, in order to use the services + * of the site you will need to register and get a public and a private API key pair, and  + * supply those to the reCAPTCHA control through setting the {@link setPrivateKey PrivateKey}  + * and {@link setPublicKey PublicKey} properties.  + * + * Currently the reCAPTCHA API supports only one reCAPTCHA field per page, so you MUST make sure that all  + * your input is protected and validated by a single reCAPTCHA control. Placing more than one reCAPTCHA + * control on the page will lead to unpredictable results, and the user will most likely unable to solve  + * any of them successfully. + * + * Upon postback, user input can be validated by calling {@link validate()}. + * The {@link TReCaptchaValidator} control can also be used to do validation, which provides + * server-side validation. Calling (@link validate()) will invalidate the token supplied, so all consecutive + * calls to the method - without solving a new captcha - will return false. Therefore if implementing a multi-stage + * input process, you must make sure that you call validate() only once, either at the end of the input process, or  + * you store the result till the end of the processing. + * + * The following template shows a typical use of TReCaptcha control: + * <code> + * <com:TReCaptcha ID="Captcha" + *                 PublicKey="..." + *                 PrivateKey="..." + * /> + * <com:TReCaptchaValidator ControlToValidate="Captcha" + *                          ErrorMessage="You are challenged!" /> + * </code> + * + * @author Bérczi Gábor <gabor.berczi@devworx.hu> + * @package System.Web.UI.WebControls + * @since 3.2 + */ +class TReCaptcha extends TWebControl implements IValidatable +{ +	private $_isValid=true; + +	const ChallengeFieldName = 'recaptcha_challenge_field'; +	const ResponseFieldName = 'recaptcha_response_field'; + +	public function getTagName() +	{ +		return 'span'; +	} +	 +	/** +	 * Returns true if this control validated successfully.  +	 * Defaults to true. +	 * @return bool wether this control validated successfully. +	 */ +	public function getIsValid() +	{ +		return $this->_isValid; +	} +	/** +	 * @param bool wether this control is valid. +	 */ +	public function setIsValid($value) +	{ +		$this->_isValid=TPropertyValue::ensureBoolean($value); +	} +	 +	public function getValidationPropertyValue() +	{ +		return $this->Request[$this->getChallengeFieldName()]; +	} + +	public function getPublicKey() +	{ +		return $this->getViewState('PublicKey'); +	} + +	public function setPublicKey($value) +	{ +		return $this->setViewState('PublicKey', TPropertyValue::ensureString($value)); +	} + +	public function getPrivateKey() +	{ +		return $this->getViewState('PrivateKey'); +	} + +	public function setPrivateKey($value) +	{ +		return $this->setViewState('PrivateKey', TPropertyValue::ensureString($value)); +	} +	 +	public function getThemeName() +	{ +		return $this->getViewState('ThemeName'); +	} + +	public function setThemeName($value) +	{ +		return $this->setViewState('ThemeName', TPropertyValue::ensureString($value)); +	} + +	public function getCustomTranslations() +	{ +		return TPropertyValue::ensureArray($this->getViewState('CustomTranslations')); +	} + +	public function setCustomTranslations($value) +	{ +		return $this->setViewState('CustomTranslations', TPropertyValue::ensureArray($value)); +	} + +	public function getLanguage() +	{ +		return $this->getViewState('Language'); +	} + +	public function setLanguage($value) +	{ +		return $this->setViewState('Language', TPropertyValue::ensureString($value)); +	} + +	protected function getChallengeFieldName() +	{ +		return /*$this->ClientID.'_'.*/self::ChallengeFieldName; +	} +	 +	public function getResponseFieldName() +	{ +		return /*$this->ClientID.'_'.*/self::ResponseFieldName; +	} +	 +	public function getClientSideOptions() +	{ +		$options = array(); +		if ($theme = $this->getThemeName()) +			$options['theme'] = $theme; +		if ($lang = $this->getLanguage()) +			$options['lang'] = $lang; +		if ($trans = $this->getCustomTranslations()) +			$options['custom_translations'] = $trans; +		return $options; +	} + +	public function validate() +	{ +		if (! +		      ( +			($challenge = @$_POST[$this->getChallengeFieldName()]) +			and +			($response = @$_POST[$this->getResponseFieldName()]) +		      ) +                   ) +		   return false; + +		$resp = recaptcha_check_answer( +			$this->getPrivateKey(), +			$_SERVER["REMOTE_ADDR"], +			$challenge, +			$response +		);  +		return ($resp->is_valid==1); +	} + +	/** +	 * Checks for API keys +	 * @param mixed event parameter +	 */ +	public function onPreRender($param) +	{ +		parent::onPreRender($param); + +		if("" == $this->getPublicKey()) +			throw new TConfigurationException('recaptcha_publickey_unknown'); +		if("" == $this->getPrivateKey()) +			throw new TConfigurationException('recaptcha_privatekey_unknown'); + +		// need to register captcha fields so they will be sent back also in callbacks  +		$page = $this->getPage(); +		$page->registerRequiresPostData($this->getChallengeFieldName()); +		$page->registerRequiresPostData($this->getResponseFieldName()); +	} + +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		$writer->addAttribute('id',$this->getClientID()); +	} + +	public function regenerateToken() +	{ +		// if we're in a callback, then schedule re-rendering of the control  +		// if not, don't do anything, because a new challenge will be rendered anyway +		if ($this->Page->IsCallback) +			$this->Page->ClientScript->registerEndScript($this->getClientID().'::refresh','Recaptcha.reload();'); +	} + +	public function renderContents($writer) +	{ +		$writer->write(TJavaScript::renderScriptBlock( +			'var RecaptchaOptions = '.TJavaScript::jsonEncode($this->getClientSideOptions()).';' +		)); + +		$html = recaptcha_get_html($this->getPublicKey()); +		/* +		reCAPTCHA currently does not support multiple validations per page +		$html = str_replace( +			array(self::ChallengeFieldName,self::ResponseFieldName), +			array($this->getChallengeFieldName(),$this->getResponseFieldName()), +			$html +		); +		*/ +		$writer->write($html); +	} + +} +  ?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TReCaptchaValidator.php b/framework/Web/UI/WebControls/TReCaptchaValidator.php index 7199e401..41abbc5a 100644 --- a/framework/Web/UI/WebControls/TReCaptchaValidator.php +++ b/framework/Web/UI/WebControls/TReCaptchaValidator.php @@ -1,123 +1,123 @@ -<?php
 -
 -/**
 - * TReCaptchaValidator class file
 - *
 - * @author Bérczi Gábor <gabor.berczi@devworx.hu>
 - * @link http://www.devworx.hu/
 - * @copyright Copyright © 2011 DevWorx
 - * @license http://www.pradosoft.com/license/
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -Prado::using('System.Web.UI.WebControls.TReCaptcha');
 -
 -/**
 - * TReCaptchaValidator class
 - *
 - * TReCaptchaValidator validates user input against a reCAPTCHA represented by
 - * a {@link TReCaptcha} control. The input control fails validation if its value
 - * is not the same as the token displayed in reCAPTCHA. Note, if the user does
 - * not enter any thing, it is still considered as failing the validation.
 - *
 - * To use TReCaptchaValidator, specify the {@link setControlToValidate ControlToValidate}
 - * to be the ID path of the {@link TReCaptcha} control.
 - *
 - * @author Bérczi Gábor <gabor.berczi@devworx.hu>
 - * @package System.Web.UI.WebControls
 - * @since 3.2
 - */
 -class TReCaptchaValidator extends TBaseValidator
 -{
 -	protected $_isvalid = null;
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TReCaptchaValidator';
 -	}
 -
 -	public function getEnableClientScript()
 -	{
 -		return true;
 -	}
 -
 -	protected function getCaptchaControl()
 -	{
 -		$control = $this->getValidationTarget();
 -		if (!$control)
 -			throw new Exception('No target control specified for TReCaptchaValidator');
 -		if (!($control instanceof TReCaptcha))
 -			throw new Exception('TReCaptchaValidator only works with TReCaptcha controls');
 -		return $control;
 -	}
 -
 -	public function getClientScriptOptions()
 -	{
 -		$options = parent::getClientScriptOptions();
 -		$options['ResponseFieldName'] = $this->getCaptchaControl()->getResponseFieldName();
 -		return $options;
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input control has the same value
 -	 * as the one displayed in the corresponding RECAPTCHA control.
 -	 *
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	protected function evaluateIsValid()
 -	{
 -		// check validity only once (if trying to evaulate multiple times, all redundant checks would fail)
 -		if (is_null($this->_isvalid))
 -		{
 -			$control = $this->getCaptchaControl();
 -			$this->_isvalid = $control->validate();
 -		}
 -		return ($this->_isvalid==true);
 -	}
 -
 -	public function onPreRender($param)
 -	{
 -		parent::onPreRender($param);
 -
 -		$cs = $this->Page->getClientScript();
 -
 -		// communicate validation status to the client side
 -		$value = $this->_isvalid===false ? '0' : '1';
 -		$cs->registerHiddenField($this->getClientID().'_1',$value);
 -
 -		// check if we need to request a new captcha too
 -		if ($this->Page->IsCallback)
 -		{
 -		  // force update of validator display
 -		  if ($control = $this->getValidationTarget())
 -		  {
 -		    $cs->registerEndScript(
 -				$this->getClientID().'::validate',
 -				'$('.TJavaScript::quoteString($this->getClientID().'_1').').value = '.TJavaScript::quoteString($value).';'.
 -				'Prado.Validation.validateControl('.TJavaScript::quoteString($control->ClientID).');'
 -		    );
 -
 -		    if ($control->getVisible(true))
 -		      if ($this->_isvalid)
 -			{
 -				// if the challenge has been solved + we're in a callback and we still reach prerender phase,
 -				// that means that some other validator failed and the user will be sent back to the page/form with 
 -				// the captcha control. in this case we need to force re-rendering of the control, because once 
 -				// solved, the old challenge won't validate anymore anyway
 -
 -				$control->regenerateToken();
 -			}
 -		  }
 -		}
 -	}
 -
 -}
 -
 +<?php + +/** + * TReCaptchaValidator class file + * + * @author Bérczi Gábor <gabor.berczi@devworx.hu> + * @link http://www.devworx.hu/ + * @copyright Copyright © 2011 DevWorx + * @license http://www.pradosoft.com/license/ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TBaseValidator'); +Prado::using('System.Web.UI.WebControls.TReCaptcha'); + +/** + * TReCaptchaValidator class + * + * TReCaptchaValidator validates user input against a reCAPTCHA represented by + * a {@link TReCaptcha} control. The input control fails validation if its value + * is not the same as the token displayed in reCAPTCHA. Note, if the user does + * not enter any thing, it is still considered as failing the validation. + * + * To use TReCaptchaValidator, specify the {@link setControlToValidate ControlToValidate} + * to be the ID path of the {@link TReCaptcha} control. + * + * @author Bérczi Gábor <gabor.berczi@devworx.hu> + * @package System.Web.UI.WebControls + * @since 3.2 + */ +class TReCaptchaValidator extends TBaseValidator +{ +	protected $_isvalid = null; + +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TReCaptchaValidator'; +	} + +	public function getEnableClientScript() +	{ +		return true; +	} + +	protected function getCaptchaControl() +	{ +		$control = $this->getValidationTarget(); +		if (!$control) +			throw new Exception('No target control specified for TReCaptchaValidator'); +		if (!($control instanceof TReCaptcha)) +			throw new Exception('TReCaptchaValidator only works with TReCaptcha controls'); +		return $control; +	} + +	public function getClientScriptOptions() +	{ +		$options = parent::getClientScriptOptions(); +		$options['ResponseFieldName'] = $this->getCaptchaControl()->getResponseFieldName(); +		return $options; +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input control has the same value +	 * as the one displayed in the corresponding RECAPTCHA control. +	 * +	 * @return boolean whether the validation succeeds +	 */ +	protected function evaluateIsValid() +	{ +		// check validity only once (if trying to evaulate multiple times, all redundant checks would fail) +		if (is_null($this->_isvalid)) +		{ +			$control = $this->getCaptchaControl(); +			$this->_isvalid = $control->validate(); +		} +		return ($this->_isvalid==true); +	} + +	public function onPreRender($param) +	{ +		parent::onPreRender($param); + +		$cs = $this->Page->getClientScript(); + +		// communicate validation status to the client side +		$value = $this->_isvalid===false ? '0' : '1'; +		$cs->registerHiddenField($this->getClientID().'_1',$value); + +		// check if we need to request a new captcha too +		if ($this->Page->IsCallback) +		{ +		  // force update of validator display +		  if ($control = $this->getValidationTarget()) +		  { +		    $cs->registerEndScript( +				$this->getClientID().'::validate', +				'$('.TJavaScript::quoteString($this->getClientID().'_1').').value = '.TJavaScript::quoteString($value).';'. +				'Prado.Validation.validateControl('.TJavaScript::quoteString($control->ClientID).');' +		    ); + +		    if ($control->getVisible(true)) +		      if ($this->_isvalid) +			{ +				// if the challenge has been solved + we're in a callback and we still reach prerender phase, +				// that means that some other validator failed and the user will be sent back to the page/form with  +				// the captcha control. in this case we need to force re-rendering of the control, because once  +				// solved, the old challenge won't validate anymore anyway + +				$control->regenerateToken(); +			} +		  } +		} +	} + +} +  ?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TRegularExpressionValidator.php b/framework/Web/UI/WebControls/TRegularExpressionValidator.php index a2a5bc64..0e85907a 100644 --- a/framework/Web/UI/WebControls/TRegularExpressionValidator.php +++ b/framework/Web/UI/WebControls/TRegularExpressionValidator.php @@ -1,144 +1,144 @@ -<?php
 -/**
 - * TRequiredFieldValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TRegularExpressionValidator class
 - *
 - * TRegularExpressionValidator validates whether the value of an associated
 - * input component matches the pattern specified by a regular expression.
 - *
 - * You can specify the regular expression by setting the {@link setRegularExpression RegularExpression}
 - * property. Some commonly used regular expressions include:
 - * <pre>
 - * French Phone Number: (0( \d|\d ))?\d\d \d\d(\d \d| \d\d )\d\d
 - * French Postal Code: \d{5}
 - * German Phone Number: ((\(0\d\d\) |(\(0\d{3}\) )?\d )?\d\d \d\d \d\d|\(0\d{4}\) \d \d\d-\d\d?)
 - * German Postal Code: (D-)?\d{5}
 - * Email Address: \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
 - * Japanese Phone Number: (0\d{1,4}-|\(0\d{1,4}\) ?)?\d{1,4}-\d{4}
 - * Japanese Postal Code: \d{3}(-(\d{4}|\d{2}))?
 - * P.R.C. Phone Number: (\(\d{3}\)|\d{3}-)?\d{8}
 - * P.R.C. Postal Code: \d{6}
 - * P.R.C. Social Security Number: \d{18}|\d{15}
 - * U.S. Phone Number: ((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}
 - * U.S. ZIP Code: \d{5}(-\d{4})?
 - * U.S. Social Security Number: \d{3}-\d{2}-\d{4}
 - * </pre>
 - *
 - * Note, the validation succeeds if the associated input control contains empty input.
 - * Use a {@link TRequiredFieldValidator} to ensure the input is not empty.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRegularExpressionValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TRegularExpressionValidator';
 -	}
 -
 -	/**
 -	 * @return string the regular expression that determines the pattern used to validate a field.
 -	 */
 -	public function getRegularExpression()
 -	{
 -		return $this->getViewState('RegularExpression','');
 -	}
 -
 -	/**
 -	 * @param string the regular expression that determines the pattern used to validate a field.
 -	 */
 -	public function setRegularExpression($value)
 -	{
 -		$this->setViewState('RegularExpression',$value,'');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input data matches the regular expression.
 -	 * The validation always succeeds if ControlToValidate is not specified
 -	 * or the regular expression is empty, or the input data is empty.
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	public function evaluateIsValid()
 -	{
 -		if(($value=$this->getValidationValue($this->getValidationTarget()))==='')
 -			return true;
 -		if(($expression=addcslashes($this->getRegularExpression(),"/"))!=='')
 -		{
 -			$mods = $this->getPatternModifiers();
 -			return preg_match("/^$expression\$/{$mods}",$value);
 -		}
 -		else
 -			return true;
 -	}
 -
 -	/**
 -	 * @param string pattern modifiers for server side validation,
 -	 * see http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
 -	 */
 -	public function setPatternModifiers($value)
 -	{
 -		$this->setViewState('PatternModifiers', $value);
 -	}
 -
 -	/**
 -	 * @return string pattern modifiers, no modifiers by default.
 -	 */
 -	public function getPatternModifiers()
 -	{
 -		return $this->getViewState('PatternModifiers', '');
 -	}
 -
 -	/**
 -	 * @param string pattern modifiers for clientside.
 -	 * (Only 'g','i' and 'm' are available.)
 -	 */
 -	public function setClientSidePatternModifiers($value)
 -	{
 -		$this->setViewState('ClientSidePatternModifiers', $value);
 -	}
 -
 -	/**
 -	 * @return string clientside pattern modifiers, no modifiers by default.
 -	 */
 -	public function getClientSidePatternModifiers()
 -	{
 -		return $this->getViewState('ClientSidePatternModifiers', '');
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options = parent::getClientScriptOptions();
 -		$options['ValidationExpression']=$this->getRegularExpression();
 -		$options['PatternModifiers']=$this->getClientSidePatternModifiers();
 -		return $options;
 -	}
 -}
 -
 +<?php +/** + * TRequiredFieldValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TRegularExpressionValidator class + * + * TRegularExpressionValidator validates whether the value of an associated + * input component matches the pattern specified by a regular expression. + * + * You can specify the regular expression by setting the {@link setRegularExpression RegularExpression} + * property. Some commonly used regular expressions include: + * <pre> + * French Phone Number: (0( \d|\d ))?\d\d \d\d(\d \d| \d\d )\d\d + * French Postal Code: \d{5} + * German Phone Number: ((\(0\d\d\) |(\(0\d{3}\) )?\d )?\d\d \d\d \d\d|\(0\d{4}\) \d \d\d-\d\d?) + * German Postal Code: (D-)?\d{5} + * Email Address: \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* + * Japanese Phone Number: (0\d{1,4}-|\(0\d{1,4}\) ?)?\d{1,4}-\d{4} + * Japanese Postal Code: \d{3}(-(\d{4}|\d{2}))? + * P.R.C. Phone Number: (\(\d{3}\)|\d{3}-)?\d{8} + * P.R.C. Postal Code: \d{6} + * P.R.C. Social Security Number: \d{18}|\d{15} + * U.S. Phone Number: ((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4} + * U.S. ZIP Code: \d{5}(-\d{4})? + * U.S. Social Security Number: \d{3}-\d{2}-\d{4} + * </pre> + * + * Note, the validation succeeds if the associated input control contains empty input. + * Use a {@link TRequiredFieldValidator} to ensure the input is not empty. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRegularExpressionValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TRegularExpressionValidator'; +	} + +	/** +	 * @return string the regular expression that determines the pattern used to validate a field. +	 */ +	public function getRegularExpression() +	{ +		return $this->getViewState('RegularExpression',''); +	} + +	/** +	 * @param string the regular expression that determines the pattern used to validate a field. +	 */ +	public function setRegularExpression($value) +	{ +		$this->setViewState('RegularExpression',$value,''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input data matches the regular expression. +	 * The validation always succeeds if ControlToValidate is not specified +	 * or the regular expression is empty, or the input data is empty. +	 * @return boolean whether the validation succeeds +	 */ +	public function evaluateIsValid() +	{ +		if(($value=$this->getValidationValue($this->getValidationTarget()))==='') +			return true; +		if(($expression=addcslashes($this->getRegularExpression(),"/"))!=='') +		{ +			$mods = $this->getPatternModifiers(); +			return preg_match("/^$expression\$/{$mods}",$value); +		} +		else +			return true; +	} + +	/** +	 * @param string pattern modifiers for server side validation, +	 * see http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php +	 */ +	public function setPatternModifiers($value) +	{ +		$this->setViewState('PatternModifiers', $value); +	} + +	/** +	 * @return string pattern modifiers, no modifiers by default. +	 */ +	public function getPatternModifiers() +	{ +		return $this->getViewState('PatternModifiers', ''); +	} + +	/** +	 * @param string pattern modifiers for clientside. +	 * (Only 'g','i' and 'm' are available.) +	 */ +	public function setClientSidePatternModifiers($value) +	{ +		$this->setViewState('ClientSidePatternModifiers', $value); +	} + +	/** +	 * @return string clientside pattern modifiers, no modifiers by default. +	 */ +	public function getClientSidePatternModifiers() +	{ +		return $this->getViewState('ClientSidePatternModifiers', ''); +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options = parent::getClientScriptOptions(); +		$options['ValidationExpression']=$this->getRegularExpression(); +		$options['PatternModifiers']=$this->getClientSidePatternModifiers(); +		return $options; +	} +} + diff --git a/framework/Web/UI/WebControls/TRepeatInfo.php b/framework/Web/UI/WebControls/TRepeatInfo.php index d7c6f0b6..2604e645 100644 --- a/framework/Web/UI/WebControls/TRepeatInfo.php +++ b/framework/Web/UI/WebControls/TRepeatInfo.php @@ -1,560 +1,560 @@ -<?php
 -/**
 - * IRepeatInfoUser, TRepeatInfo class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * IRepeatInfoUser, TRepeatInfo class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TTable');
 -
 -/**
 - * IRepeatInfoUser interface.
 - * This interface must be implemented by classes who want to use {@link TRepeatInfo}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -interface IRepeatInfoUser
 -{
 -	/**
 -	 * @return boolean whether the repeat user contains footer
 -	 */
 -	public function getHasFooter();
 -	/**
 -	 * @return boolean whether the repeat user contains header
 -	 */
 -	public function getHasHeader();
 -	/**
 -	 * @return boolean whether the repeat user contains separators
 -	 */
 -	public function getHasSeparators();
 -	/**
 -	 * @return integer number of items to be rendered (excluding header, footer and separators)
 -	 */
 -	public function getItemCount();
 -	/**
 -	 * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager)
 -	 * @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 generateItemStyle($itemType,$index);
 -	/**
 -	 * Renders an item.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param TRepeatInfo repeat information
 -	 * @param string item type
 -	 * @param integer zero-based index of the item being rendered
 -	 */
 -	public function renderItem($writer,$repeatInfo,$itemType,$index);
 -}
 -
 -/**
 - * TRepeatInfo class.
 - * TRepeatInfo represents repeat information for controls like {@link TCheckBoxList}.
 - * The layout of the repeated items is specified via {@link setRepeatLayout RepeatLayout},
 - * which can be either Table (default), Flow or Raw.
 - * A table layout uses HTML table cells to organize the items while
 - * a flow layout uses line breaks to organize the items.
 - * The number of columns used to display the items is specified via
 - * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection}
 - * governs the order of the items being rendered.
 - *
 - * Note, the Raw layout does not contain any formatting tags and thus ignores
 - * the column and repeat direction settings.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRepeatInfo extends TComponent
 -{
 -	/**
 -	 * @var string caption of the table used to organize the repeated items
 -	 */
 -	private $_caption='';
 -	/**
 -	 * @var TTableCaptionAlign alignment of the caption of the table used to organize the repeated items
 -	 */
 -	private $_captionAlign=TTableCaptionAlign::NotSet;
 -	/**
 -	 * @var integer number of columns that the items should be arranged in
 -	 */
 -	private $_repeatColumns=0;
 -	/**
 -	 * @var TRepeatDirection direction of the repetition
 -	 */
 -	private $_repeatDirection=TRepeatDirection::Vertical;
 -	/**
 -	 * @var TRepeatLayout layout of the repeated items
 -	 */
 -	private $_repeatLayout=TRepeatLayout::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 TTableCaptionAlign alignment of the caption of the table layout. Defaults to TTableCaptionAlign::NotSet.
 -	 */
 -	public function getCaptionAlign()
 -	{
 -		return $this->_captionAlign;
 -	}
 -
 -	/**
 -	 * @return TTableCaptionAlign alignment of the caption of the table layout.
 -	 */
 -	public function setCaptionAlign($value)
 -	{
 -		$this->_captionAlign=TPropertyValue::ensureEnum($value,'TTableCaptionAlign');
 -	}
 -
 -	/**
 -	 * @return integer the number of columns that the repeated items should be displayed in. Defaults to 0, meaning not set.
 -	 */
 -	public function getRepeatColumns()
 -	{
 -		return $this->_repeatColumns;
 -	}
 -
 -	/**
 -	 * @param integer the number of columns that the repeated items should be displayed in.
 -	 */
 -	public function setRepeatColumns($value)
 -	{
 -		if(($value=TPropertyValue::ensureInteger($value))<0)
 -			throw new TInvalidDataValueException('repeatinfo_repeatcolumns_invalid');
 -		$this->_repeatColumns=$value;
 -	}
 -
 -	/**
 -	 * @return TRepeatDirection the direction of traversing the repeated items, defaults to TRepeatDirection::Vertical
 -	 */
 -	public function getRepeatDirection()
 -	{
 -		return $this->_repeatDirection;
 -	}
 -
 -	/**
 -	 * @param TRepeatDirection the direction of traversing the repeated items
 -	 */
 -	public function setRepeatDirection($value)
 -	{
 -		$this->_repeatDirection=TPropertyValue::ensureEnum($value,'TRepeatDirection');
 -	}
 -
 -	/**
 -	 * @return TRepeatLayout how the repeated items should be displayed, using table or using line breaks. Defaults to TRepeatLayout::Table.
 -	 */
 -	public function getRepeatLayout()
 -	{
 -		return $this->_repeatLayout;
 -	}
 -
 -	/**
 -	 * @param TRepeatLayout how the repeated items should be displayed, using table or using line breaks.
 -	 */
 -	public function setRepeatLayout($value)
 -	{
 -		$this->_repeatLayout=TPropertyValue::ensureEnum($value,'TRepeatLayout');
 -	}
 -
 -	/**
 -	 * Renders the repeated items.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param IRepeatInfoUser repeat information user
 -	 */
 -	public function renderRepeater($writer, IRepeatInfoUser $user)
 -	{
 -		if($this->_repeatLayout===TRepeatLayout::Table)
 -		{
 -			$control=new TTable;
 -			if($this->_caption!=='')
 -			{
 -				$control->setCaption($this->_caption);
 -				$control->setCaptionAlign($this->_captionAlign);
 -			}
 -		}
 -		else if($this->_repeatLayout===TRepeatLayout::Raw)
 -		{
 -			$this->renderRawContents($writer,$user);
 -			return;
 -		}
 -		else
 -			$control=new TWebControl;
 -		$control->setID($user->getClientID());
 -		$control->copyBaseAttributes($user);
 -		if($user->getHasStyle())
 -			$control->getStyle()->copyFrom($user->getStyle());
 -		$control->renderBeginTag($writer);
 -		$writer->writeLine();
 -
 -		if($this->_repeatDirection===TRepeatDirection::Vertical)
 -			$this->renderVerticalContents($writer,$user);
 -		else
 -			$this->renderHorizontalContents($writer,$user);
 -
 -		$control->renderEndTag($writer);
 -	}
 -
 -	/**
 -	 * Renders contents in raw format.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param IRepeatInfoUser repeat information user
 -	 */
 -	protected function renderRawContents($writer,$user)
 -	{
 -		if($user->getHasHeader())
 -			$user->renderItem($writer,$this,'Header',-1);
 -
 -		// render items
 -		$hasSeparators=$user->getHasSeparators();
 -		$itemCount=$user->getItemCount();
 -		for($i=0;$i<$itemCount;++$i)
 -		{
 -			$user->renderItem($writer,$this,'Item',$i);
 -			if($hasSeparators && $i!=$itemCount-1)
 -				$user->renderItem($writer,$this,'Separator',$i);
 -		}
 -		if($user->getHasFooter())
 -			$user->renderItem($writer,$this,'Footer',-1);
 -	}
 -
 -	/**
 -	 * Renders contents in horizontal repeat direction.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param IRepeatInfoUser repeat information user
 -	 */
 -	protected function renderHorizontalContents($writer,$user)
 -	{
 -		$tableLayout=($this->_repeatLayout===TRepeatLayout::Table);
 -		$hasSeparators=$user->getHasSeparators();
 -		$itemCount=$user->getItemCount();
 -		$columns=$this->_repeatColumns===0?$itemCount:$this->_repeatColumns;
 -		$totalColumns=$hasSeparators?$columns+$columns:$columns;
 -		$needBreak=$columns<$itemCount;
 -
 -		if($user->getHasHeader())
 -			$this->renderHeader($writer,$user,$tableLayout,$totalColumns,$needBreak);
 -
 -		// render items
 -		if($tableLayout)
 -		{
 -			$writer->renderBeginTag('tbody');
 -			$column=0;
 -			for($i=0;$i<$itemCount;++$i)
 -			{
 -				if($column==0)
 -					$writer->renderBeginTag('tr');
 -				if(($style=$user->generateItemStyle('Item',$i))!==null)
 -					$style->addAttributesToRender($writer);
 -				$writer->renderBeginTag('td');
 -				$user->renderItem($writer,$this,'Item',$i);
 -				$writer->renderEndTag();
 -				$writer->writeLine();
 -				if($hasSeparators && $i!=$itemCount-1)
 -				{
 -					if(($style=$user->generateItemStyle('Separator',$i))!==null)
 -						$style->addAttributesToRender($writer);
 -					$writer->renderBeginTag('td');
 -					$user->renderItem($writer,$this,'Separator',$i);
 -					$writer->renderEndTag();
 -					$writer->writeLine();
 -				}
 -				$column++;
 -				if($i==$itemCount-1)
 -				{
 -					$restColumns=$columns-$column;
 -					if($hasSeparators)
 -						$restColumns=$restColumns?$restColumns+$restColumns+1:1;
 -					for($j=0;$j<$restColumns;++$j)
 -						$writer->write("<td></td>\n");
 -				}
 -				if($column==$columns || $i==$itemCount-1)
 -				{
 -					$writer->renderEndTag();
 -					$writer->writeLine();
 -					$column=0;
 -				}
 -			}
 -			$writer->renderEndTag();
 -		}
 -		else
 -		{
 -			$column=0;
 -			for($i=0;$i<$itemCount;++$i)
 -			{
 -				$user->renderItem($writer,$this,'Item',$i);
 -				if($hasSeparators && $i!=$itemCount-1)
 -					$user->renderItem($writer,$this,'Separator',$i);
 -				$column++;
 -				if($column==$columns || $i==$itemCount-1)
 -				{
 -					if($needBreak)
 -						$writer->writeBreak();
 -					$column=0;
 -				}
 -				$writer->writeLine();
 -			}
 -		}
 -
 -		if($user->getHasFooter())
 -			$this->renderFooter($writer,$user,$tableLayout,$totalColumns,$needBreak);
 -	}
 -
 -	/**
 -	 * Renders contents in veritcal repeat direction.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param IRepeatInfoUser repeat information user
 -	 */
 -	protected function renderVerticalContents($writer,$user)
 -	{
 -		$tableLayout=($this->_repeatLayout===TRepeatLayout::Table);
 -		$hasSeparators=$user->getHasSeparators();
 -		$itemCount=$user->getItemCount();
 -		if($this->_repeatColumns<=1)
 -		{
 -			$rows=$itemCount;
 -			$columns=1;
 -			$lastColumns=1;
 -		}
 -		else
 -		{
 -			$columns=$this->_repeatColumns;
 -			$rows=(int)(($itemCount+$columns-1)/$columns);
 -			if($rows==0 && $itemCount>0)
 -				$rows=1;
 -			if(($lastColumns=$itemCount%$columns)==0)
 -				$lastColumns=$columns;
 -		}
 -		$totalColumns=$hasSeparators?$columns+$columns:$columns;
 -
 -		if($user->getHasHeader())
 -			$this->renderHeader($writer,$user,$tableLayout,$totalColumns,false);
 -
 -		if($tableLayout)
 -		{
 -			$writer->renderBeginTag('tbody');
 -			$renderedItems=0;
 -			for($row=0;$row<$rows;++$row)
 -			{
 -				$index=$row;
 -				$writer->renderBeginTag('tr');
 -				for($col=0;$col<$columns;++$col)
 -				{
 -					if($renderedItems>=$itemCount)
 -						break;
 -					if($col>0)
 -					{
 -						$index+=$rows;
 -						if($col-1>=$lastColumns)
 -							$index--;
 -					}
 -					if($index>=$itemCount)
 -						continue;
 -					$renderedItems++;
 -					if(($style=$user->generateItemStyle('Item',$index))!==null)
 -						$style->addAttributesToRender($writer);
 -					$writer->renderBeginTag('td');
 -					$user->renderItem($writer,$this,'Item',$index);
 -					$writer->renderEndTag();
 -					$writer->writeLine();
 -					if(!$hasSeparators)
 -						continue;
 -					if($renderedItems<$itemCount-1)
 -					{
 -						if($columns==1)
 -						{
 -							$writer->renderEndTag();
 -							$writer->renderBeginTag('tr');
 -						}
 -						if(($style=$user->generateItemStyle('Separator',$index))!==null)
 -							$style->addAttributesToRender($writer);
 -						$writer->renderBeginTag('td');
 -						$user->renderItem($writer,$this,'Separator',$index);
 -						$writer->renderEndTag();
 -						$writer->writeLine();
 -					}
 -					else if($columns>1)
 -						$writer->write("<td></td>\n");
 -				}
 -				if($row==$rows-1)
 -				{
 -					$restColumns=$columns-$lastColumns;
 -					if($hasSeparators)
 -						$restColumns+=$restColumns;
 -					for($col=0;$col<$restColumns;++$col)
 -						$writer->write("<td></td>\n");
 -				}
 -				$writer->renderEndTag();
 -				$writer->writeLine();
 -			}
 -			$writer->renderEndTag();
 -		}
 -		else
 -		{
 -			$renderedItems=0;
 -			for($row=0;$row<$rows;++$row)
 -			{
 -				$index=$row;
 -				for($col=0;$col<$columns;++$col)
 -				{
 -					if($renderedItems>=$itemCount)
 -						break;
 -					if($col>0)
 -					{
 -						$index+=$rows;
 -						if($col-1>=$lastColumns)
 -							$index--;
 -					}
 -					if($index>=$itemCount)
 -						continue;
 -					$renderedItems++;
 -					$user->renderItem($writer,$this,'Item',$index);
 -					$writer->writeLine();
 -					if(!$hasSeparators)
 -						continue;
 -					if($renderedItems<$itemCount-1)
 -					{
 -						if($columns==1)
 -							$writer->writeBreak();
 -						$user->renderItem($writer,$this,'Separator',$index);
 -					}
 -					$writer->writeLine();
 -				}
 -				if($row<$rows-1 || $user->getHasFooter())
 -					$writer->writeBreak();
 -			}
 -		}
 -
 -		if($user->getHasFooter())
 -			$this->renderFooter($writer,$user,$tableLayout,$totalColumns,false);
 -
 -	}
 -
 -	/**
 -	 * Renders header.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param IRepeatInfoUser repeat information user
 -	 * @param boolean whether to render using table layout
 -	 * @param integer number of columns to be rendered
 -	 * @param boolean if a line break is needed at the end
 -	 */
 -	protected function renderHeader($writer,$user,$tableLayout,$columns,$needBreak)
 -	{
 -		if($tableLayout)
 -		{
 -			$writer->renderBeginTag('thead');
 -			$writer->renderBeginTag('tr');
 -			if($columns>1)
 -				$writer->addAttribute('colspan',"$columns");
 -			$writer->addAttribute('scope','col');
 -			if(($style=$user->generateItemStyle('Header',-1))!==null)
 -				$style->addAttributesToRender($writer);
 -			$writer->renderBeginTag('th');
 -			$user->renderItem($writer,$this,'Header',-1);
 -			$writer->renderEndTag();
 -			$writer->renderEndTag();
 -			$writer->renderEndTag();
 -		}
 -		else
 -		{
 -			$user->renderItem($writer,$this,'Header',-1);
 -			if($needBreak)
 -				$writer->writeBreak();
 -		}
 -		$writer->writeLine();
 -	}
 -
 -	/**
 -	 * Renders footer.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 * @param IRepeatInfoUser repeat information user
 -	 * @param boolean whether to render using table layout
 -	 * @param integer number of columns to be rendered
 -	 */
 -	protected function renderFooter($writer,$user,$tableLayout,$columns)
 -	{
 -		if($tableLayout)
 -		{
 -			$writer->renderBeginTag('tfoot');
 -			$writer->renderBeginTag('tr');
 -			if($columns>1)
 -				$writer->addAttribute('colspan',"$columns");
 -			if(($style=$user->generateItemStyle('Footer',-1))!==null)
 -				$style->addAttributesToRender($writer);
 -			$writer->renderBeginTag('td');
 -			$user->renderItem($writer,$this,'Footer',-1);
 -			$writer->renderEndTag();
 -			$writer->renderEndTag();
 -			$writer->renderEndTag();
 -		}
 -		else
 -			$user->renderItem($writer,$this,'Footer',-1);
 -		$writer->writeLine();
 -	}
 -}
 -
 -
 -/**
 - * TRepeatDirection class.
 - * TRepeatDirection defines the enumerable type for the possible directions
 - * that repeated contents can repeat along
 - *
 - * The following enumerable values are defined:
 - * - Vertical
 - * - Horizontal
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TRepeatDirection extends TEnumerable
 -{
 -	const Vertical='Vertical';
 -	const Horizontal='Horizontal';
 -}
 -
 -/**
 - * TRepeatLayout class.
 - * TRepeatLayout defines the enumerable type for the possible layouts
 - * that repeated contents can take.
 - *
 - * The following enumerable values are defined:
 - * - Table: the repeated contents are organized using an HTML table
 - * - Flow: the repeated contents are organized using HTML spans and breaks
 - * - Raw: the repeated contents are stacked together without any additional decorations
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TRepeatLayout extends TEnumerable
 -{
 -	const Table='Table';
 -	const Flow='Flow';
 -	const Raw='Raw';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TTable'); + +/** + * IRepeatInfoUser interface. + * This interface must be implemented by classes who want to use {@link TRepeatInfo}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +interface IRepeatInfoUser +{ +	/** +	 * @return boolean whether the repeat user contains footer +	 */ +	public function getHasFooter(); +	/** +	 * @return boolean whether the repeat user contains header +	 */ +	public function getHasHeader(); +	/** +	 * @return boolean whether the repeat user contains separators +	 */ +	public function getHasSeparators(); +	/** +	 * @return integer number of items to be rendered (excluding header, footer and separators) +	 */ +	public function getItemCount(); +	/** +	 * @param string item type (Header,Footer,Item,AlternatingItem,SelectedItem,EditItem,Separator,Pager) +	 * @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 generateItemStyle($itemType,$index); +	/** +	 * Renders an item. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param TRepeatInfo repeat information +	 * @param string item type +	 * @param integer zero-based index of the item being rendered +	 */ +	public function renderItem($writer,$repeatInfo,$itemType,$index); +} + +/** + * TRepeatInfo class. + * TRepeatInfo represents repeat information for controls like {@link TCheckBoxList}. + * The layout of the repeated items is specified via {@link setRepeatLayout RepeatLayout}, + * which can be either Table (default), Flow or Raw. + * A table layout uses HTML table cells to organize the items while + * a flow layout uses line breaks to organize the items. + * The number of columns used to display the items is specified via + * {@link setRepeatColumns RepeatColumns} property, while the {@link setRepeatDirection RepeatDirection} + * governs the order of the items being rendered. + * + * Note, the Raw layout does not contain any formatting tags and thus ignores + * the column and repeat direction settings. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeatInfo extends TComponent +{ +	/** +	 * @var string caption of the table used to organize the repeated items +	 */ +	private $_caption=''; +	/** +	 * @var TTableCaptionAlign alignment of the caption of the table used to organize the repeated items +	 */ +	private $_captionAlign=TTableCaptionAlign::NotSet; +	/** +	 * @var integer number of columns that the items should be arranged in +	 */ +	private $_repeatColumns=0; +	/** +	 * @var TRepeatDirection direction of the repetition +	 */ +	private $_repeatDirection=TRepeatDirection::Vertical; +	/** +	 * @var TRepeatLayout layout of the repeated items +	 */ +	private $_repeatLayout=TRepeatLayout::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 TTableCaptionAlign alignment of the caption of the table layout. Defaults to TTableCaptionAlign::NotSet. +	 */ +	public function getCaptionAlign() +	{ +		return $this->_captionAlign; +	} + +	/** +	 * @return TTableCaptionAlign alignment of the caption of the table layout. +	 */ +	public function setCaptionAlign($value) +	{ +		$this->_captionAlign=TPropertyValue::ensureEnum($value,'TTableCaptionAlign'); +	} + +	/** +	 * @return integer the number of columns that the repeated items should be displayed in. Defaults to 0, meaning not set. +	 */ +	public function getRepeatColumns() +	{ +		return $this->_repeatColumns; +	} + +	/** +	 * @param integer the number of columns that the repeated items should be displayed in. +	 */ +	public function setRepeatColumns($value) +	{ +		if(($value=TPropertyValue::ensureInteger($value))<0) +			throw new TInvalidDataValueException('repeatinfo_repeatcolumns_invalid'); +		$this->_repeatColumns=$value; +	} + +	/** +	 * @return TRepeatDirection the direction of traversing the repeated items, defaults to TRepeatDirection::Vertical +	 */ +	public function getRepeatDirection() +	{ +		return $this->_repeatDirection; +	} + +	/** +	 * @param TRepeatDirection the direction of traversing the repeated items +	 */ +	public function setRepeatDirection($value) +	{ +		$this->_repeatDirection=TPropertyValue::ensureEnum($value,'TRepeatDirection'); +	} + +	/** +	 * @return TRepeatLayout how the repeated items should be displayed, using table or using line breaks. Defaults to TRepeatLayout::Table. +	 */ +	public function getRepeatLayout() +	{ +		return $this->_repeatLayout; +	} + +	/** +	 * @param TRepeatLayout how the repeated items should be displayed, using table or using line breaks. +	 */ +	public function setRepeatLayout($value) +	{ +		$this->_repeatLayout=TPropertyValue::ensureEnum($value,'TRepeatLayout'); +	} + +	/** +	 * Renders the repeated items. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param IRepeatInfoUser repeat information user +	 */ +	public function renderRepeater($writer, IRepeatInfoUser $user) +	{ +		if($this->_repeatLayout===TRepeatLayout::Table) +		{ +			$control=new TTable; +			if($this->_caption!=='') +			{ +				$control->setCaption($this->_caption); +				$control->setCaptionAlign($this->_captionAlign); +			} +		} +		else if($this->_repeatLayout===TRepeatLayout::Raw) +		{ +			$this->renderRawContents($writer,$user); +			return; +		} +		else +			$control=new TWebControl; +		$control->setID($user->getClientID()); +		$control->copyBaseAttributes($user); +		if($user->getHasStyle()) +			$control->getStyle()->copyFrom($user->getStyle()); +		$control->renderBeginTag($writer); +		$writer->writeLine(); + +		if($this->_repeatDirection===TRepeatDirection::Vertical) +			$this->renderVerticalContents($writer,$user); +		else +			$this->renderHorizontalContents($writer,$user); + +		$control->renderEndTag($writer); +	} + +	/** +	 * Renders contents in raw format. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param IRepeatInfoUser repeat information user +	 */ +	protected function renderRawContents($writer,$user) +	{ +		if($user->getHasHeader()) +			$user->renderItem($writer,$this,'Header',-1); + +		// render items +		$hasSeparators=$user->getHasSeparators(); +		$itemCount=$user->getItemCount(); +		for($i=0;$i<$itemCount;++$i) +		{ +			$user->renderItem($writer,$this,'Item',$i); +			if($hasSeparators && $i!=$itemCount-1) +				$user->renderItem($writer,$this,'Separator',$i); +		} +		if($user->getHasFooter()) +			$user->renderItem($writer,$this,'Footer',-1); +	} + +	/** +	 * Renders contents in horizontal repeat direction. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param IRepeatInfoUser repeat information user +	 */ +	protected function renderHorizontalContents($writer,$user) +	{ +		$tableLayout=($this->_repeatLayout===TRepeatLayout::Table); +		$hasSeparators=$user->getHasSeparators(); +		$itemCount=$user->getItemCount(); +		$columns=$this->_repeatColumns===0?$itemCount:$this->_repeatColumns; +		$totalColumns=$hasSeparators?$columns+$columns:$columns; +		$needBreak=$columns<$itemCount; + +		if($user->getHasHeader()) +			$this->renderHeader($writer,$user,$tableLayout,$totalColumns,$needBreak); + +		// render items +		if($tableLayout) +		{ +			$writer->renderBeginTag('tbody'); +			$column=0; +			for($i=0;$i<$itemCount;++$i) +			{ +				if($column==0) +					$writer->renderBeginTag('tr'); +				if(($style=$user->generateItemStyle('Item',$i))!==null) +					$style->addAttributesToRender($writer); +				$writer->renderBeginTag('td'); +				$user->renderItem($writer,$this,'Item',$i); +				$writer->renderEndTag(); +				$writer->writeLine(); +				if($hasSeparators && $i!=$itemCount-1) +				{ +					if(($style=$user->generateItemStyle('Separator',$i))!==null) +						$style->addAttributesToRender($writer); +					$writer->renderBeginTag('td'); +					$user->renderItem($writer,$this,'Separator',$i); +					$writer->renderEndTag(); +					$writer->writeLine(); +				} +				$column++; +				if($i==$itemCount-1) +				{ +					$restColumns=$columns-$column; +					if($hasSeparators) +						$restColumns=$restColumns?$restColumns+$restColumns+1:1; +					for($j=0;$j<$restColumns;++$j) +						$writer->write("<td></td>\n"); +				} +				if($column==$columns || $i==$itemCount-1) +				{ +					$writer->renderEndTag(); +					$writer->writeLine(); +					$column=0; +				} +			} +			$writer->renderEndTag(); +		} +		else +		{ +			$column=0; +			for($i=0;$i<$itemCount;++$i) +			{ +				$user->renderItem($writer,$this,'Item',$i); +				if($hasSeparators && $i!=$itemCount-1) +					$user->renderItem($writer,$this,'Separator',$i); +				$column++; +				if($column==$columns || $i==$itemCount-1) +				{ +					if($needBreak) +						$writer->writeBreak(); +					$column=0; +				} +				$writer->writeLine(); +			} +		} + +		if($user->getHasFooter()) +			$this->renderFooter($writer,$user,$tableLayout,$totalColumns,$needBreak); +	} + +	/** +	 * Renders contents in veritcal repeat direction. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param IRepeatInfoUser repeat information user +	 */ +	protected function renderVerticalContents($writer,$user) +	{ +		$tableLayout=($this->_repeatLayout===TRepeatLayout::Table); +		$hasSeparators=$user->getHasSeparators(); +		$itemCount=$user->getItemCount(); +		if($this->_repeatColumns<=1) +		{ +			$rows=$itemCount; +			$columns=1; +			$lastColumns=1; +		} +		else +		{ +			$columns=$this->_repeatColumns; +			$rows=(int)(($itemCount+$columns-1)/$columns); +			if($rows==0 && $itemCount>0) +				$rows=1; +			if(($lastColumns=$itemCount%$columns)==0) +				$lastColumns=$columns; +		} +		$totalColumns=$hasSeparators?$columns+$columns:$columns; + +		if($user->getHasHeader()) +			$this->renderHeader($writer,$user,$tableLayout,$totalColumns,false); + +		if($tableLayout) +		{ +			$writer->renderBeginTag('tbody'); +			$renderedItems=0; +			for($row=0;$row<$rows;++$row) +			{ +				$index=$row; +				$writer->renderBeginTag('tr'); +				for($col=0;$col<$columns;++$col) +				{ +					if($renderedItems>=$itemCount) +						break; +					if($col>0) +					{ +						$index+=$rows; +						if($col-1>=$lastColumns) +							$index--; +					} +					if($index>=$itemCount) +						continue; +					$renderedItems++; +					if(($style=$user->generateItemStyle('Item',$index))!==null) +						$style->addAttributesToRender($writer); +					$writer->renderBeginTag('td'); +					$user->renderItem($writer,$this,'Item',$index); +					$writer->renderEndTag(); +					$writer->writeLine(); +					if(!$hasSeparators) +						continue; +					if($renderedItems<$itemCount-1) +					{ +						if($columns==1) +						{ +							$writer->renderEndTag(); +							$writer->renderBeginTag('tr'); +						} +						if(($style=$user->generateItemStyle('Separator',$index))!==null) +							$style->addAttributesToRender($writer); +						$writer->renderBeginTag('td'); +						$user->renderItem($writer,$this,'Separator',$index); +						$writer->renderEndTag(); +						$writer->writeLine(); +					} +					else if($columns>1) +						$writer->write("<td></td>\n"); +				} +				if($row==$rows-1) +				{ +					$restColumns=$columns-$lastColumns; +					if($hasSeparators) +						$restColumns+=$restColumns; +					for($col=0;$col<$restColumns;++$col) +						$writer->write("<td></td>\n"); +				} +				$writer->renderEndTag(); +				$writer->writeLine(); +			} +			$writer->renderEndTag(); +		} +		else +		{ +			$renderedItems=0; +			for($row=0;$row<$rows;++$row) +			{ +				$index=$row; +				for($col=0;$col<$columns;++$col) +				{ +					if($renderedItems>=$itemCount) +						break; +					if($col>0) +					{ +						$index+=$rows; +						if($col-1>=$lastColumns) +							$index--; +					} +					if($index>=$itemCount) +						continue; +					$renderedItems++; +					$user->renderItem($writer,$this,'Item',$index); +					$writer->writeLine(); +					if(!$hasSeparators) +						continue; +					if($renderedItems<$itemCount-1) +					{ +						if($columns==1) +							$writer->writeBreak(); +						$user->renderItem($writer,$this,'Separator',$index); +					} +					$writer->writeLine(); +				} +				if($row<$rows-1 || $user->getHasFooter()) +					$writer->writeBreak(); +			} +		} + +		if($user->getHasFooter()) +			$this->renderFooter($writer,$user,$tableLayout,$totalColumns,false); + +	} + +	/** +	 * Renders header. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param IRepeatInfoUser repeat information user +	 * @param boolean whether to render using table layout +	 * @param integer number of columns to be rendered +	 * @param boolean if a line break is needed at the end +	 */ +	protected function renderHeader($writer,$user,$tableLayout,$columns,$needBreak) +	{ +		if($tableLayout) +		{ +			$writer->renderBeginTag('thead'); +			$writer->renderBeginTag('tr'); +			if($columns>1) +				$writer->addAttribute('colspan',"$columns"); +			$writer->addAttribute('scope','col'); +			if(($style=$user->generateItemStyle('Header',-1))!==null) +				$style->addAttributesToRender($writer); +			$writer->renderBeginTag('th'); +			$user->renderItem($writer,$this,'Header',-1); +			$writer->renderEndTag(); +			$writer->renderEndTag(); +			$writer->renderEndTag(); +		} +		else +		{ +			$user->renderItem($writer,$this,'Header',-1); +			if($needBreak) +				$writer->writeBreak(); +		} +		$writer->writeLine(); +	} + +	/** +	 * Renders footer. +	 * @param THtmlWriter writer for the rendering purpose +	 * @param IRepeatInfoUser repeat information user +	 * @param boolean whether to render using table layout +	 * @param integer number of columns to be rendered +	 */ +	protected function renderFooter($writer,$user,$tableLayout,$columns) +	{ +		if($tableLayout) +		{ +			$writer->renderBeginTag('tfoot'); +			$writer->renderBeginTag('tr'); +			if($columns>1) +				$writer->addAttribute('colspan',"$columns"); +			if(($style=$user->generateItemStyle('Footer',-1))!==null) +				$style->addAttributesToRender($writer); +			$writer->renderBeginTag('td'); +			$user->renderItem($writer,$this,'Footer',-1); +			$writer->renderEndTag(); +			$writer->renderEndTag(); +			$writer->renderEndTag(); +		} +		else +			$user->renderItem($writer,$this,'Footer',-1); +		$writer->writeLine(); +	} +} + + +/** + * TRepeatDirection class. + * TRepeatDirection defines the enumerable type for the possible directions + * that repeated contents can repeat along + * + * The following enumerable values are defined: + * - Vertical + * - Horizontal + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TRepeatDirection extends TEnumerable +{ +	const Vertical='Vertical'; +	const Horizontal='Horizontal'; +} + +/** + * TRepeatLayout class. + * TRepeatLayout defines the enumerable type for the possible layouts + * that repeated contents can take. + * + * The following enumerable values are defined: + * - Table: the repeated contents are organized using an HTML table + * - Flow: the repeated contents are organized using HTML spans and breaks + * - Raw: the repeated contents are stacked together without any additional decorations + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TRepeatLayout extends TEnumerable +{ +	const Table='Table'; +	const Flow='Flow'; +	const Raw='Raw'; +} + diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php index 6a59cbab..944b3a17 100644 --- a/framework/Web/UI/WebControls/TRepeater.php +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -1,1025 +1,1025 @@ -<?php
 -/**
 - * TRepeater class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TRepeater class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TDataBoundControl and TDataFieldAccessor cass
 - */
 -Prado::using('System.Web.UI.WebControls.TDataBoundControl');
 -Prado::using('System.Util.TDataFieldAccessor');
 -
 -/**
 - * TRepeater class.
 - *
 - * 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 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.
 - *
 - * Since v3.1.0, the layout can also be specified 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).
 - *
 - * A renderer can be any control class.
 - * - If the class implements {@link IDataRenderer}, the <b>Data</b>
 - * 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 <b>ItemIndex</b> property will be set
 - * as the zero-based index of the item in the repeater item collection, and
 - * the <b>ItemType</b> 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}.
 - *
 - * 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 <b>OnCommand</b> event. Therefore,
 - * you can handle all sorts of <b>OnCommand</b> event in a central place by
 - * writing an event handler for {@link onItemCommand OnItemCommand}.
 - *
 - * 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 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 <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRepeater extends TDataBoundControl implements INamingContainer
 -{
 -	/**
 -	 * Repeater item types
 -	 * @deprecated deprecated since version 3.0.4. Use TListItemType constants instead.
 -	 */
 -	const IT_HEADER='Header';
 -	const IT_FOOTER='Footer';
 -	const IT_ITEM='Item';
 -	const IT_SEPARATOR='Separator';
 -	const IT_ALTERNATINGITEM='AlternatingItem';
 -
 -	/**
 -	 * @var ITemplate template for repeater items
 -	 */
 -	private $_itemTemplate=null;
 -	/**
 -	 * @var ITemplate template for each alternating item
 -	 */
 -	private $_alternatingItemTemplate=null;
 -	/**
 -	 * @var ITemplate template for header
 -	 */
 -	private $_headerTemplate=null;
 -	/**
 -	 * @var ITemplate template for footer
 -	 */
 -	private $_footerTemplate=null;
 -	/**
 -	 * @var ITemplate template used for repeater when no data is bound
 -	 */
 -	private $_emptyTemplate=null;
 -	/**
 -	 * @var ITemplate template for separator
 -	 */
 -	private $_separatorTemplate=null;
 -	/**
 -	 * @var TRepeaterItemCollection list of repeater items
 -	 */
 -	private $_items=null;
 -	/**
 -	 * @var TControl header item
 -	 */
 -	private $_header=null;
 -	/**
 -	 * @var TControl footer item
 -	 */
 -	private $_footer=null;
 -
 -
 -	/**
 -	 * @return string the class name for repeater items. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function setItemRenderer($value)
 -	{
 -		$this->setViewState('ItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for alternative repeater items. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function setAlternatingItemRenderer($value)
 -	{
 -		$this->setViewState('AlternatingItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for repeater item separators. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function setSeparatorRenderer($value)
 -	{
 -		$this->setViewState('SeparatorRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for repeater header item. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function setHeaderRenderer($value)
 -	{
 -		$this->setViewState('HeaderRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for repeater footer item. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function setFooterRenderer($value)
 -	{
 -		$this->setViewState('FooterRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for empty repeater item. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function setEmptyRenderer($value)
 -	{
 -		$this->setViewState('EmptyRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return ITemplate the template for repeater items
 -	 */
 -	public function getItemTemplate()
 -	{
 -		return $this->_itemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template for repeater items
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_itemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('repeater_template_required','ItemTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the alternative template string for the item
 -	 */
 -	public function getAlternatingItemTemplate()
 -	{
 -		return $this->_alternatingItemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the alternative item template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setAlternatingItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_alternatingItemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('repeater_template_required','AlternatingItemTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the header template
 -	 */
 -	public function getHeaderTemplate()
 -	{
 -		return $this->_headerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the header template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setHeaderTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_headerTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('repeater_template_required','HeaderTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the footer template
 -	 */
 -	public function getFooterTemplate()
 -	{
 -		return $this->_footerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the footer template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setFooterTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_footerTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('repeater_template_required','FooterTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the template applied when no data is bound to the repeater
 -	 */
 -	public function getEmptyTemplate()
 -	{
 -		return $this->_emptyTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template applied when no data is bound to the repeater
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setEmptyTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_emptyTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('repeater_template_required','EmptyTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the separator template
 -	 */
 -	public function getSeparatorTemplate()
 -	{
 -		return $this->_separatorTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the separator template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setSeparatorTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_separatorTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('repeater_template_required','SeparatorTemplate');
 -	}
 -
 -	/**
 -	 * @return TControl the header item
 -	 */
 -	public function getHeader()
 -	{
 -		return $this->_header;
 -	}
 -
 -	/**
 -	 * @return TControl the footer item
 -	 */
 -	public function getFooter()
 -	{
 -		return $this->_footer;
 -	}
 -
 -	/**
 -	 * @return TRepeaterItemCollection list of repeater item controls
 -	 */
 -	public function getItems()
 -	{
 -		if(!$this->_items)
 -			$this->_items=new TRepeaterItemCollection;
 -		return $this->_items;
 -	}
 -
 -	/**
 -	 * @return string the field of the data source that provides the keys of the list items.
 -	 */
 -	public function getDataKeyField()
 -	{
 -		return $this->getViewState('DataKeyField','');
 -	}
 -
 -	/**
 -	 * @param string the field of the data source that provides the keys of the list items.
 -	 */
 -	public function setDataKeyField($value)
 -	{
 -		$this->setViewState('DataKeyField',$value,'');
 -	}
 -
 -	/**
 -	 * @return TList the keys used in the data listing control.
 -	 */
 -	public function getDataKeys()
 -	{
 -		if(($dataKeys=$this->getViewState('DataKeys',null))===null)
 -		{
 -			$dataKeys=new TList;
 -			$this->setViewState('DataKeys',$dataKeys,null);
 -		}
 -		return $dataKeys;
 -	}
 -
 -	/**
 -	 * Creates a repeater item.
 -	 * This method invokes {@link createItem} to create a new repeater item.
 -	 * @param integer zero-based item index.
 -	 * @param TListItemType item type
 -	 * @return TControl the created item, null if item is not created
 -	 */
 -	private function createItemInternal($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 performs databinding.
 -	 * This method invokes {@link createItem} to create a new repeater item.
 -	 * @param integer zero-based item index.
 -	 * @param TListItemType item type
 -	 * @param mixed data to be associated with the item
 -	 * @return TControl the created item, null if item is not created
 -	 */
 -	private function createItemWithDataInternal($itemIndex,$itemType,$dataItem)
 -	{
 -		if(($item=$this->createItem($itemIndex,$itemType))!==null)
 -		{
 -			$param=new TRepeaterItemEventParameter($item);
 -			if($item instanceof IDataRenderer)
 -				$item->setData($dataItem);
 -			$this->onItemCreated($param);
 -			$this->getControls()->add($item);
 -			$item->dataBind();
 -			$this->onItemDataBound($param);
 -			return $item;
 -		}
 -		else
 -			return null;
 -	}
 -
 -	/**
 -	 * Creates a repeater item instance based on the item type and index.
 -	 * @param integer zero-based item index
 -	 * @param TListItemType item type
 -	 * @return TControl created repeater item
 -	 */
 -	protected function createItem($itemIndex,$itemType)
 -	{
 -		$template=null;
 -		$classPath=null;
 -		switch($itemType)
 -		{
 -			case TListItemType::Item :
 -				$classPath=$this->getItemRenderer();
 -				$template=$this->_itemTemplate;
 -				break;
 -			case TListItemType::AlternatingItem :
 -				if(($classPath=$this->getAlternatingItemRenderer())==='' && ($template=$this->_alternatingItemTemplate)===null)
 -				{
 -					$classPath=$this->getItemRenderer();
 -					$template=$this->_itemTemplate;
 -				}
 -				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($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);
 -	}
 -
 -	/**
 -	 * Renders the repeater.
 -	 * This method overrides the parent implementation by rendering the body
 -	 * content as the whole presentation of the repeater. Outer tag is not rendered.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->_items && $this->_items->getCount() || $this->_emptyTemplate!==null || $this->getEmptyRenderer()!=='')
 -			$this->renderContents($writer);
 -	}
 -
 -	/**
 -	 * Saves item count in viewstate.
 -	 * This method is invoked right before control state is to be saved.
 -	 */
 -	public function saveState()
 -	{
 -		parent::saveState();
 -		if($this->_items)
 -			$this->setViewState('ItemCount',$this->_items->getCount(),0);
 -		else
 -			$this->clearViewState('ItemCount');
 -	}
 -
 -	/**
 -	 * Loads item count information from viewstate.
 -	 * This method is invoked right after control state is loaded.
 -	 */
 -	public function loadState()
 -	{
 -		parent::loadState();
 -		if(!$this->getIsDataBound())
 -			$this->restoreItemsFromViewState();
 -		$this->clearViewState('ItemCount');
 -	}
 -
 -	/**
 -	 * Clears up all items in the repeater.
 -	 */
 -	public function reset()
 -	{
 -		$this->getControls()->clear();
 -		$this->getItems()->clear();
 -		$this->_header=null;
 -		$this->_footer=null;
 -	}
 -
 -	/**
 -	 * Creates repeater items based on viewstate information.
 -	 */
 -	protected function restoreItemsFromViewState()
 -	{
 -		$this->reset();
 -		if(($itemCount=$this->getViewState('ItemCount',0))>0)
 -		{
 -			$items=$this->getItems();
 -			$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);
 -				$itemType=$i%2==0?TListItemType::Item : TListItemType::AlternatingItem;
 -				$items->add($this->createItemInternal($i,$itemType,false,null));
 -			}
 -			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer);
 -		}
 -		else
 -			$this->createEmptyContent();
 -		$this->clearChildState();
 -	}
 -
 -	/**
 -	 * Performs databinding to populate repeater items from data source.
 -	 * This method is invoked by dataBind().
 -	 * You may override this function to provide your own way of data population.
 -	 * @param Traversable the data
 -	 */
 -	protected function performDataBinding($data)
 -	{
 -		$this->reset();
 -
 -		$keys=$this->getDataKeys();
 -		$keys->clear();
 -		$keyField=$this->getDataKeyField();
 -
 -		$items=$this->getItems();
 -		$itemIndex=0;
 -		$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->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null);
 -			if($hasSeparator && $itemIndex>0)
 -				$this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null);
 -			$itemType=$itemIndex%2==0?TListItemType::Item : TListItemType::AlternatingItem;
 -			$items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem));
 -			$itemIndex++;
 -		}
 -		if($itemIndex>0)
 -			$this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null);
 -		else
 -		{
 -			$this->createEmptyContent();
 -			$this->dataBindChildren();
 -		}
 -		$this->setViewState('ItemCount',$itemIndex,0);
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation to handle
 -	 * {@link onItemCommand OnItemCommand} event which is bubbled from
 -	 * 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
 -	 * @return boolean whether the event bubbling should stop here.
 -	 */
 -	public function bubbleEvent($sender,$param)
 -	{
 -		if($param instanceof TRepeaterCommandEventParameter)
 -		{
 -			$this->onItemCommand($param);
 -			return true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemCreated</b> event.
 -	 * This method is invoked after a repeater item is created and instantiated with
 -	 * template, but before added to the page hierarchy.
 -	 * 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.
 -	 * @param TRepeaterItemEventParameter event parameter
 -	 */
 -	public function onItemCreated($param)
 -	{
 -		$this->raiseEvent('OnItemCreated',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemDataBound</b> event.
 -	 * This method is invoked right after an item is data bound.
 -	 * 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.
 -	 * @param TRepeaterItemEventParameter event parameter
 -	 */
 -	public function onItemDataBound($param)
 -	{
 -		$this->raiseEvent('OnItemDataBound',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnItemCommand</b> event.
 -	 * This method is invoked after a button control in
 -	 * a template raises <b>OnCommand</b> 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 <b>OnCommand</b> 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
 -	 * event handlers have chance to respond to the event.
 -	 * @param TRepeaterCommandEventParameter event parameter
 -	 */
 -	public function onItemCommand($param)
 -	{
 -		$this->raiseEvent('OnItemCommand',$this,$param);
 -	}
 -
 -	/**
 -	 * Returns the value of the data at the specified field.
 -	 * If data is an array, TMap or TList, the value will be returned at the index
 -	 * of the specified field. If the data is a component with a property named
 -	 * as the field name, the property value will be returned.
 -	 * Otherwise, an exception will be raised.
 -	 * @param mixed data item
 -	 * @param mixed field name
 -	 * @return mixed data value at the specified field
 -	 * @throws TInvalidDataValueException if the data is invalid
 -	 */
 -	protected function getDataFieldValue($data,$field)
 -	{
 -		return TDataFieldAccessor::getDataFieldValue($data,$field);
 -	}
 -}
 -
 -/**
 - * TRepeaterItemEventParameter class
 - *
 - * TRepeaterItemEventParameter encapsulates the parameter data for
 - * {@link TRepeater::onItemCreated ItemCreated} event of {@link TRepeater} controls.
 - * The {@link getItem Item} property indicates the repeater item related with the event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRepeaterItemEventParameter extends TEventParameter
 -{
 -	/**
 -	 * The repeater item control responsible for the event.
 -	 * @var TControl
 -	 */
 -	private $_item=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TControl repeater item related with the corresponding event
 -	 */
 -	public function __construct($item)
 -	{
 -		$this->_item=$item;
 -	}
 -
 -	/**
 -	 * @return TControl repeater item related with the corresponding event
 -	 */
 -	public function getItem()
 -	{
 -		return $this->_item;
 -	}
 -}
 -
 -/**
 - * TRepeaterCommandEventParameter class
 - *
 - * TRepeaterCommandEventParameter encapsulates the parameter data for
 - * {@link TRepeater::onItemCommand ItemCommand} event of {@link TRepeater} controls.
 - *
 - * The {@link getItem Item} property indicates the repeater item related with the event.
 - * The {@link getCommandSource CommandSource} refers to the control that originally
 - * raises the Command event.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRepeaterCommandEventParameter extends TCommandEventParameter
 -{
 -	/**
 -	 * @var TControl the repeater item control responsible for the event.
 -	 */
 -	private $_item=null;
 -	/**
 -	 * @var TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	private $_source=null;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TControl repeater item responsible for the event
 -	 * @param TControl original event sender
 -	 * @param TCommandEventParameter original event parameter
 -	 */
 -	public function __construct($item,$source,TCommandEventParameter $param)
 -	{
 -		$this->_item=$item;
 -		$this->_source=$source;
 -		parent::__construct($param->getCommandName(),$param->getCommandParameter());
 -	}
 -
 -	/**
 -	 * @return TControl the repeater item control responsible for the event.
 -	 */
 -	public function getItem()
 -	{
 -		return $this->_item;
 -	}
 -
 -	/**
 -	 * @return TControl the control originally raises the <b>OnCommand</b> event.
 -	 */
 -	public function getCommandSource()
 -	{
 -		return $this->_source;
 -	}
 -}
 -
 -/**
 - * TRepeaterItem class
 - *
 - * A TRepeaterItem control represents an item in the {@link TRepeater} control,
 - * such as heading section, footer section, or a data item.
 - * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}>
 - * and {@link getDataItem DataItem} properties, respectively. The type of the item
 - * is given by {@link getItemType ItemType} property.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRepeaterItem extends TControl implements INamingContainer, 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
 -	 */
 -	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
 -	 * @since 3.1.0
 -	 */
 -	public function getData()
 -	{
 -		return $this->_data;
 -	}
 -
 -	/**
 -	 * @param mixed data to be associated with the item
 -	 * @since 3.1.0
 -	 */
 -	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 setDataItem($value)
 -	{
 -		return $this->setData($value);
 -	}
 -
 -	/**
 -	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>OnCommand</b> 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;
 -	}
 -}
 -
 -
 -/**
 - * TRepeaterItemCollection class.
 - *
 - * TRepeaterItemCollection represents a collection of repeater items.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRepeaterItemCollection extends TList
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by inserting only objects that are descendant of {@link TControl}.
 -	 * @param integer the speicified position.
 -	 * @param TControl new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a control.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TControl)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('repeateritemcollection_item_invalid');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TDataBoundControl and TDataFieldAccessor cass + */ +Prado::using('System.Web.UI.WebControls.TDataBoundControl'); +Prado::using('System.Util.TDataFieldAccessor'); + +/** + * TRepeater class. + * + * 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 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. + * + * Since v3.1.0, the layout can also be specified 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). + * + * A renderer can be any control class. + * - If the class implements {@link IDataRenderer}, the <b>Data</b> + * 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 <b>ItemIndex</b> property will be set + * as the zero-based index of the item in the repeater item collection, and + * the <b>ItemType</b> 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}. + * + * 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 <b>OnCommand</b> event. Therefore, + * you can handle all sorts of <b>OnCommand</b> event in a central place by + * writing an event handler for {@link onItemCommand OnItemCommand}. + * + * 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 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 <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeater extends TDataBoundControl implements INamingContainer +{ +	/** +	 * Repeater item types +	 * @deprecated deprecated since version 3.0.4. Use TListItemType constants instead. +	 */ +	const IT_HEADER='Header'; +	const IT_FOOTER='Footer'; +	const IT_ITEM='Item'; +	const IT_SEPARATOR='Separator'; +	const IT_ALTERNATINGITEM='AlternatingItem'; + +	/** +	 * @var ITemplate template for repeater items +	 */ +	private $_itemTemplate=null; +	/** +	 * @var ITemplate template for each alternating item +	 */ +	private $_alternatingItemTemplate=null; +	/** +	 * @var ITemplate template for header +	 */ +	private $_headerTemplate=null; +	/** +	 * @var ITemplate template for footer +	 */ +	private $_footerTemplate=null; +	/** +	 * @var ITemplate template used for repeater when no data is bound +	 */ +	private $_emptyTemplate=null; +	/** +	 * @var ITemplate template for separator +	 */ +	private $_separatorTemplate=null; +	/** +	 * @var TRepeaterItemCollection list of repeater items +	 */ +	private $_items=null; +	/** +	 * @var TControl header item +	 */ +	private $_header=null; +	/** +	 * @var TControl footer item +	 */ +	private $_footer=null; + + +	/** +	 * @return string the class name for repeater items. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function setItemRenderer($value) +	{ +		$this->setViewState('ItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for alternative repeater items. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function setAlternatingItemRenderer($value) +	{ +		$this->setViewState('AlternatingItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for repeater item separators. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function setSeparatorRenderer($value) +	{ +		$this->setViewState('SeparatorRenderer',$value,''); +	} + +	/** +	 * @return string the class name for repeater header item. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function setHeaderRenderer($value) +	{ +		$this->setViewState('HeaderRenderer',$value,''); +	} + +	/** +	 * @return string the class name for repeater footer item. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function setFooterRenderer($value) +	{ +		$this->setViewState('FooterRenderer',$value,''); +	} + +	/** +	 * @return string the class name for empty repeater item. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function setEmptyRenderer($value) +	{ +		$this->setViewState('EmptyRenderer',$value,''); +	} + +	/** +	 * @return ITemplate the template for repeater items +	 */ +	public function getItemTemplate() +	{ +		return $this->_itemTemplate; +	} + +	/** +	 * @param ITemplate the template for repeater items +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_itemTemplate=$value; +		else +			throw new TInvalidDataTypeException('repeater_template_required','ItemTemplate'); +	} + +	/** +	 * @return ITemplate the alternative template string for the item +	 */ +	public function getAlternatingItemTemplate() +	{ +		return $this->_alternatingItemTemplate; +	} + +	/** +	 * @param ITemplate the alternative item template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setAlternatingItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_alternatingItemTemplate=$value; +		else +			throw new TInvalidDataTypeException('repeater_template_required','AlternatingItemTemplate'); +	} + +	/** +	 * @return ITemplate the header template +	 */ +	public function getHeaderTemplate() +	{ +		return $this->_headerTemplate; +	} + +	/** +	 * @param ITemplate the header template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setHeaderTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_headerTemplate=$value; +		else +			throw new TInvalidDataTypeException('repeater_template_required','HeaderTemplate'); +	} + +	/** +	 * @return ITemplate the footer template +	 */ +	public function getFooterTemplate() +	{ +		return $this->_footerTemplate; +	} + +	/** +	 * @param ITemplate the footer template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setFooterTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_footerTemplate=$value; +		else +			throw new TInvalidDataTypeException('repeater_template_required','FooterTemplate'); +	} + +	/** +	 * @return ITemplate the template applied when no data is bound to the repeater +	 */ +	public function getEmptyTemplate() +	{ +		return $this->_emptyTemplate; +	} + +	/** +	 * @param ITemplate the template applied when no data is bound to the repeater +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setEmptyTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_emptyTemplate=$value; +		else +			throw new TInvalidDataTypeException('repeater_template_required','EmptyTemplate'); +	} + +	/** +	 * @return ITemplate the separator template +	 */ +	public function getSeparatorTemplate() +	{ +		return $this->_separatorTemplate; +	} + +	/** +	 * @param ITemplate the separator template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setSeparatorTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_separatorTemplate=$value; +		else +			throw new TInvalidDataTypeException('repeater_template_required','SeparatorTemplate'); +	} + +	/** +	 * @return TControl the header item +	 */ +	public function getHeader() +	{ +		return $this->_header; +	} + +	/** +	 * @return TControl the footer item +	 */ +	public function getFooter() +	{ +		return $this->_footer; +	} + +	/** +	 * @return TRepeaterItemCollection list of repeater item controls +	 */ +	public function getItems() +	{ +		if(!$this->_items) +			$this->_items=new TRepeaterItemCollection; +		return $this->_items; +	} + +	/** +	 * @return string the field of the data source that provides the keys of the list items. +	 */ +	public function getDataKeyField() +	{ +		return $this->getViewState('DataKeyField',''); +	} + +	/** +	 * @param string the field of the data source that provides the keys of the list items. +	 */ +	public function setDataKeyField($value) +	{ +		$this->setViewState('DataKeyField',$value,''); +	} + +	/** +	 * @return TList the keys used in the data listing control. +	 */ +	public function getDataKeys() +	{ +		if(($dataKeys=$this->getViewState('DataKeys',null))===null) +		{ +			$dataKeys=new TList; +			$this->setViewState('DataKeys',$dataKeys,null); +		} +		return $dataKeys; +	} + +	/** +	 * Creates a repeater item. +	 * This method invokes {@link createItem} to create a new repeater item. +	 * @param integer zero-based item index. +	 * @param TListItemType item type +	 * @return TControl the created item, null if item is not created +	 */ +	private function createItemInternal($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 performs databinding. +	 * This method invokes {@link createItem} to create a new repeater item. +	 * @param integer zero-based item index. +	 * @param TListItemType item type +	 * @param mixed data to be associated with the item +	 * @return TControl the created item, null if item is not created +	 */ +	private function createItemWithDataInternal($itemIndex,$itemType,$dataItem) +	{ +		if(($item=$this->createItem($itemIndex,$itemType))!==null) +		{ +			$param=new TRepeaterItemEventParameter($item); +			if($item instanceof IDataRenderer) +				$item->setData($dataItem); +			$this->onItemCreated($param); +			$this->getControls()->add($item); +			$item->dataBind(); +			$this->onItemDataBound($param); +			return $item; +		} +		else +			return null; +	} + +	/** +	 * Creates a repeater item instance based on the item type and index. +	 * @param integer zero-based item index +	 * @param TListItemType item type +	 * @return TControl created repeater item +	 */ +	protected function createItem($itemIndex,$itemType) +	{ +		$template=null; +		$classPath=null; +		switch($itemType) +		{ +			case TListItemType::Item : +				$classPath=$this->getItemRenderer(); +				$template=$this->_itemTemplate; +				break; +			case TListItemType::AlternatingItem : +				if(($classPath=$this->getAlternatingItemRenderer())==='' && ($template=$this->_alternatingItemTemplate)===null) +				{ +					$classPath=$this->getItemRenderer(); +					$template=$this->_itemTemplate; +				} +				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($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); +	} + +	/** +	 * Renders the repeater. +	 * This method overrides the parent implementation by rendering the body +	 * content as the whole presentation of the repeater. Outer tag is not rendered. +	 * @param THtmlWriter writer +	 */ +	public function render($writer) +	{ +		if($this->_items && $this->_items->getCount() || $this->_emptyTemplate!==null || $this->getEmptyRenderer()!=='') +			$this->renderContents($writer); +	} + +	/** +	 * Saves item count in viewstate. +	 * This method is invoked right before control state is to be saved. +	 */ +	public function saveState() +	{ +		parent::saveState(); +		if($this->_items) +			$this->setViewState('ItemCount',$this->_items->getCount(),0); +		else +			$this->clearViewState('ItemCount'); +	} + +	/** +	 * Loads item count information from viewstate. +	 * This method is invoked right after control state is loaded. +	 */ +	public function loadState() +	{ +		parent::loadState(); +		if(!$this->getIsDataBound()) +			$this->restoreItemsFromViewState(); +		$this->clearViewState('ItemCount'); +	} + +	/** +	 * Clears up all items in the repeater. +	 */ +	public function reset() +	{ +		$this->getControls()->clear(); +		$this->getItems()->clear(); +		$this->_header=null; +		$this->_footer=null; +	} + +	/** +	 * Creates repeater items based on viewstate information. +	 */ +	protected function restoreItemsFromViewState() +	{ +		$this->reset(); +		if(($itemCount=$this->getViewState('ItemCount',0))>0) +		{ +			$items=$this->getItems(); +			$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); +				$itemType=$i%2==0?TListItemType::Item : TListItemType::AlternatingItem; +				$items->add($this->createItemInternal($i,$itemType,false,null)); +			} +			$this->_footer=$this->createItemInternal(-1,TListItemType::Footer); +		} +		else +			$this->createEmptyContent(); +		$this->clearChildState(); +	} + +	/** +	 * Performs databinding to populate repeater items from data source. +	 * This method is invoked by dataBind(). +	 * You may override this function to provide your own way of data population. +	 * @param Traversable the data +	 */ +	protected function performDataBinding($data) +	{ +		$this->reset(); + +		$keys=$this->getDataKeys(); +		$keys->clear(); +		$keyField=$this->getDataKeyField(); + +		$items=$this->getItems(); +		$itemIndex=0; +		$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->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null); +			if($hasSeparator && $itemIndex>0) +				$this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null); +			$itemType=$itemIndex%2==0?TListItemType::Item : TListItemType::AlternatingItem; +			$items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem)); +			$itemIndex++; +		} +		if($itemIndex>0) +			$this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null); +		else +		{ +			$this->createEmptyContent(); +			$this->dataBindChildren(); +		} +		$this->setViewState('ItemCount',$itemIndex,0); +	} + +	/** +	 * This method overrides parent's implementation to handle +	 * {@link onItemCommand OnItemCommand} event which is bubbled from +	 * 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 +	 * @return boolean whether the event bubbling should stop here. +	 */ +	public function bubbleEvent($sender,$param) +	{ +		if($param instanceof TRepeaterCommandEventParameter) +		{ +			$this->onItemCommand($param); +			return true; +		} +		else +			return false; +	} + +	/** +	 * Raises <b>OnItemCreated</b> event. +	 * This method is invoked after a repeater item is created and instantiated with +	 * template, but before added to the page hierarchy. +	 * 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. +	 * @param TRepeaterItemEventParameter event parameter +	 */ +	public function onItemCreated($param) +	{ +		$this->raiseEvent('OnItemCreated',$this,$param); +	} + +	/** +	 * Raises <b>OnItemDataBound</b> event. +	 * This method is invoked right after an item is data bound. +	 * 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. +	 * @param TRepeaterItemEventParameter event parameter +	 */ +	public function onItemDataBound($param) +	{ +		$this->raiseEvent('OnItemDataBound',$this,$param); +	} + +	/** +	 * Raises <b>OnItemCommand</b> event. +	 * This method is invoked after a button control in +	 * a template raises <b>OnCommand</b> 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 <b>OnCommand</b> 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 +	 * event handlers have chance to respond to the event. +	 * @param TRepeaterCommandEventParameter event parameter +	 */ +	public function onItemCommand($param) +	{ +		$this->raiseEvent('OnItemCommand',$this,$param); +	} + +	/** +	 * Returns the value of the data at the specified field. +	 * If data is an array, TMap or TList, the value will be returned at the index +	 * of the specified field. If the data is a component with a property named +	 * as the field name, the property value will be returned. +	 * Otherwise, an exception will be raised. +	 * @param mixed data item +	 * @param mixed field name +	 * @return mixed data value at the specified field +	 * @throws TInvalidDataValueException if the data is invalid +	 */ +	protected function getDataFieldValue($data,$field) +	{ +		return TDataFieldAccessor::getDataFieldValue($data,$field); +	} +} + +/** + * TRepeaterItemEventParameter class + * + * TRepeaterItemEventParameter encapsulates the parameter data for + * {@link TRepeater::onItemCreated ItemCreated} event of {@link TRepeater} controls. + * The {@link getItem Item} property indicates the repeater item related with the event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeaterItemEventParameter extends TEventParameter +{ +	/** +	 * The repeater item control responsible for the event. +	 * @var TControl +	 */ +	private $_item=null; + +	/** +	 * Constructor. +	 * @param TControl repeater item related with the corresponding event +	 */ +	public function __construct($item) +	{ +		$this->_item=$item; +	} + +	/** +	 * @return TControl repeater item related with the corresponding event +	 */ +	public function getItem() +	{ +		return $this->_item; +	} +} + +/** + * TRepeaterCommandEventParameter class + * + * TRepeaterCommandEventParameter encapsulates the parameter data for + * {@link TRepeater::onItemCommand ItemCommand} event of {@link TRepeater} controls. + * + * The {@link getItem Item} property indicates the repeater item related with the event. + * The {@link getCommandSource CommandSource} refers to the control that originally + * raises the Command event. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeaterCommandEventParameter extends TCommandEventParameter +{ +	/** +	 * @var TControl the repeater item control responsible for the event. +	 */ +	private $_item=null; +	/** +	 * @var TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	private $_source=null; + +	/** +	 * Constructor. +	 * @param TControl repeater item responsible for the event +	 * @param TControl original event sender +	 * @param TCommandEventParameter original event parameter +	 */ +	public function __construct($item,$source,TCommandEventParameter $param) +	{ +		$this->_item=$item; +		$this->_source=$source; +		parent::__construct($param->getCommandName(),$param->getCommandParameter()); +	} + +	/** +	 * @return TControl the repeater item control responsible for the event. +	 */ +	public function getItem() +	{ +		return $this->_item; +	} + +	/** +	 * @return TControl the control originally raises the <b>OnCommand</b> event. +	 */ +	public function getCommandSource() +	{ +		return $this->_source; +	} +} + +/** + * TRepeaterItem class + * + * A TRepeaterItem control represents an item in the {@link TRepeater} control, + * such as heading section, footer section, or a data item. + * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}> + * and {@link getDataItem DataItem} properties, respectively. The type of the item + * is given by {@link getItemType ItemType} property. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeaterItem extends TControl implements INamingContainer, 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 +	 */ +	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 +	 * @since 3.1.0 +	 */ +	public function getData() +	{ +		return $this->_data; +	} + +	/** +	 * @param mixed data to be associated with the item +	 * @since 3.1.0 +	 */ +	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 setDataItem($value) +	{ +		return $this->setData($value); +	} + +	/** +	 * This method overrides parent's implementation by wrapping event parameter +	 * for <b>OnCommand</b> 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; +	} +} + + +/** + * TRepeaterItemCollection class. + * + * TRepeaterItemCollection represents a collection of repeater items. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeaterItemCollection extends TList +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by inserting only objects that are descendant of {@link TControl}. +	 * @param integer the speicified position. +	 * @param TControl new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a control. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TControl) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('repeateritemcollection_item_invalid'); +	} +} + diff --git a/framework/Web/UI/WebControls/TRepeaterItemRenderer.php b/framework/Web/UI/WebControls/TRepeaterItemRenderer.php index 85991b38..fe5171ad 100644 --- a/framework/Web/UI/WebControls/TRepeaterItemRenderer.php +++ b/framework/Web/UI/WebControls/TRepeaterItemRenderer.php @@ -1,50 +1,50 @@ -<?php
 -/**
 - * TRepeaterItemRenderer class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TRepeaterItemRenderer class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TRepeater');
 -Prado::using('System.Web.UI.WebControls.TItemDataRenderer');
 -
 -/**
 - * TRepeaterItemRenderer class
 - *
 - * TRepeaterItemRenderer can be used as a convenient base class to
 - * define an item renderer class specific for {@link TRepeater}.
 - *
 - * TRepeaterItemRenderer extends {@link TItemDataRenderer} and implements
 - * the bubbling scheme for the OnCommand event of repeater items.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.0
 - */
 -class TRepeaterItemRenderer extends TItemDataRenderer
 -{
 -	/**
 -	 * This method overrides parent's implementation by wrapping event parameter
 -	 * for <b>OnCommand</b> 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;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TRepeater'); +Prado::using('System.Web.UI.WebControls.TItemDataRenderer'); + +/** + * TRepeaterItemRenderer class + * + * TRepeaterItemRenderer can be used as a convenient base class to + * define an item renderer class specific for {@link TRepeater}. + * + * TRepeaterItemRenderer extends {@link TItemDataRenderer} and implements + * the bubbling scheme for the OnCommand event of repeater items. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.0 + */ +class TRepeaterItemRenderer extends TItemDataRenderer +{ +	/** +	 * This method overrides parent's implementation by wrapping event parameter +	 * for <b>OnCommand</b> 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; +	} +} + diff --git a/framework/Web/UI/WebControls/TRequiredFieldValidator.php b/framework/Web/UI/WebControls/TRequiredFieldValidator.php index 97555b82..89b142bf 100644 --- a/framework/Web/UI/WebControls/TRequiredFieldValidator.php +++ b/framework/Web/UI/WebControls/TRequiredFieldValidator.php @@ -1,138 +1,138 @@ -<?php
 -/**
 - * TRequiredFieldValidator class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TRequiredFieldValidator class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Using TBaseValidator class
 - */
 -Prado::using('System.Web.UI.WebControls.TBaseValidator');
 -
 -/**
 - * TRequiredFieldValidator class
 - *
 - * TRequiredFieldValidator makes the associated input control a required field.
 - * The input control fails validation if its value does not change from
 - * the {@link setInitialValue InitialValue} property upon losing focus.
 - *
 - * Validation will also succeed if input is of TListControl type and the number
 - * of selected values different from the initial value is greater than zero.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TRequiredFieldValidator extends TBaseValidator
 -{
 -	/**
 -	 * Gets the name of the javascript class responsible for performing validation for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TRequiredFieldValidator';
 -	}
 -
 -	/**
 -	 * @return string the initial value of the associated input control. Defaults to empty string.
 -	 * If the associated input control does not change from this initial value
 -	 * upon postback, the validation fails.
 -	 */
 -	public function getInitialValue()
 -	{
 -		return $this->getViewState('InitialValue','');
 -	}
 -
 -	/**
 -	 * @param string the initial value of the associated input control.
 -	 * If the associated input control does not change from this initial value
 -	 * upon postback, the validation fails.
 -	 */
 -	public function setInitialValue($value)
 -	{
 -		$this->setViewState('InitialValue',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * This method overrides the parent's implementation.
 -	 * The validation succeeds if the input component changes its data
 -	 * from the {@link getInitialValue InitialValue} or the input control is not given.
 -	 *
 -	 * Validation will also succeed if input is of TListControl type and the
 -	 * number of selected values different from the initial value is greater
 -	 * than zero.
 -	 *
 -	 * @return boolean whether the validation succeeds
 -	 */
 -	protected function evaluateIsValid()
 -	{
 -		$control = $this->getValidationTarget();
 -		if($control instanceof TListControl)
 -			return $this->validateListControl($control);
 -		else if($control instanceof TRadioButton && strlen($control->getGroupName()) > 0)
 -			return $this->validateRadioButtonGroup($control);
 -		else
 -			return $this->validateStandardControl($control);
 -	}
 -	
 -	private function validateListControl($control)
 -	{
 -		$initial = trim($this->getInitialValue());
 -		$count = 0;
 -		foreach($control->getItems() as $item)
 -		{
 -			if($item->getSelected() && $item->getValue() != $initial)
 -				$count++;
 -		}
 -		return $count > 0;
 -	}
 -	
 -	private function validateRadioButtonGroup($control)
 -	{
 -		$initial = trim($this->getInitialValue());
 -		foreach($control->getRadioButtonsInGroup() as $radio)
 -		{
 -			if($radio->getChecked())
 -			{
 -				if(strlen($value = $radio->getValue()) > 0)
 -					return $value !== $initial;
 -				else
 -					return true;
 -			}
 -		}
 -		return false;
 -	}
 -	
 -	private function validateStandardControl($control)
 -	{
 -		$initial = trim($this->getInitialValue());
 -		$value=$this->getValidationValue($control);
 -		return (is_bool($value) && $value) || trim($value)!==$initial;
 -	}
 -
 -	/**
 -	 * Returns an array of javascript validator options.
 -	 * @return array javascript validator options.
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options = parent::getClientScriptOptions();
 -		$options['InitialValue']=$this->getInitialValue();
 -		$control = $this->getValidationTarget();
 -		if($control instanceof TListControl)
 -			$options['TotalItems'] = $control->getItemCount();
 -		if($control instanceof TRadioButton && strlen($control->getGroupName()) > 0)
 -			$options['GroupName'] = $control->getGroupName();
 -		return $options;
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Using TBaseValidator class + */ +Prado::using('System.Web.UI.WebControls.TBaseValidator'); + +/** + * TRequiredFieldValidator class + * + * TRequiredFieldValidator makes the associated input control a required field. + * The input control fails validation if its value does not change from + * the {@link setInitialValue InitialValue} property upon losing focus. + * + * Validation will also succeed if input is of TListControl type and the number + * of selected values different from the initial value is greater than zero. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRequiredFieldValidator extends TBaseValidator +{ +	/** +	 * Gets the name of the javascript class responsible for performing validation for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TRequiredFieldValidator'; +	} + +	/** +	 * @return string the initial value of the associated input control. Defaults to empty string. +	 * If the associated input control does not change from this initial value +	 * upon postback, the validation fails. +	 */ +	public function getInitialValue() +	{ +		return $this->getViewState('InitialValue',''); +	} + +	/** +	 * @param string the initial value of the associated input control. +	 * If the associated input control does not change from this initial value +	 * upon postback, the validation fails. +	 */ +	public function setInitialValue($value) +	{ +		$this->setViewState('InitialValue',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * This method overrides the parent's implementation. +	 * The validation succeeds if the input component changes its data +	 * from the {@link getInitialValue InitialValue} or the input control is not given. +	 * +	 * Validation will also succeed if input is of TListControl type and the +	 * number of selected values different from the initial value is greater +	 * than zero. +	 * +	 * @return boolean whether the validation succeeds +	 */ +	protected function evaluateIsValid() +	{ +		$control = $this->getValidationTarget(); +		if($control instanceof TListControl) +			return $this->validateListControl($control); +		else if($control instanceof TRadioButton && strlen($control->getGroupName()) > 0) +			return $this->validateRadioButtonGroup($control); +		else +			return $this->validateStandardControl($control); +	} +	 +	private function validateListControl($control) +	{ +		$initial = trim($this->getInitialValue()); +		$count = 0; +		foreach($control->getItems() as $item) +		{ +			if($item->getSelected() && $item->getValue() != $initial) +				$count++; +		} +		return $count > 0; +	} +	 +	private function validateRadioButtonGroup($control) +	{ +		$initial = trim($this->getInitialValue()); +		foreach($control->getRadioButtonsInGroup() as $radio) +		{ +			if($radio->getChecked()) +			{ +				if(strlen($value = $radio->getValue()) > 0) +					return $value !== $initial; +				else +					return true; +			} +		} +		return false; +	} +	 +	private function validateStandardControl($control) +	{ +		$initial = trim($this->getInitialValue()); +		$value=$this->getValidationValue($control); +		return (is_bool($value) && $value) || trim($value)!==$initial; +	} + +	/** +	 * Returns an array of javascript validator options. +	 * @return array javascript validator options. +	 */ +	protected function getClientScriptOptions() +	{ +		$options = parent::getClientScriptOptions(); +		$options['InitialValue']=$this->getInitialValue(); +		$control = $this->getValidationTarget(); +		if($control instanceof TListControl) +			$options['TotalItems'] = $control->getItemCount(); +		if($control instanceof TRadioButton && strlen($control->getGroupName()) > 0) +			$options['GroupName'] = $control->getGroupName(); +		return $options; +	} +} + diff --git a/framework/Web/UI/WebControls/TSafeHtml.php b/framework/Web/UI/WebControls/TSafeHtml.php index e88277d4..1cd0a597 100644 --- a/framework/Web/UI/WebControls/TSafeHtml.php +++ b/framework/Web/UI/WebControls/TSafeHtml.php @@ -1,85 +1,85 @@ -<?php
 -/**
 - * TSafeHtml class file
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TSafeHtml class
 - *
 - * TSafeHtml is a control that strips down all potentially dangerous
 - * HTML content. It is mainly a wrapper of {@link http://pear.php.net/package/SafeHTML SafeHTML}
 - * project. According to the SafeHTML project, it tries to safeguard
 - * the following situations when the string is to be displayed to end-users,
 - * - Opening tag without its closing tag
 - * - closing tag without its opening tag
 - * - any of these tags: base, basefont, head, html, body, applet, object,
 - *   iframe, frame, frameset, script, layer, ilayer, embed, bgsound, link,
 - *   meta, style, title, blink, xml, etc.
 - * - any of these attributes: on*, data*, dynsrc
 - * - javascript:/vbscript:/about: etc. protocols
 - * - expression/behavior etc. in styles
 - * - any other active content.
 - *
 - * To use TSafeHtml, simply enclose the content to be secured within
 - * the body of TSafeHtml in a template.
 - *
 - * If the content is encoded in UTF-7, you'll need to enable the  {@link setRepackUTF7 RepackUTF7} property
 - * to ensure the contents gets parsed correctly.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TSafeHtml extends TControl
 -{
 -	/**
 -	 * Sets whether to parse the contents as UTF-7. This property enables a routine
 -	 * that repacks the content as UTF-7 before parsing it. Defaults to false.
 -	 * @param boolean whether to parse the contents as UTF-7
 -	 */
 -	public function setRepackUTF7($value)
 -	{
 -		$this->setViewState('RepackUTF7',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether to parse the contents as UTF-7. Defaults to false.
 -	 */
 -	public function getRepackUTF7()
 -	{
 -		return $this->getViewState('RepackUTF7',false);
 -	}
 -
 -	/**
 -	 * Renders body content.
 -	 * This method overrides parent implementation by removing
 -	 * malicious javascript code from the body content
 -	 * @param THtmlWriter writer
 -	 */
 -	public function render($writer)
 -	{
 -		$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), new TTextWriter());
 -		parent::render($htmlWriter);
 -		$writer->write($this->parseSafeHtml($htmlWriter->flush()));
 -	}
 -
 -	/**
 -	 * Use SafeHTML to remove malicous javascript from the HTML content.
 -	 * @param string HTML content
 -	 * @return string safer HTML content
 -	 */
 -	protected function parseSafeHtml($text)
 -	{
 -		$renderer = Prado::createComponent('System.3rdParty.SafeHtml.TSafeHtmlParser');
 -		return $renderer->parse($text, $this->getRepackUTF7());
 -	}
 -}
 -
 +<?php +/** + * TSafeHtml class file + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TSafeHtml class + * + * TSafeHtml is a control that strips down all potentially dangerous + * HTML content. It is mainly a wrapper of {@link http://pear.php.net/package/SafeHTML SafeHTML} + * project. According to the SafeHTML project, it tries to safeguard + * the following situations when the string is to be displayed to end-users, + * - Opening tag without its closing tag + * - closing tag without its opening tag + * - any of these tags: base, basefont, head, html, body, applet, object, + *   iframe, frame, frameset, script, layer, ilayer, embed, bgsound, link, + *   meta, style, title, blink, xml, etc. + * - any of these attributes: on*, data*, dynsrc + * - javascript:/vbscript:/about: etc. protocols + * - expression/behavior etc. in styles + * - any other active content. + * + * To use TSafeHtml, simply enclose the content to be secured within + * the body of TSafeHtml in a template. + * + * If the content is encoded in UTF-7, you'll need to enable the  {@link setRepackUTF7 RepackUTF7} property + * to ensure the contents gets parsed correctly. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TSafeHtml extends TControl +{ +	/** +	 * Sets whether to parse the contents as UTF-7. This property enables a routine +	 * that repacks the content as UTF-7 before parsing it. Defaults to false. +	 * @param boolean whether to parse the contents as UTF-7 +	 */ +	public function setRepackUTF7($value) +	{ +		$this->setViewState('RepackUTF7',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether to parse the contents as UTF-7. Defaults to false. +	 */ +	public function getRepackUTF7() +	{ +		return $this->getViewState('RepackUTF7',false); +	} + +	/** +	 * Renders body content. +	 * This method overrides parent implementation by removing +	 * malicious javascript code from the body content +	 * @param THtmlWriter writer +	 */ +	public function render($writer) +	{ +		$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), new TTextWriter()); +		parent::render($htmlWriter); +		$writer->write($this->parseSafeHtml($htmlWriter->flush())); +	} + +	/** +	 * Use SafeHTML to remove malicous javascript from the HTML content. +	 * @param string HTML content +	 * @return string safer HTML content +	 */ +	protected function parseSafeHtml($text) +	{ +		$renderer = Prado::createComponent('System.3rdParty.SafeHtml.TSafeHtmlParser'); +		return $renderer->parse($text, $this->getRepackUTF7()); +	} +} + diff --git a/framework/Web/UI/WebControls/TSlider.php b/framework/Web/UI/WebControls/TSlider.php index ce080f5f..06df52b6 100644 --- a/framework/Web/UI/WebControls/TSlider.php +++ b/framework/Web/UI/WebControls/TSlider.php @@ -1,574 +1,574 @@ -<?php
 -/**
 - * TSlider class file.
 - *
 - * @author Christophe Boulain <Christophe.Boulain@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -
 -/**
 - * TSlider class
 - *
 - * TSlider displays a slider for numeric input purpose. A slider consists of a 'track',
 - * which define the range of possible value, and a 'handle' which can slide on the track, to select
 - * a value in the range. The track can be either Horizontal or Vertical, depending of the {@link SetDirection Direction}
 - * property. By default, it's horizontal.
 - *
 - * The range boundaries are defined by {@link SetMinValue MinValue} and {@link SetMaxValue MaxValue} properties.
 - * The default range is from 0 to 100.
 - * The {@link SetStepSize StepSize} property can be used to define the <b>step</b> between 2 values inside the range.
 - * Notice that this step will be recomputed if there is more than 200 values between the range boundaries.
 - * You can also provide the allowed values by setting the {@link SetValues Values} array.
 - *
 - * A 'Progress Indicator' can be displayed within the track with the {@link SetProgressIndicator ProgressIndicator} property.
 - * 
 - * The TSlider control can be easily customized using CssClasses. You can provide your own css file, using the
 - * {@link SetCssUrl CssUrl} property.
 - * The css class for TSlider can be set by the {@link setCssClass CssClass} property. Default value is "Slider HorizontalSlider" 
 - * for an horizontal slider, and "Slider VerticalSlider" for a vertical one.
 - *
 - * If {@link SetAutoPostBack AutoPostBack} property is true, postback is sent as soon as the value changed.
 - *
 - * TSlider raises the {@link onValueChanged} event when the value of the slider has changed during postback.
 - *
 - * You can also attach ClientSide javascript events handler to the slider :
 - * - ClientSide.onSlide is called when the handle is slided on the track. You can get the current value in the <b>value</b>
 - * javascript variable. You can use this event to update on client side a label with the current value
 - * - ClientSide.onChange is called when the slider value has changed (at the end of a move).
 - *
 - * @author Christophe Boulain <Christophe.Boulain@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TSlider extends TWebControl implements IPostBackDataHandler, IDataRenderer
 -{
 -	const MAX_STEPS=200;
 -	/**
 -	 * @var TSliderHandle handle component
 -	 */
 -	private $_handle;
 -	/*
 -	 * @var boolean Wether the data has changed during postback
 -	 */
 -	private $_dataChanged=false;
 -	/**
 -	 * @var TSliderClientScript Clients side javascripts
 -	 */
 -	private $_clientScript=null;
 -
 -	/**
 -	 * @return TSliderDirection Direction of slider (Horizontal or Vertical). Defaults to Horizontal.
 -	 */
 -	public function getDirection()
 -	{
 -		return $this->getViewState('Direction', TSliderDirection::Horizontal);
 -	}
 -
 -	/**
 -	 * @param TSliderDirection Direction of slider (Horizontal or Vertical)
 -	 */
 -	public function setDirection($value)
 -	{
 -		$this->setViewState('Direction', TPropertyValue::ensureEnum($value,'TSliderDirection'),TSliderDirection::Horizontal);
 -	}
 -
 -	/**
 -	 * @return string URL for the CSS file including all relevant CSS class definitions. Defaults to '' (a default CSS file will be applied in this case.)
 -	 */
 -	public function getCssUrl()
 -	{
 -		return $this->getViewState('CssUrl','');
 -	}
 -
 -	/**
 -	 * @param string URL for the CSS file including all relevant CSS class definitions.
 -	 */
 -	public function setCssUrl($value)
 -	{
 -		$this->setViewState('CssUrl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return float Maximum value for the slider. Defaults to 100.0.
 -	 */
 -	public function getMaxValue()
 -	{
 -		return $this->getViewState('MaxValue',100.0);
 -	}
 -
 -	/**
 -	 * @param float Maximum value for slider
 -	 */
 -	public function setMaxValue($value)
 -	{
 -		$this->setViewState('MaxValue', TPropertyValue::ensureFloat($value),100.0);
 -	}
 -
 -	/**
 -	 * @return float Minimum value for slider. Defaults to 0.0.
 -	 */
 -	public function getMinValue()
 -	{
 -		return $this->getViewState('MinValue',0.0);
 -	}
 -
 -	/**
 -	 * @param float Minimum value for slider
 -	 */
 -	public function setMinValue($value)
 -	{
 -		$this->setViewState('MinValue', TPropertyValue::ensureFloat($value),0.0);
 -	}
 -
 -	/**
 -	 * @return float Step size. Defaults to 1.0.
 -	 */
 -	public function getStepSize()
 -	{
 -		return $this->getViewState('StepSize', 1.0);
 -	}
 -
 -	/**
 -	 * Sets the step size used to determine the places where the slider handle can stop at.
 -	 * An evenly distributed stop marks will be generated according to
 -	 * {@link getMinValue MinValue}, {@link getMaxValue MaxValue} and StepSize.
 -	 * To use uneven stop marks, set {@link setValues Values}.
 -	 * @param float Step size.
 -	 */
 -	public function setStepSize($value)
 -	{
 -		$this->setViewState('StepSize', $value, 1.0);
 -	}
 -	
 -	/**
 -	 * @return boolean wether to display a progress indicator or not. Defaults to true.
 -	 */
 -	public function getProgressIndicator ()
 -	{
 -		return $this->getViewState('ProgressIndicator', true);
 -	}
 -
 -	/**
 -	 * @param boolean wether to display a progress indicator or not. Defaults to true.
 -	 */
 -	public function setProgressIndicator ($value)
 -	{
 -		$this->setViewState('ProgressIndicator', TPropertyValue::ensureBoolean($value), true);
 -	}
 -	/**
 -	 * @return float current value of slider
 -	 */
 -	public function getValue()
 -	{
 -		return $this->getViewState('Value',0.0);
 -	}
 -
 -	/**
 -	 * @param float current value of slider
 -	 */
 -	public function setValue($value)
 -	{
 -		$this->setViewState('Value', TPropertyValue::ensureFloat($value),0.0);
 -	}
 -
 -	/**
 -	 * Returns the value of the TSlider control.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link getValue()}.
 -	 * @return string the value of the TSlider control.
 -	 * @see getValue
 -	 */
 -	public function getData()
 -	{
 -		return $this->getValue();
 -	}
 -
 -	/**
 -	 * Sets the value of the TSlider control.
 -	 * This method is required by {@link IDataRenderer}.
 -	 * It is the same as {@link setValue()}.
 -	 * @param string the value of the TSlider control.
 -	 * @see setValue
 -	 */
 -	public function setData($value)
 -	{
 -		$this->setValue($value);
 -	}
 -
 -	/**
 -	 * @return array list of allowed values the slider can take. Defaults to an empty array.
 -	 */
 -	public function getValues()
 -	{
 -		return $this->getViewState('Values', array());
 -	}
 -
 -	/**
 -	 * Sets the possible values that the slider can take.
 -	 * If this is set, {@link setStepSize StepSize} will be ignored. The latter
 -	 * generates a set of evenly distributed candidate values.
 -	 * @param array list of allowed values the slider can take
 -	 */
 -	public function setValues($value)
 -	{
 -		$this->setViewState('Values', TPropertyValue::ensureArray($value), array());
 -	}
 -	
 -	/**
 -	 * @return boolean a value indicating whether an automatic postback to the server
 -	 * will occur whenever the user modifies the slider value. Defaults to false.
 -	 */
 -	public function getAutoPostBack()
 -	{
 -		return $this->getViewState('AutoPostBack',false);
 -	}
 -
 -	/**
 -	 * Sets the value indicating if postback automatically.
 -	 * An automatic postback to the server will occur whenever the user
 -	 * modifies the slider value.
 -	 * @param boolean the value indicating if postback automatically
 -	 */
 -	public function setAutoPostBack($value)
 -	{
 -		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TSlider';
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method is required by {@link IPostBackDataHandler} interface.
 -	 * It is invoked by the framework when {@link getValue Value} property
 -	 * is changed on postback.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		$this->onValueChanged(null);
 -	}
 -
 -	/**
 -	 * Raises <b>OnValueChanged</b> event.
 -	 * This method is invoked when the {@link getValue Value}
 -	 * property changes on postback.
 -	 * If you override this method, be sure to call the parent implementation to ensure
 -	 * the invocation of the attached event handlers.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onValueChanged($param)
 -	{
 -		$this->raiseEvent('OnValueChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		$value=(float)$values[$this->getClientID().'_1'];
 -		if($this->getValue()!==$value)
 -		{
 -			$this->setValue($value);
 -			return $this->_dataChanged=true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Gets the TSliderClientScript to set the TSlider event handlers.
 -	 *
 -	 * The slider on the client-side supports the following events.
 -	 * # <tt>OnSliderMove</tt> -- raised when the slider is moved.
 -	 * # <tt>OnSliderChanged</tt> -- raised when the slider value is changed
 -	 *
 -	 * You can attach custom javascript code to each of these events
 -	 *
 -	 * @return TSliderClientScript javascript validator event options.
 -	 */
 -	public function getClientSide()
 -	{
 -		if($this->_clientScript===null)
 -			$this->_clientScript = $this->createClientScript();
 -		return $this->_clientScript;
 -	}
 -
 -	/**
 -	 * @return TSliderClientScript javascript event options.
 -	 */
 -	protected function createClientScript()
 -	{
 -		return new TSliderClientScript;
 -	}
 -
 -	/**
 -	 * @return string the HTML tag name for slider. Defaults to div.
 -	 */
 -	public function getTagName ()
 -	{
 -		return "div";
 -	}
 -
 -	/**
 -	 * Add the specified css classes to the track
 -	 * @param THtmlWriter writer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		$writer->addAttribute('id',$this->getClientID());
 -		if ($this->getCssClass()==='')
 -		{
 -			$class=($this->getDirection()==TSliderDirection::Horizontal)?'HorizontalSlider':'VerticalSlider';
 -			$writer->addAttribute('class', 'Slider '.$class);
 -		}
 -		
 -	}
 -
 -	/**
 -	 * Render the body content
 -	 */
 -	public function renderContents($writer)
 -	{
 -		// Render the 'Track'
 -		$writer->addAttribute('class', 'Track');
 -		$writer->addAttribute('id', $this->getClientID().'_track');
 -		$writer->renderBeginTag('div');
 -		// Render the 'Progress Indicator'
 -		if ($this->getProgressIndicator())
 -		{
 -			$writer->addAttribute('class', 'Progress');
 -			$writer->addAttribute('id', $this->getClientID().'_progress');
 -			$writer->renderBeginTag('div');
 -			$writer->renderEndTag();
 -		}
 -		// Render the 'Ruler'
 -		/*
 -		 * Removing for now
 -		$writer->addAttribute('class', 'RuleContainer');
 -		$writer->addAttribute('id', $this->getClientID()."_rule");
 -		$writer->renderBeginTag('div');
 -		for ($i=0;$i<=100;$i+=10)
 -		{
 -			$writer->addAttribute('class', 'RuleMark');
 -			$attr=($this->getDirection()===TSliderDirection::Horizontal)?"left":"top";
 -			$writer->addStyleAttribute($attr, $i.'%');
 -			$writer->renderBeginTag('div');
 -			$writer->renderEndTag();
 -		}
 -		$writer->renderEndTag();
 -		*/
 -		
 -		$writer->renderEndTag();
 -		
 -		// Render the 'Handle'
 -		$writer->addAttribute('class', 'Handle');
 -		$writer->addAttribute('id', $this->getClientID().'_handle');
 -		$writer->renderBeginTag('div');
 -		$writer->renderEndTag();
 -	}
 -	/**
 -	 * Registers CSS and JS.
 -	 * This method is invoked right before the control rendering, if the control is visible.
 -	 * @param mixed event parameter
 -	 */
 -	public function onPreRender ($param)
 -	{
 -		parent::onPreRender($param);
 -		$this->registerStyleSheet();
 -		$this->registerSliderClientScript();
 -
 -	}
 -
 -	/**
 -	 * Registers the CSS relevant to the TSlider.
 -	 * It will register the CSS file specified by {@link getCssUrl CssUrl}.
 -	 * If that is not set, it will use the default CSS.
 -	 */
 -	protected function registerStyleSheet()
 -	{
 -		if(($url=$this->getCssUrl())==='')
 -		{
 -			$manager=$this->getApplication()->getAssetManager();
 -			// publish the assets
 -			$url=$manager->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'TSlider');
 -			$url.='/TSlider.css';
 -		}
 -		$this->getPage()->getClientScript()->registerStyleSheetFile($url,$url);
 -	}
 -
 -	/**
 -	 * Registers the javascript code to initialize the slider.
 -	 */
 -	protected function registerSliderClientScript()
 -	{
 -		$page=$this->getPage();
 -		$cs = $page->getClientScript();
 -		$cs->registerPradoScript("slider");
 -		$id=$this->getClientID();
 -		$cs->registerHiddenField($id.'_1',$this->getValue());
 -		$page->registerRequiresPostData($this);
 -		$cs->registerPostBackControl($this->getClientClassName(),$this->getSliderOptions());
 -	}
 -
 -	/**
 -	 * Get javascript sliderr options.
 -	 * @return array slider client-side options
 -	 */
 -	protected function getSliderOptions()
 -	{
 -		// PostBack Options :
 -		$options['ID'] = $this->getClientID();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		$options['AutoPostBack'] = $this->getAutoPostBack();
 -
 -		// Slider Control options
 -		$minValue=$this->getMinValue();
 -		$maxValue=$this->getMaxValue();
 -		$options['axis'] = strtolower($this->getDirection());
 -		$options['maximum'] = $maxValue;
 -		$options['minimum'] = $minValue;
 -		$options['range'] = TJavascript::quoteJsLiteral('$R('.$minValue.",".$maxValue.")");
 -		$options['sliderValue'] = $this->getValue();
 -		$options['disabled'] = !$this->getEnabled();
 -		$values=$this->getValues();
 -		if (!empty($values))
 -		{
 -			// Values are provided. Check if min/max are present in them
 -			if (!in_array($minValue, $values)) $values[]=$minValue;
 -			if (!in_array($maxValue, $values)) $values[]=$maxValue;
 -			// Remove all values outsize the range [min..max]
 -			foreach ($values as $idx=>$value)
 -			{
 -				if ($value < $minValue) unset ($values[$idx]);
 -				if ($value > $maxValue) unset ($values[$idx]);
 -			}
 -		}
 -		else
 -		{
 -			// Values are not provided, generate automatically using stepsize
 -			$step=$this->getStepSize();
 -			// We want at most self::MAX_STEPS values, so, change the step if necessary
 -			if (($maxValue-$minValue)/$step > self::MAX_STEPS)
 -			{
 -				$step=($maxValue-$minValue)/self::MAX_STEPS;
 -			}
 -			$values=array();
 -			for ($i=$minValue;$i<=$maxValue;$i+=$step)
 -				$values[]=$i;
 -			// Add max if it's not in the array because of step
 -			if (!in_array($maxValue, $values)) $values[]=$maxValue;
 -		}
 -		$options['values'] = $values;
 -		if($this->_clientScript!==null)
 -			$options = array_merge($options,$this->_clientScript->getOptions()->toArray());
 -		return $options;
 -	}
 -}
 -
 -/**
 - * TSliderClientScript class.
 - *
 - * Client-side slider events {@link setOnChange OnChange} and {@line setOnMove OnMove}
 - * can be modified through the {@link TSlider:: getClientSide ClientSide}
 - * property of a slider.
 - *
 - * The current value of the slider can be get in the 'value' js variable
 - *
 - * The <tt>OnMove</tt> event is raised when the slider moves
 - * The <tt>OnChange</tt> event is raised when the slider value is changed (or at the end of a move)
 - *
 - * @author Christophe Boulain <Christophe.Boulain@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TSliderClientScript extends TClientSideOptions
 -{
 -	/**
 -	 * Javascript code to execute when the slider value is changed.
 -	 * @param string javascript code
 -	 */
 -	public function setOnChange($javascript)
 -	{
 -		$code=TJavascript::quoteJsLiteral("function (value) { {$javascript} }");
 -		$this->setFunction('onChange', $code);
 -	}
 -
 -	/**
 -	 * @return string javascript code to execute when the slider value is changed.
 -	 */
 -	public function getOnChange()
 -	{
 -		return $this->getOption('onChange');
 -	}
 -
 -	/* Javascript code to execute when the slider moves.
 -	 * @param string javascript code
 -	 */
 -	public function setOnSlide($javascript)
 -	{
 -		$code=TJavascript::quoteJsLiteral("function (value) { {$javascript} }");
 -		$this->setFunction('onSlide', $code);
 -	}
 -
 -	/**
 -	 * @return string javascript code to execute when the slider moves.
 -	 */
 -	public function getOnSlide()
 -	{
 -		return $this->getOption('onSlide');
 -	}
 -}
 -
 -
 -/**
 - * TSliderDirection class.
 - *
 - * TSliderDirection defines the enumerable type for the possible direction that can be used in a {@link TSlider}
 - *
 - * The following enumerable values are defined :
 - * - Horizontal : Horizontal slider
 - * - Vertical : Vertical slider
 - *
 - * @author Christophe Boulain <Christophe.Boulain@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1.1
 - */
 -class TSliderDirection extends TEnumerable
 -{
 -	const Horizontal='Horizontal';
 -	const Vertical='Vertical';
 -}
 -
 -
 +<?php +/** + * TSlider class file. + * + * @author Christophe Boulain <Christophe.Boulain@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ + +/** + * TSlider class + * + * TSlider displays a slider for numeric input purpose. A slider consists of a 'track', + * which define the range of possible value, and a 'handle' which can slide on the track, to select + * a value in the range. The track can be either Horizontal or Vertical, depending of the {@link SetDirection Direction} + * property. By default, it's horizontal. + * + * The range boundaries are defined by {@link SetMinValue MinValue} and {@link SetMaxValue MaxValue} properties. + * The default range is from 0 to 100. + * The {@link SetStepSize StepSize} property can be used to define the <b>step</b> between 2 values inside the range. + * Notice that this step will be recomputed if there is more than 200 values between the range boundaries. + * You can also provide the allowed values by setting the {@link SetValues Values} array. + * + * A 'Progress Indicator' can be displayed within the track with the {@link SetProgressIndicator ProgressIndicator} property. + *  + * The TSlider control can be easily customized using CssClasses. You can provide your own css file, using the + * {@link SetCssUrl CssUrl} property. + * The css class for TSlider can be set by the {@link setCssClass CssClass} property. Default value is "Slider HorizontalSlider"  + * for an horizontal slider, and "Slider VerticalSlider" for a vertical one. + * + * If {@link SetAutoPostBack AutoPostBack} property is true, postback is sent as soon as the value changed. + * + * TSlider raises the {@link onValueChanged} event when the value of the slider has changed during postback. + * + * You can also attach ClientSide javascript events handler to the slider : + * - ClientSide.onSlide is called when the handle is slided on the track. You can get the current value in the <b>value</b> + * javascript variable. You can use this event to update on client side a label with the current value + * - ClientSide.onChange is called when the slider value has changed (at the end of a move). + * + * @author Christophe Boulain <Christophe.Boulain@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TSlider extends TWebControl implements IPostBackDataHandler, IDataRenderer +{ +	const MAX_STEPS=200; +	/** +	 * @var TSliderHandle handle component +	 */ +	private $_handle; +	/* +	 * @var boolean Wether the data has changed during postback +	 */ +	private $_dataChanged=false; +	/** +	 * @var TSliderClientScript Clients side javascripts +	 */ +	private $_clientScript=null; + +	/** +	 * @return TSliderDirection Direction of slider (Horizontal or Vertical). Defaults to Horizontal. +	 */ +	public function getDirection() +	{ +		return $this->getViewState('Direction', TSliderDirection::Horizontal); +	} + +	/** +	 * @param TSliderDirection Direction of slider (Horizontal or Vertical) +	 */ +	public function setDirection($value) +	{ +		$this->setViewState('Direction', TPropertyValue::ensureEnum($value,'TSliderDirection'),TSliderDirection::Horizontal); +	} + +	/** +	 * @return string URL for the CSS file including all relevant CSS class definitions. Defaults to '' (a default CSS file will be applied in this case.) +	 */ +	public function getCssUrl() +	{ +		return $this->getViewState('CssUrl',''); +	} + +	/** +	 * @param string URL for the CSS file including all relevant CSS class definitions. +	 */ +	public function setCssUrl($value) +	{ +		$this->setViewState('CssUrl',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return float Maximum value for the slider. Defaults to 100.0. +	 */ +	public function getMaxValue() +	{ +		return $this->getViewState('MaxValue',100.0); +	} + +	/** +	 * @param float Maximum value for slider +	 */ +	public function setMaxValue($value) +	{ +		$this->setViewState('MaxValue', TPropertyValue::ensureFloat($value),100.0); +	} + +	/** +	 * @return float Minimum value for slider. Defaults to 0.0. +	 */ +	public function getMinValue() +	{ +		return $this->getViewState('MinValue',0.0); +	} + +	/** +	 * @param float Minimum value for slider +	 */ +	public function setMinValue($value) +	{ +		$this->setViewState('MinValue', TPropertyValue::ensureFloat($value),0.0); +	} + +	/** +	 * @return float Step size. Defaults to 1.0. +	 */ +	public function getStepSize() +	{ +		return $this->getViewState('StepSize', 1.0); +	} + +	/** +	 * Sets the step size used to determine the places where the slider handle can stop at. +	 * An evenly distributed stop marks will be generated according to +	 * {@link getMinValue MinValue}, {@link getMaxValue MaxValue} and StepSize. +	 * To use uneven stop marks, set {@link setValues Values}. +	 * @param float Step size. +	 */ +	public function setStepSize($value) +	{ +		$this->setViewState('StepSize', $value, 1.0); +	} +	 +	/** +	 * @return boolean wether to display a progress indicator or not. Defaults to true. +	 */ +	public function getProgressIndicator () +	{ +		return $this->getViewState('ProgressIndicator', true); +	} + +	/** +	 * @param boolean wether to display a progress indicator or not. Defaults to true. +	 */ +	public function setProgressIndicator ($value) +	{ +		$this->setViewState('ProgressIndicator', TPropertyValue::ensureBoolean($value), true); +	} +	/** +	 * @return float current value of slider +	 */ +	public function getValue() +	{ +		return $this->getViewState('Value',0.0); +	} + +	/** +	 * @param float current value of slider +	 */ +	public function setValue($value) +	{ +		$this->setViewState('Value', TPropertyValue::ensureFloat($value),0.0); +	} + +	/** +	 * Returns the value of the TSlider control. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link getValue()}. +	 * @return string the value of the TSlider control. +	 * @see getValue +	 */ +	public function getData() +	{ +		return $this->getValue(); +	} + +	/** +	 * Sets the value of the TSlider control. +	 * This method is required by {@link IDataRenderer}. +	 * It is the same as {@link setValue()}. +	 * @param string the value of the TSlider control. +	 * @see setValue +	 */ +	public function setData($value) +	{ +		$this->setValue($value); +	} + +	/** +	 * @return array list of allowed values the slider can take. Defaults to an empty array. +	 */ +	public function getValues() +	{ +		return $this->getViewState('Values', array()); +	} + +	/** +	 * Sets the possible values that the slider can take. +	 * If this is set, {@link setStepSize StepSize} will be ignored. The latter +	 * generates a set of evenly distributed candidate values. +	 * @param array list of allowed values the slider can take +	 */ +	public function setValues($value) +	{ +		$this->setViewState('Values', TPropertyValue::ensureArray($value), array()); +	} +	 +	/** +	 * @return boolean a value indicating whether an automatic postback to the server +	 * will occur whenever the user modifies the slider value. Defaults to false. +	 */ +	public function getAutoPostBack() +	{ +		return $this->getViewState('AutoPostBack',false); +	} + +	/** +	 * Sets the value indicating if postback automatically. +	 * An automatic postback to the server will occur whenever the user +	 * modifies the slider value. +	 * @param boolean the value indicating if postback automatically +	 */ +	public function setAutoPostBack($value) +	{ +		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TSlider'; +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Raises postdata changed event. +	 * This method is required by {@link IPostBackDataHandler} interface. +	 * It is invoked by the framework when {@link getValue Value} property +	 * is changed on postback. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		$this->onValueChanged(null); +	} + +	/** +	 * Raises <b>OnValueChanged</b> event. +	 * This method is invoked when the {@link getValue Value} +	 * property changes on postback. +	 * If you override this method, be sure to call the parent implementation to ensure +	 * the invocation of the attached event handlers. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onValueChanged($param) +	{ +		$this->raiseEvent('OnValueChanged',$this,$param); +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		$value=(float)$values[$this->getClientID().'_1']; +		if($this->getValue()!==$value) +		{ +			$this->setValue($value); +			return $this->_dataChanged=true; +		} +		else +			return false; +	} + +	/** +	 * Gets the TSliderClientScript to set the TSlider event handlers. +	 * +	 * The slider on the client-side supports the following events. +	 * # <tt>OnSliderMove</tt> -- raised when the slider is moved. +	 * # <tt>OnSliderChanged</tt> -- raised when the slider value is changed +	 * +	 * You can attach custom javascript code to each of these events +	 * +	 * @return TSliderClientScript javascript validator event options. +	 */ +	public function getClientSide() +	{ +		if($this->_clientScript===null) +			$this->_clientScript = $this->createClientScript(); +		return $this->_clientScript; +	} + +	/** +	 * @return TSliderClientScript javascript event options. +	 */ +	protected function createClientScript() +	{ +		return new TSliderClientScript; +	} + +	/** +	 * @return string the HTML tag name for slider. Defaults to div. +	 */ +	public function getTagName () +	{ +		return "div"; +	} + +	/** +	 * Add the specified css classes to the track +	 * @param THtmlWriter writer +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		$writer->addAttribute('id',$this->getClientID()); +		if ($this->getCssClass()==='') +		{ +			$class=($this->getDirection()==TSliderDirection::Horizontal)?'HorizontalSlider':'VerticalSlider'; +			$writer->addAttribute('class', 'Slider '.$class); +		} +		 +	} + +	/** +	 * Render the body content +	 */ +	public function renderContents($writer) +	{ +		// Render the 'Track' +		$writer->addAttribute('class', 'Track'); +		$writer->addAttribute('id', $this->getClientID().'_track'); +		$writer->renderBeginTag('div'); +		// Render the 'Progress Indicator' +		if ($this->getProgressIndicator()) +		{ +			$writer->addAttribute('class', 'Progress'); +			$writer->addAttribute('id', $this->getClientID().'_progress'); +			$writer->renderBeginTag('div'); +			$writer->renderEndTag(); +		} +		// Render the 'Ruler' +		/* +		 * Removing for now +		$writer->addAttribute('class', 'RuleContainer'); +		$writer->addAttribute('id', $this->getClientID()."_rule"); +		$writer->renderBeginTag('div'); +		for ($i=0;$i<=100;$i+=10) +		{ +			$writer->addAttribute('class', 'RuleMark'); +			$attr=($this->getDirection()===TSliderDirection::Horizontal)?"left":"top"; +			$writer->addStyleAttribute($attr, $i.'%'); +			$writer->renderBeginTag('div'); +			$writer->renderEndTag(); +		} +		$writer->renderEndTag(); +		*/ +		 +		$writer->renderEndTag(); +		 +		// Render the 'Handle' +		$writer->addAttribute('class', 'Handle'); +		$writer->addAttribute('id', $this->getClientID().'_handle'); +		$writer->renderBeginTag('div'); +		$writer->renderEndTag(); +	} +	/** +	 * Registers CSS and JS. +	 * This method is invoked right before the control rendering, if the control is visible. +	 * @param mixed event parameter +	 */ +	public function onPreRender ($param) +	{ +		parent::onPreRender($param); +		$this->registerStyleSheet(); +		$this->registerSliderClientScript(); + +	} + +	/** +	 * Registers the CSS relevant to the TSlider. +	 * It will register the CSS file specified by {@link getCssUrl CssUrl}. +	 * If that is not set, it will use the default CSS. +	 */ +	protected function registerStyleSheet() +	{ +		if(($url=$this->getCssUrl())==='') +		{ +			$manager=$this->getApplication()->getAssetManager(); +			// publish the assets +			$url=$manager->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'TSlider'); +			$url.='/TSlider.css'; +		} +		$this->getPage()->getClientScript()->registerStyleSheetFile($url,$url); +	} + +	/** +	 * Registers the javascript code to initialize the slider. +	 */ +	protected function registerSliderClientScript() +	{ +		$page=$this->getPage(); +		$cs = $page->getClientScript(); +		$cs->registerPradoScript("slider"); +		$id=$this->getClientID(); +		$cs->registerHiddenField($id.'_1',$this->getValue()); +		$page->registerRequiresPostData($this); +		$cs->registerPostBackControl($this->getClientClassName(),$this->getSliderOptions()); +	} + +	/** +	 * Get javascript sliderr options. +	 * @return array slider client-side options +	 */ +	protected function getSliderOptions() +	{ +		// PostBack Options : +		$options['ID'] = $this->getClientID(); +		$options['EventTarget'] = $this->getUniqueID(); +		$options['AutoPostBack'] = $this->getAutoPostBack(); + +		// Slider Control options +		$minValue=$this->getMinValue(); +		$maxValue=$this->getMaxValue(); +		$options['axis'] = strtolower($this->getDirection()); +		$options['maximum'] = $maxValue; +		$options['minimum'] = $minValue; +		$options['range'] = TJavascript::quoteJsLiteral('$R('.$minValue.",".$maxValue.")"); +		$options['sliderValue'] = $this->getValue(); +		$options['disabled'] = !$this->getEnabled(); +		$values=$this->getValues(); +		if (!empty($values)) +		{ +			// Values are provided. Check if min/max are present in them +			if (!in_array($minValue, $values)) $values[]=$minValue; +			if (!in_array($maxValue, $values)) $values[]=$maxValue; +			// Remove all values outsize the range [min..max] +			foreach ($values as $idx=>$value) +			{ +				if ($value < $minValue) unset ($values[$idx]); +				if ($value > $maxValue) unset ($values[$idx]); +			} +		} +		else +		{ +			// Values are not provided, generate automatically using stepsize +			$step=$this->getStepSize(); +			// We want at most self::MAX_STEPS values, so, change the step if necessary +			if (($maxValue-$minValue)/$step > self::MAX_STEPS) +			{ +				$step=($maxValue-$minValue)/self::MAX_STEPS; +			} +			$values=array(); +			for ($i=$minValue;$i<=$maxValue;$i+=$step) +				$values[]=$i; +			// Add max if it's not in the array because of step +			if (!in_array($maxValue, $values)) $values[]=$maxValue; +		} +		$options['values'] = $values; +		if($this->_clientScript!==null) +			$options = array_merge($options,$this->_clientScript->getOptions()->toArray()); +		return $options; +	} +} + +/** + * TSliderClientScript class. + * + * Client-side slider events {@link setOnChange OnChange} and {@line setOnMove OnMove} + * can be modified through the {@link TSlider:: getClientSide ClientSide} + * property of a slider. + * + * The current value of the slider can be get in the 'value' js variable + * + * The <tt>OnMove</tt> event is raised when the slider moves + * The <tt>OnChange</tt> event is raised when the slider value is changed (or at the end of a move) + * + * @author Christophe Boulain <Christophe.Boulain@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TSliderClientScript extends TClientSideOptions +{ +	/** +	 * Javascript code to execute when the slider value is changed. +	 * @param string javascript code +	 */ +	public function setOnChange($javascript) +	{ +		$code=TJavascript::quoteJsLiteral("function (value) { {$javascript} }"); +		$this->setFunction('onChange', $code); +	} + +	/** +	 * @return string javascript code to execute when the slider value is changed. +	 */ +	public function getOnChange() +	{ +		return $this->getOption('onChange'); +	} + +	/* Javascript code to execute when the slider moves. +	 * @param string javascript code +	 */ +	public function setOnSlide($javascript) +	{ +		$code=TJavascript::quoteJsLiteral("function (value) { {$javascript} }"); +		$this->setFunction('onSlide', $code); +	} + +	/** +	 * @return string javascript code to execute when the slider moves. +	 */ +	public function getOnSlide() +	{ +		return $this->getOption('onSlide'); +	} +} + + +/** + * TSliderDirection class. + * + * TSliderDirection defines the enumerable type for the possible direction that can be used in a {@link TSlider} + * + * The following enumerable values are defined : + * - Horizontal : Horizontal slider + * - Vertical : Vertical slider + * + * @author Christophe Boulain <Christophe.Boulain@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1.1 + */ +class TSliderDirection extends TEnumerable +{ +	const Horizontal='Horizontal'; +	const Vertical='Vertical'; +} + + diff --git a/framework/Web/UI/WebControls/TStatements.php b/framework/Web/UI/WebControls/TStatements.php index c3f43278..dd7631e2 100644 --- a/framework/Web/UI/WebControls/TStatements.php +++ b/framework/Web/UI/WebControls/TStatements.php @@ -1,63 +1,63 @@ -<?php
 -/**
 - * TStatements class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TStatements class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TStatements class
 - *
 - * TStatements executes one or several PHP statements and renders the display
 - * generated during the execution. The execution happens during the rendering stage.
 - * The PHP statements being executed can be set via the property
 - * {@link setStatements Statements}. The context of the statemenets executed
 - * is the TStatements object itself.
 - *
 - * Note, since TStatements allows execution of arbitrary PHP statements,
 - * make sure {@link setStatements Statements} does not come directly from user input.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TStatements extends TControl
 -{
 -	/**
 -	 * @var string PHP statements
 -	 */
 -	private $_s='';
 -
 -	/**
 -	 * @return string the statements to be executed
 -	 */
 -	public function getStatements()
 -	{
 -		return $this->_s;
 -	}
 -
 -	/**
 -	 * @param string the PHP statements to be executed
 -	 */
 -	public function setStatements($value)
 -	{
 -		$this->_s=$value;
 -	}
 -
 -	/**
 -	 * Renders the evaluation result of the statements.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		if($this->_s!=='')
 -			$writer->write($this->evaluateStatements($this->_s));
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TStatements class + * + * TStatements executes one or several PHP statements and renders the display + * generated during the execution. The execution happens during the rendering stage. + * The PHP statements being executed can be set via the property + * {@link setStatements Statements}. The context of the statemenets executed + * is the TStatements object itself. + * + * Note, since TStatements allows execution of arbitrary PHP statements, + * make sure {@link setStatements Statements} does not come directly from user input. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TStatements extends TControl +{ +	/** +	 * @var string PHP statements +	 */ +	private $_s=''; + +	/** +	 * @return string the statements to be executed +	 */ +	public function getStatements() +	{ +		return $this->_s; +	} + +	/** +	 * @param string the PHP statements to be executed +	 */ +	public function setStatements($value) +	{ +		$this->_s=$value; +	} + +	/** +	 * Renders the evaluation result of the statements. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function render($writer) +	{ +		if($this->_s!=='') +			$writer->write($this->evaluateStatements($this->_s)); +	} +} + diff --git a/framework/Web/UI/WebControls/TStyle.php b/framework/Web/UI/WebControls/TStyle.php index 58be223a..93f7d45d 100644 --- a/framework/Web/UI/WebControls/TStyle.php +++ b/framework/Web/UI/WebControls/TStyle.php @@ -1,893 +1,893 @@ -<?php
 -/**
 - * TStyle class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TFont definition
 - */
 -Prado::using('System.Web.UI.WebControls.TFont');
 -
 -/**
 - * TStyle class
 - *
 - * TStyle encapsulates the CSS style applied to a control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TStyle extends TComponent
 -{
 -	/**
 -	 * @var array storage of CSS fields
 -	 */
 -	private $_fields=array();
 -	/**
 -	 * @var TFont font object
 -	 */
 -	private $_font=null;
 -	/**
 -	 * @var string CSS class name
 -	 */
 -	private $_class=null;
 -	/**
 -	 * @var string CSS style string (those not represented by specific fields of TStyle)
 -	 */
 -	private $_customStyle=null;
 -	/**
 -	 * @var string display style
 -	 */
 -	private $_displayStyle='Fixed';
 -
 -	/**
 -	 * Constructor.
 -	 * @param TStyle style to copy from
 -	 */
 -	public function __construct($style=null)
 -	{
 -		if($style!==null)
 -			$this->copyFrom($style);
 -	}
 -
 -	/**
 -	 * Need to clone the font object.
 -	 */
 -	public function __clone()
 -	{
 -		if($this->_font!==null)
 -			$this->_font = clone($this->_font);
 -	}
 -
 -	/**
 -	 * @return string the background color of the control
 -	 */
 -	public function getBackColor()
 -	{
 -		return isset($this->_fields['background-color'])?$this->_fields['background-color']:'';
 -	}
 -
 -	/**
 -	 * @param string the background color of the control
 -	 */
 -	public function setBackColor($value)
 -	{
 -		if(trim($value)==='')
 -			unset($this->_fields['background-color']);
 -		else
 -			$this->_fields['background-color']=$value;
 -	}
 -
 -	/**
 -	 * @return string the border color of the control
 -	 */
 -	public function getBorderColor()
 -	{
 -		return isset($this->_fields['border-color'])?$this->_fields['border-color']:'';
 -	}
 -
 -	/**
 -	 * @param string the border color of the control
 -	 */
 -	public function setBorderColor($value)
 -	{
 -		if(trim($value)==='')
 -			unset($this->_fields['border-color']);
 -		else
 -			$this->_fields['border-color']=$value;
 -	}
 -
 -	/**
 -	 * @return string the border style of the control
 -	 */
 -	public function getBorderStyle()
 -	{
 -		return isset($this->_fields['border-style'])?$this->_fields['border-style']:'';
 -	}
 -
 -	/**
 -	 * Sets the border style of the control.
 -	 * @param string the border style of the control
 -	 */
 -	public function setBorderStyle($value)
 -	{
 -		if(trim($value)==='')
 -			unset($this->_fields['border-style']);
 -		else
 -			$this->_fields['border-style']=$value;
 -	}
 -
 -	/**
 -	 * @return string the border width of the control
 -	 */
 -	public function getBorderWidth()
 -	{
 -		return isset($this->_fields['border-width'])?$this->_fields['border-width']:'';
 -	}
 -
 -	/**
 -	 * @param string the border width of the control
 -	 */
 -	public function setBorderWidth($value)
 -	{
 -		if(trim($value)==='')
 -			unset($this->_fields['border-width']);
 -		else
 -			$this->_fields['border-width']=$value;
 -	}
 -
 -	/**
 -	 * @return string the CSS class of the control
 -	 */
 -	public function getCssClass()
 -	{
 -		return $this->_class===null?'':$this->_class;
 -	}
 -
 -	/**
 -	 * @return boolean true if CSS is set or empty.
 -	 */
 -	public function hasCssClass()
 -	{
 -		return ($this->_class!==null);
 -	}
 -
 -	/**
 -	 * @param string the name of the CSS class of the control
 -	 */
 -	public function setCssClass($value)
 -	{
 -		$this->_class=$value;
 -	}
 -
 -	/**
 -	 * @return TFont the font of the control
 -	 */
 -	public function getFont()
 -	{
 -		if($this->_font===null)
 -			$this->_font=new TFont;
 -		return $this->_font;
 -	}
 -
 -	/**
 -	 * @return boolean true if font is set.
 -	 */
 -	public function hasFont()
 -	{
 -		return $this->_font !== null;
 -	}
 -
 -	/**
 -	 * @param TDisplayStyle control display style, default is TDisplayStyle::Fixed
 -	 */
 -	public function setDisplayStyle($value)
 -	{
 -		$this->_displayStyle = TPropertyValue::ensureEnum($value, 'TDisplayStyle');
 -		switch($this->_displayStyle)
 -		{
 -			case TDisplayStyle::None:
 -				$this->_fields['display'] = 'none';
 -				break;
 -			case TDisplayStyle::Dynamic:
 -				$this->_fields['display'] = ''; //remove the display property
 -				break;
 -			case TDisplayStyle::Fixed:
 -				$this->_fields['visibility'] = 'visible';
 -				break;
 -			case TDisplayStyle::Hidden:
 -				$this->_fields['visibility'] = 'hidden';
 -				break;
 -		}
 -	}
 -
 -	/**
 -	 * @return TDisplayStyle display style
 -	 */
 -	public function getDisplayStyle()
 -	{
 -		return $this->_displayStyle;
 -	}
 -
 -	/**
 -	 * @return string the foreground color of the control
 -	 */
 -	public function getForeColor()
 -	{
 -		return isset($this->_fields['color'])?$this->_fields['color']:'';
 -	}
 -
 -	/**
 -	 * @param string the foreground color of the control
 -	 */
 -	public function setForeColor($value)
 -	{
 -		if(trim($value)==='')
 -			unset($this->_fields['color']);
 -		else
 -			$this->_fields['color']=$value;
 -	}
 -
 -	/**
 -	 * @return string the height of the control
 -	 */
 -	public function getHeight()
 -	{
 -		return isset($this->_fields['height'])?$this->_fields['height']:'';
 -	}
 -
 -	/**
 -	 * @param string the height of the control
 -	 */
 -	public function setHeight($value)
 -	{
 -		if(trim($value)==='')
 -			unset($this->_fields['height']);
 -		else
 -			$this->_fields['height']=$value;
 -	}
 -
 -	/**
 -	 * @return string the custom style of the control
 -	 */
 -	public function getCustomStyle()
 -	{
 -		return $this->_customStyle===null?'':$this->_customStyle;
 -	}
 -
 -	/**
 -	 * Sets custom style fields from a string.
 -	 * Custom style fields will be overwritten by style fields explicitly defined.
 -	 * @param string the custom style of the control
 -	 */
 -	public function setCustomStyle($value)
 -	{
 -		$this->_customStyle=$value;
 -	}
 -
 -	/**
 -	 * @return string a single style field value set via {@link setStyleField}. Defaults to empty string.
 -	 */
 -	public function getStyleField($name)
 -	{
 -		return isset($this->_fields[$name])?$this->_fields[$name]:'';
 -	}
 -
 -	/**
 -	 * Sets a single style field value.
 -	 * Style fields set by this method will overwrite those set by {@link setCustomStyle}.
 -	 * @param string style field name
 -	 * @param string style field value
 -	 */
 -	public function setStyleField($name,$value)
 -	{
 -		$this->_fields[$name]=$value;
 -	}
 -
 -	/**
 -	 * Clears a single style field value;
 -	 * @param string style field name
 -	 */
 -	public function clearStyleField($name)
 -	{
 -		unset($this->_fields[$name]);
 -	}
 -
 -	/**
 -	 * @return boolean whether a style field has been defined by {@link setStyleField}
 -	 */
 -	public function hasStyleField($name)
 -	{
 -		return isset($this->_fields[$name]);
 -	}
 -
 -	/**
 -	 * @return string the width of the control
 -	 */
 -	public function getWidth()
 -	{
 -		return isset($this->_fields['width'])?$this->_fields['width']:'';
 -	}
 -
 -	/**
 -	 * @param string the width of the control
 -	 */
 -	public function setWidth($value)
 -	{
 -		$this->_fields['width']=$value;
 -	}
 -
 -	/**
 -	 * Resets the style to the original empty state.
 -	 */
 -	public function reset()
 -	{
 -		$this->_fields=array();
 -		$this->_font=null;
 -		$this->_class=null;
 -		$this->_customStyle=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)
 -	{
 -		if($style instanceof TStyle)
 -		{
 -			$this->_fields=array_merge($this->_fields,$style->_fields);
 -			if($style->_class!==null)
 -				$this->_class=$style->_class;
 -			if($style->_customStyle!==null)
 -				$this->_customStyle=$style->_customStyle;
 -			if($style->_font!==null)
 -				$this->getFont()->copyFrom($style->_font);
 -		}
 -	}
 -
 -	/**
 -	 * 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)
 -	{
 -		if($style instanceof TStyle)
 -		{
 -			$this->_fields=array_merge($style->_fields,$this->_fields);
 -			if($this->_class===null)
 -				$this->_class=$style->_class;
 -			if($this->_customStyle===null)
 -				$this->_customStyle=$style->_customStyle;
 -			if($style->_font!==null)
 -				$this->getFont()->mergeWith($style->_font);
 -		}
 -	}
 -
 -	/**
 -	 * Adds attributes related to CSS styles to renderer.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function addAttributesToRender($writer)
 -	{
 -		if($this->_customStyle!==null)
 -		{
 -			foreach(explode(';',$this->_customStyle) as $style)
 -			{
 -				$arr=explode(':',$style,2);
 -				if(isset($arr[1]) && trim($arr[0])!=='')
 -					$writer->addStyleAttribute(trim($arr[0]),trim($arr[1]));
 -			}
 -		}
 -		$writer->addStyleAttributes($this->_fields);
 -		if($this->_font!==null)
 -			$this->_font->addAttributesToRender($writer);
 -		if($this->_class!==null)
 -			$writer->addAttribute('class',$this->_class);
 -	}
 -
 -	/**
 -	 * @return array list of style fields.
 -	 */
 -	public function getStyleFields()
 -	{
 -		return $this->_fields;
 -	}
 -}
 -
 -/**
 - * TDisplayStyle defines the enumerable type for the possible styles
 - * that a web control can display.
 - *
 - * The following enumerable values are defined:
 - * - None: the control is not displayed and not included in the layout.
 - * - Dynamic: the control is displayed and included in the layout, the layout flow is dependent on the control (equivalent to display:'' in css).
 - * - Fixed: Similar to Dynamic with CSS "visibility" set "shown".
 - * - Hidden: the control is not displayed and is included in the layout.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.1
 - */
 -class TDisplayStyle extends TEnumerable
 -{
 -	const None='None';
 -	const Dynamic='Dynamic';
 -	const Fixed='Fixed';
 -	const Hidden='Hidden';
 -}
 -
 -/**
 - * TTableStyle class.
 - * TTableStyle represents the CSS style specific for HTML table.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableStyle extends TStyle
 -{
 -	/**
 -	 * @var TVerticalAlign the URL of the background image for the table
 -	 */
 -	private $_backImageUrl=null;
 -	/**
 -	 * @var THorizontalAlign horizontal alignment of the contents within the table
 -	 */
 -	private $_horizontalAlign=null;
 -	/**
 -	 * @var integer cellpadding of the table
 -	 */
 -	private $_cellPadding=null;
 -	/**
 -	 * @var integer cellspacing of the table
 -	 */
 -	private $_cellSpacing=null;
 -	/**
 -	 * @var TTableGridLines grid line setting of the table
 -	 */
 -	private $_gridLines=null;
 -	/**
 -	 * @var boolean whether the table border should be collapsed
 -	 */
 -	private $_borderCollapse=null;
 -
 -	/**
 -	 * Sets the style attributes to default values.
 -	 * This method overrides the parent implementation by
 -	 * resetting additional TTableStyle specific attributes.
 -	 */
 -	public function reset()
 -	{
 -		$this->_backImageUrl=null;
 -		$this->_horizontalAlign=null;
 -		$this->_cellPadding=null;
 -		$this->_cellSpacing=null;
 -		$this->_gridLines=null;
 -		$this->_borderCollapse=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 TTableStyle)
 -		{
 -			if($style->_backImageUrl!==null)
 -				$this->_backImageUrl=$style->_backImageUrl;
 -			if($style->_horizontalAlign!==null)
 -				$this->_horizontalAlign=$style->_horizontalAlign;
 -			if($style->_cellPadding!==null)
 -				$this->_cellPadding=$style->_cellPadding;
 -			if($style->_cellSpacing!==null)
 -				$this->_cellSpacing=$style->_cellSpacing;
 -			if($style->_gridLines!==null)
 -				$this->_gridLines=$style->_gridLines;
 -			if($style->_borderCollapse!==null)
 -				$this->_borderCollapse=$style->_borderCollapse;
 -		}
 -	}
 -
 -	/**
 -	 * 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 TTableStyle)
 -		{
 -			if($this->_backImageUrl===null && $style->_backImageUrl!==null)
 -				$this->_backImageUrl=$style->_backImageUrl;
 -			if($this->_horizontalAlign===null && $style->_horizontalAlign!==null)
 -				$this->_horizontalAlign=$style->_horizontalAlign;
 -			if($this->_cellPadding===null && $style->_cellPadding!==null)
 -				$this->_cellPadding=$style->_cellPadding;
 -			if($this->_cellSpacing===null && $style->_cellSpacing!==null)
 -				$this->_cellSpacing=$style->_cellSpacing;
 -			if($this->_gridLines===null && $style->_gridLines!==null)
 -				$this->_gridLines=$style->_gridLines;
 -			if($this->_borderCollapse===null && $style->_borderCollapse!==null)
 -				$this->_borderCollapse=$style->_borderCollapse;
 -		}
 -	}
 -
 -
 -	/**
 -	 * 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()))!=='')
 -			$writer->addStyleAttribute('background-image','url('.$url.')');
 -
 -		if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet)
 -			$writer->addStyleAttribute('text-align',strtolower($horizontalAlign));
 -
 -		if(($cellPadding=$this->getCellPadding())>=0)
 -			$writer->addAttribute('cellpadding',"$cellPadding");
 -
 -		if(($cellSpacing=$this->getCellSpacing())>=0)
 -			$writer->addAttribute('cellspacing',"$cellSpacing");
 -
 -		if($this->getBorderCollapse())
 -			$writer->addStyleAttribute('border-collapse','collapse');
 -
 -		switch($this->getGridLines())
 -		{
 -			case TTableGridLines::Horizontal : $writer->addAttribute('rules','rows'); break;
 -			case TTableGridLines::Vertical : $writer->addAttribute('rules','cols'); break;
 -			case TTableGridLines::Both : $writer->addAttribute('rules','all'); break;
 -		}
 -
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * @return string the URL of the background image for the table
 -	 */
 -	public function getBackImageUrl()
 -	{
 -		return $this->_backImageUrl===null?'':$this->_backImageUrl;
 -	}
 -
 -	/**
 -	 * Sets the URL of the background image for the table
 -	 * @param string the URL
 -	 */
 -	public function setBackImageUrl($value)
 -	{
 -		$this->_backImageUrl=$value;
 -	}
 -
 -	/**
 -	 * @return THorizontalAlign the horizontal alignment of the contents within the table, defaults to THorizontalAlign::NotSet.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign;
 -	}
 -
 -	/**
 -	 * Sets the horizontal alignment of the contents within the table.
 -	 * @param THorizontalAlign the horizontal alignment
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign');
 -	}
 -
 -	/**
 -	 * @return integer cellpadding of the table. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellPadding()
 -	{
 -		return $this->_cellPadding===null?-1:$this->_cellPadding;
 -	}
 -
 -	/**
 -	 * @param integer cellpadding of the table. A value equal to -1 clears up the setting.
 -	 * @throws TInvalidDataValueException if the value is less than -1.
 -	 */
 -	public function setCellPadding($value)
 -	{
 -		if(($this->_cellPadding=TPropertyValue::ensureInteger($value))<-1)
 -			throw new TInvalidDataValueException('tablestyle_cellpadding_invalid');
 -	}
 -
 -	/**
 -	 * @return integer cellspacing of the table. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellSpacing()
 -	{
 -		return $this->_cellSpacing===null?-1:$this->_cellSpacing;
 -	}
 -
 -	/**
 -	 * @param integer cellspacing of the table. A value equal to -1 clears up the setting.
 -	 * @throws TInvalidDataValueException if the value is less than -1.
 -	 */
 -	public function setCellSpacing($value)
 -	{
 -		if(($this->_cellSpacing=TPropertyValue::ensureInteger($value))<-1)
 -			throw new TInvalidDataValueException('tablestyle_cellspacing_invalid');
 -	}
 -
 -	/**
 -	 * @return TTableGridLines the grid line setting of the table. Defaults to TTableGridLines::None.
 -	 */
 -	public function getGridLines()
 -	{
 -		return $this->_gridLines===null?TTableGridLines::None:$this->_gridLines;
 -	}
 -
 -	/**
 -	 * Sets the grid line style of the table.
 -	 * @param TTableGridLines the grid line setting of the table
 -	 */
 -	public function setGridLines($value)
 -	{
 -		$this->_gridLines=TPropertyValue::ensureEnum($value,'TTableGridLines');
 -	}
 -
 -
 -	/**
 -	 * @return boolean whether the table borders should be collapsed. Defaults to false.
 -	 */
 -	public function getBorderCollapse()
 -	{
 -		return $this->_borderCollapse===null?false:$this->_borderCollapse;
 -	}
 -
 -	/**
 -	 * @param boolean whether the table borders should be collapsed.
 -	 */
 -	public function setBorderCollapse($value)
 -	{
 -		$this->_borderCollapse=TPropertyValue::ensureBoolean($value);
 -	}
 -}
 -
 -/**
 - * TTableItemStyle class.
 - * TTableItemStyle represents the CSS style specific for HTML table item.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableItemStyle extends TStyle
 -{
 -	/**
 -	 * @var THorizontalAlign horizontal alignment of the contents within the table item
 -	 */
 -	private $_horizontalAlign=null;
 -	/**
 -	 * @var TVerticalAlign vertical alignment of the contents within the table item
 -	 */
 -	private $_verticalAlign=null;
 -	/**
 -	 * @var boolean whether the content wraps within the table item
 -	 */
 -	private $_wrap=null;
 -
 -	/**
 -	 * Sets the style attributes to default values.
 -	 * This method overrides the parent implementation by
 -	 * resetting additional TTableItemStyle specific attributes.
 -	 */
 -	public function reset()
 -	{
 -		parent::reset();
 -		$this->_verticalAlign=null;
 -		$this->_horizontalAlign=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 TTableItemStyle)
 -		{
 -			if($this->_verticalAlign===null && $style->_verticalAlign!==null)
 -				$this->_verticalAlign=$style->_verticalAlign;
 -			if($this->_horizontalAlign===null && $style->_horizontalAlign!==null)
 -				$this->_horizontalAlign=$style->_horizontalAlign;
 -			if($this->_wrap===null && $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 TTableItemStyle)
 -		{
 -			if($style->_verticalAlign!==null)
 -				$this->_verticalAlign=$style->_verticalAlign;
 -			if($style->_horizontalAlign!==null)
 -				$this->_horizontalAlign=$style->_horizontalAlign;
 -			if($style->_wrap!==null)
 -				$this->_wrap=$style->_wrap;
 -		}
 -	}
 -
 -	/**
 -	 * 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(!$this->getWrap())
 -			$writer->addStyleAttribute('white-space','nowrap');
 -
 -		if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet)
 -			$writer->addAttribute('align',strtolower($horizontalAlign));
 -
 -		if(($verticalAlign=$this->getVerticalAlign())!==TVerticalAlign::NotSet)
 -			$writer->addAttribute('valign',strtolower($verticalAlign));
 -
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * @return THorizontalAlign the horizontal alignment of the contents within the table item, defaults to THorizontalAlign::NotSet.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign;
 -	}
 -
 -	/**
 -	 * Sets the horizontal alignment of the contents within the table item.
 -	 * @param THorizontalAlign the horizontal alignment
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign');
 -	}
 -
 -	/**
 -	 * @return TVerticalAlign the vertical alignment of the contents within the table item, defaults to TVerticalAlign::NotSet.
 -	 */
 -	public function getVerticalAlign()
 -	{
 -		return $this->_verticalAlign===null?TVerticalAlign::NotSet:$this->_verticalAlign;
 -	}
 -
 -	/**
 -	 * Sets the vertical alignment of the contents within the table item.
 -	 * @param TVerticalAlign the horizontal alignment
 -	 */
 -	public function setVerticalAlign($value)
 -	{
 -		$this->_verticalAlign=TPropertyValue::ensureEnum($value,'TVerticalAlign');
 -	}
 -
 -	/**
 -	 * @return boolean whether the content wraps within the table item. Defaults to true.
 -	 */
 -	public function getWrap()
 -	{
 -		return $this->_wrap===null?true:$this->_wrap;
 -	}
 -
 -	/**
 -	 * Sets the value indicating whether the content wraps within the table item.
 -	 * @param boolean whether the content wraps within the panel.
 -	 */
 -	public function setWrap($value)
 -	{
 -		$this->_wrap=TPropertyValue::ensureBoolean($value);
 -	}
 -}
 -
 -/**
 - * THorizontalAlign class.
 - * THorizontalAlign defines the enumerable type for the possible horizontal alignments in a CSS style.
 - *
 - * The following enumerable values are defined:
 - * - NotSet: the alignment is not specified.
 - * - Left: left aligned
 - * - Right: right aligned
 - * - Center: center aligned
 - * - Justify: the begin and end are justified
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class THorizontalAlign extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const Left='Left';
 -	const Right='Right';
 -	const Center='Center';
 -	const Justify='Justify';
 -}
 -
 -/**
 - * TVerticalAlign class.
 - * TVerticalAlign defines the enumerable type for the possible vertical alignments in a CSS style.
 - *
 - * The following enumerable values are defined:
 - * - NotSet: the alignment is not specified.
 - * - Top: top aligned
 - * - Bottom: bottom aligned
 - * - Middle: middle aligned
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TVerticalAlign extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const Top='Top';
 -	const Bottom='Bottom';
 -	const Middle='Middle';
 -}
 -
 -
 -/**
 - * TTableGridLines class.
 - * TTableGridLines defines the enumerable type for the possible grid line types of an HTML table.
 - *
 - * The following enumerable values are defined:
 - * - None: no grid lines
 - * - Horizontal: horizontal grid lines only
 - * - Vertical: vertical grid lines only
 - * - Both: both horizontal and vertical grid lines are shown
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTableGridLines extends TEnumerable
 -{
 -	const None='None';
 -	const Horizontal='Horizontal';
 -	const Vertical='Vertical';
 -	const Both='Both';
 -}
 -
 +<?php +/** + * TStyle class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TFont definition + */ +Prado::using('System.Web.UI.WebControls.TFont'); + +/** + * TStyle class + * + * TStyle encapsulates the CSS style applied to a control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TStyle extends TComponent +{ +	/** +	 * @var array storage of CSS fields +	 */ +	private $_fields=array(); +	/** +	 * @var TFont font object +	 */ +	private $_font=null; +	/** +	 * @var string CSS class name +	 */ +	private $_class=null; +	/** +	 * @var string CSS style string (those not represented by specific fields of TStyle) +	 */ +	private $_customStyle=null; +	/** +	 * @var string display style +	 */ +	private $_displayStyle='Fixed'; + +	/** +	 * Constructor. +	 * @param TStyle style to copy from +	 */ +	public function __construct($style=null) +	{ +		if($style!==null) +			$this->copyFrom($style); +	} + +	/** +	 * Need to clone the font object. +	 */ +	public function __clone() +	{ +		if($this->_font!==null) +			$this->_font = clone($this->_font); +	} + +	/** +	 * @return string the background color of the control +	 */ +	public function getBackColor() +	{ +		return isset($this->_fields['background-color'])?$this->_fields['background-color']:''; +	} + +	/** +	 * @param string the background color of the control +	 */ +	public function setBackColor($value) +	{ +		if(trim($value)==='') +			unset($this->_fields['background-color']); +		else +			$this->_fields['background-color']=$value; +	} + +	/** +	 * @return string the border color of the control +	 */ +	public function getBorderColor() +	{ +		return isset($this->_fields['border-color'])?$this->_fields['border-color']:''; +	} + +	/** +	 * @param string the border color of the control +	 */ +	public function setBorderColor($value) +	{ +		if(trim($value)==='') +			unset($this->_fields['border-color']); +		else +			$this->_fields['border-color']=$value; +	} + +	/** +	 * @return string the border style of the control +	 */ +	public function getBorderStyle() +	{ +		return isset($this->_fields['border-style'])?$this->_fields['border-style']:''; +	} + +	/** +	 * Sets the border style of the control. +	 * @param string the border style of the control +	 */ +	public function setBorderStyle($value) +	{ +		if(trim($value)==='') +			unset($this->_fields['border-style']); +		else +			$this->_fields['border-style']=$value; +	} + +	/** +	 * @return string the border width of the control +	 */ +	public function getBorderWidth() +	{ +		return isset($this->_fields['border-width'])?$this->_fields['border-width']:''; +	} + +	/** +	 * @param string the border width of the control +	 */ +	public function setBorderWidth($value) +	{ +		if(trim($value)==='') +			unset($this->_fields['border-width']); +		else +			$this->_fields['border-width']=$value; +	} + +	/** +	 * @return string the CSS class of the control +	 */ +	public function getCssClass() +	{ +		return $this->_class===null?'':$this->_class; +	} + +	/** +	 * @return boolean true if CSS is set or empty. +	 */ +	public function hasCssClass() +	{ +		return ($this->_class!==null); +	} + +	/** +	 * @param string the name of the CSS class of the control +	 */ +	public function setCssClass($value) +	{ +		$this->_class=$value; +	} + +	/** +	 * @return TFont the font of the control +	 */ +	public function getFont() +	{ +		if($this->_font===null) +			$this->_font=new TFont; +		return $this->_font; +	} + +	/** +	 * @return boolean true if font is set. +	 */ +	public function hasFont() +	{ +		return $this->_font !== null; +	} + +	/** +	 * @param TDisplayStyle control display style, default is TDisplayStyle::Fixed +	 */ +	public function setDisplayStyle($value) +	{ +		$this->_displayStyle = TPropertyValue::ensureEnum($value, 'TDisplayStyle'); +		switch($this->_displayStyle) +		{ +			case TDisplayStyle::None: +				$this->_fields['display'] = 'none'; +				break; +			case TDisplayStyle::Dynamic: +				$this->_fields['display'] = ''; //remove the display property +				break; +			case TDisplayStyle::Fixed: +				$this->_fields['visibility'] = 'visible'; +				break; +			case TDisplayStyle::Hidden: +				$this->_fields['visibility'] = 'hidden'; +				break; +		} +	} + +	/** +	 * @return TDisplayStyle display style +	 */ +	public function getDisplayStyle() +	{ +		return $this->_displayStyle; +	} + +	/** +	 * @return string the foreground color of the control +	 */ +	public function getForeColor() +	{ +		return isset($this->_fields['color'])?$this->_fields['color']:''; +	} + +	/** +	 * @param string the foreground color of the control +	 */ +	public function setForeColor($value) +	{ +		if(trim($value)==='') +			unset($this->_fields['color']); +		else +			$this->_fields['color']=$value; +	} + +	/** +	 * @return string the height of the control +	 */ +	public function getHeight() +	{ +		return isset($this->_fields['height'])?$this->_fields['height']:''; +	} + +	/** +	 * @param string the height of the control +	 */ +	public function setHeight($value) +	{ +		if(trim($value)==='') +			unset($this->_fields['height']); +		else +			$this->_fields['height']=$value; +	} + +	/** +	 * @return string the custom style of the control +	 */ +	public function getCustomStyle() +	{ +		return $this->_customStyle===null?'':$this->_customStyle; +	} + +	/** +	 * Sets custom style fields from a string. +	 * Custom style fields will be overwritten by style fields explicitly defined. +	 * @param string the custom style of the control +	 */ +	public function setCustomStyle($value) +	{ +		$this->_customStyle=$value; +	} + +	/** +	 * @return string a single style field value set via {@link setStyleField}. Defaults to empty string. +	 */ +	public function getStyleField($name) +	{ +		return isset($this->_fields[$name])?$this->_fields[$name]:''; +	} + +	/** +	 * Sets a single style field value. +	 * Style fields set by this method will overwrite those set by {@link setCustomStyle}. +	 * @param string style field name +	 * @param string style field value +	 */ +	public function setStyleField($name,$value) +	{ +		$this->_fields[$name]=$value; +	} + +	/** +	 * Clears a single style field value; +	 * @param string style field name +	 */ +	public function clearStyleField($name) +	{ +		unset($this->_fields[$name]); +	} + +	/** +	 * @return boolean whether a style field has been defined by {@link setStyleField} +	 */ +	public function hasStyleField($name) +	{ +		return isset($this->_fields[$name]); +	} + +	/** +	 * @return string the width of the control +	 */ +	public function getWidth() +	{ +		return isset($this->_fields['width'])?$this->_fields['width']:''; +	} + +	/** +	 * @param string the width of the control +	 */ +	public function setWidth($value) +	{ +		$this->_fields['width']=$value; +	} + +	/** +	 * Resets the style to the original empty state. +	 */ +	public function reset() +	{ +		$this->_fields=array(); +		$this->_font=null; +		$this->_class=null; +		$this->_customStyle=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) +	{ +		if($style instanceof TStyle) +		{ +			$this->_fields=array_merge($this->_fields,$style->_fields); +			if($style->_class!==null) +				$this->_class=$style->_class; +			if($style->_customStyle!==null) +				$this->_customStyle=$style->_customStyle; +			if($style->_font!==null) +				$this->getFont()->copyFrom($style->_font); +		} +	} + +	/** +	 * 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) +	{ +		if($style instanceof TStyle) +		{ +			$this->_fields=array_merge($style->_fields,$this->_fields); +			if($this->_class===null) +				$this->_class=$style->_class; +			if($this->_customStyle===null) +				$this->_customStyle=$style->_customStyle; +			if($style->_font!==null) +				$this->getFont()->mergeWith($style->_font); +		} +	} + +	/** +	 * Adds attributes related to CSS styles to renderer. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function addAttributesToRender($writer) +	{ +		if($this->_customStyle!==null) +		{ +			foreach(explode(';',$this->_customStyle) as $style) +			{ +				$arr=explode(':',$style,2); +				if(isset($arr[1]) && trim($arr[0])!=='') +					$writer->addStyleAttribute(trim($arr[0]),trim($arr[1])); +			} +		} +		$writer->addStyleAttributes($this->_fields); +		if($this->_font!==null) +			$this->_font->addAttributesToRender($writer); +		if($this->_class!==null) +			$writer->addAttribute('class',$this->_class); +	} + +	/** +	 * @return array list of style fields. +	 */ +	public function getStyleFields() +	{ +		return $this->_fields; +	} +} + +/** + * TDisplayStyle defines the enumerable type for the possible styles + * that a web control can display. + * + * The following enumerable values are defined: + * - None: the control is not displayed and not included in the layout. + * - Dynamic: the control is displayed and included in the layout, the layout flow is dependent on the control (equivalent to display:'' in css). + * - Fixed: Similar to Dynamic with CSS "visibility" set "shown". + * - Hidden: the control is not displayed and is included in the layout. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.1 + */ +class TDisplayStyle extends TEnumerable +{ +	const None='None'; +	const Dynamic='Dynamic'; +	const Fixed='Fixed'; +	const Hidden='Hidden'; +} + +/** + * TTableStyle class. + * TTableStyle represents the CSS style specific for HTML table. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableStyle extends TStyle +{ +	/** +	 * @var TVerticalAlign the URL of the background image for the table +	 */ +	private $_backImageUrl=null; +	/** +	 * @var THorizontalAlign horizontal alignment of the contents within the table +	 */ +	private $_horizontalAlign=null; +	/** +	 * @var integer cellpadding of the table +	 */ +	private $_cellPadding=null; +	/** +	 * @var integer cellspacing of the table +	 */ +	private $_cellSpacing=null; +	/** +	 * @var TTableGridLines grid line setting of the table +	 */ +	private $_gridLines=null; +	/** +	 * @var boolean whether the table border should be collapsed +	 */ +	private $_borderCollapse=null; + +	/** +	 * Sets the style attributes to default values. +	 * This method overrides the parent implementation by +	 * resetting additional TTableStyle specific attributes. +	 */ +	public function reset() +	{ +		$this->_backImageUrl=null; +		$this->_horizontalAlign=null; +		$this->_cellPadding=null; +		$this->_cellSpacing=null; +		$this->_gridLines=null; +		$this->_borderCollapse=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 TTableStyle) +		{ +			if($style->_backImageUrl!==null) +				$this->_backImageUrl=$style->_backImageUrl; +			if($style->_horizontalAlign!==null) +				$this->_horizontalAlign=$style->_horizontalAlign; +			if($style->_cellPadding!==null) +				$this->_cellPadding=$style->_cellPadding; +			if($style->_cellSpacing!==null) +				$this->_cellSpacing=$style->_cellSpacing; +			if($style->_gridLines!==null) +				$this->_gridLines=$style->_gridLines; +			if($style->_borderCollapse!==null) +				$this->_borderCollapse=$style->_borderCollapse; +		} +	} + +	/** +	 * 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 TTableStyle) +		{ +			if($this->_backImageUrl===null && $style->_backImageUrl!==null) +				$this->_backImageUrl=$style->_backImageUrl; +			if($this->_horizontalAlign===null && $style->_horizontalAlign!==null) +				$this->_horizontalAlign=$style->_horizontalAlign; +			if($this->_cellPadding===null && $style->_cellPadding!==null) +				$this->_cellPadding=$style->_cellPadding; +			if($this->_cellSpacing===null && $style->_cellSpacing!==null) +				$this->_cellSpacing=$style->_cellSpacing; +			if($this->_gridLines===null && $style->_gridLines!==null) +				$this->_gridLines=$style->_gridLines; +			if($this->_borderCollapse===null && $style->_borderCollapse!==null) +				$this->_borderCollapse=$style->_borderCollapse; +		} +	} + + +	/** +	 * 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()))!=='') +			$writer->addStyleAttribute('background-image','url('.$url.')'); + +		if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet) +			$writer->addStyleAttribute('text-align',strtolower($horizontalAlign)); + +		if(($cellPadding=$this->getCellPadding())>=0) +			$writer->addAttribute('cellpadding',"$cellPadding"); + +		if(($cellSpacing=$this->getCellSpacing())>=0) +			$writer->addAttribute('cellspacing',"$cellSpacing"); + +		if($this->getBorderCollapse()) +			$writer->addStyleAttribute('border-collapse','collapse'); + +		switch($this->getGridLines()) +		{ +			case TTableGridLines::Horizontal : $writer->addAttribute('rules','rows'); break; +			case TTableGridLines::Vertical : $writer->addAttribute('rules','cols'); break; +			case TTableGridLines::Both : $writer->addAttribute('rules','all'); break; +		} + +		parent::addAttributesToRender($writer); +	} + +	/** +	 * @return string the URL of the background image for the table +	 */ +	public function getBackImageUrl() +	{ +		return $this->_backImageUrl===null?'':$this->_backImageUrl; +	} + +	/** +	 * Sets the URL of the background image for the table +	 * @param string the URL +	 */ +	public function setBackImageUrl($value) +	{ +		$this->_backImageUrl=$value; +	} + +	/** +	 * @return THorizontalAlign the horizontal alignment of the contents within the table, defaults to THorizontalAlign::NotSet. +	 */ +	public function getHorizontalAlign() +	{ +		return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign; +	} + +	/** +	 * Sets the horizontal alignment of the contents within the table. +	 * @param THorizontalAlign the horizontal alignment +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign'); +	} + +	/** +	 * @return integer cellpadding of the table. Defaults to -1, meaning not set. +	 */ +	public function getCellPadding() +	{ +		return $this->_cellPadding===null?-1:$this->_cellPadding; +	} + +	/** +	 * @param integer cellpadding of the table. A value equal to -1 clears up the setting. +	 * @throws TInvalidDataValueException if the value is less than -1. +	 */ +	public function setCellPadding($value) +	{ +		if(($this->_cellPadding=TPropertyValue::ensureInteger($value))<-1) +			throw new TInvalidDataValueException('tablestyle_cellpadding_invalid'); +	} + +	/** +	 * @return integer cellspacing of the table. Defaults to -1, meaning not set. +	 */ +	public function getCellSpacing() +	{ +		return $this->_cellSpacing===null?-1:$this->_cellSpacing; +	} + +	/** +	 * @param integer cellspacing of the table. A value equal to -1 clears up the setting. +	 * @throws TInvalidDataValueException if the value is less than -1. +	 */ +	public function setCellSpacing($value) +	{ +		if(($this->_cellSpacing=TPropertyValue::ensureInteger($value))<-1) +			throw new TInvalidDataValueException('tablestyle_cellspacing_invalid'); +	} + +	/** +	 * @return TTableGridLines the grid line setting of the table. Defaults to TTableGridLines::None. +	 */ +	public function getGridLines() +	{ +		return $this->_gridLines===null?TTableGridLines::None:$this->_gridLines; +	} + +	/** +	 * Sets the grid line style of the table. +	 * @param TTableGridLines the grid line setting of the table +	 */ +	public function setGridLines($value) +	{ +		$this->_gridLines=TPropertyValue::ensureEnum($value,'TTableGridLines'); +	} + + +	/** +	 * @return boolean whether the table borders should be collapsed. Defaults to false. +	 */ +	public function getBorderCollapse() +	{ +		return $this->_borderCollapse===null?false:$this->_borderCollapse; +	} + +	/** +	 * @param boolean whether the table borders should be collapsed. +	 */ +	public function setBorderCollapse($value) +	{ +		$this->_borderCollapse=TPropertyValue::ensureBoolean($value); +	} +} + +/** + * TTableItemStyle class. + * TTableItemStyle represents the CSS style specific for HTML table item. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableItemStyle extends TStyle +{ +	/** +	 * @var THorizontalAlign horizontal alignment of the contents within the table item +	 */ +	private $_horizontalAlign=null; +	/** +	 * @var TVerticalAlign vertical alignment of the contents within the table item +	 */ +	private $_verticalAlign=null; +	/** +	 * @var boolean whether the content wraps within the table item +	 */ +	private $_wrap=null; + +	/** +	 * Sets the style attributes to default values. +	 * This method overrides the parent implementation by +	 * resetting additional TTableItemStyle specific attributes. +	 */ +	public function reset() +	{ +		parent::reset(); +		$this->_verticalAlign=null; +		$this->_horizontalAlign=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 TTableItemStyle) +		{ +			if($this->_verticalAlign===null && $style->_verticalAlign!==null) +				$this->_verticalAlign=$style->_verticalAlign; +			if($this->_horizontalAlign===null && $style->_horizontalAlign!==null) +				$this->_horizontalAlign=$style->_horizontalAlign; +			if($this->_wrap===null && $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 TTableItemStyle) +		{ +			if($style->_verticalAlign!==null) +				$this->_verticalAlign=$style->_verticalAlign; +			if($style->_horizontalAlign!==null) +				$this->_horizontalAlign=$style->_horizontalAlign; +			if($style->_wrap!==null) +				$this->_wrap=$style->_wrap; +		} +	} + +	/** +	 * 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(!$this->getWrap()) +			$writer->addStyleAttribute('white-space','nowrap'); + +		if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet) +			$writer->addAttribute('align',strtolower($horizontalAlign)); + +		if(($verticalAlign=$this->getVerticalAlign())!==TVerticalAlign::NotSet) +			$writer->addAttribute('valign',strtolower($verticalAlign)); + +		parent::addAttributesToRender($writer); +	} + +	/** +	 * @return THorizontalAlign the horizontal alignment of the contents within the table item, defaults to THorizontalAlign::NotSet. +	 */ +	public function getHorizontalAlign() +	{ +		return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign; +	} + +	/** +	 * Sets the horizontal alignment of the contents within the table item. +	 * @param THorizontalAlign the horizontal alignment +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign'); +	} + +	/** +	 * @return TVerticalAlign the vertical alignment of the contents within the table item, defaults to TVerticalAlign::NotSet. +	 */ +	public function getVerticalAlign() +	{ +		return $this->_verticalAlign===null?TVerticalAlign::NotSet:$this->_verticalAlign; +	} + +	/** +	 * Sets the vertical alignment of the contents within the table item. +	 * @param TVerticalAlign the horizontal alignment +	 */ +	public function setVerticalAlign($value) +	{ +		$this->_verticalAlign=TPropertyValue::ensureEnum($value,'TVerticalAlign'); +	} + +	/** +	 * @return boolean whether the content wraps within the table item. Defaults to true. +	 */ +	public function getWrap() +	{ +		return $this->_wrap===null?true:$this->_wrap; +	} + +	/** +	 * Sets the value indicating whether the content wraps within the table item. +	 * @param boolean whether the content wraps within the panel. +	 */ +	public function setWrap($value) +	{ +		$this->_wrap=TPropertyValue::ensureBoolean($value); +	} +} + +/** + * THorizontalAlign class. + * THorizontalAlign defines the enumerable type for the possible horizontal alignments in a CSS style. + * + * The following enumerable values are defined: + * - NotSet: the alignment is not specified. + * - Left: left aligned + * - Right: right aligned + * - Center: center aligned + * - Justify: the begin and end are justified + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class THorizontalAlign extends TEnumerable +{ +	const NotSet='NotSet'; +	const Left='Left'; +	const Right='Right'; +	const Center='Center'; +	const Justify='Justify'; +} + +/** + * TVerticalAlign class. + * TVerticalAlign defines the enumerable type for the possible vertical alignments in a CSS style. + * + * The following enumerable values are defined: + * - NotSet: the alignment is not specified. + * - Top: top aligned + * - Bottom: bottom aligned + * - Middle: middle aligned + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TVerticalAlign extends TEnumerable +{ +	const NotSet='NotSet'; +	const Top='Top'; +	const Bottom='Bottom'; +	const Middle='Middle'; +} + + +/** + * TTableGridLines class. + * TTableGridLines defines the enumerable type for the possible grid line types of an HTML table. + * + * The following enumerable values are defined: + * - None: no grid lines + * - Horizontal: horizontal grid lines only + * - Vertical: vertical grid lines only + * - Both: both horizontal and vertical grid lines are shown + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTableGridLines extends TEnumerable +{ +	const None='None'; +	const Horizontal='Horizontal'; +	const Vertical='Vertical'; +	const Both='Both'; +} + diff --git a/framework/Web/UI/WebControls/TTable.php b/framework/Web/UI/WebControls/TTable.php index a333bf09..b7a774ae 100644 --- a/framework/Web/UI/WebControls/TTable.php +++ b/framework/Web/UI/WebControls/TTable.php @@ -1,410 +1,410 @@ -<?php
 -/**
 - * TTable and TTableRowCollection class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTable and TTableRowCollection class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TTableRow class
 - */
 -Prado::using('System.Web.UI.WebControls.TTableRow');
 -
 -/**
 - * TTable class
 - *
 - * TTable displays an HTML table on a Web page.
 - *
 - * A table may have {@link setCaption Caption}, whose alignment is specified
 - * via {@link setCaptionAlign CaptionAlign}. The table cellpadding and cellspacing
 - * are specified via {@link setCellPadding CellPadding} and {@link setCellSpacing CellSpacing}
 - * properties, respectively. The {@link setGridLines GridLines} specifies how
 - * the table should display its borders. The horizontal alignment of the table
 - * content can be specified via {@link setHorizontalAlign HorizontalAlign},
 - * and {@link setBackImageUrl BackImageUrl} can assign a background image to the table.
 - *
 - * A TTable maintains a list of {@link TTableRow} controls in its
 - * {@link getRows Rows} property. Each {@link TTableRow} represents
 - * an HTML table row.
 - *
 - * To populate the table {@link getRows Rows}, you may either use control template
 - * or dynamically create {@link TTableRow} in code.
 - * In template, do as follows to create the table rows and cells,
 - * <code>
 - *   <com:TTable>
 - *     <com:TTableRow>
 - *       <com:TTableCell Text="content" />
 - *       <com:TTableCell Text="content" />
 - *     </com:TTableRow>
 - *     <com:TTableRow>
 - *       <com:TTableCell Text="content" />
 - *       <com:TTableCell Text="content" />
 - *     </com:TTableRow>
 - *   </com:TTable>
 - * </code>
 - * The above can also be accomplished in code as follows,
 - * <code>
 - *   $table=new TTable;
 - *   $row=new TTableRow;
 - *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell);
 - *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell);
 - *   $table->Rows->add($row);
 - *   $row=new TTableRow;
 - *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell);
 - *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell);
 - *   $table->Rows->add($row);
 - * </code>
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTable extends TWebControl
 -{
 -	/**
 -	 * @return string tag name for the table
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'table';
 -	}
 -
 -	/**
 -	 * Adds object parsed from template to the control.
 -	 * This method adds only {@link TTableRow} objects into the {@link getRows Rows} collection.
 -	 * All other objects are ignored.
 -	 * @param mixed object parsed from template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TTableRow)
 -			$this->getRows()->add($object);
 -	}
 -
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableStyle} to be used by the table.
 -	 * @return TTableStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableStyle;
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		$border=0;
 -		if($this->getHasStyle())
 -		{
 -			if($this->getGridLines()!==TTableGridLines::None)
 -			{
 -				if(($border=$this->getBorderWidth())==='')
 -					$border=1;
 -				else
 -					$border=(int)$border;
 -			}
 -		}
 -		$writer->addAttribute('border',"$border");
 -	}
 -
 -	/**
 -	 * Creates a control collection object that is to be used to hold child controls
 -	 * @return TTableRowCollection control collection
 -	 * @see getControls
 -	 */
 -	protected function createControlCollection()
 -	{
 -		return new TTableRowCollection($this);
 -	}
 -
 -	/**
 -	 * @return TTableRowCollection list of {@link TTableRow} controls
 -	 */
 -	public function getRows()
 -	{
 -		return $this->getControls();
 -	}
 -
 -	/**
 -	 * @return string table caption
 -	 */
 -	public function getCaption()
 -	{
 -		return $this->getViewState('Caption','');
 -	}
 -
 -	/**
 -	 * @param string table caption
 -	 */
 -	public function setCaption($value)
 -	{
 -		$this->setViewState('Caption',$value,'');
 -	}
 -
 -	/**
 -	 * @return TTableCaptionAlign table caption alignment. Defaults to TTableCaptionAlign::NotSet.
 -	 */
 -	public function getCaptionAlign()
 -	{
 -		return $this->getViewState('CaptionAlign',TTableCaptionAlign::NotSet);
 -	}
 -
 -	/**
 -	 * @param TTableCaptionAlign table caption alignment.
 -	 */
 -	public function setCaptionAlign($value)
 -	{
 -		$this->setViewState('CaptionAlign',TPropertyValue::ensureEnum($value,'TTableCaptionAlign'),TTableCaptionAlign::NotSet);
 -	}
 -
 -	/**
 -	 * @return integer the cellspacing for the table. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellSpacing()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getCellSpacing();
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * @param integer the cellspacing for the table. Defaults to -1, meaning not set.
 -	 */
 -	public function setCellSpacing($value)
 -	{
 -		$this->getStyle()->setCellSpacing($value);
 -	}
 -
 -	/**
 -	 * @return integer the cellpadding for the table. Defaults to -1, meaning not set.
 -	 */
 -	public function getCellPadding()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getCellPadding();
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * @param integer the cellpadding for the table. Defaults to -1, meaning not set.
 -	 */
 -	public function setCellPadding($value)
 -	{
 -		$this->getStyle()->setCellPadding($value);
 -	}
 -
 -	/**
 -	 * @return THorizontalAlign the horizontal alignment of the table content. Defaults to THorizontalAlign::NotSet.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getHorizontalAlign();
 -		else
 -			return THorizontalAlign::NotSet;
 -	}
 -
 -	/**
 -	 * @param THorizontalAlign the horizontal alignment of the table content.
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->getStyle()->setHorizontalAlign($value);
 -	}
 -
 -	/**
 -	 * @return TTableGridLines the grid line setting of the table. Defaults to TTableGridLines::None.
 -	 */
 -	public function getGridLines()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getGridLines();
 -		else
 -			return TTableGridLines::None;
 -	}
 -
 -	/**
 -	 * @param TTableGridLines the grid line setting of the table
 -	 */
 -	public function setGridLines($value)
 -	{
 -		$this->getStyle()->setGridLines($value);
 -	}
 -
 -	/**
 -	 * @return string the URL of the background image for the table
 -	 */
 -	public function getBackImageUrl()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getBackImageUrl();
 -		else
 -			return '';
 -	}
 -
 -	/**
 -	 * Sets the URL of the background image for the table
 -	 * @param string the URL
 -	 */
 -	public function setBackImageUrl($value)
 -	{
 -		$this->getStyle()->setBackImageUrl($value);
 -	}
 -
 -	/**
 -	 * Renders the openning tag for the table control which will render table caption if present.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	public function renderBeginTag($writer)
 -	{
 -		parent::renderBeginTag($writer);
 -		if(($caption=$this->getCaption())!=='')
 -		{
 -			if(($align=$this->getCaptionAlign())!==TTableCaptionAlign::NotSet)
 -				$writer->addAttribute('align',strtolower($align));
 -			$writer->renderBeginTag('caption');
 -			$writer->write($caption);
 -			$writer->renderEndTag();
 -		}
 -	}
 -
 -	/**
 -	 * Renders body contents of the table.
 -	 * @param THtmlWriter the writer used for the rendering purpose.
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if($this->getHasControls())
 -		{
 -			$renderTableSection=false;
 -			foreach($this->getControls() as $row)
 -			{
 -				if($row->getTableSection()!==TTableRowSection::Body)
 -				{
 -					$renderTableSection=true;
 -					break;
 -				}
 -			}
 -			if($renderTableSection)
 -			{
 -				$currentSection=TTableRowSection::Header;
 -				$writer->writeLine();
 -				foreach($this->getControls() as $index=>$row)
 -				{
 -					if(($section=$row->getTableSection())===$currentSection)
 -					{
 -						if($index===0 && $currentSection===TTableRowSection::Header)
 -							$writer->renderBeginTag('thead');
 -					}
 -					else
 -					{
 -						if($currentSection===TTableRowSection::Header)
 -						{
 -							if($index>0)
 -								$writer->renderEndTag();
 -							if($section===TTableRowSection::Body)
 -								$writer->renderBeginTag('tbody');
 -							else
 -								$writer->renderBeginTag('tfoot');
 -							$currentSection=$section;
 -						}
 -						else if($currentSection===TTableRowSection::Body)
 -						{
 -							$writer->renderEndTag();
 -							if($section===TTableRowSection::Footer)
 -								$writer->renderBeginTag('tfoot');
 -							else
 -								throw new TConfigurationException('table_tablesection_outoforder');
 -							$currentSection=$section;
 -						}
 -						else // Footer
 -							throw new TConfigurationException('table_tablesection_outoforder');
 -					}
 -					$row->renderControl($writer);
 -					$writer->writeLine();
 -				}
 -				$writer->renderEndTag();
 -			}
 -			else
 -			{
 -				$writer->writeLine();
 -				foreach($this->getControls() as $row)
 -				{
 -					$row->renderControl($writer);
 -					$writer->writeLine();
 -				}
 -			}
 -		}
 -	}
 -}
 -
 -
 -/**
 - * TTableRowCollection class.
 - *
 - * TTableRowCollection is used to maintain a list of rows belong to a table.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableRowCollection extends TControlCollection
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by performing additional
 -	 * operations for each newly added table row.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a TTableRow object.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TTableRow)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('tablerowcollection_tablerow_required');
 -	}
 -}
 -
 -
 -/**
 - * TTableCaptionAlign class.
 - * TTableCaptionAlign defines the enumerable type for the possible alignments
 - * that a table caption can take.
 - *
 - * The following enumerable values are defined:
 - * - NotSet: alignment not specified
 - * - Top: top aligned
 - * - Bottom: bottom aligned
 - * - Left: left aligned
 - * - Right: right aligned
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTableCaptionAlign extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const Top='Top';
 -	const Bottom='Bottom';
 -	const Left='Left';
 -	const Right='Right';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TTableRow class + */ +Prado::using('System.Web.UI.WebControls.TTableRow'); + +/** + * TTable class + * + * TTable displays an HTML table on a Web page. + * + * A table may have {@link setCaption Caption}, whose alignment is specified + * via {@link setCaptionAlign CaptionAlign}. The table cellpadding and cellspacing + * are specified via {@link setCellPadding CellPadding} and {@link setCellSpacing CellSpacing} + * properties, respectively. The {@link setGridLines GridLines} specifies how + * the table should display its borders. The horizontal alignment of the table + * content can be specified via {@link setHorizontalAlign HorizontalAlign}, + * and {@link setBackImageUrl BackImageUrl} can assign a background image to the table. + * + * A TTable maintains a list of {@link TTableRow} controls in its + * {@link getRows Rows} property. Each {@link TTableRow} represents + * an HTML table row. + * + * To populate the table {@link getRows Rows}, you may either use control template + * or dynamically create {@link TTableRow} in code. + * In template, do as follows to create the table rows and cells, + * <code> + *   <com:TTable> + *     <com:TTableRow> + *       <com:TTableCell Text="content" /> + *       <com:TTableCell Text="content" /> + *     </com:TTableRow> + *     <com:TTableRow> + *       <com:TTableCell Text="content" /> + *       <com:TTableCell Text="content" /> + *     </com:TTableRow> + *   </com:TTable> + * </code> + * The above can also be accomplished in code as follows, + * <code> + *   $table=new TTable; + *   $row=new TTableRow; + *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell); + *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell); + *   $table->Rows->add($row); + *   $row=new TTableRow; + *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell); + *   $cell=new TTableCell; $cell->Text="content"; $row->Cells->add($cell); + *   $table->Rows->add($row); + * </code> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTable extends TWebControl +{ +	/** +	 * @return string tag name for the table +	 */ +	protected function getTagName() +	{ +		return 'table'; +	} + +	/** +	 * Adds object parsed from template to the control. +	 * This method adds only {@link TTableRow} objects into the {@link getRows Rows} collection. +	 * All other objects are ignored. +	 * @param mixed object parsed from template +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TTableRow) +			$this->getRows()->add($object); +	} + +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableStyle} to be used by the table. +	 * @return TTableStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableStyle; +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		$border=0; +		if($this->getHasStyle()) +		{ +			if($this->getGridLines()!==TTableGridLines::None) +			{ +				if(($border=$this->getBorderWidth())==='') +					$border=1; +				else +					$border=(int)$border; +			} +		} +		$writer->addAttribute('border',"$border"); +	} + +	/** +	 * Creates a control collection object that is to be used to hold child controls +	 * @return TTableRowCollection control collection +	 * @see getControls +	 */ +	protected function createControlCollection() +	{ +		return new TTableRowCollection($this); +	} + +	/** +	 * @return TTableRowCollection list of {@link TTableRow} controls +	 */ +	public function getRows() +	{ +		return $this->getControls(); +	} + +	/** +	 * @return string table caption +	 */ +	public function getCaption() +	{ +		return $this->getViewState('Caption',''); +	} + +	/** +	 * @param string table caption +	 */ +	public function setCaption($value) +	{ +		$this->setViewState('Caption',$value,''); +	} + +	/** +	 * @return TTableCaptionAlign table caption alignment. Defaults to TTableCaptionAlign::NotSet. +	 */ +	public function getCaptionAlign() +	{ +		return $this->getViewState('CaptionAlign',TTableCaptionAlign::NotSet); +	} + +	/** +	 * @param TTableCaptionAlign table caption alignment. +	 */ +	public function setCaptionAlign($value) +	{ +		$this->setViewState('CaptionAlign',TPropertyValue::ensureEnum($value,'TTableCaptionAlign'),TTableCaptionAlign::NotSet); +	} + +	/** +	 * @return integer the cellspacing for the table. Defaults to -1, meaning not set. +	 */ +	public function getCellSpacing() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getCellSpacing(); +		else +			return -1; +	} + +	/** +	 * @param integer the cellspacing for the table. Defaults to -1, meaning not set. +	 */ +	public function setCellSpacing($value) +	{ +		$this->getStyle()->setCellSpacing($value); +	} + +	/** +	 * @return integer the cellpadding for the table. Defaults to -1, meaning not set. +	 */ +	public function getCellPadding() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getCellPadding(); +		else +			return -1; +	} + +	/** +	 * @param integer the cellpadding for the table. Defaults to -1, meaning not set. +	 */ +	public function setCellPadding($value) +	{ +		$this->getStyle()->setCellPadding($value); +	} + +	/** +	 * @return THorizontalAlign the horizontal alignment of the table content. Defaults to THorizontalAlign::NotSet. +	 */ +	public function getHorizontalAlign() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getHorizontalAlign(); +		else +			return THorizontalAlign::NotSet; +	} + +	/** +	 * @param THorizontalAlign the horizontal alignment of the table content. +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->getStyle()->setHorizontalAlign($value); +	} + +	/** +	 * @return TTableGridLines the grid line setting of the table. Defaults to TTableGridLines::None. +	 */ +	public function getGridLines() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getGridLines(); +		else +			return TTableGridLines::None; +	} + +	/** +	 * @param TTableGridLines the grid line setting of the table +	 */ +	public function setGridLines($value) +	{ +		$this->getStyle()->setGridLines($value); +	} + +	/** +	 * @return string the URL of the background image for the table +	 */ +	public function getBackImageUrl() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getBackImageUrl(); +		else +			return ''; +	} + +	/** +	 * Sets the URL of the background image for the table +	 * @param string the URL +	 */ +	public function setBackImageUrl($value) +	{ +		$this->getStyle()->setBackImageUrl($value); +	} + +	/** +	 * Renders the openning tag for the table control which will render table caption if present. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	public function renderBeginTag($writer) +	{ +		parent::renderBeginTag($writer); +		if(($caption=$this->getCaption())!=='') +		{ +			if(($align=$this->getCaptionAlign())!==TTableCaptionAlign::NotSet) +				$writer->addAttribute('align',strtolower($align)); +			$writer->renderBeginTag('caption'); +			$writer->write($caption); +			$writer->renderEndTag(); +		} +	} + +	/** +	 * Renders body contents of the table. +	 * @param THtmlWriter the writer used for the rendering purpose. +	 */ +	public function renderContents($writer) +	{ +		if($this->getHasControls()) +		{ +			$renderTableSection=false; +			foreach($this->getControls() as $row) +			{ +				if($row->getTableSection()!==TTableRowSection::Body) +				{ +					$renderTableSection=true; +					break; +				} +			} +			if($renderTableSection) +			{ +				$currentSection=TTableRowSection::Header; +				$writer->writeLine(); +				foreach($this->getControls() as $index=>$row) +				{ +					if(($section=$row->getTableSection())===$currentSection) +					{ +						if($index===0 && $currentSection===TTableRowSection::Header) +							$writer->renderBeginTag('thead'); +					} +					else +					{ +						if($currentSection===TTableRowSection::Header) +						{ +							if($index>0) +								$writer->renderEndTag(); +							if($section===TTableRowSection::Body) +								$writer->renderBeginTag('tbody'); +							else +								$writer->renderBeginTag('tfoot'); +							$currentSection=$section; +						} +						else if($currentSection===TTableRowSection::Body) +						{ +							$writer->renderEndTag(); +							if($section===TTableRowSection::Footer) +								$writer->renderBeginTag('tfoot'); +							else +								throw new TConfigurationException('table_tablesection_outoforder'); +							$currentSection=$section; +						} +						else // Footer +							throw new TConfigurationException('table_tablesection_outoforder'); +					} +					$row->renderControl($writer); +					$writer->writeLine(); +				} +				$writer->renderEndTag(); +			} +			else +			{ +				$writer->writeLine(); +				foreach($this->getControls() as $row) +				{ +					$row->renderControl($writer); +					$writer->writeLine(); +				} +			} +		} +	} +} + + +/** + * TTableRowCollection class. + * + * TTableRowCollection is used to maintain a list of rows belong to a table. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableRowCollection extends TControlCollection +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by performing additional +	 * operations for each newly added table row. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a TTableRow object. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TTableRow) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('tablerowcollection_tablerow_required'); +	} +} + + +/** + * TTableCaptionAlign class. + * TTableCaptionAlign defines the enumerable type for the possible alignments + * that a table caption can take. + * + * The following enumerable values are defined: + * - NotSet: alignment not specified + * - Top: top aligned + * - Bottom: bottom aligned + * - Left: left aligned + * - Right: right aligned + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTableCaptionAlign extends TEnumerable +{ +	const NotSet='NotSet'; +	const Top='Top'; +	const Bottom='Bottom'; +	const Left='Left'; +	const Right='Right'; +} + diff --git a/framework/Web/UI/WebControls/TTableCell.php b/framework/Web/UI/WebControls/TTableCell.php index 6b43990b..70ff573f 100644 --- a/framework/Web/UI/WebControls/TTableCell.php +++ b/framework/Web/UI/WebControls/TTableCell.php @@ -1,222 +1,222 @@ -<?php
 -/**
 - * TTableCell class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTableCell class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TTableCell class.
 - *
 - * TTableCell displays a table cell on a Web page. Content of the table cell
 - * is specified by the {@link setText Text} property. If {@link setText Text}
 - * is empty, the body contents enclosed by the table cell component tag are rendered.
 - * Note, {@link setText Text} is not HTML-encoded when displayed. So make sure
 - * it does not contain dangerous characters.
 - *
 - * The horizontal and vertical alignments of the contents in the cell
 - * are specified via {@link setHorizontalAlign HorizontalAlign} and
 - * {@link setVerticalAlign VerticalAlign} properties, respectively.
 - *
 - * The colspan and rowspan of the cell are specified via {@link setColumnSpan ColumnSpan}
 - * and {@link setRowSpan RowSpan} properties. And the {@link setWrap Wrap} property
 - * indicates whether the contents in the cell should be wrapped.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableCell extends TWebControl implements IDataRenderer
 -{
 -	/**
 -	 * @return string tag name for the table cell
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'td';
 -	}
 -
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableItemStyle} to be used by the table cell.
 -	 * @return TStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableItemStyle;
 -	}
 -
 -	/**
 -	 * @return string the horizontal alignment of the contents within the table item, defaults to 'NotSet'.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getHorizontalAlign();
 -		else
 -			return 'NotSet';
 -	}
 -
 -	/**
 -	 * Sets the horizontal alignment of the contents within the table item.
 -     * Valid values include 'NotSet', 'Justify', 'Left', 'Right', 'Center'
 -	 * @param string the horizontal alignment
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->getStyle()->setHorizontalAlign($value);
 -	}
 -
 -	/**
 -	 * @return string the vertical alignment of the contents within the table item, defaults to 'NotSet'.
 -	 */
 -	public function getVerticalAlign()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getVerticalAlign();
 -		else
 -			return 'NotSet';
 -	}
 -
 -	/**
 -	 * Sets the vertical alignment of the contents within the table item.
 -     * Valid values include 'NotSet','Top','Bottom','Middle'
 -	 * @param string the horizontal alignment
 -	 */
 -	public function setVerticalAlign($value)
 -	{
 -		$this->getStyle()->setVerticalAlign($value);
 -	}
 -
 -	/**
 -	 * @return integer the columnspan for the table cell, 0 if not set.
 -	 */
 -	public function getColumnSpan()
 -	{
 -		return $this->getViewState('ColumnSpan', 0);
 -	}
 -
 -	/**
 -	 * Sets the columnspan for the table cell.
 -	 * @param integer the columnspan for the table cell, 0 if not set.
 -	 */
 -	public function setColumnSpan($value)
 -	{
 -		$this->setViewState('ColumnSpan', TPropertyValue::ensureInteger($value), 0);
 -	}
 -
 -	/**
 -	 * @return integer the rowspan for the table cell, 0 if not set.
 -	 */
 -	public function getRowSpan()
 -	{
 -		return $this->getViewState('RowSpan', 0);
 -	}
 -
 -	/**
 -	 * Sets the rowspan for the table cell.
 -	 * @param integer the rowspan for the table cell, 0 if not set.
 -	 */
 -	public function setRowSpan($value)
 -	{
 -		$this->setViewState('RowSpan', TPropertyValue::ensureInteger($value), 0);
 -	}
 -
 -	/**
 -	 * @return boolean whether the text content wraps within a table cell. Defaults to true.
 -	 */
 -	public function getWrap()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getWrap();
 -		else
 -			return true;
 -	}
 -
 -	/**
 -	 * Sets the value indicating whether the text content wraps within a table cell.
 -	 * @param boolean whether the text content wraps within a table cell.
 -	 */
 -	public function setWrap($value)
 -	{
 -		$this->getStyle()->setWrap($value);
 -	}
 -
 -	/**
 -	 * @return string the text content of the table cell.
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text content of the table cell.
 -	 * If the text content is empty, body content (child controls) of the cell will be rendered.
 -	 * @param string the text content
 -	 */
 -	public function setText($value)
 -	{
 -		$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
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		if(($colspan=$this->getColumnSpan())>0)
 -			$writer->addAttribute('colspan',"$colspan");
 -		if(($rowspan=$this->getRowSpan())>0)
 -			$writer->addAttribute('rowspan',"$rowspan");
 -	}
 -
 -	/**
 -	 * Renders body contents of the table cell.
 -	 * @param THtmlWriter the writer used for the rendering purpose.
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if(($text=$this->getText())!=='')
 -			$writer->write($text);
 -		else if($this->getHasControls())
 -			parent::renderContents($writer);
 -		else
 -			$writer->write(' ');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TTableCell class. + * + * TTableCell displays a table cell on a Web page. Content of the table cell + * is specified by the {@link setText Text} property. If {@link setText Text} + * is empty, the body contents enclosed by the table cell component tag are rendered. + * Note, {@link setText Text} is not HTML-encoded when displayed. So make sure + * it does not contain dangerous characters. + * + * The horizontal and vertical alignments of the contents in the cell + * are specified via {@link setHorizontalAlign HorizontalAlign} and + * {@link setVerticalAlign VerticalAlign} properties, respectively. + * + * The colspan and rowspan of the cell are specified via {@link setColumnSpan ColumnSpan} + * and {@link setRowSpan RowSpan} properties. And the {@link setWrap Wrap} property + * indicates whether the contents in the cell should be wrapped. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableCell extends TWebControl implements IDataRenderer +{ +	/** +	 * @return string tag name for the table cell +	 */ +	protected function getTagName() +	{ +		return 'td'; +	} + +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableItemStyle} to be used by the table cell. +	 * @return TStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableItemStyle; +	} + +	/** +	 * @return string the horizontal alignment of the contents within the table item, defaults to 'NotSet'. +	 */ +	public function getHorizontalAlign() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getHorizontalAlign(); +		else +			return 'NotSet'; +	} + +	/** +	 * Sets the horizontal alignment of the contents within the table item. +     * Valid values include 'NotSet', 'Justify', 'Left', 'Right', 'Center' +	 * @param string the horizontal alignment +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->getStyle()->setHorizontalAlign($value); +	} + +	/** +	 * @return string the vertical alignment of the contents within the table item, defaults to 'NotSet'. +	 */ +	public function getVerticalAlign() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getVerticalAlign(); +		else +			return 'NotSet'; +	} + +	/** +	 * Sets the vertical alignment of the contents within the table item. +     * Valid values include 'NotSet','Top','Bottom','Middle' +	 * @param string the horizontal alignment +	 */ +	public function setVerticalAlign($value) +	{ +		$this->getStyle()->setVerticalAlign($value); +	} + +	/** +	 * @return integer the columnspan for the table cell, 0 if not set. +	 */ +	public function getColumnSpan() +	{ +		return $this->getViewState('ColumnSpan', 0); +	} + +	/** +	 * Sets the columnspan for the table cell. +	 * @param integer the columnspan for the table cell, 0 if not set. +	 */ +	public function setColumnSpan($value) +	{ +		$this->setViewState('ColumnSpan', TPropertyValue::ensureInteger($value), 0); +	} + +	/** +	 * @return integer the rowspan for the table cell, 0 if not set. +	 */ +	public function getRowSpan() +	{ +		return $this->getViewState('RowSpan', 0); +	} + +	/** +	 * Sets the rowspan for the table cell. +	 * @param integer the rowspan for the table cell, 0 if not set. +	 */ +	public function setRowSpan($value) +	{ +		$this->setViewState('RowSpan', TPropertyValue::ensureInteger($value), 0); +	} + +	/** +	 * @return boolean whether the text content wraps within a table cell. Defaults to true. +	 */ +	public function getWrap() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getWrap(); +		else +			return true; +	} + +	/** +	 * Sets the value indicating whether the text content wraps within a table cell. +	 * @param boolean whether the text content wraps within a table cell. +	 */ +	public function setWrap($value) +	{ +		$this->getStyle()->setWrap($value); +	} + +	/** +	 * @return string the text content of the table cell. +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text content of the table cell. +	 * If the text content is empty, body content (child controls) of the cell will be rendered. +	 * @param string the text content +	 */ +	public function setText($value) +	{ +		$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 +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		if(($colspan=$this->getColumnSpan())>0) +			$writer->addAttribute('colspan',"$colspan"); +		if(($rowspan=$this->getRowSpan())>0) +			$writer->addAttribute('rowspan',"$rowspan"); +	} + +	/** +	 * Renders body contents of the table cell. +	 * @param THtmlWriter the writer used for the rendering purpose. +	 */ +	public function renderContents($writer) +	{ +		if(($text=$this->getText())!=='') +			$writer->write($text); +		else if($this->getHasControls()) +			parent::renderContents($writer); +		else +			$writer->write(' '); +	} +} + diff --git a/framework/Web/UI/WebControls/TTableFooterRow.php b/framework/Web/UI/WebControls/TTableFooterRow.php index 84bc29f1..1387c385 100644 --- a/framework/Web/UI/WebControls/TTableFooterRow.php +++ b/framework/Web/UI/WebControls/TTableFooterRow.php @@ -1,47 +1,47 @@ -<?php
 -/**
 - * TTableFooterRow class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTableFooterRow class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TTableRow class.
 - */
 -Prado::using('System.Web.UI.WebControls.TTableRow');
 -
 -/**
 - * TTableFooterRow class.
 - *
 - * TTableFooterRow displays a table footer row.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.1
 - */
 -class TTableFooterRow extends TTableRow
 -{
 -	/**
 -	 * @return string location of a row in a table. Always returns 'Footer'.
 -	 */
 -	public function getTableSection()
 -	{
 -		return 'Footer';
 -	}
 -
 -	/**
 -	 * @param string location of a row in a table.
 -	 * @throws TInvalidOperationException if this method is invoked
 -	 */
 -	public function setTableSection($value)
 -	{
 -		throw new TInvalidOperationException('tablefooterrow_tablesection_readonly');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TTableRow class. + */ +Prado::using('System.Web.UI.WebControls.TTableRow'); + +/** + * TTableFooterRow class. + * + * TTableFooterRow displays a table footer row. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.1 + */ +class TTableFooterRow extends TTableRow +{ +	/** +	 * @return string location of a row in a table. Always returns 'Footer'. +	 */ +	public function getTableSection() +	{ +		return 'Footer'; +	} + +	/** +	 * @param string location of a row in a table. +	 * @throws TInvalidOperationException if this method is invoked +	 */ +	public function setTableSection($value) +	{ +		throw new TInvalidOperationException('tablefooterrow_tablesection_readonly'); +	} +} + diff --git a/framework/Web/UI/WebControls/TTableHeaderCell.php b/framework/Web/UI/WebControls/TTableHeaderCell.php index bbf3e58a..72eae44e 100644 --- a/framework/Web/UI/WebControls/TTableHeaderCell.php +++ b/framework/Web/UI/WebControls/TTableHeaderCell.php @@ -1,124 +1,124 @@ -<?php
 -/**
 - * TTableHeaderCell class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTableHeaderCell class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TTableCell class
 - */
 -Prado::using('System.Web.UI.WebControls.TTableCell');
 -
 -
 -/**
 - * TTableHeaderCell class.
 - *
 - * TTableHeaderCell displays a table header cell on a Web page.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableHeaderCell extends TTableCell
 -{
 -	/**
 -	 * @return string tag name for the table header cell
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'th';
 -	}
 -
 -	/**
 -	 * Adds attributes to renderer.
 -	 * @param THtmlWriter the renderer
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		parent::addAttributesToRender($writer);
 -		if(($scope=$this->getScope())!==TTableHeaderScope::NotSet)
 -			$writer->addAttribute('scope',$scope===TTableHeaderScope::Row?'row':'col');
 -		if(($text=$this->getAbbreviatedText())!=='')
 -			$writer->addAttribute('abbr',$text);
 -		if(($text=$this->getCategoryText())!=='')
 -			$writer->addAttribute('axis',$text);
 -	}
 -
 -	/**
 -	 * @return TTableHeaderScope the scope of the cells that the header cell applies to. Defaults to TTableHeaderScope::NotSet.
 -	 */
 -	public function getScope()
 -	{
 -		return $this->getViewState('Scope',TTableHeaderScope::NotSet);
 -	}
 -
 -	/**
 -	 * @param TTableHeaderScope the scope of the cells that the header cell applies to.
 -	 */
 -	public function setScope($value)
 -	{
 -		$this->setViewState('Scope',TPropertyValue::ensureEnum($value,'TTableHeaderScope'),TTableHeaderScope::NotSet);
 -	}
 -
 -	/**
 -	 * @return string  the abbr attribute of the HTML th element
 -	 */
 -	public function getAbbreviatedText()
 -	{
 -		return $this->getViewState('AbbreviatedText','');
 -	}
 -
 -	/**
 -	 * @param string  the abbr attribute of the HTML th element
 -	 */
 -	public function setAbbreviatedText($value)
 -	{
 -		$this->setViewState('AbbreviatedText',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the axis attribute of the HTML th element
 -	 */
 -	public function getCategoryText()
 -	{
 -		return $this->getViewState('CategoryText','');
 -	}
 -
 -	/**
 -	 * @param string the axis attribute of the HTML th element
 -	 */
 -	public function setCategoryText($value)
 -	{
 -		$this->setViewState('CategoryText',$value,'');
 -	}
 -}
 -
 -
 -/**
 - * TTableHeaderScope class.
 - * TTableHeaderScope defines the enumerable type for the possible table scopes that a table header is associated with.
 - *
 - * The following enumerable values are defined:
 - * - NotSet: the scope is not specified
 - * - Row: the scope is row-wise
 - * - Column: the scope is column-wise
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTableHeaderScope extends TEnumerable
 -{
 -	const NotSet='NotSet';
 -	const Row='Row';
 -	const Column='Column';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TTableCell class + */ +Prado::using('System.Web.UI.WebControls.TTableCell'); + + +/** + * TTableHeaderCell class. + * + * TTableHeaderCell displays a table header cell on a Web page. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableHeaderCell extends TTableCell +{ +	/** +	 * @return string tag name for the table header cell +	 */ +	protected function getTagName() +	{ +		return 'th'; +	} + +	/** +	 * Adds attributes to renderer. +	 * @param THtmlWriter the renderer +	 */ +	protected function addAttributesToRender($writer) +	{ +		parent::addAttributesToRender($writer); +		if(($scope=$this->getScope())!==TTableHeaderScope::NotSet) +			$writer->addAttribute('scope',$scope===TTableHeaderScope::Row?'row':'col'); +		if(($text=$this->getAbbreviatedText())!=='') +			$writer->addAttribute('abbr',$text); +		if(($text=$this->getCategoryText())!=='') +			$writer->addAttribute('axis',$text); +	} + +	/** +	 * @return TTableHeaderScope the scope of the cells that the header cell applies to. Defaults to TTableHeaderScope::NotSet. +	 */ +	public function getScope() +	{ +		return $this->getViewState('Scope',TTableHeaderScope::NotSet); +	} + +	/** +	 * @param TTableHeaderScope the scope of the cells that the header cell applies to. +	 */ +	public function setScope($value) +	{ +		$this->setViewState('Scope',TPropertyValue::ensureEnum($value,'TTableHeaderScope'),TTableHeaderScope::NotSet); +	} + +	/** +	 * @return string  the abbr attribute of the HTML th element +	 */ +	public function getAbbreviatedText() +	{ +		return $this->getViewState('AbbreviatedText',''); +	} + +	/** +	 * @param string  the abbr attribute of the HTML th element +	 */ +	public function setAbbreviatedText($value) +	{ +		$this->setViewState('AbbreviatedText',$value,''); +	} + +	/** +	 * @return string the axis attribute of the HTML th element +	 */ +	public function getCategoryText() +	{ +		return $this->getViewState('CategoryText',''); +	} + +	/** +	 * @param string the axis attribute of the HTML th element +	 */ +	public function setCategoryText($value) +	{ +		$this->setViewState('CategoryText',$value,''); +	} +} + + +/** + * TTableHeaderScope class. + * TTableHeaderScope defines the enumerable type for the possible table scopes that a table header is associated with. + * + * The following enumerable values are defined: + * - NotSet: the scope is not specified + * - Row: the scope is row-wise + * - Column: the scope is column-wise + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTableHeaderScope extends TEnumerable +{ +	const NotSet='NotSet'; +	const Row='Row'; +	const Column='Column'; +} + diff --git a/framework/Web/UI/WebControls/TTableHeaderRow.php b/framework/Web/UI/WebControls/TTableHeaderRow.php index 448902dc..2c05b94d 100644 --- a/framework/Web/UI/WebControls/TTableHeaderRow.php +++ b/framework/Web/UI/WebControls/TTableHeaderRow.php @@ -1,47 +1,47 @@ -<?php
 -/**
 - * TTableHeaderRow class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTableHeaderRow class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TTableRow class.
 - */
 -Prado::using('System.Web.UI.WebControls.TTableRow');
 -
 -/**
 - * TTableHeaderRow class.
 - *
 - * TTableHeaderRow displays a table header row.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.1
 - */
 -class TTableHeaderRow extends TTableRow
 -{
 -	/**
 -	 * @return string location of a row in a table. Always returns 'Header'.
 -	 */
 -	public function getTableSection()
 -	{
 -		return 'Header';
 -	}
 -
 -	/**
 -	 * @param string location of a row in a table.
 -	 * @throws TInvalidOperationException if this method is invoked
 -	 */
 -	public function setTableSection($value)
 -	{
 -		throw new TInvalidOperationException('tableheaderrow_tablesection_readonly');
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TTableRow class. + */ +Prado::using('System.Web.UI.WebControls.TTableRow'); + +/** + * TTableHeaderRow class. + * + * TTableHeaderRow displays a table header row. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.1 + */ +class TTableHeaderRow extends TTableRow +{ +	/** +	 * @return string location of a row in a table. Always returns 'Header'. +	 */ +	public function getTableSection() +	{ +		return 'Header'; +	} + +	/** +	 * @param string location of a row in a table. +	 * @throws TInvalidOperationException if this method is invoked +	 */ +	public function setTableSection($value) +	{ +		throw new TInvalidOperationException('tableheaderrow_tablesection_readonly'); +	} +} + diff --git a/framework/Web/UI/WebControls/TTableRow.php b/framework/Web/UI/WebControls/TTableRow.php index e50099bf..3cfc82d0 100644 --- a/framework/Web/UI/WebControls/TTableRow.php +++ b/framework/Web/UI/WebControls/TTableRow.php @@ -1,208 +1,208 @@ -<?php
 -/**
 - * TTableRow and TTableCellCollection class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTableRow and TTableCellCollection class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TTableCell class
 - */
 -Prado::using('System.Web.UI.WebControls.TTableCell');
 -
 -/**
 - * TTableRow class.
 - *
 - * TTableRow displays a table row. The table cells in the row can be accessed
 - * via {@link getCells Cells}. The horizontal and vertical alignments of the row
 - * are specified via {@link setHorizontalAlign HorizontalAlign} and
 - * {@link setVerticalAlign VerticalAlign} properties, respectively.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableRow extends TWebControl
 -{
 -	/**
 -	 * @return string tag name for the table
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'tr';
 -	}
 -
 -	/**
 -	 * Adds object parsed from template to the control.
 -	 * This method adds only {@link TTableCell} objects into the {@link getCells Cells} collection.
 -	 * All other objects are ignored.
 -	 * @param mixed object parsed from template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TTableCell)
 -			$this->getCells()->add($object);
 -	}
 -
 -	/**
 -	 * Creates a style object for the control.
 -	 * This method creates a {@link TTableItemStyle} to be used by the table row.
 -	 * @return TStyle control style to be used
 -	 */
 -	protected function createStyle()
 -	{
 -		return new TTableItemStyle;
 -	}
 -
 -	/**
 -	 * Creates a control collection object that is to be used to hold child controls
 -	 * @return TTableCellCollection control collection
 -	 * @see getControls
 -	 */
 -	protected function createControlCollection()
 -	{
 -		return new TTableCellCollection($this);
 -	}
 -
 -	/**
 -	 * @return TTableCellCollection list of {@link TTableCell} controls
 -	 */
 -	public function getCells()
 -	{
 -		return $this->getControls();
 -	}
 -
 -	/**
 -	 * @return string the horizontal alignment of the contents within the table item, defaults to 'NotSet'.
 -	 */
 -	public function getHorizontalAlign()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getHorizontalAlign();
 -		else
 -			return 'NotSet';
 -	}
 -
 -	/**
 -	 * Sets the horizontal alignment of the contents within the table item.
 -     * Valid values include 'NotSet', 'Justify', 'Left', 'Right', 'Center'
 -	 * @param string the horizontal alignment
 -	 */
 -	public function setHorizontalAlign($value)
 -	{
 -		$this->getStyle()->setHorizontalAlign($value);
 -	}
 -
 -	/**
 -	 * @return string the vertical alignment of the contents within the table item, defaults to 'NotSet'.
 -	 */
 -	public function getVerticalAlign()
 -	{
 -		if($this->getHasStyle())
 -			return $this->getStyle()->getVerticalAlign();
 -		else
 -			return 'NotSet';
 -	}
 -
 -	/**
 -	 * Sets the vertical alignment of the contents within the table item.
 -     * Valid values include 'NotSet','Top','Bottom','Middle'
 -	 * @param string the horizontal alignment
 -	 */
 -	public function setVerticalAlign($value)
 -	{
 -		$this->getStyle()->setVerticalAlign($value);
 -	}
 -
 -	/**
 -	 * @return TTableRowSection location of a row in a table. Defaults to TTableRowSection::Body.
 -	 */
 -	public function getTableSection()
 -	{
 -		return $this->getViewState('TableSection',TTableRowSection::Body);
 -	}
 -
 -	/**
 -	 * @param TTableRowSection location of a row in a table.
 -	 */
 -	public function setTableSection($value)
 -	{
 -		$this->setViewState('TableSection',TPropertyValue::ensureEnum($value,'TTableRowSection'),TTableRowSection::Body);
 -	}
 -
 -	/**
 -	 * Renders body contents of the table row
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if($this->getHasControls())
 -		{
 -			$writer->writeLine();
 -			foreach($this->getControls() as $cell)
 -			{
 -				$cell->renderControl($writer);
 -				$writer->writeLine();
 -			}
 -		}
 -	}
 -}
 -
 -/**
 - * TTableCellCollection class.
 - *
 - * TTableCellCollection is used to maintain a list of cells belong to a table row.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTableCellCollection extends TControlCollection
 -{
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This overrides the parent implementation by performing additional
 -	 * operations for each newly added table cell.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item to be inserted is not a TTableCell object.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TTableCell)
 -			parent::insertAt($index,$item);
 -		else
 -			throw new TInvalidDataTypeException('tablecellcollection_tablecell_required');
 -	}
 -}
 -
 -
 -/**
 - * TTableRowSection class.
 - * TTableRowSection defines the enumerable type for the possible table sections
 - * that a {@link TTableRow} can be within.
 - *
 - * The following enumerable values are defined:
 - * - Header: in table header
 - * - Body: in table body
 - * - Footer: in table footer
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTableRowSection extends TEnumerable
 -{
 -	const Header='Header';
 -	const Body='Body';
 -	const Footer='Footer';
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TTableCell class + */ +Prado::using('System.Web.UI.WebControls.TTableCell'); + +/** + * TTableRow class. + * + * TTableRow displays a table row. The table cells in the row can be accessed + * via {@link getCells Cells}. The horizontal and vertical alignments of the row + * are specified via {@link setHorizontalAlign HorizontalAlign} and + * {@link setVerticalAlign VerticalAlign} properties, respectively. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableRow extends TWebControl +{ +	/** +	 * @return string tag name for the table +	 */ +	protected function getTagName() +	{ +		return 'tr'; +	} + +	/** +	 * Adds object parsed from template to the control. +	 * This method adds only {@link TTableCell} objects into the {@link getCells Cells} collection. +	 * All other objects are ignored. +	 * @param mixed object parsed from template +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TTableCell) +			$this->getCells()->add($object); +	} + +	/** +	 * Creates a style object for the control. +	 * This method creates a {@link TTableItemStyle} to be used by the table row. +	 * @return TStyle control style to be used +	 */ +	protected function createStyle() +	{ +		return new TTableItemStyle; +	} + +	/** +	 * Creates a control collection object that is to be used to hold child controls +	 * @return TTableCellCollection control collection +	 * @see getControls +	 */ +	protected function createControlCollection() +	{ +		return new TTableCellCollection($this); +	} + +	/** +	 * @return TTableCellCollection list of {@link TTableCell} controls +	 */ +	public function getCells() +	{ +		return $this->getControls(); +	} + +	/** +	 * @return string the horizontal alignment of the contents within the table item, defaults to 'NotSet'. +	 */ +	public function getHorizontalAlign() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getHorizontalAlign(); +		else +			return 'NotSet'; +	} + +	/** +	 * Sets the horizontal alignment of the contents within the table item. +     * Valid values include 'NotSet', 'Justify', 'Left', 'Right', 'Center' +	 * @param string the horizontal alignment +	 */ +	public function setHorizontalAlign($value) +	{ +		$this->getStyle()->setHorizontalAlign($value); +	} + +	/** +	 * @return string the vertical alignment of the contents within the table item, defaults to 'NotSet'. +	 */ +	public function getVerticalAlign() +	{ +		if($this->getHasStyle()) +			return $this->getStyle()->getVerticalAlign(); +		else +			return 'NotSet'; +	} + +	/** +	 * Sets the vertical alignment of the contents within the table item. +     * Valid values include 'NotSet','Top','Bottom','Middle' +	 * @param string the horizontal alignment +	 */ +	public function setVerticalAlign($value) +	{ +		$this->getStyle()->setVerticalAlign($value); +	} + +	/** +	 * @return TTableRowSection location of a row in a table. Defaults to TTableRowSection::Body. +	 */ +	public function getTableSection() +	{ +		return $this->getViewState('TableSection',TTableRowSection::Body); +	} + +	/** +	 * @param TTableRowSection location of a row in a table. +	 */ +	public function setTableSection($value) +	{ +		$this->setViewState('TableSection',TPropertyValue::ensureEnum($value,'TTableRowSection'),TTableRowSection::Body); +	} + +	/** +	 * Renders body contents of the table row +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +		if($this->getHasControls()) +		{ +			$writer->writeLine(); +			foreach($this->getControls() as $cell) +			{ +				$cell->renderControl($writer); +				$writer->writeLine(); +			} +		} +	} +} + +/** + * TTableCellCollection class. + * + * TTableCellCollection is used to maintain a list of cells belong to a table row. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTableCellCollection extends TControlCollection +{ +	/** +	 * Inserts an item at the specified position. +	 * This overrides the parent implementation by performing additional +	 * operations for each newly added table cell. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item to be inserted is not a TTableCell object. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TTableCell) +			parent::insertAt($index,$item); +		else +			throw new TInvalidDataTypeException('tablecellcollection_tablecell_required'); +	} +} + + +/** + * TTableRowSection class. + * TTableRowSection defines the enumerable type for the possible table sections + * that a {@link TTableRow} can be within. + * + * The following enumerable values are defined: + * - Header: in table header + * - Body: in table body + * - Footer: in table footer + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTableRowSection extends TEnumerable +{ +	const Header='Header'; +	const Body='Body'; +	const Footer='Footer'; +} + diff --git a/framework/Web/UI/WebControls/TTemplateColumn.php b/framework/Web/UI/WebControls/TTemplateColumn.php index f2bf02d7..34c9bbaf 100644 --- a/framework/Web/UI/WebControls/TTemplateColumn.php +++ b/framework/Web/UI/WebControls/TTemplateColumn.php @@ -1,256 +1,256 @@ -<?php
 -/**
 - * TTemplateColumn class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTemplateColumn class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TDataGridColumn class file
 - */
 -Prado::using('System.Web.UI.WebControls.TDataGridColumn');
 -
 -/**
 - * TTemplateColumn class
 - *
 - * TTemplateColumn customizes the layout of controls in the column with templates.
 - * In particular, you can specify {@link setItemTemplate ItemTemplate},
 - * {@link setEditItemTemplate EditItemTemplate}, {@link setHeaderTemplate HeaderTemplate}
 - * and {@link setFooterTemplate FooterTemplate} to customize specific
 - * type of cells in the column.
 - *
 - * Since v3.1.0, TTemplateColumn has introduced two new properties {@link setItemRenderer ItemRenderer}
 - * and {@link setEditItemRenderer EditItemRenderer} which can be used to specify
 - * the layout of the datagrid cells in browsing and editing mode.
 - * A renderer refers to a control class that is to be instantiated as a control.
 - * For more details, see {@link TRepeater} and {@link TDataList}.
 - *
 - * When a renderer and a template are both defined for a type of item, the former
 - * takes precedence.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTemplateColumn extends TDataGridColumn
 -{
 -	/**
 -	 * Various item templates
 -	 * @var string
 -	 */
 -	private $_itemTemplate=null;
 -	private $_editItemTemplate=null;
 -	private $_headerTemplate=null;
 -	private $_footerTemplate=null;
 -
 -	/**
 -	 * @return string the class name for the item cell renderer. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getItemRenderer()
 -	{
 -		return $this->getViewState('ItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the item cell renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as a child control in the item cells of the column.
 -	 *
 -	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property
 -	 * will be set as the row of the data associated with the datagrid item that this cell resides in.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @since 3.1.0
 -	 */
 -	public function setItemRenderer($value)
 -	{
 -		$this->setViewState('ItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return string the class name for the edit item cell renderer. Defaults to empty, meaning not set.
 -	 * @since 3.1.0
 -	 */
 -	public function getEditItemRenderer()
 -	{
 -		return $this->getViewState('EditItemRenderer','');
 -	}
 -
 -	/**
 -	 * Sets the edit item cell renderer class.
 -	 *
 -	 * If not empty, the class will be used to instantiate as a child control in the item cell that is in edit mode.
 -	 *
 -	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property
 -	 * will be set as the row of the data associated with the datagrid item that this cell resides in.
 -	 *
 -	 * @param string the renderer class name in namespace format.
 -	 * @since 3.1.0
 -	 */
 -	public function setEditItemRenderer($value)
 -	{
 -		$this->setViewState('EditItemRenderer',$value,'');
 -	}
 -
 -	/**
 -	 * @return ITemplate the edit item template
 -	 */
 -	public function getEditItemTemplate()
 -	{
 -		return $this->_editItemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the edit item template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setEditItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_editItemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('templatecolumn_template_required','EditItemTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the item template
 -	 */
 -	public function getItemTemplate()
 -	{
 -		return $this->_itemTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the item template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setItemTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_itemTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('templatecolumn_template_required','ItemTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the header template
 -	 */
 -	public function getHeaderTemplate()
 -	{
 -		return $this->_headerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the header template.
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setHeaderTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_headerTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('templatecolumn_template_required','HeaderTemplate');
 -	}
 -
 -	/**
 -	 * @return ITemplate the footer template
 -	 */
 -	public function getFooterTemplate()
 -	{
 -		return $this->_footerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the footer template
 -	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
 -	 */
 -	public function setFooterTemplate($value)
 -	{
 -		if($value instanceof ITemplate || $value===null)
 -			$this->_footerTemplate=$value;
 -		else
 -			throw new TInvalidDataTypeException('templatecolumn_template_required','FooterTemplate');
 -	}
 -
 -	/**
 -	 * Initializes the specified cell to its initial values.
 -	 * This method overrides the parent implementation.
 -	 * It initializes the cell based on different templates
 -	 * (ItemTemplate, EditItemTemplate, HeaderTemplate, FooterTemplate).
 -	 * @param TTableCell the cell to be initialized.
 -	 * @param integer the index to the Columns property that the cell resides in.
 -	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem)
 -	 */
 -	public function initializeCell($cell,$columnIndex,$itemType)
 -	{
 -		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem)
 -		{
 -			if($itemType===TListItemType::EditItem)
 -			{
 -				if(($classPath=$this->getEditItemRenderer())==='' && ($template=$this->_editItemTemplate)===null)
 -				{
 -					$classPath=$this->getItemRenderer();
 -					$template=$this->_itemTemplate;
 -				}
 -			}
 -			else
 -			{
 -				$template=$this->_itemTemplate;
 -				$classPath=$this->getItemRenderer();
 -			}
 -			if($classPath!=='')
 -			{
 -				$control=Prado::createComponent($classPath);
 -				$cell->getControls()->add($control);
 -				if($control instanceof IItemDataRenderer)
 -				{
 -					$control->setItemIndex($cell->getParent()->getItemIndex());
 -					$control->setItemType($itemType);
 -				}
 -				if($control instanceof IDataRenderer)
 -					$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
 -			}
 -			else if($template!==null)
 -				$template->instantiateIn($cell);
 -			else if($itemType!==TListItemType::EditItem)
 -				$cell->setText(' ');
 -		}
 -		else if($itemType===TListItemType::Header)
 -		{
 -			if(($classPath=$this->getHeaderRenderer())!=='')
 -				$this->initializeHeaderCell($cell,$columnIndex);
 -			else if($this->_headerTemplate!==null)
 -				$this->_headerTemplate->instantiateIn($cell);
 -			else
 -				$this->initializeHeaderCell($cell,$columnIndex);
 -		}
 -		else if($itemType===TListItemType::Footer)
 -		{
 -			if(($classPath=$this->getFooterRenderer())!=='')
 -				$this->initializeFooterCell($cell,$columnIndex);
 -			else if($this->_footerTemplate!==null)
 -				$this->_footerTemplate->instantiateIn($cell);
 -			else
 -				$this->initializeFooterCell($cell,$columnIndex);
 -		}
 -	}
 -
 -	/**
 -	 * Databinds a cell in the column.
 -	 * This method is invoked when datagrid performs databinding.
 -	 * It populates the content of the cell with the relevant data from data source.
 -	 */
 -	public function dataBindColumn($sender,$param)
 -	{
 -		$item=$sender->getNamingContainer();
 -		$sender->setData($item->getData());
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TDataGridColumn class file + */ +Prado::using('System.Web.UI.WebControls.TDataGridColumn'); + +/** + * TTemplateColumn class + * + * TTemplateColumn customizes the layout of controls in the column with templates. + * In particular, you can specify {@link setItemTemplate ItemTemplate}, + * {@link setEditItemTemplate EditItemTemplate}, {@link setHeaderTemplate HeaderTemplate} + * and {@link setFooterTemplate FooterTemplate} to customize specific + * type of cells in the column. + * + * Since v3.1.0, TTemplateColumn has introduced two new properties {@link setItemRenderer ItemRenderer} + * and {@link setEditItemRenderer EditItemRenderer} which can be used to specify + * the layout of the datagrid cells in browsing and editing mode. + * A renderer refers to a control class that is to be instantiated as a control. + * For more details, see {@link TRepeater} and {@link TDataList}. + * + * When a renderer and a template are both defined for a type of item, the former + * takes precedence. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTemplateColumn extends TDataGridColumn +{ +	/** +	 * Various item templates +	 * @var string +	 */ +	private $_itemTemplate=null; +	private $_editItemTemplate=null; +	private $_headerTemplate=null; +	private $_footerTemplate=null; + +	/** +	 * @return string the class name for the item cell renderer. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getItemRenderer() +	{ +		return $this->getViewState('ItemRenderer',''); +	} + +	/** +	 * Sets the item cell renderer class. +	 * +	 * If not empty, the class will be used to instantiate as a child control in the item cells of the column. +	 * +	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property +	 * will be set as the row of the data associated with the datagrid item that this cell resides in. +	 * +	 * @param string the renderer class name in namespace format. +	 * @since 3.1.0 +	 */ +	public function setItemRenderer($value) +	{ +		$this->setViewState('ItemRenderer',$value,''); +	} + +	/** +	 * @return string the class name for the edit item cell renderer. Defaults to empty, meaning not set. +	 * @since 3.1.0 +	 */ +	public function getEditItemRenderer() +	{ +		return $this->getViewState('EditItemRenderer',''); +	} + +	/** +	 * Sets the edit item cell renderer class. +	 * +	 * If not empty, the class will be used to instantiate as a child control in the item cell that is in edit mode. +	 * +	 * If the class implements {@link IDataRenderer}, the <b>Data</b> property +	 * will be set as the row of the data associated with the datagrid item that this cell resides in. +	 * +	 * @param string the renderer class name in namespace format. +	 * @since 3.1.0 +	 */ +	public function setEditItemRenderer($value) +	{ +		$this->setViewState('EditItemRenderer',$value,''); +	} + +	/** +	 * @return ITemplate the edit item template +	 */ +	public function getEditItemTemplate() +	{ +		return $this->_editItemTemplate; +	} + +	/** +	 * @param ITemplate the edit item template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setEditItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_editItemTemplate=$value; +		else +			throw new TInvalidDataTypeException('templatecolumn_template_required','EditItemTemplate'); +	} + +	/** +	 * @return ITemplate the item template +	 */ +	public function getItemTemplate() +	{ +		return $this->_itemTemplate; +	} + +	/** +	 * @param ITemplate the item template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setItemTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_itemTemplate=$value; +		else +			throw new TInvalidDataTypeException('templatecolumn_template_required','ItemTemplate'); +	} + +	/** +	 * @return ITemplate the header template +	 */ +	public function getHeaderTemplate() +	{ +		return $this->_headerTemplate; +	} + +	/** +	 * @param ITemplate the header template. +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setHeaderTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_headerTemplate=$value; +		else +			throw new TInvalidDataTypeException('templatecolumn_template_required','HeaderTemplate'); +	} + +	/** +	 * @return ITemplate the footer template +	 */ +	public function getFooterTemplate() +	{ +		return $this->_footerTemplate; +	} + +	/** +	 * @param ITemplate the footer template +	 * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null. +	 */ +	public function setFooterTemplate($value) +	{ +		if($value instanceof ITemplate || $value===null) +			$this->_footerTemplate=$value; +		else +			throw new TInvalidDataTypeException('templatecolumn_template_required','FooterTemplate'); +	} + +	/** +	 * Initializes the specified cell to its initial values. +	 * This method overrides the parent implementation. +	 * It initializes the cell based on different templates +	 * (ItemTemplate, EditItemTemplate, HeaderTemplate, FooterTemplate). +	 * @param TTableCell the cell to be initialized. +	 * @param integer the index to the Columns property that the cell resides in. +	 * @param string the type of cell (Header,Footer,Item,AlternatingItem,EditItem,SelectedItem) +	 */ +	public function initializeCell($cell,$columnIndex,$itemType) +	{ +		if($itemType===TListItemType::Item || $itemType===TListItemType::AlternatingItem || $itemType===TListItemType::SelectedItem || $itemType===TListItemType::EditItem) +		{ +			if($itemType===TListItemType::EditItem) +			{ +				if(($classPath=$this->getEditItemRenderer())==='' && ($template=$this->_editItemTemplate)===null) +				{ +					$classPath=$this->getItemRenderer(); +					$template=$this->_itemTemplate; +				} +			} +			else +			{ +				$template=$this->_itemTemplate; +				$classPath=$this->getItemRenderer(); +			} +			if($classPath!=='') +			{ +				$control=Prado::createComponent($classPath); +				$cell->getControls()->add($control); +				if($control instanceof IItemDataRenderer) +				{ +					$control->setItemIndex($cell->getParent()->getItemIndex()); +					$control->setItemType($itemType); +				} +				if($control instanceof IDataRenderer) +					$control->attachEventHandler('OnDataBinding',array($this,'dataBindColumn')); +			} +			else if($template!==null) +				$template->instantiateIn($cell); +			else if($itemType!==TListItemType::EditItem) +				$cell->setText(' '); +		} +		else if($itemType===TListItemType::Header) +		{ +			if(($classPath=$this->getHeaderRenderer())!=='') +				$this->initializeHeaderCell($cell,$columnIndex); +			else if($this->_headerTemplate!==null) +				$this->_headerTemplate->instantiateIn($cell); +			else +				$this->initializeHeaderCell($cell,$columnIndex); +		} +		else if($itemType===TListItemType::Footer) +		{ +			if(($classPath=$this->getFooterRenderer())!=='') +				$this->initializeFooterCell($cell,$columnIndex); +			else if($this->_footerTemplate!==null) +				$this->_footerTemplate->instantiateIn($cell); +			else +				$this->initializeFooterCell($cell,$columnIndex); +		} +	} + +	/** +	 * Databinds a cell in the column. +	 * This method is invoked when datagrid performs databinding. +	 * It populates the content of the cell with the relevant data from data source. +	 */ +	public function dataBindColumn($sender,$param) +	{ +		$item=$sender->getNamingContainer(); +		$sender->setData($item->getData()); +	} +} + diff --git a/framework/Web/UI/WebControls/TTextBox.php b/framework/Web/UI/WebControls/TTextBox.php index 7a9f0445..5cd1149a 100644 --- a/framework/Web/UI/WebControls/TTextBox.php +++ b/framework/Web/UI/WebControls/TTextBox.php @@ -1,652 +1,652 @@ -<?php
 -/**
 - * TTextBox class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TTextBox class
 - *
 - * TTextBox displays a text box on the Web page for user input.
 - * The text displayed in the TTextBox control is determined by the
 - * {@link setText Text} property. You can create a <b>SingleLine</b>,
 - * a <b>MultiLine</b>, or a <b>Password</b> text box by setting
 - * the {@link setTextMode TextMode} property. If the TTextBox control
 - * is a multiline text box, the number of rows it displays is determined
 - * by the {@link setRows Rows} property, and the {@link setWrap Wrap} property
 - * can be used to determine whether to wrap the text in the component.
 - *
 - * To specify the display width of the text box, in characters, set
 - * the {@link setColumns Columns} property. To prevent the text displayed
 - * in the component from being modified, set the {@link setReadOnly ReadOnly}
 - * property to true. If you want to limit the user input to a specified number
 - * of characters, set the {@link setMaxLength MaxLength} property.
 - * To use AutoComplete feature, set the {@link setAutoCompleteType AutoCompleteType} property.
 - *
 - * If {@link setAutoPostBack AutoPostBack} is set true, updating the text box
 - * and then changing the focus out of it will cause postback action.
 - * And if {@link setCausesValidation CausesValidation} is true, validation will
 - * also be processed, which can be further restricted within
 - * a {@link setValidationGroup ValidationGroup}.
 - *
 - * WARNING: Be careful if you want to display the text collected via TTextBox.
 - * Malicious cross-site script may be injected in. You may use {@link getSafeText SafeText}
 - * to prevent this problem.
 - *
 - * NOTE: If you set {@link setWrap Wrap} to false or use {@link setAutoCompleteType AutoCompleteType},
 - * the generated HTML output for the textbox will not be XHTML-compatible.
 - * Currently, no alternatives are available.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer
 -{
 -	/**
 -	 * Default number of rows (for MultiLine text box)
 -	 */
 -	const DEFAULT_ROWS=4;
 -	/**
 -	 * Default number of columns (for MultiLine text box)
 -	 */
 -	const DEFAULT_COLUMNS=20;
 -	/**
 -	 * @var mixed safe text parser
 -	 */
 -	private static $_safeTextParser=null;
 -	/**
 -	 * @var string safe textbox content with javascript stripped off
 -	 */
 -	private $_safeText;
 -	private $_dataChanged=false;
 -	private $_isValid=true;
 -
 -	/**
 -	 * @return string tag name of the textbox
 -	 */
 -	protected function getTagName()
 -	{
 -		return ($this->getTextMode()==='MultiLine')?'textarea':'input';
 -	}
 -
 -	/**
 -	 * @return boolean whether to render javascript.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to render javascript.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * Adds attribute name-value pairs to renderer.
 -	 * This method overrides the parent implementation with additional textbox specific attributes.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function addAttributesToRender($writer)
 -	{
 -		$page=$this->getPage();
 -		$page->ensureRenderInForm($this);
 -		if(($uid=$this->getUniqueID())!=='')
 -			$writer->addAttribute('name',$uid);
 -		if(($textMode=$this->getTextMode())===TTextBoxMode::MultiLine)
 -		{
 -			if(($rows=$this->getRows())<=0)
 -				$rows=self::DEFAULT_ROWS;
 -			if(($cols=$this->getColumns())<=0)
 -				$cols=self::DEFAULT_COLUMNS;
 -			$writer->addAttribute('rows',"$rows");
 -			$writer->addAttribute('cols',"$cols");
 -			if(!$this->getWrap())
 -				$writer->addAttribute('wrap','off');
 -		}
 -		else
 -		{
 -			if($textMode===TTextBoxMode::SingleLine)
 -			{
 -				$writer->addAttribute('type','text');
 -				if(($text=$this->getText())!=='')
 -					$writer->addAttribute('value',$text);
 -			}
 -			else
 -			{
 -				if($this->getPersistPassword() && ($text=$this->getText())!=='')
 -					$writer->addAttribute('value',$text);
 -				$writer->addAttribute('type','password');
 -			}
 -
 -			if(($act=$this->getAutoCompleteType())!=='None')
 -			{
 -				if($act==='Disabled')
 -					$writer->addAttribute('autocomplete','off');
 -				else if($act==='Search')
 -					$writer->addAttribute('vcard_name','search');
 -				else if($act==='HomeCountryRegion')
 -					$writer->addAttribute('vcard_name','HomeCountry');
 -				else if($act==='BusinessCountryRegion')
 -					$writer->addAttribute('vcard_name','BusinessCountry');
 -				else
 -				{
 -					if(strpos($act,'Business')===0)
 -						$act='Business'.'.'.substr($act,8);
 -					else if(strpos($act,'Home')===0)
 -						$act='Home'.'.'.substr($act,4);
 -					$writer->addAttribute('vcard_name','vCard.'.$act);
 -				}
 -			}
 -
 -			if(($cols=$this->getColumns())>0)
 -				$writer->addAttribute('size',"$cols");
 -			if(($maxLength=$this->getMaxLength())>0)
 -				$writer->addAttribute('maxlength',"$maxLength");
 -		}
 -		if($this->getReadOnly())
 -			$writer->addAttribute('readonly','readonly');
 -		$isEnabled=$this->getEnabled(true);
 -		if(!$isEnabled && $this->getEnabled())  // in this case parent will not render 'disabled'
 -			$writer->addAttribute('disabled','disabled');
 -		if($isEnabled
 -			&& $this->getEnableClientScript()
 -			&& ( $this->getAutoPostBack() || $textMode===TTextBoxMode::SingleLine)
 -			&& $page->getClientSupportsJavaScript())
 -		{
 -			$this->renderClientControlScript($writer);
 -		}
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Renders the javascript for textbox.
 -	 */
 -	protected function renderClientControlScript($writer)
 -	{
 -		$writer->addAttribute('id',$this->getClientID());
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
 -	}
 -
 -	/**
 -	 * Gets the name of the javascript class responsible for performing postback for this control.
 -	 * This method overrides the parent implementation.
 -	 * @return string the javascript class name
 -	 */
 -	protected function getClientClassName()
 -	{
 -		return 'Prado.WebUI.TTextBox';
 -	}
 -
 -	/**
 -	 * Gets the post back options for this textbox.
 -	 * @return array
 -	 */
 -	protected function getPostBackOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['EventTarget'] = $this->getUniqueID();
 -		$options['AutoPostBack'] = $this->getAutoPostBack();
 -		$options['CausesValidation'] = $this->getCausesValidation();
 -		$options['ValidationGroup'] = $this->getValidationGroup();
 -		$options['TextMode'] = $this->getTextMode();
 -		return $options;
 -	}
 -
 -	/**
 -	 * Loads user input data.
 -	 * This method is primarly used by framework developers.
 -	 * @param string the key that can be used to retrieve data from the input data collection
 -	 * @param array the input data collection
 -	 * @return boolean whether the data of the component has been changed
 -	 */
 -	public function loadPostData($key,$values)
 -	{
 -		$value=$values[$key];
 -		if($this->getAutoTrim())
 -			$value=trim($value);
 -		if(!$this->getReadOnly() && $this->getText()!==$value)
 -		{
 -			$this->setText($value);
 -			return $this->_dataChanged=true;
 -		}
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * Returns a value indicating whether postback has caused the control data change.
 -	 * This method is required by the IPostBackDataHandler interface.
 -	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
 -	 */
 -	public function getDataChanged()
 -	{
 -		return $this->_dataChanged;
 -	}
 -
 -	/**
 -	 * Returns the value to be validated.
 -	 * This methid is required by IValidatable interface.
 -	 * @return mixed the value of the property to be validated.
 -	 */
 -	public function getValidationPropertyValue()
 -	{
 -		return $this->getText();
 -	}
 -
 -	/**
 -	 * Returns true if this control validated successfully.
 -	 * Defaults to true.
 -	 * @return bool wether this control validated successfully.
 -	 */
 -	public function getIsValid()
 -	{
 -	    return $this->_isValid;
 -	}
 -	/**
 -	 * @param bool wether this control is valid.
 -	 */
 -	public function setIsValid($value)
 -	{
 -	    $this->_isValid=TPropertyValue::ensureBoolean($value);
 -	}
 -
 -	/**
 -	 * Raises <b>OnTextChanged</b> event.
 -	 * This method is invoked when the value of the {@link getText Text}
 -	 * property changes on postback.
 -	 * If you override this method, be sure to call the parent implementation to ensure
 -	 * the invocation of the attached event handlers.
 -	 * @param TEventParameter event parameter to be passed to the event handlers
 -	 */
 -	public function onTextChanged($param)
 -	{
 -		$this->raiseEvent('OnTextChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises postdata changed event.
 -	 * This method is required by {@link IPostBackDataHandler} interface.
 -	 * It is invoked by the framework when {@link getText Text} property
 -	 * is changed on postback.
 -	 * This method is primarly used by framework developers.
 -	 */
 -	public function raisePostDataChangedEvent()
 -	{
 -		if($this->getAutoPostBack() && $this->getCausesValidation())
 -			$this->getPage()->validate($this->getValidationGroup());
 -		$this->onTextChanged(null);
 -	}
 -
 -	/**
 -	 * Renders the body content of the textbox when it is in MultiLine text mode.
 -	 * @param THtmlWriter the writer for rendering
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if($this->getTextMode()==='MultiLine')
 -			$writer->write(THttpUtility::htmlEncode($this->getText()));
 -	}
 -
 -	/**
 -	 * Renders an additional line-break after the opening tag when it
 -	 * is in MultiLine text mode.
 -	 * @param THtmlWriter the writer used for the rendering purpose^M
 -	 */
 -	public function renderBeginTag($writer)
 -	{
 -		parent::renderBeginTag($writer);
 -		if($this->getTextMode()==='MultiLine')
 -			$writer->write("\n");
 -	}
 -
 -	/**
 -	 * @return TTextBoxAutoCompleteType the AutoComplete type of the textbox
 -	 */
 -	public function getAutoCompleteType()
 -	{
 -		return $this->getViewState('AutoCompleteType',TTextBoxAutoCompleteType::None);
 -	}
 -
 -	/**
 -	 * @param TTextBoxAutoCompleteType the AutoComplete type of the textbox, default value is TTextBoxAutoCompleteType::None.
 -	 * @throws TInvalidDataValueException if the input parameter is not a valid AutoComplete type
 -	 */
 -	public function setAutoCompleteType($value)
 -	{
 -		$this->setViewState('AutoCompleteType',TPropertyValue::ensureEnum($value,'TTextBoxAutoCompleteType'),TTextBoxAutoCompleteType::None);
 -	}
 -
 -	/**
 -	 * @return boolean a value indicating whether an automatic postback to the server
 -     * will occur whenever the user modifies the text in the TTextBox control and
 -     * then tabs out of the component. Defaults to false.
 -	 */
 -	public function getAutoPostBack()
 -	{
 -		return $this->getViewState('AutoPostBack',false);
 -	}
 -
 -	/**
 -	 * Sets the value indicating if postback automatically.
 -	 * An automatic postback to the server will occur whenever the user
 -	 * modifies the text in the TTextBox control and then tabs out of the component.
 -	 * @param boolean the value indicating if postback automatically
 -	 */
 -	public function setAutoPostBack($value)
 -	{
 -		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean a value indicating whether the input text should be trimmed spaces. Defaults to false.
 -	 */
 -	public function getAutoTrim()
 -	{
 -		return $this->getViewState('AutoTrim',false);
 -	}
 -
 -	/**
 -	 * Sets the value indicating if the input text should be trimmed spaces
 -	 * @param boolean the value indicating if the input text should be trimmed spaces
 -	 */
 -	public function setAutoTrim($value)
 -	{
 -		$this->setViewState('AutoTrim',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether postback event trigger by this text box will cause input validation, default is true.
 -	 */
 -	public function getCausesValidation()
 -	{
 -		return $this->getViewState('CausesValidation',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether postback event trigger by this text box will cause input validation.
 -	 */
 -	public function setCausesValidation($value)
 -	{
 -		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return integer the display width of the text box in characters, default is 0 meaning not set.
 -	 */
 -	public function getColumns()
 -	{
 -		return $this->getViewState('Columns',0);
 -	}
 -
 -	/**
 -	 * Sets the display width of the text box in characters.
 -	 * @param integer the display width, set it 0 to clear the setting
 -	 */
 -	public function setColumns($value)
 -	{
 -		$this->setViewState('Columns',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return integer the maximum number of characters allowed in the text box, default is 0 meaning not set.
 -	 */
 -	public function getMaxLength()
 -	{
 -		return $this->getViewState('MaxLength',0);
 -	}
 -
 -	/**
 -	 * Sets the maximum number of characters allowed in the text box.
 -	 * @param integer the maximum length,  set it 0 to clear the setting
 -	 */
 -	public function setMaxLength($value)
 -	{
 -		$this->setViewState('MaxLength',TPropertyValue::ensureInteger($value),0);
 -	}
 -
 -	/**
 -	 * @return boolean whether the textbox is read only, default is false.
 -	 */
 -	public function getReadOnly()
 -	{
 -		return $this->getViewState('ReadOnly',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the textbox is read only
 -	 */
 -	public function setReadOnly($value)
 -	{
 -		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return integer the number of rows displayed in a multiline text box, default is 4
 -	 */
 -	public function getRows()
 -	{
 -		return $this->getViewState('Rows',self::DEFAULT_ROWS);
 -	}
 -
 -	/**
 -	 * Sets the number of rows displayed in a multiline text box.
 -	 * @param integer the number of rows
 -	 */
 -	public function setRows($value)
 -	{
 -		$this->setViewState('Rows',TPropertyValue::ensureInteger($value),self::DEFAULT_ROWS);
 -	}
 -
 -	/**
 -	 * @return boolean whether password should be displayed in the textbox during postback. Defaults to false. This property only applies when TextMode='Password'.
 -	 */
 -	public function getPersistPassword()
 -	{
 -		return $this->getViewState('PersistPassword',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether password should be displayed in the textbox during postback. This property only applies when TextMode='Password'.
 -	 */
 -	public function setPersistPassword($value)
 -	{
 -		$this->setViewState('PersistPassword',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return string the text content of the TTextBox control.
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * Sets the text content of the TTextBox control.
 -	 * @param string the text content
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value,'');
 -		$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
 -	 */
 -	public function getSafeText()
 -	{
 -		if($this->_safeText===null)
 -			$this->_safeText=$this->getSafeTextParser()->parse($this->getText());
 -		return $this->_safeText;
 -	}
 -
 -	/**
 -	 * @return mixed safe text parser
 -	 */
 -	protected function getSafeTextParser()
 -	{
 -		if(!self::$_safeTextParser)
 -			self::$_safeTextParser=Prado::createComponent('System.3rdParty.SafeHtml.TSafeHtmlParser');
 -		return self::$_safeTextParser;
 -	}
 -
 -	/**
 -	 * @return TTextBoxMode the behavior mode of the TTextBox component. Defaults to TTextBoxMode::SingleLine.
 -	 */
 -	public function getTextMode()
 -	{
 -		return $this->getViewState('TextMode',TTextBoxMode::SingleLine);
 -	}
 -
 -	/**
 -	 * Sets the behavior mode of the TTextBox component.
 -	 * @param TTextBoxMode the text mode
 -	 * @throws TInvalidDataValueException if the input value is not a valid text mode.
 -	 */
 -	public function setTextMode($value)
 -	{
 -		$this->setViewState('TextMode',TPropertyValue::ensureEnum($value,'TTextBoxMode'),TTextBoxMode::SingleLine);
 -	}
 -
 -	/**
 -	 * @return string the group of validators which the text box causes validation upon postback
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group of validators which the text box causes validation upon postback
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	/**
 -	 * @return boolean whether the text content wraps within a multiline text box. Defaults to true.
 -	 */
 -	public function getWrap()
 -	{
 -		return $this->getViewState('Wrap',true);
 -	}
 -
 -	/**
 -	 * Sets the value indicating whether the text content wraps within a multiline text box.
 -	 * @param boolean whether the text content wraps within a multiline text box.
 -	 */
 -	public function setWrap($value)
 -	{
 -		$this->setViewState('Wrap',TPropertyValue::ensureBoolean($value),true);
 -	}
 -}
 -
 -/**
 - * TTextBoxMode class.
 - * TTextBoxMode defines the enumerable type for the possible mode
 - * that a {@link TTextBox} control could be at.
 - *
 - * The following enumerable values are defined:
 - * - SingleLine: the textbox will be a regular single line input
 - * - MultiLine: the textbox will be a textarea allowing multiple line input
 - * - Password: the textbox will hide user input like a password input box
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTextBoxMode extends TEnumerable
 -{
 -	const SingleLine='SingleLine';
 -	const MultiLine='MultiLine';
 -	const Password='Password';
 -}
 -
 -/**
 - * TTextBoxAutoCompleteType class.
 - * TTextBoxAutoCompleteType defines the possible AutoComplete type that is supported
 - * by a {@link TTextBox} control.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TTextBoxAutoCompleteType extends TEnumerable
 -{
 -	const BusinessCity='BusinessCity';
 -	const BusinessCountryRegion='BusinessCountryRegion';
 -	const BusinessFax='BusinessFax';
 -	const BusinessPhone='BusinessPhone';
 -	const BusinessState='BusinessState';
 -	const BusinessStreetAddress='BusinessStreetAddress';
 -	const BusinessUrl='BusinessUrl';
 -	const BusinessZipCode='BusinessZipCode';
 -	const Cellular='Cellular';
 -	const Company='Company';
 -	const Department='Department';
 -	const Disabled='Disabled';
 -	const DisplayName='DisplayName';
 -	const Email='Email';
 -	const FirstName='FirstName';
 -	const Gender='Gender';
 -	const HomeCity='HomeCity';
 -	const HomeCountryRegion='HomeCountryRegion';
 -	const HomeFax='HomeFax';
 -	const Homepage='Homepage';
 -	const HomePhone='HomePhone';
 -	const HomeState='HomeState';
 -	const HomeStreetAddress='HomeStreetAddress';
 -	const HomeZipCode='HomeZipCode';
 -	const JobTitle='JobTitle';
 -	const LastName='LastName';
 -	const MiddleName='MiddleName';
 -	const None='None';
 -	const Notes='Notes';
 -	const Office='Office';
 -	const Pager='Pager';
 -	const Search='Search';
 -}
 -
 +<?php +/** + * TTextBox class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TTextBox class + * + * TTextBox displays a text box on the Web page for user input. + * The text displayed in the TTextBox control is determined by the + * {@link setText Text} property. You can create a <b>SingleLine</b>, + * a <b>MultiLine</b>, or a <b>Password</b> text box by setting + * the {@link setTextMode TextMode} property. If the TTextBox control + * is a multiline text box, the number of rows it displays is determined + * by the {@link setRows Rows} property, and the {@link setWrap Wrap} property + * can be used to determine whether to wrap the text in the component. + * + * To specify the display width of the text box, in characters, set + * the {@link setColumns Columns} property. To prevent the text displayed + * in the component from being modified, set the {@link setReadOnly ReadOnly} + * property to true. If you want to limit the user input to a specified number + * of characters, set the {@link setMaxLength MaxLength} property. + * To use AutoComplete feature, set the {@link setAutoCompleteType AutoCompleteType} property. + * + * If {@link setAutoPostBack AutoPostBack} is set true, updating the text box + * and then changing the focus out of it will cause postback action. + * And if {@link setCausesValidation CausesValidation} is true, validation will + * also be processed, which can be further restricted within + * a {@link setValidationGroup ValidationGroup}. + * + * WARNING: Be careful if you want to display the text collected via TTextBox. + * Malicious cross-site script may be injected in. You may use {@link getSafeText SafeText} + * to prevent this problem. + * + * NOTE: If you set {@link setWrap Wrap} to false or use {@link setAutoCompleteType AutoCompleteType}, + * the generated HTML output for the textbox will not be XHTML-compatible. + * Currently, no alternatives are available. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable, IDataRenderer +{ +	/** +	 * Default number of rows (for MultiLine text box) +	 */ +	const DEFAULT_ROWS=4; +	/** +	 * Default number of columns (for MultiLine text box) +	 */ +	const DEFAULT_COLUMNS=20; +	/** +	 * @var mixed safe text parser +	 */ +	private static $_safeTextParser=null; +	/** +	 * @var string safe textbox content with javascript stripped off +	 */ +	private $_safeText; +	private $_dataChanged=false; +	private $_isValid=true; + +	/** +	 * @return string tag name of the textbox +	 */ +	protected function getTagName() +	{ +		return ($this->getTextMode()==='MultiLine')?'textarea':'input'; +	} + +	/** +	 * @return boolean whether to render javascript. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether to render javascript. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * Adds attribute name-value pairs to renderer. +	 * This method overrides the parent implementation with additional textbox specific attributes. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function addAttributesToRender($writer) +	{ +		$page=$this->getPage(); +		$page->ensureRenderInForm($this); +		if(($uid=$this->getUniqueID())!=='') +			$writer->addAttribute('name',$uid); +		if(($textMode=$this->getTextMode())===TTextBoxMode::MultiLine) +		{ +			if(($rows=$this->getRows())<=0) +				$rows=self::DEFAULT_ROWS; +			if(($cols=$this->getColumns())<=0) +				$cols=self::DEFAULT_COLUMNS; +			$writer->addAttribute('rows',"$rows"); +			$writer->addAttribute('cols',"$cols"); +			if(!$this->getWrap()) +				$writer->addAttribute('wrap','off'); +		} +		else +		{ +			if($textMode===TTextBoxMode::SingleLine) +			{ +				$writer->addAttribute('type','text'); +				if(($text=$this->getText())!=='') +					$writer->addAttribute('value',$text); +			} +			else +			{ +				if($this->getPersistPassword() && ($text=$this->getText())!=='') +					$writer->addAttribute('value',$text); +				$writer->addAttribute('type','password'); +			} + +			if(($act=$this->getAutoCompleteType())!=='None') +			{ +				if($act==='Disabled') +					$writer->addAttribute('autocomplete','off'); +				else if($act==='Search') +					$writer->addAttribute('vcard_name','search'); +				else if($act==='HomeCountryRegion') +					$writer->addAttribute('vcard_name','HomeCountry'); +				else if($act==='BusinessCountryRegion') +					$writer->addAttribute('vcard_name','BusinessCountry'); +				else +				{ +					if(strpos($act,'Business')===0) +						$act='Business'.'.'.substr($act,8); +					else if(strpos($act,'Home')===0) +						$act='Home'.'.'.substr($act,4); +					$writer->addAttribute('vcard_name','vCard.'.$act); +				} +			} + +			if(($cols=$this->getColumns())>0) +				$writer->addAttribute('size',"$cols"); +			if(($maxLength=$this->getMaxLength())>0) +				$writer->addAttribute('maxlength',"$maxLength"); +		} +		if($this->getReadOnly()) +			$writer->addAttribute('readonly','readonly'); +		$isEnabled=$this->getEnabled(true); +		if(!$isEnabled && $this->getEnabled())  // in this case parent will not render 'disabled' +			$writer->addAttribute('disabled','disabled'); +		if($isEnabled +			&& $this->getEnableClientScript() +			&& ( $this->getAutoPostBack() || $textMode===TTextBoxMode::SingleLine) +			&& $page->getClientSupportsJavaScript()) +		{ +			$this->renderClientControlScript($writer); +		} +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Renders the javascript for textbox. +	 */ +	protected function renderClientControlScript($writer) +	{ +		$writer->addAttribute('id',$this->getClientID()); +		$cs = $this->getPage()->getClientScript(); +		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions()); +	} + +	/** +	 * Gets the name of the javascript class responsible for performing postback for this control. +	 * This method overrides the parent implementation. +	 * @return string the javascript class name +	 */ +	protected function getClientClassName() +	{ +		return 'Prado.WebUI.TTextBox'; +	} + +	/** +	 * Gets the post back options for this textbox. +	 * @return array +	 */ +	protected function getPostBackOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['EventTarget'] = $this->getUniqueID(); +		$options['AutoPostBack'] = $this->getAutoPostBack(); +		$options['CausesValidation'] = $this->getCausesValidation(); +		$options['ValidationGroup'] = $this->getValidationGroup(); +		$options['TextMode'] = $this->getTextMode(); +		return $options; +	} + +	/** +	 * Loads user input data. +	 * This method is primarly used by framework developers. +	 * @param string the key that can be used to retrieve data from the input data collection +	 * @param array the input data collection +	 * @return boolean whether the data of the component has been changed +	 */ +	public function loadPostData($key,$values) +	{ +		$value=$values[$key]; +		if($this->getAutoTrim()) +			$value=trim($value); +		if(!$this->getReadOnly() && $this->getText()!==$value) +		{ +			$this->setText($value); +			return $this->_dataChanged=true; +		} +		else +			return false; +	} + +	/** +	 * Returns a value indicating whether postback has caused the control data change. +	 * This method is required by the IPostBackDataHandler interface. +	 * @return boolean whether postback has caused the control data change. False if the page is not in postback mode. +	 */ +	public function getDataChanged() +	{ +		return $this->_dataChanged; +	} + +	/** +	 * Returns the value to be validated. +	 * This methid is required by IValidatable interface. +	 * @return mixed the value of the property to be validated. +	 */ +	public function getValidationPropertyValue() +	{ +		return $this->getText(); +	} + +	/** +	 * Returns true if this control validated successfully. +	 * Defaults to true. +	 * @return bool wether this control validated successfully. +	 */ +	public function getIsValid() +	{ +	    return $this->_isValid; +	} +	/** +	 * @param bool wether this control is valid. +	 */ +	public function setIsValid($value) +	{ +	    $this->_isValid=TPropertyValue::ensureBoolean($value); +	} + +	/** +	 * Raises <b>OnTextChanged</b> event. +	 * This method is invoked when the value of the {@link getText Text} +	 * property changes on postback. +	 * If you override this method, be sure to call the parent implementation to ensure +	 * the invocation of the attached event handlers. +	 * @param TEventParameter event parameter to be passed to the event handlers +	 */ +	public function onTextChanged($param) +	{ +		$this->raiseEvent('OnTextChanged',$this,$param); +	} + +	/** +	 * Raises postdata changed event. +	 * This method is required by {@link IPostBackDataHandler} interface. +	 * It is invoked by the framework when {@link getText Text} property +	 * is changed on postback. +	 * This method is primarly used by framework developers. +	 */ +	public function raisePostDataChangedEvent() +	{ +		if($this->getAutoPostBack() && $this->getCausesValidation()) +			$this->getPage()->validate($this->getValidationGroup()); +		$this->onTextChanged(null); +	} + +	/** +	 * Renders the body content of the textbox when it is in MultiLine text mode. +	 * @param THtmlWriter the writer for rendering +	 */ +	public function renderContents($writer) +	{ +		if($this->getTextMode()==='MultiLine') +			$writer->write(THttpUtility::htmlEncode($this->getText())); +	} + +	/** +	 * Renders an additional line-break after the opening tag when it +	 * is in MultiLine text mode. +	 * @param THtmlWriter the writer used for the rendering purpose^M +	 */ +	public function renderBeginTag($writer) +	{ +		parent::renderBeginTag($writer); +		if($this->getTextMode()==='MultiLine') +			$writer->write("\n"); +	} + +	/** +	 * @return TTextBoxAutoCompleteType the AutoComplete type of the textbox +	 */ +	public function getAutoCompleteType() +	{ +		return $this->getViewState('AutoCompleteType',TTextBoxAutoCompleteType::None); +	} + +	/** +	 * @param TTextBoxAutoCompleteType the AutoComplete type of the textbox, default value is TTextBoxAutoCompleteType::None. +	 * @throws TInvalidDataValueException if the input parameter is not a valid AutoComplete type +	 */ +	public function setAutoCompleteType($value) +	{ +		$this->setViewState('AutoCompleteType',TPropertyValue::ensureEnum($value,'TTextBoxAutoCompleteType'),TTextBoxAutoCompleteType::None); +	} + +	/** +	 * @return boolean a value indicating whether an automatic postback to the server +     * will occur whenever the user modifies the text in the TTextBox control and +     * then tabs out of the component. Defaults to false. +	 */ +	public function getAutoPostBack() +	{ +		return $this->getViewState('AutoPostBack',false); +	} + +	/** +	 * Sets the value indicating if postback automatically. +	 * An automatic postback to the server will occur whenever the user +	 * modifies the text in the TTextBox control and then tabs out of the component. +	 * @param boolean the value indicating if postback automatically +	 */ +	public function setAutoPostBack($value) +	{ +		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean a value indicating whether the input text should be trimmed spaces. Defaults to false. +	 */ +	public function getAutoTrim() +	{ +		return $this->getViewState('AutoTrim',false); +	} + +	/** +	 * Sets the value indicating if the input text should be trimmed spaces +	 * @param boolean the value indicating if the input text should be trimmed spaces +	 */ +	public function setAutoTrim($value) +	{ +		$this->setViewState('AutoTrim',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether postback event trigger by this text box will cause input validation, default is true. +	 */ +	public function getCausesValidation() +	{ +		return $this->getViewState('CausesValidation',true); +	} + +	/** +	 * @param boolean whether postback event trigger by this text box will cause input validation. +	 */ +	public function setCausesValidation($value) +	{ +		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return integer the display width of the text box in characters, default is 0 meaning not set. +	 */ +	public function getColumns() +	{ +		return $this->getViewState('Columns',0); +	} + +	/** +	 * Sets the display width of the text box in characters. +	 * @param integer the display width, set it 0 to clear the setting +	 */ +	public function setColumns($value) +	{ +		$this->setViewState('Columns',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return integer the maximum number of characters allowed in the text box, default is 0 meaning not set. +	 */ +	public function getMaxLength() +	{ +		return $this->getViewState('MaxLength',0); +	} + +	/** +	 * Sets the maximum number of characters allowed in the text box. +	 * @param integer the maximum length,  set it 0 to clear the setting +	 */ +	public function setMaxLength($value) +	{ +		$this->setViewState('MaxLength',TPropertyValue::ensureInteger($value),0); +	} + +	/** +	 * @return boolean whether the textbox is read only, default is false. +	 */ +	public function getReadOnly() +	{ +		return $this->getViewState('ReadOnly',false); +	} + +	/** +	 * @param boolean whether the textbox is read only +	 */ +	public function setReadOnly($value) +	{ +		$this->setViewState('ReadOnly',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return integer the number of rows displayed in a multiline text box, default is 4 +	 */ +	public function getRows() +	{ +		return $this->getViewState('Rows',self::DEFAULT_ROWS); +	} + +	/** +	 * Sets the number of rows displayed in a multiline text box. +	 * @param integer the number of rows +	 */ +	public function setRows($value) +	{ +		$this->setViewState('Rows',TPropertyValue::ensureInteger($value),self::DEFAULT_ROWS); +	} + +	/** +	 * @return boolean whether password should be displayed in the textbox during postback. Defaults to false. This property only applies when TextMode='Password'. +	 */ +	public function getPersistPassword() +	{ +		return $this->getViewState('PersistPassword',false); +	} + +	/** +	 * @param boolean whether password should be displayed in the textbox during postback. This property only applies when TextMode='Password'. +	 */ +	public function setPersistPassword($value) +	{ +		$this->setViewState('PersistPassword',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return string the text content of the TTextBox control. +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * Sets the text content of the TTextBox control. +	 * @param string the text content +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value,''); +		$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 +	 */ +	public function getSafeText() +	{ +		if($this->_safeText===null) +			$this->_safeText=$this->getSafeTextParser()->parse($this->getText()); +		return $this->_safeText; +	} + +	/** +	 * @return mixed safe text parser +	 */ +	protected function getSafeTextParser() +	{ +		if(!self::$_safeTextParser) +			self::$_safeTextParser=Prado::createComponent('System.3rdParty.SafeHtml.TSafeHtmlParser'); +		return self::$_safeTextParser; +	} + +	/** +	 * @return TTextBoxMode the behavior mode of the TTextBox component. Defaults to TTextBoxMode::SingleLine. +	 */ +	public function getTextMode() +	{ +		return $this->getViewState('TextMode',TTextBoxMode::SingleLine); +	} + +	/** +	 * Sets the behavior mode of the TTextBox component. +	 * @param TTextBoxMode the text mode +	 * @throws TInvalidDataValueException if the input value is not a valid text mode. +	 */ +	public function setTextMode($value) +	{ +		$this->setViewState('TextMode',TPropertyValue::ensureEnum($value,'TTextBoxMode'),TTextBoxMode::SingleLine); +	} + +	/** +	 * @return string the group of validators which the text box causes validation upon postback +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group of validators which the text box causes validation upon postback +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	/** +	 * @return boolean whether the text content wraps within a multiline text box. Defaults to true. +	 */ +	public function getWrap() +	{ +		return $this->getViewState('Wrap',true); +	} + +	/** +	 * Sets the value indicating whether the text content wraps within a multiline text box. +	 * @param boolean whether the text content wraps within a multiline text box. +	 */ +	public function setWrap($value) +	{ +		$this->setViewState('Wrap',TPropertyValue::ensureBoolean($value),true); +	} +} + +/** + * TTextBoxMode class. + * TTextBoxMode defines the enumerable type for the possible mode + * that a {@link TTextBox} control could be at. + * + * The following enumerable values are defined: + * - SingleLine: the textbox will be a regular single line input + * - MultiLine: the textbox will be a textarea allowing multiple line input + * - Password: the textbox will hide user input like a password input box + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTextBoxMode extends TEnumerable +{ +	const SingleLine='SingleLine'; +	const MultiLine='MultiLine'; +	const Password='Password'; +} + +/** + * TTextBoxAutoCompleteType class. + * TTextBoxAutoCompleteType defines the possible AutoComplete type that is supported + * by a {@link TTextBox} control. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TTextBoxAutoCompleteType extends TEnumerable +{ +	const BusinessCity='BusinessCity'; +	const BusinessCountryRegion='BusinessCountryRegion'; +	const BusinessFax='BusinessFax'; +	const BusinessPhone='BusinessPhone'; +	const BusinessState='BusinessState'; +	const BusinessStreetAddress='BusinessStreetAddress'; +	const BusinessUrl='BusinessUrl'; +	const BusinessZipCode='BusinessZipCode'; +	const Cellular='Cellular'; +	const Company='Company'; +	const Department='Department'; +	const Disabled='Disabled'; +	const DisplayName='DisplayName'; +	const Email='Email'; +	const FirstName='FirstName'; +	const Gender='Gender'; +	const HomeCity='HomeCity'; +	const HomeCountryRegion='HomeCountryRegion'; +	const HomeFax='HomeFax'; +	const Homepage='Homepage'; +	const HomePhone='HomePhone'; +	const HomeState='HomeState'; +	const HomeStreetAddress='HomeStreetAddress'; +	const HomeZipCode='HomeZipCode'; +	const JobTitle='JobTitle'; +	const LastName='LastName'; +	const MiddleName='MiddleName'; +	const None='None'; +	const Notes='Notes'; +	const Office='Office'; +	const Pager='Pager'; +	const Search='Search'; +} + diff --git a/framework/Web/UI/WebControls/TTextProcessor.php b/framework/Web/UI/WebControls/TTextProcessor.php index 6d95a482..60d047fe 100644 --- a/framework/Web/UI/WebControls/TTextProcessor.php +++ b/framework/Web/UI/WebControls/TTextProcessor.php @@ -1,86 +1,86 @@ -<?php
 -/**
 - * TTextProcessor class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TTextProcessor class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TTextProcessor class.
 - *
 - * TTextProcessor is the base class for classes that process or transform
 - * text content into different forms. The text content to be processed
 - * is specified by {@link setText Text} property. If it is not set, the body
 - * content enclosed within the processor control will be processed and rendered.
 - * The body content includes static text strings and the rendering result
 - * of child controls.
 - *
 - * Note, all child classes must implement {@link processText} method.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI
 - * @since 3.0.1
 - */
 -abstract class TTextProcessor extends TWebControl
 -{
 -	/**
 -	 * Processes a text string.
 -	 * This method must be implemented by child classes.
 -	 * @param string text string to be processed
 -	 * @return string the processed text result
 -	 */
 -	abstract public function processText($text);
 -
 -	/**
 -	 * HTML-decodes static text.
 -	 * This method overrides parent implementation.
 -	 * @param mixed object to be added as body content
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if(is_string($object))
 -			$object=html_entity_decode($object,ENT_QUOTES,'UTF-8');
 -		parent::addParsedObject($object);
 -	}
 -
 -	/**
 -	 * @return string text to be processed
 -	 */
 -	public function getText()
 -	{
 -		return $this->getViewState('Text','');
 -	}
 -
 -	/**
 -	 * @param string text to be processed
 -	 */
 -	public function setText($value)
 -	{
 -		$this->setViewState('Text',$value);
 -	}
 -
 -	/**
 -	 * Renders body content.
 -	 * This method overrides the parent implementation by replacing
 -	 * the body content with the processed text content.
 -	 * @param THtmlWriter writer
 -	 */
 -	public function renderContents($writer)
 -	{
 -		if(($text=$this->getText())==='' && $this->getHasControls())
 -		{
 -			$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), new TTextWriter());
 -			parent::renderContents($htmlWriter);
 -			$text=$htmlWriter->flush();
 -		}
 -		if($text!=='')
 -			$writer->write($this->processText($text));
 -	}
 -
 -}
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TTextProcessor class. + * + * TTextProcessor is the base class for classes that process or transform + * text content into different forms. The text content to be processed + * is specified by {@link setText Text} property. If it is not set, the body + * content enclosed within the processor control will be processed and rendered. + * The body content includes static text strings and the rendering result + * of child controls. + * + * Note, all child classes must implement {@link processText} method. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI + * @since 3.0.1 + */ +abstract class TTextProcessor extends TWebControl +{ +	/** +	 * Processes a text string. +	 * This method must be implemented by child classes. +	 * @param string text string to be processed +	 * @return string the processed text result +	 */ +	abstract public function processText($text); + +	/** +	 * HTML-decodes static text. +	 * This method overrides parent implementation. +	 * @param mixed object to be added as body content +	 */ +	public function addParsedObject($object) +	{ +		if(is_string($object)) +			$object=html_entity_decode($object,ENT_QUOTES,'UTF-8'); +		parent::addParsedObject($object); +	} + +	/** +	 * @return string text to be processed +	 */ +	public function getText() +	{ +		return $this->getViewState('Text',''); +	} + +	/** +	 * @param string text to be processed +	 */ +	public function setText($value) +	{ +		$this->setViewState('Text',$value); +	} + +	/** +	 * Renders body content. +	 * This method overrides the parent implementation by replacing +	 * the body content with the processed text content. +	 * @param THtmlWriter writer +	 */ +	public function renderContents($writer) +	{ +		if(($text=$this->getText())==='' && $this->getHasControls()) +		{ +			$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), new TTextWriter()); +			parent::renderContents($htmlWriter); +			$text=$htmlWriter->flush(); +		} +		if($text!=='') +			$writer->write($this->processText($text)); +	} + +} diff --git a/framework/Web/UI/WebControls/TValidationSummary.php b/framework/Web/UI/WebControls/TValidationSummary.php index 6c258927..c915d163 100644 --- a/framework/Web/UI/WebControls/TValidationSummary.php +++ b/framework/Web/UI/WebControls/TValidationSummary.php @@ -1,536 +1,536 @@ -<?php
 -/**
 - * TValidationSummary class file
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TValidationSummary class
 - *
 - * TValidationSummary displays a summary of validation errors inline on a Web page,
 - * in a message box, or both. By default, a validation summary will collect
 - * {@link TBaseValidator::getErrorMessage ErrorMessage} of all failed validators
 - * on the page. If {@link getValidationGroup ValidationGroup} is not
 - * empty, only those validators who belong to the group will show their error messages
 - * in the summary.
 - *
 - * The summary can be displayed as a list, as a bulleted list, or as a single
 - * paragraph based on the {@link setDisplayMode DisplayMode} property.
 - * The messages shown can be prefixed with {@link setHeaderText HeaderText}.
 - *
 - * The summary can be displayed on the Web page and in a message box by setting
 - * the {@link setShowSummary ShowSummary} and {@link setShowMessageBox ShowMessageBox}
 - * properties, respectively. Note, the latter is only effective when
 - * {@link setEnableClientScript EnableClientScript} is true.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TValidationSummary extends TWebControl
 -{
 -	/**
 -	 * @var TClientSideValidationSummaryOptions validation client side options.
 -	 */
 -	private $_clientSide;
 -
 -	/**
 -	 * Constructor.
 -	 * This method sets the foreground color to red.
 -	 */
 -	public function __construct()
 -	{
 -		parent::__construct();
 -		$this->setForeColor('red');
 -	}
 -
 -	/**
 -	 * @return TValidationSummaryDisplayStyle the style of displaying the error messages. Defaults to TValidationSummaryDisplayStyle::Fixed.
 -	 */
 -	public function getDisplay()
 -	{
 -		return $this->getViewState('Display',TValidationSummaryDisplayStyle::Fixed);
 -	}
 -
 -	/**
 -	 * @param TValidationSummaryDisplayStyle the style of displaying the error messages
 -	 */
 -	public function setDisplay($value)
 -	{
 -		$this->setViewState('Display',TPropertyValue::ensureEnum($value,'TValidationSummaryDisplayStyle'),TValidationSummaryDisplayStyle::Fixed);
 -	}
 -
 -	/**
 -	 * @return string the header text displayed at the top of the summary
 -	 */
 -	public function getHeaderText()
 -	{
 -		return $this->getViewState('HeaderText','');
 -	}
 -
 -	/**
 -	 * Sets the header text to be displayed at the top of the summary
 -	 * @param string the header text
 -	 */
 -	public function setHeaderText($value)
 -	{
 -		$this->setViewState('HeaderText',$value,'');
 -	}
 -
 -	/**
 -	 * @return TValidationSummaryDisplayMode the mode of displaying error messages. Defaults to TValidationSummaryDisplayMode::BulletList.
 -	 */
 -	public function getDisplayMode()
 -	{
 -		return $this->getViewState('DisplayMode',TValidationSummaryDisplayMode::BulletList);
 -	}
 -
 -	/**
 -	 * @param TValidationSummaryDisplayMode the mode of displaying error messages
 -	 */
 -	public function setDisplayMode($value)
 -	{
 -		$this->setViewState('DisplayMode',TPropertyValue::ensureEnum($value,'TValidationSummaryDisplayMode'),TValidationSummaryDisplayMode::BulletList);
 -	}
 -
 -	/**
 -	 * @return boolean whether the TValidationSummary component updates itself using client-side script. Defaults to true.
 -	 */
 -	public function getEnableClientScript()
 -	{
 -		return $this->getViewState('EnableClientScript',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether the TValidationSummary component updates itself using client-side script.
 -	 */
 -	public function setEnableClientScript($value)
 -	{
 -		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return boolean whether the validation summary is displayed in a message box. Defaults to false.
 -	 */
 -	public function getShowMessageBox()
 -	{
 -		return $this->getViewState('ShowMessageBox',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the validation summary is displayed in a message box.
 -	 */
 -	public function setShowMessageBox($value)
 -	{
 -		$this->setViewState('ShowMessageBox',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether the validation summary is displayed inline. Defaults to true.
 -	 */
 -	public function getShowSummary()
 -	{
 -		return $this->getViewState('ShowSummary',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether the validation summary is displayed inline.
 -	 */
 -	public function setShowSummary($value)
 -	{
 -		$this->setViewState('ShowSummary',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return boolean whether scroll summary into viewport or not. Defaults to true.
 -	 */
 -	public function getScrollToSummary()
 -	{
 -		return $this->getViewState('ScrollToSummary',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether scroll summary into viewport or not.
 -	 */
 -	public function setScrollToSummary($value)
 -	{
 -		$this->setViewState('ScrollToSummary',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return boolean whether the validation summary should be anchored. Defaults to false.
 -	 */
 -	public function getShowAnchor()
 -	{
 -		return $this->getViewState('ShowAnchor',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether the validation summary should be anchored.
 -	 */
 -	public function setShowAnchor($value)
 -	{
 -		$this->setViewState('ShowAnchor',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * Gets the auto-update for this summary.
 -	 * @return boolean automatic client-side summary updates. Defaults to true.
 -	 */
 -	public function getAutoUpdate()
 -	{
 -		return $this->getViewState('AutoUpdate', true);
 -	}
 -
 -	/**
 -	 * Sets the summary to auto-update on the client-side
 -	 * @param boolean true for automatic summary updates.
 -	 */
 -	public function setAutoUpdate($value)
 -	{
 -		$this->setViewState('AutoUpdate', TPropertyValue::ensureBoolean($value), true);
 -	}
 -
 -	/**
 -	 * @return string the group which this validator belongs to
 -	 */
 -	public function getValidationGroup()
 -	{
 -		return $this->getViewState('ValidationGroup','');
 -	}
 -
 -	/**
 -	 * @param string the group which this validator belongs to
 -	 */
 -	public function setValidationGroup($value)
 -	{
 -		$this->setViewState('ValidationGroup',$value,'');
 -	}
 -
 -	protected function addAttributesToRender($writer)
 -	{
 -		$display=$this->getDisplay();
 -		$visible=$this->getEnabled(true) && count($this->getErrorMessages()) > 0;
 -		if(!$visible)
 -		{
 -			if($display===TValidationSummaryDisplayStyle::None || $display===TValidationSummaryDisplayStyle::Dynamic)
 -				$writer->addStyleAttribute('display','none');
 -			else
 -				$writer->addStyleAttribute('visibility','hidden');
 -		}
 -		$writer->addAttribute('id',$this->getClientID());
 -		parent::addAttributesToRender($writer);
 -	}
 -
 -	/**
 -	 * Render the javascript for validation summary.
 -	 * @param array list of options for validation summary.
 -	 */
 -	protected function renderJsSummary()
 -	{
 -		if(!$this->getEnabled(true) || !$this->getEnableClientScript())
 -			return;
 -		$cs = $this->getPage()->getClientScript();
 -		$cs->registerPradoScript('validator');
 -
 -		//need to register the validation manager is validation summary is alone.
 -		$formID=$this->getPage()->getForm()->getClientID();
 -		$scriptKey = "TBaseValidator:$formID";
 -		if($this->getEnableClientScript() && !$cs->isEndScriptRegistered($scriptKey))
 -		{
 -			$manager['FormID'] = $formID;
 -			$options = TJavaScript::encode($manager);
 -			$cs->registerPradoScript('validator');
 -			$cs->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});");
 -		}
 -
 -
 -		$options=TJavaScript::encode($this->getClientScriptOptions());
 -		$script = "new Prado.WebUI.TValidationSummary({$options});";
 -		$cs->registerEndScript($this->getClientID(), $script);
 -	}
 -
 -	/**
 -	 * Get a list of options for the client-side javascript validation summary.
 -	 * @return array list of options for the summary
 -	 */
 -	protected function getClientScriptOptions()
 -	{
 -		$options['ID'] = $this->getClientID();
 -		$options['FormID'] = $this->getPage()->getForm()->getClientID();
 -		if($this->getShowMessageBox())
 -			$options['ShowMessageBox']=true;
 -		if(!$this->getShowSummary())
 -			$options['ShowSummary']=false;
 -
 -		$options['ScrollToSummary']=$this->getScrollToSummary();
 -		$options['HeaderText']=$this->getHeaderText();
 -		$options['DisplayMode']=$this->getDisplayMode();
 -
 -		$options['Refresh'] = $this->getAutoUpdate();
 -		$options['ValidationGroup'] =  $this->getValidationGroup();
 -		$options['Display'] = $this->getDisplay();
 -
 -		if($this->_clientSide!==null)
 -			$options = array_merge($options,$this->_clientSide->getOptions()->toArray());
 -
 -		return $options;
 -	}
 -
 -	/**
 -	 * @return TClientSideValidationSummaryOptions client-side validation summary
 -	 * event options.
 -	 */
 -	public function getClientSide()
 -	{
 -		if($this->_clientSide===null)
 -			$this->_clientSide = $this->createClientScript();
 -		return $this->_clientSide;
 -	}
 -
 -	/**
 -	 * @return TClientSideValidationSummaryOptions javascript validation summary
 -	 * event options.
 -	 */
 -	protected function createClientScript()
 -	{
 -		return new TClientSideValidationSummaryOptions;
 -	}
 -	/**
 -	 * Get the list of validation error messages.
 -	 * @return array list of validator error messages.
 -	 */
 -	protected function getErrorMessages()
 -	{
 -		$validators=$this->getPage()->getValidators($this->getValidationGroup());
 -		$messages = array();
 -		foreach($validators as $validator)
 -		{
 -			if(!$validator->getIsValid() && ($msg=$validator->getErrorMessage())!=='')
 -				//$messages[] = $validator->getAnchoredMessage($msg);
 -				$messages[] = $msg;
 -		}
 -		return $messages;
 -	}
 -
 -	/**
 -	 * Overrides parent implementation by rendering TValidationSummary-specific presentation.
 -	 * @return string the rendering result
 -	 */
 -	public function renderContents($writer)
 -	{
 -		$this->renderJsSummary();
 -		if($this->getShowSummary())
 -		{
 -//		    $this->setStyle('display:block');
 -			switch($this->getDisplayMode())
 -			{
 -				case TValidationSummaryDisplayMode::SimpleList:
 -					$this->renderList($writer);
 -					break;
 -				case TValidationSummaryDisplayMode::SingleParagraph:
 -					$this->renderSingleParagraph($writer);
 -					break;
 -				case TValidationSummaryDisplayMode::BulletList:
 -					$this->renderBulletList($writer);
 -					break;
 -				case TValidationSummaryDisplayMode::HeaderOnly:
 -					$this->renderHeaderOnly($writer);
 -					break;
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Render the validation summary as a simple list.
 -	 * @param array list of messages
 -	 * @param string the header text
 -	 * @return string summary list
 -	 */
 -	protected function renderList($writer)
 -	{
 -		$header=$this->getHeaderText();
 -		$messages=$this->getErrorMessages();
 -		$content = '';
 -		if(strlen($header))
 -			$content.= $header."<br/>\n";
 -		foreach($messages as $message)
 -			$content.="$message<br/>\n";
 -		$writer->write($content);
 -	}
 -
 -	/**
 -	 * Render the validation summary as a paragraph.
 -	 * @param array list of messages
 -	 * @param string the header text
 -	 * @return string summary paragraph
 -	 */
 -	protected function renderSingleParagraph($writer)
 -	{
 -		$header=$this->getHeaderText();
 -		$messages=$this->getErrorMessages();
 -		$content = $header;
 -		foreach($messages as $message)
 -			$content.= ' '.$message;
 -		$writer->write($content);
 -	}
 -
 -	/**
 -	 * Render the validation summary as a bullet list.
 -	 * @param array list of messages
 -	 * @param string the header text
 -	 * @return string summary bullet list
 -	 */
 -	protected function renderBulletList($writer)
 -	{
 -		$header=$this->getHeaderText();
 -		$messages=$this->getErrorMessages();
 -		$content = $header;
 -		if(count($messages)>0)
 -		{
 -			$content .= "<ul>\n";
 -			foreach($messages as $message)
 -				$content.= '<li>'.$message."</li>\n";
 -			$content .= "</ul>\n";
 -		}
 -		$writer->write($content);
 -	}
 -
 -	/**
 -	 * Render the validation summary header text only.
 -	 * @param THtmlWriter the writer used for the rendering purpose
 -	 */
 -	protected function renderHeaderOnly($writer)
 -	{
 -		$writer->write($this->getHeaderText());
 -	}
 -}
 -
 -/**
 - * TClientSideValidationSummaryOptions class.
 - *
 - * Client-side validation summary events such as {@link setOnHideSummary
 - * OnHideSummary} and {@link setOnShowSummary OnShowSummary} can be modified
 - * through the {@link TBaseValidator:: getClientSide ClientSide} property of a
 - * validation summary.
 - *
 - * The <tt>OnHideSummary</tt> event is raise when the validation summary
 - * requests to hide the messages.
 - *
 - * The <tt>OnShowSummary</tt> event is raised when the validation summary
 - * requests to show the messages.
 - *
 - * See the quickstart documentation for further details.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TClientSideValidationSummaryOptions extends TClientSideOptions
 -{
 -	/**
 -	 * @return string javascript code for client-side OnHideSummary event.
 -	 */
 -	public function getOnHideSummary()
 -	{
 -		return $this->getOption('OnHideSummary');
 -	}
 -
 -	/**
 -	 * Client-side OnHideSummary validation summary event is raise when all the
 -	 * validators are valid. This will override the default client-side
 -	 * validation summary behaviour.
 -	 * @param string javascript code for client-side OnHideSummary event.
 -	 */
 -	public function setOnHideSummary($javascript)
 -	{
 -		$this->setFunction('OnHideSummary', $javascript);
 -	}
 -
 -	/**
 -	 * Client-side OnShowSummary event is raise when one or more validators are
 -	 * not valid. This will override the default client-side validation summary
 -	 * behaviour.
 -	 * @param string javascript code for client-side OnShowSummary event.
 -	 */
 -	public function setOnShowSummary($javascript)
 -	{
 -		$this->setFunction('OnShowSummary', $javascript);
 -	}
 -
 -	/**
 -	 * @return string javascript code for client-side OnShowSummary event.
 -	 */
 -	public function getOnShowSummary()
 -	{
 -		return $this->getOption('OnShowSummary');
 -	}
 -
 -	/**
 -	 * Ensure the string is a valid javascript function. The code block
 -	 * is enclosed with "function(summary, validators){ }" block.
 -	 * @param string javascript code.
 -	 * @return string javascript function code.
 -	 */
 -	protected function ensureFunction($javascript)
 -	{
 -		return "function(summary, validators){ {$javascript} }";
 -	}
 -}
 -
 -
 -/**
 - * TValidationSummaryDisplayMode class.
 - * TValidationSummaryDisplayMode defines the enumerable type for the possible modes
 - * that a {@link TValidationSummary} can organize and display the collected error messages.
 - *
 - * The following enumerable values are defined:
 - * - SimpleList: the error messages are displayed as a list without any decorations.
 - * - SingleParagraph: the error messages are concatenated together into a paragraph.
 - * - BulletList: the error messages are displayed as a bulleted list.
 - * - HeaderOnly: only the HeaderText will be display.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TValidationSummaryDisplayMode extends TEnumerable
 -{
 -	const SimpleList='SimpleList';
 -	const SingleParagraph='SingleParagraph';
 -	const BulletList='BulletList';
 -	const HeaderOnly='HeaderOnly';
 -}
 -
 -
 -/**
 - * TValidationSummaryDisplay class.
 - * TValidationSummaryDisplay defines the enumerable type for the possible styles
 - * that a {@link TValidationSummary} can display the collected error messages.
 - *
 - * The following enumerable values are defined:
 - * - None: the error messages are not displayed
 - * - Dynamic: the error messages are dynamically added to display as the corresponding validators fail
 - * - Fixed: Similar to Dynamic except that the error messages physically occupy the page layout (even though they may not be visible)
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TValidationSummaryDisplayStyle extends TEnumerable
 -{
 -	const None='None';
 -	const Dynamic='Dynamic';
 -	const Fixed='Fixed';
 -}
 -
 +<?php +/** + * TValidationSummary class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TValidationSummary class + * + * TValidationSummary displays a summary of validation errors inline on a Web page, + * in a message box, or both. By default, a validation summary will collect + * {@link TBaseValidator::getErrorMessage ErrorMessage} of all failed validators + * on the page. If {@link getValidationGroup ValidationGroup} is not + * empty, only those validators who belong to the group will show their error messages + * in the summary. + * + * The summary can be displayed as a list, as a bulleted list, or as a single + * paragraph based on the {@link setDisplayMode DisplayMode} property. + * The messages shown can be prefixed with {@link setHeaderText HeaderText}. + * + * The summary can be displayed on the Web page and in a message box by setting + * the {@link setShowSummary ShowSummary} and {@link setShowMessageBox ShowMessageBox} + * properties, respectively. Note, the latter is only effective when + * {@link setEnableClientScript EnableClientScript} is true. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TValidationSummary extends TWebControl +{ +	/** +	 * @var TClientSideValidationSummaryOptions validation client side options. +	 */ +	private $_clientSide; + +	/** +	 * Constructor. +	 * This method sets the foreground color to red. +	 */ +	public function __construct() +	{ +		parent::__construct(); +		$this->setForeColor('red'); +	} + +	/** +	 * @return TValidationSummaryDisplayStyle the style of displaying the error messages. Defaults to TValidationSummaryDisplayStyle::Fixed. +	 */ +	public function getDisplay() +	{ +		return $this->getViewState('Display',TValidationSummaryDisplayStyle::Fixed); +	} + +	/** +	 * @param TValidationSummaryDisplayStyle the style of displaying the error messages +	 */ +	public function setDisplay($value) +	{ +		$this->setViewState('Display',TPropertyValue::ensureEnum($value,'TValidationSummaryDisplayStyle'),TValidationSummaryDisplayStyle::Fixed); +	} + +	/** +	 * @return string the header text displayed at the top of the summary +	 */ +	public function getHeaderText() +	{ +		return $this->getViewState('HeaderText',''); +	} + +	/** +	 * Sets the header text to be displayed at the top of the summary +	 * @param string the header text +	 */ +	public function setHeaderText($value) +	{ +		$this->setViewState('HeaderText',$value,''); +	} + +	/** +	 * @return TValidationSummaryDisplayMode the mode of displaying error messages. Defaults to TValidationSummaryDisplayMode::BulletList. +	 */ +	public function getDisplayMode() +	{ +		return $this->getViewState('DisplayMode',TValidationSummaryDisplayMode::BulletList); +	} + +	/** +	 * @param TValidationSummaryDisplayMode the mode of displaying error messages +	 */ +	public function setDisplayMode($value) +	{ +		$this->setViewState('DisplayMode',TPropertyValue::ensureEnum($value,'TValidationSummaryDisplayMode'),TValidationSummaryDisplayMode::BulletList); +	} + +	/** +	 * @return boolean whether the TValidationSummary component updates itself using client-side script. Defaults to true. +	 */ +	public function getEnableClientScript() +	{ +		return $this->getViewState('EnableClientScript',true); +	} + +	/** +	 * @param boolean whether the TValidationSummary component updates itself using client-side script. +	 */ +	public function setEnableClientScript($value) +	{ +		$this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return boolean whether the validation summary is displayed in a message box. Defaults to false. +	 */ +	public function getShowMessageBox() +	{ +		return $this->getViewState('ShowMessageBox',false); +	} + +	/** +	 * @param boolean whether the validation summary is displayed in a message box. +	 */ +	public function setShowMessageBox($value) +	{ +		$this->setViewState('ShowMessageBox',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether the validation summary is displayed inline. Defaults to true. +	 */ +	public function getShowSummary() +	{ +		return $this->getViewState('ShowSummary',true); +	} + +	/** +	 * @param boolean whether the validation summary is displayed inline. +	 */ +	public function setShowSummary($value) +	{ +		$this->setViewState('ShowSummary',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return boolean whether scroll summary into viewport or not. Defaults to true. +	 */ +	public function getScrollToSummary() +	{ +		return $this->getViewState('ScrollToSummary',true); +	} + +	/** +	 * @param boolean whether scroll summary into viewport or not. +	 */ +	public function setScrollToSummary($value) +	{ +		$this->setViewState('ScrollToSummary',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return boolean whether the validation summary should be anchored. Defaults to false. +	 */ +	public function getShowAnchor() +	{ +		return $this->getViewState('ShowAnchor',false); +	} + +	/** +	 * @param boolean whether the validation summary should be anchored. +	 */ +	public function setShowAnchor($value) +	{ +		$this->setViewState('ShowAnchor',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * Gets the auto-update for this summary. +	 * @return boolean automatic client-side summary updates. Defaults to true. +	 */ +	public function getAutoUpdate() +	{ +		return $this->getViewState('AutoUpdate', true); +	} + +	/** +	 * Sets the summary to auto-update on the client-side +	 * @param boolean true for automatic summary updates. +	 */ +	public function setAutoUpdate($value) +	{ +		$this->setViewState('AutoUpdate', TPropertyValue::ensureBoolean($value), true); +	} + +	/** +	 * @return string the group which this validator belongs to +	 */ +	public function getValidationGroup() +	{ +		return $this->getViewState('ValidationGroup',''); +	} + +	/** +	 * @param string the group which this validator belongs to +	 */ +	public function setValidationGroup($value) +	{ +		$this->setViewState('ValidationGroup',$value,''); +	} + +	protected function addAttributesToRender($writer) +	{ +		$display=$this->getDisplay(); +		$visible=$this->getEnabled(true) && count($this->getErrorMessages()) > 0; +		if(!$visible) +		{ +			if($display===TValidationSummaryDisplayStyle::None || $display===TValidationSummaryDisplayStyle::Dynamic) +				$writer->addStyleAttribute('display','none'); +			else +				$writer->addStyleAttribute('visibility','hidden'); +		} +		$writer->addAttribute('id',$this->getClientID()); +		parent::addAttributesToRender($writer); +	} + +	/** +	 * Render the javascript for validation summary. +	 * @param array list of options for validation summary. +	 */ +	protected function renderJsSummary() +	{ +		if(!$this->getEnabled(true) || !$this->getEnableClientScript()) +			return; +		$cs = $this->getPage()->getClientScript(); +		$cs->registerPradoScript('validator'); + +		//need to register the validation manager is validation summary is alone. +		$formID=$this->getPage()->getForm()->getClientID(); +		$scriptKey = "TBaseValidator:$formID"; +		if($this->getEnableClientScript() && !$cs->isEndScriptRegistered($scriptKey)) +		{ +			$manager['FormID'] = $formID; +			$options = TJavaScript::encode($manager); +			$cs->registerPradoScript('validator'); +			$cs->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});"); +		} + + +		$options=TJavaScript::encode($this->getClientScriptOptions()); +		$script = "new Prado.WebUI.TValidationSummary({$options});"; +		$cs->registerEndScript($this->getClientID(), $script); +	} + +	/** +	 * Get a list of options for the client-side javascript validation summary. +	 * @return array list of options for the summary +	 */ +	protected function getClientScriptOptions() +	{ +		$options['ID'] = $this->getClientID(); +		$options['FormID'] = $this->getPage()->getForm()->getClientID(); +		if($this->getShowMessageBox()) +			$options['ShowMessageBox']=true; +		if(!$this->getShowSummary()) +			$options['ShowSummary']=false; + +		$options['ScrollToSummary']=$this->getScrollToSummary(); +		$options['HeaderText']=$this->getHeaderText(); +		$options['DisplayMode']=$this->getDisplayMode(); + +		$options['Refresh'] = $this->getAutoUpdate(); +		$options['ValidationGroup'] =  $this->getValidationGroup(); +		$options['Display'] = $this->getDisplay(); + +		if($this->_clientSide!==null) +			$options = array_merge($options,$this->_clientSide->getOptions()->toArray()); + +		return $options; +	} + +	/** +	 * @return TClientSideValidationSummaryOptions client-side validation summary +	 * event options. +	 */ +	public function getClientSide() +	{ +		if($this->_clientSide===null) +			$this->_clientSide = $this->createClientScript(); +		return $this->_clientSide; +	} + +	/** +	 * @return TClientSideValidationSummaryOptions javascript validation summary +	 * event options. +	 */ +	protected function createClientScript() +	{ +		return new TClientSideValidationSummaryOptions; +	} +	/** +	 * Get the list of validation error messages. +	 * @return array list of validator error messages. +	 */ +	protected function getErrorMessages() +	{ +		$validators=$this->getPage()->getValidators($this->getValidationGroup()); +		$messages = array(); +		foreach($validators as $validator) +		{ +			if(!$validator->getIsValid() && ($msg=$validator->getErrorMessage())!=='') +				//$messages[] = $validator->getAnchoredMessage($msg); +				$messages[] = $msg; +		} +		return $messages; +	} + +	/** +	 * Overrides parent implementation by rendering TValidationSummary-specific presentation. +	 * @return string the rendering result +	 */ +	public function renderContents($writer) +	{ +		$this->renderJsSummary(); +		if($this->getShowSummary()) +		{ +//		    $this->setStyle('display:block'); +			switch($this->getDisplayMode()) +			{ +				case TValidationSummaryDisplayMode::SimpleList: +					$this->renderList($writer); +					break; +				case TValidationSummaryDisplayMode::SingleParagraph: +					$this->renderSingleParagraph($writer); +					break; +				case TValidationSummaryDisplayMode::BulletList: +					$this->renderBulletList($writer); +					break; +				case TValidationSummaryDisplayMode::HeaderOnly: +					$this->renderHeaderOnly($writer); +					break; +			} +		} +	} + +	/** +	 * Render the validation summary as a simple list. +	 * @param array list of messages +	 * @param string the header text +	 * @return string summary list +	 */ +	protected function renderList($writer) +	{ +		$header=$this->getHeaderText(); +		$messages=$this->getErrorMessages(); +		$content = ''; +		if(strlen($header)) +			$content.= $header."<br/>\n"; +		foreach($messages as $message) +			$content.="$message<br/>\n"; +		$writer->write($content); +	} + +	/** +	 * Render the validation summary as a paragraph. +	 * @param array list of messages +	 * @param string the header text +	 * @return string summary paragraph +	 */ +	protected function renderSingleParagraph($writer) +	{ +		$header=$this->getHeaderText(); +		$messages=$this->getErrorMessages(); +		$content = $header; +		foreach($messages as $message) +			$content.= ' '.$message; +		$writer->write($content); +	} + +	/** +	 * Render the validation summary as a bullet list. +	 * @param array list of messages +	 * @param string the header text +	 * @return string summary bullet list +	 */ +	protected function renderBulletList($writer) +	{ +		$header=$this->getHeaderText(); +		$messages=$this->getErrorMessages(); +		$content = $header; +		if(count($messages)>0) +		{ +			$content .= "<ul>\n"; +			foreach($messages as $message) +				$content.= '<li>'.$message."</li>\n"; +			$content .= "</ul>\n"; +		} +		$writer->write($content); +	} + +	/** +	 * Render the validation summary header text only. +	 * @param THtmlWriter the writer used for the rendering purpose +	 */ +	protected function renderHeaderOnly($writer) +	{ +		$writer->write($this->getHeaderText()); +	} +} + +/** + * TClientSideValidationSummaryOptions class. + * + * Client-side validation summary events such as {@link setOnHideSummary + * OnHideSummary} and {@link setOnShowSummary OnShowSummary} can be modified + * through the {@link TBaseValidator:: getClientSide ClientSide} property of a + * validation summary. + * + * The <tt>OnHideSummary</tt> event is raise when the validation summary + * requests to hide the messages. + * + * The <tt>OnShowSummary</tt> event is raised when the validation summary + * requests to show the messages. + * + * See the quickstart documentation for further details. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TClientSideValidationSummaryOptions extends TClientSideOptions +{ +	/** +	 * @return string javascript code for client-side OnHideSummary event. +	 */ +	public function getOnHideSummary() +	{ +		return $this->getOption('OnHideSummary'); +	} + +	/** +	 * Client-side OnHideSummary validation summary event is raise when all the +	 * validators are valid. This will override the default client-side +	 * validation summary behaviour. +	 * @param string javascript code for client-side OnHideSummary event. +	 */ +	public function setOnHideSummary($javascript) +	{ +		$this->setFunction('OnHideSummary', $javascript); +	} + +	/** +	 * Client-side OnShowSummary event is raise when one or more validators are +	 * not valid. This will override the default client-side validation summary +	 * behaviour. +	 * @param string javascript code for client-side OnShowSummary event. +	 */ +	public function setOnShowSummary($javascript) +	{ +		$this->setFunction('OnShowSummary', $javascript); +	} + +	/** +	 * @return string javascript code for client-side OnShowSummary event. +	 */ +	public function getOnShowSummary() +	{ +		return $this->getOption('OnShowSummary'); +	} + +	/** +	 * Ensure the string is a valid javascript function. The code block +	 * is enclosed with "function(summary, validators){ }" block. +	 * @param string javascript code. +	 * @return string javascript function code. +	 */ +	protected function ensureFunction($javascript) +	{ +		return "function(summary, validators){ {$javascript} }"; +	} +} + + +/** + * TValidationSummaryDisplayMode class. + * TValidationSummaryDisplayMode defines the enumerable type for the possible modes + * that a {@link TValidationSummary} can organize and display the collected error messages. + * + * The following enumerable values are defined: + * - SimpleList: the error messages are displayed as a list without any decorations. + * - SingleParagraph: the error messages are concatenated together into a paragraph. + * - BulletList: the error messages are displayed as a bulleted list. + * - HeaderOnly: only the HeaderText will be display. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TValidationSummaryDisplayMode extends TEnumerable +{ +	const SimpleList='SimpleList'; +	const SingleParagraph='SingleParagraph'; +	const BulletList='BulletList'; +	const HeaderOnly='HeaderOnly'; +} + + +/** + * TValidationSummaryDisplay class. + * TValidationSummaryDisplay defines the enumerable type for the possible styles + * that a {@link TValidationSummary} can display the collected error messages. + * + * The following enumerable values are defined: + * - None: the error messages are not displayed + * - Dynamic: the error messages are dynamically added to display as the corresponding validators fail + * - Fixed: Similar to Dynamic except that the error messages physically occupy the page layout (even though they may not be visible) + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TValidationSummaryDisplayStyle extends TEnumerable +{ +	const None='None'; +	const Dynamic='Dynamic'; +	const Fixed='Fixed'; +} + diff --git a/framework/Web/UI/WebControls/TWebControlAdapter.php b/framework/Web/UI/WebControls/TWebControlAdapter.php index 68fecf1c..ad1e1642 100644 --- a/framework/Web/UI/WebControls/TWebControlAdapter.php +++ b/framework/Web/UI/WebControls/TWebControlAdapter.php @@ -1,71 +1,71 @@ -<?php
 -/**
 - * TWebControlAdapter class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TWebControlAdapter class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * TWebControlAdapter class
 - *
 - * TWebControlAdapter is the base class for adapters that customize
 - * rendering for the Web control to which the adapter is attached.
 - * It may be used to modify the default markup or behavior for specific
 - * browsers.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWebControlAdapter extends TControlAdapter
 -{
 -	/**
 -	 * Renders the control to which the adapter is attached.
 -	 * It calls {@link renderBeginTag}, {@link renderContents} and
 -	 * {@link renderEndTag} in order.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function render($writer)
 -	{
 -		$this->renderBeginTag($writer);
 -		$this->renderContents($writer);
 -		$this->renderEndTag($writer);
 -	}
 -
 -	/**
 -	 * Renders the openning tag for the attached control.
 -	 * Default implementation calls the attached control's corresponding method.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function renderBeginTag($writer)
 -	{
 -		$this->getControl()->renderBeginTag($writer);
 -	}
 -
 -	/**
 -	 * Renders the body contents within the attached control tag.
 -	 * Default implementation calls the attached control's corresponding method.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function renderContents($writer)
 -	{
 -		$this->getControl()->renderContents($writer);
 -	}
 -
 -	/**
 -	 * Renders the closing tag for the attached control.
 -	 * Default implementation calls the attached control's corresponding method.
 -	 * @param THtmlWriter writer for the rendering purpose
 -	 */
 -	public function renderEndTag($writer)
 -	{
 -		$this->getControl()->renderEndTag($writer);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +/** + * TWebControlAdapter class + * + * TWebControlAdapter is the base class for adapters that customize + * rendering for the Web control to which the adapter is attached. + * It may be used to modify the default markup or behavior for specific + * browsers. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWebControlAdapter extends TControlAdapter +{ +	/** +	 * Renders the control to which the adapter is attached. +	 * It calls {@link renderBeginTag}, {@link renderContents} and +	 * {@link renderEndTag} in order. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function render($writer) +	{ +		$this->renderBeginTag($writer); +		$this->renderContents($writer); +		$this->renderEndTag($writer); +	} + +	/** +	 * Renders the openning tag for the attached control. +	 * Default implementation calls the attached control's corresponding method. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function renderBeginTag($writer) +	{ +		$this->getControl()->renderBeginTag($writer); +	} + +	/** +	 * Renders the body contents within the attached control tag. +	 * Default implementation calls the attached control's corresponding method. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function renderContents($writer) +	{ +		$this->getControl()->renderContents($writer); +	} + +	/** +	 * Renders the closing tag for the attached control. +	 * Default implementation calls the attached control's corresponding method. +	 * @param THtmlWriter writer for the rendering purpose +	 */ +	public function renderEndTag($writer) +	{ +		$this->getControl()->renderEndTag($writer); +	} +} + diff --git a/framework/Web/UI/WebControls/TWizard.php b/framework/Web/UI/WebControls/TWizard.php index 25d3a41b..b497d719 100644 --- a/framework/Web/UI/WebControls/TWizard.php +++ b/framework/Web/UI/WebControls/TWizard.php @@ -1,1402 +1,1402 @@ -<?php
 -/**
 - * TWizard and the relevant class definitions.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TWizard and the relevant class definitions. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - */
 -
 -Prado::using('System.Web.UI.WebControls.TMultiView');
 -Prado::using('System.Web.UI.WebControls.TPanel');
 -Prado::using('System.Web.UI.WebControls.TButton');
 -Prado::using('System.Web.UI.WebControls.TLinkButton');
 -Prado::using('System.Web.UI.WebControls.TImageButton');
 -Prado::using('System.Web.UI.WebControls.TDataList');
 -Prado::using('System.Web.UI.WebControls.TWizardNavigationButtonStyle');
 -
 -/**
 - * Class TWizard.
 - *
 - * TWizard splits a large form and presents the user with a series of smaller
 - * forms to complete. TWizard is analogous to the installation wizard commonly
 - * used to install software in Windows.
 - *
 - * The smaller forms are called wizard steps ({@link TWizardStep}, which can be accessed via
 - * {@link getWizardSteps WizardSteps}. In template, wizard steps can be added
 - * into a wizard using the following syntax,
 - * <code>
 - *   <com:TWizard>
 - *      <com:TWizardStep Title="step 1">
 - *          content in step 1, may contain other controls
 - *      </com:TWizardStep>
 - *      <com:TWizardStep Title="step 2">
 - *          content in step 2, may contain other controls
 - *      </com:TWizardStep>
 - *   </com:TWizard>
 - * </code>
 - *
 - * Each wizard step can be one of the following types:
 - * - Start : the first step in the wizard.
 - * - Step : the internal steps in the wizard.
 - * - Finish : the last step that allows user interaction.
 - * - Complete : the step that shows a summary to user (no interaction is allowed).
 - * - Auto : the step type is determined by wizard automatically.
 - * At any time, only one step is visible to end-users, which can be obtained
 - * by {@link getActiveStep ActiveStep}. Its index in the step collection is given by
 - * {@link getActiveStepIndex ActiveStepIndex}.
 - *
 - * Wizard content can be customized in many ways.
 - *
 - * The layout of a wizard consists of four parts: header, step content, navigation
 - * and side bar. Their content are affected by the following properties, respectively,
 - * - header: {@link setHeaderText HeaderText} and {@link setHeaderTemplate HeaderTemplate}.
 - *   If both are present, the latter takes precedence.
 - * - step: {@link getWizardSteps WizardSteps}.
 - * - navigation: {@link setStartNavigationTemplate StartNavigationTemplate},
 - *   {@link setStepNavigationTemplate StepNavigationTemplate},
 - *   {@link setFinishNavigationTemplate FinishNavigationTemplate}.
 - *   Default templates will be used if above templates are not set.
 - * - side bar: {@link setSideBarTemplate SideBarTemplate}.
 - *   A default template will be used if this template is not set.
 - *   Its visibility is toggled by {@link setShowSideBar ShowSideBar}.
 - *
 - * The style of these wizard layout components can be customized via the following style properties,
 - * - header: {@link getHeaderStyle HeaderStyle}.
 - * - step: {@link getStepStyle StepStyle}.
 - * - navigation: {@link getNavigationStyle NavigationStyle},
 - *   {@link getStartNextButtonStyle StartNextButtonStyle},
 - *   {@link getStepNextButtonStyle StepNextButtonStyle},
 - *   {@link getStepPreviousButtonStyle StepPreviousButtonStyle},
 - *   {@link getFinishPreviousButtonStyle FinishPreviousButtonStyle},
 - *   {@link getFinishCompleteButtonStyle FinishCompleteButtonStyle},
 - *   {@link getCancelButtonStyle CancelButtonStyle}.
 - * - side bar: {@link getSideBarStyle SideBarStyle} and {@link getSideBarButtonStyle SideBarButtonStyle}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizard extends TWebControl implements INamingContainer
 -{
 -	/**
 -	 * Wizard step types.
 -	 * @deprecated deprecated since version 3.0.4 (use TWizardStepType constants instead)
 -	 */
 -	const ST_AUTO='Auto';
 -	const ST_START='Start';
 -	const ST_STEP='Step';
 -	const ST_FINISH='Finish';
 -	const ST_COMPLETE='Complete';
 -	/**
 -	 * Navigation commands.
 -	 */
 -	const CMD_PREVIOUS='PreviousStep';
 -	const CMD_NEXT='NextStep';
 -	const CMD_CANCEL='Cancel';
 -	const CMD_COMPLETE='Complete';
 -	const CMD_MOVETO='MoveTo';
 -	/**
 -	 * Side bar button ID
 -	 */
 -	const ID_SIDEBAR_BUTTON='SideBarButton';
 -	/**
 -	 * Side bar data list
 -	 */
 -	const ID_SIDEBAR_LIST='SideBarList';
 -
 -	/**
 -	 * @var TMultiView multiview that contains the wizard steps
 -	 */
 -	private $_multiView=null;
 -	/**
 -	 * @var mixed navigation template for the start step.
 -	 */
 -	private $_startNavigationTemplate=null;
 -	/**
 -	 * @var mixed navigation template for internal steps.
 -	 */
 -	private $_stepNavigationTemplate=null;
 -	/**
 -	 * @var mixed navigation template for the finish step.
 -	 */
 -	private $_finishNavigationTemplate=null;
 -	/**
 -	 * @var mixed template for wizard header.
 -	 */
 -	private $_headerTemplate=null;
 -	/**
 -	 * @var mixed template for the side bar.
 -	 */
 -	private $_sideBarTemplate=null;
 -	/**
 -	 * @var TWizardStepCollection
 -	 */
 -	private $_wizardSteps=null;
 -	/**
 -	 * @var TPanel container of the wizard header
 -	 */
 -	private $_header;
 -	/**
 -	 * @var TPanel container of the wizard step content
 -	 */
 -	private $_stepContent;
 -	/**
 -	 * @var TPanel container of the wizard side bar
 -	 */
 -	private $_sideBar;
 -	/**
 -	 * @var TPanel navigation panel
 -	 */
 -	private $_navigation;
 -	/**
 -	 * @var TWizardNavigationContainer container of the start navigation
 -	 */
 -	private $_startNavigation;
 -	/**
 -	 * @var TWizardNavigationContainer container of the step navigation
 -	 */
 -	private $_stepNavigation;
 -	/**
 -	 * @var TWizardNavigationContainer container of the finish navigation
 -	 */
 -	private $_finishNavigation;
 -	/**
 -	 * @var boolean whether ActiveStepIndex was already set
 -	 */
 -	private $_activeStepIndexSet=false;
 -	/**
 -	 * @var TDataList side bar data list.
 -	 */
 -	private $_sideBarDataList;
 -	/**
 -	 * @var boolean whether navigation should be cancelled (a status set in OnSideBarButtonClick)
 -	 */
 -	private $_cancelNavigation=false;
 -
 -	/**
 -	 * @return string tag name for the wizard
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'div';
 -	}
 -
 -	/**
 -	 * Adds {@link TWizardStep} objects into step collection.
 -	 * This method overrides the parent implementation and is
 -	 * invoked when template is being instantiated.
 -	 * @param mixed object instantiated in template
 -	 */
 -	public function addParsedObject($object)
 -	{
 -		if($object instanceof TWizardStep)
 -			$this->getWizardSteps()->add($object);
 -	}
 -
 -	/**
 -	 * @return TWizardStep the currently active wizard step
 -	 */
 -	public function getActiveStep()
 -	{
 -		return $this->getMultiView()->getActiveView();
 -	}
 -
 -	/**
 -	 * @param TWizardStep step to be activated
 -	 * @throws TInvalidOperationException if the step is not in the wizard step collection
 -	 */
 -	public function setActiveStep($step)
 -	{
 -		if(($index=$this->getWizardSteps()->indexOf($step))<0)
 -			throw new TInvalidOperationException('wizard_step_invalid');
 -		$this->setActiveStepIndex($index);
 -	}
 -
 -	/**
 -	 * @return integer the zero-based index of the active wizard step
 -	 */
 -	public function getActiveStepIndex()
 -	{
 -		return $this->getMultiView()->getActiveViewIndex();
 -	}
 -
 -	/**
 -	 * @param integer the zero-based index of the wizard step to be activated
 -	 */
 -	public function setActiveStepIndex($value)
 -	{
 -		$value=TPropertyValue::ensureInteger($value);
 -		$multiView=$this->getMultiView();
 -		if($multiView->getActiveViewIndex()!==$value)
 -		{
 -			$multiView->setActiveViewIndex($value);
 -			$this->_activeStepIndexSet=true;
 -			if($this->_sideBarDataList!==null && $this->getSideBarTemplate()!==null)
 -			{
 -				$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex());
 -				$this->_sideBarDataList->dataBind();
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * @return TWizardStepCollection collection of wizard steps
 -	 */
 -	public function getWizardSteps()
 -	{
 -		if($this->_wizardSteps===null)
 -			$this->_wizardSteps=new TWizardStepCollection($this);
 -		return $this->_wizardSteps;
 -	}
 -
 -	/**
 -	 * @return boolean whether to display a cancel button in each wizard step. Defaults to false.
 -	 */
 -	public function getShowCancelButton()
 -	{
 -		return $this->getViewState('ShowCancelButton',false);
 -	}
 -
 -	/**
 -	 * @param boolean whether to display a cancel button in each wizard step.
 -	 */
 -	public function setShowCancelButton($value)
 -	{
 -		$this->setViewState('ShowCancelButton',TPropertyValue::ensureBoolean($value),false);
 -	}
 -
 -	/**
 -	 * @return boolean whether to display a side bar that contains links to wizard steps. Defaults to true.
 -	 */
 -	public function getShowSideBar()
 -	{
 -		return $this->getViewState('ShowSideBar',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to display a side bar that contains links to wizard steps.
 -	 */
 -	public function setShowSideBar($value)
 -	{
 -		$this->setViewState('ShowSideBar',TPropertyValue::ensureBoolean($value),true);
 -		$this->requiresControlsRecreation();
 -	}
 -
 -	/**
 -	 * @return ITemplate navigation template for the start step. Defaults to null.
 -	 */
 -	public function getStartNavigationTemplate()
 -	{
 -		return $this->_startNavigationTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate navigation template for the start step.
 -	 */
 -	public function setStartNavigationTemplate($value)
 -	{
 -		$this->_startNavigationTemplate=$value;
 -		$this->requiresControlsRecreation();
 -	}
 -
 -	/**
 -	 * @return ITemplate navigation template for internal steps. Defaults to null.
 -	 */
 -	public function getStepNavigationTemplate()
 -	{
 -		return $this->_stepNavigationTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate navigation template for internal steps.
 -	 */
 -	public function setStepNavigationTemplate($value)
 -	{
 -		$this->_stepNavigationTemplate=$value;
 -		$this->requiresControlsRecreation();
 -	}
 -
 -	/**
 -	 * @return ITemplate navigation template for the finish step. Defaults to null.
 -	 */
 -	public function getFinishNavigationTemplate()
 -	{
 -		return $this->_finishNavigationTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate navigation template for the finish step.
 -	 */
 -	public function setFinishNavigationTemplate($value)
 -	{
 -		$this->_finishNavigationTemplate=$value;
 -		$this->requiresControlsRecreation();
 -	}
 -
 -	/**
 -	 * @return ITemplate template for wizard header. Defaults to null.
 -	 */
 -	public function getHeaderTemplate()
 -	{
 -		return $this->_headerTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate template for wizard header.
 -	 */
 -	public function setHeaderTemplate($value)
 -	{
 -		$this->_headerTemplate=$value;
 -		$this->requiresControlsRecreation();
 -	}
 -
 -	/**
 -	 * @return ITemplate template for the side bar. Defaults to null.
 -	 */
 -	public function getSideBarTemplate()
 -	{
 -		return $this->_sideBarTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate template for the side bar.
 -	 */
 -	public function setSideBarTemplate($value)
 -	{
 -		$this->_sideBarTemplate=$value;
 -		$this->requiresControlsRecreation();
 -	}
 -
 -	/**
 -	 * @return string header text. Defaults to ''.
 -	 */
 -	public function getHeaderText()
 -	{
 -		return $this->getViewState('HeaderText','');
 -	}
 -
 -	/**
 -	 * @param string header text.
 -	 */
 -	public function setHeaderText($value)
 -	{
 -		$this->setViewState('HeaderText',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string the URL that the browser will be redirected to if the cancel button in the
 -	 * wizard is clicked. Defaults to ''.
 -	 */
 -	public function getCancelDestinationUrl()
 -	{
 -		return $this->getViewState('CancelDestinationUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL that the browser will be redirected to if the cancel button in the
 -	 * wizard is clicked.
 -	 */
 -	public function setCancelDestinationUrl($value)
 -	{
 -		$this->setViewState('CancelDestinationUrl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return string the URL that the browser will be redirected to if the wizard finishes.
 -	 * Defaults to ''.
 -	 */
 -	public function getFinishDestinationUrl()
 -	{
 -		return $this->getViewState('FinishDestinationUrl','');
 -	}
 -
 -	/**
 -	 * @param string the URL that the browser will be redirected to if the wizard finishes.
 -	 */
 -	public function setFinishDestinationUrl($value)
 -	{
 -		$this->setViewState('FinishDestinationUrl',TPropertyValue::ensureString($value),'');
 -	}
 -
 -	/**
 -	 * @return TStyle the style for the buttons displayed in the side bar.
 -	 */
 -	public function getSideBarButtonStyle()
 -	{
 -		if(($style=$this->getViewState('SideBarButtonStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$this->setViewState('SideBarButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TStyle the style common for all navigation buttons.
 -	 */
 -	public function getNavigationButtonStyle()
 -	{
 -		if(($style=$this->getViewState('NavigationButtonStyle',null))===null)
 -		{
 -			$style=new TStyle;
 -			$this->setViewState('NavigationButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonStyle the style for the next button in the start wizard step.
 -	 */
 -	public function getStartNextButtonStyle()
 -	{
 -		if(($style=$this->getViewState('StartNextButtonStyle',null))===null)
 -		{
 -			$style=new TWizardNavigationButtonStyle;
 -			$style->setButtonText('Next');
 -			$this->setViewState('StartNextButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonStyle the style for the next button in each internal wizard step.
 -	 */
 -	public function getStepNextButtonStyle()
 -	{
 -		if(($style=$this->getViewState('StepNextButtonStyle',null))===null)
 -		{
 -			$style=new TWizardNavigationButtonStyle;
 -			$style->setButtonText('Next');
 -			$this->setViewState('StepNextButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonStyle the style for the previous button in the start wizard step.
 -	 */
 -	public function getStepPreviousButtonStyle()
 -	{
 -		if(($style=$this->getViewState('StepPreviousButtonStyle',null))===null)
 -		{
 -			$style=new TWizardNavigationButtonStyle;
 -			$style->setButtonText('Previous');
 -			$this->setViewState('StepPreviousButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonStyle the style for the complete button in the finish wizard step.
 -	 */
 -	public function getFinishCompleteButtonStyle()
 -	{
 -		if(($style=$this->getViewState('FinishCompleteButtonStyle',null))===null)
 -		{
 -			$style=new TWizardNavigationButtonStyle;
 -			$style->setButtonText('Complete');
 -			$this->setViewState('FinishCompleteButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonStyle the style for the previous button in the start wizard step.
 -	 */
 -	public function getFinishPreviousButtonStyle()
 -	{
 -		if(($style=$this->getViewState('FinishPreviousButtonStyle',null))===null)
 -		{
 -			$style=new TWizardNavigationButtonStyle;
 -			$style->setButtonText('Previous');
 -			$this->setViewState('FinishPreviousButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonStyle the style for the cancel button
 -	 */
 -	public function getCancelButtonStyle()
 -	{
 -		if(($style=$this->getViewState('CancelButtonStyle',null))===null)
 -		{
 -			$style=new TWizardNavigationButtonStyle;
 -			$style->setButtonText('Cancel');
 -			$this->setViewState('CancelButtonStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TPanelStyle the style for the side bar.
 -	 */
 -	public function getSideBarStyle()
 -	{
 -		if(($style=$this->getViewState('SideBarStyle',null))===null)
 -		{
 -			$style=new TPanelStyle;
 -			$this->setViewState('SideBarStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TPanelStyle the style for the header.
 -	 */
 -	public function getHeaderStyle()
 -	{
 -		if(($style=$this->getViewState('HeaderStyle',null))===null)
 -		{
 -			$style=new TPanelStyle;
 -			$this->setViewState('HeaderStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TPanelStyle the style for each internal wizard step.
 -	 */
 -	public function getStepStyle()
 -	{
 -		if(($style=$this->getViewState('StepStyle',null))===null)
 -		{
 -			$style=new TPanelStyle;
 -			$this->setViewState('StepStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return TPanelStyle the style for the navigation panel.
 -	 */
 -	public function getNavigationStyle()
 -	{
 -		if(($style=$this->getViewState('NavigationStyle',null))===null)
 -		{
 -			$style=new TPanelStyle;
 -			$this->setViewState('NavigationStyle',$style,null);
 -		}
 -		return $style;
 -	}
 -
 -	/**
 -	 * @return boolean whether to use default layout to arrange side bar and the rest wizard components. Defaults to true.
 -	 */
 -	public function getUseDefaultLayout()
 -	{
 -		return $this->getViewState('UseDefaultLayout',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether to use default layout to arrange side bar and the rest wizard components.
 -	 * If true, an HTML table will be used which places the side bar in the left cell
 -	 * while the rest components in the right cell.
 -	 */
 -	public function setUseDefaultLayout($value)
 -	{
 -		$this->setViewState('UseDefaultLayout',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return TPanel container of the wizard header
 -	 */
 -	public function getHeader()
 -	{
 -		return $this->_header;
 -	}
 -
 -	/**
 -	 * @return TPanel container of the wizard step content
 -	 */
 -	public function getStepContent()
 -	{
 -		return $this->_stepContent;
 -	}
 -
 -	/**
 -	 * @return TPanel container of the wizard side bar
 -	 */
 -	public function getSideBar()
 -	{
 -		return $this->_sideBar;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationContainer container of the start navigation
 -	 */
 -	public function getStartNavigation()
 -	{
 -		return $this->_startNavigation;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationContainer container of the step navigation
 -	 */
 -	public function getStepNavigation()
 -	{
 -		return $this->_stepNavigation;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationContainer container of the finish navigation
 -	 */
 -	public function getFinishNavigation()
 -	{
 -		return $this->_finishNavigation;
 -	}
 -
 -	/**
 -	 * Raises <b>OnActiveStepChanged</b> event.
 -	 * This event is raised when the current visible step is changed in the
 -	 * wizard.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onActiveStepChanged($param)
 -	{
 -		$this->raiseEvent('OnActiveStepChanged',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnCancelButtonClick</b> event.
 -	 * This event is raised when a cancel navigation button is clicked in the
 -	 * current active step.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onCancelButtonClick($param)
 -	{
 -		$this->raiseEvent('OnCancelButtonClick',$this,$param);
 -		if(($url=$this->getCancelDestinationUrl())!=='')
 -			$this->getResponse()->redirect($url);
 -	}
 -
 -	/**
 -	 * Raises <b>OnCompleteButtonClick</b> event.
 -	 * This event is raised when a finish navigation button is clicked in the
 -	 * current active step.
 -	 * @param TWizardNavigationEventParameter event parameter
 -	 */
 -	public function onCompleteButtonClick($param)
 -	{
 -		$this->raiseEvent('OnCompleteButtonClick',$this,$param);
 -		if(($url=$this->getFinishDestinationUrl())!=='')
 -			$this->getResponse()->redirect($url);
 -	}
 -
 -	/**
 -	 * Raises <b>OnNextButtonClick</b> event.
 -	 * This event is raised when a next navigation button is clicked in the
 -	 * current active step.
 -	 * @param TWizardNavigationEventParameter event parameter
 -	 */
 -	public function onNextButtonClick($param)
 -	{
 -		$this->raiseEvent('OnNextButtonClick',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnPreviousButtonClick</b> event.
 -	 * This event is raised when a previous navigation button is clicked in the
 -	 * current active step.
 -	 * @param TWizardNavigationEventParameter event parameter
 -	 */
 -	public function onPreviousButtonClick($param)
 -	{
 -		$this->raiseEvent('OnPreviousButtonClick',$this,$param);
 -	}
 -
 -	/**
 -	 * Raises <b>OnSideBarButtonClick</b> event.
 -	 * This event is raised when a link button in the side bar is clicked.
 -	 * @param TWizardNavigationEventParameter event parameter
 -	 */
 -	public function onSideBarButtonClick($param)
 -	{
 -		$this->raiseEvent('OnSideBarButtonClick',$this,$param);
 -	}
 -
 -	/**
 -	 * Returns the multiview that holds the wizard steps.
 -	 * This method should only be used by control developers.
 -	 * @return TMultiView the multiview holding wizard steps
 -	 */
 -	public function getMultiView()
 -	{
 -		if($this->_multiView===null)
 -		{
 -			$this->_multiView=new TMultiView;
 -			$this->_multiView->setID('WizardMultiView');
 -			$this->_multiView->attachEventHandler('OnActiveViewChanged',array($this,'onActiveStepChanged'));
 -			$this->_multiView->ignoreBubbleEvents();
 -		}
 -		return $this->_multiView;
 -	}
 -
 -	/**
 -	 * Adds a wizard step to the multiview.
 -	 * This method should only be used by control developers.
 -	 * It is invoked when a step is added into the step collection of the wizard.
 -	 * @param TWizardStep wizard step to be added into multiview.
 -	 */
 -	public function addedWizardStep($step)
 -	{
 -		if(($wizard=$step->getWizard())!==null)
 -			$wizard->getWizardSteps()->remove($step);
 -		$step->setWizard($this);
 -		$this->wizardStepsChanged();
 -	}
 -
 -	/**
 -	 * Removes a wizard step from the multiview.
 -	 * This method should only be used by control developers.
 -	 * It is invoked when a step is removed from the step collection of the wizard.
 -	 * @param TWizardStep wizard step to be removed from multiview.
 -	 */
 -	public function removedWizardStep($step)
 -	{
 -		$step->setWizard(null);
 -		$this->wizardStepsChanged();
 -	}
 -
 -	/**
 -	 * Creates the child controls of the wizard.
 -	 * This method overrides the parent implementation.
 -	 * @param TEventParameter event parameter
 -	 */
 -	public function onInit($param)
 -	{
 -		parent::onInit($param);
 -		$this->ensureChildControls();
 -		if($this->getActiveStepIndex()<0 && $this->getWizardSteps()->getCount()>0)
 -			$this->setActiveStepIndex(0);
 -	}
 -
 -	/**
 -	 * Saves the current active step index into history.
 -	 * This method is invoked by the framework when the control state is being saved.
 -	 */
 -	public function saveState()
 -	{
 -		$index=$this->getActiveStepIndex();
 -		$history=$this->getHistory();
 -		if(!$history->getCount() || $history->peek()!==$index)
 -			$history->push($index);
 -	}
 -
 -	/**
 -	 * Indicates the wizard needs to recreate all child controls.
 -	 */
 -	protected function requiresControlsRecreation()
 -	{
 -		if($this->getChildControlsCreated())
 -			$this->setChildControlsCreated(false);
 -	}
 -
 -	/**
 -	 * Renders the wizard.
 -	 * @param THtmlWriter
 -	 */
 -	public function render($writer)
 -	{
 -		$this->ensureChildControls();
 -		if($this->getHasControls())
 -		{
 -			if($this->getUseDefaultLayout())
 -			{
 -				$this->applyControlProperties();
 -				$this->renderBeginTag($writer);
 -				$writer->write("\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" height=\"100%\" width=\"100%\">\n<tr><td width=\"1\" valign=\"top\">\n");
 -				$this->_sideBar->renderControl($writer);
 -				$writer->write("\n</td><td valign=\"top\">\n");
 -				$this->_header->renderControl($writer);
 -				$this->_stepContent->renderControl($writer);
 -				$this->_navigation->renderControl($writer);
 -				$writer->write("\n</td></tr></table>\n");
 -				$this->renderEndTag($writer);
 -			}
 -			else
 -			{
 -				$this->applyControlProperties();
 -				$this->renderBeginTag($writer);
 -				$this->_sideBar->renderControl($writer);
 -				$this->_header->renderControl($writer);
 -				$this->_stepContent->renderControl($writer);
 -				$this->_navigation->renderControl($writer);
 -				$this->renderEndTag($writer);
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Applies various properties to the components of wizard
 -	 */
 -	protected function applyControlProperties()
 -	{
 -		$this->applyHeaderProperties();
 -		$this->applySideBarProperties();
 -		$this->applyStepContentProperties();
 -		$this->applyNavigationProperties();
 -	}
 -
 -	/**
 -	 * Applies properties to the wizard header
 -	 */
 -	protected function applyHeaderProperties()
 -	{
 -		if(($style=$this->getViewState('HeaderStyle',null))!==null)
 -			$this->_header->getStyle()->mergeWith($style);
 -		if($this->getHeaderTemplate()===null)
 -		{
 -			$this->_header->getControls()->clear();
 -			$this->_header->getControls()->add($this->getHeaderText());
 -		}
 -	}
 -
 -	/**
 -	 * Applies properties to the wizard sidebar
 -	 */
 -	protected function applySideBarProperties()
 -	{
 -		$this->_sideBar->setVisible($this->getShowSideBar());
 -		if($this->_sideBarDataList!==null && $this->getShowSideBar())
 -		{
 -			$this->_sideBarDataList->setDataSource($this->getWizardSteps());
 -			$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex());
 -			$this->_sideBarDataList->dataBind();
 -			if(($style=$this->getViewState('SideBarButtonStyle',null))!==null)
 -			{
 -				foreach($this->_sideBarDataList->getItems() as $item)
 -				{
 -					if(($button=$item->findControl('SideBarButton'))!==null)
 -						$button->getStyle()->mergeWith($style);
 -				}
 -			}
 -		}
 -		if(($style=$this->getViewState('SideBarStyle',null))!==null)
 -			$this->_sideBar->getStyle()->mergeWith($style);
 -	}
 -
 -	/**
 -	 * Applies properties to the wizard step content
 -	 */
 -	protected function applyStepContentProperties()
 -	{
 -		if(($style=$this->getViewState('StepStyle',null))!==null)
 -			$this->_stepContent->getStyle()->mergeWith($style);
 -	}
 -
 -	/**
 -	 * Apply properties to various navigation panels.
 -	 */
 -	protected function applyNavigationProperties()
 -	{
 -		$wizardSteps=$this->getWizardSteps();
 -		$activeStep=$this->getActiveStep();
 -		$activeStepIndex=$this->getActiveStepIndex();
 -
 -		if(!$this->_navigation)
 -			return;
 -		else if($activeStepIndex<0 || $activeStepIndex>=$wizardSteps->getCount())
 -		{
 -			$this->_navigation->setVisible(false);
 -			return;
 -		}
 -
 -		// set visibility of different types of navigation panel
 -		$showStandard=true;
 -		foreach($wizardSteps as $step)
 -		{
 -			if(($step instanceof TTemplatedWizardStep) && ($container=$step->getNavigationContainer())!==null)
 -			{
 -				if($activeStep===$step)
 -				{
 -					$container->setVisible(true);
 -					$showStandard=false;
 -				}
 -				else
 -					$container->setVisible(false);
 -			}
 -		}
 -		$activeStepType=$this->getStepType($activeStep);
 -		if($activeStepType===TWizardStepType::Complete)
 -		{
 -			$this->_sideBar->setVisible(false);
 -			$this->_header->setVisible(false);
 -		}
 -		$this->_startNavigation->setVisible($showStandard && $activeStepType===self::ST_START);
 -		$this->_stepNavigation->setVisible($showStandard && $activeStepType===self::ST_STEP);
 -		$this->_finishNavigation->setVisible($showStandard && $activeStepType===self::ST_FINISH);
 -
 -		if(($navigationStyle=$this->getViewState('NavigationStyle',null))!==null)
 -			$this->_navigation->getStyle()->mergeWith($navigationStyle);
 -
 -		$displayCancelButton=$this->getShowCancelButton();
 -		$cancelButtonStyle=$this->getCancelButtonStyle();
 -		$buttonStyle=$this->getViewState('NavigationButtonStyle',null);
 -		if($buttonStyle!==null)
 -			$cancelButtonStyle->mergeWith($buttonStyle);
 -
 -		// apply styles to start navigation buttons
 -		if(($cancelButton=$this->_startNavigation->getCancelButton())!==null)
 -		{
 -			$cancelButton->setVisible($displayCancelButton);
 -			$cancelButtonStyle->apply($cancelButton);
 -		}
 -		if(($button=$this->_startNavigation->getNextButton())!==null)
 -		{
 -			$button->setVisible(true);
 -			$style=$this->getStartNextButtonStyle();
 -			if($buttonStyle!==null)
 -				$style->mergeWith($buttonStyle);
 -			$style->apply($button);
 -			if($activeStepType===TWizardStepType::Start)
 -				$this->getPage()->getClientScript()->registerDefaultButton($this, $button);
 -		}
 -
 -		// apply styles to finish navigation buttons
 -		if(($cancelButton=$this->_finishNavigation->getCancelButton())!==null)
 -		{
 -			$cancelButton->setVisible($displayCancelButton);
 -			$cancelButtonStyle->apply($cancelButton);
 -		}
 -		if(($button=$this->_finishNavigation->getPreviousButton())!==null)
 -		{
 -			$button->setVisible($this->allowNavigationToPreviousStep());
 -			$style=$this->getFinishPreviousButtonStyle();
 -			if($buttonStyle!==null)
 -				$style->mergeWith($buttonStyle);
 -			$style->apply($button);
 -		}
 -		if(($button=$this->_finishNavigation->getCompleteButton())!==null)
 -		{
 -			$button->setVisible(true);
 -			$style=$this->getFinishCompleteButtonStyle();
 -			if($buttonStyle!==null)
 -				$style->mergeWith($buttonStyle);
 -			$style->apply($button);
 -			if($activeStepType===TWizardStepType::Finish)
 -				$this->getPage()->getClientScript()->registerDefaultButton($this, $button);
 -		}
 -
 -		// apply styles to step navigation buttons
 -		if(($cancelButton=$this->_stepNavigation->getCancelButton())!==null)
 -		{
 -			$cancelButton->setVisible($displayCancelButton);
 -			$cancelButtonStyle->apply($cancelButton);
 -		}
 -		if(($button=$this->_stepNavigation->getPreviousButton())!==null)
 -		{
 -			$button->setVisible($this->allowNavigationToPreviousStep());
 -			$style=$this->getStepPreviousButtonStyle();
 -			if($buttonStyle!==null)
 -				$style->mergeWith($buttonStyle);
 -			$style->apply($button);
 -		}
 -		if(($button=$this->_stepNavigation->getNextButton())!==null)
 -		{
 -			$button->setVisible(true);
 -			$style=$this->getStepNextButtonStyle();
 -			if($buttonStyle!==null)
 -				$style->mergeWith($buttonStyle);
 -			$style->apply($button);
 -			if($activeStepType===TWizardStepType::Step)
 -				$this->getPage()->getClientScript()->registerDefaultButton($this, $button);
 -		}
 -	}
 -
 -	/**
 -	 * @return TStack history containing step indexes that were navigated before
 -	 */
 -	protected function getHistory()
 -	{
 -		if(($history=$this->getControlState('History',null))===null)
 -		{
 -			$history=new TStack;
 -			$this->setControlState('History',$history);
 -		}
 -		return $history;
 -	}
 -
 -	/**
 -	 * Determines the type of the specified wizard step.
 -	 * @param TWizardStep
 -	 * @return TWizardStepType type of the step
 -	 */
 -	protected function getStepType($wizardStep)
 -	{
 -		if(($type=$wizardStep->getStepType())===TWizardStepType::Auto)
 -		{
 -			$steps=$this->getWizardSteps();
 -			if(($index=$steps->indexOf($wizardStep))>=0)
 -			{
 -				$stepCount=$steps->getCount();
 -				if($stepCount===1 || ($index<$stepCount-1 && $steps->itemAt($index+1)->getStepType()===TWizardStepType::Complete))
 -					return TWizardStepType::Finish;
 -				else if($index===0)
 -					return TWizardStepType::Start;
 -				else if($index===$stepCount-1)
 -					return TWizardStepType::Finish;
 -				else
 -					return TWizardStepType::Step;
 -			}
 -			else
 -				return $type;
 -		}
 -		else
 -			return $type;
 -	}
 -
 -	/**
 -	 * Clears up everything within the wizard.
 -	 */
 -	protected function reset()
 -	{
 -		$this->getControls()->clear();
 -		$this->_header=null;
 -		$this->_stepContent=null;
 -		$this->_sideBar=null;
 -		$this->_sideBarDataList=null;
 -		$this->_navigation=null;
 -		$this->_startNavigation=null;
 -		$this->_stepNavigation=null;
 -		$this->_finishNavigation=null;
 -	}
 -
 -	/**
 -	 * Creates child controls within the wizard
 -	 */
 -	public function createChildControls()
 -	{
 -		$this->reset();
 -		$this->createSideBar();
 -		$this->createHeader();
 -		$this->createStepContent();
 -		$this->createNavigation();
 -//		$this->clearChildState();
 -	}
 -
 -	/**
 -	 * Creates the wizard header.
 -	 */
 -	protected function createHeader()
 -	{
 -		$this->_header=new TPanel;
 -		if(($template=$this->getHeaderTemplate())!==null)
 -			$template->instantiateIn($this->_header);
 -		else
 -			$this->_header->getControls()->add($this->getHeaderText());
 -		$this->getControls()->add($this->_header);
 -	}
 -
 -	/**
 -	 * Creates the wizard side bar
 -	 */
 -	protected function createSideBar()
 -	{
 -		if($this->getShowSideBar())
 -		{
 -			if(($template=$this->getSideBarTemplate())===null)
 -				$template=new TWizardSideBarTemplate;
 -			$this->_sideBar=new TPanel;
 -			$template->instantiateIn($this->_sideBar);
 -			$this->getControls()->add($this->_sideBar);
 -
 -			if(($this->_sideBarDataList=$this->_sideBar->findControl(self::ID_SIDEBAR_LIST))!==null)
 -			{
 -				$this->_sideBarDataList->attachEventHandler('OnItemCommand',array($this,'dataListItemCommand'));
 -				$this->_sideBarDataList->attachEventHandler('OnItemDataBound',array($this,'dataListItemDataBound'));
 -				$this->_sideBarDataList->setDataSource($this->getWizardSteps());
 -				$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex());
 -				$this->_sideBarDataList->dataBind();
 -			}
 -		}
 -		else
 -		{
 -			$this->_sideBar=new TPanel;
 -			$this->getControls()->add($this->_sideBar);
 -		}
 -	}
 -
 -	/**
 -	 * Event handler for sidebar datalist's OnItemCommand event.
 -	 * This method is used internally by wizard. It mainly
 -	 * sets the active step index according to the button clicked in the sidebar.
 -	 * @param mixed sender of the event
 -	 * @param TDataListCommandEventParameter
 -	 */
 -	public function dataListItemCommand($sender,$param)
 -	{
 -		$item=$param->getItem();
 -		if($param->getCommandName()===self::CMD_MOVETO)
 -		{
 -			$stepIndex=$this->getActiveStepIndex();
 -			$newStepIndex=TPropertyValue::ensureInteger($param->getCommandParameter());
 -			$navParam=new TWizardNavigationEventParameter($stepIndex);
 -			$navParam->setNextStepIndex($newStepIndex);
 -
 -			// if the button clicked causes validation which fails,
 -			// by default we will cancel navigation to the new step
 -			$button=$param->getCommandSource();
 -			if(($button instanceof IButtonControl) && $button->getCausesValidation() && ($page=$this->getPage())!==null && !$page->getIsValid())
 -				$navParam->setCancelNavigation(true);
 -
 -			$this->_activeStepIndexSet=false;
 -			$this->onSideBarButtonClick($navParam);
 -			$this->_cancelNavigation=$navParam->getCancelNavigation();
 -			if(!$this->_cancelNavigation)
 -			{
 -				if(!$this->_activeStepIndexSet && $this->allowNavigationToStep($newStepIndex))
 -					$this->setActiveStepIndex($newStepIndex);
 -			}
 -			else
 -				$this->setActiveStepIndex($stepIndex);
 -		}
 -	}
 -
 -	/**
 -	 * Event handler for sidebar datalist's OnItemDataBound event.
 -	 * This method is used internally by wizard. It mainly configures
 -	 * the buttons in the sidebar datalist.
 -	 * @param mixed sender of the event
 -	 * @param TDataListItemEventParameter
 -	 */
 -	public function dataListItemDataBound($sender,$param)
 -	{
 -		$item=$param->getItem();
 -		$itemType=$item->getItemType();
 -		if($itemType==='Item' || $itemType==='AlternatingItem' || $itemType==='SelectedItem' || $itemType==='EditItem')
 -		{
 -			if(($button=$item->findControl(self::ID_SIDEBAR_BUTTON))!==null)
 -			{
 -				$step=$item->getData();
 -				if(($this->getStepType($step)===TWizardStepType::Complete))
 -					$button->setEnabled(false);
 -				if(($title=$step->getTitle())!=='')
 -					$button->setText($title);
 -				else
 -					$button->setText($step->getID(false));
 -				$index=$this->getWizardSteps()->indexOf($step);
 -				$button->setCommandName(self::CMD_MOVETO);
 -				$button->setCommandParameter("$index");
 -			}
 -		}
 -	}
 -
 -	/**
 -	 * Creates wizard step content.
 -	 */
 -	protected function createStepContent()
 -	{
 -		foreach($this->getWizardSteps() as $step)
 -		{
 -			if($step instanceof TTemplatedWizardStep)
 -				$step->ensureChildControls();
 -		}
 -		$multiView=$this->getMultiView();
 -		$this->_stepContent=new TPanel;
 -		$this->_stepContent->getControls()->add($multiView);
 -		$this->getControls()->add($this->_stepContent);
 -		if($multiView->getViews()->getCount())
 -			$multiView->setActiveViewIndex(0);
 -	}
 -
 -	/**
 -	 * Creates navigation panel.
 -	 */
 -	protected function createNavigation()
 -	{
 -		$this->_navigation=new TPanel;
 -		$this->getControls()->add($this->_navigation);
 -		$controls=$this->_navigation->getControls();
 -		foreach($this->getWizardSteps() as $step)
 -		{
 -			if($step instanceof TTemplatedWizardStep)
 -			{
 -				$step->instantiateNavigationTemplate();
 -				if(($panel=$step->getNavigationContainer())!==null)
 -					$controls->add($panel);
 -			}
 -		}
 -		$this->_startNavigation=$this->createStartNavigation();
 -		$controls->add($this->_startNavigation);
 -		$this->_stepNavigation=$this->createStepNavigation();
 -		$controls->add($this->_stepNavigation);
 -		$this->_finishNavigation=$this->createFinishNavigation();
 -		$controls->add($this->_finishNavigation);
 -	}
 -
 -	/**
 -	 * Creates start navigation panel.
 -	 */
 -	protected function createStartNavigation()
 -	{
 -		if(($template=$this->getStartNavigationTemplate())===null)
 -			$template=new TWizardStartNavigationTemplate($this);
 -		$navigation=new TWizardNavigationContainer;
 -		$template->instantiateIn($navigation);
 -		return $navigation;
 -	}
 -
 -	/**
 -	 * Creates step navigation panel.
 -	 */
 -	protected function createStepNavigation()
 -	{
 -		if(($template=$this->getStepNavigationTemplate())===null)
 -			$template=new TWizardStepNavigationTemplate($this);
 -		$navigation=new TWizardNavigationContainer;
 -		$template->instantiateIn($navigation);
 -		return $navigation;
 -	}
 -
 -	/**
 -	 * Creates finish navigation panel.
 -	 */
 -	protected function createFinishNavigation()
 -	{
 -		if(($template=$this->getFinishNavigationTemplate())===null)
 -			$template=new TWizardFinishNavigationTemplate($this);
 -		$navigation=new TWizardNavigationContainer;
 -		$template->instantiateIn($navigation);
 -		return $navigation;
 -	}
 -
 -	/**
 -	 * Updates the sidebar datalist if any.
 -	 * This method is invoked when any wizard step is changed.
 -	 */
 -	public function wizardStepsChanged()
 -	{
 -		if($this->_sideBarDataList!==null)
 -		{
 -			$this->_sideBarDataList->setDataSource($this->getWizardSteps());
 -			$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex());
 -			$this->_sideBarDataList->dataBind();
 -		}
 -	}
 -
 -	/**
 -	 * Determines the index of the previous step based on history.
 -	 * @param boolean whether the first item in the history stack should be popped
 -	 * up after calling this method.
 -	 */
 -	protected function getPreviousStepIndex($popStack)
 -	{
 -		$history=$this->getHistory();
 -		if($history->getCount()>=0)
 -		{
 -			$activeStepIndex=$this->getActiveStepIndex();
 -			$previousStepIndex=-1;
 -			if($popStack)
 -			{
 -				$previousStepIndex=$history->pop();
 -				if($activeStepIndex===$previousStepIndex && $history->getCount()>0)
 -					$previousStepIndex=$history->pop();
 -			}
 -			else
 -			{
 -				$previousStepIndex=$history->peek();
 -				if($activeStepIndex===$previousStepIndex && $history->getCount()>1)
 -				{
 -					$saveIndex=$history->pop();
 -					$previousStepIndex=$history->peek();
 -					$history->push($saveIndex);
 -				}
 -			}
 -			return $activeStepIndex===$previousStepIndex ? -1 : $previousStepIndex;
 -		}
 -		else
 -			return -1;
 -	}
 -
 -	/**
 -	 * @return boolean whether navigation to the previous step is allowed
 -	 */
 -	protected function allowNavigationToPreviousStep()
 -	{
 -		if(($index=$this->getPreviousStepIndex(false))!==-1)
 -			return $this->getWizardSteps()->itemAt($index)->getAllowReturn();
 -		else
 -			return false;
 -	}
 -
 -	/**
 -	 * @param integer index of the step
 -	 * @return boolean whether navigation to the specified step is allowed
 -	 */
 -	protected function allowNavigationToStep($index)
 -	{
 -		if($this->getHistory()->contains($index))
 -			return $this->getWizardSteps()->itemAt($index)->getAllowReturn();
 -		else
 -			return true;
 -	}
 -
 -	/**
 -	 * Handles bubbled events.
 -	 * This method mainly translate certain command events into
 -	 * wizard-specific events.
 -	 * @param mixed sender of the original command event
 -	 * @param TEventParameter event parameter
 -	 * @throws TInvalidDataValueException if a navigation command is associated with an invalid parameter
 -	 */
 -	public function bubbleEvent($sender,$param)
 -	{
 -		if($param instanceof TCommandEventParameter)
 -		{
 -			$command=$param->getCommandName();
 -			if(strcasecmp($command,self::CMD_CANCEL)===0)
 -			{
 -				$this->onCancelButtonClick($param);
 -				return true;
 -			}
 -
 -			$type=$this->getStepType($this->getActiveStep());
 -			$index=$this->getActiveStepIndex();
 -			$navParam=new TWizardNavigationEventParameter($index);
 -			if(($sender instanceof IButtonControl) && $sender->getCausesValidation() && ($page=$this->getPage())!==null && !$page->getIsValid())
 -				$navParam->setCancelNavigation(true);
 -
 -			$handled=false;
 -			$movePrev=false;
 -			$this->_activeStepIndexSet=false;
 -
 -			if(strcasecmp($command,self::CMD_NEXT)===0)
 -			{
 -				if($type!==self::ST_START && $type!==self::ST_STEP)
 -					throw new TInvalidDataValueException('wizard_command_invalid',self::CMD_NEXT);
 -				if($index<$this->getWizardSteps()->getCount()-1)
 -					$navParam->setNextStepIndex($index+1);
 -				$this->onNextButtonClick($navParam);
 -				$handled=true;
 -			}
 -			else if(strcasecmp($command,self::CMD_PREVIOUS)===0)
 -			{
 -				if($type!==self::ST_FINISH && $type!==self::ST_STEP)
 -					throw new TInvalidDataValueException('wizard_command_invalid',self::CMD_PREVIOUS);
 -				$movePrev=true;
 -				if(($prevIndex=$this->getPreviousStepIndex(false))>=0)
 -					$navParam->setNextStepIndex($prevIndex);
 -				$this->onPreviousButtonClick($navParam);
 -				$handled=true;
 -			}
 -			else if(strcasecmp($command,self::CMD_COMPLETE)===0)
 -			{
 -				if($type!==self::ST_FINISH)
 -					throw new TInvalidDataValueException('wizard_command_invalid',self::CMD_COMPLETE);
 -				if($index<$this->getWizardSteps()->getCount()-1)
 -					$navParam->setNextStepIndex($index+1);
 -				$this->onCompleteButtonClick($navParam);
 -				$handled=true;
 -			}
 -			else if(strcasecmp($command,self::CMD_MOVETO)===0)
 -			{
 -				if($this->_cancelNavigation)  // may be set in onSideBarButtonClick
 + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TMultiView'); +Prado::using('System.Web.UI.WebControls.TPanel'); +Prado::using('System.Web.UI.WebControls.TButton'); +Prado::using('System.Web.UI.WebControls.TLinkButton'); +Prado::using('System.Web.UI.WebControls.TImageButton'); +Prado::using('System.Web.UI.WebControls.TDataList'); +Prado::using('System.Web.UI.WebControls.TWizardNavigationButtonStyle'); + +/** + * Class TWizard. + * + * TWizard splits a large form and presents the user with a series of smaller + * forms to complete. TWizard is analogous to the installation wizard commonly + * used to install software in Windows. + * + * The smaller forms are called wizard steps ({@link TWizardStep}, which can be accessed via + * {@link getWizardSteps WizardSteps}. In template, wizard steps can be added + * into a wizard using the following syntax, + * <code> + *   <com:TWizard> + *      <com:TWizardStep Title="step 1"> + *          content in step 1, may contain other controls + *      </com:TWizardStep> + *      <com:TWizardStep Title="step 2"> + *          content in step 2, may contain other controls + *      </com:TWizardStep> + *   </com:TWizard> + * </code> + * + * Each wizard step can be one of the following types: + * - Start : the first step in the wizard. + * - Step : the internal steps in the wizard. + * - Finish : the last step that allows user interaction. + * - Complete : the step that shows a summary to user (no interaction is allowed). + * - Auto : the step type is determined by wizard automatically. + * At any time, only one step is visible to end-users, which can be obtained + * by {@link getActiveStep ActiveStep}. Its index in the step collection is given by + * {@link getActiveStepIndex ActiveStepIndex}. + * + * Wizard content can be customized in many ways. + * + * The layout of a wizard consists of four parts: header, step content, navigation + * and side bar. Their content are affected by the following properties, respectively, + * - header: {@link setHeaderText HeaderText} and {@link setHeaderTemplate HeaderTemplate}. + *   If both are present, the latter takes precedence. + * - step: {@link getWizardSteps WizardSteps}. + * - navigation: {@link setStartNavigationTemplate StartNavigationTemplate}, + *   {@link setStepNavigationTemplate StepNavigationTemplate}, + *   {@link setFinishNavigationTemplate FinishNavigationTemplate}. + *   Default templates will be used if above templates are not set. + * - side bar: {@link setSideBarTemplate SideBarTemplate}. + *   A default template will be used if this template is not set. + *   Its visibility is toggled by {@link setShowSideBar ShowSideBar}. + * + * The style of these wizard layout components can be customized via the following style properties, + * - header: {@link getHeaderStyle HeaderStyle}. + * - step: {@link getStepStyle StepStyle}. + * - navigation: {@link getNavigationStyle NavigationStyle}, + *   {@link getStartNextButtonStyle StartNextButtonStyle}, + *   {@link getStepNextButtonStyle StepNextButtonStyle}, + *   {@link getStepPreviousButtonStyle StepPreviousButtonStyle}, + *   {@link getFinishPreviousButtonStyle FinishPreviousButtonStyle}, + *   {@link getFinishCompleteButtonStyle FinishCompleteButtonStyle}, + *   {@link getCancelButtonStyle CancelButtonStyle}. + * - side bar: {@link getSideBarStyle SideBarStyle} and {@link getSideBarButtonStyle SideBarButtonStyle}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizard extends TWebControl implements INamingContainer +{ +	/** +	 * Wizard step types. +	 * @deprecated deprecated since version 3.0.4 (use TWizardStepType constants instead) +	 */ +	const ST_AUTO='Auto'; +	const ST_START='Start'; +	const ST_STEP='Step'; +	const ST_FINISH='Finish'; +	const ST_COMPLETE='Complete'; +	/** +	 * Navigation commands. +	 */ +	const CMD_PREVIOUS='PreviousStep'; +	const CMD_NEXT='NextStep'; +	const CMD_CANCEL='Cancel'; +	const CMD_COMPLETE='Complete'; +	const CMD_MOVETO='MoveTo'; +	/** +	 * Side bar button ID +	 */ +	const ID_SIDEBAR_BUTTON='SideBarButton'; +	/** +	 * Side bar data list +	 */ +	const ID_SIDEBAR_LIST='SideBarList'; + +	/** +	 * @var TMultiView multiview that contains the wizard steps +	 */ +	private $_multiView=null; +	/** +	 * @var mixed navigation template for the start step. +	 */ +	private $_startNavigationTemplate=null; +	/** +	 * @var mixed navigation template for internal steps. +	 */ +	private $_stepNavigationTemplate=null; +	/** +	 * @var mixed navigation template for the finish step. +	 */ +	private $_finishNavigationTemplate=null; +	/** +	 * @var mixed template for wizard header. +	 */ +	private $_headerTemplate=null; +	/** +	 * @var mixed template for the side bar. +	 */ +	private $_sideBarTemplate=null; +	/** +	 * @var TWizardStepCollection +	 */ +	private $_wizardSteps=null; +	/** +	 * @var TPanel container of the wizard header +	 */ +	private $_header; +	/** +	 * @var TPanel container of the wizard step content +	 */ +	private $_stepContent; +	/** +	 * @var TPanel container of the wizard side bar +	 */ +	private $_sideBar; +	/** +	 * @var TPanel navigation panel +	 */ +	private $_navigation; +	/** +	 * @var TWizardNavigationContainer container of the start navigation +	 */ +	private $_startNavigation; +	/** +	 * @var TWizardNavigationContainer container of the step navigation +	 */ +	private $_stepNavigation; +	/** +	 * @var TWizardNavigationContainer container of the finish navigation +	 */ +	private $_finishNavigation; +	/** +	 * @var boolean whether ActiveStepIndex was already set +	 */ +	private $_activeStepIndexSet=false; +	/** +	 * @var TDataList side bar data list. +	 */ +	private $_sideBarDataList; +	/** +	 * @var boolean whether navigation should be cancelled (a status set in OnSideBarButtonClick) +	 */ +	private $_cancelNavigation=false; + +	/** +	 * @return string tag name for the wizard +	 */ +	protected function getTagName() +	{ +		return 'div'; +	} + +	/** +	 * Adds {@link TWizardStep} objects into step collection. +	 * This method overrides the parent implementation and is +	 * invoked when template is being instantiated. +	 * @param mixed object instantiated in template +	 */ +	public function addParsedObject($object) +	{ +		if($object instanceof TWizardStep) +			$this->getWizardSteps()->add($object); +	} + +	/** +	 * @return TWizardStep the currently active wizard step +	 */ +	public function getActiveStep() +	{ +		return $this->getMultiView()->getActiveView(); +	} + +	/** +	 * @param TWizardStep step to be activated +	 * @throws TInvalidOperationException if the step is not in the wizard step collection +	 */ +	public function setActiveStep($step) +	{ +		if(($index=$this->getWizardSteps()->indexOf($step))<0) +			throw new TInvalidOperationException('wizard_step_invalid'); +		$this->setActiveStepIndex($index); +	} + +	/** +	 * @return integer the zero-based index of the active wizard step +	 */ +	public function getActiveStepIndex() +	{ +		return $this->getMultiView()->getActiveViewIndex(); +	} + +	/** +	 * @param integer the zero-based index of the wizard step to be activated +	 */ +	public function setActiveStepIndex($value) +	{ +		$value=TPropertyValue::ensureInteger($value); +		$multiView=$this->getMultiView(); +		if($multiView->getActiveViewIndex()!==$value) +		{ +			$multiView->setActiveViewIndex($value); +			$this->_activeStepIndexSet=true; +			if($this->_sideBarDataList!==null && $this->getSideBarTemplate()!==null) +			{ +				$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex()); +				$this->_sideBarDataList->dataBind(); +			} +		} +	} + +	/** +	 * @return TWizardStepCollection collection of wizard steps +	 */ +	public function getWizardSteps() +	{ +		if($this->_wizardSteps===null) +			$this->_wizardSteps=new TWizardStepCollection($this); +		return $this->_wizardSteps; +	} + +	/** +	 * @return boolean whether to display a cancel button in each wizard step. Defaults to false. +	 */ +	public function getShowCancelButton() +	{ +		return $this->getViewState('ShowCancelButton',false); +	} + +	/** +	 * @param boolean whether to display a cancel button in each wizard step. +	 */ +	public function setShowCancelButton($value) +	{ +		$this->setViewState('ShowCancelButton',TPropertyValue::ensureBoolean($value),false); +	} + +	/** +	 * @return boolean whether to display a side bar that contains links to wizard steps. Defaults to true. +	 */ +	public function getShowSideBar() +	{ +		return $this->getViewState('ShowSideBar',true); +	} + +	/** +	 * @param boolean whether to display a side bar that contains links to wizard steps. +	 */ +	public function setShowSideBar($value) +	{ +		$this->setViewState('ShowSideBar',TPropertyValue::ensureBoolean($value),true); +		$this->requiresControlsRecreation(); +	} + +	/** +	 * @return ITemplate navigation template for the start step. Defaults to null. +	 */ +	public function getStartNavigationTemplate() +	{ +		return $this->_startNavigationTemplate; +	} + +	/** +	 * @param ITemplate navigation template for the start step. +	 */ +	public function setStartNavigationTemplate($value) +	{ +		$this->_startNavigationTemplate=$value; +		$this->requiresControlsRecreation(); +	} + +	/** +	 * @return ITemplate navigation template for internal steps. Defaults to null. +	 */ +	public function getStepNavigationTemplate() +	{ +		return $this->_stepNavigationTemplate; +	} + +	/** +	 * @param ITemplate navigation template for internal steps. +	 */ +	public function setStepNavigationTemplate($value) +	{ +		$this->_stepNavigationTemplate=$value; +		$this->requiresControlsRecreation(); +	} + +	/** +	 * @return ITemplate navigation template for the finish step. Defaults to null. +	 */ +	public function getFinishNavigationTemplate() +	{ +		return $this->_finishNavigationTemplate; +	} + +	/** +	 * @param ITemplate navigation template for the finish step. +	 */ +	public function setFinishNavigationTemplate($value) +	{ +		$this->_finishNavigationTemplate=$value; +		$this->requiresControlsRecreation(); +	} + +	/** +	 * @return ITemplate template for wizard header. Defaults to null. +	 */ +	public function getHeaderTemplate() +	{ +		return $this->_headerTemplate; +	} + +	/** +	 * @param ITemplate template for wizard header. +	 */ +	public function setHeaderTemplate($value) +	{ +		$this->_headerTemplate=$value; +		$this->requiresControlsRecreation(); +	} + +	/** +	 * @return ITemplate template for the side bar. Defaults to null. +	 */ +	public function getSideBarTemplate() +	{ +		return $this->_sideBarTemplate; +	} + +	/** +	 * @param ITemplate template for the side bar. +	 */ +	public function setSideBarTemplate($value) +	{ +		$this->_sideBarTemplate=$value; +		$this->requiresControlsRecreation(); +	} + +	/** +	 * @return string header text. Defaults to ''. +	 */ +	public function getHeaderText() +	{ +		return $this->getViewState('HeaderText',''); +	} + +	/** +	 * @param string header text. +	 */ +	public function setHeaderText($value) +	{ +		$this->setViewState('HeaderText',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string the URL that the browser will be redirected to if the cancel button in the +	 * wizard is clicked. Defaults to ''. +	 */ +	public function getCancelDestinationUrl() +	{ +		return $this->getViewState('CancelDestinationUrl',''); +	} + +	/** +	 * @param string the URL that the browser will be redirected to if the cancel button in the +	 * wizard is clicked. +	 */ +	public function setCancelDestinationUrl($value) +	{ +		$this->setViewState('CancelDestinationUrl',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return string the URL that the browser will be redirected to if the wizard finishes. +	 * Defaults to ''. +	 */ +	public function getFinishDestinationUrl() +	{ +		return $this->getViewState('FinishDestinationUrl',''); +	} + +	/** +	 * @param string the URL that the browser will be redirected to if the wizard finishes. +	 */ +	public function setFinishDestinationUrl($value) +	{ +		$this->setViewState('FinishDestinationUrl',TPropertyValue::ensureString($value),''); +	} + +	/** +	 * @return TStyle the style for the buttons displayed in the side bar. +	 */ +	public function getSideBarButtonStyle() +	{ +		if(($style=$this->getViewState('SideBarButtonStyle',null))===null) +		{ +			$style=new TStyle; +			$this->setViewState('SideBarButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TStyle the style common for all navigation buttons. +	 */ +	public function getNavigationButtonStyle() +	{ +		if(($style=$this->getViewState('NavigationButtonStyle',null))===null) +		{ +			$style=new TStyle; +			$this->setViewState('NavigationButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TWizardNavigationButtonStyle the style for the next button in the start wizard step. +	 */ +	public function getStartNextButtonStyle() +	{ +		if(($style=$this->getViewState('StartNextButtonStyle',null))===null) +		{ +			$style=new TWizardNavigationButtonStyle; +			$style->setButtonText('Next'); +			$this->setViewState('StartNextButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TWizardNavigationButtonStyle the style for the next button in each internal wizard step. +	 */ +	public function getStepNextButtonStyle() +	{ +		if(($style=$this->getViewState('StepNextButtonStyle',null))===null) +		{ +			$style=new TWizardNavigationButtonStyle; +			$style->setButtonText('Next'); +			$this->setViewState('StepNextButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TWizardNavigationButtonStyle the style for the previous button in the start wizard step. +	 */ +	public function getStepPreviousButtonStyle() +	{ +		if(($style=$this->getViewState('StepPreviousButtonStyle',null))===null) +		{ +			$style=new TWizardNavigationButtonStyle; +			$style->setButtonText('Previous'); +			$this->setViewState('StepPreviousButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TWizardNavigationButtonStyle the style for the complete button in the finish wizard step. +	 */ +	public function getFinishCompleteButtonStyle() +	{ +		if(($style=$this->getViewState('FinishCompleteButtonStyle',null))===null) +		{ +			$style=new TWizardNavigationButtonStyle; +			$style->setButtonText('Complete'); +			$this->setViewState('FinishCompleteButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TWizardNavigationButtonStyle the style for the previous button in the start wizard step. +	 */ +	public function getFinishPreviousButtonStyle() +	{ +		if(($style=$this->getViewState('FinishPreviousButtonStyle',null))===null) +		{ +			$style=new TWizardNavigationButtonStyle; +			$style->setButtonText('Previous'); +			$this->setViewState('FinishPreviousButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TWizardNavigationButtonStyle the style for the cancel button +	 */ +	public function getCancelButtonStyle() +	{ +		if(($style=$this->getViewState('CancelButtonStyle',null))===null) +		{ +			$style=new TWizardNavigationButtonStyle; +			$style->setButtonText('Cancel'); +			$this->setViewState('CancelButtonStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TPanelStyle the style for the side bar. +	 */ +	public function getSideBarStyle() +	{ +		if(($style=$this->getViewState('SideBarStyle',null))===null) +		{ +			$style=new TPanelStyle; +			$this->setViewState('SideBarStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TPanelStyle the style for the header. +	 */ +	public function getHeaderStyle() +	{ +		if(($style=$this->getViewState('HeaderStyle',null))===null) +		{ +			$style=new TPanelStyle; +			$this->setViewState('HeaderStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TPanelStyle the style for each internal wizard step. +	 */ +	public function getStepStyle() +	{ +		if(($style=$this->getViewState('StepStyle',null))===null) +		{ +			$style=new TPanelStyle; +			$this->setViewState('StepStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return TPanelStyle the style for the navigation panel. +	 */ +	public function getNavigationStyle() +	{ +		if(($style=$this->getViewState('NavigationStyle',null))===null) +		{ +			$style=new TPanelStyle; +			$this->setViewState('NavigationStyle',$style,null); +		} +		return $style; +	} + +	/** +	 * @return boolean whether to use default layout to arrange side bar and the rest wizard components. Defaults to true. +	 */ +	public function getUseDefaultLayout() +	{ +		return $this->getViewState('UseDefaultLayout',true); +	} + +	/** +	 * @param boolean whether to use default layout to arrange side bar and the rest wizard components. +	 * If true, an HTML table will be used which places the side bar in the left cell +	 * while the rest components in the right cell. +	 */ +	public function setUseDefaultLayout($value) +	{ +		$this->setViewState('UseDefaultLayout',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return TPanel container of the wizard header +	 */ +	public function getHeader() +	{ +		return $this->_header; +	} + +	/** +	 * @return TPanel container of the wizard step content +	 */ +	public function getStepContent() +	{ +		return $this->_stepContent; +	} + +	/** +	 * @return TPanel container of the wizard side bar +	 */ +	public function getSideBar() +	{ +		return $this->_sideBar; +	} + +	/** +	 * @return TWizardNavigationContainer container of the start navigation +	 */ +	public function getStartNavigation() +	{ +		return $this->_startNavigation; +	} + +	/** +	 * @return TWizardNavigationContainer container of the step navigation +	 */ +	public function getStepNavigation() +	{ +		return $this->_stepNavigation; +	} + +	/** +	 * @return TWizardNavigationContainer container of the finish navigation +	 */ +	public function getFinishNavigation() +	{ +		return $this->_finishNavigation; +	} + +	/** +	 * Raises <b>OnActiveStepChanged</b> event. +	 * This event is raised when the current visible step is changed in the +	 * wizard. +	 * @param TEventParameter event parameter +	 */ +	public function onActiveStepChanged($param) +	{ +		$this->raiseEvent('OnActiveStepChanged',$this,$param); +	} + +	/** +	 * Raises <b>OnCancelButtonClick</b> event. +	 * This event is raised when a cancel navigation button is clicked in the +	 * current active step. +	 * @param TEventParameter event parameter +	 */ +	public function onCancelButtonClick($param) +	{ +		$this->raiseEvent('OnCancelButtonClick',$this,$param); +		if(($url=$this->getCancelDestinationUrl())!=='') +			$this->getResponse()->redirect($url); +	} + +	/** +	 * Raises <b>OnCompleteButtonClick</b> event. +	 * This event is raised when a finish navigation button is clicked in the +	 * current active step. +	 * @param TWizardNavigationEventParameter event parameter +	 */ +	public function onCompleteButtonClick($param) +	{ +		$this->raiseEvent('OnCompleteButtonClick',$this,$param); +		if(($url=$this->getFinishDestinationUrl())!=='') +			$this->getResponse()->redirect($url); +	} + +	/** +	 * Raises <b>OnNextButtonClick</b> event. +	 * This event is raised when a next navigation button is clicked in the +	 * current active step. +	 * @param TWizardNavigationEventParameter event parameter +	 */ +	public function onNextButtonClick($param) +	{ +		$this->raiseEvent('OnNextButtonClick',$this,$param); +	} + +	/** +	 * Raises <b>OnPreviousButtonClick</b> event. +	 * This event is raised when a previous navigation button is clicked in the +	 * current active step. +	 * @param TWizardNavigationEventParameter event parameter +	 */ +	public function onPreviousButtonClick($param) +	{ +		$this->raiseEvent('OnPreviousButtonClick',$this,$param); +	} + +	/** +	 * Raises <b>OnSideBarButtonClick</b> event. +	 * This event is raised when a link button in the side bar is clicked. +	 * @param TWizardNavigationEventParameter event parameter +	 */ +	public function onSideBarButtonClick($param) +	{ +		$this->raiseEvent('OnSideBarButtonClick',$this,$param); +	} + +	/** +	 * Returns the multiview that holds the wizard steps. +	 * This method should only be used by control developers. +	 * @return TMultiView the multiview holding wizard steps +	 */ +	public function getMultiView() +	{ +		if($this->_multiView===null) +		{ +			$this->_multiView=new TMultiView; +			$this->_multiView->setID('WizardMultiView'); +			$this->_multiView->attachEventHandler('OnActiveViewChanged',array($this,'onActiveStepChanged')); +			$this->_multiView->ignoreBubbleEvents(); +		} +		return $this->_multiView; +	} + +	/** +	 * Adds a wizard step to the multiview. +	 * This method should only be used by control developers. +	 * It is invoked when a step is added into the step collection of the wizard. +	 * @param TWizardStep wizard step to be added into multiview. +	 */ +	public function addedWizardStep($step) +	{ +		if(($wizard=$step->getWizard())!==null) +			$wizard->getWizardSteps()->remove($step); +		$step->setWizard($this); +		$this->wizardStepsChanged(); +	} + +	/** +	 * Removes a wizard step from the multiview. +	 * This method should only be used by control developers. +	 * It is invoked when a step is removed from the step collection of the wizard. +	 * @param TWizardStep wizard step to be removed from multiview. +	 */ +	public function removedWizardStep($step) +	{ +		$step->setWizard(null); +		$this->wizardStepsChanged(); +	} + +	/** +	 * Creates the child controls of the wizard. +	 * This method overrides the parent implementation. +	 * @param TEventParameter event parameter +	 */ +	public function onInit($param) +	{ +		parent::onInit($param); +		$this->ensureChildControls(); +		if($this->getActiveStepIndex()<0 && $this->getWizardSteps()->getCount()>0) +			$this->setActiveStepIndex(0); +	} + +	/** +	 * Saves the current active step index into history. +	 * This method is invoked by the framework when the control state is being saved. +	 */ +	public function saveState() +	{ +		$index=$this->getActiveStepIndex(); +		$history=$this->getHistory(); +		if(!$history->getCount() || $history->peek()!==$index) +			$history->push($index); +	} + +	/** +	 * Indicates the wizard needs to recreate all child controls. +	 */ +	protected function requiresControlsRecreation() +	{ +		if($this->getChildControlsCreated()) +			$this->setChildControlsCreated(false); +	} + +	/** +	 * Renders the wizard. +	 * @param THtmlWriter +	 */ +	public function render($writer) +	{ +		$this->ensureChildControls(); +		if($this->getHasControls()) +		{ +			if($this->getUseDefaultLayout()) +			{ +				$this->applyControlProperties(); +				$this->renderBeginTag($writer); +				$writer->write("\n<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" height=\"100%\" width=\"100%\">\n<tr><td width=\"1\" valign=\"top\">\n"); +				$this->_sideBar->renderControl($writer); +				$writer->write("\n</td><td valign=\"top\">\n"); +				$this->_header->renderControl($writer); +				$this->_stepContent->renderControl($writer); +				$this->_navigation->renderControl($writer); +				$writer->write("\n</td></tr></table>\n"); +				$this->renderEndTag($writer); +			} +			else +			{ +				$this->applyControlProperties(); +				$this->renderBeginTag($writer); +				$this->_sideBar->renderControl($writer); +				$this->_header->renderControl($writer); +				$this->_stepContent->renderControl($writer); +				$this->_navigation->renderControl($writer); +				$this->renderEndTag($writer); +			} +		} +	} + +	/** +	 * Applies various properties to the components of wizard +	 */ +	protected function applyControlProperties() +	{ +		$this->applyHeaderProperties(); +		$this->applySideBarProperties(); +		$this->applyStepContentProperties(); +		$this->applyNavigationProperties(); +	} + +	/** +	 * Applies properties to the wizard header +	 */ +	protected function applyHeaderProperties() +	{ +		if(($style=$this->getViewState('HeaderStyle',null))!==null) +			$this->_header->getStyle()->mergeWith($style); +		if($this->getHeaderTemplate()===null) +		{ +			$this->_header->getControls()->clear(); +			$this->_header->getControls()->add($this->getHeaderText()); +		} +	} + +	/** +	 * Applies properties to the wizard sidebar +	 */ +	protected function applySideBarProperties() +	{ +		$this->_sideBar->setVisible($this->getShowSideBar()); +		if($this->_sideBarDataList!==null && $this->getShowSideBar()) +		{ +			$this->_sideBarDataList->setDataSource($this->getWizardSteps()); +			$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex()); +			$this->_sideBarDataList->dataBind(); +			if(($style=$this->getViewState('SideBarButtonStyle',null))!==null) +			{ +				foreach($this->_sideBarDataList->getItems() as $item) +				{ +					if(($button=$item->findControl('SideBarButton'))!==null) +						$button->getStyle()->mergeWith($style); +				} +			} +		} +		if(($style=$this->getViewState('SideBarStyle',null))!==null) +			$this->_sideBar->getStyle()->mergeWith($style); +	} + +	/** +	 * Applies properties to the wizard step content +	 */ +	protected function applyStepContentProperties() +	{ +		if(($style=$this->getViewState('StepStyle',null))!==null) +			$this->_stepContent->getStyle()->mergeWith($style); +	} + +	/** +	 * Apply properties to various navigation panels. +	 */ +	protected function applyNavigationProperties() +	{ +		$wizardSteps=$this->getWizardSteps(); +		$activeStep=$this->getActiveStep(); +		$activeStepIndex=$this->getActiveStepIndex(); + +		if(!$this->_navigation) +			return; +		else if($activeStepIndex<0 || $activeStepIndex>=$wizardSteps->getCount()) +		{ +			$this->_navigation->setVisible(false); +			return; +		} + +		// set visibility of different types of navigation panel +		$showStandard=true; +		foreach($wizardSteps as $step) +		{ +			if(($step instanceof TTemplatedWizardStep) && ($container=$step->getNavigationContainer())!==null) +			{ +				if($activeStep===$step) +				{ +					$container->setVisible(true); +					$showStandard=false; +				} +				else +					$container->setVisible(false); +			} +		} +		$activeStepType=$this->getStepType($activeStep); +		if($activeStepType===TWizardStepType::Complete) +		{ +			$this->_sideBar->setVisible(false); +			$this->_header->setVisible(false); +		} +		$this->_startNavigation->setVisible($showStandard && $activeStepType===self::ST_START); +		$this->_stepNavigation->setVisible($showStandard && $activeStepType===self::ST_STEP); +		$this->_finishNavigation->setVisible($showStandard && $activeStepType===self::ST_FINISH); + +		if(($navigationStyle=$this->getViewState('NavigationStyle',null))!==null) +			$this->_navigation->getStyle()->mergeWith($navigationStyle); + +		$displayCancelButton=$this->getShowCancelButton(); +		$cancelButtonStyle=$this->getCancelButtonStyle(); +		$buttonStyle=$this->getViewState('NavigationButtonStyle',null); +		if($buttonStyle!==null) +			$cancelButtonStyle->mergeWith($buttonStyle); + +		// apply styles to start navigation buttons +		if(($cancelButton=$this->_startNavigation->getCancelButton())!==null) +		{ +			$cancelButton->setVisible($displayCancelButton); +			$cancelButtonStyle->apply($cancelButton); +		} +		if(($button=$this->_startNavigation->getNextButton())!==null) +		{ +			$button->setVisible(true); +			$style=$this->getStartNextButtonStyle(); +			if($buttonStyle!==null) +				$style->mergeWith($buttonStyle); +			$style->apply($button); +			if($activeStepType===TWizardStepType::Start) +				$this->getPage()->getClientScript()->registerDefaultButton($this, $button); +		} + +		// apply styles to finish navigation buttons +		if(($cancelButton=$this->_finishNavigation->getCancelButton())!==null) +		{ +			$cancelButton->setVisible($displayCancelButton); +			$cancelButtonStyle->apply($cancelButton); +		} +		if(($button=$this->_finishNavigation->getPreviousButton())!==null) +		{ +			$button->setVisible($this->allowNavigationToPreviousStep()); +			$style=$this->getFinishPreviousButtonStyle(); +			if($buttonStyle!==null) +				$style->mergeWith($buttonStyle); +			$style->apply($button); +		} +		if(($button=$this->_finishNavigation->getCompleteButton())!==null) +		{ +			$button->setVisible(true); +			$style=$this->getFinishCompleteButtonStyle(); +			if($buttonStyle!==null) +				$style->mergeWith($buttonStyle); +			$style->apply($button); +			if($activeStepType===TWizardStepType::Finish) +				$this->getPage()->getClientScript()->registerDefaultButton($this, $button); +		} + +		// apply styles to step navigation buttons +		if(($cancelButton=$this->_stepNavigation->getCancelButton())!==null) +		{ +			$cancelButton->setVisible($displayCancelButton); +			$cancelButtonStyle->apply($cancelButton); +		} +		if(($button=$this->_stepNavigation->getPreviousButton())!==null) +		{ +			$button->setVisible($this->allowNavigationToPreviousStep()); +			$style=$this->getStepPreviousButtonStyle(); +			if($buttonStyle!==null) +				$style->mergeWith($buttonStyle); +			$style->apply($button); +		} +		if(($button=$this->_stepNavigation->getNextButton())!==null) +		{ +			$button->setVisible(true); +			$style=$this->getStepNextButtonStyle(); +			if($buttonStyle!==null) +				$style->mergeWith($buttonStyle); +			$style->apply($button); +			if($activeStepType===TWizardStepType::Step) +				$this->getPage()->getClientScript()->registerDefaultButton($this, $button); +		} +	} + +	/** +	 * @return TStack history containing step indexes that were navigated before +	 */ +	protected function getHistory() +	{ +		if(($history=$this->getControlState('History',null))===null) +		{ +			$history=new TStack; +			$this->setControlState('History',$history); +		} +		return $history; +	} + +	/** +	 * Determines the type of the specified wizard step. +	 * @param TWizardStep +	 * @return TWizardStepType type of the step +	 */ +	protected function getStepType($wizardStep) +	{ +		if(($type=$wizardStep->getStepType())===TWizardStepType::Auto) +		{ +			$steps=$this->getWizardSteps(); +			if(($index=$steps->indexOf($wizardStep))>=0) +			{ +				$stepCount=$steps->getCount(); +				if($stepCount===1 || ($index<$stepCount-1 && $steps->itemAt($index+1)->getStepType()===TWizardStepType::Complete)) +					return TWizardStepType::Finish; +				else if($index===0) +					return TWizardStepType::Start; +				else if($index===$stepCount-1) +					return TWizardStepType::Finish; +				else +					return TWizardStepType::Step; +			} +			else +				return $type; +		} +		else +			return $type; +	} + +	/** +	 * Clears up everything within the wizard. +	 */ +	protected function reset() +	{ +		$this->getControls()->clear(); +		$this->_header=null; +		$this->_stepContent=null; +		$this->_sideBar=null; +		$this->_sideBarDataList=null; +		$this->_navigation=null; +		$this->_startNavigation=null; +		$this->_stepNavigation=null; +		$this->_finishNavigation=null; +	} + +	/** +	 * Creates child controls within the wizard +	 */ +	public function createChildControls() +	{ +		$this->reset(); +		$this->createSideBar(); +		$this->createHeader(); +		$this->createStepContent(); +		$this->createNavigation(); +//		$this->clearChildState(); +	} + +	/** +	 * Creates the wizard header. +	 */ +	protected function createHeader() +	{ +		$this->_header=new TPanel; +		if(($template=$this->getHeaderTemplate())!==null) +			$template->instantiateIn($this->_header); +		else +			$this->_header->getControls()->add($this->getHeaderText()); +		$this->getControls()->add($this->_header); +	} + +	/** +	 * Creates the wizard side bar +	 */ +	protected function createSideBar() +	{ +		if($this->getShowSideBar()) +		{ +			if(($template=$this->getSideBarTemplate())===null) +				$template=new TWizardSideBarTemplate; +			$this->_sideBar=new TPanel; +			$template->instantiateIn($this->_sideBar); +			$this->getControls()->add($this->_sideBar); + +			if(($this->_sideBarDataList=$this->_sideBar->findControl(self::ID_SIDEBAR_LIST))!==null) +			{ +				$this->_sideBarDataList->attachEventHandler('OnItemCommand',array($this,'dataListItemCommand')); +				$this->_sideBarDataList->attachEventHandler('OnItemDataBound',array($this,'dataListItemDataBound')); +				$this->_sideBarDataList->setDataSource($this->getWizardSteps()); +				$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex()); +				$this->_sideBarDataList->dataBind(); +			} +		} +		else +		{ +			$this->_sideBar=new TPanel; +			$this->getControls()->add($this->_sideBar); +		} +	} + +	/** +	 * Event handler for sidebar datalist's OnItemCommand event. +	 * This method is used internally by wizard. It mainly +	 * sets the active step index according to the button clicked in the sidebar. +	 * @param mixed sender of the event +	 * @param TDataListCommandEventParameter +	 */ +	public function dataListItemCommand($sender,$param) +	{ +		$item=$param->getItem(); +		if($param->getCommandName()===self::CMD_MOVETO) +		{ +			$stepIndex=$this->getActiveStepIndex(); +			$newStepIndex=TPropertyValue::ensureInteger($param->getCommandParameter()); +			$navParam=new TWizardNavigationEventParameter($stepIndex); +			$navParam->setNextStepIndex($newStepIndex); + +			// if the button clicked causes validation which fails, +			// by default we will cancel navigation to the new step +			$button=$param->getCommandSource(); +			if(($button instanceof IButtonControl) && $button->getCausesValidation() && ($page=$this->getPage())!==null && !$page->getIsValid()) +				$navParam->setCancelNavigation(true); + +			$this->_activeStepIndexSet=false; +			$this->onSideBarButtonClick($navParam); +			$this->_cancelNavigation=$navParam->getCancelNavigation(); +			if(!$this->_cancelNavigation) +			{ +				if(!$this->_activeStepIndexSet && $this->allowNavigationToStep($newStepIndex)) +					$this->setActiveStepIndex($newStepIndex); +			} +			else +				$this->setActiveStepIndex($stepIndex); +		} +	} + +	/** +	 * Event handler for sidebar datalist's OnItemDataBound event. +	 * This method is used internally by wizard. It mainly configures +	 * the buttons in the sidebar datalist. +	 * @param mixed sender of the event +	 * @param TDataListItemEventParameter +	 */ +	public function dataListItemDataBound($sender,$param) +	{ +		$item=$param->getItem(); +		$itemType=$item->getItemType(); +		if($itemType==='Item' || $itemType==='AlternatingItem' || $itemType==='SelectedItem' || $itemType==='EditItem') +		{ +			if(($button=$item->findControl(self::ID_SIDEBAR_BUTTON))!==null) +			{ +				$step=$item->getData(); +				if(($this->getStepType($step)===TWizardStepType::Complete)) +					$button->setEnabled(false); +				if(($title=$step->getTitle())!=='') +					$button->setText($title); +				else +					$button->setText($step->getID(false)); +				$index=$this->getWizardSteps()->indexOf($step); +				$button->setCommandName(self::CMD_MOVETO); +				$button->setCommandParameter("$index"); +			} +		} +	} + +	/** +	 * Creates wizard step content. +	 */ +	protected function createStepContent() +	{ +		foreach($this->getWizardSteps() as $step) +		{ +			if($step instanceof TTemplatedWizardStep) +				$step->ensureChildControls(); +		} +		$multiView=$this->getMultiView(); +		$this->_stepContent=new TPanel; +		$this->_stepContent->getControls()->add($multiView); +		$this->getControls()->add($this->_stepContent); +		if($multiView->getViews()->getCount()) +			$multiView->setActiveViewIndex(0); +	} + +	/** +	 * Creates navigation panel. +	 */ +	protected function createNavigation() +	{ +		$this->_navigation=new TPanel; +		$this->getControls()->add($this->_navigation); +		$controls=$this->_navigation->getControls(); +		foreach($this->getWizardSteps() as $step) +		{ +			if($step instanceof TTemplatedWizardStep) +			{ +				$step->instantiateNavigationTemplate(); +				if(($panel=$step->getNavigationContainer())!==null) +					$controls->add($panel); +			} +		} +		$this->_startNavigation=$this->createStartNavigation(); +		$controls->add($this->_startNavigation); +		$this->_stepNavigation=$this->createStepNavigation(); +		$controls->add($this->_stepNavigation); +		$this->_finishNavigation=$this->createFinishNavigation(); +		$controls->add($this->_finishNavigation); +	} + +	/** +	 * Creates start navigation panel. +	 */ +	protected function createStartNavigation() +	{ +		if(($template=$this->getStartNavigationTemplate())===null) +			$template=new TWizardStartNavigationTemplate($this); +		$navigation=new TWizardNavigationContainer; +		$template->instantiateIn($navigation); +		return $navigation; +	} + +	/** +	 * Creates step navigation panel. +	 */ +	protected function createStepNavigation() +	{ +		if(($template=$this->getStepNavigationTemplate())===null) +			$template=new TWizardStepNavigationTemplate($this); +		$navigation=new TWizardNavigationContainer; +		$template->instantiateIn($navigation); +		return $navigation; +	} + +	/** +	 * Creates finish navigation panel. +	 */ +	protected function createFinishNavigation() +	{ +		if(($template=$this->getFinishNavigationTemplate())===null) +			$template=new TWizardFinishNavigationTemplate($this); +		$navigation=new TWizardNavigationContainer; +		$template->instantiateIn($navigation); +		return $navigation; +	} + +	/** +	 * Updates the sidebar datalist if any. +	 * This method is invoked when any wizard step is changed. +	 */ +	public function wizardStepsChanged() +	{ +		if($this->_sideBarDataList!==null) +		{ +			$this->_sideBarDataList->setDataSource($this->getWizardSteps()); +			$this->_sideBarDataList->setSelectedItemIndex($this->getActiveStepIndex()); +			$this->_sideBarDataList->dataBind(); +		} +	} + +	/** +	 * Determines the index of the previous step based on history. +	 * @param boolean whether the first item in the history stack should be popped +	 * up after calling this method. +	 */ +	protected function getPreviousStepIndex($popStack) +	{ +		$history=$this->getHistory(); +		if($history->getCount()>=0) +		{ +			$activeStepIndex=$this->getActiveStepIndex(); +			$previousStepIndex=-1; +			if($popStack) +			{ +				$previousStepIndex=$history->pop(); +				if($activeStepIndex===$previousStepIndex && $history->getCount()>0) +					$previousStepIndex=$history->pop(); +			} +			else +			{ +				$previousStepIndex=$history->peek(); +				if($activeStepIndex===$previousStepIndex && $history->getCount()>1) +				{ +					$saveIndex=$history->pop(); +					$previousStepIndex=$history->peek(); +					$history->push($saveIndex); +				} +			} +			return $activeStepIndex===$previousStepIndex ? -1 : $previousStepIndex; +		} +		else +			return -1; +	} + +	/** +	 * @return boolean whether navigation to the previous step is allowed +	 */ +	protected function allowNavigationToPreviousStep() +	{ +		if(($index=$this->getPreviousStepIndex(false))!==-1) +			return $this->getWizardSteps()->itemAt($index)->getAllowReturn(); +		else +			return false; +	} + +	/** +	 * @param integer index of the step +	 * @return boolean whether navigation to the specified step is allowed +	 */ +	protected function allowNavigationToStep($index) +	{ +		if($this->getHistory()->contains($index)) +			return $this->getWizardSteps()->itemAt($index)->getAllowReturn(); +		else +			return true; +	} + +	/** +	 * Handles bubbled events. +	 * This method mainly translate certain command events into +	 * wizard-specific events. +	 * @param mixed sender of the original command event +	 * @param TEventParameter event parameter +	 * @throws TInvalidDataValueException if a navigation command is associated with an invalid parameter +	 */ +	public function bubbleEvent($sender,$param) +	{ +		if($param instanceof TCommandEventParameter) +		{ +			$command=$param->getCommandName(); +			if(strcasecmp($command,self::CMD_CANCEL)===0) +			{ +				$this->onCancelButtonClick($param); +				return true; +			} + +			$type=$this->getStepType($this->getActiveStep()); +			$index=$this->getActiveStepIndex(); +			$navParam=new TWizardNavigationEventParameter($index); +			if(($sender instanceof IButtonControl) && $sender->getCausesValidation() && ($page=$this->getPage())!==null && !$page->getIsValid()) +				$navParam->setCancelNavigation(true); + +			$handled=false; +			$movePrev=false; +			$this->_activeStepIndexSet=false; + +			if(strcasecmp($command,self::CMD_NEXT)===0) +			{ +				if($type!==self::ST_START && $type!==self::ST_STEP) +					throw new TInvalidDataValueException('wizard_command_invalid',self::CMD_NEXT); +				if($index<$this->getWizardSteps()->getCount()-1) +					$navParam->setNextStepIndex($index+1); +				$this->onNextButtonClick($navParam); +				$handled=true; +			} +			else if(strcasecmp($command,self::CMD_PREVIOUS)===0) +			{ +				if($type!==self::ST_FINISH && $type!==self::ST_STEP) +					throw new TInvalidDataValueException('wizard_command_invalid',self::CMD_PREVIOUS); +				$movePrev=true; +				if(($prevIndex=$this->getPreviousStepIndex(false))>=0) +					$navParam->setNextStepIndex($prevIndex); +				$this->onPreviousButtonClick($navParam); +				$handled=true; +			} +			else if(strcasecmp($command,self::CMD_COMPLETE)===0) +			{ +				if($type!==self::ST_FINISH) +					throw new TInvalidDataValueException('wizard_command_invalid',self::CMD_COMPLETE); +				if($index<$this->getWizardSteps()->getCount()-1) +					$navParam->setNextStepIndex($index+1); +				$this->onCompleteButtonClick($navParam); +				$handled=true; +			} +			else if(strcasecmp($command,self::CMD_MOVETO)===0) +			{ +				if($this->_cancelNavigation)  // may be set in onSideBarButtonClick  					$navParam->setCancelNavigation(true);  				$requestedStep=$param->getCommandParameter();  				if (!is_numeric($requestedStep)) @@ -1412,750 +1412,750 @@ class TWizard extends TWebControl implements INamingContainer  						throw new TConfigurationException('wizard_step_invalid');  				}  				else -					$requestedIndex=TPropertyValue::ensureInteger($requestedStep);
 -				$navParam->setNextStepIndex($requestedIndex);
 -				$handled=true;
 -			}
 -
 -			if($handled)
 -			{
 -				if(!$navParam->getCancelNavigation())
 -				{
 -					$nextStepIndex=$navParam->getNextStepIndex();
 -					if(!$this->_activeStepIndexSet && $this->allowNavigationToStep($nextStepIndex))
 -					{
 -						if($movePrev)
 -							$this->getPreviousStepIndex(true);  // pop out the previous move from history
 -						$this->setActiveStepIndex($nextStepIndex);
 -					}
 -				}
 -				else
 -					$this->setActiveStepIndex($index);
 -				return true;
 -			}
 -		}
 -		return false;
 -	}
 -}
 -
 -
 -/**
 - * TWizardStep class.
 - *
 - * TWizardStep represents a wizard step. The wizard owning the step
 - * can be obtained by {@link getWizard Wizard}.
 - * To specify the type of the step, set {@link setStepType StepType};
 - * For step title, set {@link setTitle Title}. If a step can be re-visited,
 - * set {@link setAllowReturn AllowReturn} to true.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardStep extends TView
 -{
 -	private $_wizard;
 -
 -	/**
 -	 * @return TWizard the wizard owning this step
 -	 */
 -	public function getWizard()
 -	{
 -		return $this->_wizard;
 -	}
 -
 -	/**
 -	 * Sets the wizard owning this step.
 -	 * This method is used internally by {@link TWizard}.
 -	 * @param TWizard the wizard owning this step
 -	 */
 -	public function setWizard($wizard)
 -	{
 -		$this->_wizard=$wizard;
 -	}
 -
 -	/**
 -	 * @return string the title for this step.
 -	 */
 -	public function getTitle()
 -	{
 -		return $this->getViewState('Title','');
 -	}
 -
 -	/**
 -	 * @param string the title for this step.
 -	 */
 -	public function setTitle($value)
 -	{
 -		$this->setViewState('Title',$value,'');
 -		if($this->_wizard)
 -			$this->_wizard->wizardStepsChanged();
 -	}
 -
 -	/**
 -	 * @return boolean whether this step can be re-visited. Default to true.
 -	 */
 -	public function getAllowReturn()
 -	{
 -		return $this->getViewState('AllowReturn',true);
 -	}
 -
 -	/**
 -	 * @param boolean whether this step can be re-visited.
 -	 */
 -	public function setAllowReturn($value)
 -	{
 -		$this->setViewState('AllowReturn',TPropertyValue::ensureBoolean($value),true);
 -	}
 -
 -	/**
 -	 * @return TWizardStepType the wizard step type. Defaults to TWizardStepType::Auto.
 -	 */
 -	public function getStepType()
 -	{
 -		return $this->getViewState('StepType',TWizardStepType::Auto);
 -	}
 -
 -	/**
 -	 * @param TWizardStepType the wizard step type.
 -	 */
 -	public function setStepType($type)
 -	{
 -		$type=TPropertyValue::ensureEnum($type,'TWizardStepType');
 -		if($type!==$this->getStepType())
 -		{
 -			$this->setViewState('StepType',$type,TWizardStepType::Auto);
 -			if($this->_wizard)
 -				$this->_wizard->wizardStepsChanged();
 -		}
 -	}
 -}
 -
 -
 -/**
 - * TCompleteWizardStep class.
 - *
 - * TCompleteWizardStep represents a wizard step of type TWizardStepType::Complete.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TCompleteWizardStep extends TWizardStep
 -{
 -	/**
 -	 * @return TWizardStepType the wizard step type. Always TWizardStepType::Complete.
 -	 */
 -	public function getStepType()
 -	{
 -		return TWizardStepType::Complete;
 -	}
 -
 -	/**
 -	 * @param string the wizard step type.
 -	 * @throws TInvalidOperationException whenever this method is invoked.
 -	 */
 -	public function setStepType($value)
 -	{
 -		throw new TInvalidOperationException('completewizardstep_steptype_readonly');
 -	}
 -}
 -
 -
 -/**
 - * TTemplatedWizardStep class.
 - *
 - * TTemplatedWizardStep represents a wizard step whose content and navigation
 - * can be customized using templates. To customize the step content, specify
 - * {@link setContentTemplate ContentTemplate}. To customize navigation specific
 - * to the step, specify {@link setNavigationTemplate NavigationTemplate}. Note,
 - * if the navigation template is not specified, default navigation will be used.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TTemplatedWizardStep extends TWizardStep implements INamingContainer
 -{
 -	/**
 -	 * @var ITemplate the template for displaying the navigation UI of a wizard step.
 -	 */
 -	private $_navigationTemplate=null;
 -	/**
 -	 * @var ITemplate the template for displaying the content within the wizard step.
 -	 */
 -	private $_contentTemplate=null;
 -	/**
 -	 * @var TWizardNavigationContainer
 -	 */
 -	private $_navigationContainer=null;
 -
 -	/**
 -	 * Creates child controls.
 -	 * This method mainly instantiates the content template, if any.
 -	 */
 -	public function createChildControls()
 -	{
 -		$this->getControls()->clear();
 -		if($this->_contentTemplate)
 -			$this->_contentTemplate->instantiateIn($this);
 -	}
 -
 -	/**
 -	 * Ensures child controls are created.
 -	 * @param mixed event parameter
 -	 */
 -	public function onInit($param)
 -	{
 -		parent::onInit($param);
 -		$this->ensureChildControls();
 -	}
 -
 -	/**
 -	 * @return ITemplate the template for the content of the wizard step.
 -	 */
 -	public function getContentTemplate()
 -	{
 -		return $this->_contentTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template for the content of the wizard step.
 -	 */
 -	public function setContentTemplate($value)
 -	{
 -		$this->_contentTemplate=$value;
 -	}
 -
 -	/**
 -	 * @return ITemplate the template for displaying the navigation UI of a wizard step. Defaults to null.
 -	 */
 -	public function getNavigationTemplate()
 -	{
 -		return $this->_navigationTemplate;
 -	}
 -
 -	/**
 -	 * @param ITemplate the template for displaying the navigation UI of a wizard step.
 -	 */
 -	public function setNavigationTemplate($value)
 -	{
 -		$this->_navigationTemplate=$value;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationContainer the control containing the navigation.
 -	 * It could be null if no navigation template is specified.
 -	 */
 -	public function getNavigationContainer()
 -	{
 -		return $this->_navigationContainer;
 -	}
 -
 -	/**
 -	 * Instantiates the navigation template if any
 -	 */
 -	public function instantiateNavigationTemplate()
 -	{
 -		if(!$this->_navigationContainer && $this->_navigationTemplate)
 -		{
 -			$this->_navigationContainer=new TWizardNavigationContainer;
 -			$this->_navigationTemplate->instantiateIn($this->_navigationContainer);
 -		}
 -	}
 -}
 -
 -
 -/**
 - * TWizardStepCollection class.
 - *
 - * TWizardStepCollection represents the collection of wizard steps owned
 - * by a {@link TWizard}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardStepCollection extends TList
 -{
 -	/**
 -	 * @var TWizard
 -	 */
 -	private $_wizard;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TWizard wizard that owns this collection
 -	 */
 -	public function __construct(TWizard $wizard)
 -	{
 -		$this->_wizard=$wizard;
 -	}
 -
 -	/**
 -	 * Inserts an item at the specified position.
 -	 * This method overrides the parent implementation by checking if
 -	 * the item being added is a {@link TWizardStep}.
 -	 * @param integer the speicified position.
 -	 * @param mixed new item
 -	 * @throws TInvalidDataTypeException if the item being added is not TWizardStep.
 -	 */
 -	public function insertAt($index,$item)
 -	{
 -		if($item instanceof TWizardStep)
 -		{
 -			parent::insertAt($index,$item);
 -			$this->_wizard->getMultiView()->getViews()->insertAt($index,$item);
 -			$this->_wizard->addedWizardStep($item);
 -		}
 -		else
 -			throw new TInvalidDataTypeException('wizardstepcollection_wizardstep_required');
 -	}
 -
 -	/**
 -	 * Removes an item at the specified position.
 -	 * @param integer the index of the item to be removed.
 -	 * @return mixed the removed item.
 -	 */
 -	public function removeAt($index)
 -	{
 -		$step=parent::removeAt($index);
 -		$this->_wizard->getMultiView()->getViews()->remove($step);
 -		$this->_wizard->removedWizardStep($step);
 -		return $step;
 -	}
 -}
 -
 -
 -/**
 - * TWizardNavigationContainer class.
 - *
 - * TWizardNavigationContainer represents a control containing
 - * a wizard navigation. The navigation may contain a few buttons, including
 - * {@link getPreviousButton PreviousButton}, {@link getNextButton NextButton},
 - * {@link getCancelButton CancelButton}, {@link getCompleteButton CompleteButton}.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardNavigationContainer extends TControl implements INamingContainer
 -{
 -	private $_previousButton=null;
 -	private $_nextButton=null;
 -	private $_cancelButton=null;
 -	private $_completeButton=null;
 -
 -	/**
 -	 * @return mixed the previous button
 -	 */
 -	public function getPreviousButton()
 -	{
 -		return $this->_previousButton;
 -	}
 -
 -	/**
 -	 * @param mixed the previous button
 -	 */
 -	public function setPreviousButton($value)
 -	{
 -		$this->_previousButton=$value;
 -	}
 -
 -	/**
 -	 * @return mixed the next button
 -	 */
 -	public function getNextButton()
 -	{
 -		return $this->_nextButton;
 -	}
 -
 -	/**
 -	 * @param mixed the next button
 -	 */
 -	public function setNextButton($value)
 -	{
 -		$this->_nextButton=$value;
 -	}
 -
 -	/**
 -	 * @return mixed the cancel button
 -	 */
 -	public function getCancelButton()
 -	{
 -		return $this->_cancelButton;
 -	}
 -
 -	/**
 -	 * @param mixed the cancel button
 -	 */
 -	public function setCancelButton($value)
 -	{
 -		$this->_cancelButton=$value;
 -	}
 -
 -	/**
 -	 * @return mixed the complete button
 -	 */
 -	public function getCompleteButton()
 -	{
 -		return $this->_completeButton;
 -	}
 -
 -	/**
 -	 * @param mixed the complete button
 -	 */
 -	public function setCompleteButton($value)
 -	{
 -		$this->_completeButton=$value;
 -	}
 -}
 -
 -
 -/**
 - * TWizardNavigationEventParameter class.
 - *
 - * TWizardNavigationEventParameter represents the parameter for
 - * {@link TWizard}'s navigation events.
 - *
 - * The index of the currently active step can be obtained from
 - * {@link getCurrentStepIndex CurrentStepIndex}, while the index
 - * of the candidate new step is in {@link getNextStepIndex NextStepIndex}.
 - * By modifying {@link setNextStepIndex NextStepIndex}, the new step
 - * can be changed to another one. If there is anything wrong with
 - * the navigation and it is not wanted, set {@link setCancelNavigation CancelNavigation}
 - * to true.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardNavigationEventParameter extends TEventParameter
 -{
 -	private $_cancel=false;
 -	private $_currentStep;
 -	private $_nextStep;
 -
 -	/**
 -	 * Constructor.
 -	 * @param integer current step index
 -	 */
 -	public function __construct($currentStep)
 -	{
 -		$this->_currentStep=$currentStep;
 -		$this->_nextStep=$currentStep;
 -	}
 -
 -	/**
 -	 * @return integer the zero-based index of the currently active step.
 -	 */
 -	public function getCurrentStepIndex()
 -	{
 -		return $this->_currentStep;
 -	}
 -
 -	/**
 -	 * @return integer the zero-based index of the next step. Default to {@link getCurrentStepIndex CurrentStepIndex}.
 -	 */
 -	public function getNextStepIndex()
 -	{
 -		return $this->_nextStep;
 -	}
 -
 -	/**
 -	 * @param integer the zero-based index of the next step.
 -	 */
 -	public function setNextStepIndex($index)
 -	{
 -		$this->_nextStep=TPropertyValue::ensureInteger($index);
 -	}
 -
 -	/**
 -	 * @return boolean whether navigation to the next step should be canceled. Default to false.
 -	 */
 -	public function getCancelNavigation()
 -	{
 -		return $this->_cancel;
 -	}
 -
 -	/**
 -	 * @param boolean whether navigation to the next step should be canceled.
 -	 */
 -	public function setCancelNavigation($value)
 -	{
 -		$this->_cancel=TPropertyValue::ensureBoolean($value);
 -	}
 -}
 -
 -/**
 - * TWizardSideBarTemplate class.
 - * TWizardSideBarTemplate is the default template for wizard sidebar.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardSideBarTemplate extends TComponent implements ITemplate
 -{
 -	/**
 -	 * Instantiates the template.
 -	 * It creates a {@link TDataList} control.
 -	 * @param TControl parent to hold the content within the template
 -	 */
 -	public function instantiateIn($parent)
 -	{
 -		$dataList=new TDataList;
 -		$dataList->setID(TWizard::ID_SIDEBAR_LIST);
 -		$dataList->getSelectedItemStyle()->getFont()->setBold(true);
 -		$dataList->setItemTemplate(new TWizardSideBarListItemTemplate);
 -		$parent->getControls()->add($dataList);
 -	}
 -}
 -
 -/**
 - * TWizardSideBarListItemTemplate class.
 - * TWizardSideBarListItemTemplate is the default template for each item in the sidebar datalist.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardSideBarListItemTemplate extends TComponent implements ITemplate
 -{
 -	/**
 -	 * Instantiates the template.
 -	 * It creates a {@link TLinkButton}.
 -	 * @param TControl parent to hold the content within the template
 -	 */
 -	public function instantiateIn($parent)
 -	{
 -		$button=new TLinkButton;
 -		$button->setID(TWizard::ID_SIDEBAR_BUTTON);
 -		$parent->getControls()->add($button);
 -	}
 -}
 -
 -/**
 - * TWizardNavigationTemplate class.
 - * TWizardNavigationTemplate is the base class for various navigation templates.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardNavigationTemplate extends TComponent implements ITemplate
 -{
 -	private $_wizard;
 -
 -	/**
 -	 * Constructor.
 -	 * @param TWizard the wizard owning this template
 -	 */
 -	public function __construct($wizard)
 -	{
 -		$this->_wizard=$wizard;
 -	}
 -
 -	/**
 -	 * @return TWizard the wizard owning this template
 -	 */
 -	public function getWizard()
 -	{
 -		return $this->_wizard;
 -	}
 -
 -	/**
 -	 * Instantiates the template.
 -	 * Derived classes should override this method.
 -	 * @param TControl parent to hold the content within the template
 -	 */
 -	public function instantiateIn($parent)
 -	{
 -	}
 -
 -	/**
 -	 * Creates a navigation button.
 -	 * It creates a {@link TButton}, {@link TLinkButton}, or {@link TImageButton},
 -	 * depending on the given parameters.
 -	 * @param TWizardNavigationButtonStyle button style
 -	 * @param boolean whether the button should cause validation
 -	 * @param string command name for the button's OnCommand event
 -	 * @throws TInvalidDataValueException if the button type is not recognized
 -	 */
 -	protected function createNavigationButton($buttonStyle,$causesValidation,$commandName)
 -	{
 -		switch($buttonStyle->getButtonType())
 -		{
 -			case TWizardNavigationButtonType::Button:
 -				$button=new TButton;
 -				break;
 -			case TWizardNavigationButtonType::Link:
 -				$button=new TLinkButton;
 -				break;
 -			case TWizardNavigationButtonType::Image:
 -				$button=new TImageButton;
 -				$button->setImageUrl($buttonStyle->getImageUrl());
 -				break;
 -			default:
 -				throw new TInvalidDataValueException('wizard_buttontype_unknown',$buttonStyle->getButtonType());
 -		}
 -		$button->setText($buttonStyle->getButtonText());
 -		$button->setCausesValidation($causesValidation);
 -		$button->setCommandName($commandName);
 -		return $button;
 -	}
 -}
 -
 -/**
 - * TWizardStartNavigationTemplate class.
 - * TWizardStartNavigationTemplate is the template used as default wizard start navigation panel.
 - * It consists of two buttons, Next and Cancel.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardStartNavigationTemplate extends TWizardNavigationTemplate
 -{
 -	/**
 -	 * Instantiates the template.
 -	 * @param TControl parent to hold the content within the template
 -	 */
 -	public function instantiateIn($parent)
 -	{
 -		$nextButton=$this->createNavigationButton($this->getWizard()->getStartNextButtonStyle(),true,TWizard::CMD_NEXT);
 -		$cancelButton=$this->createNavigationButton($this->getWizard()->getCancelButtonStyle(),false,TWizard::CMD_CANCEL);
 -
 -		$controls=$parent->getControls();
 -		$controls->add($nextButton);
 -		$controls->add("\n");
 -		$controls->add($cancelButton);
 -
 -		$parent->setNextButton($nextButton);
 -		$parent->setCancelButton($cancelButton);
 -	}
 -}
 -
 -/**
 - * TWizardFinishNavigationTemplate class.
 - * TWizardFinishNavigationTemplate is the template used as default wizard finish navigation panel.
 - * It consists of three buttons, Previous, Complete and Cancel.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardFinishNavigationTemplate extends TWizardNavigationTemplate
 -{
 -	/**
 -	 * Instantiates the template.
 -	 * @param TControl parent to hold the content within the template
 -	 */
 -	public function instantiateIn($parent)
 -	{
 -		$previousButton=$this->createNavigationButton($this->getWizard()->getFinishPreviousButtonStyle(),false,TWizard::CMD_PREVIOUS);
 -		$completeButton=$this->createNavigationButton($this->getWizard()->getFinishCompleteButtonStyle(),true,TWizard::CMD_COMPLETE);
 -		$cancelButton=$this->createNavigationButton($this->getWizard()->getCancelButtonStyle(),false,TWizard::CMD_CANCEL);
 -
 -		$controls=$parent->getControls();
 -		$controls->add($previousButton);
 -		$controls->add("\n");
 -		$controls->add($completeButton);
 -		$controls->add("\n");
 -		$controls->add($cancelButton);
 -
 -		$parent->setPreviousButton($previousButton);
 -		$parent->setCompleteButton($completeButton);
 -		$parent->setCancelButton($cancelButton);
 -	}
 -}
 -
 -/**
 - * TWizardStepNavigationTemplate class.
 - * TWizardStepNavigationTemplate is the template used as default wizard step navigation panel.
 - * It consists of three buttons, Previous, Next and Cancel.
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardStepNavigationTemplate extends TWizardNavigationTemplate
 -{
 -	/**
 -	 * Instantiates the template.
 -	 * @param TControl parent to hold the content within the template
 -	 */
 -	public function instantiateIn($parent)
 -	{
 -		$previousButton=$this->createNavigationButton($this->getWizard()->getStepPreviousButtonStyle(),false,TWizard::CMD_PREVIOUS);
 -		$nextButton=$this->createNavigationButton($this->getWizard()->getStepNextButtonStyle(),true,TWizard::CMD_NEXT);
 -		$cancelButton=$this->createNavigationButton($this->getWizard()->getCancelButtonStyle(),false,TWizard::CMD_CANCEL);
 -
 -		$controls=$parent->getControls();
 -		$controls->add($previousButton);
 -		$controls->add("\n");
 -		$controls->add($nextButton);
 -		$controls->add("\n");
 -		$controls->add($cancelButton);
 -
 -		$parent->setPreviousButton($previousButton);
 -		$parent->setNextButton($nextButton);
 -		$parent->setCancelButton($cancelButton);
 -	}
 -}
 -
 -
 -/**
 - * TWizardNavigationButtonType class.
 - * TWizardNavigationButtonType defines the enumerable type for the possible types of buttons
 - * that can be used in the navigation part of a {@link TWizard}.
 - *
 - * The following enumerable values are defined:
 - * - Button: a regular click button
 - * - Image: an image button
 - * - Link: a hyperlink button
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TWizardNavigationButtonType extends TEnumerable
 -{
 -	const Button='Button';
 -	const Image='Image';
 -	const Link='Link';
 -}
 -
 -
 -/**
 - * TWizardStepType class.
 - * TWizardStepType defines the enumerable type for the possible types of {@link TWizard wizard} steps.
 - *
 - * The following enumerable values are defined:
 - * - Auto: the type is automatically determined based on the location of the wizard step in the whole step collection.
 - * - Complete: the step is the last summary step.
 - * - Start: the step is the first step
 - * - Step: the step is between the begin and the end steps.
 - * - Finish: the last step before the Complete step.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0.4
 - */
 -class TWizardStepType extends TEnumerable
 -{
 -	const Auto='Auto';
 -	const Complete='Complete';
 -	const Start='Start';
 -	const Step='Step';
 -	const Finish='Finish';
 -}
 -
 +					$requestedIndex=TPropertyValue::ensureInteger($requestedStep); +				$navParam->setNextStepIndex($requestedIndex); +				$handled=true; +			} + +			if($handled) +			{ +				if(!$navParam->getCancelNavigation()) +				{ +					$nextStepIndex=$navParam->getNextStepIndex(); +					if(!$this->_activeStepIndexSet && $this->allowNavigationToStep($nextStepIndex)) +					{ +						if($movePrev) +							$this->getPreviousStepIndex(true);  // pop out the previous move from history +						$this->setActiveStepIndex($nextStepIndex); +					} +				} +				else +					$this->setActiveStepIndex($index); +				return true; +			} +		} +		return false; +	} +} + + +/** + * TWizardStep class. + * + * TWizardStep represents a wizard step. The wizard owning the step + * can be obtained by {@link getWizard Wizard}. + * To specify the type of the step, set {@link setStepType StepType}; + * For step title, set {@link setTitle Title}. If a step can be re-visited, + * set {@link setAllowReturn AllowReturn} to true. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardStep extends TView +{ +	private $_wizard; + +	/** +	 * @return TWizard the wizard owning this step +	 */ +	public function getWizard() +	{ +		return $this->_wizard; +	} + +	/** +	 * Sets the wizard owning this step. +	 * This method is used internally by {@link TWizard}. +	 * @param TWizard the wizard owning this step +	 */ +	public function setWizard($wizard) +	{ +		$this->_wizard=$wizard; +	} + +	/** +	 * @return string the title for this step. +	 */ +	public function getTitle() +	{ +		return $this->getViewState('Title',''); +	} + +	/** +	 * @param string the title for this step. +	 */ +	public function setTitle($value) +	{ +		$this->setViewState('Title',$value,''); +		if($this->_wizard) +			$this->_wizard->wizardStepsChanged(); +	} + +	/** +	 * @return boolean whether this step can be re-visited. Default to true. +	 */ +	public function getAllowReturn() +	{ +		return $this->getViewState('AllowReturn',true); +	} + +	/** +	 * @param boolean whether this step can be re-visited. +	 */ +	public function setAllowReturn($value) +	{ +		$this->setViewState('AllowReturn',TPropertyValue::ensureBoolean($value),true); +	} + +	/** +	 * @return TWizardStepType the wizard step type. Defaults to TWizardStepType::Auto. +	 */ +	public function getStepType() +	{ +		return $this->getViewState('StepType',TWizardStepType::Auto); +	} + +	/** +	 * @param TWizardStepType the wizard step type. +	 */ +	public function setStepType($type) +	{ +		$type=TPropertyValue::ensureEnum($type,'TWizardStepType'); +		if($type!==$this->getStepType()) +		{ +			$this->setViewState('StepType',$type,TWizardStepType::Auto); +			if($this->_wizard) +				$this->_wizard->wizardStepsChanged(); +		} +	} +} + + +/** + * TCompleteWizardStep class. + * + * TCompleteWizardStep represents a wizard step of type TWizardStepType::Complete. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TCompleteWizardStep extends TWizardStep +{ +	/** +	 * @return TWizardStepType the wizard step type. Always TWizardStepType::Complete. +	 */ +	public function getStepType() +	{ +		return TWizardStepType::Complete; +	} + +	/** +	 * @param string the wizard step type. +	 * @throws TInvalidOperationException whenever this method is invoked. +	 */ +	public function setStepType($value) +	{ +		throw new TInvalidOperationException('completewizardstep_steptype_readonly'); +	} +} + + +/** + * TTemplatedWizardStep class. + * + * TTemplatedWizardStep represents a wizard step whose content and navigation + * can be customized using templates. To customize the step content, specify + * {@link setContentTemplate ContentTemplate}. To customize navigation specific + * to the step, specify {@link setNavigationTemplate NavigationTemplate}. Note, + * if the navigation template is not specified, default navigation will be used. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TTemplatedWizardStep extends TWizardStep implements INamingContainer +{ +	/** +	 * @var ITemplate the template for displaying the navigation UI of a wizard step. +	 */ +	private $_navigationTemplate=null; +	/** +	 * @var ITemplate the template for displaying the content within the wizard step. +	 */ +	private $_contentTemplate=null; +	/** +	 * @var TWizardNavigationContainer +	 */ +	private $_navigationContainer=null; + +	/** +	 * Creates child controls. +	 * This method mainly instantiates the content template, if any. +	 */ +	public function createChildControls() +	{ +		$this->getControls()->clear(); +		if($this->_contentTemplate) +			$this->_contentTemplate->instantiateIn($this); +	} + +	/** +	 * Ensures child controls are created. +	 * @param mixed event parameter +	 */ +	public function onInit($param) +	{ +		parent::onInit($param); +		$this->ensureChildControls(); +	} + +	/** +	 * @return ITemplate the template for the content of the wizard step. +	 */ +	public function getContentTemplate() +	{ +		return $this->_contentTemplate; +	} + +	/** +	 * @param ITemplate the template for the content of the wizard step. +	 */ +	public function setContentTemplate($value) +	{ +		$this->_contentTemplate=$value; +	} + +	/** +	 * @return ITemplate the template for displaying the navigation UI of a wizard step. Defaults to null. +	 */ +	public function getNavigationTemplate() +	{ +		return $this->_navigationTemplate; +	} + +	/** +	 * @param ITemplate the template for displaying the navigation UI of a wizard step. +	 */ +	public function setNavigationTemplate($value) +	{ +		$this->_navigationTemplate=$value; +	} + +	/** +	 * @return TWizardNavigationContainer the control containing the navigation. +	 * It could be null if no navigation template is specified. +	 */ +	public function getNavigationContainer() +	{ +		return $this->_navigationContainer; +	} + +	/** +	 * Instantiates the navigation template if any +	 */ +	public function instantiateNavigationTemplate() +	{ +		if(!$this->_navigationContainer && $this->_navigationTemplate) +		{ +			$this->_navigationContainer=new TWizardNavigationContainer; +			$this->_navigationTemplate->instantiateIn($this->_navigationContainer); +		} +	} +} + + +/** + * TWizardStepCollection class. + * + * TWizardStepCollection represents the collection of wizard steps owned + * by a {@link TWizard}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardStepCollection extends TList +{ +	/** +	 * @var TWizard +	 */ +	private $_wizard; + +	/** +	 * Constructor. +	 * @param TWizard wizard that owns this collection +	 */ +	public function __construct(TWizard $wizard) +	{ +		$this->_wizard=$wizard; +	} + +	/** +	 * Inserts an item at the specified position. +	 * This method overrides the parent implementation by checking if +	 * the item being added is a {@link TWizardStep}. +	 * @param integer the speicified position. +	 * @param mixed new item +	 * @throws TInvalidDataTypeException if the item being added is not TWizardStep. +	 */ +	public function insertAt($index,$item) +	{ +		if($item instanceof TWizardStep) +		{ +			parent::insertAt($index,$item); +			$this->_wizard->getMultiView()->getViews()->insertAt($index,$item); +			$this->_wizard->addedWizardStep($item); +		} +		else +			throw new TInvalidDataTypeException('wizardstepcollection_wizardstep_required'); +	} + +	/** +	 * Removes an item at the specified position. +	 * @param integer the index of the item to be removed. +	 * @return mixed the removed item. +	 */ +	public function removeAt($index) +	{ +		$step=parent::removeAt($index); +		$this->_wizard->getMultiView()->getViews()->remove($step); +		$this->_wizard->removedWizardStep($step); +		return $step; +	} +} + + +/** + * TWizardNavigationContainer class. + * + * TWizardNavigationContainer represents a control containing + * a wizard navigation. The navigation may contain a few buttons, including + * {@link getPreviousButton PreviousButton}, {@link getNextButton NextButton}, + * {@link getCancelButton CancelButton}, {@link getCompleteButton CompleteButton}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardNavigationContainer extends TControl implements INamingContainer +{ +	private $_previousButton=null; +	private $_nextButton=null; +	private $_cancelButton=null; +	private $_completeButton=null; + +	/** +	 * @return mixed the previous button +	 */ +	public function getPreviousButton() +	{ +		return $this->_previousButton; +	} + +	/** +	 * @param mixed the previous button +	 */ +	public function setPreviousButton($value) +	{ +		$this->_previousButton=$value; +	} + +	/** +	 * @return mixed the next button +	 */ +	public function getNextButton() +	{ +		return $this->_nextButton; +	} + +	/** +	 * @param mixed the next button +	 */ +	public function setNextButton($value) +	{ +		$this->_nextButton=$value; +	} + +	/** +	 * @return mixed the cancel button +	 */ +	public function getCancelButton() +	{ +		return $this->_cancelButton; +	} + +	/** +	 * @param mixed the cancel button +	 */ +	public function setCancelButton($value) +	{ +		$this->_cancelButton=$value; +	} + +	/** +	 * @return mixed the complete button +	 */ +	public function getCompleteButton() +	{ +		return $this->_completeButton; +	} + +	/** +	 * @param mixed the complete button +	 */ +	public function setCompleteButton($value) +	{ +		$this->_completeButton=$value; +	} +} + + +/** + * TWizardNavigationEventParameter class. + * + * TWizardNavigationEventParameter represents the parameter for + * {@link TWizard}'s navigation events. + * + * The index of the currently active step can be obtained from + * {@link getCurrentStepIndex CurrentStepIndex}, while the index + * of the candidate new step is in {@link getNextStepIndex NextStepIndex}. + * By modifying {@link setNextStepIndex NextStepIndex}, the new step + * can be changed to another one. If there is anything wrong with + * the navigation and it is not wanted, set {@link setCancelNavigation CancelNavigation} + * to true. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardNavigationEventParameter extends TEventParameter +{ +	private $_cancel=false; +	private $_currentStep; +	private $_nextStep; + +	/** +	 * Constructor. +	 * @param integer current step index +	 */ +	public function __construct($currentStep) +	{ +		$this->_currentStep=$currentStep; +		$this->_nextStep=$currentStep; +	} + +	/** +	 * @return integer the zero-based index of the currently active step. +	 */ +	public function getCurrentStepIndex() +	{ +		return $this->_currentStep; +	} + +	/** +	 * @return integer the zero-based index of the next step. Default to {@link getCurrentStepIndex CurrentStepIndex}. +	 */ +	public function getNextStepIndex() +	{ +		return $this->_nextStep; +	} + +	/** +	 * @param integer the zero-based index of the next step. +	 */ +	public function setNextStepIndex($index) +	{ +		$this->_nextStep=TPropertyValue::ensureInteger($index); +	} + +	/** +	 * @return boolean whether navigation to the next step should be canceled. Default to false. +	 */ +	public function getCancelNavigation() +	{ +		return $this->_cancel; +	} + +	/** +	 * @param boolean whether navigation to the next step should be canceled. +	 */ +	public function setCancelNavigation($value) +	{ +		$this->_cancel=TPropertyValue::ensureBoolean($value); +	} +} + +/** + * TWizardSideBarTemplate class. + * TWizardSideBarTemplate is the default template for wizard sidebar. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardSideBarTemplate extends TComponent implements ITemplate +{ +	/** +	 * Instantiates the template. +	 * It creates a {@link TDataList} control. +	 * @param TControl parent to hold the content within the template +	 */ +	public function instantiateIn($parent) +	{ +		$dataList=new TDataList; +		$dataList->setID(TWizard::ID_SIDEBAR_LIST); +		$dataList->getSelectedItemStyle()->getFont()->setBold(true); +		$dataList->setItemTemplate(new TWizardSideBarListItemTemplate); +		$parent->getControls()->add($dataList); +	} +} + +/** + * TWizardSideBarListItemTemplate class. + * TWizardSideBarListItemTemplate is the default template for each item in the sidebar datalist. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardSideBarListItemTemplate extends TComponent implements ITemplate +{ +	/** +	 * Instantiates the template. +	 * It creates a {@link TLinkButton}. +	 * @param TControl parent to hold the content within the template +	 */ +	public function instantiateIn($parent) +	{ +		$button=new TLinkButton; +		$button->setID(TWizard::ID_SIDEBAR_BUTTON); +		$parent->getControls()->add($button); +	} +} + +/** + * TWizardNavigationTemplate class. + * TWizardNavigationTemplate is the base class for various navigation templates. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardNavigationTemplate extends TComponent implements ITemplate +{ +	private $_wizard; + +	/** +	 * Constructor. +	 * @param TWizard the wizard owning this template +	 */ +	public function __construct($wizard) +	{ +		$this->_wizard=$wizard; +	} + +	/** +	 * @return TWizard the wizard owning this template +	 */ +	public function getWizard() +	{ +		return $this->_wizard; +	} + +	/** +	 * Instantiates the template. +	 * Derived classes should override this method. +	 * @param TControl parent to hold the content within the template +	 */ +	public function instantiateIn($parent) +	{ +	} + +	/** +	 * Creates a navigation button. +	 * It creates a {@link TButton}, {@link TLinkButton}, or {@link TImageButton}, +	 * depending on the given parameters. +	 * @param TWizardNavigationButtonStyle button style +	 * @param boolean whether the button should cause validation +	 * @param string command name for the button's OnCommand event +	 * @throws TInvalidDataValueException if the button type is not recognized +	 */ +	protected function createNavigationButton($buttonStyle,$causesValidation,$commandName) +	{ +		switch($buttonStyle->getButtonType()) +		{ +			case TWizardNavigationButtonType::Button: +				$button=new TButton; +				break; +			case TWizardNavigationButtonType::Link: +				$button=new TLinkButton; +				break; +			case TWizardNavigationButtonType::Image: +				$button=new TImageButton; +				$button->setImageUrl($buttonStyle->getImageUrl()); +				break; +			default: +				throw new TInvalidDataValueException('wizard_buttontype_unknown',$buttonStyle->getButtonType()); +		} +		$button->setText($buttonStyle->getButtonText()); +		$button->setCausesValidation($causesValidation); +		$button->setCommandName($commandName); +		return $button; +	} +} + +/** + * TWizardStartNavigationTemplate class. + * TWizardStartNavigationTemplate is the template used as default wizard start navigation panel. + * It consists of two buttons, Next and Cancel. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardStartNavigationTemplate extends TWizardNavigationTemplate +{ +	/** +	 * Instantiates the template. +	 * @param TControl parent to hold the content within the template +	 */ +	public function instantiateIn($parent) +	{ +		$nextButton=$this->createNavigationButton($this->getWizard()->getStartNextButtonStyle(),true,TWizard::CMD_NEXT); +		$cancelButton=$this->createNavigationButton($this->getWizard()->getCancelButtonStyle(),false,TWizard::CMD_CANCEL); + +		$controls=$parent->getControls(); +		$controls->add($nextButton); +		$controls->add("\n"); +		$controls->add($cancelButton); + +		$parent->setNextButton($nextButton); +		$parent->setCancelButton($cancelButton); +	} +} + +/** + * TWizardFinishNavigationTemplate class. + * TWizardFinishNavigationTemplate is the template used as default wizard finish navigation panel. + * It consists of three buttons, Previous, Complete and Cancel. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardFinishNavigationTemplate extends TWizardNavigationTemplate +{ +	/** +	 * Instantiates the template. +	 * @param TControl parent to hold the content within the template +	 */ +	public function instantiateIn($parent) +	{ +		$previousButton=$this->createNavigationButton($this->getWizard()->getFinishPreviousButtonStyle(),false,TWizard::CMD_PREVIOUS); +		$completeButton=$this->createNavigationButton($this->getWizard()->getFinishCompleteButtonStyle(),true,TWizard::CMD_COMPLETE); +		$cancelButton=$this->createNavigationButton($this->getWizard()->getCancelButtonStyle(),false,TWizard::CMD_CANCEL); + +		$controls=$parent->getControls(); +		$controls->add($previousButton); +		$controls->add("\n"); +		$controls->add($completeButton); +		$controls->add("\n"); +		$controls->add($cancelButton); + +		$parent->setPreviousButton($previousButton); +		$parent->setCompleteButton($completeButton); +		$parent->setCancelButton($cancelButton); +	} +} + +/** + * TWizardStepNavigationTemplate class. + * TWizardStepNavigationTemplate is the template used as default wizard step navigation panel. + * It consists of three buttons, Previous, Next and Cancel. + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardStepNavigationTemplate extends TWizardNavigationTemplate +{ +	/** +	 * Instantiates the template. +	 * @param TControl parent to hold the content within the template +	 */ +	public function instantiateIn($parent) +	{ +		$previousButton=$this->createNavigationButton($this->getWizard()->getStepPreviousButtonStyle(),false,TWizard::CMD_PREVIOUS); +		$nextButton=$this->createNavigationButton($this->getWizard()->getStepNextButtonStyle(),true,TWizard::CMD_NEXT); +		$cancelButton=$this->createNavigationButton($this->getWizard()->getCancelButtonStyle(),false,TWizard::CMD_CANCEL); + +		$controls=$parent->getControls(); +		$controls->add($previousButton); +		$controls->add("\n"); +		$controls->add($nextButton); +		$controls->add("\n"); +		$controls->add($cancelButton); + +		$parent->setPreviousButton($previousButton); +		$parent->setNextButton($nextButton); +		$parent->setCancelButton($cancelButton); +	} +} + + +/** + * TWizardNavigationButtonType class. + * TWizardNavigationButtonType defines the enumerable type for the possible types of buttons + * that can be used in the navigation part of a {@link TWizard}. + * + * The following enumerable values are defined: + * - Button: a regular click button + * - Image: an image button + * - Link: a hyperlink button + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TWizardNavigationButtonType extends TEnumerable +{ +	const Button='Button'; +	const Image='Image'; +	const Link='Link'; +} + + +/** + * TWizardStepType class. + * TWizardStepType defines the enumerable type for the possible types of {@link TWizard wizard} steps. + * + * The following enumerable values are defined: + * - Auto: the type is automatically determined based on the location of the wizard step in the whole step collection. + * - Complete: the step is the last summary step. + * - Start: the step is the first step + * - Step: the step is between the begin and the end steps. + * - Finish: the last step before the Complete step. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0.4 + */ +class TWizardStepType extends TEnumerable +{ +	const Auto='Auto'; +	const Complete='Complete'; +	const Start='Start'; +	const Step='Step'; +	const Finish='Finish'; +} + diff --git a/framework/Web/UI/WebControls/TWizardNavigationButtonStyle.php b/framework/Web/UI/WebControls/TWizardNavigationButtonStyle.php index 0e05c556..c3b4b603 100644 --- a/framework/Web/UI/WebControls/TWizardNavigationButtonStyle.php +++ b/framework/Web/UI/WebControls/TWizardNavigationButtonStyle.php @@ -1,155 +1,155 @@ -<?php
 -/**
 - * TWizardNavigationButtonStyle class file.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 +<?php +/** + * TWizardNavigationButtonStyle class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/   * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id $
 - * @package System.Web.UI.WebControls
 - */
 -
 -/**
 - * Includes TStyle class file
 - */
 -Prado::using('System.Web.UI.WebControls.TStyle');
 -
 -/**
 - * TWizardNavigationButtonStyle class.
 - * TWizardNavigationButtonStyle defines the style applied to a wizard navigation button.
 - * The button type can be specified via {@link setButtonType ButtonType}, which
 - * can be 'Button', 'Image' or 'Link'.
 - * If the button is an image button, {@link setImageUrl ImageUrl} will be
 - * used to load the image for the button.
 - * Otherwise, {@link setButtonText ButtonText} will be displayed as the button caption.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @version $Id$
 - * @package System.Web.UI.WebControls
 - * @since 3.0
 - */
 -class TWizardNavigationButtonStyle extends TStyle
 -{
 -	private $_imageUrl=null;
 -	private $_buttonText=null;
 -	private $_buttonType=null;
 -
 -	/**
 -	 * Sets the style attributes to default values.
 -	 * This method overrides the parent implementation by
 -	 * resetting additional TWizardNavigationButtonStyle specific attributes.
 -	 */
 -	public function reset()
 -	{
 -		parent::reset();
 -		$this->_imageUrl=null;
 -		$this->_buttonText=null;
 -		$this->_buttonType=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 TWizardNavigationButtonStyle)
 -		{
 -			if($this->_imageUrl===null && $style->_imageUrl!==null)
 -				$this->_imageUrl=$style->_imageUrl;
 -			if($this->_buttonText===null && $style->_buttonText!==null)
 -				$this->_buttonText=$style->_buttonText;
 -			if($this->_buttonType===null && $style->_buttonType!==null)
 -				$this->_buttonType=$style->_buttonType;
 -		}
 -	}
 -
 -	/**
 -	 * 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 TWizardNavigationButtonStyle)
 -		{
 -			if($style->_imageUrl!==null)
 -				$this->_imageUrl=$style->_imageUrl;
 -			if($style->_buttonText!==null)
 -				$this->_buttonText=$style->_buttonText;
 -			if($style->_buttonType!==null)
 -				$this->_buttonType=$style->_buttonType;
 -		}
 -	}
 -
 -	/**
 -	 * @return string image URL for the image button
 -	 */
 -	public function getImageUrl()
 -	{
 -		return $this->_imageUrl===null?'':$this->_imageUrl;
 -	}
 -
 -	/**
 -	 * @param string image URL for the image button
 -	 */
 -	public function setImageUrl($value)
 -	{
 -		$this->_imageUrl=$value;
 -	}
 -
 -	/**
 -	 * @return string button caption
 -	 */
 -	public function getButtonText()
 -	{
 -		return $this->_buttonText===null?'':$this->_buttonText;
 -	}
 -
 -	/**
 -	 * @param string button caption
 -	 */
 -	public function setButtonText($value)
 -	{
 -		$this->_buttonText=$value;
 -	}
 -
 -	/**
 -	 * @return TWizardNavigationButtonType button type. Default to TWizardNavigationButtonType::Button.
 -	 */
 -	public function getButtonType()
 -	{
 -		return $this->_buttonType===null? TWizardNavigationButtonType::Button :$this->_buttonType;
 -	}
 -
 -	/**
 -	 * @param TWizardNavigationButtonType button type.
 -	 */
 -	public function setButtonType($value)
 -	{
 -		$this->_buttonType=TPropertyValue::ensureEnum($value,'TWizardNavigationButtonType');
 -	}
 -
 -	/**
 -	 * Applies this style to the specified button
 -	 * @param mixed button to be applied with this style
 -	 */
 -	public function apply($button)
 -	{
 -		if($button instanceof TImageButton)
 -		{
 -			if($button->getImageUrl()==='')
 -				$button->setImageUrl($this->getImageUrl());
 -		}
 -		if($button->getText()==='')
 -			$button->setText($this->getButtonText());
 -		$button->getStyle()->mergeWith($this);
 -	}
 -}
 -
 + * @license http://www.pradosoft.com/license/ + * @version $Id $ + * @package System.Web.UI.WebControls + */ + +/** + * Includes TStyle class file + */ +Prado::using('System.Web.UI.WebControls.TStyle'); + +/** + * TWizardNavigationButtonStyle class. + * TWizardNavigationButtonStyle defines the style applied to a wizard navigation button. + * The button type can be specified via {@link setButtonType ButtonType}, which + * can be 'Button', 'Image' or 'Link'. + * If the button is an image button, {@link setImageUrl ImageUrl} will be + * used to load the image for the button. + * Otherwise, {@link setButtonText ButtonText} will be displayed as the button caption. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TWizardNavigationButtonStyle extends TStyle +{ +	private $_imageUrl=null; +	private $_buttonText=null; +	private $_buttonType=null; + +	/** +	 * Sets the style attributes to default values. +	 * This method overrides the parent implementation by +	 * resetting additional TWizardNavigationButtonStyle specific attributes. +	 */ +	public function reset() +	{ +		parent::reset(); +		$this->_imageUrl=null; +		$this->_buttonText=null; +		$this->_buttonType=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 TWizardNavigationButtonStyle) +		{ +			if($this->_imageUrl===null && $style->_imageUrl!==null) +				$this->_imageUrl=$style->_imageUrl; +			if($this->_buttonText===null && $style->_buttonText!==null) +				$this->_buttonText=$style->_buttonText; +			if($this->_buttonType===null && $style->_buttonType!==null) +				$this->_buttonType=$style->_buttonType; +		} +	} + +	/** +	 * 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 TWizardNavigationButtonStyle) +		{ +			if($style->_imageUrl!==null) +				$this->_imageUrl=$style->_imageUrl; +			if($style->_buttonText!==null) +				$this->_buttonText=$style->_buttonText; +			if($style->_buttonType!==null) +				$this->_buttonType=$style->_buttonType; +		} +	} + +	/** +	 * @return string image URL for the image button +	 */ +	public function getImageUrl() +	{ +		return $this->_imageUrl===null?'':$this->_imageUrl; +	} + +	/** +	 * @param string image URL for the image button +	 */ +	public function setImageUrl($value) +	{ +		$this->_imageUrl=$value; +	} + +	/** +	 * @return string button caption +	 */ +	public function getButtonText() +	{ +		return $this->_buttonText===null?'':$this->_buttonText; +	} + +	/** +	 * @param string button caption +	 */ +	public function setButtonText($value) +	{ +		$this->_buttonText=$value; +	} + +	/** +	 * @return TWizardNavigationButtonType button type. Default to TWizardNavigationButtonType::Button. +	 */ +	public function getButtonType() +	{ +		return $this->_buttonType===null? TWizardNavigationButtonType::Button :$this->_buttonType; +	} + +	/** +	 * @param TWizardNavigationButtonType button type. +	 */ +	public function setButtonType($value) +	{ +		$this->_buttonType=TPropertyValue::ensureEnum($value,'TWizardNavigationButtonType'); +	} + +	/** +	 * Applies this style to the specified button +	 * @param mixed button to be applied with this style +	 */ +	public function apply($button) +	{ +		if($button instanceof TImageButton) +		{ +			if($button->getImageUrl()==='') +				$button->setImageUrl($this->getImageUrl()); +		} +		if($button->getText()==='') +			$button->setText($this->getButtonText()); +		$button->getStyle()->mergeWith($this); +	} +} + diff --git a/framework/Web/UI/WebControls/assets/captcha.php b/framework/Web/UI/WebControls/assets/captcha.php index b26df895..08a857b5 100644 --- a/framework/Web/UI/WebControls/assets/captcha.php +++ b/framework/Web/UI/WebControls/assets/captcha.php @@ -1,224 +1,224 @@ -<?php
 -/**
 - * CAPTCHA generator script.
 - *
 - * @author Qiang Xue <qiang.xue@gmail.com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2012 PradoSoft
 - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Web.UI.WebControls.assets
 - */
 -
 -define('THEME_OPAQUE_BACKGROUND',0x0001);
 -define('THEME_NOISY_BACKGROUND',0x0002);
 -define('THEME_HAS_GRID',0x0004);
 -define('THEME_HAS_SCRIBBLE',0x0008);
 -define('THEME_MORPH_BACKGROUND',0x0010);
 -define('THEME_SHADOWED_TEXT',0x0020);
 -
 -require_once(dirname(__FILE__).'/captcha_key.php');
 -
 -$token='error';
 -$theme=0;
 -
 -if(isset($_GET['options']))
 -{
 -	$str=base64_decode($_GET['options']);
 -	if(strlen($str)>32)
 -	{
 -		$hash=substr($str,0,32);
 -		$str=substr($str,32);
 -		if(md5($privateKey.$str)===$hash)
 -		{
 -			$options=unserialize($str);
 -			$publicKey=$options['publicKey'];
 -			$tokenLength=$options['tokenLength'];
 -			$caseSensitive=$options['caseSensitive'];
 -			$alphabet=$options['alphabet'];
 -			$fontSize=$options['fontSize'];
 -			$theme=$options['theme'];
 -			if(($randomSeed=$options['randomSeed'])>0)
 -				srand($randomSeed);
 -			else
 -				srand((int)(microtime()*1000000));
 -			$token=generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive);
 -		}
 -	}
 -}
 -
 -displayToken($token,$fontSize,$theme);
 -
 -function generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive)
 -{
 -	$token=substr(hash2string(md5($publicKey.$privateKey),$alphabet).hash2string(md5($privateKey.$publicKey),$alphabet),0,$tokenLength);
 -	return $caseSensitive?$token:strtoupper($token);
 -}
 -
 -function hash2string($hex,$alphabet)
 -{
 -	if(strlen($alphabet)<2)
 -		$alphabet='234578adefhijmnrtABDEFGHJLMNRT';
 -	$hexLength=strlen($hex);
 -	$base=strlen($alphabet);
 -	$result='';
 -	for($i=0;$i<$hexLength;$i+=6)
 -	{
 -		$number=hexdec(substr($hex,$i,6));
 -		while($number)
 -		{
 -			$result.=$alphabet[$number%$base];
 -			$number=floor($number/$base);
 -		}
 -	}
 -	return $result;
 -}
 -
 -function displayToken($token,$fontSize,$theme)
 -{
 -	if(($fontSize=(int)$fontSize)<22)
 -		$fontSize=22;
 -	if($fontSize>100)
 -		$fontSize=100;
 -	$length=strlen($token);
 -	$padding=10;
 -	$fontWidth=$fontSize;
 -	$fontHeight=floor($fontWidth*1.5);
 -	$width=$fontWidth*$length+$padding*2;
 -	$height=$fontHeight;
 -	$image=imagecreatetruecolor($width,$height);
 -
 -	addBackground
 -	(
 -		$image, $width, $height,
 -		$theme&THEME_OPAQUE_BACKGROUND,
 -		$theme&THEME_NOISY_BACKGROUND,
 -		$theme&THEME_HAS_GRID,
 -		$theme&THEME_HAS_SCRIBBLE,
 -		$theme&THEME_MORPH_BACKGROUND
 -	);
 -
 -	$font=dirname(__FILE__).DIRECTORY_SEPARATOR.'verase.ttf';
 -
 -	if(function_exists('imagefilter'))
 -    	imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR);
 -
 -	$hasShadow=($theme&THEME_SHADOWED_TEXT);
 -    for($i=0;$i<$length;$i++)
 -	{
 -        $color=imagecolorallocate($image,rand(150,220),rand(150,220),rand(150,220));
 -        $size=rand($fontWidth-10,$fontWidth);
 -        $angle=rand(-30,30);
 -        $x=$padding+$i*$fontWidth;
 -        $y=rand($fontHeight-15,$fontHeight-10);
 -        imagettftext($image,$size,$angle,$x,$y,$color,$font,$token[$i]);
 -        if($hasShadow)
 -        	imagettftext($image,$size,$angle,$x+2,$y+2,$color,$font,$token[$i]);
 -        imagecolordeallocate($image,$color);
 -    }
 -	
 -	header('Content-Type: image/png');
 -	imagepng($image);
 -	imagedestroy($image);
 -}
 -
 -function addBackground($image,$width,$height,$opaque,$noisy,$hasGrid,$hasScribble,$morph)
 -{
 -	$background=imagecreatetruecolor($width*2,$height*2);
 -	$white=imagecolorallocate($background,255,255,255);
 -	imagefill($background,0,0,$white);
 -
 -	if($opaque)
 -		imagefill($background,0,0,imagecolorallocate($background,100,100,100));
 -
 -	if($noisy)
 -		addNoise($background,$width*2,$height*2);
 -
 -	if($hasGrid)
 -		addGrid($background,$width*2,$height*2);
 -
 -	if($hasScribble)
 -		addScribble($background,$width*2,$height*2);
 -
 -	if($morph)
 -		morphImage($background,$width*2,$height*2);
 -
 -	imagecopy($image,$background,0,0,30,30,$width,$height);
 -
 -	if(!$opaque)
 -		imagecolortransparent($image,$white);
 -}
 -
 -function addNoise($image,$width,$height)
 -{
 -	for($x=0;$x<$width;++$x)
 -	{
 -		for($y=0;$y<$height;++$y)
 -		{
 -			if(rand(0,100)<25)
 -			{
 -				$color=imagecolorallocate($image,rand(150,220),rand(150,220),rand(150,220));
 -				imagesetpixel($image,$x,$y,$color);
 -	            imagecolordeallocate($image,$color);
 -	        }
 -		}
 -	}
 -}
 -
 -function addGrid($image,$width,$height)
 -{
 -	for($i=0;$i<$width;$i+=rand(15,25))
 -	{
 -		imagesetthickness($image,rand(2,6));
 -		$color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180));
 -		imageline($image,$i+rand(-10,20),0,$i+rand(-10,20),$height,$color);
 -		imagecolordeallocate($image,$color);
 -	}
 -	for($i=0;$i<$height;$i+=rand(15,25))
 -	{
 -		imagesetthickness($image,rand(2,6));
 -		$color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180));
 -		imageline($image,0,$i+rand(-10,20),$width,$i+rand(-10,20),$color);
 -		imagecolordeallocate($image,$color);
 -	}
 -}
 -
 -function addScribble($image,$width,$height)
 -{
 -	for($i=0;$i<8;$i++)
 -	{
 -		$color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180));
 -		$points=array();
 -		for($j=1;$j<rand(5,10);$j++)
 -		{
 -			$points[]=rand(2*(20*($i+1)),2*(50*($i+1)));
 -			$points[]=rand(30,$height+30);
 -		}
 -		imagesetthickness($image,rand(2,6));
 -		imagepolygon($image,$points,intval(sizeof($points)/2),$color);
 -		imagecolordeallocate($image,$color);
 -	}
 -}
 -
 -function morphImage($image,$width,$height)
 -{
 -	$tempImage=imagecreatetruecolor($width,$height);
 -	$chunk=rand(1,5);
 -	for($x=$y=0;$x<$width;$x+=$chunk)
 -	{
 -		$chunk=rand(1,5);
 -		$y+=rand(-1,1);
 -		if($y>=$height)	$y=$height-5;
 -		if($y<0) $y=5;
 -		imagecopy($tempImage,$image,$x,0,$x,$y,$chunk,$height);
 -	}
 -	for($x=$y=0;$y<$height;$y+=$chunk)
 -	{
 -		$chunk=rand(1,5);
 -		$x+=rand(-1,1);
 -		if($x>=$width)	$x=$width-5;
 -		if($x<0) $x=5;
 -		imagecopy($image,$tempImage,$x,$y,0,$y,$width,$chunk);
 -	}
 -}
 -
 +<?php +/** + * CAPTCHA generator script. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.WebControls.assets + */ + +define('THEME_OPAQUE_BACKGROUND',0x0001); +define('THEME_NOISY_BACKGROUND',0x0002); +define('THEME_HAS_GRID',0x0004); +define('THEME_HAS_SCRIBBLE',0x0008); +define('THEME_MORPH_BACKGROUND',0x0010); +define('THEME_SHADOWED_TEXT',0x0020); + +require_once(dirname(__FILE__).'/captcha_key.php'); + +$token='error'; +$theme=0; + +if(isset($_GET['options'])) +{ +	$str=base64_decode($_GET['options']); +	if(strlen($str)>32) +	{ +		$hash=substr($str,0,32); +		$str=substr($str,32); +		if(md5($privateKey.$str)===$hash) +		{ +			$options=unserialize($str); +			$publicKey=$options['publicKey']; +			$tokenLength=$options['tokenLength']; +			$caseSensitive=$options['caseSensitive']; +			$alphabet=$options['alphabet']; +			$fontSize=$options['fontSize']; +			$theme=$options['theme']; +			if(($randomSeed=$options['randomSeed'])>0) +				srand($randomSeed); +			else +				srand((int)(microtime()*1000000)); +			$token=generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive); +		} +	} +} + +displayToken($token,$fontSize,$theme); + +function generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive) +{ +	$token=substr(hash2string(md5($publicKey.$privateKey),$alphabet).hash2string(md5($privateKey.$publicKey),$alphabet),0,$tokenLength); +	return $caseSensitive?$token:strtoupper($token); +} + +function hash2string($hex,$alphabet) +{ +	if(strlen($alphabet)<2) +		$alphabet='234578adefhijmnrtABDEFGHJLMNRT'; +	$hexLength=strlen($hex); +	$base=strlen($alphabet); +	$result=''; +	for($i=0;$i<$hexLength;$i+=6) +	{ +		$number=hexdec(substr($hex,$i,6)); +		while($number) +		{ +			$result.=$alphabet[$number%$base]; +			$number=floor($number/$base); +		} +	} +	return $result; +} + +function displayToken($token,$fontSize,$theme) +{ +	if(($fontSize=(int)$fontSize)<22) +		$fontSize=22; +	if($fontSize>100) +		$fontSize=100; +	$length=strlen($token); +	$padding=10; +	$fontWidth=$fontSize; +	$fontHeight=floor($fontWidth*1.5); +	$width=$fontWidth*$length+$padding*2; +	$height=$fontHeight; +	$image=imagecreatetruecolor($width,$height); + +	addBackground +	( +		$image, $width, $height, +		$theme&THEME_OPAQUE_BACKGROUND, +		$theme&THEME_NOISY_BACKGROUND, +		$theme&THEME_HAS_GRID, +		$theme&THEME_HAS_SCRIBBLE, +		$theme&THEME_MORPH_BACKGROUND +	); + +	$font=dirname(__FILE__).DIRECTORY_SEPARATOR.'verase.ttf'; + +	if(function_exists('imagefilter')) +    	imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR); + +	$hasShadow=($theme&THEME_SHADOWED_TEXT); +    for($i=0;$i<$length;$i++) +	{ +        $color=imagecolorallocate($image,rand(150,220),rand(150,220),rand(150,220)); +        $size=rand($fontWidth-10,$fontWidth); +        $angle=rand(-30,30); +        $x=$padding+$i*$fontWidth; +        $y=rand($fontHeight-15,$fontHeight-10); +        imagettftext($image,$size,$angle,$x,$y,$color,$font,$token[$i]); +        if($hasShadow) +        	imagettftext($image,$size,$angle,$x+2,$y+2,$color,$font,$token[$i]); +        imagecolordeallocate($image,$color); +    } +	 +	header('Content-Type: image/png'); +	imagepng($image); +	imagedestroy($image); +} + +function addBackground($image,$width,$height,$opaque,$noisy,$hasGrid,$hasScribble,$morph) +{ +	$background=imagecreatetruecolor($width*2,$height*2); +	$white=imagecolorallocate($background,255,255,255); +	imagefill($background,0,0,$white); + +	if($opaque) +		imagefill($background,0,0,imagecolorallocate($background,100,100,100)); + +	if($noisy) +		addNoise($background,$width*2,$height*2); + +	if($hasGrid) +		addGrid($background,$width*2,$height*2); + +	if($hasScribble) +		addScribble($background,$width*2,$height*2); + +	if($morph) +		morphImage($background,$width*2,$height*2); + +	imagecopy($image,$background,0,0,30,30,$width,$height); + +	if(!$opaque) +		imagecolortransparent($image,$white); +} + +function addNoise($image,$width,$height) +{ +	for($x=0;$x<$width;++$x) +	{ +		for($y=0;$y<$height;++$y) +		{ +			if(rand(0,100)<25) +			{ +				$color=imagecolorallocate($image,rand(150,220),rand(150,220),rand(150,220)); +				imagesetpixel($image,$x,$y,$color); +	            imagecolordeallocate($image,$color); +	        } +		} +	} +} + +function addGrid($image,$width,$height) +{ +	for($i=0;$i<$width;$i+=rand(15,25)) +	{ +		imagesetthickness($image,rand(2,6)); +		$color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180)); +		imageline($image,$i+rand(-10,20),0,$i+rand(-10,20),$height,$color); +		imagecolordeallocate($image,$color); +	} +	for($i=0;$i<$height;$i+=rand(15,25)) +	{ +		imagesetthickness($image,rand(2,6)); +		$color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180)); +		imageline($image,0,$i+rand(-10,20),$width,$i+rand(-10,20),$color); +		imagecolordeallocate($image,$color); +	} +} + +function addScribble($image,$width,$height) +{ +	for($i=0;$i<8;$i++) +	{ +		$color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180)); +		$points=array(); +		for($j=1;$j<rand(5,10);$j++) +		{ +			$points[]=rand(2*(20*($i+1)),2*(50*($i+1))); +			$points[]=rand(30,$height+30); +		} +		imagesetthickness($image,rand(2,6)); +		imagepolygon($image,$points,intval(sizeof($points)/2),$color); +		imagecolordeallocate($image,$color); +	} +} + +function morphImage($image,$width,$height) +{ +	$tempImage=imagecreatetruecolor($width,$height); +	$chunk=rand(1,5); +	for($x=$y=0;$x<$width;$x+=$chunk) +	{ +		$chunk=rand(1,5); +		$y+=rand(-1,1); +		if($y>=$height)	$y=$height-5; +		if($y<0) $y=5; +		imagecopy($tempImage,$image,$x,0,$x,$y,$chunk,$height); +	} +	for($x=$y=0;$y<$height;$y+=$chunk) +	{ +		$chunk=rand(1,5); +		$x+=rand(-1,1); +		if($x>=$width)	$x=$width-5; +		if($x<0) $x=5; +		imagecopy($image,$tempImage,$x,$y,0,$y,$width,$chunk); +	} +} +  | 
