/****************************************************************************** * Copyright (c) 2016 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.libgdx.input; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.InputAdapter; /** * Performs a single action when a key combination (which may also just be a single key) is detected. * The action is performed on keyDown(). * * @author Yevgeny Krasik */ public abstract class KeyCombinationProcessor extends InputAdapter { private int keycode; private boolean shift; private boolean ctrl; private boolean alt; private boolean fired; /** * The action is fired on keyDown(), however a keyTyped() call will also be generated, * which we must consume - this key was never intended to be typed. */ private boolean consumeNextKeyTyped; /** * Create a key combination with the given keycode. * Meta keys can be enabled with {@link #shift()}, {@link #ctrl()}, {@link #alt()}. * * @param keycode Base keycode for this combination. * @see Keys */ public KeyCombinationProcessor(int keycode) { this.keycode = keycode; } /** * @return Combination keycode. */ public int getKeycode() { return keycode; } /** * @param keycode keycode for this key combination. */ public void setKeycode(int keycode) { this.keycode = keycode; } /** * @return {@code true} if this key combination includes the {@code shift} key. */ public boolean isShift() { return shift; } /** * @param shift Whether this key combination should include the {@code shift} key. * @return {@code this}, for chaining. */ public KeyCombinationProcessor setShift(boolean shift) { this.shift = shift; return this; } /** * Shortcut for {@link #setShift(boolean)} that enables {@code shift} for this key combination. * * @return {@code this}, for chaining. */ public KeyCombinationProcessor shift() { return setShift(true); } /** * @return {@code true} if this key combination includes the {@code ctrl} key. */ public boolean isCtrl() { return ctrl; } /** * @param ctrl Whether this key combination should include the {@code ctrl} key. * @return {@code this}, for chaining. */ public KeyCombinationProcessor setCtrl(boolean ctrl) { this.ctrl = ctrl; return this; } /** * Shortcut for {@link #setCtrl(boolean)} that enables {@code ctrl} for this key combination. * * @return {@code this}, for chaining. */ public KeyCombinationProcessor ctrl() { return setCtrl(true); } /** * @return {@code true} if this key combination includes the {@code alt} key. */ public boolean isAlt() { return alt; } /** * @param alt Whether this key combination should include the {@code alt} key. * @return {@code this}, for chaining. */ public KeyCombinationProcessor setAlt(boolean alt) { this.alt = alt; return this; } /** * Shortcut for {@link #setAlt(boolean)} that enables {@code alt} for this key combination. * * @return {@code this}, for chaining. */ public KeyCombinationProcessor alt() { return setAlt(true); } @Override public boolean keyDown(int keycode) { if (fired || keycode != this.keycode) { return false; } if (!checkMetaKey(shift, Keys.SHIFT_LEFT, Keys.SHIFT_RIGHT)) { return false; } if (!checkMetaKey(ctrl, Keys.CONTROL_LEFT, Keys.CONTROL_RIGHT)) { return false; } if (!checkMetaKey(alt, Keys.ALT_LEFT, Keys.ALT_RIGHT)) { return false; } consumeNextKeyTyped = true; fired = true; fire(); return true; } private boolean checkMetaKey(boolean expected, int leftKeycode, int rightKeycode) { return !expected || isKeyPressed(leftKeycode) || isKeyPressed(rightKeycode); } private boolean isKeyPressed(int keycode) { return Gdx.input.isKeyPressed(keycode); } @Override public boolean keyUp(int keycode) { if (!fired) { return false; } if (keycode == this.keycode) { fired = false; return true; } return false; } @Override public boolean keyTyped(char character) { if (consumeNextKeyTyped) { // Consume this event to stop it from being propagated. consumeNextKeyTyped = false; return true; } return false; } /** * Action to be performed when this key combination is detected. */ protected abstract void fire(); }