From 51ccd340f64a7e0e84a1c5fade6a4504a66990f5 Mon Sep 17 00:00:00 2001
From: xue <>
Date: Sat, 4 Mar 2006 13:08:11 +0000
Subject: Added TMultiView and TView control.

---
 framework/Web/UI/WebControls/TMultiView.php | 350 ++++++++++++++++++++++++++++
 1 file changed, 350 insertions(+)
 create mode 100644 framework/Web/UI/WebControls/TMultiView.php

(limited to 'framework/Web')

diff --git a/framework/Web/UI/WebControls/TMultiView.php b/framework/Web/UI/WebControls/TMultiView.php
new file mode 100644
index 00000000..4208c6d0
--- /dev/null
+++ b/framework/Web/UI/WebControls/TMultiView.php
@@ -0,0 +1,350 @@
+<?php
+/**
+ * TMultiView and TView class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @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
+ * - PrevView : 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.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TMultiView extends TControl
+{
+	const CMD_NEXTVIEW='NextView';
+	const CMD_PREVIOUSVIEW='PrevView';
+	const CMD_SWITCHVIEWID='SwitchViewID';
+	const CMD_SWITCHVIEWINDEX='SwitchViewIndex';
+
+	/**
+	 * 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.
+	 */
+	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($view->getCount()===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));
+		}
+		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',$value);
+		if($index<0)
+			return null;
+		$view=$views->itemAt($index);
+		if(!$view->getActive())
+			$this->activateView($view);
+		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
+	 */
+	protected function activateView($view)
+	{
+		if($view->getActive())
+			return;
+		$triggerEvent=$this->getControlStage()>=TControl::CS_STATE_LOADED || !$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();
+	}
+
+	/**
+	 * Initializes the active view if any.
+	 * This method overrides the parent implementation.
+	 * @param mixed 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 mixed 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 onBubbleEvent($sender,$param)
+	{
+		if($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($param->getCommandParameter());
+					if($view!==null && $view->getParent()===$this)
+					{
+						$this->setActiveView($view);
+						return true;
+					}
+					else
+						throw new TInvalidDataValueException('multiview_viewid_invalid');
+				case self::CMD_SWITCHVIEWINDEX:
+					$index=TPropertyValue::ensureInteger($param->getCommandParameter());
+					$this->setActiveViewIndex($index);
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * 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 $Revision: $  $Date: $
+ * @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 $Revision: $  $Date: $
+ * @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('Activate',$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);
+	}
+
+	/**
+	 * @return boolean whether this view is visible.
+	 * The view is visible if it is active and its parent is visible.
+	 */
+	public function getVisible()
+	{
+		if(($parent=$this->getParent())===null)
+			return $this->getActive();
+		else if($this->getActive())
+			return $parent->getVisible();
+		else
+			return false;
+	}
+
+	/**
+	 * @param boolean
+	 * @throw TInvalidOperationException whenever this method is invoked.
+	 */
+	public function setVisible($value)
+	{
+		throw new TInvalidOperationException('view_visible_readonly');
+	}
+}
+
+?>
\ No newline at end of file
-- 
cgit v1.2.3