| @@ -0,0 +1,21 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * A declaration set manager is used to handle the different declaration sets | ||
| * associated to the pseudo classes of a given target. For instance, is the | ||
| * declaration set associated to the ':hover' pseudo classe of a button target | ||
| * is not empty, this manager should register a mouse listener with the button | ||
| * that would apply the good declaration set to the button when a mouseOver | ||
| * event rise. | ||
| * <p/> | ||
| * If all targets extends a root class, then it should only be necessary to | ||
| * register a single manager with the CSS engine. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public interface DeclarationSetManager<T> | ||
| { | ||
| public void manage(T target, Map<String, DeclarationSet> dss); | ||
| } |
| @@ -0,0 +1,13 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| /** | ||
| * A declarations processor is responsible for applying a group of declarations | ||
| * to a target object. These declarations are retrieved from the stylesheet and | ||
| * correspond to the rules which selectors were walidated by the target object. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public interface DeclarationSetProcessor<T> | ||
| { | ||
| public void process(T t, DeclarationSet ds); | ||
| } |
| @@ -0,0 +1,45 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * A function, or a "functional notation", is used to produce a value for a | ||
| * parameter of a declaration value. It takes one or more parameters (which can | ||
| * be functions too), processes them and returns an object. | ||
| * <p/> | ||
| * See <a href="http://www.w3.org/TR/css3-values/#functional-notation">w3.org | ||
| * </a> for more information about functional notations. | ||
| * | ||
| * @see Property | ||
| * @see Style | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public interface Function extends Parameterized | ||
| { | ||
| /** | ||
| * Gets the name of the function, as it will be called in a CSS declaration. | ||
| */ | ||
| public String getName(); | ||
|
|
||
| /** | ||
| * Gets the parameters configuration. A configuration describes one or more | ||
| * sets of valid parameter classes. See {@link Property#getParams()} | ||
| * documentation for more information. | ||
| */ | ||
| public Class<?>[][] getParams(); | ||
|
|
||
| /** | ||
| * Gets the parameters names. | ||
| */ | ||
| public String[][] getParamsNames(); | ||
|
|
||
| /** | ||
| * Gets the class of the returned object. | ||
| */ | ||
| public Class<?> getReturn(); | ||
|
|
||
| /** | ||
| * Processes the given parameters and returns an object. | ||
| */ | ||
| public Object process(List<Object> params); | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| /** | ||
| * Some definitions in a CSS stylesheet may correspond to some objects that are | ||
| * not defined. This is the case for color definitions, like "#FFF", which need | ||
| * to be assigned to a color object. However, since the CSS engine is not bound | ||
| * to any UI technology, it will ask you to create a color object from every | ||
| * color definition, according to your framework. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public interface ParamConverter | ||
| { | ||
| /** | ||
| * Creates an object representing a color from a color definition (argb). | ||
| */ | ||
| public Object convertColor(int argb); | ||
|
|
||
| /** | ||
| * Gets the class of the returned result for convertColor method. | ||
| */ | ||
| public Class<?> getColorClass(); | ||
| } |
| @@ -0,0 +1,11 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| /** | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public interface Parameterized | ||
| { | ||
| public Class<?>[][] getParams(); | ||
|
|
||
| public String[][] getParamsNames(); | ||
| } |
| @@ -0,0 +1,51 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| /** | ||
| * A property defines a style attribute, like "margin", "border" or "color" in | ||
| * common CSS syntax. A property is always associated with a value in | ||
| * declarations, like "color: #FFF", and this value can be made of one or more | ||
| * parameters. Actually, a property can support different sets of parameters. | ||
| * For instance, the common "margin" CSS property can be called with either 1, 2 | ||
| * or 4 parameters, defining the margin insets. | ||
| * <p/> | ||
| * Therefore, the engine tests the parameters associated to a property when it | ||
| * parses the file, to ensure that the stylesheet is valid. That's why a | ||
| * Property implementation needs to implement the getParams() function: to tell | ||
| * the engine what are the valid configurations of parameters for a given | ||
| * property. | ||
| * <p/> | ||
| * See <a href="http://www.w3schools.com/css/css_syntax.asp">w3schools</a> for | ||
| * more information about CSS syntax. | ||
| * | ||
| * @see Rule | ||
| * @see DeclarationSet | ||
| * @see Style | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public interface Property extends Parameterized | ||
| { | ||
| /** | ||
| * Gets the name of the property, as it will be called in a CSS rule. | ||
| */ | ||
| public String getName(); | ||
|
|
||
| /** | ||
| * Gets the parameters configuration. A configuration describes one or more | ||
| * sets of valid parameter classes. | ||
| * <p/> | ||
| * For instance, the common "margin" CSS property can be called with either | ||
| * 1, 2 or 4 parameters, defining the margin insets. You would actually | ||
| * implement that as follows: | ||
| * | ||
| * <pre> | ||
| * return new Class[][] { { Integer.class }, { Integer.class, Integer.class }, | ||
| * { Integer.class, Integer.class, Integer.class, Integer.class }, }; | ||
| * </pre> | ||
| */ | ||
| public Class<?>[][] getParams(); | ||
|
|
||
| /** | ||
| * Gets the parameters names. | ||
| */ | ||
| public String[][] getParamsNames(); | ||
| } |
| @@ -0,0 +1,58 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| /** | ||
| * A rule is defined by a selector, and a group of declarations associated to | ||
| * it, like (in common CSS for HTML): | ||
| * | ||
| * <pre> | ||
| * p { | ||
| * color: #FFF; | ||
| * text-align: center; | ||
| * } | ||
| * </pre> | ||
| * | ||
| * In the CSS engine, like in common CSS, a selector name can be a CSS class | ||
| * name, beginning with a dot, like ".redLabel", or the exact name of the | ||
| * element, like "p". In the latter case, this translates here to the Java class | ||
| * name of the element, with dots replaced by "-", like "javax-swing-JLabel" to | ||
| * match every JLabel. | ||
| * <p/> | ||
| * Note that selectors may be nested, to target some elements that are children | ||
| * of others. For instance: | ||
| * | ||
| * <pre> | ||
| * .parent .child { | ||
| * color: #FFF; | ||
| * text-align: center; | ||
| * } | ||
| * </pre> | ||
| * <p/> | ||
| * See <a href="http://www.w3schools.com/css/css_syntax.asp">w3schools</a> for | ||
| * more information about CSS syntax. | ||
| * | ||
| * @see DeclarationSet | ||
| * @see Property | ||
| * @see Style | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public class Rule | ||
| { | ||
| private final Selector selector; | ||
| private final DeclarationSet declarations; | ||
|
|
||
| public Rule(Selector selector, DeclarationSet declarations) | ||
| { | ||
| this.selector = selector; | ||
| this.declarations = declarations; | ||
| } | ||
|
|
||
| public Selector getSelector() | ||
| { | ||
| return selector; | ||
| } | ||
|
|
||
| public DeclarationSet getDeclarations() | ||
| { | ||
| return declarations; | ||
| } | ||
| } |
| @@ -0,0 +1,146 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public class Selector | ||
| { | ||
| private final List<Atom> atoms = new ArrayList<Atom>(); | ||
| private final String pseudoClass; | ||
|
|
||
| public Selector(String rawSelector) | ||
| { | ||
| rawSelector = rawSelector.trim(); | ||
| rawSelector = rawSelector.replaceAll("\\s+", " "); | ||
| rawSelector = rawSelector.replaceAll("\\s*>\\s*", " >"); | ||
|
|
||
| final int pcIdx = rawSelector.indexOf(":"); | ||
| if (pcIdx > -1) | ||
| { | ||
| pseudoClass = rawSelector.substring(pcIdx).trim(); | ||
| rawSelector = rawSelector.substring(0, pcIdx); | ||
| } | ||
| else | ||
| { | ||
| pseudoClass = ""; | ||
| } | ||
|
|
||
| final String[] parts = rawSelector.split(" "); | ||
| for (int i = 0; i < parts.length; i++) | ||
| { | ||
| atoms.add(new Atom(parts[i])); | ||
| } | ||
| } | ||
|
|
||
| public List<Atom> getAtoms() | ||
| { | ||
| return atoms; | ||
| } | ||
|
|
||
| public Atom getLastAtom() | ||
| { | ||
| return atoms.get(atoms.size() - 1); | ||
| } | ||
|
|
||
| public String getPseudoClass() | ||
| { | ||
| return pseudoClass; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() | ||
| { | ||
| String str = ""; | ||
| for (final Atom atom : atoms) | ||
| { | ||
| str += atom.toString() + " > "; | ||
| } | ||
| return str.substring(0, str.length() - 3); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
|
|
||
| public static class Atom | ||
| { | ||
| private final Class<?> type; | ||
| private final List<String> classes; | ||
| private final boolean strictNext; | ||
|
|
||
| public Atom(String str) | ||
| { | ||
| strictNext = str.startsWith(">"); | ||
|
|
||
| str = str.replaceAll(">", ""); | ||
| str = str.replaceAll("#", "."); | ||
|
|
||
| final String[] parts = str.startsWith(".") ? str.substring(1) | ||
| .split("\\.") : str.split("\\."); | ||
|
|
||
| if (parts[0].equals("*")) | ||
| { | ||
| type = Object.class; | ||
| classes = Arrays.asList(parts).subList(1, parts.length); | ||
| } | ||
| else if (str.startsWith(".")) | ||
| { | ||
| type = Object.class; | ||
| classes = Arrays.asList(parts); | ||
| } | ||
| else | ||
| { | ||
| Class<?> type = Style.getRegisteredType(parts[0]); | ||
| if (type == null) | ||
| { | ||
| try | ||
| { | ||
| type = Class.forName(parts[0].replaceAll("-", ".")); | ||
| } | ||
| catch (final ClassNotFoundException ex) | ||
| { | ||
| throw new RuntimeException(ex); | ||
| } | ||
| } | ||
|
|
||
| this.type = type; | ||
| classes = Arrays.asList(parts).subList(1, parts.length); | ||
| } | ||
| } | ||
|
|
||
| public Atom(Class<?> type, List<String> classes) | ||
| { | ||
| this.type = type; | ||
| this.classes = classes == null ? new ArrayList<String>() : classes; | ||
| strictNext = false; | ||
| } | ||
|
|
||
| public Class<?> getType() | ||
| { | ||
| return type; | ||
| } | ||
|
|
||
| public List<String> getClasses() | ||
| { | ||
| return classes; | ||
| } | ||
|
|
||
| public boolean isStrictNext() | ||
| { | ||
| return strictNext; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() | ||
| { | ||
| String str = type.getSimpleName(); | ||
| for (final String c : classes) | ||
| { | ||
| str += " " + c; | ||
| } | ||
| return str; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,54 @@ | ||
| package aurelienribon.ui.css; | ||
|
|
||
| /** | ||
| * Just an exception raised while parsing a CSS stylesheet, if anything is | ||
| * wrong. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public class StyleException extends RuntimeException | ||
| { | ||
| /** | ||
| * | ||
| */ | ||
| private static final long serialVersionUID = -6071140481291150131L; | ||
|
|
||
| public static StyleException forProperty(String name) | ||
| { | ||
| return new StyleException("Property \"" + name | ||
| + "\" is not registered."); | ||
| } | ||
|
|
||
| public static StyleException forPropertyParams(Property property) | ||
| { | ||
| return new StyleException("Bad parameter(s) for property \"" | ||
| + property.getName() + "\""); | ||
| } | ||
|
|
||
| public static StyleException forFunction(String name) | ||
| { | ||
| return new StyleException("Function \"" + name | ||
| + "\" is not registered."); | ||
| } | ||
|
|
||
| public static StyleException forFunctionParams(Function function) | ||
| { | ||
| return new StyleException("Bad parameter(s) for function \"" | ||
| + function.getName() + "\""); | ||
| } | ||
|
|
||
| public static StyleException forKeyword(String name, String... keywords) | ||
| { | ||
| String msg = "Bad keyword \"" + name + "\". Allowed:"; | ||
| for (final String s : keywords) | ||
| { | ||
| msg += " " + s; | ||
| } | ||
| return new StyleException(msg); | ||
| } | ||
|
|
||
| public StyleException(String msg) | ||
| { | ||
| super(msg); | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| package aurelienribon.ui.css.primitives; | ||
|
|
||
| import aurelienribon.ui.css.Function; | ||
|
|
||
| /** | ||
| * Convenience class to create a function. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public abstract class BaseFunction implements Function | ||
| { | ||
| private final String name; | ||
|
|
||
| public BaseFunction(String name) | ||
| { | ||
| this.name = name; | ||
| } | ||
|
|
||
| public String getName() | ||
| { | ||
| return name; | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| package aurelienribon.ui.css.primitives; | ||
|
|
||
| import aurelienribon.ui.css.Property; | ||
|
|
||
| /** | ||
| * Convenience class to create a property. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public abstract class BaseProperty implements Property | ||
| { | ||
| private final String name; | ||
|
|
||
| public BaseProperty(String name) | ||
| { | ||
| this.name = name; | ||
| } | ||
|
|
||
| public String getName() | ||
| { | ||
| return name; | ||
| } | ||
| } |
| @@ -0,0 +1,54 @@ | ||
| package aurelienribon.ui.css.primitives; | ||
|
|
||
| import aurelienribon.ui.css.Function; | ||
|
|
||
| /** | ||
| * A FunctionProperty is a property that accepts the exact same parameters as an | ||
| * existing function, plus the function result itself. To avoid duplicating | ||
| * code, the params classes and names of the property are computed from the | ||
| * function. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public class FunctionProperty extends BaseProperty | ||
| { | ||
| private final Function function; | ||
| private final Class<?> paramClass; | ||
| private final String paramName; | ||
|
|
||
| public FunctionProperty(String name, Function function, String paramName) | ||
| { | ||
| super(name); | ||
| this.function = function; | ||
| paramClass = function.getReturn(); | ||
| this.paramName = paramName; | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return concat(paramClass, function); | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return concat(paramName, function); | ||
| } | ||
|
|
||
| private Class<?>[][] concat(Class<?> newParam, Function function) | ||
| { | ||
| final Class<?>[][] ps = function.getParams(); | ||
| final Class<?>[][] result = new Class<?>[ps.length + 1][]; | ||
| result[0] = new Class<?>[] { newParam }; | ||
| System.arraycopy(ps, 0, result, 1, ps.length); | ||
| return result; | ||
| } | ||
|
|
||
| private String[][] concat(String newParam, Function function) | ||
| { | ||
| final String[][] ps = function.getParamsNames(); | ||
| final String[][] result = new String[ps.length + 1][]; | ||
| result[0] = new String[] { newParam }; | ||
| System.arraycopy(ps, 0, result, 1, ps.length); | ||
| return result; | ||
| } | ||
| } |
| @@ -0,0 +1,31 @@ | ||
| package aurelienribon.ui.css.primitives; | ||
|
|
||
| /** | ||
| * Convenience class to define a property accepting one set of parameters as | ||
| * value. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public class MultiParamsProperty extends BaseProperty | ||
| { | ||
| private final Class<?>[] paramsClasses; | ||
| private final String[] paramsNames; | ||
|
|
||
| public MultiParamsProperty(String name, Class<?>[] paramsClasses, | ||
| String[] paramsNames) | ||
| { | ||
| super(name); | ||
| this.paramsClasses = paramsClasses; | ||
| this.paramsNames = paramsNames; | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class[][] { paramsClasses }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { paramsNames }; | ||
| } | ||
| } |
| @@ -0,0 +1,31 @@ | ||
| package aurelienribon.ui.css.primitives; | ||
|
|
||
| /** | ||
| * Convenience class to define a property that accepts only one parameter as | ||
| * value. | ||
| * | ||
| * @author Aurelien Ribon | http://www.aurelienribon.com/ | ||
| */ | ||
| public class SingleParamProperty extends BaseProperty | ||
| { | ||
| private final Class<?> paramClass; | ||
| private final String paramName; | ||
|
|
||
| public SingleParamProperty(String name, Class<?> paramClass, | ||
| String paramName) | ||
| { | ||
| super(name); | ||
| this.paramClass = paramClass; | ||
| this.paramName = paramName; | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class[][] { { paramClass } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { paramName } }; | ||
| } | ||
| } |
| @@ -1172,5 +1172,10 @@ public ScrollContainer clone() | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| public Object[] getChildren() | ||
| { | ||
| return getContent().toArray(); | ||
| } | ||
|
|
||
| } | ||
| @@ -709,5 +709,10 @@ public boolean hasChildWidgets() | ||
| { | ||
| return firstWidget != null || secondWidget != null; | ||
| } | ||
|
|
||
| public Object[] getChildren() | ||
| { | ||
| return getContent().toArray(); | ||
| } | ||
|
|
||
| } | ||
| @@ -358,8 +358,8 @@ else if (e.getKey() == 'V') | ||
| } | ||
| else | ||
| { | ||
| final boolean result = textData.handleKeyPresses( | ||
| e.getKeyClass(), e.getModifiers(), getAppearance()); | ||
| return result; | ||
| } | ||
| default: | ||
| @@ -111,7 +111,7 @@ public void add(IDecorator decorator) | ||
|
|
||
| public void add(Background background) | ||
| { | ||
| add("default", background); | ||
| } | ||
|
|
||
| public void addForeground(IDecorator decorator) | ||
| @@ -61,6 +61,7 @@ public Dimension calculateSize(String text) | ||
| return null; | ||
| } | ||
|
|
||
| @SuppressWarnings("deprecation") | ||
| private FontMetrics getMetric() | ||
| { | ||
| if (metric == null) | ||
| @@ -0,0 +1,46 @@ | ||
| package org.fenggui.theme.css; | ||
|
|
||
| import java.io.File; | ||
| import java.io.IOException; | ||
|
|
||
| import org.fenggui.IWidget; | ||
| import org.fenggui.theme.ITheme; | ||
|
|
||
| import aurelienribon.ui.css.Style; | ||
|
|
||
| public class CSSTheme implements ITheme | ||
| { | ||
| private final Style style; | ||
|
|
||
| public CSSTheme(File file) throws IOException | ||
| { | ||
| FengGUIStyle.init(); | ||
|
|
||
| style = new Style(file.toURI().toURL()); | ||
| } | ||
|
|
||
| public void setUp(IWidget widget) | ||
| { | ||
| String id = widget.getId(); | ||
| String styleClass = widget.getStyleClass(); | ||
|
|
||
| if (id != null) | ||
| { | ||
| Style.registerCssClasses(widget, "#" + id); | ||
| } | ||
|
|
||
| if (styleClass != null) | ||
| { | ||
| Style.registerCssClasses(widget, "." + styleClass); | ||
| } | ||
|
|
||
| Style.apply(widget, style); | ||
|
|
||
| Style.unregister(widget); | ||
| } | ||
|
|
||
| public Style getStyle() | ||
| { | ||
| return style; | ||
| } | ||
| } |
| @@ -0,0 +1,28 @@ | ||
| package org.fenggui.theme.css; | ||
|
|
||
| import org.fenggui.theme.css.functions.*; | ||
|
|
||
| import aurelienribon.ui.css.Function; | ||
| import aurelienribon.ui.css.Style; | ||
|
|
||
| public class FengGUIFunctions | ||
| { | ||
| public final static Function rgb = new RgbFunction(); | ||
| public final static Function rgba = new RgbaFunction(); | ||
| public final static Function insets = new InsetsFunction(); | ||
| public final static Function border = new BorderFunction(); | ||
| public final static Function url = new UrlFunction(); | ||
| public final static Function background = new BackgroundFunction(); | ||
| public final static Function font = new FontFunction(); | ||
|
|
||
| public static void registerFunctions() | ||
| { | ||
| Style.registerFunction(rgb); | ||
| Style.registerFunction(rgba); | ||
| Style.registerFunction(insets); | ||
| Style.registerFunction(border); | ||
| Style.registerFunction(url); | ||
| Style.registerFunction(background); | ||
| Style.registerFunction(font); | ||
| } | ||
| } |
| @@ -0,0 +1,106 @@ | ||
| package org.fenggui.theme.css; | ||
|
|
||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.Property; | ||
| import aurelienribon.ui.css.Style; | ||
| import aurelienribon.ui.css.primitives.FunctionProperty; | ||
| import aurelienribon.ui.css.primitives.SingleParamProperty; | ||
|
|
||
| public class FengGUIProperties | ||
| { | ||
| // Widget | ||
| public final static Property visible = new SingleParamProperty( | ||
| "visible", | ||
| Boolean.class, "v"); | ||
| public final static Property width = new SingleParamProperty( | ||
| "width", Integer.class, | ||
| "w"); | ||
| public final static Property height = new SingleParamProperty( | ||
| "height", Integer.class, | ||
| "h"); | ||
| public final static Property minWidth = new SingleParamProperty( | ||
| "minWidth", | ||
| Integer.class, "w"); | ||
| public final static Property minHeight = new SingleParamProperty( | ||
| "minHeight", | ||
| Integer.class, "h"); | ||
|
|
||
| // StandardWidget > SpacingAppearance | ||
| public final static Property padding = new FunctionProperty( | ||
| "padding", | ||
| FengGUIFunctions.insets, | ||
| "insets"); | ||
| public final static Property paddingTop = new SingleParamProperty( | ||
| "padding-top", | ||
| Integer.class, "s"); | ||
| public final static Property paddingRight = new SingleParamProperty( | ||
| "padding-right", | ||
| Integer.class, "s"); | ||
| public final static Property paddingBottom = new SingleParamProperty( | ||
| "padding-bottom", | ||
| Integer.class, "s"); | ||
| public final static Property paddingLeft = new SingleParamProperty( | ||
| "padding-left", | ||
| Integer.class, "s"); | ||
| public final static Property margin = new FunctionProperty("margin", | ||
| FengGUIFunctions.insets, | ||
| "insets"); | ||
| public final static Property marginTop = new SingleParamProperty( | ||
| "margin-top", | ||
| Integer.class, "s"); | ||
| public final static Property marginRight = new SingleParamProperty( | ||
| "margin-right", | ||
| Integer.class, "s"); | ||
| public final static Property marginBottom = new SingleParamProperty( | ||
| "margin-bottom", | ||
| Integer.class, "s"); | ||
| public final static Property marginLeft = new SingleParamProperty( | ||
| "margin-left", | ||
| Integer.class, "s"); | ||
|
|
||
| // StandardWidget > TextAppearance | ||
| public final static Property textAlign = new SingleParamProperty( | ||
| "text-align", | ||
| String.class, "align"); | ||
| public final static Property color = new SingleParamProperty( | ||
| "color", Color.class, | ||
| "color"); | ||
| public final static Property font = new FunctionProperty("font", | ||
| FengGUIFunctions.font, | ||
| "font"); | ||
|
|
||
| // StatefullWidget | ||
| public final static Property background = new FunctionProperty( | ||
| "background", | ||
| FengGUIFunctions.background, | ||
| "background"); | ||
| public final static Property border = new FunctionProperty("border", | ||
| FengGUIFunctions.border, | ||
| "border"); | ||
|
|
||
| public static void registerProperties() | ||
| { | ||
| Style.registerProperty(visible); | ||
| Style.registerProperty(width); | ||
| Style.registerProperty(height); | ||
|
|
||
| Style.registerProperty(padding); | ||
| Style.registerProperty(paddingTop); | ||
| Style.registerProperty(paddingRight); | ||
| Style.registerProperty(paddingBottom); | ||
| Style.registerProperty(paddingLeft); | ||
| Style.registerProperty(margin); | ||
| Style.registerProperty(marginTop); | ||
| Style.registerProperty(marginRight); | ||
| Style.registerProperty(marginBottom); | ||
| Style.registerProperty(marginLeft); | ||
|
|
||
| Style.registerProperty(textAlign); | ||
| Style.registerProperty(color); | ||
| Style.registerProperty(font); | ||
|
|
||
| Style.registerProperty(background); | ||
| Style.registerProperty(border); | ||
| } | ||
| } |
| @@ -0,0 +1,70 @@ | ||
| package org.fenggui.theme.css; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.fenggui.*; | ||
| import org.fenggui.composite.Window; | ||
| import org.fenggui.composite.menu.Menu; | ||
| import org.fenggui.composite.menu.MenuBar; | ||
| import org.fenggui.theme.css.manager.IWidgetDeclarationSetManager; | ||
| import org.fenggui.theme.css.processors.*; | ||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.ChildrenAccessor; | ||
| import aurelienribon.ui.css.ParamConverter; | ||
| import aurelienribon.ui.css.Style; | ||
| import aurelienribon.ui.css.StyleException; | ||
|
|
||
| public class FengGUIStyle | ||
| { | ||
| public static void init() throws StyleException | ||
| { | ||
| // Properties | ||
| FengGUIProperties.registerProperties(); | ||
|
|
||
| // Functions | ||
| FengGUIFunctions.registerFunctions(); | ||
|
|
||
| // Types | ||
| Style.registerType("button", Button.class); | ||
| Style.registerType("window", Window.class); | ||
| Style.registerType("label", Label.class); | ||
| Style.registerType("textfield", TextEditor.class); | ||
| Style.registerType("container", Container.class); | ||
| Style.registerType("menubar", MenuBar.class); | ||
| Style.registerType("menu", Menu.class); | ||
|
|
||
| // Processors | ||
| Style.registerProcessor(Widget.class, new WidgetProcessor()); | ||
| Style.registerProcessor(StandardWidget.class, | ||
| new StandardWidgetProcessor()); | ||
| Style.registerProcessor(StatefullWidget.class, | ||
| new StatefullWidgetProcessor()); | ||
|
|
||
| // Misc. | ||
| Style.registerDeclarationSetManager(IWidget.class, | ||
| new IWidgetDeclarationSetManager()); | ||
| Style.registerChildrenAccessor(IContainer.class, | ||
| new ChildrenAccessor<IContainer>() { | ||
|
|
||
| public List<?> getChildren(IContainer target) | ||
| { | ||
| return target.getContent(); | ||
| } | ||
| }); | ||
| Style.setParamConverter(new ParamConverter() { | ||
|
|
||
| public Class<?> getColorClass() | ||
| { | ||
| return Color.class; | ||
| } | ||
|
|
||
| public Object convertColor(int argb) | ||
| { | ||
| Color color = new Color(argb); | ||
|
|
||
| return color; | ||
| } | ||
| }); | ||
| } | ||
| } |
| @@ -0,0 +1,9 @@ | ||
| package org.fenggui.theme.css; | ||
|
|
||
| import org.fenggui.StatefullWidget; | ||
|
|
||
| public class StyleUtils | ||
| { | ||
| public static boolean applyStates = false; | ||
| public static String state = StatefullWidget.STATE_DEFAULT; | ||
| } |
| @@ -0,0 +1,74 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.io.IOException; | ||
| import java.net.URL; | ||
| import java.util.List; | ||
|
|
||
| import org.fenggui.binding.render.Binding; | ||
| import org.fenggui.binding.render.ITexture; | ||
| import org.fenggui.binding.render.Pixmap; | ||
| import org.fenggui.decorator.background.Background; | ||
| import org.fenggui.decorator.background.PixmapBackground; | ||
| import org.fenggui.decorator.background.PlainBackground; | ||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class BackgroundFunction extends BaseFunction | ||
| { | ||
|
|
||
| public BackgroundFunction() | ||
| { | ||
| super("background"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class<?>[][] { { URL.class }, { Color.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "url" }, { "color" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return Background.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| Background background = new PlainBackground(); | ||
|
|
||
| if (params.size() == 1) | ||
| { | ||
| if (params.get(0) instanceof URL) | ||
| { | ||
| URL url = (URL) params.get(0); | ||
| try | ||
| { | ||
| ITexture tex = Binding.getInstance().getTexture(url); | ||
| Pixmap pixmap = new Pixmap(tex); | ||
| background = new PixmapBackground(pixmap); | ||
| ((PixmapBackground) background).setScaled(true); | ||
| } | ||
| catch (IOException e) | ||
| { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
| else if (params.get(0) instanceof Color) | ||
| { | ||
| Color color = (Color) params.get(0); | ||
| if (background instanceof PlainBackground) | ||
| { | ||
| ((PlainBackground) background).setColor(color); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return background; | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,58 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.fenggui.decorator.border.Border; | ||
| import org.fenggui.decorator.border.PlainBorder; | ||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class BorderFunction extends BaseFunction | ||
| { | ||
|
|
||
| public BorderFunction() | ||
| { | ||
| super("border"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class<?>[][] { { String.class, Integer.class }, | ||
| { String.class, Integer.class, Color.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "type", "lineWidth" }, | ||
| { "type", "lineWidth", "color" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return Border.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| Border border = null; | ||
|
|
||
| String type = (String) params.get(0); | ||
|
|
||
| if (type.equals("plain")) | ||
| { | ||
| int size = (Integer) params.get(1); | ||
| if (params.size() > 2) | ||
| { | ||
| Color c = (Color) params.get(2); | ||
| border = new PlainBorder(c, size); | ||
| } | ||
| else | ||
| { | ||
| border = new PlainBorder(size); | ||
| } | ||
| } | ||
|
|
||
| return border; | ||
| } | ||
| } |
| @@ -0,0 +1,96 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.awt.Font; | ||
| import java.util.List; | ||
|
|
||
| import org.fenggui.binding.render.IFont; | ||
| import org.fenggui.util.fonttoolkit.FontFactory; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class FontFunction extends BaseFunction | ||
| { | ||
|
|
||
| public FontFunction() | ||
| { | ||
| super("font"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class<?>[][] { { String.class }, | ||
| { String.class, String.class }, | ||
| { String.class, Integer.class }, | ||
| { String.class, String.class, Integer.class }, | ||
| { String.class, Integer.class, String.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "name" }, { "name", "weight" }, | ||
| { "name", "size" }, { "name", "weight", "size" }, | ||
| { "name", "size", "weight" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return IFont.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| IFont font = null; | ||
|
|
||
| String name = (String) params.get(0); | ||
|
|
||
| int style = Font.PLAIN; | ||
| int size = 12; | ||
|
|
||
| if (params.size() == 2) | ||
| { | ||
| if (params.get(1) instanceof String) | ||
| { | ||
| style = getStyle((String) params.get(1)); | ||
| } | ||
| else | ||
| { | ||
| size = (Integer) params.get(1); | ||
| } | ||
| } | ||
| else if (params.size() == 3) | ||
| { | ||
| if (params.get(1) instanceof String) | ||
| { | ||
| style = getStyle((String) params.get(1)); | ||
| size = (Integer) params.get(2); | ||
| } | ||
| else | ||
| { | ||
| style = getStyle((String) params.get(2)); | ||
| size = (Integer) params.get(1); | ||
| } | ||
| } | ||
|
|
||
| Font awtFont = new Font(name, style, size); | ||
| font = FontFactory.renderStandardFont(awtFont); | ||
|
|
||
| return font; | ||
| } | ||
|
|
||
| private int getStyle(String str) | ||
| { | ||
| int style = Font.PLAIN; | ||
|
|
||
| if (str.contains("bold")) | ||
| { | ||
| style = Font.BOLD | style; | ||
| } | ||
| if (str.contains("italic")) | ||
| { | ||
| style = Font.ITALIC | style; | ||
| } | ||
|
|
||
| return style; | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,62 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.fenggui.util.Spacing; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class InsetsFunction extends BaseFunction | ||
| { | ||
|
|
||
| public InsetsFunction() | ||
| { | ||
| super("insets"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class[][] { | ||
| { Integer.class, Integer.class, Integer.class, Integer.class }, | ||
| { Integer.class, Integer.class }, { Integer.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "top", "right", "bottom", "left" }, | ||
| { "topBottom", "leftRight" }, { "thickness" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return Spacing.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| int top = 0; | ||
| int bottom = 0; | ||
| int left = 0; | ||
| int right = 0; | ||
|
|
||
| if (params.size() == 1) | ||
| { | ||
| top = bottom = left = right = (Integer) params.get(0); | ||
| } | ||
| else if (params.size() == 2) | ||
| { | ||
| top = bottom = (Integer) params.get(0); | ||
| right = left = (Integer) params.get(1); | ||
| } | ||
| else if (params.size() == 4) | ||
| { | ||
| top = (Integer) params.get(0); | ||
| right = (Integer) params.get(1); | ||
| bottom = (Integer) params.get(2); | ||
| left = (Integer) params.get(3); | ||
| } | ||
|
|
||
| return new Spacing(top, left, right, bottom); | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,40 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class RgbFunction extends BaseFunction | ||
| { | ||
|
|
||
| public RgbFunction() | ||
| { | ||
| super("rgb"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class<?>[][] { { Integer.class, Integer.class, Integer.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "r", "g", "b" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return Color.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| int r = (Integer) params.get(0); | ||
| int g = (Integer) params.get(1); | ||
| int b = (Integer) params.get(2); | ||
| return new Color(r, g, b); | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,42 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class RgbaFunction extends BaseFunction | ||
| { | ||
|
|
||
| public RgbaFunction() | ||
| { | ||
| super("rgba"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class<?>[][] { { Integer.class, Integer.class, | ||
| Integer.class, Integer.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "r", "g", "b", "a" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return Color.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| int r = (Integer) params.get(0); | ||
| int g = (Integer) params.get(1); | ||
| int b = (Integer) params.get(2); | ||
| int a = (Integer) params.get(3); | ||
| return new Color(r, g, b, a); | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,37 @@ | ||
| package org.fenggui.theme.css.functions; | ||
|
|
||
| import java.net.URL; | ||
| import java.util.List; | ||
|
|
||
| import aurelienribon.ui.css.primitives.BaseFunction; | ||
|
|
||
| public class UrlFunction extends BaseFunction | ||
| { | ||
| public UrlFunction() | ||
| { | ||
| super("url"); | ||
| } | ||
|
|
||
| public Class<?>[][] getParams() | ||
| { | ||
| return new Class<?>[][] { { String.class } }; | ||
| } | ||
|
|
||
| public String[][] getParamsNames() | ||
| { | ||
| return new String[][] { { "url" } }; | ||
| } | ||
|
|
||
| public Class<?> getReturn() | ||
| { | ||
| return URL.class; | ||
| } | ||
|
|
||
| public Object process(List<Object> params) | ||
| { | ||
| String url = (String) params.get(0); | ||
| URL url2 = UrlFunction.class.getResource(url); | ||
| return url2; | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,209 @@ | ||
| package org.fenggui.theme.css.manager; | ||
|
|
||
| import java.util.LinkedHashMap; | ||
| import java.util.Map; | ||
|
|
||
| import org.fenggui.IWidget; | ||
| import org.fenggui.StatefullWidget; | ||
| import org.fenggui.appearance.DecoratorAppearance; | ||
| import org.fenggui.event.ActivationEvent; | ||
| import org.fenggui.event.FocusEvent; | ||
| import org.fenggui.event.IActivationListener; | ||
| import org.fenggui.event.IFocusListener; | ||
| import org.fenggui.event.mouse.MouseAdapter; | ||
| import org.fenggui.event.mouse.MouseEnteredEvent; | ||
| import org.fenggui.event.mouse.MouseExitedEvent; | ||
| import org.fenggui.event.mouse.MousePressedEvent; | ||
| import org.fenggui.event.mouse.MouseReleasedEvent; | ||
| import org.fenggui.theme.css.StyleUtils; | ||
|
|
||
| import aurelienribon.ui.css.DeclarationSet; | ||
| import aurelienribon.ui.css.DeclarationSetManager; | ||
| import aurelienribon.ui.css.Style; | ||
|
|
||
| public class IWidgetDeclarationSetManager implements | ||
| DeclarationSetManager<IWidget> | ||
| { | ||
| public void manage(IWidget target, Map<String, DeclarationSet> dss) | ||
| { | ||
| if (dss.isEmpty()) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| TargetManager.applyStates(target, dss); | ||
|
|
||
| if (target instanceof StatefullWidget) | ||
| { | ||
| TargetManager.manage(target, dss); | ||
| } | ||
| else | ||
| { | ||
| Style.apply(target, dss.get("")); | ||
| } | ||
| } | ||
|
|
||
| private static class TargetManager extends MouseAdapter implements | ||
| IFocusListener, IActivationListener | ||
| { | ||
| private final StatefullWidget<? extends DecoratorAppearance> target; | ||
| private final Map<String, DeclarationSet> dss; | ||
| private final Map<String, Boolean> states; | ||
|
|
||
| public TargetManager( | ||
| StatefullWidget<? extends DecoratorAppearance> target, | ||
| Map<String, DeclarationSet> dss) | ||
| { | ||
| this.target = target; | ||
| this.dss = dss; | ||
| states = new LinkedHashMap<String, Boolean>(dss.size()); | ||
|
|
||
| boolean moused = false; | ||
| for (String pseudoClass : dss.keySet()) | ||
| { | ||
| if (!pseudoClass.equals(":disabled")) | ||
| { | ||
| states.put(pseudoClass, false); | ||
| } | ||
| if (pseudoClass.equals(":focus")) | ||
| { | ||
| states.put(pseudoClass, target.hasFocus()); | ||
| } | ||
| if ((pseudoClass.equals(":hover") || pseudoClass | ||
| .equals(":active")) && !moused) | ||
| { | ||
| moused = true; | ||
| target.addMouseListener(this); | ||
| } | ||
| else if (pseudoClass.equals(":focus")) | ||
| { | ||
| target.addFocusListener(this); | ||
| } | ||
| else if (pseudoClass.equals(":disabled")) | ||
| { | ||
| target.addActivationListener(this); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public void apply() | ||
| { | ||
| if (dss.containsKey("")) | ||
| { | ||
| Style.apply(target, dss.get("")); | ||
| } | ||
|
|
||
| if (target.isEnabled()) | ||
| { | ||
| for (String pseudoClass : states.keySet()) | ||
| { | ||
| if (states.get(pseudoClass) == true | ||
| && dss.containsKey(pseudoClass)) | ||
| { | ||
| Style.apply(target, dss.get(pseudoClass)); | ||
| } | ||
| } | ||
| } | ||
| else if (dss.containsKey(":disabled")) | ||
| { | ||
| Style.apply(target, dss.get(":disabled")); | ||
| } | ||
| } | ||
|
|
||
| public void focusChanged(FocusEvent e) | ||
| { | ||
| if (e.isFocusGained()) | ||
| { | ||
| states.put(":focus", true); | ||
| } | ||
| else | ||
| { | ||
| states.put(":focus", false); | ||
| } | ||
| apply(); | ||
| } | ||
|
|
||
| public void widgetActivationChanged(ActivationEvent e) | ||
| { | ||
| if (e.isEnabled()) | ||
| { | ||
| states.put(":disabled", false); | ||
| } | ||
| else | ||
| { | ||
| states.put(":disabled", true); | ||
| } | ||
| apply(); | ||
| } | ||
|
|
||
| @Override | ||
| public void mouseEntered(MouseEnteredEvent e) | ||
| { | ||
| states.put(":hover", true); | ||
| apply(); | ||
| } | ||
|
|
||
| @Override | ||
| public void mouseExited(MouseExitedEvent e) | ||
| { | ||
| states.put(":hover", false); | ||
| apply(); | ||
| } | ||
|
|
||
| @Override | ||
| public void mousePressed(MousePressedEvent e) | ||
| { | ||
| states.put(":active", true); | ||
| apply(); | ||
| } | ||
|
|
||
| @Override | ||
| public void mouseReleased(MouseReleasedEvent e) | ||
| { | ||
| states.put(":active", false); | ||
| apply(); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| public static void manage(IWidget target, | ||
| Map<String, DeclarationSet> dss) | ||
| { | ||
| TargetManager tm = new TargetManager( | ||
| (StatefullWidget<? extends DecoratorAppearance>) target, | ||
| dss); | ||
| tm.apply(); | ||
| } | ||
|
|
||
| public static void applyStates(IWidget target, | ||
| Map<String, DeclarationSet> dss) | ||
| { | ||
| StyleUtils.applyStates = true; | ||
| if (dss.containsKey("")) | ||
| { | ||
| StyleUtils.state = StatefullWidget.STATE_DEFAULT; | ||
| Style.apply(target, dss.get("")); | ||
| } | ||
| if (dss.containsKey(":hover")) | ||
| { | ||
| StyleUtils.state = StatefullWidget.STATE_HOVERED; | ||
| Style.apply(target, dss.get(":hover")); | ||
| } | ||
| if (dss.containsKey(":focus")) | ||
| { | ||
| StyleUtils.state = StatefullWidget.STATE_FOCUSED; | ||
| Style.apply(target, dss.get(":focus")); | ||
| } | ||
| if (dss.containsKey(":active")) | ||
| { | ||
| StyleUtils.state = StatefullWidget.STATE_ACTIVE; | ||
| Style.apply(target, dss.get(":active")); | ||
| } | ||
| if (dss.containsKey(":disabled")) | ||
| { | ||
| StyleUtils.state = StatefullWidget.STATE_DISABLED; | ||
| Style.apply(target, dss.get(":disabled")); | ||
| } | ||
| StyleUtils.applyStates = false; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,167 @@ | ||
| package org.fenggui.theme.css.processors; | ||
|
|
||
| import org.fenggui.StandardWidget; | ||
| import org.fenggui.appearance.DecoratorAppearance; | ||
| import org.fenggui.appearance.SpacingAppearance; | ||
| import org.fenggui.appearance.TextAppearance; | ||
| import org.fenggui.binding.render.IFont; | ||
| import org.fenggui.binding.render.text.DirectTextRenderer; | ||
| import org.fenggui.binding.render.text.ITextRenderer; | ||
| import org.fenggui.text.content.factory.simple.TextStyle; | ||
| import org.fenggui.text.content.factory.simple.TextStyleEntry; | ||
| import org.fenggui.theme.css.FengGUIFunctions; | ||
| import org.fenggui.theme.css.FengGUIProperties; | ||
| import org.fenggui.theme.css.StyleUtils; | ||
| import org.fenggui.util.Alignment; | ||
| import org.fenggui.util.Color; | ||
| import org.fenggui.util.Spacing; | ||
|
|
||
| import aurelienribon.ui.css.DeclarationSet; | ||
| import aurelienribon.ui.css.DeclarationSetProcessor; | ||
|
|
||
| public class StandardWidgetProcessor implements | ||
| DeclarationSetProcessor<StandardWidget> | ||
| { | ||
| public void process(StandardWidget t, DeclarationSet ds) | ||
| { | ||
| if (t.getAppearance() instanceof SpacingAppearance) | ||
| { | ||
| SpacingAppearance appearance = (SpacingAppearance) t | ||
| .getAppearance(); | ||
|
|
||
| // Padding | ||
| if (ds.contains(FengGUIProperties.padding) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| Spacing padding = ds.getValue(FengGUIProperties.padding, | ||
| Spacing.class, FengGUIFunctions.insets); | ||
| appearance.setPadding(padding); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.paddingTop) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.paddingTop, | ||
| Integer.class); | ||
| appearance.getPadding().setTop(value); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.paddingRight) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.paddingRight, | ||
| Integer.class); | ||
| appearance.getPadding().setRight(value); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.paddingBottom) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.paddingBottom, | ||
| Integer.class); | ||
| appearance.getPadding().setBottom(value); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.paddingLeft) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.paddingLeft, | ||
| Integer.class); | ||
| appearance.getPadding().setLeft(value); | ||
| } | ||
|
|
||
| // Margin | ||
| if (ds.contains(FengGUIProperties.margin) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| Spacing margin = ds.getValue(FengGUIProperties.margin, | ||
| Spacing.class, FengGUIFunctions.insets); | ||
| appearance.setMargin(margin); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.marginTop) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.marginTop, | ||
| Integer.class); | ||
| appearance.getMargin().setTop(value); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.marginRight) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.marginRight, | ||
| Integer.class); | ||
| appearance.getMargin().setRight(value); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.marginBottom) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.marginBottom, | ||
| Integer.class); | ||
| appearance.getMargin().setBottom(value); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.marginLeft) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| int value = ds.getValue(FengGUIProperties.marginLeft, | ||
| Integer.class); | ||
| appearance.getMargin().setLeft(value); | ||
| } | ||
| } | ||
|
|
||
| if (t.getAppearance() instanceof TextAppearance) | ||
| { | ||
| TextAppearance appearance = (TextAppearance) t.getAppearance(); | ||
|
|
||
| if (ds.contains(FengGUIProperties.textAlign) | ||
| && !StyleUtils.applyStates) | ||
| { | ||
| String textAlign = ds.getValue(FengGUIProperties.textAlign, | ||
| String.class); | ||
| if (textAlign.equals("left")) | ||
| { | ||
| appearance.setAlignment(Alignment.LEFT); | ||
| } | ||
| else if (textAlign.equals("center")) | ||
| { | ||
| appearance.setAlignment(Alignment.MIDDLE); | ||
| } | ||
| else if (textAlign.equals("right")) | ||
| { | ||
| appearance.setAlignment(Alignment.RIGHT); | ||
| } | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.color) && !StyleUtils.applyStates) | ||
| { | ||
| Color color = ds.getValue(FengGUIProperties.color, Color.class); | ||
| appearance.getStyle(TextStyle.DEFAULTSTYLEKEY) | ||
| .getTextStyleEntry(TextStyleEntry.DEFAULTSTYLESTATEKEY) | ||
| .setColor(color); | ||
| } | ||
|
|
||
| ITextRenderer textRenderer = appearance | ||
| .getRenderer(ITextRenderer.DEFAULTTEXTRENDERERKEY); | ||
| IFont font = textRenderer.getFont(); | ||
|
|
||
| if (ds.contains(FengGUIProperties.font) && !StyleUtils.applyStates) | ||
| { | ||
| font = ds.getValue(FengGUIProperties.font, IFont.class, | ||
| FengGUIFunctions.font); | ||
| } | ||
|
|
||
| textRenderer = new DirectTextRenderer(); | ||
| textRenderer.setFont(font); | ||
| appearance.addRenderer(ITextRenderer.DEFAULTTEXTRENDERERKEY, | ||
| textRenderer); | ||
| } | ||
|
|
||
| if (t.getAppearance() instanceof DecoratorAppearance) | ||
| { | ||
| StatefullWidgetProcessor.processWidget(t, ds); | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,56 @@ | ||
| package org.fenggui.theme.css.processors; | ||
|
|
||
| import org.fenggui.StandardWidget; | ||
| import org.fenggui.StatefullWidget; | ||
| import org.fenggui.appearance.DecoratorAppearance; | ||
| import org.fenggui.decorator.background.Background; | ||
| import org.fenggui.decorator.background.PlainBackground; | ||
| import org.fenggui.decorator.border.Border; | ||
| import org.fenggui.theme.css.FengGUIFunctions; | ||
| import org.fenggui.theme.css.FengGUIProperties; | ||
| import org.fenggui.theme.css.StyleUtils; | ||
| import org.fenggui.util.Color; | ||
|
|
||
| import aurelienribon.ui.css.DeclarationSet; | ||
| import aurelienribon.ui.css.DeclarationSetProcessor; | ||
|
|
||
| public class StatefullWidgetProcessor implements | ||
| DeclarationSetProcessor<StatefullWidget<? extends DecoratorAppearance>> | ||
| { | ||
| public void process(StatefullWidget<? extends DecoratorAppearance> t, | ||
| DeclarationSet ds) | ||
| { | ||
| processWidget(t, ds); | ||
| } | ||
|
|
||
| public static void processWidget(StandardWidget t, DeclarationSet ds) | ||
| { | ||
| if (t.getAppearance() instanceof DecoratorAppearance) | ||
| { | ||
| DecoratorAppearance appearance = (DecoratorAppearance) t | ||
| .getAppearance(); | ||
|
|
||
| if (ds.contains(FengGUIProperties.background) | ||
| && StyleUtils.applyStates) | ||
| { | ||
| Background background = ds.getValue( | ||
| FengGUIProperties.background, Background.class, | ||
| FengGUIFunctions.background); | ||
| appearance.add(StyleUtils.state, background); | ||
| } | ||
|
|
||
| if (ds.contains(FengGUIProperties.border) && StyleUtils.applyStates) | ||
| { | ||
| Border border = ds.getValue(FengGUIProperties.border, | ||
| Border.class, FengGUIFunctions.border); | ||
| appearance.add(StyleUtils.state, border); | ||
| } | ||
|
|
||
| if (!StyleUtils.state.equals(StatefullWidget.STATE_DEFAULT) | ||
| && StyleUtils.applyStates) | ||
| { | ||
| appearance.setEnabled(StyleUtils.state, false); | ||
| } | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,52 @@ | ||
| package org.fenggui.theme.css.processors; | ||
|
|
||
| import org.fenggui.Widget; | ||
| import org.fenggui.theme.css.FengGUIProperties; | ||
| import org.fenggui.theme.css.StyleUtils; | ||
|
|
||
| import aurelienribon.ui.css.DeclarationSet; | ||
| import aurelienribon.ui.css.DeclarationSetProcessor; | ||
|
|
||
| public class WidgetProcessor implements DeclarationSetProcessor<Widget> | ||
| { | ||
| public void process(Widget t, DeclarationSet ds) | ||
| { | ||
| // Visible | ||
| if (ds.contains(FengGUIProperties.visible) && !StyleUtils.applyStates) | ||
| { | ||
| boolean visible = ds.getValue(FengGUIProperties.visible, | ||
| Boolean.class); | ||
| t.setVisible(visible); | ||
| } | ||
|
|
||
| // Width | ||
| if (ds.contains(FengGUIProperties.width) && !StyleUtils.applyStates) | ||
| { | ||
| int width = ds.getValue(FengGUIProperties.width, Integer.class); | ||
| t.setWidth(width); | ||
| } | ||
|
|
||
| // Height | ||
| if (ds.contains(FengGUIProperties.height) && !StyleUtils.applyStates) | ||
| { | ||
| int height = ds.getValue(FengGUIProperties.height, Integer.class); | ||
| t.setHeight(height); | ||
| } | ||
|
|
||
| // Minimum Width | ||
| if (ds.contains(FengGUIProperties.minWidth) && !StyleUtils.applyStates) | ||
| { | ||
| int minWidth = ds.getValue(FengGUIProperties.minWidth, | ||
| Integer.class); | ||
| t.setMinWidth(minWidth); | ||
| } | ||
|
|
||
| // Minimum Height | ||
| if (ds.contains(FengGUIProperties.minHeight) && !StyleUtils.applyStates) | ||
| { | ||
| int minHeight = ds.getValue(FengGUIProperties.minHeight, | ||
| Integer.class); | ||
| t.setMinHeight(minHeight); | ||
| } | ||
| } | ||
| } |