Get the size of a scene to which a custom control is added at the control's class definition
<p>I have a ripple button that once it's clicked, plays a ripple effect animation.
Inside of the button's skin, there's a <code>Circle</code> whose opacity is set to <code>0</code> at the beginning of the execution of the program and once the button is clicked, the opacity is set to <code>1</code> and the radius of the button gets larger.</p>

<p>There is a <code>DoubleBinding</code> binding, whose definition is the following:</p>

<pre><code>DoubleBinding circleRippleRadius = new DoubleBinding() {
            {
                bind(heightProperty(), widthProperty()); // Sets the parameters of the bind method.
            }

            @Override // Overrides the computeValue method, which computes the value of the binding.
            protected double computeValue() {
                return Math.max(heightProperty().get(), widthProperty().get()); // Return the greatest of both numbers
            }
        };
</code></pre>

<p>Instead of using the button's <code>heightProperty</code> and <code>widthProperty</code> properties, I'd like to use the height and width of the scene to which the button is added, since I want the circle that appears once the button is clicked to fill the entire screen.</p>

<p>How could I achieve this?</p>

<p><strong>UPDATE</strong>: Here is the code that defines the animation's component's values and the animation itself:</p>

<pre><code>    private void createRippleEffect(Circle circleRipple) {

            circleRipple.setOpacity(1.0); // Sets the opacity of the circleRipple to 0, since it must not be showed yet.

            /*Fade Transition*/
            FadeTransition fadeTransition = new FadeTransition(RIPPLE_DURATION, circleRipple);
            fadeTransition.setInterpolator(Interpolator.EASE_OUT);
            fadeTransition.setFromValue(1.0); // Sets the opacity to %100
            fadeTransition.setToValue(1.0); // The opacity doesn't change. 

            /*Scale Transition*/
            Timeline scaleRippleTimeline = new Timeline();

            NumberBinding circleRippleRadius = 
                    Bindings.max(Bindings.selectDouble(sceneProperty(), "width"),
                    Bindings.selectDouble(sceneProperty(), "height"));

            circleRippleRadius.addListener((ObservableValue&lt;? extends Number&gt; observable, Number oldValue, Number newValue) -&gt; { // Each time it changes
                KeyValue scaleValue = new KeyValue(circleRipple.radiusProperty(), newValue, Interpolator.EASE_OUT);
                KeyFrame scaleFrame = new KeyFrame(RIPPLE_DURATION, scaleValue);
                scaleRippleTimeline.getKeyFrames().add(scaleFrame);
            });

private void createRippleEffect(Circle circleRipple) {

        circleRipple.setOpacity(1.0); // Sets the opacity of the circleRipple to 0, since it must not be showed yet.

        /*Fade Transition*/
        FadeTransition fadeTransition = new FadeTransition(RIPPLE_DURATION, circleRipple);
        fadeTransition.setInterpolator(Interpolator.EASE_OUT);
        fadeTransition.setFromValue(1.0); // Sets the opacity to %100
        fadeTransition.setToValue(1.0); // The opacity doesn't change. 

        /*Scale Transition*/
        Timeline scaleRippleTimeline = new Timeline();

        NumberBinding circleRippleRadius = 
                Bindings.max(Bindings.selectDouble(sceneProperty(), "width"),
                Bindings.selectDouble(sceneProperty(), "height"));

        circleRippleRadius.addListener((ObservableValue&lt;? extends Number&gt; observable, Number oldValue, Number newValue) -&gt; { // Each time it changes
            KeyValue scaleValue = new KeyValue(circleRipple.radiusProperty(), newValue, Interpolator.EASE_OUT);
            KeyFrame scaleFrame = new KeyFrame(RIPPLE_DURATION, scaleValue);
            scaleRippleTimeline.getKeyFrames().add(scaleFrame);
        });

        SequentialTransition rippleTransition = new SequentialTransition(); // The circle must change its opacity and scale at the same time
        rippleTransition.getChildren().addAll(
                scaleRippleTimeline,
                fadeTransition
        );

        ParallelTransition parallelTransition = new ParallelTransition();

        getStyleClass().addListener((ListChangeListener.Change&lt;? extends String&gt; c) -&gt; { // Don't pay attention to this. The style changes if
                                                                                         // the CSS file has "toggle" or "flat" inside its list,
                                                                                         // but these are never added so it doesn't matter.
            if (c.getList().indexOf("flat") == -1 &amp;&amp; c.getList().indexOf("toggle") == -1) {
                setMinWidth(88);
                setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.30), 5, 0.10, 0, 2));
                parallelTransition.getChildren().addAll(rippleTransition); // parallelTransition is basically the same as rippleTransition, since
                                                                           // "toggle" and "flat" are never added to the CSS's list.
            } else {

                parallelTransition.getChildren().addAll(rippleTransition);
                setMinWidth(USE_COMPUTED_SIZE);
                setEffect(null);
            }
        });

        this.addEventHandler(MouseEvent.MOUSE_PRESSED, event -&gt; {
            parallelTransition.stop(); // In case that the parallelTransition is already running, stop it.
            circleRipple.setOpacity(0.0); // Sets the opacity of the circle to 0, since the animation must play from he beginning.
            circleRipple.setRadius(0.1); // Sets the radius to 0.1 for the same reason as the circle's opacity.
            circleRipple.setCenterX(event.getX()); // The center of the circle is the location in which the mouse was clicked.
            circleRipple.setCenterY(event.getY()); // The center of the circle is the location in which the mouse was clicked.
            parallelTransition.playFromStart(); // Plays the animation.

        });
    }
</code></pre>

<p>being this the method that defines the button's skin:</p>

<pre><code>@Override
    public Skin&lt;?&gt; createDefaultSkin() {
        ButtonSkin buttonSkin = getButtonSkin();
        if (buttonSkin == null) {
            buttonSkin = new ButtonSkin(this);
            Circle circleRipple = new Circle(0.1, RIPPLE_COLOR);
            buttonSkin.getChildren().add(0, circleRipple);
            setSkin(buttonSkin);

            createRippleEffect(circleRipple);
            getStyleClass().add("ripple-button"); // What the CSS does is changing the button's color and text size, nothing important.
        }
        return buttonSkin;
    }
</code></pre>

<p>Thanks in advance.</p>

<p><strong>SOLUTION</strong>:
The problem of the <code>circleRippleRadius</code>'s value being shorter than what the stage's one was probably due to that the stage's size was different than the scene's. I didn't know that, now I do.</p>

<p>For having the button's circle filling the entire screen, all I had to do was passing the <code>widthProperty</code> and <code>heightProperty</code> properties of the stage as parameters through the button's constructor.</p>

<p>Inside of the button's class, I create two <code>ReadOnlyDoubleProperty</code> properties for the width and the height that are empty until a button is created; in which case, the values of the defined <code>ReadOnlyDoubleProperty</code> properties are overwritten by the value of the <code>widthProperty</code> and <code>heightProperty</code> properties passed as parameters.</p>

<p>Having done that, all what I have to do is adding a listener to each property and changing the value of the <code>circleRippleRadius</code> to the greater of the properties' values each time that one of them changes.</p>