/****************************************************************************** * Copyright (C) 2014 Yevgeny Krasik * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * ******************************************************************************/ package com.github.ykrasik.jaci.cli.javafx; import javafx.event.EventHandler; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyEvent; import javafx.stage.Stage; import java.util.Objects; /** * An {@link EventHandler} that toggles between the currently active scene and a different scene * when a key combination is pressed. * The default key combination is ` (back tick, usually above tab). * * @author Yevgeny Krasik */ // FIXME: When doing a sceneToggle and the cursor is over the textArea, the cursor remains the text cursor. public class SceneToggler implements EventHandler<KeyEvent> { private static final KeyCombination DEFAULT_KEY_COMBINATION = KeyCombination.keyCombination("`"); private final Stage stage; private final Scene scene; private Scene prevScene; private KeyCombination toggleCombination = DEFAULT_KEY_COMBINATION; public SceneToggler(Stage stage, Parent parent) { this(stage, new Scene(parent)); } public SceneToggler(Stage stage, Scene scene) { this.stage = Objects.requireNonNull(stage, "stage"); this.scene = Objects.requireNonNull(scene, "scene"); } /** * Set a new toggle keyCombination. * * @param toggleCombination New keyCombination to set. */ public void setToggleCombination(KeyCombination toggleCombination) { this.toggleCombination = Objects.requireNonNull(toggleCombination, "toggleCombination"); } @Override public void handle(KeyEvent event) { if (toggleCombination.match(event)) { final Scene currentScene = stage.getScene(); if (currentScene == scene) { deactivate(); } else { activate(); } } } private void activate() { prevScene = stage.getScene(); stage.setScene(scene); // This is a workaround for an annoying bug (observed with JDK7u75). // When a scene is made visible by the stage, it is not resized to fill the stage automatically, // but only if the stage is somehow changed. // So... here is a fake change. final boolean resizable = stage.isResizable(); stage.setResizable(!resizable); stage.setResizable(resizable); } private void deactivate() { stage.setScene(prevScene); prevScene = null; } /** * Register a {@link SceneToggler} as an event filter with the {@link Stage}. * Will toggle on the default key combination of Ctrl+` * * @param stage Stage to register on. * @param parent The parent to show upon toggle. * @return The sceneToggler, in case a different key combination is desired. * * @see #setToggleCombination(KeyCombination) */ public static SceneToggler register(Stage stage, Parent parent) { final SceneToggler toggler = new SceneToggler(stage, parent); stage.addEventFilter(KeyEvent.KEY_PRESSED, toggler); return toggler; } }