📄 propertymanager.java
字号:
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.stylesheet;
import java.awt.Color;
import java.util.*;
import com.sun.stylesheet.*;
import com.sun.stylesheet.styleable.*;
import com.sun.stylesheet.types.*;
/**
* Used by {@link Rule Rules} to apply properties to styleable objects.
* <code>PropertyManager</code> provides automatic support for priorities as
* well as property removal, and so for these features to work correctly all
* modifications to {@link Styleable} objects should be made through
* <code>PropertyManager</code>.
*
*@author Ethan Nicholas
*/
public class PropertyManager {
private static final String NO_STYLE = "no style";
private static final boolean debug = false;
/**
* Maps styleables to their property values. Property values are stored in
* a Map, and each "value" is actually a list of all applicable values
* sorted by priority.
*/
private static Map<Styleable, Map<String, PropertyList>> properties =
new WeakHashMap<Styleable, Map<String, PropertyList>>();
/**
* Maps styleables to their pseudoclass listeners.
*/
private static Map<Styleable, List<PseudoclassValue>> pseudoclasses =
new WeakHashMap<Styleable, List<PseudoclassValue>>();
private static class PropertyList extends ArrayList<PropertyValue> {
private boolean overridden; // true if someone has modified this
// property outside of CSS' control
}
/**
* Encapsulates a property value in effect for a Styleable. Each property
* value stores its priority for use in determining which one should
* currently be in effect, and its stylesheet to help manage stylesheet
* updates.
*/
public static class PropertyValue implements Comparable {
private String property;
private Object value;
private Priority priority;
private Rule source;
private Animation animation;
private boolean inherited;
public PropertyValue(String property, Object value, Rule source,
Priority priority, Animation animation, boolean inherited) {
this.property = property;
this.value = value;
this.priority = priority;
this.source = source;
this.animation = animation;
this.inherited = inherited;
}
public String getPropertyName() {
return property;
}
public Object getValue() {
return value;
}
public Priority getPriority() {
return priority;
}
public Rule getSource() {
return source;
}
public Animation getAnimation() {
return animation;
}
public boolean wasInherited() {
return inherited;
}
public int compareTo(Object o) {
return getPriority().compareTo(((PropertyValue) o).getPriority());
}
public boolean equals(Object o) {
// we explicitly do not compare the values -- if two properties
// came from the same stylesheet with the same priority, they're
// from the same rule. By not comparing the values, we're free
// to recreate them as needed without worrying about identity.
if (!(o instanceof PropertyValue))
return false;
PropertyValue value = (PropertyValue) o;
if (!value.getPriority().equals(getPriority()))
return false;
if (!property.equals(value.getPropertyName()))
return false;
if (value.inherited != inherited)
return false;
return source == value.getSource();
}
public int hashCode() {
return property.hashCode() ^
(source != null ? source.hashCode() : 0) ^
(value != null ? value.hashCode() : 0) ^
priority.hashCode();
}
public String toString() {
return "PropertyValue[" + property + "=" + value + ", " + priority +
"]";
}
}
private static class PseudoclassValue {
private String pseudoclass;
private PseudoclassListener listener;
private Rule source;
public PseudoclassValue(String pseudoclass,
PseudoclassListener listener, Rule source) {
this.pseudoclass = pseudoclass;
this.listener = listener;
this.source = source;
}
public String getPseudoclass() {
return pseudoclass;
}
public PseudoclassListener getPseudoclassListener() {
return listener;
}
public Rule getSource() {
return source;
}
public boolean equals(Object o) {
if (!(o instanceof PseudoclassValue))
return false;
PseudoclassValue p = (PseudoclassValue) o;
return pseudoclass.equals(p.pseudoclass) &&
listener == p.listener &&
source == p.source;
}
public int hashCode() {
return pseudoclass.hashCode() ^
listener.hashCode() ^
source.hashCode();
}
}
private PropertyManager() { /* not instantiable */ }
/**
* Returns an unsorted list of all properties currently applied to the
* specified object (this includes values which are being masked by
* higher-priority values).
*/
public static List<PropertyValue> getAllPropertiesForObject(
Styleable object) {
Map<String, PropertyList> propertyMap = properties.get(object);
if (propertyMap == null) {
propertyMap = new HashMap<String, PropertyList>();
properties.put(object, propertyMap);
}
List<PropertyValue> result = new ArrayList<PropertyValue>();
for (List<PropertyValue> list : propertyMap.values())
result.addAll(list);
return result;
}
/**
* Returns a sorted list of all values for the specified property currently
* applied to an object. The highest-priority value is at the end of the
* list; this is the value which should actually take effect.
*/
public static List<PropertyValue> getPropertyListForObject(Styleable object,
String property) {
Map<String, PropertyList> propertyMap = properties.get(object);
if (propertyMap == null) {
propertyMap = new HashMap<String, PropertyList>();
properties.put(object, propertyMap);
}
PropertyList propertyList = propertyMap.get(property);
if (propertyList == null) {
propertyList = new PropertyList();
propertyMap.put(property, propertyList);
}
return propertyList;
}
/**
* Returns true if there is a matching value currently applied to the
* object.
*/
private static boolean isPropertyApplied(Styleable object, String property,
Rule source, Priority priority, boolean wasInherited) {
List<PropertyValue> propertyList = getPropertyListForObject(object,
property);
for (int i = 0; i < propertyList.size(); i++) {
PropertyValue p = propertyList.get(i);
if (p.getSource() == source)
return true;
}
return false;
}
/** Adds the specified value to the property list for the object. */
private static void propertyApplied(Styleable object, String property,
Object value, Rule source, Priority priority, Animation animation,
boolean wasInherited) {
PropertyList propertyList = (PropertyList) getPropertyListForObject(
object, property);
propertyList.overridden = false;
propertyList.add(new PropertyValue(property, value, source, priority,
animation, wasInherited));
Collections.sort(propertyList);
}
/** Removes the specified value from the property list for the object. */
private static void propertyRemoved(Styleable object, String property,
Object value, Rule source, Priority priority, Animation animation,
boolean wasInherited) {
PropertyList propertyList = (PropertyList) getPropertyListForObject(
object, property);
if (propertyList.overridden == false &&
!AnimationManager.isAnimating(object, property)) {
Object value1 = object.getProperty(property);
Object value2 = getCurrentValue(object, property);
boolean equal;
if (value1 == null)
equal = value2 == null;
else
equal = value1.equals(value2);
if (!equal) { // property has been changed outside of our control
if (debug)
System.err.println("WARNING: property " + property +
" of " + object + " has been overridden (" +
value1 + " != " + value2 + ")");
propertyList.overridden = true;
}
}
propertyList.remove(new PropertyValue(property, value, source, priority,
animation, wasInherited));
}
/**
* Returns the highest-priority value currently in effect for the specified
* property.
*/
private static Object getCurrentValue(Styleable object, String property) {
PropertyList propertyList = (PropertyList) getPropertyListForObject(
object, property);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -