/* * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.javafx.css; import javafx.css.PseudoClass; import javafx.css.Styleable; 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. * */ abstract public class Selector { private static class UniversalSelector { private static final Selector INSTANCE = new SimpleSelector("*", null, null, null); } public static Selector getUniversalSelector() { return UniversalSelector.INSTANCE; } private Rule rule; void setRule(Rule rule) { this.rule = rule; } Rule getRule() { return rule; } private int ordinal = -1; void setOrdinal(int ordinal) { this.ordinal = ordinal; } int getOrdinal() { return ordinal; } 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 abstract boolean applies(Styleable styleable, Set[] triggerStates, int bit); /** * Determines whether 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 state); private static final int TYPE_SIMPLE = 1; private static final int TYPE_COMPOUND = 2; protected void writeBinary(DataOutputStream os, 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 selectors = new ArrayList(); List combinators = new ArrayList(); List parts = new ArrayList(); int start = 0; int end = -1; char combinator = '\0'; for (int i=0; i') { 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 pseudoClasses = new ArrayList(); for (int j=1; j styleClasses = new ArrayList(); // 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