/* * Copyright (c) 2014, Oracle and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * - Neither the name of Oracle Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.javafx.scenebuilder.kit.editor.panel.css; import com.oracle.javafx.scenebuilder.kit.editor.panel.css.CssContentMaker.CssPropertyState; import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject; import com.oracle.javafx.scenebuilder.kit.util.CssInternal; import com.oracle.javafx.scenebuilder.kit.util.Deprecation; import javafx.css.Rule; import javafx.css.Style; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.css.CssMetaData; import javafx.css.StyleOrigin; import javafx.css.Styleable; import javafx.css.StyleableProperty; import javafx.scene.Node; import javafx.scene.control.Skinnable; /** * * @treatAsPrivate */ public class NodeCssState { private static final List ORDERED_ORIGIN = new ArrayList<>(); static { ORDERED_ORIGIN.add(StyleOrigin.USER_AGENT);// fxTheme : modena/caspian ORDERED_ORIGIN.add(StyleOrigin.USER);//Bean API Call ORDERED_ORIGIN.add(StyleOrigin.AUTHOR);//CSS files ORDERED_ORIGIN.add(StyleOrigin.INLINE);//Style property } @SuppressWarnings("rawtypes") private final Map> map; private final Node node; private final FXOMObject fxomObject; private Collection author; private Collection inline; private Collection userAgent; private Map> matchingRules; private List sortedMatchingRules = new ArrayList<>(); private Collection props; @SuppressWarnings("rawtypes") protected NodeCssState(Map> map, Node node, FXOMObject fxomObject) { this.map = map; this.node = node; this.fxomObject = fxomObject; getAuthorStyles(); getInlineStyles(); getUserAgentStyles(); getMatchingRules(); getAllStyleables(); } /** * * @treatAsPrivate */ @SuppressWarnings("rawtypes") public static class CssProperty implements Comparable { private final CssMetaData cssMeta; private final CssProperty mainProperty; private final Node target; private final List sub = new ArrayList<>(); private final ObjectProperty name = new SimpleObjectProperty<>(); private final ObjectProperty builtin = new SimpleObjectProperty<>(); private final ObjectProperty fxTheme = new SimpleObjectProperty<>(); private final ObjectProperty authorCss = new SimpleObjectProperty<>(); private final ObjectProperty inlineCss = new SimpleObjectProperty<>(); private final ObjectProperty fxmlModel = new SimpleObjectProperty<>(); private CssContentMaker.PropertyState currentState; CssProperty(NodeCssState nodeCssState, CssMetaData cssMeta, Node target, FXOMObject fxomObject) { this(nodeCssState, null, cssMeta, target, fxomObject); } CssProperty(NodeCssState nodeCssState, CssProperty mainProperty, CssMetaData cssMeta, Node target, FXOMObject fxomObject) { this.mainProperty = mainProperty; this.cssMeta = cssMeta; this.target = target; name.setValue(cssMeta.getProperty()); CssContentMaker.CssPropertyState inlineState = nodeCssState.retrieveCssStyle(cssMeta, nodeCssState.getInlineStyles()); if (inlineState != null) { inlineCss.setValue(inlineState); } CssContentMaker.CssPropertyState authorState = nodeCssState.retrieveCssStyle(cssMeta, nodeCssState.getAuthorStyles()); if (authorState != null) { authorCss.setValue(authorState); } CssContentMaker.CssPropertyState fxThemeState = nodeCssState.retrieveCssStyle(cssMeta, nodeCssState.getUserAgentStyles()); if (fxThemeState != null) { fxTheme.setValue(fxThemeState); } @SuppressWarnings("unchecked") CssContentMaker.PropertyState builtinState = CssContentMaker.initialValue(target, mainProperty == null ? this : mainProperty, cssMeta); assert builtinState != null; builtin.setValue(builtinState); CssContentMaker.PropertyState modelState = CssContentMaker.modelValue(target, cssMeta, fxomObject); if (modelState != null) { fxmlModel.setValue(modelState); } } public ObjectProperty builtinState() { return builtin; } public ObjectProperty modelState() { return fxmlModel; } public ObjectProperty fxThemeState() { return fxTheme; } public ObjectProperty authorState() { return authorCss; } public ObjectProperty inlineState() { return inlineCss; } public ObjectProperty propertyName() { return name; } public CssMetaData getStyleable() { return cssMeta; } public Node getTarget() { return target; } public List getSubProperties() { return sub; } public CssProperty getMainProperty() { return mainProperty; } @Override public int compareTo(CssProperty cssProperty) { return cssMeta.getProperty().compareTo(cssProperty.cssMeta.getProperty()); } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } CssProperty cssProperty = (CssProperty) obj; return cssMeta.getProperty().compareTo(cssProperty.cssMeta.getProperty()) == 0; } @Override public int hashCode() { int hash = 3; hash = 31 * hash + Objects.hashCode(this.cssMeta); hash = 31 * hash + Objects.hashCode(this.mainProperty); hash = 31 * hash + Objects.hashCode(this.target); return hash; } public boolean isBuiltinSource() { return inlineState().get() == null && authorState().get() == null && modelState().get() == null && fxThemeState().get() == null; } public boolean isFxThemeSource() { return fxThemeState().get() != null && inlineState().get() == null && authorState().get() == null && modelState().get() == null; } public boolean isModelSource() { return modelState().get() != null && inlineState().get() == null && authorState().get() == null; } public boolean isAuthorSource() { return authorState().get() != null && inlineState().get() == null; } public boolean isInlineSource() { return inlineState().get() != null; } // CSS only, model and builtin doesn't make sense there public CssContentMaker.CssPropertyState getWinner() { if (inlineState().get() != null) { return inlineState().get(); } if (authorState().get() != null) { return authorState().get(); } return fxThemeState().get(); } public CssContentMaker.PropertyState getCurrentStyle() { if (currentState == null) { currentState = builtinState().get(); CssContentMaker.PropertyState model = modelState().get(); CssContentMaker.CssPropertyState cssState = getWinner(); if (cssState == null) { if (model != null) { currentState = model; } } else { if (model != null && cssState.getStyle() != null && cssState.getStyle().getOrigin() == StyleOrigin.USER_AGENT) { currentState = model; } else { currentState = cssState; } } } return currentState; } public StyleOrigin getCurrentStyleOrigin() { CssContentMaker.PropertyState state = getCurrentStyle(); if (state instanceof CssContentMaker.CssPropertyState) { CssContentMaker.CssPropertyState cssState = (CssContentMaker.CssPropertyState) state; return cssState.getStyle().getOrigin(); } else { if (state instanceof CssContentMaker.BeanPropertyState) { return StyleOrigin.USER; } else { return null; } } } public boolean isInlineInherited() { boolean ret = false; CssContentMaker.CssPropertyState css = inlineCss.get(); if (css != null) { ret = CssContentMaker.isInlineInherited(target, css); } return ret; } public Node getSourceNodeForInline() { Node ret = null; CssContentMaker.CssPropertyState css = inlineCss.get(); if (css != null) { ret = CssContentMaker.getSourceNodeForStyle(target, propertyName().get()); } return ret; } public List getFxThemeHiddenByModel() { List ret = new ArrayList<>(); CssContentMaker.CssPropertyState ps = getWinner(); List notAppliedStyles = ps == null ? Collections.emptyList() : ps.getNotAppliedStyles(); boolean hasModel = modelState().get() != null; if (hasModel) { List