changeset 6461:55c7382f2098

Backed out RT-20642 changeset c42d31058266
author David Grieve<david.grieve@oracle.com>
date Thu, 13 Mar 2014 14:32:36 -0400
parents c42d31058266
children e6a0305158da
files apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/NodeCssState.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/CssInternal.java apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/Deprecation.java modules/graphics/src/main/java/javafx/scene/CssStyleHelper.java modules/graphics/src/main/java/javafx/scene/Node.java modules/graphics/src/test/java/com/sun/javafx/css/Node_cssStyleMap_Test.java
diffstat 6 files changed, 284 insertions(+), 214 deletions(-) [+]
line wrap: on
line diff
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/NodeCssState.java	Thu Mar 13 12:56:00 2014 -0400
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/editor/panel/css/NodeCssState.java	Thu Mar 13 14:32:36 2014 -0400
@@ -73,7 +73,7 @@
     }
 
     @SuppressWarnings("rawtypes")
-    private final Map<StyleableProperty<?>, List<Style>> map;
+    private final Map<StyleableProperty, List<Style>> map;
     private final Node node;
     private final FXOMObject fxomObject;
     private Collection<CssContentMaker.CssPropertyState> author;
@@ -84,7 +84,7 @@
     private Collection<CssProperty> props;
 
     @SuppressWarnings("rawtypes")
-    protected NodeCssState(Map<StyleableProperty<?>, List<Style>> map, Node node, FXOMObject fxomObject) {
+    protected NodeCssState(Map<StyleableProperty, List<Style>> map, Node node, FXOMObject fxomObject) {
         this.map = map;
         this.node = node;
         this.fxomObject = fxomObject;
@@ -641,7 +641,7 @@
 //                }
 //                System.out.println("\n\n\n");
 //            }
-        for (Map.Entry<StyleableProperty<?>, List<Style>> entry : map.entrySet()) {//NOI18N
+        for (Map.Entry<StyleableProperty, List<Style>> entry : map.entrySet()) {//NOI18N
             StyleableProperty<?> value = entry.getKey();
 //                System.out.println("\nStyleable property: " + value);
             assert entry.getValue() != null;
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/CssInternal.java	Thu Mar 13 12:56:00 2014 -0400
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/CssInternal.java	Thu Mar 13 14:32:36 2014 -0400
@@ -269,8 +269,8 @@
 
     private static CssPropAuthorInfo getCssInfoForNode(Node node, ValuePropertyMetadata prop) {
         @SuppressWarnings("rawtypes")
-        Map<StyleableProperty<?>, List<Style>> map = collectCssState(node);
-        for (@SuppressWarnings("rawtypes") Map.Entry<StyleableProperty<?>, List<Style>> entry : map.entrySet()) {//NOI18N
+        Map<StyleableProperty, List<Style>> map = collectCssState(node);
+        for (@SuppressWarnings("rawtypes") Map.Entry<StyleableProperty, List<Style>> entry : map.entrySet()) {//NOI18N
             StyleableProperty<?> beanProp = entry.getKey();
             List<Style> styles = new ArrayList<>(entry.getValue());
             @SuppressWarnings("unchecked") //NOI18N
@@ -403,25 +403,26 @@
         return property;
     }
 
-//    public static void attachMapToNode(Node node) {
-//        @SuppressWarnings("rawtypes")
-//        Map<StyleableProperty<?>, List<Style>> smap = new HashMap<>();
-//        Deprecation.setStyleMap(node, FXCollections.observableMap(smap));
-//    }
+    public static void attachMapToNode(Node node) {
+        @SuppressWarnings("rawtypes")
+        Map<StyleableProperty<?>, List<Style>> smap = new HashMap<>();
+        Deprecation.setStyleMap(node, FXCollections.observableMap(smap));
+    }
 
-//    public static void detachMapToNode(Node node) {
-//        Deprecation.setStyleMap(node, null);
-//    }
+    public static void detachMapToNode(Node node) {
+        Deprecation.setStyleMap(node, null);
+    }
 
     @SuppressWarnings("rawtypes")
-    public static Map<StyleableProperty<?>, List<Style>> collectCssState(Node node) {
-//        attachMapToNode(node);
+    public static Map<StyleableProperty, List<Style>> collectCssState(Node node) {
+        attachMapToNode(node);
         // Force CSS to apply
         node.applyCss();
 
-        Map<StyleableProperty<?>, List<Style>> ret = Deprecation.getStyleMap(node);
+        Map<StyleableProperty, List<Style>> ret = new HashMap<>();
+        ret.putAll(Deprecation.getStyleMap(node));
         // Attached map may impact css performance, so remove it.
-//        detachMapToNode(node);
+        detachMapToNode(node);
         // DEBUG
 //        System.out.println("collectCssState() for " + node);
 //        for (StyleableProperty s : ret.keySet()) {
--- a/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/Deprecation.java	Thu Mar 13 12:56:00 2014 -0400
+++ b/apps/scenebuilder/SceneBuilderKit/src/com/oracle/javafx/scenebuilder/kit/util/Deprecation.java	Thu Mar 13 14:32:36 2014 -0400
@@ -41,8 +41,6 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.List;
-import java.util.Map;
-
 import javafx.collections.ObservableMap;
 import javafx.css.CssMetaData;
 import javafx.css.Styleable;
@@ -62,8 +60,6 @@
 import javafx.scene.image.Image;
 import javafx.scene.layout.GridPane;
 
-import javax.naming.OperationNotSupportedException;
-
 @SuppressWarnings("deprecation")
 public class Deprecation {
 
@@ -84,13 +80,13 @@
     }
 
 //    // RT-21096 : Promote impl_getStyleMap / impl_setStyleMap to public API
-//    public static void setStyleMap(Node node, ObservableMap<StyleableProperty<?>, List<com.sun.javafx.css.Style>> map) {
-//        node.impl_setStyleMap(map);
-//    }
+    public static void setStyleMap(Node node, ObservableMap<StyleableProperty<?>, List<com.sun.javafx.css.Style>> map) {
+        node.impl_setStyleMap(map);
+    }
 
 //    // RT-21096 : Promote impl_getStyleMap / impl_setStyleMap to public API
-    public static Map<StyleableProperty<?>, List<Style>> getStyleMap(Node node) {
-        return node.impl_findStyles(null);
+    public static ObservableMap<StyleableProperty<?>, List<Style>> getStyleMap(Node node) {
+        return node.impl_getStyleMap();
     }
 
     // Used to woraround RT-34863
--- a/modules/graphics/src/main/java/javafx/scene/CssStyleHelper.java	Thu Mar 13 12:56:00 2014 -0400
+++ b/modules/graphics/src/main/java/javafx/scene/CssStyleHelper.java	Thu Mar 13 14:32:36 2014 -0400
@@ -25,9 +25,11 @@
 package javafx.scene;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -38,6 +40,8 @@
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.WritableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableMap;
 import javafx.css.CssMetaData;
 import javafx.css.FontCssMetaData;
 import javafx.css.ParsedValue;
@@ -85,7 +89,7 @@
     /**
      * Creates a new StyleHelper.
      */
-    static CssStyleHelper createStyleHelper(final Node node, WritableValue<Boolean> clearCacheOnReuse) {
+    static CssStyleHelper createStyleHelper(final Node node, WritableValue<Boolean> clearCacheOnReuse, ObservableMap<StyleableProperty<?>, List<Style>> styleObserver) {
 
         // need to know how far we are to root in order to init arrays.
         // TODO: should we hang onto depth to avoid this nonsense later?
@@ -153,16 +157,28 @@
 
             if (mightInherit == false) {
 
-                // If this node had a style helper, then reset properties to their initial value
-                // since the node won't have a style helper after this call
-                if (node.styleHelper != null) {
-                    node.styleHelper.resetToInitialValues(node);
+                //
+                // If there is an observer listening for css style changes, then that listener needs to be
+                // preserved, even if there aren't any changes. At some point in the future, this node might
+                // have styles and the observer should start notifying of changes.
+                //
+                // So, if there isn't an observer listening for css style changes, we can just return null here.
+                // If there is, then we'll fall through and create a new StyleHelper which will be assigned
+                // the current StyleHelper's observer.
+                //
+                if ((styleObserver == null) || (FXCollections.emptyObservableMap() == (ObservableMap)styleObserver)) {
+
+                    // If this node had a style helper, then reset properties to their initial value
+                    // since the node won't have a style helper after this call
+                    if (node.styleHelper != null) {
+                        node.styleHelper.resetToInitialValues(node);
+                    }
+
+                    //
+                    // This node didn't have a StyleHelper before and it doesn't need one now since there are
+                    // no styles in the StyleMap and no inherited styles.
+                    return null;
                 }
-
-                //
-                // This node didn't have a StyleHelper before and it doesn't need one now since there are
-                // no styles in the StyleMap and no inherited styles.
-                return null;
             }
 
         }
@@ -207,6 +223,9 @@
             node.styleHelper.resetToInitialValues(node);
         }
 
+        // Don't lose track of the observer, if any.
+        helper.observableStyleMap = styleObserver;
+
         return helper;
     }
 
@@ -524,6 +543,23 @@
 
     }
 
+    ObservableMap<StyleableProperty<?>, List<Style>> observableStyleMap;
+     /**
+      * RT-17293
+      */
+     ObservableMap<StyleableProperty<?>, List<Style>> getObservableStyleMap() {
+         return (observableStyleMap != null)
+             ? observableStyleMap
+             : FXCollections.<StyleableProperty<?>, List<Style>>emptyObservableMap();
+     }
+
+     /**
+      * RT-17293
+      */
+     void setObservableStyleMap(ObservableMap<StyleableProperty<?>, List<Style>> observableStyleMap) {
+         this.observableStyleMap = observableStyleMap;
+     }
+
     /**
      * Called by the Node whenever it has transitioned from one set of
      * pseudo-class states to another. This function will then lookup the
@@ -612,6 +648,13 @@
             final CssMetaData<Styleable,Object> cssMetaData =
                     (CssMetaData<Styleable,Object>)styleables.get(n);
 
+            if (observableStyleMap != null) {
+                final StyleableProperty styleableProperty = cssMetaData.getStyleableProperty(node);
+                if (styleableProperty != null && observableStyleMap.containsKey(styleableProperty)) {
+                    observableStyleMap.remove(styleableProperty);
+                }
+            }
+
             // Don't bother looking up styles that don't inherit.
             if (inheritOnly && cssMetaData.isInherits() == false) {
                 continue;
@@ -751,6 +794,12 @@
 
                 }
 
+                if (observableStyleMap != null) {
+
+                    List<Style> styleList = getMatchingStyles(node, cssMetaData, true);
+                    observableStyleMap.put(styleableProperty, styleList);
+                }
+
             } catch (Exception e) {
 
                 // RT-27155: if setting value raises exception, reset value
@@ -1923,50 +1972,16 @@
 
 
     /**
-     * Called from Node impl_getMatchingStyles
+     * Called from CssMetaData getMatchingStyles
      * @param node
      * @param styleableProperty
      * @return
      */
-    static List<Style> getMatchingStyles(final Styleable styleable, final CssMetaData styleableProperty) {
-
-        if (!(styleable instanceof Node)) return Collections.<Style>emptyList();
-
-        Node node = (Node)styleable;
-        final CssStyleHelper helper = (node.styleHelper != null) ? node.styleHelper : createStyleHelper(node, null);
-
-        if (helper != null) {
-            return helper.getMatchingStyles(node, styleableProperty, false);
-        }
-        else {
-            return Collections.<Style>emptyList();
-        }
+    List<Style> getMatchingStyles(final Styleable node, final CssMetaData styleableProperty) {
+        return getMatchingStyles(node, styleableProperty, false);
     }
 
-    static Map<StyleableProperty<?>, List<Style>> getMatchingStyles(Map<StyleableProperty<?>, List<Style>> map, final Node node) {
-
-        final CssStyleHelper helper = (node.styleHelper != null) ? node.styleHelper : createStyleHelper(node, null);
-        if (helper != null) {
-            if (map == null) map = new HashMap<>();
-            for (CssMetaData metaData : node.getCssMetaData()) {
-                List<Style> styleList = helper.getMatchingStyles(node, metaData, true);
-                if (styleList != null && !styleList.isEmpty()) {
-                    StyleableProperty prop = metaData.getStyleableProperty(node);
-                    map.put(prop, styleList);
-                }
-            }
-        }
-
-        if (node instanceof Parent) {
-            for (Node child : ((Parent)node).getChildren()) {
-                map = getMatchingStyles(map, child);
-            }
-        }
-
-        return map;
-    }
-
-    private List<Style> getMatchingStyles(final Styleable node, final CssMetaData styleableProperty, boolean matchState) {
+    List<Style> getMatchingStyles(final Styleable node, final CssMetaData styleableProperty, boolean matchState) {
 
         final List<CascadingStyle> styleList = new ArrayList<CascadingStyle>();
 
--- a/modules/graphics/src/main/java/javafx/scene/Node.java	Thu Mar 13 12:56:00 2014 -0400
+++ b/modules/graphics/src/main/java/javafx/scene/Node.java	Thu Mar 13 14:32:36 2014 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, 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
@@ -104,7 +104,6 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import com.sun.javafx.Logging;
 import com.sun.javafx.TempState;
@@ -8541,27 +8540,48 @@
      */
      @Deprecated // SB-dependency: RT-21096 has been filed to track this
     public static List<Style> impl_getMatchingStyles(CssMetaData cssMetaData, Styleable styleable) {
-         return CssStyleHelper.getMatchingStyles(styleable, cssMetaData);
-    }
-
-    /**
-     * Find CSS styles that were used to style this Node in its current pseudo-class state. The map will contain the styles from this node and,
-     * if the node is a Parent, its children. The node corresponding to an entry in the Map can be obtained by casting a StyleableProperty key to a
-     * javafx.beans.property.Property and calling getBean(). The List<Style> contains only those styles used to style the property and will contain
-     * styles used to resolve lookup values.
-     *
-     * @param  styleMap A Map to be populated with the styles. If null, a new Map will be allocated.
-     * @return The Map populated with matching styles.
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
-     */
-    @Deprecated // SB-dependency: RT-21096 has been filed to track this
-     public Map<StyleableProperty<?>,List<Style>> impl_findStyles(Map<StyleableProperty<?>,List<Style>> styleMap) {
-
-        Map<StyleableProperty<?>,List<Style>> ret = CssStyleHelper.getMatchingStyles(styleMap, this);
-        return ret != null ? ret : Collections.<StyleableProperty<?>,List<Style>>emptyMap();
-
-    }
+        if (styleable != null && cssMetaData != null && styleable instanceof Node) {
+
+            Node node = (Node)styleable;
+
+            if (node.styleHelper != null) {
+                return node.styleHelper.getMatchingStyles(node, cssMetaData);
+            }
+
+        }
+        return Collections.<Style>emptyList();
+    }
+
+     /**
+      * RT-17293
+      * @treatAsPrivate implementation detail
+      * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
+      */
+     @Deprecated // SB-dependency: RT-21096 has been filed to track this
+     public final ObservableMap<StyleableProperty<?>, List<Style>> impl_getStyleMap() {
+         return styleHelper != null
+             ? styleHelper.getObservableStyleMap()
+             : FXCollections.<StyleableProperty<?>, List<Style>>emptyObservableMap();
+     }
+
+     /**
+      * RT-17293
+      * @treatAsPrivate implementation detail
+      * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
+      */
+     @Deprecated // SB-dependency: RT-21096 has been filed to track this
+     public final void impl_setStyleMap(ObservableMap<StyleableProperty<?>, List<Style>> styleMap) {
+         //
+         // Node doesn't have a field for this map. Rather, this is held by CssStyleHelper. If this node
+         // doesn't have a styleHelper, then there is nothing to attach the listener to. So a styleHelper has
+         // to be created.
+         //
+         if (styleHelper == null) {
+             styleHelper = CssStyleHelper.createStyleHelper(this, null, styleMap);
+         } else {
+             styleHelper.setObservableStyleMap(styleMap);
+         }
+     }
 
     /**
      * Flags used to indicate in which way this node is dirty (or whether it
@@ -8866,8 +8886,11 @@
                 return;
             }
 
+            ObservableMap<StyleableProperty<?>, List<Style>> styleObserver =
+                    styleHelper != null ? styleHelper.observableStyleMap : null;
+
             // Match new styles if my own indicates I need to reapply
-            styleHelper = CssStyleHelper.createStyleHelper(this, cacheHint);
+            styleHelper = CssStyleHelper.createStyleHelper(this, cacheHint, styleObserver);
 
         }
 
--- a/modules/graphics/src/test/java/com/sun/javafx/css/Node_cssStyleMap_Test.java	Thu Mar 13 12:56:00 2014 -0400
+++ b/modules/graphics/src/test/java/com/sun/javafx/css/Node_cssStyleMap_Test.java	Thu Mar 13 14:32:36 2014 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
@@ -33,14 +33,11 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
-import javafx.beans.property.Property;
 import javafx.collections.FXCollections;
 import javafx.collections.MapChangeListener;
 import javafx.css.CssMetaData;
 import javafx.css.ParsedValue;
 import javafx.css.StyleOrigin;
-import javafx.css.Styleable;
 import javafx.css.StyleableProperty;
 import javafx.scene.Group;
 import javafx.scene.Node;
@@ -52,7 +49,6 @@
 import javafx.stage.Stage;
 import static org.junit.Assert.*;
 
-import javafx.util.Pair;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -62,142 +58,153 @@
     }
 
     boolean disabled = false;
+    int nadds = 0;
+    int nremoves = 0;
 
-    private void checkFoundStyle(Property<?> property, Map<StyleableProperty<?>, List<Style>> map, List<Declaration> decls) {
-
-        List<Style> styles = map.get(property);
-        assert (styles != null && !styles.isEmpty());
-
-        String pname = ((StyleableProperty<?>)property).getCssMetaData().getProperty();
-        Declaration declaration = null;
-        for(Declaration decl : decls) {
-            if (pname.equals(decl.getProperty())) {
-                declaration = decl;
-                break;
-            }
+    static List<CascadingStyle> createStyleList(List<Declaration> decls) {
+        
+        final List<CascadingStyle> styles = new ArrayList<CascadingStyle>();
+        
+        for (Declaration decl : decls) {
+            styles.add(
+                new CascadingStyle(
+                    new Style(decl.rule.getUnobservedSelectorList().get(0), decl),
+                    new PseudoClassState(),
+                    0, 
+                    0
+                )
+            );
         }
-        assertNotNull(pname, declaration);
-
-        Style style = null;
-        for(Style s : styles) {
-            if (pname.equals(s.getDeclaration().getProperty())) {
-                style = s;
-                break;
-            }
-        }
-        assertNotNull(pname, style);
-
-        assert(style.getDeclaration() == declaration);
-
+        
+        return styles;
     }
     
-    @Test
-    public void testStyleMap() {
-
+    static Map<String, List<CascadingStyle>> createStyleMap(List<CascadingStyle> styles) {
+        
+        final Map<String, List<CascadingStyle>> smap = 
+            new HashMap<String, List<CascadingStyle>>();
+        
+        final int max = styles != null ? styles.size() : 0;
+        for (int i=0; i<max; i++) {
+            final CascadingStyle style = styles.get(i);
+            final String property = style.getProperty();
+            // This is carefully written to use the minimal amount of hashing.
+            List<CascadingStyle> list = smap.get(property);
+            if (list == null) {
+                list = new ArrayList<CascadingStyle>(5);
+                smap.put(property, list);
+            }
+            list.add(style);
+        }
+        return smap;
+    }
+    
+    @Test @Ignore ("Pending RT-34463")
+    public void testStyleMapTracksChanges() {
+                
         final List<Declaration> declsNoState = new ArrayList<Declaration>();
-        Collections.addAll(declsNoState,
+        Collections.addAll(declsNoState, 
             new Declaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.RED, null), false),
             new Declaration("-fx-stroke", new ParsedValueImpl<Color,Color>(Color.YELLOW, null), false),
             new Declaration("-fx-stroke-width", new ParsedValueImpl<ParsedValue<?,Size>,Number>(
-                new ParsedValueImpl<Size,Size>(new Size(3d, SizeUnits.PX), null),
+                new ParsedValueImpl<Size,Size>(new Size(3d, SizeUnits.PX), null), 
                 SizeConverter.getInstance()), false)
         );
-
-
+        
+        
         final List<Selector> selsNoState = new ArrayList<Selector>();
-        Collections.addAll(selsNoState,
+        Collections.addAll(selsNoState, 
             Selector.createSelector(".rect")
         );
-
-        Rule rule = new Rule(selsNoState, declsNoState);
-
-        Stylesheet stylesheet = new Stylesheet("testStyleMap");
+        
+        Rule rule = new Rule(selsNoState, declsNoState);        
+        
+        Stylesheet stylesheet = new Stylesheet("testStyleMapTracksChanges");
         stylesheet.setOrigin(StyleOrigin.USER_AGENT);
         stylesheet.getRules().add(rule);
-
+        
         final List<Declaration> declsDisabledState = new ArrayList<Declaration>();
-        Collections.addAll(declsDisabledState,
+        Collections.addAll(declsDisabledState, 
             new Declaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.GRAY, null), false),
             new Declaration("-fx-stroke", new ParsedValueImpl<Color,Color>(Color.DARKGRAY, null), false)
         );
-
+        
         final List<Selector> selsDisabledState = new ArrayList<Selector>();
-        Collections.addAll(selsDisabledState,
+        Collections.addAll(selsDisabledState, 
             Selector.createSelector(".rect:disabled")
         );
-
-        rule = new Rule(selsDisabledState, declsDisabledState);
+        
+        rule = new Rule(selsDisabledState, declsDisabledState);        
         stylesheet.getRules().add(rule);
-
+        
+        final List<CascadingStyle> stylesNoState = createStyleList(declsNoState);
+        final List<CascadingStyle> stylesDisabledState = createStyleList(declsDisabledState);
+        
+        // add to this list on wasAdded, check bean on wasRemoved.
+        final List<StyleableProperty<?>> beans = new ArrayList<StyleableProperty<?>>();
         Rectangle rect = new Rectangle(50,50);
         rect.getStyleClass().add("rect");
+        rect.impl_setStyleMap(FXCollections.observableMap(new HashMap<StyleableProperty<?>, List<Style>>()));
+        rect.impl_getStyleMap().addListener(new MapChangeListener<StyleableProperty, List<Style>>() {
+
+            public void onChanged(MapChangeListener.Change<? extends StyleableProperty, ? extends List<Style>> change) {
+
+                if (change.wasAdded()) {
+                    
+                    List<Style> styles = change.getValueAdded();
+                    for (Style style : styles) {
+
+                        // stroke width comes from ".rect" even for disabled state.
+                        if (disabled == false || "-fx-stroke-width".equals(style.getDeclaration().getProperty())) {
+                            assertTrue(style.getDeclaration().toString(),declsNoState.contains(style.getDeclaration()));
+                            assertTrue(style.getSelector().toString(),selsNoState.contains(style.getSelector()));
+                        } else {
+                            assertTrue(style.getDeclaration().toString(),declsDisabledState.contains(style.getDeclaration()));
+                            assertTrue(style.getSelector().toString(),selsDisabledState.contains(style.getSelector()));                            
+                        }
+                        Object value = style.getDeclaration().parsedValue.convert(null);
+                        StyleableProperty styleableProperty = change.getKey();
+                        beans.add(styleableProperty);
+                        assertEquals(styleableProperty.getValue(), value);
+                        nadds += 1;                        
+                    }
+                    
+                } if (change.wasRemoved()) {
+                    StyleableProperty styleableProperty = change.getKey();
+                    assert(beans.contains(styleableProperty));
+                    nremoves += 1;
+                }
+            }
+        });
 
         Group root = new Group();
         root.getChildren().add(rect);
-        StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
+        StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);        
         Scene scene = new Scene(root);
+        Stage stage = new Stage();
+        stage.setScene(scene);
+        stage.show();
 
-        rect.applyCss();
-
-        Map<StyleableProperty<?>, List<Style>> map = rect.impl_findStyles(null);
-        assert (map != null && !map.isEmpty());
-
-        checkFoundStyle(rect.fillProperty(), map, declsNoState);
-        checkFoundStyle(rect.strokeProperty(), map, declsNoState);
-        checkFoundStyle(rect.strokeWidthProperty(), map, declsNoState);
+        // The three no state styles should be applied
+        assertEquals(3, nadds);
+        assertEquals(0, nremoves);
 
         rect.setDisable(true);
-        rect.applyCss();
-
-        map = rect.impl_findStyles(null);
-        assert (map != null && !map.isEmpty());
-
-        checkFoundStyle(rect.fillProperty(), map, declsDisabledState);
-        checkFoundStyle(rect.strokeProperty(), map, declsDisabledState);
-        checkFoundStyle(rect.strokeWidthProperty(), map, declsNoState);
-
+        disabled = true;
+        nadds = 0;
+        nremoves = 0;
+        
+        Toolkit.getToolkit().firePulse();
+        
+        // The three no state styles should be removed and the 
+        // two disabled state styles plus the stroke width style 
+        // should be applied. 
+        assertEquals(3, nadds);
+        assertEquals(3, nremoves);
+        
     }
-
-    @Test
-    public void testStyleMapChildren() {
-
-        final List<Declaration> declsNoState = new ArrayList<Declaration>();
-        Collections.addAll(declsNoState,
-                new Declaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.RED, null), false)
-        );
-
-        final List<Selector> selsNoState = new ArrayList<Selector>();
-        Collections.addAll(selsNoState,
-                Selector.createSelector(".rect")
-        );
-
-        Rule rule = new Rule(selsNoState, declsNoState);
-
-        Stylesheet stylesheet = new Stylesheet("testStyleMapChildren");
-        stylesheet.setOrigin(StyleOrigin.USER_AGENT);
-        stylesheet.getRules().add(rule);
-
-        Rectangle rect = new Rectangle(50,50);
-        rect.getStyleClass().add("rect");
-
-        Group root = new Group();
-        Group group = new Group();
-        root.getChildren().add(group);
-        group.getChildren().add(rect);
-        StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
-        Scene scene = new Scene(root);
-
-        root.applyCss();
-
-        // Even though root and group have no styles, the styles for rect should still be found
-        Map<StyleableProperty<?>, List<Style>> map = root.impl_findStyles(null);
-        assert (map != null && !map.isEmpty());
-
-        checkFoundStyle(rect.fillProperty(), map, declsNoState);
-
-    }
-
-    @Test
+    
+    @Test @Ignore ("Pending RT-34463")
     public void testRT_21212() {
 
         final List<Declaration> rootDecls = new ArrayList<Declaration>();
@@ -218,6 +225,11 @@
         stylesheet.setOrigin(StyleOrigin.USER_AGENT);
         stylesheet.getRules().add(rootRule);
 
+        final List<CascadingStyle> rootStyles = createStyleList(rootDecls);
+        final Map<String,List<CascadingStyle>> rootStyleMap = createStyleMap(rootStyles);
+        final Map<StyleCache.Key, StyleCache> styleCache = 
+            new HashMap<StyleCache.Key, StyleCache>();
+        
         Group group = new Group();
         group.getStyleClass().add("root");
         
@@ -245,19 +257,42 @@
         Rule textRule = new Rule(textSels, textDecls);        
         stylesheet.getRules().add(textRule);
                 
+        final List<CascadingStyle> styles = createStyleList(textDecls);
+        final Map<String,List<CascadingStyle>> styleMap = createStyleMap(styles);
+        final Map<String,List<CascadingStyle>> emptyMap = createStyleMap(null);
+
         Text text = new Text("HelloWorld");
-        text.getStyleClass().add("text");
         group.getChildren().add(text);
 
-        StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
+        final List<Declaration> expecteds = new ArrayList<Declaration>();
+        expecteds.addAll(rootDecls);
+        expecteds.addAll(textDecls);
+        text.getStyleClass().add("text");
+        text.impl_setStyleMap(FXCollections.observableMap(new HashMap<StyleableProperty<?>, List<Style>>()));
+        text.impl_getStyleMap().addListener(new MapChangeListener<StyleableProperty, List<Style>>() {
+
+            // a little different than the other tests since we should end up 
+            // with font and font-size in the map and nothing else. After all 
+            // the changes have been handled, the expecteds list should be empty.
+            public void onChanged(MapChangeListener.Change<? extends StyleableProperty, ? extends List<Style>> change) {
+                if (change.wasAdded()) {
+                    List<Style> styles = change.getValueAdded();
+                    for (Style style : styles) {
+                        assertTrue(expecteds.contains(style.getDeclaration()));
+                        expecteds.remove(style.getDeclaration());
+                    }
+                }
+            }
+        });
+             
+        StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);        
         Scene scene = new Scene(group);
+        Stage stage = new Stage();
+        stage.setScene(scene);
+        stage.show();
 
-        text.applyCss();
-
-        Map<StyleableProperty<?>, List<Style>> map = text.impl_findStyles(null);
-        assert (map != null && !map.isEmpty());
-
-        checkFoundStyle(text.fontProperty(), map, textDecls);
+        assertEquals(18, text.getFont().getSize(),0);
+        assertTrue(Integer.toString(expecteds.size()), expecteds.isEmpty());
 
     }