changeset 1432:cefe52608b67

RT-20643: add Scene to CssError and Node to CssError.PropertySetError
author David Grieve<david.grieve@oracle.com>
date Tue, 10 Jul 2012 20:22:00 -0400
parents 302ba4698b33
children 30b375f0ad85
files javafx-ui-common/src/com/sun/javafx/css/CssError.java javafx-ui-common/src/com/sun/javafx/css/StyleHelper.java javafx-ui-common/src/com/sun/javafx/css/StyleManager.java javafx-ui-controls/src/javafx/scene/control/Control.java
diffstat 4 files changed, 115 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-common/src/com/sun/javafx/css/CssError.java	Tue Jul 10 20:19:59 2012 -0400
+++ b/javafx-ui-common/src/com/sun/javafx/css/CssError.java	Tue Jul 10 20:22:00 2012 -0400
@@ -25,7 +25,11 @@
 
 package com.sun.javafx.css;
 
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 import java.net.URL;
+import javafx.scene.Node;
+import javafx.scene.Scene;
 
 /**
  * Encapsulate information about the source and nature of errors encountered
@@ -33,15 +37,51 @@
  */
 public class CssError {
  
-    /** The error message from the CSS code */
+    // RT-20643 - hold a ref so CssError doesn't leak Scene.
+    private static Reference<Scene> SCENE_REF;
+            
+    /** 
+     * Set the static scene variable. This scene will be set on all CssErrors
+     * generated after the call is made. The argument may be null. Null should
+     * be passed when the code exits a method from which CssErrors may be 
+     * created. This is intended internal use and should not be called from
+     * outside the css code.
+     */
+    public static void setCurrentScene(Scene scene) {
+        
+        if (scene != null) {
+            // don't make new ref for same scene
+            final Scene oldScene = SCENE_REF != null ? SCENE_REF.get() : null;
+            if (oldScene != scene) {
+                SCENE_REF = new WeakReference<Scene>(scene);
+            }
+        } else {
+            SCENE_REF = null;
+        }
+    }
+    
+    /** @return The error message from the CSS code. */
     public final String getMessage() {
         return message;
     }
-        
+
     public CssError(String message) {
         this.message = message;
+        // RT-20643        
+        this.sceneRef = SCENE_REF;
     }
     
+    /** 
+     * @return The Scene in which this error occurred, if known, or null.
+     */
+    public Scene getScene() {
+        return sceneRef != null ? sceneRef.get() : null;
+    }
+    
+    // RT-20643 - track the scene that this error belongs to       
+    // Note that CssError has the potential to leak Scene so the Scene
+    // variable is held as a Reference.
+    private final Reference<Scene> sceneRef;
     protected final String message;
 
     @Override
@@ -125,14 +165,14 @@
     public final static class PropertySetError extends CssError { 
         
         public PropertySetError(StyleableProperty styleableProperty, 
-                Styleable styleable, String message) {
+                Node node, String message) {
             super(message);
             this.styleableProperty = styleableProperty;
-            this.styleable = styleable;
+            this.node = node;
         }
         
-        public Styleable getStyleable() {
-            return styleable;
+        public Node getNode() {
+            return node;
         }
         
         public StyleableProperty getProperty() {
@@ -140,7 +180,7 @@
         }
         
         private final StyleableProperty styleableProperty;
-        private final Styleable styleable;
+        private final Node node;
         
     }
 }     
--- a/javafx-ui-common/src/com/sun/javafx/css/StyleHelper.java	Tue Jul 10 20:19:59 2012 -0400
+++ b/javafx-ui-common/src/com/sun/javafx/css/StyleHelper.java	Tue Jul 10 20:22:00 2012 -0400
@@ -782,6 +782,9 @@
         // Used in the for loop below, and a convenient place to stop when debugging.
         final int max = styleables.size();
 
+        // RT-20643
+        CssError.setCurrentScene(node.getScene());
+        
         // For each property that is settable, we need to do a lookup and
         // transition to that value.
         for(int n=0; n<max; n++) {
@@ -883,7 +886,7 @@
                     List<CssError> errors = null;
                     if ((errors = StyleManager.getInstance().getErrors()) != null) {
                         final String msg = String.format("Failed to set css [%s] due to %s\n", styleable, e.getMessage());
-                        final CssError error = new CssError.PropertySetError(styleable, node.impl_getStyleable(), msg);
+                        final CssError error = new CssError.PropertySetError(styleable, node, msg);
                         errors.add(error);
                     }
                     // TODO: use logger here
@@ -894,6 +897,10 @@
                 }
 
             }
+        
+        // RT-20643
+        CssError.setCurrentScene(null);
+
         // If the list weren't empty, we'd worry about animations at this
         // point. TODO need to implement animation trickery here
     }
@@ -1064,7 +1071,7 @@
                     final String msg = formatExceptionMessage(node, styleable, style.getStyle(), cce);
                     List<CssError> errors = null;
                     if ((errors = StyleManager.getInstance().getErrors()) != null) {
-                        final CssError error = new CssError.PropertySetError(styleable, node.impl_getStyleable(), msg);
+                        final CssError error = new CssError.PropertySetError(styleable, node, msg);
                         errors.add(error);
                     }
                     if (LOGGER.isLoggable(PlatformLogger.WARNING)) {
@@ -1512,7 +1519,7 @@
                 final String msg = formatUnresolvedLookupMessage(node, styleable, style.getStyle(),resolved);
                 List<CssError> errors = null;
                 if ((errors = StyleManager.getInstance().getErrors()) != null) {
-                    final CssError error = new CssError.PropertySetError(styleable, node.impl_getStyleable(), msg);
+                    final CssError error = new CssError.PropertySetError(styleable, node, msg);
                     errors.add(error);
                 }
                 if (LOGGER.isLoggable(PlatformLogger.WARNING)) {
@@ -1526,7 +1533,7 @@
                 final String msg = formatExceptionMessage(node, styleable, style.getStyle(), iae);
                 List<CssError> errors = null;
                 if ((errors = StyleManager.getInstance().getErrors()) != null) {
-                    final CssError error = new CssError.PropertySetError(styleable, node.impl_getStyleable(), msg);
+                    final CssError error = new CssError.PropertySetError(styleable, node, msg);
                     errors.add(error);
                 }
                 if (LOGGER.isLoggable(PlatformLogger.WARNING)) {
@@ -1539,7 +1546,7 @@
                 final String msg = formatExceptionMessage(node, styleable, style.getStyle(), npe);
                 List<CssError> errors = null;
                 if ((errors = StyleManager.getInstance().getErrors()) != null) {
-                    final CssError error = new CssError.PropertySetError(styleable, node.impl_getStyleable(), msg);
+                    final CssError error = new CssError.PropertySetError(styleable, node, msg);
                     errors.add(error);
                 }
                 if (LOGGER.isLoggable(PlatformLogger.WARNING)) {
--- a/javafx-ui-common/src/com/sun/javafx/css/StyleManager.java	Tue Jul 10 20:19:59 2012 -0400
+++ b/javafx-ui-common/src/com/sun/javafx/css/StyleManager.java	Tue Jul 10 20:22:00 2012 -0400
@@ -636,16 +636,31 @@
     
     /**
      * Add a user agent stylesheet, possibly overriding styles in the default
-     * user agent stylesheet. The node argument must be an instance of Control.
+     * user agent stylesheet.
      *
      * @param fname The file URL, either relative or absolute, as a String.
      */
     public void addUserAgentStylesheet(String fname) {
+        addUserAgentStylesheet(null, fname);
+    }
+    
+    /**
+     * Add a user agent stylesheet, possibly overriding styles in the default
+     * user agent stylesheet.
+     * @param scene Only used in CssError for tracking back to the scene that loaded the stylesheet
+     * @param fname  The file URL, either relative or absolute, as a String.
+     */
+    // For RT-20643    
+    public void addUserAgentStylesheet(Scene scene, String fname) {
                 
         // nothing to add
         if (fname == null ||  fname.trim().isEmpty()) return;
 
         if (userAgentStylesheetMap.containsKey(fname) == false) {
+
+            // RT-20643
+            CssError.setCurrentScene(scene);
+            
             Stylesheet ua_stylesheet = loadStylesheet(fname);
             ua_stylesheet.setOrigin(Stylesheet.Origin.USER_AGENT);
             userAgentStylesheetMap.put(fname, ua_stylesheet);
@@ -653,6 +668,9 @@
             if (ua_stylesheet != null) {
                 userAgentStylesheetsChanged();                
             }
+            
+            // RT-20643
+            CssError.setCurrentScene(null);
         }
 
     }
@@ -663,15 +681,31 @@
      * @param fname The file URL, either relative or absolute, as a String.
      */
     public void setDefaultUserAgentStylesheet(String fname) {
+        setDefaultUserAgentStylesheet(null, fname);
+    }
+    
+    /**
+     * Set the default user agent stylesheet
+     * @param scene Only used in CssError for tracking back to the scene that loaded the stylesheet
+     * @param fname  The file URL, either relative or absolute, as a String.
+     */
+    // For RT-20643
+    public void setDefaultUserAgentStylesheet(Scene scene, String fname) {
 
         if (fname == null || fname.trim().isEmpty())
             throw new IllegalArgumentException("null arg fname");
 
+        // RT-20643
+        CssError.setCurrentScene(scene);
+        
         Stylesheet ua_stylesheet = loadStylesheet(fname);
         if (ua_stylesheet != null) {
             ua_stylesheet.setOrigin(Stylesheet.Origin.USER_AGENT);
             setDefaultUserAgentStylesheet(ua_stylesheet);
         } 
+        
+        // RT-20643
+        CssError.setCurrentScene(null);
 
     }
     
@@ -811,6 +845,9 @@
         // if there are no stylesheets, then they were probably all removed.
         if (scene.getStylesheets().size() == 0) return;
 
+        // RT-20643
+        CssError.setCurrentScene(scene);
+        
         // create the stylesheets, one per URL supplied
         final Collection<Stylesheet> stylesheets = new ArrayList<Stylesheet>();
         for (int i = 0; i < scene.getStylesheets().size(); i++) {
@@ -830,6 +867,9 @@
             }
         }
 
+        // RT-20643
+        CssError.setCurrentScene(scene);
+        
         // Look up existing user stylesheets and add new stylesheets.
         // We defer creation of the containerMap until needed
         if (containerMap == null) containerMap =
@@ -1347,12 +1387,26 @@
     }
 
     private ObservableList<CssError> errors = null;
+    /** 
+     * Errors that may have occurred during css processing. 
+     * This list is null until errorsProperty() is called.
+     * @return 
+     */
     public ObservableList<CssError> errorsProperty() {
         if (errors == null) {
             errors = FXCollections.observableArrayList();
         }
         return errors;
     }
+    
+    /** 
+     * Errors that may have occurred during css processing.
+     * This list is null until errorsProperty() is called and is used 
+     * internally to figure out whether or  not anyone is interested in 
+     * receiving CssError.
+     * Not meant for general use - call errorsProperty() instead. 
+     * @return 
+     */
     public ObservableList<CssError> getErrors() {
         return errors;
     }
--- a/javafx-ui-controls/src/javafx/scene/control/Control.java	Tue Jul 10 20:19:59 2012 -0400
+++ b/javafx-ui-controls/src/javafx/scene/control/Control.java	Tue Jul 10 20:22:00 2012 -0400
@@ -1096,7 +1096,7 @@
     @Deprecated
     @Override public void impl_processCSS(boolean reapply) {
         if (reapply && getUserAgentStylesheet() != null) {
-            StyleManager.getInstance().addUserAgentStylesheet(getUserAgentStylesheet());
+            StyleManager.getInstance().addUserAgentStylesheet(getScene(), getUserAgentStylesheet());
         }
 
         super.impl_processCSS(reapply);