Large diffs are not rendered by default.

@@ -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;
}
}
}

Large diffs are not rendered by default.

@@ -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);
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -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 } };
}
}
@@ -233,6 +233,7 @@ public void process(InputOutputStream stream) throws IOException,
* @see org.fenggui.ObservableLabelWidget#clone()
*/

@SuppressWarnings("unchecked")
@Override
public CheckBox<E> clone()
{
@@ -434,6 +434,7 @@ public void removedFromWidgetTree()
@Override
public void addedToWidgetTree()
{
super.addedToWidgetTree();
synchronized (notifyList)
{
for (final IWidget w : notifyList)
@@ -1064,4 +1065,9 @@ public Container clone()

return result;
}

public Object[] getChildren()
{
return getContent().toArray();
}
}
@@ -105,6 +105,17 @@ public static void removePrototypes()
}
}

public static <T extends IWidget> T createWidget(Class<T> widgetClass)
{
return createWidget(widgetClass, null);
}

public static <T extends IWidget> T createWidget(Class<T> widgetClass,
String id)
{
return createWidget(widgetClass, id, null);
}

/**
* Created a themed instance of a Widget. This is the preferred way to
* create widgets. It handles a cache of prototype widgets to improve speed.
@@ -114,10 +125,15 @@ public static void removePrototypes()
* @param <T>
* @param widgetClass
* The class of the Widget to create a instance from.
* @param id
* The widget ID
* @param styleClass
* The widget style class
* @return a themed instance of a widget.
*/
@SuppressWarnings("unchecked")
public static <T extends IWidget> T createWidget(Class<T> widgetClass)
public static <T extends IWidget> T createWidget(Class<T> widgetClass,
String id, String styleClass)
{
T widget = null;
final boolean cloneableClass = Cloneable.class
@@ -137,6 +153,8 @@ public static <T extends IWidget> T createWidget(Class<T> widgetClass)
}

widget = Util.createInstanceOfClass(widgetClass);
widget.setId(id);
widget.setStyleClass(styleClass);
FengGUI.setUpAppearance(widget);

if (cloneableClass)
@@ -503,7 +521,7 @@ public static Label createLabel()
{
if (ptLabel == null)
{
ptLabel = new Label();
ptLabel = createWidget(Label.class);
FengGUI.setUpAppearance(ptLabel);
}
final Label l = new Label(ptLabel);
@@ -19,13 +19,15 @@
*/
package org.fenggui;

import aurelienribon.ui.css.Container;

/**
* A Container is a set of Widgets. The layout manager that is assigned to the
* Container is responsible for the size and position of its content. In terms
* of the tree data structure, a container is a node with an arbitrary number of
* child nodes.
*/
public interface IContainer extends IBasicContainer
public interface IContainer extends IBasicContainer, Container
{

/**
@@ -21,13 +21,16 @@

import org.fenggui.binding.render.Graphics;
import org.fenggui.event.FocusEvent;
import org.fenggui.event.IFocusListener;
import org.fenggui.event.IPositionChangedListener;
import org.fenggui.event.ISizeChangedListener;
import org.fenggui.event.PositionChangedEvent;
import org.fenggui.event.SizeChangedEvent;
import org.fenggui.event.key.IKeyListener;
import org.fenggui.event.key.KeyPressedEvent;
import org.fenggui.event.key.KeyReleasedEvent;
import org.fenggui.event.key.KeyTypedEvent;
import org.fenggui.event.mouse.IMouseListener;
import org.fenggui.event.mouse.MouseClickedEvent;
import org.fenggui.event.mouse.MouseDoubleClickedEvent;
import org.fenggui.event.mouse.MouseDraggedEvent;
@@ -72,6 +75,8 @@ public interface IWidget extends IXMLStreamable
*/
public IBasicContainer getParent();

public boolean hasFocus();

/**
* The <code>clone</code> method creates a shallow copy of the Widget. The
* returned Widget will be independent of the current cloned Widget. Usually
@@ -516,4 +521,34 @@ public interface IWidget extends IXMLStreamable
* @see org.fenggui.util.Util
*/
public Object getData(String key);

/**
* Return the style ID which identify the widget.
*
* @return the widget style ID.
*/
public String getId();

/**
* Set the style ID which identify the widget.
*
* @param id
* The widget style ID.
*/
public void setId(String id);

/**
* Return the style class which determine how to represent the widget.
*
* @return the widget style class.
*/
public String getStyleClass();

/**
* Set the style class which determine how to represent the widget
*
* @param styleClass
* the widget style class
*/
public void setStyleClass(String styleClass);
}
@@ -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();
}

}
@@ -45,6 +45,7 @@
public static final String STATE_HOVERED = "hovered";
public static final String STATE_DISABLED = "disabled";
public static final String STATE_ERROR = "error";
public static final String STATE_ACTIVE = "pressed";

private T appearance = null;
private boolean hovered = false;
@@ -358,8 +358,8 @@ else if (e.getKey() == 'V')
}
else
{
final boolean result = textData.handleKeyPresses(e.getKeyClass(),
e.getModifiers(), getAppearance());
final boolean result = textData.handleKeyPresses(
e.getKeyClass(), e.getModifiers(), getAppearance());
return result;
}
default:
@@ -26,18 +26,22 @@

import org.fenggui.binding.render.Graphics;
import org.fenggui.event.FocusEvent;
import org.fenggui.event.IFocusListener;
import org.fenggui.event.IPositionChangedListener;
import org.fenggui.event.ISizeChangedListener;
import org.fenggui.event.PositionChangedEvent;
import org.fenggui.event.SizeChangedEvent;
import org.fenggui.event.key.IKeyListener;
import org.fenggui.event.key.KeyPressedEvent;
import org.fenggui.event.key.KeyReleasedEvent;
import org.fenggui.event.key.KeyTypedEvent;
import org.fenggui.event.mouse.IMouseListener;
import org.fenggui.event.mouse.MouseClickedEvent;
import org.fenggui.event.mouse.MouseDoubleClickedEvent;
import org.fenggui.event.mouse.MouseDraggedEvent;
import org.fenggui.event.mouse.MouseEnteredEvent;
import org.fenggui.event.mouse.MouseExitedEvent;
import org.fenggui.event.mouse.MouseMovedEvent;
import org.fenggui.event.mouse.MousePressedEvent;
import org.fenggui.event.mouse.MouseReleasedEvent;
import org.fenggui.event.mouse.MouseWheelEvent;
@@ -49,6 +53,8 @@
import org.fenggui.util.Log;
import org.fenggui.util.Point;

import aurelienribon.ui.css.Style;

/**
* Implementation of a widget. A widget is the most basic unit of a GUI system. <br/>
* The background spans over the content, padding and border, but not over the
@@ -69,6 +75,8 @@
*/
public class Widget implements IWidget
{
private String id = null;
private String styleClass = null;

private Dimension size;
private Dimension minSize;
@@ -503,7 +511,7 @@ public void removedFromWidgetTree()

public void addedToWidgetTree()
{
// does nothing. Supposed to be overridden

}

/*
@@ -682,7 +690,7 @@ public String toString()

public void focusChanged(FocusEvent focusEvent)
{
// does nothing. Supposed to be overridden

}

/**
@@ -888,6 +896,16 @@ public void setMinSize(int minWidth, int minHeight)
this.setMinSize(new Dimension(minWidth, minHeight));
}

public void setMinWidth(int minWidth)
{
this.setMinSize(new Dimension(minWidth, minSize.getHeight()));
}

public void setMinHeight(int minHeight)
{
this.setMinSize(new Dimension(minSize.getWidth(), minHeight));
}

/**
* Sets the size of this widget.
*
@@ -1122,4 +1140,31 @@ public Widget clone()

return result;
}

public String getId()
{
return id;
}

public void setId(String id)
{
this.id = id;
Style.registerCssClasses(this, "#" + id);
}

public String getStyleClass()
{
return styleClass;
}

public void setStyleClass(String styleClass)
{
this.styleClass = styleClass;
Style.registerCssClasses(this, "." + styleClass);
}

public void applyTheme()
{
FengGUI.getTheme().setUp(this);
}
}
@@ -111,7 +111,7 @@ public void add(IDecorator decorator)

public void add(Background background)
{
add("default", background, Span.PADDING);
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)
@@ -308,7 +308,7 @@ public Point getTranslation()

public void setFont(Font awtFont)
{
ImageFont font = FontFactory.renderStandardFont(awtFont);
final ImageFont font = FontFactory.renderStandardFont(awtFont);

setFont(font);
}
@@ -1052,8 +1052,8 @@ public void drawFilledCircle(int x, int y, double radius, Color color)
gl.vertex(x, y);
gl.vertex((int) (Math.cos(d) * radius + x + 0.5),
(int) (Math.sin(d) * radius + y + 0.5));
gl.vertex((int) (Math.cos(d + (TWO_PI / STEPS)) * radius + x + 0.5),
(int) (Math.sin(d + (TWO_PI / STEPS)) * radius + y + 0.5));
gl.vertex((int) (Math.cos(d + TWO_PI / STEPS) * radius + x + 0.5),
(int) (Math.sin(d + TWO_PI / STEPS) * radius + y + 0.5));
}

gl.end();
@@ -109,9 +109,9 @@ public void update()

while (Keyboard.next())
{
int code = Keyboard.getEventKey();
char c = EventHelper.mapKeyChar();
Key key = EventHelper.mapEventKey();
final int code = Keyboard.getEventKey();
final char c = EventHelper.mapKeyChar();
final Key key = EventHelper.mapEventKey();

System.out.println("Key '" + code + "' - State: "
+ (Keyboard.getEventKeyState() ? "pressed" : "released"));
@@ -123,11 +123,11 @@ public void update()

if (!keyStates.containsKey(code))
{
State state = new State(Keyboard.getEventKeyState());
final State state = new State(Keyboard.getEventKeyState());
keyStates.put(code, state);
}

State state = keyStates.get(code);
final State state = keyStates.get(code);
final long current = System.currentTimeMillis();
final long diff = current - state.getLastPressed();

@@ -156,12 +156,12 @@ public void update()
}
}

for (int code : keyStates.keySet())
for (final int code : keyStates.keySet())
{
if (Keyboard.isKeyDown(code))
{
char c = keyChars.get(code);
Key key = EventHelper.mapEventKey(code);
final char c = keyChars.get(code);
final Key key = EventHelper.mapEventKey(code);

display.fireKeyPressedEvent(c, key);
}
@@ -282,7 +282,7 @@ public int getID()
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
final StringBuilder builder = new StringBuilder();
builder.append("LWJGLTexture [textureID=");
builder.append(textureID);
builder.append(", imgHeight=");
@@ -182,11 +182,13 @@ protected void build(boolean closeBtn, boolean maximizeBtn,
boolean minimizeBtn)
{
titleBar = new Container();
titleBar.setStyleClass("title-bar");
this.addWidget(titleBar);

setLayoutManager(new BorderLayout());

content = new Container();
content.setStyleClass("content");
((Container) content).setLayoutData(BorderLayoutData.CENTER);
((Container) content).setKeyTraversalRoot(true);
this.addWidget(content);
@@ -239,6 +241,9 @@ protected void buildTitleBar(boolean closeBtn, boolean maximizeBtn,
protected void buildMinimizeButton()
{
minimizeButton = new Button("_");
minimizeButton.setStyleClass("window-minimize");
minimizeButton.setExpandable(false);
minimizeButton.setShrinkable(false);
titleBar.addWidget(minimizeButton);
minimizeButton.addButtonPressedListener(new IButtonPressedListener() {

@@ -256,7 +261,10 @@ public void buttonPressed(ButtonPressedEvent e)
*/
protected void buildMaximizeButton()
{
maximizeButton = new Button();
maximizeButton = new Button(" ");
maximizeButton.setStyleClass("window-maximize");
maximizeButton.setExpandable(false);
maximizeButton.setShrinkable(false);
titleBar.addWidget(maximizeButton);
maximizeButton.addButtonPressedListener(new IButtonPressedListener() {

@@ -273,9 +281,11 @@ public void buttonPressed(ButtonPressedEvent e)
*/
protected void buildCloseButton()
{
closeButton = new Button();
closeButton = new Button("X");
closeButton.setStyleClass("window-close");
closeButton.setExpandable(false);
closeButton.setShrinkable(false);
titleBar.addWidget(closeButton);
closeButton.setText("X");
closeButton.addButtonPressedListener(new IButtonPressedListener() {

public void buttonPressed(ButtonPressedEvent e)
@@ -68,6 +68,11 @@ public PlainBorder()
setSpacing(1, 1, 1, 1);
}

public PlainBorder(int lineWidth)
{
setSpacing(lineWidth, lineWidth, lineWidth, lineWidth);
}

public PlainBorder(InputOnlyStream stream) throws IOException,
IXMLStreamableException
{
@@ -468,11 +468,19 @@ public void setUp(ProgressBar l)
@Override
public void setUp(Container w)
{
for (IWidget child : w.getContent())
{
setUp(child);
}
}

@Override
public void setUpUnknown(IWidget w)
{
if (w instanceof Container)
{
setUp((Container) w);
}
}

@Override
@@ -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);
}
}
}
@@ -286,17 +286,21 @@ public Color(float red, float green, float blue, float alpha)
*/
public Color(Color value)
{
red = value.red;
green = value.green;
blue = value.blue;
red = value.getRed();
green = value.getGreen();
blue = value.getBlue();
}

public Color(int argb)
{
this((argb >> 16) & 0xFF, (argb >> 8) & 0xFF, (argb >> 0) & 0xFF,
(argb >> 24) & 0xFF);
}

public Color(java.awt.Color awtColor)
{
red = awtColor.getRed();
green = awtColor.getGreen();
blue = awtColor.getBlue();
alpha = awtColor.getAlpha();
this(awtColor.getRed(), awtColor.getGreen(), awtColor.getBlue(),
awtColor.getAlpha());
}

/**
@@ -185,7 +185,7 @@ public int getBottomPlusTop()
* @param bottom
* The spacing to the bottom.
*/
protected void setSpacing(int top, int left, int right, int bottom)
public void setSpacing(int top, int left, int right, int bottom)
{
this.top = top;
this.left = left;
@@ -208,20 +208,40 @@ protected void setSpacing(int top, int left, int right, int bottom)
*
*
*/
protected void setSpacing(int topbottom, int leftright)
public void setSpacing(int topbottom, int leftright)
{
left = right = leftright;
bottom = top = topbottom;
}

protected void setSpacing(Spacing s)
public void setSpacing(Spacing s)
{
left = s.left;
right = s.right;
top = s.top;
bottom = s.bottom;
}

public void setTop(int top)
{
this.top = top;
}

public void setLeft(int left)
{
this.left = left;
}

public void setRight(int right)
{
this.right = right;
}

public void setBottom(int bottom)
{
this.bottom = bottom;
}

public static final Spacing ZERO_SPACING = new Spacing(0, 0, 0, 0);

@Override