package com.github.czyzby.lml.parser.impl.tag.macro; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.utils.IntSet; import com.github.czyzby.lml.parser.LmlParser; import com.github.czyzby.lml.parser.impl.attribute.listener.ListenerKeysLmlAttribute; import com.github.czyzby.lml.parser.impl.tag.listener.InputListenerLmlTag.KeysListener; import com.github.czyzby.lml.parser.tag.LmlTag; /** Attaches {@link InputListener} to its actor parent. When the selected keys are typed, content between macro tags * will be parsed using {@link LmlParser#parseTemplate(String)} and the returned actors will be added to the stage. This * is very useful for adding "delayed" actors creation that should occur only if certain event is detected. For example, * this shows a dialog when space is typed: * * <blockquote> * * <pre> * <textField> * <:onInput keys="Space"> * <dialog>Space typed!</dialog> * </:onInput> * </button> * </pre> * * </blockquote>However, you might want to cache the actors to prevent from parsing it each time the event occurs. Also, * you might need to show the actors only if certain condition is met. Both of these functionalities are supported: * * <blockquote> * * <pre> * <textField> * <:onInput keys="Space;Tab;Enter" if="$myMethod == 13" cache="true" button="1" > * <dialog>Whitespace typed!</dialog> * </:onInput> * </button> * </pre> * * </blockquote>In the example above, the actors will be displayed only if the result of myMethod is 13. Also, actors * will be cached after first parsing ("cache" attribute). The listener will be triggered only by the mouse button with * ID of 1 ("button" attribute). Keys attribute should be an array of string values that represent keys as returned by * {@link Keys#toString(int)} or the exact int values of key codes. If you set "combined" attribute to true, actors will * be shown only when all keys are pressed at the same time. * * @author MJ */ public class InputListenerLmlMacroTag extends AbstractListenerLmlMacroTag { /** An array of keys that trigger the event. Names have to match exact values from {@link Keys}. Optional - if not * set, event will be triggered for all keys. */ public static final String KEYS_ATTRIBUTE = "keys"; /** If this attribute is set to true, the event will be invoked only all selected keys are pressed at the same time. * Optional. */ public static final String COMBINED_ATTRIBUTE = "combined"; private final IntSet keys = new IntSet(); private final KeysListener listener = new KeysListener(keys) { @Override protected void handleEvent(final Actor actor) { doOnEvent(actor); } }; public InputListenerLmlMacroTag(final LmlParser parser, final LmlTag parentTag, final StringBuilder rawTagData) { super(parser, parentTag, rawTagData); } @Override protected InputListener getEventListener() { return listener; } @Override public void closeTag() { extractKeys(); listener.setCombined(hasAttribute(COMBINED_ATTRIBUTE) && getParser().parseBoolean(getAttribute(COMBINED_ATTRIBUTE), getActor())); super.closeTag(); } /** Extract key codes from {@link #KEYS_ATTRIBUTE}. */ protected void extractKeys() { if (!hasAttribute(KEYS_ATTRIBUTE)) { return; } ListenerKeysLmlAttribute.processKeysAttribute(getParser(), getActor(), getAttribute(KEYS_ATTRIBUTE), keys); } @Override public String[] getExpectedAttributes() { return new String[] { IF_ATTRIBUTE, CACHE_ATTRIBUTE, KEEP_ATTRIBUTE, IDS_ATTRIBUTE, KEYS_ATTRIBUTE, COMBINED_ATTRIBUTE }; } }