📄 fxobjectstylesupport.java
字号:
* If the given object is a Group, then each of the child nodes will be
* styleable. If it is a Container, then each of the child components will
* be wrapped in styleables.
*
* @param object
* @return
*/
public Styleable[] getStyleableChildren(Object object) {
if (isGroup || isContainer || isCanvas) {
Attribute attr = getAttribute("content");
Object var = attr.getProperty(object);
if (var instanceof Sequence) {
Sequence content = (Sequence)var;
Styleable[] styleables = new Styleable[content.size()];
for (int i = 0; i < content.size(); i++) {
Object node = content.get(i);
styleables[i] = TypeManager.getStyleable(node);
}
return styleables;
} else {
return var == null ? null : new Styleable[]{TypeManager.getStyleable(var)};
}
}
return null;
}
/**
* This method cannot be properly implemented at this time, at least until
* I understand how to get this information at runtime from the JavaFX classes
* via Java based reflection. I don't see how this is currently possible.
*
* For the time being, I just have a switch statement for returning the
* types of known attributes.
*
* @param object
* @param propertyName
* @return
*/
public Class getPropertyType(Object object, String propertyName) {
return getAttribute(propertyName).getPropertyType(object);
}
/**
* Gets the value for an attribute (property) with the given name. If the
* class is a Control, then the styleable property may be in the Skin
* as opposed to directly in the class itself. We check the skin first. If
* it isn't there, then we check the class.
*
* @param object
* @param propertyName
* @return
*/
public Object getProperty(Object object, String propertyName) {
return getAttribute(propertyName).getProperty(object);
}
/**
* Sets the value for an attribute (property) with the given name. If the
* class is a Control, then the styleable property may be in the Skin as
* opposed to directly on the class itself. We check the skin first.
*
* @param object
* @param propertyName
* @param value
*/
public void setProperty(Object object, String propertyName, Object value) {
getAttribute(propertyName).setProperty(object, value);
}
public PropertyHandler getPropertyHandler(String propertyName) {
return getAttribute(propertyName);
}
private Map<String,List<PseudoclassListener>> listeners = new HashMap<String,List<PseudoclassListener>>();
public void addPseudoclassListener(DefaultStyleable object,
String pseudoclass, PseudoclassListener listener) {
List<PseudoclassListener> list = listeners.get(pseudoclass);
if (list == null) {
list = new ArrayList<PseudoclassListener>();
listeners.put(pseudoclass, list);
}
list.add(listener);
}
public void removePseudoclassListener(DefaultStyleable object,
String pseudoclass, PseudoclassListener listener) {
List<PseudoclassListener> list = listeners.get(pseudoclass);
if (list != null) {
list.remove(pseudoclass);
if (list.size() == 0) {
listeners.remove(pseudoclass);
}
}
}
public boolean isPropertyInherited(Object object, String propertyName) {
throw new UnsupportedOperationException();
}
private Attribute getAttribute(String name) {
Attribute a = attributes.get(name);
if (a == null) {
a = new Attribute(name);
attributes.put(name, a);
}
return a;
}
/**
* Represents an Attribute in JavaFX Script. An instance of this class
* can be reused with an class implementing an attribute of the given name.
* It abstracts attributes over Controls and Skins. That is, the attributes
* that are visible to CSS are the union of the attributes on a Control and
* the attributes on the skin of a Control. Since the skin can be changed
* dynamically, this class recomputes the property type every time it is
* asked.
*/
private final class Attribute implements PropertyHandler {
private String name;
Attribute(String name) {
this.name = name;
}
public Class getPropertyType(Object object) throws StylesheetException {
try {
Method getMethod = getMethod(object);
Type t = getMethod.getGenericReturnType();
if (t == DoubleVariable.class) {
return Double.class;
} else if (t == IntVariable.class) {
return Integer.class;
} else if (t == BooleanVariable.class) {
return Boolean.class;
} else if (t == SequenceVariable.class) {
throw new IllegalArgumentException("Attempted to set a " +
"sequence attribute with a value from CSS which is " +
"currently unsupported");
} else if (t instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) t;
// the actual type arguments should be an array of length 1
if (pt.getActualTypeArguments().length == 1) {
// it is possible this will fail according to the API, but
// it won't really unless the JavaFX compiler changes its
// ways
return (Class) pt.getActualTypeArguments()[0];
} else {
throw new IllegalStateException("Unexpected number of " +
"parameterized types.");
}
}
return null;
} catch (Exception e) {
throw new StylesheetException(e);
}
}
public Object getProperty(Object object) throws StylesheetException {
AbstractVariable var = getAttributeVariable(object);
return var == null ? null : var.get();
}
public void setProperty(Object object, Object value) throws StylesheetException {
//TODO need to convert AWT values to JavaFX type values
AbstractVariable var = getAttributeVariable(object);
if (var != null) {
var.set(value);
}
}
/**
* Gets the AbstractVariable which wraps the attribute value for a given
* named attribute. If the FXObjectStyleSupport was created for a Control,
* then the Skin is consulted for the attribute variable first.
*
* @param object
* @return null if not found
* @throws java.lang.Exception
*/
private AbstractVariable getAttributeVariable(Object object) {
try {
// try to get the accessor method on the skin first
Object skin = getSkin(object);
Object target = skin;
Method m = null;
if (skin != null) {
try {
m = skin.getClass().getMethod("get$" + name);
} catch (Exception ignored) {}
}
if (m == null) {
m = object.getClass().getMethod("get$" + name);
target = object;
}
Object result = m.invoke(target);
if (result instanceof AbstractVariable) {
return (AbstractVariable)result;
}
} catch (Exception ignored) {}
return null;
}
/**
* If the FXObjecStyleSupport was created for a Control class, then this
* method will return the Skin object owned by the given control Object.
* Otherwise it simply returns null.
*
* @param object
* @return
* @throws java.lang.Exception
*/
private Object getSkin(Object object) throws Exception {
if (isControl) {
Method m = object.getClass().getMethod("get$skin");
if (m != null) {
return ((AbstractVariable)m.invoke(object)).get();
}
}
return null;
}
/**
* Returns the get$attrname method that is created and declared for
* each attribute. If this FXObjectStyleSupport was created for a
* Control class, then it attempts to find the get method on the
* skin first. If that fails, then it attempts to find it on the
* object itself.
*
* @param object
* @return
* @throws java.lang.Exception
*/
private Method getMethod(Object object) throws Exception {
// try to get the accessor method on the skin first
Object skin = getSkin(object);
if (skin != null) {
try {
return skin.getClass().getMethod("get$" + name);
} catch (Exception ignored) {}
}
return object.getClass().getMethod("get$" + name);
}
}
private final class EventHandler implements ChangeListener {
private String pseudoclass;
EventHandler(String s) { pseudoclass = s; }
public boolean onChange() {
List<PseudoclassListener> list = listeners.get(pseudoclass);
if (list != null) {
//list.get(0).
}
return false;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -