/*
 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.javafx.css;

import javafx.css.Declaration;
import javafx.css.Match;
import javafx.css.ParsedValue;
import javafx.css.PseudoClass;
import javafx.css.Rule;
import javafx.css.Selector;
import javafx.css.Style;
import javafx.css.StyleOrigin;

import java.util.Set;

A marriage of pseudo-classes (potentially empty) to property and value
Since:9
/** A marriage of pseudo-classes (potentially empty) to property and value * * @since 9 */
public class CascadingStyle implements Comparable<CascadingStyle> { /** */ private final Style style; public Style getStyle() { return style; }
State variables, like "hover" or "pressed"
/** State variables, like &quot;hover&quot; or &quot;pressed&quot; */
private final Set<PseudoClass> pseudoClasses; /* specificity of the selector that matched */ private final int specificity; /* order in which this style appeared in the stylesheet */ private final int ordinal; /* * True if the property is -fx-skin. We want the skin property to * sort less than all other properties. */ private final boolean skinProp; public CascadingStyle(final Style style, Set<PseudoClass> pseudoClasses, final int specificity, final int ordinal) { this.style = style; this.pseudoClasses = pseudoClasses; this.specificity = specificity; this.ordinal = ordinal; this.skinProp = "-fx-skin".equals(style.getDeclaration().getProperty()); } public CascadingStyle(final Declaration decl, final Match match, final int ordinal) { this(new Style(match.getSelector(), decl), match.getPseudoClasses(), match.getSpecificity(), ordinal); } // Wrapper to make StyleHelper's life a little easier public String getProperty() { return style.getDeclaration().getProperty(); } // Wrapper to make StyleHelper's life a little easier public Selector getSelector() { return style.getSelector(); } // Wrapper to make StyleHelper's life a little easier public Rule getRule() { return style.getDeclaration().getRule(); } // Wrapper to make StyleHelper's life a little easier public StyleOrigin getOrigin() { return getRule().getOrigin(); } // Wrapper to make StyleHelper's life a little easier public ParsedValue getParsedValue() { return style.getDeclaration().getParsedValue(); } @Override public String toString() { return getProperty(); }
When testing equality against another Style, we only care about the property and pseudo-classes. In other words, we only care about where the style is applied, not what is applied.
/** * When testing equality against another Style, we only care about * the property and pseudo-classes. In other words, we only care about * where the style is applied, not what is applied. */
@Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } CascadingStyle other = (CascadingStyle)obj; final String property = getProperty(); final String otherProperty = other.getProperty(); if (property == null ? otherProperty != null : !property.equals(otherProperty)) { return false; } // does [foo bar bang] contain all of [foo bar]? if (pseudoClasses == null ? other.pseudoClasses != null : !pseudoClasses.containsAll(other.pseudoClasses)) { return false; } return true; } /* * Hash on property and pseudoclasses since * obj1.hashCode() should equal obj2.hashCode() if obj1.equals(obj2) */ @Override public int hashCode() { int hash = 7; final String property = getProperty(); hash = 47 * hash + (property != null ? property.hashCode() : 0); hash = 47 * hash + (pseudoClasses != null ? pseudoClasses.hashCode() : 0); return hash; }
Implementation of Comparable such that more specific styles get sorted before less specific ones.
/** * Implementation of Comparable such that more specific styles get * sorted before less specific ones. */
@Override public int compareTo(CascadingStyle other) { // // Important styles take the cake // Importance being equal, then specificity is considered // Specificity being equal, then the order of declaration decides. // final Declaration decl = style.getDeclaration(); final boolean important = decl != null ? decl.isImportant() : false; final Rule rule = decl != null ? decl.getRule() : null; final StyleOrigin source = rule != null ? rule.getOrigin() : null; final Declaration otherDecl = other.style.getDeclaration(); final boolean otherImportant = otherDecl != null ? otherDecl.isImportant() : false; final Rule otherRule = otherDecl != null ? otherDecl.getRule() : null; final StyleOrigin otherSource = otherRule != null ? otherRule.getOrigin() : null; int c = 0; if (this.skinProp && !other.skinProp) { c = 1; } else if (important != otherImportant) { c = important ? -1 : 1; } else if (source != otherSource) { if (source == null) c = -1; else if (otherSource == null) c = 1; else c = otherSource.compareTo(source); } else { c = other.specificity - this.specificity; }; if (c == 0) c = other.ordinal - this.ordinal; return c; } }