import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.TransferMode;
import javafx.stage.Stage;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;

import javafx.scene.paint.Color;
import javafx.scene.input.Dragboard;
import javafx.scene.input.DragEvent;

public  class DndDemoApp extends Application {

	@Override
	public void start(Stage stage) {
		HBox root = new HBox();
		root.setPadding(new Insets(5));
		root.setSpacing(25);

		Scene scene = new Scene(root, 400, 200);

		final Label source = new Label("DRAG ME");
		source.setCursor(Cursor.HAND);
		source.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));

		final Label target = new Label("DROP HERE");
		target.setBackground(new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)));

		root.addEventHandler(DragEvent.ANY, evt -> {
			System.out.println("drag event: " + evt.getEventType());
		});

		source.setOnDragDetected((event) -> {
			System.out.println("onDragDetected");

			Dragboard db = source.startDragAndDrop(TransferMode.MOVE);
			ClipboardContent content = new ClipboardContent();
			content.putString("DRAGGED CONTENT");
			db.setContent(content);

			// not setting drag view made D&D work reliably with JFX 11, but under JFX 18 it's broken anyway
			// db.setDragView(...);

			event.consume();
		});

		source.setOnDragDone((event) -> {
			System.out.println("onDragDone");

			event.consume();
		});

		target.setOnDragOver((event) -> {
			System.out.println("onDragOver");

			if (event.getGestureSource() != target && event.getDragboard().hasString()) {
				event.acceptTransferModes(TransferMode.MOVE);
			}

			event.consume();
		});

		target.setOnDragEntered((event) -> {
			System.out.println("onDragEntered");

			event.consume();
		});

		target.setOnDragExited((event) -> {
			System.out.println("onDragExited");

			event.consume();
		});

		target.setOnDragDropped((event) -> {
			System.out.println("onDragDropped");

			Dragboard db = event.getDragboard();
			boolean hasString = db.hasString();
			if (hasString) target.setText(db.getString());

			event.setDropCompleted(hasString);

			event.consume();
		});

		root.getChildren().add(source);
		root.getChildren().add(target);
		stage.setScene(scene);
		stage.show();
	}

	public static void main(String[] args) {
		Application.launch(args);
	} 
}	
	