import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 * Key events and the data you can read from them. Everything prints to the console.
 *
 * One pad. Key events only reach the node that has focus, and clicking a Label does not give it
 * focus, so the pad asks for it: requestFocus() at the start and again whenever it is clicked.
 *
 * Event types handled: key pressed, key released, key typed.
 * getCode is meaningful on pressed and released; getCharacter only on typed.
 * Try: a letter; the same letter with shift; arrow keys; Enter; Escape; Tab (it moves focus away);
 * hold a key down (pressed repeats). Compare what you get on pressed with what you get on typed.
 */
public class SimpleKeyDemo extends Application {

	// KeyEvent.CHAR_UNDEFINED is what getCharacter() holds on a pressed or
	// released event.
	private String show ( String text ) {
		if ( text.equals(KeyEvent.CHAR_UNDEFINED) ) {
			return "(undefined)";
		}
		if ( text.length() == 1 && Character.isISOControl(text.charAt(0)) ) {
			return "(control character, code " + (int) text.charAt(0) + ")"; // Enter,
			                                                                 // Tab,
			                                                                 // Escape
			                                                                 // ...
		}
		return "\"" + text + "\"";
	}

	// Print the useful data from one key event.
	private void report ( KeyEvent e ) {
		System.out.println(e.getEventType() + "   getCode " + e.getCode()
		    + "   getCharacter " + show(e.getCharacter()) + "   shift "
		    + e.isShiftDown() + " control " + e.isControlDown() + " alt "
		    + e.isAltDown());
	}

	@Override
	public void start ( Stage stage ) {
		Label pad = new Label("click here, then type");
		pad.setPrefSize(260,120);
		pad.setAlignment(Pos.CENTER);
		pad.setStyle("-fx-background-color: #cfe8ff; -fx-border-color: #333;");
		pad.setFocusTraversable(true); // part of the Tab order

		pad.setOnKeyPressed(e -> report(e)); // a physical key goes down (repeats
		                                     // while held)
		pad.setOnKeyReleased(e -> report(e)); // a physical key comes up
		pad.setOnKeyTyped(e -> report(e)); // a character was produced (layout and
		                                   // shift applied)

		pad.setOnMouseClicked(e -> pad.requestFocus()); // a click does not focus a
		                                                // Label, so ask for it

		VBox root =
		    new VBox(15,new Label("Type on the pad. Watch the console."),pad);
		root.setPadding(new Insets(20));

		stage.setScene(new Scene(root,300,200));
		stage.setTitle("Key events");
		stage.show();

		pad.requestFocus(); // focus the pad at the start (needs the stage showing)
	}

	public static void main ( String[] args ) {
		launch(args);
	}
}