summaryrefslogtreecommitdiff
path: root/lib/prado/framework/Web/UI/WebControls/TMultiView.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/prado/framework/Web/UI/WebControls/TMultiView.php')
-rw-r--r--lib/prado/framework/Web/UI/WebControls/TMultiView.php374
1 files changed, 374 insertions, 0 deletions
diff --git a/lib/prado/framework/Web/UI/WebControls/TMultiView.php b/lib/prado/framework/Web/UI/WebControls/TMultiView.php
new file mode 100644
index 0000000..5f338d7
--- /dev/null
+++ b/lib/prado/framework/Web/UI/WebControls/TMultiView.php
@@ -0,0 +1,374 @@
+<?php
+/**
+ * TMultiView and TView class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link https://github.com/pradosoft/prado
+ * @copyright Copyright &copy; 2005-2015 The PRADO Group
+ * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
+ * @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>
+ * @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>
+ * @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>
+ * @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');
+ }
+}
+