/*
 * Copyright (c) 2008, 2017, 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 javafx.css;

import com.sun.javafx.css.Combinator;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

Used by CSSRule to determine whether or not the selector applies to a given object.
Since:9
/** * Used by CSSRule to determine whether or not the selector applies to a * given object. * * @since 9 */
abstract public class Selector { private static class UniversalSelector { private static final Selector INSTANCE = new SimpleSelector("*", null, null, null); } static Selector getUniversalSelector() { return UniversalSelector.INSTANCE; } private Rule rule; void setRule(Rule rule) { this.rule = rule; } public Rule getRule() { return rule; } private int ordinal = -1; public void setOrdinal(int ordinal) { this.ordinal = ordinal; } public int getOrdinal() { return ordinal; } public abstract Match createMatch(); // same as the matches method expect return true/false rather than a match public abstract boolean applies(Styleable styleable); // same as applies, but will return pseudoclass state that it finds along the way public abstract boolean applies(Styleable styleable, Set<PseudoClass>[] triggerStates, int bit);
Determines whether the current state of the node and its parents matches the pseudo-classes defined (if any) for this selector.
Params:
  • styleable – the styleable
  • state – the state
Returns:true if the current state of the node and its parents matches the pseudo-classes defined (if any) for this selector
/** * Determines whether the current state of the node and its parents * matches the pseudo-classes defined (if any) for this selector. * @param styleable the styleable * @param state the state * @return {@code true} if the current state of the node and its parents * matches the pseudo-classes defined (if any) for this selector */
public abstract boolean stateMatches(Styleable styleable, Set<PseudoClass> state); private static final int TYPE_SIMPLE = 1; private static final int TYPE_COMPOUND = 2; protected void writeBinary(DataOutputStream os, StyleConverter.StringStore stringStore) throws IOException { if (this instanceof SimpleSelector) { os.writeByte(TYPE_SIMPLE); } else { os.writeByte(TYPE_COMPOUND); } } static Selector readBinary(int bssVersion, DataInputStream is, String[] strings) throws IOException { final int type = is.readByte(); if (type == TYPE_SIMPLE) return SimpleSelector.readBinary(bssVersion, is,strings); else return CompoundSelector.readBinary(bssVersion, is,strings); } public static Selector createSelector(final String cssSelector) { if (cssSelector == null || cssSelector.length() == 0) { return null; // actually return a default no-match selector } // A very primitive parser List<SimpleSelector> selectors = new ArrayList<SimpleSelector>(); List<Combinator> combinators = new ArrayList<Combinator>(); List<String> parts = new ArrayList<String>(); int start = 0; int end = -1; char combinator = '\0'; for (int i=0; i<cssSelector.length(); i++) { char ch = cssSelector.charAt(i); if (ch == ' ') { if (combinator == '\0') { combinator = ch; end = i; } } else if (ch == '>') { if (combinator == '\0') end = i; combinator = ch; } else if (combinator != '\0'){ parts.add(cssSelector.substring(start, end)); start = i; combinators.add(combinator == ' ' ? Combinator.DESCENDANT : Combinator.CHILD); combinator = '\0'; } } parts.add(cssSelector.substring(start)); for (int i=0; i<parts.size(); i++) { final String part = parts.get(i); if (part != null && !part.equals("")) { // Now we have the parts, we can split off the pseudo classes String[] pseudoClassParts = part.split(":"); List<String> pseudoClasses = new ArrayList<String>(); for (int j=1; j<pseudoClassParts.length; j++) { if (pseudoClassParts[j] != null && !pseudoClassParts[j].equals("")) { pseudoClasses.add(pseudoClassParts[j].trim()); } } // Now that we've read off the pseudo classes, we can go ahead and pull // apart the beginning. final String selector = pseudoClassParts[0].trim(); // There might be style classes, so lets peel those off next String[] styleClassParts = selector.split("\\."); List<String> styleClasses = new ArrayList<String>(); // If the first one is an empty string, then it started with a pseudo class // If the first one starts with a #, it was an id // Otherwise, it was a name for (int j=1; j<styleClassParts.length; j++) { if (styleClassParts[j] != null && !styleClassParts[j].equals("")) { styleClasses.add(styleClassParts[j].trim()); } } String name = null, id = null; if (styleClassParts[0].equals("")) { // Do nothing! } else if (styleClassParts[0].charAt(0) == '#') { id = styleClassParts[0].substring(1).trim(); } else { name = styleClassParts[0].trim(); } selectors.add(new SimpleSelector(name, styleClasses, pseudoClasses, id)); } } if (selectors.size() == 1) { return selectors.get(0); } else { return new CompoundSelector(selectors, combinators); } } }