summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
authorxue <>2005-11-25 03:18:09 +0000
committerxue <>2005-11-25 03:18:09 +0000
commit635ae748a34dadc241bd264e11d3251ffffe3aac (patch)
tree206ce58ecc3348fb43a945d7e927dfadcef35653 /framework
parent81b7d150b1c815cdd032c2b5795b6c4244e56ace (diff)
Diffstat (limited to 'framework')
-rw-r--r--framework/Exceptions/messages.txt9
-rw-r--r--framework/TODO.txt6
-rw-r--r--framework/Web/Services/TPageService.php5
-rw-r--r--framework/Web/UI/TControl.php212
-rw-r--r--framework/Web/UI/THtmlWriter.php23
-rw-r--r--framework/Web/UI/WebControls/TButton.php4
-rw-r--r--framework/Web/UI/WebControls/TCheckBox.php2
-rw-r--r--framework/Web/UI/WebControls/TExpression.php2
-rw-r--r--framework/Web/UI/WebControls/TFont.php39
-rw-r--r--framework/Web/UI/WebControls/THyperLink.php2
-rw-r--r--framework/Web/UI/WebControls/TImage.php2
-rw-r--r--framework/Web/UI/WebControls/TImageButton.php2
-rw-r--r--framework/Web/UI/WebControls/TLabel.php4
-rw-r--r--framework/Web/UI/WebControls/TLiteral.php2
-rw-r--r--framework/Web/UI/WebControls/TPanel.php2
-rw-r--r--framework/Web/UI/WebControls/TStatements.php10
-rw-r--r--framework/Web/UI/WebControls/TStyle.php176
-rw-r--r--framework/Web/UI/WebControls/TTextBox.php4
-rw-r--r--framework/Web/UI/WebControls/TWebControl.php46
19 files changed, 312 insertions, 240 deletions
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt
index 3788ce37..abb6c0dd 100644
--- a/framework/Exceptions/messages.txt
+++ b/framework/Exceptions/messages.txt
@@ -125,3 +125,12 @@ theme_skinid_duplicated = SkinID '%s.%s' is duplicated in theme '%s'.
theme_databind_forbidden = Databind cannot be used in theme '%s' for control skin '%s.%s' about property '%s'.
theme_property_readonly = Skin is being applied to a read-only control property '%s.%s'.
theme_property_undefined = Skin is being applied to an inexistent control property '%s.%s'.
+
+control_id_invalid = %s.ID '%s' is invalid. Only alphanumeric and underline characters are allowed. The first character must be an alphabetic or underline character.
+control_skinid_unchangeable = %s.SkinID cannot be modified after a skin has been applied to the control or the child controls have been created.
+control_enabletheming_unchangeable = %s.EnableTheming cannot be modified after the child controls have been created.
+control_stylesheet_applied = StyleSheet skin has already been applied to %s.
+control_id_nonunique = %s.ID '%s' is not unique among all controls under the same naming container.
+
+webcontrol_accesskey_invalid = %s.AccessKey '%s' is invalid. It must be a single character only.
+webcontrol_style_invalid = %s.Style must take string value only. \ No newline at end of file
diff --git a/framework/TODO.txt b/framework/TODO.txt
index e7d988c6..ff3c2598 100644
--- a/framework/TODO.txt
+++ b/framework/TODO.txt
@@ -3,16 +3,10 @@ how to do this for Theme (skin files)?
how to correctly highlight source code displayed for exception context?
checkbox if checked, posted, unchecked and then post, it will be checked.
-add application state: off, debug, normal, performance
think more about encoding/decoding
<%@ MasterClass="Pages.MasterPage" %>
-THtmlTextWriter::addStyleAttribute(), also change how TStyle renders its content.
-callback
-
-http://www.xisc.com/index.php?page=homepage
-
Features to be implemented later:
- SmartNavigation: TForm, TPage
- DefaultButton: TForm, TClientScriptManager
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php
index 3218138e..520c4187 100644
--- a/framework/Web/Services/TPageService.php
+++ b/framework/Web/Services/TPageService.php
@@ -344,11 +344,6 @@ class TPageService extends TComponent implements IService
throw new TConfigurationException('pageservice_basepath_invalid',$value);
}
- protected function createHtmlTextWriter()
- {
- $writer=new THtmlTextWriter($this->_application->getResponse());
- }
-
/**
* Runs the service.
* This will create the requested page, initializes it with the property values
diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php
index d0e9083e..af925d98 100644
--- a/framework/Web/UI/TControl.php
+++ b/framework/Web/UI/TControl.php
@@ -16,32 +16,43 @@
* TControl is the base class for all components on a page hierarchy.
* It implements the following features for UI-related functionalities:
* - databinding feature
- * - naming container and containee relationship
* - parent and child relationship
+ * - naming container and containee relationship
* - viewstate and controlstate features
* - rendering scheme
* - control lifecycles
*
- * A property can be data-bound with an expression. By calling {@link dataBind}
+ * A property can be data-bound with an expression. By calling {@link dataBind},
* expressions bound to properties will be evaluated and the results will be
* set to the corresponding properties.
*
+ * Parent and child relationship determines how the presentation of controls are
+ * enclosed within each other. A parent will determine where to place
+ * the presentation of its child controls. For example, a TPanel will enclose
+ * all its child controls' presentation within a div html tag. A control's parent
+ * can be obtained via {@link getParent Parent} property, and its
+ * {@link getControls Controls} property returns a list of the control's children,
+ * including controls and static texts. The property can be manipulated
+ * like an array for adding or removing a child (see {@link TList} for more details).
+ *
* A naming container control implements INamingContainer and ensures that
* its containee controls can be differentiated by their ID property values.
* Naming container and containee realtionship specifies a protocol to uniquely
* identify an arbitrary control on a page hierarchy by an ID path (concatenation
* of all naming containers' IDs and the target control's ID).
*
- * Parent and child relationship determines how the presentation of controls are
- * enclosed within each other. A parent will determine where to place
- * the presentation of its child controls. For example, a TPanel will enclose
- * all its child controls' presentation within a div html tag.
- *
* Viewstate and controlstate are two approaches to preserve state across
* page postback requests. ViewState is mainly related with UI specific state
* and can be disabled if not needed. ControlState represents crucial logic state
* and cannot be disabled.
*
+ * A control is rendered via its {@link render()} method (the method is invoked
+ * by the framework.) Descendant control classes may override this method for
+ * customized rendering. By default, {@link render()} invokes {@link renderChildren()}
+ * which is responsible for rendering of children of the control.
+ * Control's {@link getVisible Visible} property governs whether the control
+ * should be rendered or not.
+ *
* Each control on a page will undergo a series of lifecycles, including
* control construction, OnInit, OnLoad, OnPreRender, Render, and OnUnload.
* They work together with page lifecycles to process a page request.
@@ -84,13 +95,12 @@ class TControl extends TComponent
* State bits.
*/
const IS_ID_SET=0x01;
- const IS_INVISIBLE=0x02;
- const IS_DISABLE_VIEWSTATE=0x04;
- const IS_SKIN_APPLIED=0x08;
- const IS_STYLESHEET_APPLIED=0x10;
- const IS_DISABLE_THEMING=0x20;
- const IS_CHILD_CREATED=0x40;
- const IS_CREATING_CHILD=0x80;
+ const IS_DISABLE_VIEWSTATE=0x02;
+ const IS_SKIN_APPLIED=0x04;
+ const IS_STYLESHEET_APPLIED=0x08;
+ const IS_DISABLE_THEMING=0x10;
+ const IS_CHILD_CREATED=0x20;
+ const IS_CREATING_CHILD=0x40;
/**
* Indexes for the rare fields.
@@ -186,7 +196,12 @@ class TControl extends TComponent
public function getNamingContainer()
{
if(!$this->_namingContainer && $this->_parent)
- $this->_namingContainer=$this->_parent->getNamingContainer();
+ {
+ if($this->_parent instanceof INamingContainer)
+ $this->_namingContainer=$this->_parent;
+ else
+ $this->_namingContainer=$this->_parent->getNamingContainer();
+ }
return $this->_namingContainer;
}
@@ -195,23 +210,14 @@ class TControl extends TComponent
*/
public function getPage()
{
- if($this->_page)
- return $this->_page;
- else
+ if(!$this->_page)
{
if($this->_parent)
- {
$this->_page=$this->_parent->getPage();
- return $this->_page;
- }
else if($this->_tplControl)
- {
$this->_page=$this->_tplControl->getPage();
- return $this->_page;
- }
- else
- return null;
}
+ return $this->_page;
}
/**
@@ -239,15 +245,9 @@ class TControl extends TComponent
*/
public function getTemplateControl()
{
- if($this->_tplControl)
- return $this->_tplControl;
- else if($this->_parent)
- {
+ if(!$this->_tplControl && $this->_parent)
$this->_tplControl=$this->_parent->getTemplateControl();
- return $this->_tplControl;
- }
- else
- return null;
+ return $this->_tplControl;
}
/**
@@ -298,6 +298,14 @@ class TControl extends TComponent
return Prado::getApplication()->getUser();
}
+ /**
+ * Publishes a private asset and gets its URL.
+ * This method will publish a private asset (file or directory)
+ * and gets the URL to the asset. Note, if the asset refers to
+ * a directory, all contents under that directory will be published.
+ * @param string path of the asset that is relative to the directory containing the control class file.
+ * @return string URL to the asset path.
+ */
public function getAsset($assetPath)
{
$class=new ReflectionClass(get_class($this));
@@ -327,7 +335,7 @@ class TControl extends TComponent
public function setID($id)
{
if(!preg_match(self::ID_FORMAT,$id))
- throw new TInvalidDataValueException('control_id_invalid',$id,get_class($this));
+ throw new TInvalidDataValueException('control_id_invalid',get_class($this),$id);
$this->_id=$id;
$this->_flags |= self::IS_ID_SET;
$this->clearCachedUniqueID($this instanceof INamingContainer);
@@ -375,7 +383,7 @@ class TControl extends TComponent
}
/**
- * @return string the skin ID of this control
+ * @return string the skin ID of this control, '' if not set
*/
public function getSkinID()
{
@@ -389,7 +397,7 @@ class TControl extends TComponent
public function setSkinID($value)
{
if(($this->_flags & self::IS_SKIN_APPLIED) || $this->_stage>=self::CS_CHILD_INITIALIZED)
- throw new TInvalidOperationException('control_skinid_unchangeable',get_class($this),$this->getUniqueID());
+ throw new TInvalidOperationException('control_skinid_unchangeable',get_class($this));
else
$this->_rf[self::RF_SKIN_ID]=$value;
}
@@ -439,26 +447,31 @@ class TControl extends TComponent
}
/**
- * @param boolean whether the control is visible
+ * Checks if a control is visible.
+ * If parent check is required, then a control is visible only if the control
+ * and all its ancestors are visible.
+ * @param boolean whether the parents should also be checked if visible
+ * @return boolean whether the control is visible (default=true).
*/
- public function setVisible($value)
+ public function getVisible($checkParents=false)
{
- if(TPropertyValue::ensureBoolean($value))
- $this->_flags &= ~self::IS_INVISIBLE;
+ if($checkParents)
+ {
+ for($control=$this;$control;$control=$control->_parent)
+ if(!$control->getViewState('Visible',true))
+ return false;
+ return true;
+ }
else
- $this->_flags |= self::IS_INVISIBLE;
+ return $this->getViewState('Visible',true);
}
/**
- * @return boolean whether the control is visible (default=true).
- * A control is visible if all its parents and itself are visible.
+ * @param boolean whether the control is visible
*/
- public function getVisible()
+ public function setVisible($value)
{
- if($this->_flags & self::IS_INVISIBLE)
- return false;
- else
- return $this->_parent?$this->_parent->getVisible():true;
+ $this->setViewState('Visible',TPropertyValue::ensureBoolean($value),true);
}
/**
@@ -476,7 +489,7 @@ class TControl extends TComponent
if($checkParents)
{
for($control=$this;$control;$control=$control->_parent)
- if(!$control->getEnabled())
+ if(!$control->getViewState('Enabled',true))
return false;
return true;
}
@@ -504,17 +517,6 @@ class TControl extends TComponent
}
/**
- * Returns a value indicating whether this control type can take attributes in template.
- * This method can be overriden.
- * Only framework developers and control developers should use this method.
- * @return boolean whether the control allows attributes in template (default=true)
- */
- public function getAllowCustomAttributes()
- {
- return true;
- }
-
- /**
* Returns the list of custom attributes.
* Custom attributes are name-value pairs that may be rendered
* as HTML tags' attributes.
@@ -533,6 +535,58 @@ class TControl extends TComponent
}
/**
+ * @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, '' if attribute does not exist
+ */
+ public function getAttribute($name)
+ {
+ if($attributes=$this->getViewState('Attributes',null))
+ return $attributes->itemAt($name);
+ else
+ return '';
+ }
+
+ /**
+ * @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.
+ */
+ public function removeAttribute($name)
+ {
+ if($attributes=$this->getViewState('Attributes',null))
+ $attributes->remove($name);
+ }
+
+ /**
+ * Returns a value indicating whether this control type can take attributes in template.
+ * This method can be overriden.
+ * Only framework developers and control developers should use this method.
+ * @return boolean whether the control allows attributes in template (default=true)
+ */
+ public function getAllowCustomAttributes()
+ {
+ return true;
+ }
+
+ /**
* @return boolean whether viewstate is enabled
*/
public function getEnableViewState()
@@ -688,7 +742,7 @@ class TControl extends TComponent
/**
* Ensures child controls are created.
* If child controls are not created yet, this method will invoke
- * {@link createChildControl} to create them.
+ * {@link createChildControls} to create them.
*/
public function ensureChildControls()
{
@@ -795,7 +849,7 @@ class TControl extends TComponent
/**
* Processes an object that is created during parsing template.
- * The object can be either a control or a static text string.
+ * The object can be either a component or a static text string.
* By default, the object will be added into the child control collection.
* This method can be overriden to customize the handling of newly created objects in template.
* Only framework developers and control developers should use this method.
@@ -955,20 +1009,12 @@ class TControl extends TComponent
*/
protected function preRenderRecursive()
{
- if($this->getVisible())
- {
- $this->_flags &= ~self::IS_INVISIBLE;
- $this->onPreRender(null);
- if($this->getHasControls())
- {
- foreach($this->_rf[self::RF_CONTROLS] as $control)
- if($control instanceof TControl)
- $control->preRenderRecursive();
- }
- }
- else
+ $this->onPreRender(null);
+ if($this->getHasControls())
{
- $this->_flags |= self::IS_INVISIBLE;
+ foreach($this->_rf[self::RF_CONTROLS] as $control)
+ if($control instanceof TControl)
+ $control->preRenderRecursive();
}
$this->_stage=self::CS_PRERENDERED;
}
@@ -1083,11 +1129,11 @@ class TControl extends TComponent
/**
* Renders the control.
* Only when the control is visible will the control be rendered.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function renderControl($writer)
{
- if(!($this->_flags & self::IS_INVISIBLE))
+ if($this->getVisible())
$this->render($writer);
}
@@ -1096,7 +1142,7 @@ class TControl extends TComponent
* This method is invoked by {@link renderControl} when the control is visible.
* You can override this method to provide customized rendering of the control.
* By default, the control simply renders all its child contents.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function render($writer)
{
@@ -1107,7 +1153,7 @@ class TControl extends TComponent
* Renders the children of the control.
* This method iterates through all child controls and static text strings
* and renders them in order.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function renderChildren($writer)
{
@@ -1131,7 +1177,6 @@ class TControl extends TComponent
*/
protected function onSaveState($param)
{
- $this->setViewState('Visible',!($this->_flags & self::IS_INVISIBLE),true);
$this->raiseEvent('SaveState',$this,$param);
}
@@ -1143,7 +1188,6 @@ class TControl extends TComponent
*/
protected function onLoadState($param)
{
- $this->setVisible($this->getViewState('Visible',true));
$this->raiseEvent('LoadState',$this,$param);
}
@@ -1255,7 +1299,7 @@ class TControl extends TComponent
$this->_flags |= self::IS_STYLESHEET_APPLIED;
}
else if($this->_flags & self::IS_STYLESHEET_APPLIED)
- throw new TInvalidOperationException('control_stylesheet_applied',get_class($this),$this->getUniqueID());
+ throw new TInvalidOperationException('control_stylesheet_applied',get_class($this));
}
/**
@@ -1310,7 +1354,7 @@ class TControl extends TComponent
if($control->_id!=='')
{
if(isset($container->_rf[self::RF_NAMED_CONTROLS][$control->_id]))
- throw new TInvalidDataValueException('control_id_not_unique',$control->_id,get_class($control));
+ throw new TInvalidDataValueException('control_id_nonunique',get_class($control),$control->_id);
else
$container->_rf[self::RF_NAMED_CONTROLS][$control->_id]=$control;
}
diff --git a/framework/Web/UI/THtmlWriter.php b/framework/Web/UI/THtmlWriter.php
index 75926d55..7388818f 100644
--- a/framework/Web/UI/THtmlWriter.php
+++ b/framework/Web/UI/THtmlWriter.php
@@ -165,10 +165,15 @@ class THtmlWriter extends TComponent implements ITextWriter
'width'=>false,
'wrap'=>false
);
-
+ private static $_styleEncode=array(
+ 'background-image'=>true,
+ 'font-family'=>false,
+ 'list-style-image'=>true
+ );
private $_attributes=array();
private $_openTags=array();
private $_writer=null;
+ private $_styles=array();
public function __construct($writer)
{
@@ -185,6 +190,14 @@ class THtmlWriter extends TComponent implements ITextWriter
$this->_attributes[$name]=isset(self::$_attrEncode[$name])?THttpUtility::htmlEncode($value):$value;
}
+ public function addStyleAttribute($name,$value)
+ {
+ if(isset(self::$_styleEncode[$name]))
+ $this->_styles[$name]=HttpUtility::htmlEncode($value);
+ else
+ $this->_styles[$name]=$value;
+ }
+
public function flush()
{
$this->_writer->flush();
@@ -211,6 +224,13 @@ class THtmlWriter extends TComponent implements ITextWriter
$str='<'.$tagName;
foreach($this->_attributes as $name=>$value)
$str.=' '.$name.'="'.$value.'"';
+ if(!empty($this->_styles))
+ {
+ $str.=' style="';
+ foreach($this->_styles as $name=>$value)
+ $str.=$name.':'.$value.';';
+ $str.='"';
+ }
if($tagType===self::TAG_NONCLOSING)
{
$str.=' />';
@@ -223,6 +243,7 @@ class THtmlWriter extends TComponent implements ITextWriter
}
$this->_writer->write($str);
$this->_attributes=array();
+ $this->_styles=array();
}
public function renderEndTag()
diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php
index f2979255..4eb8e093 100644
--- a/framework/Web/UI/WebControls/TButton.php
+++ b/framework/Web/UI/WebControls/TButton.php
@@ -58,7 +58,7 @@ class TButton extends TWebControl implements IPostBackEventHandler
/**
* Adds attribute name-value pairs to renderer.
* This overrides the parent implementation with additional button specific attributes.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function addAttributesToRender($writer)
{
@@ -90,7 +90,7 @@ class TButton extends TWebControl implements IPostBackEventHandler
/**
* Renders the body content enclosed between the control tag.
* This overrides the parent implementation with nothing to be rendered.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function renderContents($writer)
{
diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php
index 02167544..756fb2ea 100644
--- a/framework/Web/UI/WebControls/TCheckBox.php
+++ b/framework/Web/UI/WebControls/TCheckBox.php
@@ -295,7 +295,7 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl
$page=$this->getPage();
$page->ensureRenderInForm($this);
$needSpan=true;
- if($this->getStyleCreated())
+ if($this->getHasStyle())
{
$this->getStyle()->addAttributesToRender($writer);
$needSpan=true;
diff --git a/framework/Web/UI/WebControls/TExpression.php b/framework/Web/UI/WebControls/TExpression.php
index 6cecf9c4..9168f178 100644
--- a/framework/Web/UI/WebControls/TExpression.php
+++ b/framework/Web/UI/WebControls/TExpression.php
@@ -49,7 +49,7 @@ class TExpression extends TControl
/**
* Renders the evaluation result of the expression.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function render($writer)
{
diff --git a/framework/Web/UI/WebControls/TFont.php b/framework/Web/UI/WebControls/TFont.php
index 468aa9f9..75917b6c 100644
--- a/framework/Web/UI/WebControls/TFont.php
+++ b/framework/Web/UI/WebControls/TFont.php
@@ -3,9 +3,9 @@
* TFont class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.xisc.com/
- * @copyright Copyright &copy; 2004-2005, Qiang Xue
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
*/
@@ -214,7 +214,7 @@ class TFont extends TComponent
*/
public function mergeWith($font)
{
- if($font===null)
+ if($font===null || $font->_flags===0)
return;
if($font->_flags & self::IS_SET_BOLD)
$this->setBold($font->getBold());
@@ -248,7 +248,7 @@ class TFont extends TComponent
*/
public function toString()
{
- if($this->getIsEmpty())
+ if($this->_flags===0)
return '';
$str='';
if($this->_flags & self::IS_SET_BOLD)
@@ -271,6 +271,33 @@ class TFont extends TComponent
$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);
+ }
+}
?> \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/THyperLink.php b/framework/Web/UI/WebControls/THyperLink.php
index 2b57e101..916501a7 100644
--- a/framework/Web/UI/WebControls/THyperLink.php
+++ b/framework/Web/UI/WebControls/THyperLink.php
@@ -47,7 +47,7 @@ class THyperLink extends TWebControl
/**
* Renders the body content of the hyperlink.
- * @param THtmlTextWriter the writer for rendering
+ * @param THtmlWriter the writer for rendering
*/
protected function renderContents($writer)
{
diff --git a/framework/Web/UI/WebControls/TImage.php b/framework/Web/UI/WebControls/TImage.php
index 46e61083..0033209a 100644
--- a/framework/Web/UI/WebControls/TImage.php
+++ b/framework/Web/UI/WebControls/TImage.php
@@ -44,7 +44,7 @@ class TImage extends TWebControl
/**
* Renders the body content of the image.
* None will be rendered for an image.
- * @param THtmlTextWriter the writer for rendering
+ * @param THtmlWriter the writer for rendering
*/
protected function renderContents($writer)
{
diff --git a/framework/Web/UI/WebControls/TImageButton.php b/framework/Web/UI/WebControls/TImageButton.php
index 34ab4375..724dcf5c 100644
--- a/framework/Web/UI/WebControls/TImageButton.php
+++ b/framework/Web/UI/WebControls/TImageButton.php
@@ -59,7 +59,7 @@ class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEven
/**
* Adds attribute name-value pairs to renderer.
* This overrides the parent implementation with additional button specific attributes.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function addAttributesToRender($writer)
{
diff --git a/framework/Web/UI/WebControls/TLabel.php b/framework/Web/UI/WebControls/TLabel.php
index 464a4cd7..15148732 100644
--- a/framework/Web/UI/WebControls/TLabel.php
+++ b/framework/Web/UI/WebControls/TLabel.php
@@ -41,7 +41,7 @@ class TLabel extends TWebControl
/**
* Adds attributes to renderer.
- * @param THtmlTextWriter the renderer
+ * @param THtmlWriter the renderer
* @throws TInvalidDataValueException if associated control cannot be found using the ID
*/
protected function addAttributesToRender($writer)
@@ -58,7 +58,7 @@ class TLabel extends TWebControl
/**
* Renders the body content of the label.
- * @param THtmlTextWriter the renderer
+ * @param THtmlWriter the renderer
*/
protected function renderContents($writer)
{
diff --git a/framework/Web/UI/WebControls/TLiteral.php b/framework/Web/UI/WebControls/TLiteral.php
index 0509724a..459552f7 100644
--- a/framework/Web/UI/WebControls/TLiteral.php
+++ b/framework/Web/UI/WebControls/TLiteral.php
@@ -62,7 +62,7 @@ class TLiteral extends TControl
/**
* Renders the evaluation result of the statements.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function render($writer)
{
diff --git a/framework/Web/UI/WebControls/TPanel.php b/framework/Web/UI/WebControls/TPanel.php
index 36f70479..0f85a52f 100644
--- a/framework/Web/UI/WebControls/TPanel.php
+++ b/framework/Web/UI/WebControls/TPanel.php
@@ -33,7 +33,7 @@ class TPanel extends TWebControl
/**
* Adds attributes to renderer.
- * @param THtmlTextWriter the renderer
+ * @param THtmlWriter the renderer
*/
protected function addAttributesToRender($writer)
{
diff --git a/framework/Web/UI/WebControls/TStatements.php b/framework/Web/UI/WebControls/TStatements.php
index e0892f2b..5c1ffe1e 100644
--- a/framework/Web/UI/WebControls/TStatements.php
+++ b/framework/Web/UI/WebControls/TStatements.php
@@ -15,10 +15,10 @@
*
* TStatements executes a set of PHP statements and renders the display
* generated by the statements. The execution happens during rendering stage.
- * You can set the statements via the property <b>Statements</b>.
- * You should also specify the context object by <b>Context</b> property
- * which is used as the object in which the statements is evaluated.
- * If the <b>Context</b> property is not set, the TStatements component
+ * You can set the statements via the property <b>Statements</b>.
+ * You should also specify the context object by <b>Context</b> property
+ * which is used as the object in which the statements is evaluated.
+ * If the <b>Context</b> property is not set, the TStatements component
* itself will be assumed as the context.
*
* @author Qiang Xue <qiang.xue@gmail.com>
@@ -49,7 +49,7 @@ class TStatements extends TControl
/**
* Renders the evaluation result of the statements.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function render($writer)
{
diff --git a/framework/Web/UI/WebControls/TStyle.php b/framework/Web/UI/WebControls/TStyle.php
index e1e92b1b..8a046ff1 100644
--- a/framework/Web/UI/WebControls/TStyle.php
+++ b/framework/Web/UI/WebControls/TStyle.php
@@ -3,9 +3,9 @@
* TStyle class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.xisc.com/
- * @copyright Copyright &copy; 2004-2005, Qiang Xue
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
*/
@@ -23,35 +23,28 @@
class TStyle extends TComponent
{
/**
- * @var array The enumerable type for border styles
+ * @var array storage of CSS fields
*/
- public static $ENUM_BORDER_STYLE=array('NotSet','None','Dashed','Dotted','Solid','Double','Groove','Ridge','Inset','Outset');
-
+ private $_data=array();
/**
- * Various CSS fields
+ * @var TFont font object
*/
- const FLD_BACKCOLOR=0;
- const FLD_BORDERCOLOR=1;
- const FLD_BORDERWIDTH=2;
- const FLD_BORDERSTYLE=3;
- const FLD_FONT=4;
- const FLD_FORECOLOR=5;
- const FLD_HEIGHT=6;
- const FLD_WIDTH=7;
- const FLD_CSSCLASS=8;
- const FLD_STYLE=9;
-
+ private $_font=null;
/**
- * @var array storage of CSS fields
+ * @var string CSS class name
*/
- private $_data=array();
+ private $_class='';
+ /**
+ * @var string CSS style string (those not represented by specific fields of TStyle)
+ */
+ private $_style='';
/**
* @return string the background color of the control
*/
public function getBackColor()
{
- return isset($this->_data[self::FLD_BACKCOLOR])?$this->_data[self::FLD_BACKCOLOR]:'';
+ return isset($this->_data['background-color'])?$this->_data['background-color']:'';
}
/**
@@ -60,9 +53,9 @@ class TStyle extends TComponent
public function setBackColor($value)
{
if($value==='')
- unset($this->_data[self::FLD_BACKCOLOR]);
+ unset($this->_data['background-color']);
else
- $this->_data[self::FLD_BACKCOLOR]=$value;
+ $this->_data['background-color']=$value;
}
/**
@@ -70,7 +63,7 @@ class TStyle extends TComponent
*/
public function getBorderColor()
{
- return isset($this->_data[self::FLD_BORDERCOLOR])?$this->_data[self::FLD_BORDERCOLOR]:'';
+ return isset($this->_data['border-color'])?$this->_data['border-color']:'';
}
/**
@@ -79,9 +72,9 @@ class TStyle extends TComponent
public function setBorderColor($value)
{
if($value==='')
- unset($this->_data[self::FLD_BORDERCOLOR]);
+ unset($this->_data['border-color']);
else
- $this->_data[self::FLD_BORDERCOLOR]=$value;
+ $this->_data['border-color']=$value;
}
/**
@@ -89,21 +82,19 @@ class TStyle extends TComponent
*/
public function getBorderStyle()
{
- return isset($this->_data[self::FLD_BORDERSTYLE])?$this->_data[self::FLD_BORDERSTYLE]:'';
+ return isset($this->_data['border-style'])?$this->_data['border-style']:'';
}
/**
* Sets the border style of the control.
- * Valid values include:
- * 'NotSet','None','Dashed','Dotted','Solid','Double','Groove','Ridge','Inset','Outset'
* @param string the border style of the control
*/
public function setBorderStyle($value)
{
if($value==='')
- unset($this->_data[self::FLD_BORDERSTYLE]);
+ unset($this->_data['border-style']);
else
- $this->_data[self::FLD_BORDERSTYLE]=TPropertyValue::ensureEnum($value,self::$ENUM_BORDER_STYLE);
+ $this->_data['border-style']=$value;
}
/**
@@ -111,7 +102,7 @@ class TStyle extends TComponent
*/
public function getBorderWidth()
{
- return isset($this->_data[self::FLD_BORDERWIDTH])?$this->_data[self::FLD_BORDERWIDTH]:'';
+ return isset($this->_data['border-width'])?$this->_data['border-width']:'';
}
/**
@@ -120,9 +111,9 @@ class TStyle extends TComponent
public function setBorderWidth($value)
{
if($value==='')
- unset($this->_data[self::FLD_BORDERWIDTH]);
+ unset($this->_data['border-width']);
else
- $this->_data[self::FLD_BORDERWIDTH]=$value;
+ $this->_data['border-width']=$value;
}
/**
@@ -130,7 +121,7 @@ class TStyle extends TComponent
*/
public function getCssClass()
{
- return isset($this->_data[self::FLD_CSSCLASS])?$this->_data[self::FLD_CSSCLASS]:'';
+ return $this->_class;
}
/**
@@ -138,10 +129,7 @@ class TStyle extends TComponent
*/
public function setCssClass($value)
{
- if($value==='')
- unset($this->_data[self::FLD_CSSCLASS]);
- else
- $this->_data[self::FLD_CSSCLASS]=$value;
+ $this->_class=$value;
}
/**
@@ -149,9 +137,9 @@ class TStyle extends TComponent
*/
public function getFont()
{
- if(!isset($this->_data[self::FLD_FONT]))
- $this->_data[self::FLD_FONT]=new TFont;
- return $this->_data[self::FLD_FONT];
+ if($this->_font===null)
+ $this->_font=new TFont;
+ return $this->_font;
}
/**
@@ -159,7 +147,7 @@ class TStyle extends TComponent
*/
public function getForeColor()
{
- return isset($this->_data[self::FLD_FORECOLOR])?$this->_data[self::FLD_FORECOLOR]:'';
+ return isset($this->_data['color'])?$this->_data['color']:'';
}
/**
@@ -168,9 +156,9 @@ class TStyle extends TComponent
public function setForeColor($value)
{
if($value==='')
- unset($this->_data[self::FLD_FORECOLOR]);
+ unset($this->_data['color']);
else
- $this->_data[self::FLD_FORECOLOR]=$value;
+ $this->_data['color']=$value;
}
/**
@@ -178,7 +166,7 @@ class TStyle extends TComponent
*/
public function getHeight()
{
- return isset($this->_data[self::FLD_HEIGHT])?$this->_data[self::FLD_HEIGHT]:'';
+ return isset($this->_data['height'])?$this->_data['height']:'';
}
/**
@@ -187,9 +175,9 @@ class TStyle extends TComponent
public function setHeight($value)
{
if($value==='')
- unset($this->_data[self::FLD_HEIGHT]);
+ unset($this->_data['height']);
else
- $this->_data[self::FLD_HEIGHT]=$value;
+ $this->_data['height']=$value;
}
/**
@@ -197,7 +185,7 @@ class TStyle extends TComponent
*/
public function getStyle()
{
- return isset($this->_data[self::FLD_STYLE])?$this->_data[self::FLD_STYLE]:'';
+ return $this->_style;
}
/**
@@ -205,10 +193,7 @@ class TStyle extends TComponent
*/
public function setStyle($value)
{
- if($value==='')
- unset($this->_data[self::FLD_STYLE]);
- else
- $this->_data[self::FLD_STYLE]=$value;
+ $this->_style=$value;
}
/**
@@ -216,7 +201,7 @@ class TStyle extends TComponent
*/
public function getWidth()
{
- return isset($this->_data[self::FLD_WIDTH])?$this->_data[self::FLD_WIDTH]:'';
+ return isset($this->_data['width'])?$this->_data['width']:'';
}
/**
@@ -225,9 +210,9 @@ class TStyle extends TComponent
public function setWidth($value)
{
if($value==='')
- unset($this->_data[self::FLD_WIDTH]);
+ unset($this->_data['width']);
else
- $this->_data[self::FLD_WIDTH]=$value;
+ $this->_data['width']=$value;
}
/**
@@ -235,7 +220,7 @@ class TStyle extends TComponent
*/
public function getIsEmpty()
{
- return empty($this->_data) || (isset($this->_data[self::FLD_FONT]) && $this->_data[self::FLD_FONT]->getIsEmpty());
+ return empty($this->_data) && $this->_class==='' && $this->_style==='' && (!$this->_font || $this->_font->getIsEmpty());
}
/**
@@ -244,7 +229,9 @@ class TStyle extends TComponent
public function reset()
{
$this->_data=array();
- $this->flags=0;
+ $this->_font=null;
+ $this->_class='';
+ $this->_style='';
}
/**
@@ -257,24 +244,14 @@ class TStyle extends TComponent
{
if($style===null)
return;
- if(isset($style->_data[self::FLD_BACKCOLOR]))
- $this->_data[self::FLD_BACKCOLOR]=$style->_data[self::FLD_BACKCOLOR];
- if(isset($style->_data[self::FLD_BORDERCOLOR]))
- $this->_data[self::FLD_BORDERCOLOR]=$style->_data[self::FLD_BORDERCOLOR];
- if(isset($style->_data[self::FLD_BORDERWIDTH]))
- $this->_data[self::FLD_BORDERWIDTH]=$style->_data[self::FLD_BORDERWIDTH];
- if(isset($style->_data[self::FLD_BORDERSTYLE]))
- $this->_data[self::FLD_BORDERSTYLE]=$style->_data[self::FLD_BORDERSTYLE];
- if(isset($style->_data[self::FLD_FORECOLOR]))
- $this->_data[self::FLD_FORECOLOR]=$style->_data[self::FLD_FORECOLOR];
- if(isset($style->_data[self::FLD_HEIGHT]))
- $this->_data[self::FLD_HEIGHT]=$style->_data[self::FLD_HEIGHT];
- if(isset($style->_data[self::FLD_WIDTH]))
- $this->_data[self::FLD_WIDTH]=$style->_data[self::FLD_WIDTH];
- if(isset($style->_data[self::FLD_FONT]))
- $this->getFont()->mergeWith($style->_data[self::FLD_FONT]);
- if(isset($style->_data[self::FLD_CSSCLASS]))
- $this->_data[self::FLD_CSSCLASS]=$style->_data[self::FLD_CSSCLASS];
+ foreach($style->_data as $name=>$value)
+ $this->_data[$name]=$value;
+ if($style->_class!=='')
+ $this->_class=$style->_class;
+ if($style->_style!=='')
+ $this->_style=$style->_style;
+ if($style->_font!==null)
+ $this->getFont()->mergeWith($style->_font);
}
/**
@@ -294,40 +271,35 @@ class TStyle extends TComponent
*/
public function toString()
{
- if($this->getIsEmpty())
- return '';
- if(($str=$this->getStyle())!=='')
- $str=rtrim($str).';';
- if(isset($this->_data[self::FLD_BACKCOLOR]))
- $str.='background-color:'.$this->_data[self::FLD_BACKCOLOR].';';
- if(isset($this->_data[self::FLD_BORDERCOLOR]))
- $str.='border-color:'.$this->_data[self::FLD_BORDERCOLOR].';';
- if(isset($this->_data[self::FLD_BORDERWIDTH]))
- $str.='border-width:'.$this->_data[self::FLD_BORDERWIDTH].';';
- if(isset($this->_data[self::FLD_BORDERSTYLE]))
- $str.='border-style:'.$this->_data[self::FLD_BORDERSTYLE].';';
- if(isset($this->_data[self::FLD_FORECOLOR]))
- $str.='color:'.$this->_data[self::FLD_FORECOLOR].';';
- if(isset($this->_data[self::FLD_HEIGHT]))
- $str.='height:'.$this->_data[self::FLD_HEIGHT].';';
- if(isset($this->_data[self::FLD_WIDTH]))
- $str.='width:'.$this->_data[self::FLD_WIDTH].';';
- if(isset($this->_data[self::FLD_FONT]))
- $str.=$this->_data[self::FLD_FONT]->toString();
+ $str='';
+ foreach($this->_data as $name=>$value)
+ $str.=' '.$name.':'.$value.';';
+ if($this->_font)
+ $str.=$this->_font->toString();
return $str;
}
/**
* Adds attributes related to CSS styles to renderer.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
public function addAttributesToRender($writer)
{
- $str=$this->toString();
- if($str!=='')
- $writer->addAttribute('style',$str);
- if(isset($this->_data[self::FLD_CSSCLASS]))
- $writer->addAttribute('class',$this->_data[self::FLD_CSSCLASS]);
+ if($this->_style!=='')
+ {
+ foreach(explode(';',$this->_style) as $style)
+ {
+ $arr=explode(':',$style);
+ if(isset($arr[1]) && trim($arr[0])!=='')
+ $writer->addStyleAttribute(trim($arr[0]),trim($arry[1]));
+ }
+ }
+ foreach($this->_data as $name=>$value)
+ $writer->addStyleAttribute($name,$value);
+ if($this->_font!==null)
+ $this->_font->addAttributesToRender($writer);
+ if($this->_class!=='')
+ $writer->addAttribute('class',$this->_class);
}
}
diff --git a/framework/Web/UI/WebControls/TTextBox.php b/framework/Web/UI/WebControls/TTextBox.php
index 700906e8..b8c594f3 100644
--- a/framework/Web/UI/WebControls/TTextBox.php
+++ b/framework/Web/UI/WebControls/TTextBox.php
@@ -70,7 +70,7 @@ class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable
/**
* Adds attribute name-value pairs to renderer.
* This overrides the parent implementation with additional textbox specific attributes.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function addAttributesToRender($writer)
{
@@ -235,7 +235,7 @@ class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable
/**
* Renders the body content of the textbox when it is in MultiLine text mode.
- * @param THtmlTextWriter the writer for rendering
+ * @param THtmlWriter the writer for rendering
*/
protected function renderContents($writer)
{
diff --git a/framework/Web/UI/WebControls/TWebControl.php b/framework/Web/UI/WebControls/TWebControl.php
index 8a9765f7..b54f0e71 100644
--- a/framework/Web/UI/WebControls/TWebControl.php
+++ b/framework/Web/UI/WebControls/TWebControl.php
@@ -3,9 +3,9 @@
* TWebControl class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.xisc.com/
- * @copyright Copyright &copy; 2004-2005, Qiang Xue
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
*/
@@ -14,13 +14,18 @@
* TWebControl class
*
* TWebControl is the base class for controls that share a common set
- * of UI-related properties and methods. TWebControl derived controls
- * are usually corresponding to HTML tags. They thus have tag name, attributes
+ * of UI-related properties and methods. TWebControl-derived controls
+ * are usually associated with HTML tags. They thus have tag name, attributes
* and body contents. You can override {@link getTagName} to specify the tag name,
* {@link addAttributesToRender} to specify the attributes to be rendered,
* and {@link renderContents} to customize the body content rendering.
* TWebControl encapsulates a set of properties related with CSS style fields,
- * such as <b>BackColor</b>, <b>BorderWidth</b>, etc.
+ * such as {@link getBackColor BackColor}, {@link getBorderWidth BorderWidth}, etc.
+ *
+ * Subclasses of TWebControl typically needs to override {@link addAttributesToRender}
+ * and {@link renderContent}. The former is used to render the attributes
+ * of the HTML tag associated with the control, while the latter is to render
+ * the body contents enclosed within the HTML tag.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
@@ -40,14 +45,14 @@ class TWebControl extends TControl
/**
* Sets the access key of the control.
* Only one-character string can be set, or an exception will be raised.
- * Pass empty string if you want to disable access key.
+ * Pass in an empty string if you want to disable access key.
* @param string the access key to be set
* @throws TInvalidDataValueException if the access key is specified with more than one character
*/
public function setAccessKey($value)
{
if(strlen($value)>1)
- throw new TInvalidDataValueException('invalid_accesskey',get_class($this));
+ throw new TInvalidDataValueException('webcontrol_accesskey_invalid',get_class($this),$value);
$this->setViewState('AccessKey',$value,'');
}
@@ -192,7 +197,10 @@ class TWebControl extends TControl
$this->getStyle()->setHeight($value);
}
- public function getStyleCreated()
+ /**
+ * @return boolean whether the control has defined any style information
+ */
+ public function getHasStyle()
{
return $this->getViewState('Style',null)!==null;
}
@@ -223,7 +231,7 @@ class TWebControl extends TControl
if(is_string($value))
$this->getStyle()->setStyle($value);
else
- throw new TInvalidDataValueException('invalid_style_value',get_class($this));
+ throw new TInvalidDataValueException('webcontrol_style_invalid',get_class($this));
}
/**
@@ -265,7 +273,7 @@ class TWebControl extends TControl
/**
* Sets the tooltip of the control.
- * Pass empty string if you want to disable tooltip.
+ * Pass an empty string if you want to disable tooltip.
* @param string the tooltip to be set
*/
public function setToolTip($value)
@@ -294,8 +302,10 @@ class TWebControl extends TControl
/**
* Adds attribute name-value pairs to renderer.
- * This method can be overriden to provide customized attributes to be rendered.
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * By default, the method will render 'id', 'accesskey', 'disabled',
+ * 'tabindex', 'title' and all custom attributes.
+ * The method can be overriden to provide customized attribute rendering.
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function addAttributesToRender($writer)
{
@@ -306,7 +316,7 @@ class TWebControl extends TControl
if(!$this->getEnabled())
$writer->addAttribute('disabled','disabled');
if(($tabIndex=$this->getTabIndex())>0)
- $writer->addAttribute('tabindex',$tabIndex);
+ $writer->addAttribute('tabindex',"$tabIndex");
if(($toolTip=$this->getToolTip())!=='')
$writer->addAttribute('title',$toolTip);
if($style=$this->getViewState('Style',null))
@@ -325,7 +335,7 @@ class TWebControl extends TControl
* - {@link renderBeginTag}
* - {@link renderContents}
* - {@link renderEndTag}
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function render($writer)
{
@@ -336,7 +346,7 @@ class TWebControl extends TControl
/**
* Renders the openning tag for the control (including attributes)
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function renderBeginTag($writer)
{
@@ -348,7 +358,7 @@ class TWebControl extends TControl
* 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 THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function renderContents($writer)
{
@@ -357,7 +367,7 @@ class TWebControl extends TControl
/**
* Renders the closing tag for the control
- * @param THtmlTextWriter the writer used for the rendering purpose
+ * @param THtmlWriter the writer used for the rendering purpose
*/
protected function renderEndTag($writer)
{