Gridarta Editor
DefaultInputHandler.java
Go to the documentation of this file.
1 /*
2  * DefaultInputHandler.java - Default implementation of an input handler
3  * Copyright (C) 1999 Slava Pestov
4  * Copyright (C) 2000-2015 The Gridarta Developers.
5  *
6  * You may use and modify this package for any purpose. Redistribution is
7  * permitted, in both source and binary form, provided that this notice
8  * remains intact in all source distributions of this package.
9  */
10 
11 package net.sf.gridarta.textedit.textarea;
12 
13 import java.awt.event.ActionListener;
14 import java.awt.event.InputEvent;
15 import java.awt.event.KeyEvent;
16 import java.util.HashMap;
17 import java.util.Map;
18 import javax.swing.KeyStroke;
22 import org.apache.log4j.Category;
23 import org.apache.log4j.Logger;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.annotations.Nullable;
26 
33 public class DefaultInputHandler extends InputHandler {
34 
35  @NotNull
36  private final Map<KeyStroke, ActionListener> bindings;
37 
41  private static final Category LOG = Logger.getLogger(DefaultInputHandler.class);
42 
43  @NotNull
44  private final InputActions inputActions;
45 
52  public DefaultInputHandler(@NotNull final ScriptEditControl scriptEditControl, @NotNull final MenuEntries menuEntries) {
53  inputActions = new InputActions(scriptEditControl, menuEntries);
54  bindings = new HashMap<>();
55  }
56 
60  @Override
61  public void addDefaultKeyBindings() {
62  addKeyBinding("BACK_SPACE", inputActions.backspace);
63  addKeyBinding("C+BACK_SPACE", inputActions.backspaceWord);
64  addKeyBinding("DELETE", inputActions.delete);
65  addKeyBinding("C+DELETE", inputActions.deleteWord);
66 
67  addKeyBinding("ENTER", inputActions.insertBreak);
68  addKeyBinding("TAB", inputActions.insertTab);
69 
70  addKeyBinding("INSERT", inputActions.overwrite);
71  addKeyBinding("C+\\", inputActions.toggleRectangle);
72 
73  addKeyBinding("HOME", inputActions.home);
74  addKeyBinding("END", inputActions.end);
75  addKeyBinding("S+HOME", inputActions.selectHome);
76  addKeyBinding("S+END", inputActions.selectEnd);
77  addKeyBinding("C+HOME", inputActions.documentHome);
78  addKeyBinding("C+END", inputActions.documentEnd);
79  addKeyBinding("CS+HOME", inputActions.selectDocHome);
80  addKeyBinding("CS+END", inputActions.selectDocEnd);
81 
82  addKeyBinding("PAGE_UP", inputActions.prevPage);
83  addKeyBinding("PAGE_DOWN", inputActions.nextPage);
84  addKeyBinding("S+PAGE_UP", inputActions.selectPrevPage);
85  addKeyBinding("S+PAGE_DOWN", inputActions.selectNextPage);
86 
87  addKeyBinding("LEFT", inputActions.prevChar);
88  addKeyBinding("S+LEFT", inputActions.selectPrevChar);
89  addKeyBinding("C+LEFT", inputActions.prevWord);
90  addKeyBinding("CS+LEFT", inputActions.selectPrevWord);
91  addKeyBinding("RIGHT", inputActions.nextChar);
92  addKeyBinding("S+RIGHT", inputActions.selectNextChar);
93  addKeyBinding("C+RIGHT", inputActions.nextWord);
94  addKeyBinding("CS+RIGHT", inputActions.selectNextWord);
95  addKeyBinding("UP", inputActions.prevLine);
96  addKeyBinding("S+UP", inputActions.selectPrevLine);
97  addKeyBinding("DOWN", inputActions.nextLine);
98  addKeyBinding("S+DOWN", inputActions.selectNextLine);
99 
100  addKeyBinding("C+ENTER", inputActions.repeat);
101 
102  addKeyBinding(".", inputActions.functionMenu);
103  }
104 
114  private void addKeyBinding(final String keyBinding, final ActionListener action) {
115  final KeyStroke keyStroke = parseKeyStroke(keyBinding);
116  if (keyStroke != null) {
117  bindings.put(keyStroke, action);
118  }
119  }
120 
125  @Override
126  public InputHandler copy() {
127  return new DefaultInputHandler(this);
128  }
129 
134  @Override
135  public void keyPressed(final KeyEvent e) {
136  final int keyCode = e.getKeyCode();
137  final int modifiers = e.getModifiers();
138 
139  if (keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT || keyCode == KeyEvent.VK_ALT || keyCode == KeyEvent.VK_META) {
140  return;
141  }
142 
143  if ((modifiers & ~InputEvent.SHIFT_MASK) != 0 || e.isActionKey() || keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_DELETE || keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ESCAPE) {
144  if (handleGrabAction(e)) {
145  return;
146  }
147 
148  final KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers);
149  final ActionListener actionListener = bindings.get(keyStroke);
150  if (actionListener != null) {
151  executeAction(actionListener, e.getSource(), null);
152  e.consume();
153  }
154  }
155  }
156 
157  @Override
158  public void keyReleased(final KeyEvent e) {
159  }
160 
164  @Override
165  public void keyTyped(final KeyEvent e) {
166  final int modifiers = e.getModifiers();
167  final char c = e.getKeyChar();
168 
169  if (c != KeyEvent.CHAR_UNDEFINED && (modifiers & InputEvent.ALT_MASK) == 0) {
170  if (c >= (char) 0x20 && c != (char) 0x7f) {
171  final KeyStroke keyStroke = KeyStroke.getKeyStroke(Character.toUpperCase(c));
172  final ActionListener actionListener = bindings.get(keyStroke);
173 
174  if (actionListener != null) {
175  executeAction(actionListener, e.getSource(), String.valueOf(c));
176  return;
177  }
178 
179  if (handleGrabAction(e)) {
180  return;
181  }
182 
183  // 0-9 adds another 'digit' to the repeat number
184  if (isRepeatEnabled() && Character.isDigit(c)) {
185  repeatCount *= 10;
186  repeatCount += (int) c - (int) '0';
187  return;
188  }
189 
190  executeAction(inputActions.insertChar, e.getSource(), String.valueOf(e.getKeyChar()));
191 
192  repeatCount = 0;
193  setRepeatEnabled(false);
194  }
195  }
196  }
197 
207  @Nullable
208  private static KeyStroke parseKeyStroke(final String keyStroke) {
209  if (keyStroke == null) {
210  return null;
211  }
212 
213  int modifiers = 0;
214  final int index = keyStroke.indexOf('+');
215  if (index != -1) {
216  for (int i = 0; i < index; i++) {
217  switch (Character.toUpperCase(keyStroke.charAt(i))) {
218  case 'A':
219  modifiers |= InputEvent.ALT_MASK;
220  break;
221  case 'C':
222  modifiers |= InputEvent.CTRL_MASK;
223  break;
224  case 'M':
225  modifiers |= InputEvent.META_MASK;
226  break;
227  case 'S':
228  modifiers |= InputEvent.SHIFT_MASK;
229  break;
230  }
231  }
232  }
233 
234  final String key = keyStroke.substring(index + 1);
235  if (key.length() == 1) {
236  final char ch = Character.toUpperCase(key.charAt(0));
237  if (modifiers == 0) {
238  return KeyStroke.getKeyStroke(ch);
239  } else {
240  return KeyStroke.getKeyStroke(ch, modifiers);
241  }
242  } else if (key.isEmpty()) {
243  LOG.error("Invalid key stroke: " + keyStroke);
244  return null;
245  } else {
246  final int ch;
247 
248  try {
249  ch = KeyEvent.class.getField("VK_" + key).getInt(null);
250  } catch (final IllegalAccessException ignored) {
251  LOG.error("Invalid key stroke: " + keyStroke);
252  return null;
253  } catch (final NoSuchFieldException ignored) {
254  LOG.error("Invalid key stroke: " + keyStroke);
255  return null;
256  }
257 
258  return KeyStroke.getKeyStroke(ch, modifiers);
259  }
260  }
261 
263  inputActions = copy.inputActions;
264  bindings = copy.bindings;
265  }
266 
267 }
void keyPressed(final KeyEvent e)
Handle a key pressed event.
boolean handleGrabAction(final KeyEvent evt)
If a key is being grabbed, this method should be called with the appropriate key event.
static KeyStroke parseKeyStroke(final String keyStroke)
Converts a string to a keystroke.
InputHandler copy()
Returns a copy of this input handler that shares the same key bindings.
void addKeyBinding(final String keyBinding, final ActionListener action)
Adds a key binding to this input handler.
An input handler converts the user&#39;s key strokes into concrete actions.
Base package of all Gridarta classes.
This package contains the classes for the script editor used within the editor to create and modify P...
Definition: Actions.java:20
boolean isRepeatEnabled()
Returns if repetition is enabled.
static final Category LOG
The Logger for printing log messages.
void addDefaultKeyBindings()
Sets up the default key bindings.
This package contains the other part of the script editor.
ScriptEditControl - Manages events and data flow for the script editor entity.
void setRepeatEnabled(final boolean repeat)
Sets the enabled state of repetition.
List of menu entries (all CFPython commands).
DefaultInputHandler(@NotNull final ScriptEditControl scriptEditControl, @NotNull final MenuEntries menuEntries)
Creates a new input handler with no key bindings defined.
void executeAction(final ActionListener listener, final Object source, @Nullable final String actionCommand)
Executes the specified action, repeating and recording it as necessary.
void keyTyped(final KeyEvent e)
Handle a key typed event.