<commit_before>package com.athaydes.automaton

import com.athaydes.automaton.selector.*
import com.athaydes.internal.Config
import com.athaydes.internal.interceptor.ToFrontInterceptor
import com.sun.javafx.robot.impl.FXRobotHelper
import groovy.util.logging.Slf4j
import javafx.application.Application
import javafx.application.Platform
import javafx.scene.Node
import javafx.scene.Scene
import javafx.scene.control.TextInputControl
import javafx.scene.layout.VBox
import javafx.stage.Stage
import org.codehaus.groovy.runtime.InvokerHelper

import java.awt.*
import java.util.List
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.TimeUnit

import static com.athaydes.automaton.selector.StringSelectors.matchingAny

/**
 *
 * User: Renato
 */
class FXAutomaton extends Automaton<FXAutomaton> {

    private static instance

    /**
     * Get the singleton instance of FXAutomaton, which is lazily created.
     * @return FXAutomaton singleton instance
     */
    static synchronized FXAutomaton getUser() {
        if ( !instance ) instance = new FXAutomaton()
        instance
    }

    protected FXAutomaton() {}

    /**
     * Block until all events in the JavaFX Thread have been processed.
     */
    FXAutomaton waitForFxEvents() {
        FXApp.doInFXThreadBlocking {}
        this
    }

    FXAutomaton clickOn( Node node, Speed speed = DEFAULT ) {
        moveTo( node, speed ).click()
    }

    FXAutomaton clickOnNodes( Collection<Node> nodes, long pauseBetween = 100, Speed speed = DEFAULT ) {
        nodes.each { node -> clickOn( node, speed ).pause( pauseBetween ) }
        this
    }

    FXAutomaton doubleClickOn( Node node, Speed speed = DEFAULT ) {
        moveTo( node, speed ).doubleClick()
    }

    FXAutomaton doubleClickOnNodes( Collection<Node> nodes, long pauseBetween = 100, Speed speed = DEFAULT ) {
        nodes.each { node -> doubleClickOn( node, speed ).pause( pauseBetween ) }
        this
    }

    FXAutomaton moveTo( Node node, Speed speed = DEFAULT ) {
        moveTo( { centerOf( node ) }, speed )
    }

    FXAutomaton moveToNodes( Collection<Node> nodes, long pauseBetween = 100, Speed speed = DEFAULT ) {
        nodes.each { node -> moveTo( node, speed ).pause( pauseBetween ) }
        this
    }

    FXDragOn<FXAutomaton> drag( Node node ) {
        def target = centerOf node
        new FXDragOn( this, target.x, target.y )
    }

    static Point centerOf( Node node ) {
        assert node != null, "Node could not be found"
        def windowPos = getWindowPosition( node )
        def scenePos = getScenePosition( node )

        def boundsInScene = node.localToScene node.boundsInLocal
        def absX = windowPos.x + scenePos.x + boundsInScene.minX
        def absY = windowPos.y + scenePos.y + boundsInScene.minY
        [ ( absX + boundsInScene.width / 2 ).intValue(),
          ( absY + boundsInScene.height / 2 ).intValue() ] as Point
    }

    static Point getWindowPosition( Node node ) {
        new Point( node.scene.window.x.intValue(), node.scene.window.y.intValue() )
    }

	// required because of JavaFX bug: RT-34307
	protected static Point getScenePosition( Node node ) {
		if ( FXApp.scene == node.scene ) { // is top-level Scene
			scenePos.x = Math.max( node.scene.x.intValue(), scenePos.x )
			scenePos.y = Math.max( node.scene.y.intValue(), scenePos.y )
			return scenePos
		} else {
			return [ node.scene.x.intValue(), node.scene.y.intValue() ] as Point
		}
	}

    private static scenePos = new Point()

}

@Slf4j
class FXApp extends Application {

    private static Stage stage
    private static stageFuture = new ArrayBlockingQueue<Stage>( 1 )

    static Scene getScene() {
        if ( stage ) stage.scene
        else throw new RuntimeException( "You must initialize FXApp before you can get the Scene" )
    }

    static Stage getStage() {
        if ( stage ) stage
        else throw new RuntimeException( "You must initialize FXApp before you can get the Stage" )
    }

    synchronized static Stage initialize( String... args ) {<commit_msg>Made fix for bug #28 more robust - should work regardless of whether user is using FXApp<commit_after>package com.athaydes.automaton

import com.athaydes.automaton.selector.*
import com.athaydes.internal.Config
import com.athaydes.internal.interceptor.ToFrontInterceptor
import com.sun.javafx.robot.impl.FXRobotHelper
import groovy.util.logging.Slf4j
import javafx.application.Application
import javafx.application.Platform
import javafx.scene.Node
import javafx.scene.Scene
import javafx.scene.control.TextInputControl
import javafx.scene.layout.VBox
import javafx.stage.Stage
import org.codehaus.groovy.runtime.InvokerHelper

import java.awt.*
import java.util.List
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.TimeUnit

import static com.athaydes.automaton.selector.StringSelectors.matchingAny

/**
 *
 * User: Renato
 */
class FXAutomaton extends Automaton<FXAutomaton> {

    private static instance

    /**
     * Get the singleton instance of FXAutomaton, which is lazily created.
     * @return FXAutomaton singleton instance
     */
    static synchronized FXAutomaton getUser() {
        if ( !instance ) instance = new FXAutomaton()
        instance
    }

    protected FXAutomaton() {}

    /**
     * Block until all events in the JavaFX Thread have been processed.
     */
    FXAutomaton waitForFxEvents() {
        FXApp.doInFXThreadBlocking {}
        this
    }

    FXAutomaton clickOn( Node node, Speed speed = DEFAULT ) {
        moveTo( node, speed ).click()
    }

    FXAutomaton clickOnNodes( Collection<Node> nodes, long pauseBetween = 100, Speed speed = DEFAULT ) {
        nodes.each { node -> clickOn( node, speed ).pause( pauseBetween ) }
        this
    }

    FXAutomaton doubleClickOn( Node node, Speed speed = DEFAULT ) {
        moveTo( node, speed ).doubleClick()
    }

    FXAutomaton doubleClickOnNodes( Collection<Node> nodes, long pauseBetween = 100, Speed speed = DEFAULT ) {
        nodes.each { node -> doubleClickOn( node, speed ).pause( pauseBetween ) }
        this
    }

    FXAutomaton moveTo( Node node, Speed speed = DEFAULT ) {
        moveTo( { centerOf( node ) }, speed )
    }

    FXAutomaton moveToNodes( Collection<Node> nodes, long pauseBetween = 100, Speed speed = DEFAULT ) {
        nodes.each { node -> moveTo( node, speed ).pause( pauseBetween ) }
        this
    }

    FXDragOn<FXAutomaton> drag( Node node ) {
        def target = centerOf node
        new FXDragOn( this, target.x, target.y )
    }

    static Point centerOf( Node node ) {
        assert node != null, "Node could not be found"
        def windowPos = getWindowPosition( node )
        def scenePos = getScenePosition( node )

        def boundsInScene = node.localToScene node.boundsInLocal
        def absX = windowPos.x + scenePos.x + boundsInScene.minX
        def absY = windowPos.y + scenePos.y + boundsInScene.minY
        [ ( absX + boundsInScene.width / 2 ).intValue(),
          ( absY + boundsInScene.height / 2 ).intValue() ] as Point
    }

    static Point getWindowPosition( Node node ) {
        new Point( node.scene.window.x.intValue(), node.scene.window.y.intValue() )
    }

	// required because of JavaFX bug: RT-34307
	protected static Point getScenePosition( Node node ) {
		if ( FXApp.@stage?.scene == node.scene ) { // is top-level Scene
			scenePos.x = Math.max( node.scene.x.intValue(), scenePos.x )
			scenePos.y = Math.max( node.scene.y.intValue(), scenePos.y )
			return scenePos
		} else {
			return [ node.scene.x.intValue(), node.scene.y.intValue() ] as Point
		}
	}

    private static scenePos = new Point()

}

@Slf4j
class FXApp extends Application {

    private static Stage stage
    private static stageFuture = new ArrayBlockingQueue<Stage>( 1 )

    static Scene getScene() {
        if ( stage ) stage.scene
        else throw new RuntimeException( "You must initialize FXApp before you can get the Scene" )
    }

    static Stage getStage() {
        if ( stage ) stage
        else throw new RuntimeException( "You must initialize FXApp before you can get the Stage" )
    }

    synchronized static Stage initialize( String... args ) {
{'fraction_non_alphanumeric': 0.0947112462006079, 'fraction_numerical': 0.004863221884498481, 'mean_word_length': 2.9190090519294905, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '253863', 'n_tokens_mistral': 2515, 'n_tokens_neox': 2355, 'n_words': 701}