Change build scripts
[jvcard.git] / src / com / googlecode / lanterna / gui2 / AbstractInteractableComponent.java
CommitLineData
a3b510ab
NR
1/*
2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
3 *
4 * lanterna is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Copyright (C) 2010-2015 Martin
18 */
19package com.googlecode.lanterna.gui2;
20
21import com.googlecode.lanterna.TerminalPosition;
22import com.googlecode.lanterna.input.KeyStroke;
23
24/**
25 * Default implementation of Interactable that extends from AbstractComponent. If you want to write your own component
26 * that is interactable, i.e. can receive keyboard (and mouse) input, you probably want to extend from this class as
27 * it contains some common implementations of the methods from {@code Interactable} interface
28 * @param <T> Should always be itself, see {@code AbstractComponent}
29 * @author Martin
30 */
31public abstract class AbstractInteractableComponent<T extends AbstractInteractableComponent<T>> extends AbstractComponent<T> implements Interactable {
32
33 private InputFilter inputFilter;
34 private boolean inFocus;
35
36 /**
37 * Default constructor
38 */
39 protected AbstractInteractableComponent() {
40 inputFilter = null;
41 inFocus = false;
42 }
43
44 @Override
45 public T takeFocus() {
46 BasePane basePane = getBasePane();
47 if(basePane != null) {
48 basePane.setFocusedInteractable(this);
49 }
50 return self();
51 }
52
53 /**
54 * {@inheritDoc}
55 * <p>
56 * This method is final in {@code AbstractInteractableComponent}, please override {@code afterEnterFocus} instead
57 */
58 @Override
59 public final void onEnterFocus(FocusChangeDirection direction, Interactable previouslyInFocus) {
60 inFocus = true;
61 afterEnterFocus(direction, previouslyInFocus);
62 }
63
64 /**
65 * Called by {@code AbstractInteractableComponent} automatically after this component has received input focus. You
66 * can override this method if you need to trigger some action based on this.
67 * @param direction How focus was transferred, keep in mind this is from the previous component's point of view so
68 * if this parameter has value DOWN, focus came in from above
69 * @param previouslyInFocus Which interactable component had focus previously
70 */
71 @SuppressWarnings("EmptyMethod")
72 protected void afterEnterFocus(FocusChangeDirection direction, Interactable previouslyInFocus) {
73 //By default no action
74 }
75
76 /**
77 * {@inheritDoc}
78 * <p>
79 * This method is final in {@code AbstractInteractableComponent}, please override {@code afterLeaveFocus} instead
80 */
81 @Override
82 public final void onLeaveFocus(FocusChangeDirection direction, Interactable nextInFocus) {
83 inFocus = false;
84 afterLeaveFocus(direction, nextInFocus);
85 }
86
87 /**
88 * Called by {@code AbstractInteractableComponent} automatically after this component has lost input focus. You
89 * can override this method if you need to trigger some action based on this.
90 * @param direction How focus was transferred, keep in mind this is from the this component's point of view so
91 * if this parameter has value DOWN, focus is moving down to a component below
92 * @param nextInFocus Which interactable component is going to receive focus
93 */
94 @SuppressWarnings("EmptyMethod")
95 protected void afterLeaveFocus(FocusChangeDirection direction, Interactable nextInFocus) {
96 //By default no action
97 }
98
99 @Override
100 protected abstract InteractableRenderer<T> createDefaultRenderer();
101
102 @Override
103 public InteractableRenderer<T> getRenderer() {
104 return (InteractableRenderer<T>)super.getRenderer();
105 }
106
107 @Override
108 public boolean isFocused() {
109 return inFocus;
110 }
111
112 @Override
113 public final synchronized Result handleInput(KeyStroke keyStroke) {
114 if(inputFilter == null || inputFilter.onInput(this, keyStroke)) {
115 return handleKeyStroke(keyStroke);
116 }
117 else {
118 return Result.UNHANDLED;
119 }
120 }
121
122 /**
123 * This method can be overridden to handle various user input (mostly from the keyboard) when this component is in
124 * focus. The input method from the interface, {@code handleInput(..)} is final in
125 * {@code AbstractInteractableComponent} to ensure the input filter is properly handled. If the filter decides that
126 * this event should be processed, it will call this method.
127 * @param keyStroke What input was entered by the user
128 * @return Result of processing the key-stroke
129 */
130 protected Result handleKeyStroke(KeyStroke keyStroke) {
131 // Skip the keystroke if ctrl, alt or shift was down
132 if(!keyStroke.isAltDown() && !keyStroke.isCtrlDown() && !keyStroke.isShiftDown()) {
133 switch(keyStroke.getKeyType()) {
134 case ArrowDown:
135 return Result.MOVE_FOCUS_DOWN;
136 case ArrowLeft:
137 return Result.MOVE_FOCUS_LEFT;
138 case ArrowRight:
139 return Result.MOVE_FOCUS_RIGHT;
140 case ArrowUp:
141 return Result.MOVE_FOCUS_UP;
142 case Tab:
143 return Result.MOVE_FOCUS_NEXT;
144 case ReverseTab:
145 return Result.MOVE_FOCUS_PREVIOUS;
146 case MouseEvent:
147 getBasePane().setFocusedInteractable(this);
148 return Result.HANDLED;
149 default:
150 }
151 }
152 return Result.UNHANDLED;
153 }
154
155 @Override
156 public TerminalPosition getCursorLocation() {
157 return getRenderer().getCursorLocation(self());
158 }
159
160 @Override
161 public InputFilter getInputFilter() {
162 return inputFilter;
163 }
164
165 @Override
166 public synchronized T setInputFilter(InputFilter inputFilter) {
167 this.inputFilter = inputFilter;
168 return self();
169 }
170}