- Merged XSLT and AJAX -based themes - Added automatic browser detection and mode selection - Added automatic ajax-html page generation - Added automatic XSLT theme header generation (no more window template modifications needed!) svn changeset:187/svn branch:toolkittags/6.7.0.beta1
@@ -114,7 +114,7 @@ public class AjaxApplicationManager implements Paintable.RepaintRequestListener, | |||
application.removeListener((Application.WindowDetachListener) this); | |||
} | |||
public void handleXmlHttpRequest(HttpServletRequest request, | |||
public void handleUidlRequest(HttpServletRequest request, | |||
HttpServletResponse response) throws IOException { | |||
boolean repaintAll = request.getParameter(GET_PARAM_REPAINT_ALL) != null; |
@@ -52,7 +52,9 @@ import java.util.List; | |||
import java.util.Map; | |||
import java.util.Properties; | |||
import java.util.Set; | |||
import java.util.Stack; | |||
import java.util.StringTokenizer; | |||
import java.util.Vector; | |||
import java.util.WeakHashMap; | |||
import javax.servlet.ServletContext; | |||
@@ -136,49 +138,49 @@ public class ApplicationServlet extends HttpServlet implements | |||
private static final String PARAMETER_TRANSFORMER_CACHETIME = "TransformerCacheTime"; | |||
private static int DEFAULT_THEME_CACHETIME = 1000 * 60 * 60 * 24; | |||
private static final int DEFAULT_THEME_CACHETIME = 1000 * 60 * 60 * 24; | |||
private static int DEFAULT_BUFFER_SIZE = 32 * 1024; | |||
private static final int DEFAULT_BUFFER_SIZE = 32 * 1024; | |||
private static int DEFAULT_MAX_TRANSFORMERS = 1; | |||
private static final int DEFAULT_MAX_TRANSFORMERS = 1; | |||
private static int MAX_BUFFER_SIZE = 64 * 1024; | |||
private static final int MAX_BUFFER_SIZE = 64 * 1024; | |||
private static String SESSION_ATTR_VARMAP = "itmill-toolkit-varmap"; | |||
private static final String SESSION_ATTR_VARMAP = "itmill-toolkit-varmap"; | |||
static String SESSION_ATTR_CONTEXT = "itmill-toolkit-context"; | |||
private static final String SESSION_ATTR_CONTEXT = "itmill-toolkit-context"; | |||
static String SESSION_ATTR_APPS = "itmill-toolkit-apps"; | |||
protected static final String SESSION_ATTR_APPS = "itmill-toolkit-apps"; | |||
private static String SESSION_BINDING_LISTENER = "itmill-toolkit-bindinglistener"; | |||
private static final String SESSION_BINDING_LISTENER = "itmill-toolkit-bindinglistener"; | |||
// TODO Should default or base theme be the default? | |||
private static String DEFAULT_THEME = "default"; | |||
protected static final String DEFAULT_THEME = "base"; | |||
private static String RESOURCE_URI = "/RES/"; | |||
private static final String RESOURCE_URI = "/RES/"; | |||
private static String AJAX_UIDL_URI = "/UIDL/"; | |||
private static final String AJAX_UIDL_URI = "/UIDL/"; | |||
private static String THEME_DIRECTORY_PATH = "WEB-INF/lib/themes/"; | |||
private static final String THEME_DIRECTORY_PATH = "WEB-INF/lib/themes/"; | |||
private static String THEME_LISTING_FILE = THEME_DIRECTORY_PATH | |||
private static final String THEME_LISTING_FILE = THEME_DIRECTORY_PATH | |||
+ "themes.txt"; | |||
private static String DEFAULT_THEME_JAR_PREFIX = "itmill-toolkit-themes"; | |||
private static final String DEFAULT_THEME_JAR_PREFIX = "itmill-toolkit-themes"; | |||
private static String DEFAULT_THEME_JAR = "WEB-INF/lib/" | |||
private static final String DEFAULT_THEME_JAR = "WEB-INF/lib/" | |||
+ DEFAULT_THEME_JAR_PREFIX + "-" + VERSION + ".jar"; | |||
private static String DEFAULT_THEME_TEMP_FILE_PREFIX = "ITMILL_TMP_"; | |||
private static final String DEFAULT_THEME_TEMP_FILE_PREFIX = "ITMILL_TMP_"; | |||
private static String SERVER_COMMAND_PARAM = "SERVER_COMMANDS"; | |||
private static final String SERVER_COMMAND_PARAM = "SERVER_COMMANDS"; | |||
private static int SERVER_COMMAND_STREAM_MAINTAIN_PERIOD = 15000; | |||
private static final int SERVER_COMMAND_STREAM_MAINTAIN_PERIOD = 15000; | |||
private static int SERVER_COMMAND_HEADER_PADDING = 2000; | |||
private static final int SERVER_COMMAND_HEADER_PADDING = 2000; | |||
// Maximum delay between request for an user to be considered active (in ms) | |||
private static long ACTIVE_USER_REQUEST_INTERVAL = 1000 * 45; | |||
private static final long ACTIVE_USER_REQUEST_INTERVAL = 1000 * 45; | |||
// Private fields | |||
private Class applicationClass; | |||
@@ -499,15 +501,9 @@ public class ApplicationServlet extends HttpServlet implements | |||
HttpVariableMap variableMap = null; | |||
OutputStream out = response.getOutputStream(); | |||
HashSet currentlyDirtyWindowsForThisApplication = new HashSet(); | |||
WebApplicationContext appContext = null; | |||
Application application = null; | |||
try { | |||
// If the resource path is unassigned, initialize it | |||
if (resourcePath == null) | |||
resourcePath = request.getContextPath() | |||
+ request.getServletPath() + RESOURCE_URI; | |||
// Handle resource requests | |||
if (handleResourceRequest(request, response)) | |||
return; | |||
@@ -523,19 +519,15 @@ public class ApplicationServlet extends HttpServlet implements | |||
if (application == null) | |||
application = createApplication(request); | |||
// Is this a download request from application | |||
DownloadStream download = null; | |||
// Set the last application request date | |||
applicationToLastRequestDate.put(application, new Date()); | |||
// Invoke context transaction listeners | |||
if (application != null) { | |||
appContext = (WebApplicationContext) application.getContext(); | |||
} | |||
if (appContext != null) { | |||
appContext.startTransaction(application, request); | |||
} | |||
((WebApplicationContext) application.getContext()) | |||
.startTransaction(application, request); | |||
// Set the last application request date | |||
applicationToLastRequestDate.put(application, new Date()); | |||
// Is this a download request from application | |||
DownloadStream download = null; | |||
// The rest of the process is synchronized with the application | |||
// in order to guarantee that no parallel variable handling is | |||
@@ -546,7 +538,7 @@ public class ApplicationServlet extends HttpServlet implements | |||
String resourceId = request.getPathInfo(); | |||
if (resourceId != null && resourceId.startsWith(AJAX_UIDL_URI)) { | |||
getApplicationManager(application).handleXmlHttpRequest( | |||
getApplicationManager(application).handleUidlRequest( | |||
request, response); | |||
return; | |||
@@ -594,6 +586,7 @@ public class ApplicationServlet extends HttpServlet implements | |||
window, t)); | |||
} | |||
} | |||
// Remove application if it has stopped | |||
if (!application.isRunning()) { | |||
endApplication(request, response, application); | |||
@@ -634,34 +627,128 @@ public class ApplicationServlet extends HttpServlet implements | |||
window.setTerminal(terminalType); | |||
} | |||
// Find theme and initialize TransformerType | |||
UIDLTransformerType transformerType = null; | |||
if (window.getTheme() != null) { | |||
Theme activeTheme; | |||
if ((activeTheme = this.themeSource | |||
.getThemeByName(window.getTheme())) != null) { | |||
transformerType = new UIDLTransformerType( | |||
terminalType, activeTheme); | |||
} else { | |||
Log | |||
.info("Theme named '" | |||
+ window.getTheme() | |||
+ "' not found. Using system default theme."); | |||
// Find theme | |||
Theme theme = themeSource | |||
.getThemeByName(window.getTheme() != null ? window | |||
.getTheme() : DEFAULT_THEME); | |||
if (theme == null) | |||
throw new ServletException("Default theme (named '" | |||
+ DEFAULT_THEME + "') can not be found"); | |||
// If UIDL rendering mode is preferred, a page for it is | |||
// rendered | |||
String renderingMode = theme.getPreferredMode(terminalType, | |||
themeSource); | |||
if (Theme.MODE_UIDL.equals(renderingMode)) { | |||
response.setContentType("text/html"); | |||
BufferedWriter page = new BufferedWriter( | |||
new OutputStreamWriter(out)); | |||
page | |||
.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " | |||
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"); | |||
page.write("<html><head>\n<title>" | |||
+ window.getCaption() + "</title>\n"); | |||
Theme t = theme; | |||
Vector themes = new Vector(); | |||
themes.add(t); | |||
while (t.getParent() != null) { | |||
String parentName = t.getParent(); | |||
t = themeSource.getThemeByName(parentName); | |||
themes.add(t); | |||
} | |||
} | |||
for (int k=themes.size()-1; k>=0; k--) { | |||
t = (Theme) themes.get(k); | |||
Collection files = t.getFileNames(terminalType, | |||
Theme.MODE_UIDL); | |||
for (Iterator i = files.iterator(); i.hasNext();) { | |||
String file = (String) i.next(); | |||
if (file.endsWith(".css")) | |||
page | |||
.write("<link rel=\"stylesheet\" href=\"" | |||
+ getResourceLocation(t | |||
.getName(), | |||
new ThemeResource( | |||
file)) | |||
+ "\" type=\"text/css\" />\n"); | |||
else if (file.endsWith(".js")) | |||
page | |||
.write("<script src=\"" | |||
+ getResourceLocation(t | |||
.getName(), | |||
new ThemeResource( | |||
file)) | |||
+ "\" type=\"text/javascript\"></script>\n"); | |||
} | |||
} | |||
page.write("</head><body>\n"); | |||
// Use default theme if selected theme was not found. | |||
if (transformerType == null) { | |||
Theme defaultTheme = this.themeSource | |||
.getThemeByName(ApplicationServlet.DEFAULT_THEME); | |||
if (defaultTheme == null) { | |||
throw new ServletException( | |||
"Default theme not found in the specified theme source(s)."); | |||
page | |||
.write("<div id=\"ajax-wait\"><div>Loading...</div></div>\n"); | |||
page.write("<div id=\"ajax-window\"></div>\n"); | |||
page.write("<script language=\"JavaScript\">\n"); | |||
page | |||
.write("var client = new ITMillToolkitClient(" | |||
+ "document.getElementById('ajax-window')," | |||
+ "\"" | |||
+ getApplicationUrl(request) | |||
+ "/UIDL/" | |||
+ "\",\"" | |||
+ resourcePath + ((Theme)themes.get(themes.size()-1)).getName() + "/" | |||
+ "client/\",document.getElementById('ajax-wait'));\n"); | |||
// TODO Should we also show debug information? | |||
/* | |||
* var debug = | |||
* document.location.href.split("debug=")[1]; if (debug && | |||
* debug.split("&")[0] == "1") client.debugEnabled = | |||
* true; | |||
*/ | |||
for (int k=themes.size()-1; k>=0; k--) { | |||
t = (Theme) themes.get(k); | |||
String themeObjName = t.getName() + "Theme"; | |||
themeObjName = themeObjName.substring(0,1).toUpperCase() + themeObjName.substring(1); | |||
page | |||
.write(" (new "+themeObjName+"(\"" + resourcePath + ((Theme)themes.get(k)).getName() + "/\")).registerTo(client);\n"); | |||
} | |||
transformerType = new UIDLTransformerType(terminalType, | |||
defaultTheme); | |||
page.write("client.start();\n"); | |||
page.write("</script>\n"); | |||
page.write("</body></html>\n"); | |||
page.close(); | |||
return; | |||
} | |||
// If other than XSLT or UIDL mode is requested | |||
if (!Theme.MODE_XSLT.equals(renderingMode)) { | |||
// TODO More informal message should be given is browser | |||
// is not supported | |||
response.setContentType("text/html"); | |||
BufferedWriter page = new BufferedWriter( | |||
new OutputStreamWriter(out)); | |||
page.write("<html><head></head><body>"); | |||
page.write("Unsupported browser."); | |||
page.write("</body></html>"); | |||
page.close(); | |||
return; | |||
} | |||
// Initialize Transformer | |||
UIDLTransformerType transformerType = new UIDLTransformerType( | |||
terminalType, theme); | |||
transformer = this.transformerFactory | |||
.getTransformer(transformerType); | |||
@@ -769,9 +856,9 @@ public class ApplicationServlet extends HttpServlet implements | |||
transformerFactory.releaseTransformer(transformer); | |||
// Notify transaction end | |||
if (appContext != null && application != null) { | |||
appContext.endTransaction(application, request); | |||
} | |||
if (application != null) | |||
((WebApplicationContext) application.getContext()) | |||
.endTransaction(application, request); | |||
// Clean the function library state for this thread | |||
// for security reasons | |||
@@ -988,6 +1075,11 @@ public class ApplicationServlet extends HttpServlet implements | |||
private boolean handleResourceRequest(HttpServletRequest request, | |||
HttpServletResponse response) throws ServletException { | |||
// If the resource path is unassigned, initialize it | |||
if (resourcePath == null) | |||
resourcePath = request.getContextPath() + request.getServletPath() | |||
+ RESOURCE_URI; | |||
String resourceId = request.getPathInfo(); | |||
// Check if this really is a resource request |
@@ -1,30 +1,30 @@ | |||
/* ************************************************************************* | |||
IT Mill Toolkit | |||
IT Mill Toolkit | |||
Development of Browser User Intarfaces Made Easy | |||
Development of Browser User Intarfaces Made Easy | |||
Copyright (C) 2000-2006 IT Mill Ltd | |||
************************************************************************* | |||
Copyright (C) 2000-2006 IT Mill Ltd | |||
************************************************************************* | |||
This product is distributed under commercial license that can be found | |||
from the product package on license/license.txt. Use of this product might | |||
require purchasing a commercial license from IT Mill Ltd. For guidelines | |||
on usage, see license/licensing-guidelines.html | |||
This product is distributed under commercial license that can be found | |||
from the product package on license/license.txt. Use of this product might | |||
require purchasing a commercial license from IT Mill Ltd. For guidelines | |||
on usage, see license/licensing-guidelines.html | |||
************************************************************************* | |||
For more information, contact: | |||
IT Mill Ltd phone: +358 2 4802 7180 | |||
Ruukinkatu 2-4 fax: +358 2 4802 7181 | |||
20540, Turku email: info@itmill.com | |||
Finland company www: www.itmill.com | |||
Primary source for information and releases: www.itmill.com | |||
************************************************************************* | |||
For more information, contact: | |||
IT Mill Ltd phone: +358 2 4802 7180 | |||
Ruukinkatu 2-4 fax: +358 2 4802 7181 | |||
20540, Turku email: info@itmill.com | |||
Finland company www: www.itmill.com | |||
Primary source for information and releases: www.itmill.com | |||
********************************************************************** */ | |||
********************************************************************** */ | |||
package com.itmill.toolkit.terminal.web; | |||
@@ -34,12 +34,15 @@ import java.util.Iterator; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
/** Theme source for consisting of collection of other theme sources. | |||
* This class is used to implement the retrieval of themes | |||
* from multiple sources. Also this class implements the inheritance | |||
* of themes by first retrieving the relevant parent theme information. | |||
/** | |||
* Theme source for consisting of collection of other theme sources. This class | |||
* is used to implement the retrieval of themes from multiple sources. Also this | |||
* class implements the inheritance of themes by first retrieving the relevant | |||
* parent theme information. | |||
* | |||
* @author IT Mill Ltd. | |||
* @version @VERSION@ | |||
* @version | |||
* @VERSION@ | |||
* @since 3.0 | |||
*/ | |||
public class CollectionThemeSource implements ThemeSource { | |||
@@ -54,10 +57,11 @@ public class CollectionThemeSource implements ThemeSource { | |||
} | |||
/** | |||
* @see com.itmill.toolkit.terminal.web.ThemeSource#getXSLStreams(Theme, WebBrowser) | |||
* @see com.itmill.toolkit.terminal.web.ThemeSource#getXSLStreams(Theme, | |||
* WebBrowser) | |||
*/ | |||
public Collection getXSLStreams(Theme theme, WebBrowser type) | |||
throws ThemeException { | |||
throws ThemeException { | |||
Collection xslFiles = new LinkedList(); | |||
// Add parent theme XSL | |||
@@ -74,17 +78,16 @@ public class CollectionThemeSource implements ThemeSource { | |||
} | |||
private Collection getParentXSLStreams(Theme theme, WebBrowser type) | |||
throws ThemeException { | |||
throws ThemeException { | |||
Collection xslFiles = new LinkedList(); | |||
Collection parents = theme.getParentThemes(); | |||
for (Iterator i = parents.iterator(); i.hasNext();) { | |||
String name = (String) i.next(); | |||
Theme parent = this.getThemeByName(name); | |||
String parentName = theme.getParent(); | |||
if (parentName != null) { | |||
Theme parent = this.getThemeByName(parentName); | |||
if (parent != null) { | |||
xslFiles.addAll(this.getXSLStreams(parent, type)); | |||
} else { | |||
throw new ThemeSource.ThemeException( | |||
"Parent theme not found for name: " + name); | |||
"Parent theme not found for name: " + parentName); | |||
} | |||
} | |||
return xslFiles; | |||
@@ -112,7 +115,7 @@ public class CollectionThemeSource implements ThemeSource { | |||
int delim = resourceId.indexOf("/"); | |||
String subResourceId = ""; | |||
String themeName = ""; | |||
if (delim >=0 && delim < resourceId.length() - 1) { | |||
if (delim >= 0 && delim < resourceId.length() - 1) { | |||
subResourceId = resourceId.substring(delim + 1); | |||
themeName = resourceId.substring(0, delim); | |||
} | |||
@@ -122,8 +125,9 @@ public class CollectionThemeSource implements ThemeSource { | |||
if (themeName.length() > 0) { | |||
Theme t = this.getThemeByName(themeName); | |||
if (t != null) { | |||
themes.add(t.getName()); | |||
addAllParents(themes, t); | |||
themes.add(themeName); | |||
if (t.getParent() != null) | |||
themes.add(t.getParent()); | |||
} | |||
} | |||
@@ -134,8 +138,8 @@ public class CollectionThemeSource implements ThemeSource { | |||
// Search all sources | |||
for (Iterator i = this.sources.iterator(); i.hasNext();) { | |||
try { | |||
InputStream in = | |||
((ThemeSource) i.next()).getResource(resource); | |||
InputStream in = ((ThemeSource) i.next()) | |||
.getResource(resource); | |||
if (in != null) | |||
return in; | |||
} catch (ThemeException e) { | |||
@@ -144,26 +148,8 @@ public class CollectionThemeSource implements ThemeSource { | |||
} | |||
} | |||
throw new ThemeException( | |||
"Theme resource not found:" | |||
+ subResourceId | |||
+ " in themes " | |||
+ themes); | |||
} | |||
/** Recusrivelu get list of parent themes in inheritace order. | |||
* | |||
* @param t Theme which parents should be listed | |||
* @return Collection of themes in inheritance order. | |||
*/ | |||
private void addAllParents(List list, Theme t) { | |||
if (t == null) | |||
return; | |||
List parents = t.getParentThemes(); | |||
list.addAll(parents); | |||
for (Iterator i = parents.iterator(); i.hasNext();) { | |||
addAllParents(list, this.getThemeByName((String) i.next())); | |||
} | |||
throw new ThemeException("Theme resource not found:" + subResourceId | |||
+ " in themes " + themes); | |||
} | |||
/** | |||
@@ -190,8 +176,11 @@ public class CollectionThemeSource implements ThemeSource { | |||
return null; | |||
} | |||
/**Add new theme source to this collection. | |||
* @param source Theme source to be added. | |||
/** | |||
* Add new theme source to this collection. | |||
* | |||
* @param source | |||
* Theme source to be added. | |||
*/ | |||
public void add(ThemeSource source) { | |||
this.sources.add(source); |
@@ -172,8 +172,8 @@ public class Theme extends DefaultHandler { | |||
/** Author of the theme. */ | |||
private Author author; | |||
/** List of parent themes */ | |||
private List parentThemes = new LinkedList(); | |||
/** Name of the theme, which this theme extends */ | |||
private String parentTheme = null; | |||
/** Fileset of included XSL files. */ | |||
private Fileset files = null; | |||
@@ -234,26 +234,30 @@ public class Theme extends DefaultHandler { | |||
* Get the preferred operating mode supported by this theme for given | |||
* terminal. | |||
*/ | |||
public String getPreferredMode(WebBrowser terminal) { | |||
public String getPreferredMode(WebBrowser terminal, ThemeSource themeSource) { | |||
// If no supported modes are declared, then we use parents preferred | |||
// mode | |||
if (parentThemes != null && parentThemes.size() > 0 | |||
&& supportedModes.keySet().isEmpty()) | |||
return ((Theme) parentThemes.get(0)).getPreferredMode(terminal); | |||
if (parentTheme != null | |||
&& supportedModes.keySet().isEmpty()) { | |||
Theme parent = themeSource.getThemeByName(parentTheme); | |||
if (parent == null) | |||
throw new IllegalStateException("Parent theme '"+parentTheme+"' is not found for theme '"+getName()+"'."); | |||
return parent.getPreferredMode(terminal, themeSource); | |||
} | |||
// Iterate and test the modes in order | |||
for (Iterator i = supportedModes.keySet().iterator(); i.hasNext();) { | |||
String mode = (String) i.next(); | |||
if (supportsMode(mode, terminal)) | |||
if (supportsMode(mode, terminal,themeSource)) | |||
return mode; | |||
} | |||
return MODE_FALLBACK; | |||
return null; | |||
} | |||
/** Tests if this theme suppors given mode */ | |||
public boolean supportsMode(String mode, WebBrowser terminal) { | |||
public boolean supportsMode(String mode, WebBrowser terminal, ThemeSource themeSource) { | |||
// Theme must explicitly support the given mode | |||
RequirementCollection rc = (RequirementCollection) supportedModes | |||
@@ -262,9 +266,13 @@ public class Theme extends DefaultHandler { | |||
return false; | |||
// All parents must also support the mode | |||
for (Iterator i = parentThemes.iterator(); i.hasNext();) | |||
if (!((Theme) i.next()).supportsMode(mode, terminal)) | |||
return false; | |||
if (parentTheme != null) { | |||
Theme parent = themeSource.getThemeByName(parentTheme); | |||
if (parent == null) | |||
throw new IllegalStateException("Parent theme '"+parentTheme+"' is not found for theme '"+getName()+"'."); | |||
if(!parent.supportsMode(mode, terminal, themeSource)) | |||
return false; | |||
} | |||
return true; | |||
} | |||
@@ -324,7 +332,9 @@ public class Theme extends DefaultHandler { | |||
if (this.name.equals(themeName)) | |||
throw new IllegalArgumentException("Theme " + this.name | |||
+ " extends itself."); | |||
this.parentThemes.add(themeName); | |||
if (parentTheme != null) | |||
throw new IllegalArgumentException("Only one extends statement is allowed"); | |||
this.parentTheme = themeName; | |||
} else if (TAG_FILE.equals(qName)) { | |||
File f = new File(atts.getValue(ATTR_NAME)); | |||
if (this.openFilesets.isEmpty()) { | |||
@@ -437,6 +447,11 @@ public class Theme extends DefaultHandler { | |||
this.modesListCurrentlyOpen = false; | |||
} else if (TAG_MODE.equals(qName)) { | |||
this.currentlyOpenMode = null; | |||
} else if (TAG_OR.equals(qName) || TAG_AND.equals(qName)) { | |||
RequirementCollection r = (RequirementCollection) openRequirements.pop(); | |||
if (openRequirements.size() < 1) | |||
throw new IllegalStateException(); | |||
((RequirementCollection)openRequirements.peek()).addRequirement(r); | |||
} | |||
} | |||
@@ -532,8 +547,8 @@ public class Theme extends DefaultHandler { | |||
* @see java.lang.Object#toString() | |||
*/ | |||
public String toString() { | |||
return this.name + " author=[" + this.author + "]" + " inherits=" | |||
+ parentThemes + "]" + " files={" | |||
return this.name + " author='" + this.author + "'" + (parentTheme != null ? " inherits='" | |||
+ parentTheme + "'" : "" )+ " files={" | |||
+ (files != null ? files.toString() : "null") + "}"; | |||
} | |||
@@ -1082,13 +1097,11 @@ public class Theme extends DefaultHandler { | |||
} | |||
/** | |||
* Returns the list of parent themes of this theme. Returns list of all | |||
* inherited themes in the inheritance order. | |||
* Returns the name of the parent theme. | |||
* | |||
* @return List of parent theme instances. | |||
*/ | |||
public List getParentThemes() { | |||
return parentThemes; | |||
public String getParent() { | |||
return parentTheme; | |||
} | |||
/** Get theme description */ |
@@ -100,7 +100,7 @@ public class WebBrowser implements Terminal { | |||
* @return Name of the terminal window | |||
*/ | |||
public String getDefaultTheme() { | |||
return "default"; | |||
return ApplicationServlet.DEFAULT_THEME; | |||
} | |||
/** Get the name and version of the web browser application. |