From 2a4097f1c50e820fde0f3a769463c1858985b7fb Mon Sep 17 00:00:00 2001 From: xue <> Date: Sun, 20 Nov 2005 23:47:41 +0000 Subject: --- framework/Web/UI/TThemeManager.php | 150 ++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 29 deletions(-) (limited to 'framework/Web/UI') diff --git a/framework/Web/UI/TThemeManager.php b/framework/Web/UI/TThemeManager.php index b2b205ed..5d7319e8 100644 --- a/framework/Web/UI/TThemeManager.php +++ b/framework/Web/UI/TThemeManager.php @@ -15,9 +15,21 @@ * * TThemeManager manages the themes used in a Prado application. * - * Themes are stored in under {@link setBasePath BasePath} that can be accessed - * via URL {@link setBaseUrl BaseUrl}. Each theme is defined by a subdirectory - * and all the files under that directory. + * Themes are stored under the directory specified by the + * {@link setBasePath BasePath} property. The themes can be accessed + * via URL {@link setBaseUrl BaseUrl}. Each theme is represented by a subdirectory + * and all the files under that directory. The name of a theme is the name + * of the corresponding subdirectory. + * By default, the base path of all themes is a directory named "themes" + * under the directory containing the application entry script. + * To get a theme (normally you do not need to), call {@link getTheme}. + * + * TThemeManager may be configured within page service tag in application + * configuration file as follows, + * + * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl} + * and {@link getBufferOutput BufferOutput} are configurable properties of THttpResponse. * * @author Qiang Xue * @version $Revision: $ $Date: $ @@ -26,7 +38,9 @@ */ class TThemeManager extends TComponent implements IModule { - const THEME_CACHE_PREFIX='prado:theme:'; + /** + * default themes base path + */ const DEFAULT_BASEPATH='themes'; /** * @var string module ID @@ -40,6 +54,9 @@ class TThemeManager extends TComponent implements IModule * @var string the directory containing all themes */ private $_basePath=null; + /** + * @var string the base URL for all themes + */ private $_baseUrl=null; /** * @var TApplication application @@ -55,11 +72,6 @@ class TThemeManager extends TComponent implements IModule public function init($application,$config) { $this->_application=$application; - if($this->_basePath===null) - $this->_basePath=dirname($application->getRequest()->getPhysicalApplicationPath()).'/'.self::DEFAULT_BASEPATH; - if(($basePath=realpath($this->_basePath))===false || !is_dir($basePath)) - throw new TConfigurationException('thememanager_basepath_invalid',$this->_basePath); - $this->_basePath=$basePath; $this->_initialized=true; $application->getService()->setThemeManager($this); } @@ -80,30 +92,38 @@ class TThemeManager extends TComponent implements IModule $this->_id=$value; } + /** + * @param string name of the theme to be retrieved + * @return TTheme the theme retrieved + */ public function getTheme($name) { - if(($themePath=realpath($this->_basePath.'/'.$name))===false || !is_dir($themePath)) - throw new TConfigurationException('thememanager_theme_inexistent',$name); - - if($this->_baseUrl===null) - { - $appPath=dirname(Prado::getApplication()->getRequest()->getPhysicalApplicationPath()); - if(strpos($themePath,$appPath)===false) - throw new TConfigurationException('theme_baseurl_required'); - $appUrl=dirname(Prado::getApplication()->getRequest()->getApplicationPath()); - $themeUrl=$appUrl.'/'.strtr(substr($themePath,strlen($appPath)),'\\','/'); - } - else - $themeUrl=$this->_baseUrl.'/'.basename($themePath); + $themePath=$this->getBasePath().'/'.$name; + $themeUrl=$this->getBaseUrl().'/'.$name; return new TTheme($this->_application,$themePath,$themeUrl); } + /** + * @return string the base path for all themes. It is returned as an absolute path. + * @throws TConfigurationException if base path is not set and "themes" directory does not exist. + */ public function getBasePath() { + if($this->_basePath===null) + { + $this->_basePath=dirname($this->_application->getRequest()->getPhysicalApplicationPath()).'/'.self::DEFAULT_BASEPATH; + if(($basePath=realpath($this->_basePath))===false || !is_dir($basePath)) + throw new TConfigurationException('thememanager_basepath_invalid',$this->_basePath); + $this->_basePath=$basePath; + } return $this->_basePath; } + /** + * @param string the base path for all themes. It must be in the format of a namespace. + * @throws TInvalidDataValueException if the base path is not a proper namespace. + */ public function setBasePath($value) { if($this->_initialized) @@ -117,25 +137,89 @@ class TThemeManager extends TComponent implements IModule } } + /** + * @return string the base URL for all themes. + * @throws TConfigurationException If base URL is not set and a correct one cannot be determined by Prado. + */ public function getBaseUrl() { + if($this->_baseUrl===null) + { + $appPath=dirname($this->_application->getRequest()->getPhysicalApplicationPath()); + $basePath=$this->getBasePath(); + if(strpos($basePath,$appPath)===false) + throw new TConfigurationException('thememanager_baseurl_required'); + $appUrl=dirname($this->_application->getRequest()->getApplicationPath()); + $this->_baseUrl=$appUrl.'/'.strtr(substr($basePath,strlen($appPath)),'\\','/'); + } return $this->_baseUrl; } + /** + * @param string the base URL for all themes. + */ public function setBaseUrl($value) { - $this->_baseUrl=$value; + $this->_baseUrl=rtrim($value,'/'); } } +/** + * TTheme class + * + * TTheme represents a particular theme. It is merely a collection of skins + * that are applicable to the corresponding controls. + * + * Each theme is stored as a directory and files under that directory. + * The theme name is the directory name. When TTheme is created, the files + * whose name has the extension ".skin" are parsed and saved as controls skins. + * + * A skin is essentially a list of initial property values that are to be applied + * to a control when the skin is applied. + * Each type of control can have multiple skins identified by the SkinID. + * If a skin does not have SkinID, it is the default skin that will be applied + * to controls that do not specify particular SkinID. + * + * Whenever possible, TTheme will try to make use of available cache to save + * the parsing time. + * + * To apply a theme to a particular control, call {@link applySkin}. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI + * @since 3.0 + */ class TTheme extends TComponent { + /** + * prefix for cache variable name used to store parsed themes + */ const THEME_CACHE_PREFIX='prado:theme:'; + /** + * Extension name of skin files + */ const SKIN_FILE_EXT='.skin'; + /** + * @var string theme path + */ private $_themePath; + /** + * @var string theme url + */ private $_themeUrl; + /** + * @var array list of skins for the theme + */ private $_skins=null; + /** + * Constructor. + * @param TApplication application instance + * @param string theme path + * @param string theme URL + * @throws TConfigurationException if theme path does not exist or any parsing error of the skin files + */ public function __construct($application,$themePath,$themeUrl) { $this->_themeUrl=$themeUrl; @@ -176,18 +260,18 @@ class TTheme extends TComponent foreach($template->getItems() as $skin) { if($skin[0]!==-1) - throw new TConfigurationException('theme_control_nested',$skin[1]); + throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath)); else if(!isset($skin[2])) // a text string, ignored continue; $type=$skin[1]; $id=isset($skin[2]['skinid'])?$skin[2]['skinid']:0; unset($skin[2]['skinid']); if(isset($this->_skins[$type][$id])) - throw new TConfigurationException('theme_skinid_duplicated',$type,$id); + throw new TConfigurationException('theme_skinid_duplicated',$type,$id,dirname($themePath)); foreach($skin[2] as $name=>$value) { if(is_array($value) && $value[0]===0) - throw new TConfigurationException('theme_databind_forbidden',$type,$id,$name); + throw new TConfigurationException('theme_databind_forbidden',dirname($themePath),$type,$id); } $this->_skins[$type][$id]=$skin[2]; } @@ -199,6 +283,15 @@ class TTheme extends TComponent } } + /** + * Applies the theme to a particular control. + * The control's class name and SkinID value will be used to + * identify which skin to be applied. If the control's SkinID is empty, + * the default skin will be applied. + * @param TControl the control to be applied with a skin + * @return boolean if a skin is successfully applied + * @throws TConfigurationException if any error happened during the skin application + */ public function applySkin($control) { $type=get_class($control); @@ -225,12 +318,12 @@ class TTheme extends TComponent $control->$setter($value); } else - throw new TConfigurationException('theme_property_readonly',get_class($control),$name); + throw new TConfigurationException('theme_property_readonly',$type,$name); } else if($control->getAllowCustomAttributes()) $control->getAttributes()->add($name,$value); else - throw new TConfigurationException('theme_property_undefined',get_class($control),$name); + throw new TConfigurationException('theme_property_undefined',$type,$name); } else // complex property $control->setSubProperty($name,$value); @@ -242,5 +335,4 @@ class TTheme extends TComponent } } - ?> \ No newline at end of file -- cgit v1.2.3