summaryrefslogtreecommitdiff
path: root/framework/Web/UI
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Web/UI')
-rw-r--r--framework/Web/UI/WebControls/TCheckBox.php2
-rw-r--r--framework/Web/UI/WebControls/TDataBoundControl.php260
-rw-r--r--framework/Web/UI/WebControls/TDropDownList.php42
-rw-r--r--framework/Web/UI/WebControls/TListBox.php86
4 files changed, 388 insertions, 2 deletions
diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php
index 2f51d8f5..72d15822 100644
--- a/framework/Web/UI/WebControls/TCheckBox.php
+++ b/framework/Web/UI/WebControls/TCheckBox.php
@@ -102,8 +102,6 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl
* This is necessary because a checkbox if unchecked, when postback,
* does not have direct mapping between post data and the checkbox name.
*
- * Auto-postback javascript code is also registered here.
- *
* This method overrides the parent implementation and is invoked before render.
* @param mixed event parameter
*/
diff --git a/framework/Web/UI/WebControls/TDataBoundControl.php b/framework/Web/UI/WebControls/TDataBoundControl.php
new file mode 100644
index 00000000..032370f7
--- /dev/null
+++ b/framework/Web/UI/WebControls/TDataBoundControl.php
@@ -0,0 +1,260 @@
+<?php
+
+abstract class TDataBoundControl extends TWebControl
+{
+ private $_initialized=false;
+ private $_dataSource=null;
+ private $_requiresBindToNull=false;
+ private $_requiresDataBinding=false;
+ private $_throwOnDataPropertyChange=false;
+ private $_prerendered=false;
+
+ /**
+ * @return Traversable data source object, defaults to null.
+ */
+ public function getDataSource()
+ {
+ return $this->_dataSource;
+ }
+
+ /**
+ * @param Traversable|array|string data source object
+ */
+ public function setDataSource($value)
+ {
+ if($value!==null)
+ $this->validateDataSource($value);
+ $this->_dataSource=$value;
+ $this->onDataPropertyChanged();
+ }
+
+ /**
+ * @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->onDataPropertyChanged();
+ }
+
+ /**
+ * This method is invoked when either {@link setDataSource} or {@link setDataSourceID} is changed.
+ */
+ protected function onDataPropertyChanged()
+ {
+ if($this->_throwOnDataPropertyChanged)
+ throw new TInvalidOperationException('databoundcontrol_dataproperty_unchangeable');
+ if($this->getInitialized())
+ $this->setRequiresDataBinding(true);
+ }
+
+ /**
+ * @return boolean whether the databound control has been initialized.
+ */
+ protected function getInitialized()
+ {
+ return $this->_initialized;
+ }
+
+ /**
+ * @param boolean a value indicating whether the databound control is initialized.
+ */
+ protected function setInitialized($value)
+ {
+ $this->_initialized=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * @return boolean if the databound control uses the data source control specified
+ * by {@link setDataSourceID}, or it uses the data source object specified
+ * by {@link setDataSource}.
+ */
+ protected function getUsingDataSourceID()
+ {
+ return $this->getDataSourceID()!=='';
+ }
+
+ /**
+ * @return boolean whether a databind call is required (by the data bound control)
+ */
+ protected function getRequiresDataBinding()
+ {
+ return $this->_requiresDataBinding;
+ }
+
+ /**
+ * 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->getUsingDataSourceID())
+ {
+ $this->_requiresDataBinding=true;
+ $this->ensureDataBound();
+ }
+ else
+ $this->_requiresDataBinding=$value;
+ }
+
+ /**
+ * Performs databinding.
+ * This method overrides the parent implementation by calling
+ * {@link performSelect} which fetches data from data source and does
+ * the actual binding work.
+ * @param boolean whether to raise DataBind event. This parameter is ignored.
+ */
+ public function dataBind($raiseDataBindingEvent=true)
+ {
+ $this->performSelect();
+ }
+
+ /**
+ * 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()
+ {
+ try
+ {
+ $this->_throwOnDataPropertyChange=true;
+ if($this->_requiresDataBinding && ($this->getUsingDataSourceID() || $this->_requiresBindToNull))
+ {
+ $this->dataBind();
+ $this->_requiresBindToNull=false;
+ }
+ }
+ catch(Exception $e)
+ {
+ $this->_throwOnDataPropertyChange=false;
+ throw $e;
+ }
+ }
+
+ /**
+ * Raises <b>DataBound</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('DataBound',$this,$param);
+ }
+
+ /**
+ * Sets page's <b>PreLoad</b> event handler as {@link onPagePreLoad}.
+ * 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
+ */
+ protected function onInit($param)
+ {
+ parent::onInit($param);
+ $page=$this->getPage();
+ $page->attachEventHandler('PreLoad',array($this,'onPagePreLoad'));
+ if(!$this->getEnableViewState(true) && $page->getIsPostBack())
+ $this->setRequiresDataBinding(true);
+ }
+
+ /**
+ * Sets {@link getInitialized} as true.
+ * This method is invoked when page raises <b>PreLoad</b> event.
+ * @param mixed event sender
+ * @param TEventParameter event parameter
+ */
+ protected function onPagePreLoad($sender,$param)
+ {
+ $this->_initialized=true;
+ }
+
+ /**
+ * Ensures any pending databind is performed.
+ * This method overrides the parent implementation.
+ * @param TEventParameter event parameter
+ */
+ protected function onPreRender($param)
+ {
+ $this->_prerendered=true;
+ $this->ensureDataBound();
+ parent::onPreRender($param);
+ }
+
+ /**
+ * Validates if the parameter is a valid data source.
+ * @return boolean if the parameter is a valid data source
+ */
+ protected function validateDataSource($value)
+ {
+ if(!is_array($value) && !($value instanceof Traversable))
+ throw new TInvalidDataTypeException('databoundcontrol_datasource_invalid');
+ }
+
+ /**
+ * @return ???
+ */
+ protected function performSelect()
+ {
+ if(!$this->getUsingDataSourceID())
+ $this->onDataBinding(null);
+ $view=$this->getDataSourceView();
+ $this->setRequiresDataBinding(false);
+ $this->setDataBound(true);
+ $data=$view->select($this->getSelectParameters());
+ if($this->getUsingDataSourceID())
+ $this->onDataBinding(null);
+ $this->performDataBinding($data);
+ $this->onDataBound(null);
+ }
+
+ protected function getDataSourceView()
+ {
+ $source=$this->getDataSourceByID();
+ return $source->getView($this->getDataMember());
+ }
+
+ protected function performDataBinding($data)
+ {
+ }
+
+ public function getDataMember()
+ {
+ return $this->getViewState('DataMember','');
+ }
+
+ public function setDataMember($value)
+ {
+ $this->setViewState('DataMember',$value,'');
+ }
+
+ public function getSelectParameters()
+ {
+ if(!$this->_parameters)
+ $this->_parameters=$this->createSelectParameters();
+ return $this->_parameters;
+ }
+
+ protected function createSelectParameters()
+ {
+ return new TDataSourceSelectParameters;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TDropDownList.php b/framework/Web/UI/WebControls/TDropDownList.php
new file mode 100644
index 00000000..07549c6c
--- /dev/null
+++ b/framework/Web/UI/WebControls/TDropDownList.php
@@ -0,0 +1,42 @@
+<?php
+
+class TDropDownList extends TListControl implements IPostBackDataHandler
+{
+ protected function addAttributesToRender($writer)
+ {
+ $writer->addAttribute('name',$this->getUniqueID());
+ parent::addAttributesToRender($writer);
+ }
+
+ public function loadPostData($key,$values)
+ {
+ if(!$this->getEnabled(true))
+ return false;
+ // ensure DataBound???
+ }
+
+ public function raisePostDataChangedEvent()
+ {
+ $page=$this->getPage();
+ if($this->getAutoPostBack() && !$page->getPostBackEventTarget())
+ {
+ $page->setPostBackEventTarget($this);
+ if($this->getCausesValidation())
+ $page->validate($this->getValidationGroup());
+ }
+ $this->onSelectedIndexChanged(null);
+ }
+
+ public function getSelectedIndex()
+ {
+ $index=parent::getSelectedIndex();
+ if($index<0 && $this->getItems()->getCount()>0)
+ {
+ $this->setSelectedIndex(0);
+ return 0;
+ }
+ else
+ return $index;
+ }
+}
+?> \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TListBox.php b/framework/Web/UI/WebControls/TListBox.php
new file mode 100644
index 00000000..79afc133
--- /dev/null
+++ b/framework/Web/UI/WebControls/TListBox.php
@@ -0,0 +1,86 @@
+<?php
+
+class TListBox extends TListControl implements IPostBackDataHandler
+{
+ protected function addAttributesToRender($writer)
+ {
+ $rows=$this->getRows();
+ $writer->addAttribute('size',"$rows");
+ $writer->addAttribute('name',$this->getUniqueID());
+ parent::addAttributesToRender($writer);
+ }
+
+ protected function onPreRender($param)
+ {
+ parent::onPreRender($param);
+ if($this->getSelectionMode()==='Multiple' && $this->getEnabled(true))
+ $this->getPage()->registerRequiresPostData($this);
+ }
+
+ public function loadPostData($key,$values)
+ {
+ if(!$this->getEnabled(true))
+ return false;
+ // ensure DataBound???
+ }
+
+ public function raisePostDataChangedEvent()
+ {
+ $page=$this->getPage();
+ if($this->getAutoPostBack() && !$page->getPostBackEventTarget())
+ {
+ $page->setPostBackEventTarget($this);
+ if($this->getCausesValidation())
+ $page->validate($this->getValidationGroup());
+ }
+ $this->onSelectedIndexChanged(null);
+ }
+
+ protected function getIsMultiSelect()
+ {
+ return $this->getSelectionMode()==='Multiple';
+ }
+
+ public function getSelectedIndices()
+ {
+ return parent::getSelectedIndices();
+ }
+
+ /**
+ * @return integer the number of rows to be displayed in the component
+ */
+ public function getRows()
+ {
+ return $this->getViewState('Rows', 4);
+ }
+
+ /**
+ * Sets the number of rows to be displayed in the component
+ * @param integer the number of rows
+ */
+ public function setRows($value)
+ {
+ $value=TPropertyValue::ensureInteger($value);
+ if($value<=0)
+ $value=4;
+ $this->setViewState('Rows', $value, 4);
+ }
+
+ /**
+ * @return string the selection mode (Single, Multiple )
+ */
+ public function getSelectionMode()
+ {
+ return $this->getViewState('SelectionMode', 'Single');
+ }
+
+ /**
+ * Sets the selection mode of the component (Single, Multiple)
+ * @param string the selection mode
+ */
+ function setSelectionMode($value)
+ {
+ $this->setViewState('SelectionMode',TPropertyValue::ensureEnum($value,array('Single','Multiple')),'Single');
+ }
+}
+?> \ No newline at end of file