All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zkoss.web.fn.ThemeFns Maven / Gradle / Ivy

/* ThemeFns.java

{{IS_NOTE
	Purpose:
		
	Description:
		
	History:
		Jul 10, 2012 9:35:27 AM , Created by jumperchen
}}IS_NOTE

Copyright (C) 2012 Potix Corporation. All Rights Reserved.

{{IS_RIGHT
}}IS_RIGHT
 */
package org.zkoss.web.fn;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.zkoss.lang.Library;
import org.zkoss.lang.Strings;
import org.zkoss.util.resource.Locators;
import org.zkoss.web.servlet.Servlets;
import org.zkoss.web.theme.StandardTheme;
import org.zkoss.web.theme.Theme;
import org.zkoss.web.theme.ThemeRegistry;
import org.zkoss.web.theme.ThemeResolver;
import org.zkoss.web.util.resource.ClassWebResource;

/**
 * Providing theme relevant functions for EL.
 * 
 * @author simonpai
 * @author jumperchen
 * @since 6.5.0
 */
public class ThemeFns {

	private ThemeFns() {
	}

	private static Browser getBrowser() {
		Double number = Servlets.getBrowser(ServletFns.getCurrentRequest(), "ff");
		if (number != null && number >= 3.6)
			return Browser.Firefox;
		number = Servlets.getBrowser(ServletFns.getCurrentRequest(), "ie");
		if (number != null) {
			if (number <= 9) {
				return Browser.IE9;
			} else
				return Browser.IE;
		}
		number = Servlets.getBrowser(ServletFns.getCurrentRequest(), "webkit");
		if (number != null) {
			Double android = Servlets.getBrowser(ServletFns.getCurrentRequest(), "android");
			if (android != null && android < 3) {
				return Browser.Old_WebKit;
			}
			Double version = Servlets.getBrowser(ServletFns.getCurrentRequest(), "chrome");
			if (version != null) {
				if (version >= 10)
					return Browser.WebKit;
				if (version >= 1)
					return Browser.Old_WebKit;
			}

			// B65-ZK-1614: Full Screen iPad Web Apps Missing Component Buttons
			version = Servlets.getBrowser(ServletFns.getCurrentRequest(), "ios");
			if (version != null && version >= 500)
				return Browser.WebKit;

			version = Servlets.getBrowser(ServletFns.getCurrentRequest(), "safari");
			if (version != null) {
				if (version >= 5.1)
					return Browser.WebKit;
				if (version >= 4)
					return Browser.Old_WebKit;
			}
		}
		number = Servlets.getBrowser(ServletFns.getCurrentRequest(), "opera");
		if (number != null && number >= 11.1)
			return Browser.Opera;
		return Browser.Old;
	}

	/**
	 * Generates a specific of browser CSS color gradient rules String.
	 * 
	 * @param direction
	 *            "ver", "hor", "diag-", "diag+", "rad"
	 * @param colors
	 *            the colors with stops, which are separated by semicolon ";".
	 *        For example,
	 *        
ThemeFns.gradient("ver", "#fefefe 0%; #eeeeee 100%");
* @return A specific CSS gradient rules String */ public static String gradient(String direction, String colors) { Browser temp = getBrowser(); if (temp == Browser.Old || temp == Browser.W3C) return "\tbackground:" + grad(direction, getBrowser(), colors.split(";")); else { String[] cols = colors.split(";"); StringBuilder sb = new StringBuilder(); sb.append("\tbackground:"); sb.append(grad(direction, temp, cols)); sb.append("\tbackground:").append(grad(direction, Browser.W3C, cols)); return sb.toString(); } } /** * Generates a specific CSS color gradient value only. * * @param direction * "ver", "hor", "diag-", "diag+", "rad" * @param colors * the colors with stops, which are separated by semicolon ";" * For example, *
ThemeFns.gradValue("ver", "#fefefe 0%; #eeeeee 100%");
* @return A specific CSS gradient rules String without the words * "background:". */ public static String gradValue(String direction, String colors) { return grad(direction, getBrowser(), colors.split(";")).replace(";", ""); } private static String grad(String dir, Browser template, String[] colors) { if ("|ver|hor|diag-|diag+|rad|".indexOf("|" + dir + "|") == -1) throw new IllegalArgumentException("Type must be ver, hor, diag-, diag+, or rad."); if (colors.length < 2) throw new IllegalArgumentException("Please specify more than two colors."); String color1 = toHex(colors[0]); String color2 = toHex(colors[1]); StringBuilder colorAll = new StringBuilder(); if (template == Browser.Old_WebKit) { for (String color : colors) { color = color.trim(); boolean hex = color.startsWith("#"); int end = hex ? color.indexOf(" ") + 1 : color.indexOf(")") + 1; if (end == 0 && !color.toLowerCase(java.util.Locale.ENGLISH).contains("transparent")) if (hex) throw new IllegalArgumentException( "The format of hexadecimal is wrong! [" + color + "] or without stops (%)"); else throw new IllegalArgumentException( "The format of RGBA is wrong! [" + color + "] or without stops (%)"); String pos = color.substring(end, color.length()); color = color.substring(0, end); colorAll.append("color-stop(").append(pos).append(',').append(color).append("),"); } int len = colorAll.length(); if (len > 0) colorAll.delete(len - 1, len); } else if (template == Browser.IE9) { for (String color : colors) { color = color.trim(); boolean hex = color.startsWith("#"); int end = hex ? color.indexOf(" ") + 1 : color.indexOf(")") + 1; if (end == 0 && !color.toLowerCase(java.util.Locale.ENGLISH).contains("transparent")) if (hex) throw new IllegalArgumentException( "The format of hexadecimal is wrong! [" + color + "] or without stops (%)"); else throw new IllegalArgumentException( "The format of RGBA is wrong! [" + color + "] or without stops (%)"); String pos = color.substring(end, color.length()); color = color.substring(0, end); colorAll.append(""); } } else { for (String color : colors) { colorAll.append(color).append(','); } int len = colorAll.length(); if (len > 0) colorAll.delete(len - 1, len); } String gradType = "rad".equals(dir) ? "radial" : "linear"; int ieGradType = "hor".equals(dir) ? 1 : 0; // IE only supports // ver/hor String result = String.format(template.getGradient(dir), color1, color2, "", gradType, ieGradType, colorAll.toString()); if (template == Browser.IE9) { result = "url(data:image/svg+xml;base64," + Base64.getEncoder() .encodeToString(result.getBytes(StandardCharsets.UTF_8)) + ");"; } return result; } /** * Generates a set of cross-browser CSS color gradient rules String. * * @param direction * "ver", "hor", "diag-", "diag+", "rad" * @param colors * the colors, which are separated by semicolon ";" * @return A set of cross-browser CSS gradient rules String */ public static String gradients(String direction, String colors) { StringBuilder sb = new StringBuilder(); String[] cols = colors.split(";"); for (Browser grad : Browser.values()) { sb.append("\tbackground:"); sb.append(grad(direction, grad, cols)); } return sb.toString(); } private static String CSS_TEMPLATE = "\t %1$s%2$s:\t %3$s;\n\t %2$s:\t%3$s;"; private static String CSS_TEMPLATE_W3C = "\t %1$s:\t%2$s;"; private static String applyCSS(String styleName, String styleValue) { Browser browser = getBrowser(); if (!Strings.isEmpty(browser.getPrefix())) { return String.format(CSS_TEMPLATE, browser.getPrefix(), styleName, styleValue); } return String.format(CSS_TEMPLATE_W3C, styleName, styleValue); } /** * Generates a specific browser CSS rule String for the given style name and * value. *

* Note: the method is only applied with the browser prefix as the style * name, if the CSS3 style usage rule is different between browsers, please * use another method instead. * * @param styleName * the value of the style name, like box-sizing, * animation * @param styleValue * the value according to the style name, like * border-box, mymove 5s infinite * @return a specific browser CSS rule string, like * -moz-box-sizing for firefox and * -webkit-box-sizing for safari and chrome */ public static String applyCSS3(String styleName, String styleValue) { return applyCSS(styleName, styleValue); } /** * Generates a specific browser CSS rule string for box model. * * @param styleName * the value of the style name, like box-orient, * box-pack * @param styleValue * the value according to the style name, like * horizontal, center * @return a specific browser CSS rule string, like * -moz-box-orient for firefox and * -webkit-box-orient for safari and chrome */ public static String box(String styleName, String styleValue) { Browser browser = getBrowser(); StringBuilder sb = new StringBuilder(32); if (browser == Browser.Firefox || browser == Browser.WebKit) { sb.append("\t display:\t").append(browser.getPrefix()).append("box;\n"); } sb.append("\t display:\t box;\n"); return sb.append(applyCSS(styleName, styleValue)).toString(); } /** * Generates a specific browser CSS rule string for box model with two pair * styles. * * @see #box(String, String) */ public static String box2(String styleName, String styleValue, String styleName2, String styleValue2) { Browser browser = getBrowser(); StringBuilder sb = new StringBuilder(32); if (browser == Browser.Firefox || browser == Browser.WebKit) { sb.append("\t display:\t").append(browser.getPrefix()).append("box;\n"); } sb.append("\t display:\t box;\n"); return sb.append(applyCSS(styleName, styleValue)).append(applyCSS(styleName2, styleValue2)).toString(); } /** * Generates a specific browser CSS rule string for box model with three pair * styles. * * @see #box(String, String) * @see #box2(String, String, String, String) */ public static String box3(String styleName, String styleValue, String styleName2, String styleValue2, String styleName3, String styleValue3) { Browser browser = getBrowser(); StringBuilder sb = new StringBuilder(32); if (browser == Browser.Firefox || browser == Browser.WebKit) { sb.append("\t display:\t").append(browser.getPrefix()).append("box;\n"); } sb.append("\t display:\t box;\n"); return sb.append(applyCSS(styleName, styleValue)).append(applyCSS(styleName2, styleValue2)) .append(applyCSS(styleName3, styleValue3)).toString(); } /** * Generates a specific browser CSS transform. * * @param style * the value of the transform * @return a specific browser CSS transform */ public static String transform(String style) { return applyCSS("transform", style); } /** * Generates a specific browser CSS box-shadow. * * @param style * the value of the box-shadow * @return a specific browser CSS box-shadow */ public static String boxShadow(String style) { return applyCSS("box-shadow", style); } /** * Generates a specific browser CSS border-radius. * * @param style * the value of the border-radius * @return a specific browser CSS border-radius */ public static String borderRadius(String style) { return applyCSS("border-radius", style); } @SuppressWarnings("unchecked") private static String toHex(String color) { color = color.trim(); if (color.startsWith("#")) { int end = color.indexOf(" "); if (end > 0) return color.substring(0, end); return color; } int end = color.indexOf(')') + 1; if (end > 0) color = color.substring(0, end); Map colors = (Map) ServletFns.getCurrentRequest() .getAttribute("themeFns.colors"); if (colors == null) ServletFns.getCurrentRequest().setAttribute("themeFns.colors", colors = new HashMap()); if (!colors.containsKey(color)) colors.put(color, toHex(toColor(color))); return colors.get(color); } private static String toHex(Color color) { return Colors.getHexString(color); } @SuppressWarnings("unchecked") private static String toIEHex(String color) { color = color.trim(); if (color.startsWith("#")) { int end = color.indexOf(" "); if (end > 0) return color.substring(0, end); return color; } int end = color.indexOf(')') + 1; if (end > 0) color = color.substring(0, end); Map colors = (Map) ServletFns.getCurrentRequest() .getAttribute("themeFns.IEcolors"); if (colors == null) ServletFns.getCurrentRequest().setAttribute("themeFns.IEcolors", colors = new HashMap()); if (!colors.containsKey(color)) colors.put(color, toIEHex(toColor(color))); return colors.get(color); } private static String toIEHex(Color color) { return Colors.getIEHexString(color); } private static String locate(String path) { try { if (path.startsWith("~./")) { path = Servlets.locate(ServletFns.getCurrentServletContext(), ServletFns.getCurrentRequest(), ClassWebResource.PATH_PREFIX + path.substring(2), Locators.getDefault()); return path; } return Servlets.locate(ServletFns.getCurrentServletContext(), ServletFns.getCurrentRequest(), path, null); } catch (ServletException ex) { log(ex.getLocalizedMessage()); } return path; } private static void log(String msg) { Logger log = LoggerFactory.getLogger("global"); if (log.isErrorEnabled()) log.error(msg); else System.err.println(msg); } /** * Loads a theme properties and apply them into the request scope. * @param path a file path */ public static void loadProperties(String path) { // add ability to load theme properties from a folder // @since 6.5.2 if (!ThemeProperties.loadProperties(ServletFns.getCurrentRequest(), locate(ServletFns.resolveThemeURL(path)))) { log("The properties file is not loaded correctly! [" + path + "]"); } } private static Color toColor(String color) { return Colors.parseCSS(color); } private enum Browser { WebKit("-webkit-", "Chrome10+,Safari5.1+"), W3C("", "W3C"), Firefox("-moz-", "FF3.6+"), Opera("-o-", "Opera 11.10+"), IE("-ms-", "IE10+"), IE9("-ms-", "IE9"), Old(null, null), Old_WebKit("-webkit-", "Chrome,Safari4+"); private final String _template; private final String _prefix; private HashMap _GRAD_TYPE = null; Browser(String prefix, String browser) { _prefix = prefix; if ("IE9".equals(browser)) { _template = new StringBuilder( "\n") .append("%3$s\n").append("%6$s\n").append("\n") .append("") .toString(); _GRAD_TYPE = new HashMap(); _GRAD_TYPE.put("ver", ""); _GRAD_TYPE.put("hor", ""); _GRAD_TYPE.put("diag-", ""); _GRAD_TYPE.put("diag+", ""); _GRAD_TYPE.put("rad", ""); } else if ("Chrome,Safari4+".equals(browser)) { _template = new StringBuilder().append("\t").append(prefix).append("gradient(%4$s, %3$s, %6$s); /* ") .append(browser).append(" */\n").toString(); _GRAD_TYPE = new HashMap(); _GRAD_TYPE.put("ver", "left top, left bottom"); _GRAD_TYPE.put("hor", "left top, right top"); _GRAD_TYPE.put("diag-", "left top, right bottom"); _GRAD_TYPE.put("diag+", "left bottom, right top"); _GRAD_TYPE.put("rad", "center center, 0px, center center, 100%"); } else if (browser != null) { _template = new StringBuilder().append("\t").append(prefix).append("%4$s-gradient(%3$s, %6$s); /* ") .append(browser).append(" */\n").toString(); if ("W3C".equals(browser)) { _GRAD_TYPE = new HashMap(); _GRAD_TYPE.put("ver", "to bottom"); _GRAD_TYPE.put("hor", "to right"); _GRAD_TYPE.put("diag-", "135deg"); _GRAD_TYPE.put("diag+", "45deg"); _GRAD_TYPE.put("rad", "ellipse at center"); } else { _GRAD_TYPE = new HashMap(); _GRAD_TYPE.put("ver", "top"); _GRAD_TYPE.put("hor", "left"); _GRAD_TYPE.put("diag-", "-45deg"); _GRAD_TYPE.put("diag+", "45deg"); _GRAD_TYPE.put("rad", "center, ellipse cover"); } } else _template = "\t%1$s; /* Old browsers */\n"; } public String getPrefix() { return _prefix; } public String getGradient(String dir) { return _template.replace("%3$s", getType(dir)); } private String getType(String dir) { return _GRAD_TYPE != null ? _GRAD_TYPE.get(dir) : ""; } } // the current theme registry private static ThemeRegistry _themeRegistry = null; // the current theme resolver private static ThemeResolver _themeResolver = null; /** * Returns the current theme registry * * @return the current theme registry * @since 6.5.2 */ public static ThemeRegistry getThemeRegistry() { return _themeRegistry; } /** * Change the theme registry * * @param themeRegistry the new theme registry * @since 6.5.2 */ public static void setThemeRegistry(ThemeRegistry themeRegistry) { _themeRegistry = themeRegistry; } /** * Returns the current theme resolver * * @return the current theme resolver * @since 6.5.2 */ public static ThemeResolver getThemeResolver() { return _themeResolver; } /** * Change the current theme resolver * * @param themeResolver the new theme resolver */ public static void setThemeResolver(ThemeResolver themeResolver) { _themeResolver = themeResolver; } private static final String THEME_PREFERRED_KEY = "org.zkoss.theme.preferred"; /** * Returns the current theme name * * @return the current theme name * @since 6.5.2 */ public static String getCurrentTheme() { // 1. cookie's key String t = getTheme(); if (_themeRegistry.hasTheme(t)) return t; // 2. library property t = Library.getProperty(THEME_PREFERRED_KEY); if (_themeRegistry.hasTheme(t)) return t; // 3. theme of highest priority Theme[] themes = _themeRegistry.getThemes(); StandardTheme highest = null; Comparator comparator = StandardTheme.getComparator(); for (Theme theme : themes) { if (theme instanceof StandardTheme) { if (comparator.compare((StandardTheme) theme, highest) < 0) { highest = (StandardTheme) theme; } } } return (highest != null) ? highest.getName() : StandardTheme.DEFAULT_NAME; } /** * Returns the theme specified in cookies * @return the name of the theme or default theme. */ private static String getTheme() { ServletRequest request = ServletFns.getCurrentRequest(); if (!(request instanceof HttpServletRequest)) return StandardTheme.DEFAULT_NAME; return _themeResolver.getTheme((HttpServletRequest) request); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy