modules/graphics/src/main/java/javafx/scene/layout/Region.java

Print this page

        

@@ -64,11 +64,13 @@
 import com.sun.javafx.css.converters.InsetsConverter;
 import com.sun.javafx.css.converters.ShapeConverter;
 import com.sun.javafx.css.converters.SizeConverter;
 import com.sun.javafx.geom.BaseBounds;
 import com.sun.javafx.geom.PickRay;
+import com.sun.javafx.geom.RectBounds;
 import com.sun.javafx.geom.Vec2d;
+import com.sun.javafx.geom.transform.Affine2D;
 import com.sun.javafx.geom.transform.BaseTransform;
 import com.sun.javafx.scene.DirtyBits;
 import com.sun.javafx.scene.input.PickResultChooser;
 import com.sun.javafx.sg.prism.NGNode;
 import com.sun.javafx.sg.prism.NGRegion;

@@ -865,10 +867,11 @@
         // is now going to recompute the width eagerly. The cost of excessive and
         // unnecessary bounds changes, however, is relatively high.
         if (value != _width) {
             _width = value;
             boundingBox = null;
+            scaledShape = null;
             impl_layoutBoundsChanged();
             impl_geomChanged();
             impl_markDirty(DirtyBits.NODE_GEOMETRY);
             setNeedsLayout(true);
             requestParentLayout();

@@ -923,10 +926,12 @@
             // it previously held. If this is the case, we want to avoid excessive layouts.
             // Note that I have biased this for layout over binding, because the heightProperty
             // is now going to recompute the height eagerly. The cost of excessive and
             // unnecessary bounds changes, however, is relatively high.
             boundingBox = null;
+            // Scaled shape might depend on width/height if it's centered or scaled.
+            scaledShape = null;
             // Note: although impl_geomChanged will usually also invalidate the
             // layout bounds, that is not the case for Regions, and both must
             // be called separately.
             impl_geomChanged();
             impl_layoutBoundsChanged();

@@ -1238,15 +1243,17 @@
                     // we therefore need to fire that the insets value may have changed.
                     insets.fireValueChanged();
                 }
                 // Update our reference to the old shape
                 _shape = value;
+                scaledShape = null;
             }
         }
 
         @Override public void run() {
             impl_geomChanged();
+            scaledShape = null;
             impl_markDirty(DirtyBits.REGION_SHAPE);
         }
     };
 
     /**

@@ -1270,10 +1277,11 @@
                 @Override public CssMetaData<Region, Boolean> getCssMetaData() {
                     return StyleableProperties.SCALE_SHAPE;
                 }
                 @Override public void invalidated() {
                     impl_geomChanged();
+                    scaledShape = null;
                     impl_markDirty(DirtyBits.REGION_SHAPE);
                 }
             };
         }
         return scaleShape;

@@ -1299,10 +1307,11 @@
                 @Override public CssMetaData<Region, Boolean> getCssMetaData() {
                     return StyleableProperties.POSITION_SHAPE;
                 }
                 @Override public void invalidated() {
                     impl_geomChanged();
+                    scaledShape = null;
                     impl_markDirty(DirtyBits.REGION_SHAPE);
                 }
             };
         }
         return centerShape;

@@ -2456,10 +2465,20 @@
     /** @treatAsPrivate */
     @Override public NGNode impl_createPeer() {
         return new NGRegion();
     }
 
+    private com.sun.javafx.geom.Shape scaledShape;
+    
+    private com.sun.javafx.geom.Shape getShapeScaledAndPositioned() {
+        if (scaledShape == null) {
+             scaledShape = NGRegion.resizeShape(_shape.impl_configShape(), isScaleShape(), isCenterShape(),
+                    (float)getWidth(), (float)getHeight(), 0f,0f,0f,0f);
+        }
+        return scaledShape;
+    }
+    
     /**
      * @treatAsPrivate implementation detail
      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
      */
     @Deprecated

@@ -2475,19 +2494,13 @@
         final double y2 = getHeight();
         // Figure out what the maximum possible radius value is.
         final double maxRadius = Math.min(x2 / 2.0, y2 / 2.0);
 
         // First check the shape. Shape could be impacted by scaleShape & positionShape properties.
-        // This is going to be ugly! The problem is that basically all the scale / position operations
-        // have to be implemented here in Region, whereas right now they are all implemented in
-        // NGRegion. Drat. Basically I can't implement this properly until I have a way to get the
-        // geometry backing an arbitrary FX shape. For example, in this case I need an NGShape peer
-        // of this shape so that I can resize it as appropriate for these picking tests.
-        // Lacking that, for now, I will simply check the shape (so that picking works for pie charts)
-        // Bug is filed as RT-27775.
+        // We are calling NGRegion static method here because we lack a better place for the code.
         if (_shape != null) {
-            return _shape.contains(localX, localY);
+            return getShapeScaledAndPositioned().contains((float)localX, (float)localY);
         }
 
         // OK, there was no background shape, so I'm going to work on the principle of
         // nested rounded rectangles. We'll start by checking the backgrounds. The
         // first background which passes the test is good enough for us!