package leigh.mecha.javafx;

import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import org.apache.commons.lang.StringUtils;

/**
 * This class provides the ability to measure JFX nodes before they are visible on the screen. This is useful for
 * implementing layout managers which must know the render size of the node prior to rendering the node onto the
 * screen.
 *
 * @author Alex Leigh
 * @since mk14 mod19 (CRYSTAL)
 */
public class NodeRuler {
    private static final String WIDE_CHAR = "w";
    /**
     * Attempt to measure the given JFX node. The bounds that is returned will contain a width and height for the
     * element. This method should not be called on nodes which are already part of a {@link Scene}.
     */
    public static Bounds measure(Node node) {
        Group root = new Group();

        // Even though this appears unused, it is magical. Do not remove it.
        Scene s = new Scene(root);
        root.getChildren().add(node);

        root.applyCss();
        root.layout();

        return node.getLayoutBounds();
    }

    public static double measureTextWidth(String str) {
        final Text text = new Text(str);
        new Scene(new Group(text));
        text.applyCss();
        return text.getLayoutBounds().getWidth();
    }

    public static double measureTextWidth(int chars) {
        return measureTextWidth(StringUtils.repeat(WIDE_CHAR, chars));
    }
}
