Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.css; 027 028import java.util.Collections; 029import java.util.List; 030import javafx.scene.Node; 031 032/** 033 * A CssMetaData instance provides information about the CSS style and 034 * provides the hooks that allow CSS to set a property value. 035 * It encapsulates the CSS property name, the type into which the CSS value 036 * is converted, and the default value of the property. 037 * <p> 038 * CssMetaData is the bridge between a value that can be represented 039 * syntactically in a .css file, and a {@link StyleableProperty}. There is 040 * a one-to-one correspondence between a CssMetaData and a StyleableProperty. 041 * Typically, the CssMetaData of a will include the CssMetaData of its ancestors. 042 * During CSS processing, the CSS engine iterates over the Node's CssMetaData, 043 * looks up the parsed value of each, converts the parsed value, and 044 * sets the value on the StyleableProperty. 045 * <p> 046 * The method {@link Node#getCssMetaData()} is called to obtain the 047 * List<CssMetaData>. This method is called frequently and it is prudent 048 * to return a static list rather than creating the list on each call. By 049 * convention, node classes that have CssMetaData will implement a 050 * static method {@code getClassCssMetaData()} and it is customary to have 051 * {@code getCssMetaData()} simply return {@code getClassCssMetaData()}. The 052 * purpose of {@code getClassCssMetaData()} is to allow sub-classes to easily 053 * include the CssMetaData of some ancestor. 054 * <p> 055 * This example is a typical implementation. 056 * <code><pre> 057 * private DoubleProperty gapProperty = new StyleableDoubleProperty(0) { 058 * {@literal @}Override 059 * public CssMetaData{@literal <}MyWidget,Number{@literal >} getCssMetaData() { 060 * return GAP_META_DATA; 061 * } 062 * 063 * {@literal @}Override 064 * public Object getBean() { 065 * return MyWidget.this; 066 * } 067 * 068 * {@literal @}Override 069 * public String getName() { 070 * return "gap"; 071 * } 072 * }; 073 * 074 * private static final CssMetaData GAP_META_DATA = 075 * new CssMetaData{@literal <}MyWidget,Number{@literal >}("-my-gap", StyleConverter.getSizeConverter(), 0d) { 076 * 077 * {@literal @}Override 078 * public boolean isSettable(MyWidget node) { 079 * return node.gapProperty == null || !node.gapProperty.isBound(); 080 * } 081 * 082 * {@literal @}Override 083 * public StyleableProperty{@literal <}Number{@literal >} getStyleableProperty(MyWidget node) { 084 * return (StyleableProperty{@literal <}Number{@literal >})node.gapProperty; 085 * } 086 * }; 087 * 088 * private static final List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} cssMetaDataList; 089 * static { 090 * List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} temp = 091 * new ArrayList{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >}(Control.getClassCssMetaData()); 092 * temp.add(GAP_META_DATA); 093 * cssMetaDataList = Collections.unmodifiableList(temp); 094 * } 095 * 096 * public static List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} getClassCssMetaData() { 097 * return cssMetaDataList; 098 * } 099 * 100 * {@literal @}Override 101 * public List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} getCssMetaData() { 102 * return getClassCssMetaData(); 103 * } 104 * </pre><code> 105 * @param <S> The type of Styleable 106 * @param <V> The type into which the parsed value is converted. 107 */ 108public abstract class CssMetaData<S extends Styleable, V> { 109 110 /** 111 * Set the value of the corresponding property on the given Node. 112 * @param styleable The Styleable on which the property value is being set 113 * @param value The value to which the property is set 114 * @deprecated This method is no longer called from CSS code. 115 * Use {@link StyleableProperty#applyStyle(javafx.css.StyleOrigin, java.lang.Object)} 116 */ 117 @Deprecated 118 public void set(S styleable, V value, StyleOrigin origin) { 119 120 final StyleableProperty<V> styleableProperty = getStyleableProperty(styleable); 121 final StyleOrigin currentOrigin = styleableProperty.getStyleOrigin(); 122 final V currentValue = styleableProperty.getValue(); 123 124 // RT-21185: Only apply the style if something has changed. 125 if ((currentOrigin != origin) 126 || (currentValue != null 127 ? currentValue.equals(value) == false 128 : value != null)) { 129 130 styleableProperty.applyStyle(origin, value); 131 132 } 133 } 134 135 /** 136 * Check to see if the corresponding property on the given Node is 137 * settable. This method is called before any styles are looked up for the 138 * given property. It is abstract so that the code can check if the property 139 * is settable without expanding the property. Generally, the property is 140 * settable if it is not null or is not bound. 141 * 142 * @param styleable The Styleable on which the property value is being set 143 * @return true if the property can be set. 144 */ 145 public abstract boolean isSettable(S styleable); 146 147 /** 148 * Return the corresponding {@link StyleableProperty} for the given Node. 149 * Note that calling this method will cause the property to be expanded. 150 * @param styleable The Styleable for which the property is returned 151 * @return The StyleableProperty corresponding to this CssMetaData for the 152 * given Styleable 153 */ 154 public abstract StyleableProperty<V> getStyleableProperty(S styleable); 155 156 private final String property; 157 /** 158 * @return the CSS property name 159 */ 160 public final String getProperty() { 161 return property; 162 } 163 164 private final StyleConverter<?,V> converter; 165 /** 166 * @return The CSS converter that handles conversion from a CSS value to a Java Object 167 */ 168 public final StyleConverter<?,V> getConverter() { 169 return converter; 170 } 171 172 private final V initialValue; 173 /** 174 * The initial value of a CssMetaData corresponds to the default 175 * value of the StyleableProperty in code. 176 * For example, the default value of Shape.fill is Color.BLACK and the 177 * initialValue of Shape.StyleableProperties.FILL is also Color.BLACK. 178 * <p> 179 * There may be exceptions to this, however. The initialValue may depend 180 * on the state of the Node. A ScrollBar has a default orientation of 181 * horizontal. If the ScrollBar is vertical, however, this method should 182 * return Orientation.VERTICAL. Otherwise, a vertical ScrollBar would be 183 * incorrectly set to a horizontal ScrollBar when the initial value is 184 * applied. 185 * @return The initial value of the property, possibly null 186 */ 187 public V getInitialValue(S styleable) { 188 return initialValue; 189 } 190 191 private final List<CssMetaData<? extends Styleable, ?>> subProperties; 192 /** 193 * The sub-properties refers to the constituent properties of this property, 194 * if any. For example, "-fx-font-weight" is sub-property of "-fx-font". 195 */ 196 public final List<CssMetaData<? extends Styleable, ?>> getSubProperties() { 197 return subProperties; 198 } 199 200 private final boolean inherits; 201 /** 202 * If true, the value of this property is the same as 203 * the parent's computed value of this property. 204 * @default false 205 * @see <a href="http://www.w3.org/TR/css3-cascade/#inheritance">CSS Inheritance</a> 206 */ 207 public final boolean isInherits() { 208 return inherits; 209 } 210 211 /** 212 * Construct a CssMetaData with the given parameters and no sub-properties. 213 * @param property the CSS property 214 * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. 215 * @param initalValue the CSS string 216 * @param inherits true if this property uses CSS inheritance 217 * @param subProperties the sub-properties of this property. For example, 218 * the -fx-font property has the sub-properties -fx-font-family, 219 * -fx-font-size, -fx-font-weight, and -fx-font-style. 220 */ 221 protected CssMetaData( 222 final String property, 223 final StyleConverter<?,V> converter, 224 final V initialValue, 225 boolean inherits, 226 final List<CssMetaData<? extends Styleable, ?>> subProperties) { 227 228 this.property = property; 229 this.converter = converter; 230 this.initialValue = initialValue; 231 this.inherits = inherits; 232 this.subProperties = subProperties != null ? Collections.unmodifiableList(subProperties) : null; 233 234 if (this.property == null || this.converter == null) { 235 throw new IllegalArgumentException("neither property nor converter can be null"); 236 } 237 } 238 239 /** 240 * Construct a CssMetaData with the given parameters and no sub-properties. 241 * @param property the CSS property 242 * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. 243 * @param initalValue the CSS string 244 * @param inherits true if this property uses CSS inheritance 245 */ 246 protected CssMetaData( 247 final String property, 248 final StyleConverter<?,V> converter, 249 final V initialValue, 250 boolean inherits) { 251 this(property, converter, initialValue, inherits, null); 252 } 253 254 /** 255 * Construct a CssMetaData with the given parameters, inherit set to 256 * false and no sub-properties. 257 * @param property the CSS property 258 * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. 259 * @param initalValue the CSS string 260 */ 261 protected CssMetaData( 262 final String property, 263 final StyleConverter<?,V> converter, 264 final V initialValue) { 265 this(property, converter, initialValue, false, null); 266 } 267 268 /** 269 * Construct a CssMetaData with the given parameters, initialValue is 270 * null, inherit is set to false, and no sub-properties. 271 * @param property the CSS property 272 * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. 273 * @param initalValue the CSS string 274 */ 275 protected CssMetaData( 276 final String property, 277 final StyleConverter<?,V> converter) { 278 this(property, converter, null, false, null); 279 } 280 281 @Override 282 public boolean equals(Object obj) { 283 if (obj == null) { 284 return false; 285 } 286 if (getClass() != obj.getClass()) { 287 return false; 288 } 289 final CssMetaData<? extends Styleable, ?> other = (CssMetaData<? extends Styleable, ?>) obj; 290 if ((this.property == null) ? (other.property != null) : !this.property.equals(other.property)) { 291 return false; 292 } 293 return true; 294 } 295 296 @Override 297 public int hashCode() { 298 int hash = 3; 299 hash = 19 * hash + (this.property != null ? this.property.hashCode() : 0); 300 return hash; 301 } 302 303 304 @Override public String toString() { 305 return new StringBuilder("CSSProperty {") 306 .append("property: ").append(property) 307 .append(", converter: ").append(converter.toString()) 308 .append(", initalValue: ").append(String.valueOf(initialValue)) 309 .append(", inherits: ").append(inherits) 310 .append(", subProperties: ").append( 311 (subProperties != null) ? subProperties.toString() : "[]") 312 .append("}").toString(); 313 } 314 315 316}