File Source: InputHandler.java
/*
P/P * Method: com.dmdirc.ui.input.InputHandler__static_init
*/
1 /*
2 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 package com.dmdirc.ui.input;
24
25 import com.dmdirc.actions.ActionManager;
26 import com.dmdirc.actions.CoreActionType;
27 import com.dmdirc.commandparser.CommandArguments;
28 import com.dmdirc.commandparser.CommandInfo;
29 import com.dmdirc.commandparser.CommandManager;
30 import com.dmdirc.commandparser.commands.Command;
31 import com.dmdirc.commandparser.commands.ValidatingCommand;
32 import com.dmdirc.commandparser.commands.WrappableCommand;
33 import com.dmdirc.commandparser.parsers.CommandParser;
34 import com.dmdirc.config.prefs.validator.ValidationResponse;
35 import com.dmdirc.interfaces.ConfigChangeListener;
36 import com.dmdirc.plugins.PluginManager;
37 import com.dmdirc.ui.input.tabstyles.TabCompletionResult;
38 import com.dmdirc.ui.input.tabstyles.TabCompletionStyle;
39 import com.dmdirc.ui.interfaces.InputField;
40 import com.dmdirc.ui.interfaces.InputValidationListener;
41 import com.dmdirc.ui.interfaces.InputWindow;
42 import com.dmdirc.ui.messages.Styliser;
43 import com.dmdirc.util.ListenerList;
44 import com.dmdirc.util.RollingList;
45
46 import java.awt.Toolkit;
47 import java.awt.event.KeyEvent;
48 import java.util.ArrayList;
49 import java.util.List;
50 import java.util.Map;
51
52 /**
53 * Handles events generated by a user typing into a textfield. Allows the user
54 * to use shortcut keys for control characters (ctrl+b, etc), to tab complete
55 * nicknames/channel names/etc, and to scroll through their previously issued
56 * commands.
57 *
58 * @author chris
59 */
60 public abstract class InputHandler implements ConfigChangeListener {
61
62 /**
63 * Indicates that the caret should be moved to the end of a selection when
64 * a control code has been inserted.
65 */
66 private static final int POSITION_END = 1;
67 /**
68 * Indicates that the caret should be moved to the start of a selection when
69 * a control code has been inserted.
70 */
71 protected static final int POSITION_START = 2;
72 /** Flag to indicate that this input handler should handle tab completion. */
73 protected static final int HANDLE_TABCOMPLETION = 1;
74 /** Flag to indicate that this input handler should maintain a back buffer. */
75 protected static final int HANDLE_BACKBUFFER = 2;
76 /** Flag to indicate that this input handler should handle formatting. */
77 protected static final int HANDLE_FORMATTING = 4;
78 /** Flag to indicate that this input handler should handle returns. */
79 protected static final int HANDLE_RETURN = 8;
80 /** The flags for this particular input handler. */
81 protected int flags = HANDLE_TABCOMPLETION | HANDLE_BACKBUFFER
82 | HANDLE_FORMATTING | HANDLE_RETURN;
83 /** The input buffer. */
84 protected RollingList<String> buffer;
85 /** The textfield that we're handling input for. */
86 protected final InputField target;
87 /** The TabCompleter to use for tab completion. */
88 protected TabCompleter tabCompleter;
89 /** The CommandParser to use for our input. */
90 protected final CommandParser commandParser;
91 /** The frame that we belong to. */
92 protected final InputWindow parentWindow;
93 /** The tab completion style. */
94 protected TabCompletionStyle style;
95 /** Our listener list. */
96 private final ListenerList listeners = new ListenerList();
97
98 /**
99 * Creates a new instance of InputHandler. Adds listeners to the target
100 * that we need to operate.
101 *
102 * @param thisTarget The text field this input handler is dealing with.
103 * @param thisCommandParser The command parser to use for this text field.
104 * @param thisParentWindow The window that owns this input handler
105 */
106 public InputHandler(final InputField thisTarget,
107 final CommandParser thisCommandParser,
/*
P/P * Method: void com.dmdirc.ui.input.InputHandler(InputField, CommandParser, InputWindow)
*
* Preconditions:
* thisParentWindow != null
*
* Presumptions:
* com.dmdirc.ui.interfaces.InputWindow:getConfigManager(...)@110 != null
* com.dmdirc.ui.interfaces.InputWindow:getConfigManager(...)@119 != null
*
* Postconditions:
* this.buffer == &new RollingList(InputHandler#2)
* this.commandParser == thisCommandParser
* init'ed(this.commandParser)
* this.flags == 15
* this.listeners == &new ListenerList(InputHandler#1)
* this.parentWindow == thisParentWindow
* this.parentWindow != null
* init'ed(this.style)
* init'ed(this.tabCompleter)
* this.target == thisTarget
* ...
*/
108 final InputWindow thisParentWindow) {
109
110 buffer = new RollingList<String>(thisParentWindow.getConfigManager().
111 getOptionInt("ui", "inputbuffersize"), "");
112
113 this.commandParser = thisCommandParser;
114 this.parentWindow = thisParentWindow;
115 this.target = thisTarget;
116
117 setStyle();
118
119 parentWindow.getConfigManager().addChangeListener("tabcompletion",
120 "style", this);
121
122 addUpHandler();
123 addDownHandler();
124 addTabHandler();
125 addKeyHandler();
126 addEnterHandler();
127 }
128
129 /**
130 * Adds an arrow up key handler.
131 */
132 protected abstract void addUpHandler();
133
134 /**
135 * Adds an arrow down key handler.
136 */
137 protected abstract void addDownHandler();
138
139 /**
140 * Adds an tab key handler.
141 */
142 protected abstract void addTabHandler();
143
144 /**
145 * Adds a key handler.
146 */
147 protected abstract void addKeyHandler();
148
149 /**
150 * Adds an enter key handler.
151 */
152 protected abstract void addEnterHandler();
153
154 /**
155 * Indicates which types of input this handler should handle.
156 *
157 * @param handleTabCompletion Whether or not to handle tab completion
158 * @param handleBackBuffer Whether or not to maintain an input back buffer
159 * @param handleFormatting Whether or not to handle formatting
160 * @param handleReturn Whether or not to handle returns
161 */
162 public void setTypes(final boolean handleTabCompletion,
163 final boolean handleBackBuffer,
164 final boolean handleFormatting, final boolean handleReturn) {
/*
P/P * Method: void setTypes(bool, bool, bool, bool)
*
* Postconditions:
* this.flags == One-of{8, 0} | One-of{4, 0} | One-of{1, 0} | One-of{2, 0}
* this.flags in {0..15}
*/
165 flags = (handleTabCompletion ? HANDLE_TABCOMPLETION : 0)
166 | (handleBackBuffer ? HANDLE_BACKBUFFER : 0)
167 | (handleFormatting ? HANDLE_FORMATTING : 0)
168 | (handleReturn ? HANDLE_RETURN : 0);
169 }
170
171 /**
172 * Sets this inputhandler's tab completion style.
173 */
174 private void setStyle() {
/*
P/P * Method: void setStyle()
*
* Preconditions:
* init'ed(com/dmdirc/plugins/PluginManager.me)
* this.parentWindow != null
* init'ed(this.tabCompleter)
* (soft) com/dmdirc/plugins/GlobalClassLoader.me != null
*
* Presumptions:
* com.dmdirc.ui.interfaces.InputWindow:getConfigManager(...)@175 != null
* getPluginManager(...).services != null
* getServiceProvider(...).exports@175 != null
*
* Postconditions:
* init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
* com/dmdirc/plugins/PluginManager.me == One-of{old com/dmdirc/plugins/PluginManager.me, &new PluginManager(getPluginManager#1)}
* com/dmdirc/plugins/PluginManager.me != null
* java.lang.StringBuilder:toString(...)._tainted == 0
* init'ed(this.style)
* new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0
* init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
* new HashMap(GlobalClassLoader#1) num objects == 0
* new HashMap(PluginManager#2) num objects <= 1
* new Hashtable(PluginManager#1) num objects == new HashMap(PluginManager#2) num objects
* ...
*/
175 style = (TabCompletionStyle) PluginManager.getPluginManager()
176 .getServiceProvider("tabcompletion", parentWindow.getConfigManager()
177 .getOption("tabcompletion", "style"))
178 .getExportedService("getCompletionStyle").execute(tabCompleter, parentWindow);
179 }
180
181 /**
182 * Sets this input handler's tab completer.
183 *
184 * @param newTabCompleter The new tab completer
185 */
186 public void setTabCompleter(final TabCompleter newTabCompleter) {
/*
P/P * Method: void setTabCompleter(TabCompleter)
*
* Postconditions:
* this.style == old this.style
* this.tabCompleter == newTabCompleter
* init'ed(this.tabCompleter)
*/
187 tabCompleter = newTabCompleter;
188 setStyle();
189 }
190
191 /**
192 * Handles the pressing of a key. Inserts control chars as appropriate.
193 *
194 * @param line Text in the target
195 * @param keyCode Keycode for the pressed key
196 * @param shiftPressed Was shift pressed
197 * @param ctrlPressed Was ctrl key pressed
198 */
199 protected void handleKeyPressed(final String line, final int keyCode,
200 final boolean shiftPressed, final boolean ctrlPressed) {
/*
P/P * Method: void handleKeyPressed(String, int, bool, bool)
*
* Preconditions:
* this.target != null
* (soft) line != null
* (soft) this.buffer != null
* (soft) this.commandParser != null
* (soft) init'ed(this.flags)
* (soft) this.listeners != null
* (soft) this.parentWindow != null
*
* Test Vectors:
* ctrlPressed: {0}, {1}
* this.flags & 4: {0}, {1..4}
*/
201 target.hideColourPicker();
202
203 if (ctrlPressed && (flags & HANDLE_FORMATTING) != 0) {
204 handleControlKey(line, keyCode, shiftPressed);
205 }
206
207 validateText();
208 }
209
210 /**
211 * Validates the text currently entered in the text field.
212 */
213 protected void validateText() {
/*
P/P * Method: void validateText()
*
* Preconditions:
* this.target != null
* (soft) this.listeners != null
* (soft) this.parentWindow != null
*
* Presumptions:
* com.dmdirc.commandparser.commands.ValidatingCommand:validateArguments(...)@223 != null
* com.dmdirc.ui.interfaces.InputWindow:getContainer(...)@239 != null
* java.util.Map_Entry:getValue(...)@223 != null
* java.util.Map_Entry:getValue(...)@234 != null
*
* Test Vectors:
* com.dmdirc.commandparser.CommandArguments:isCommand(...)@218: {0}, {1}
* com.dmdirc.commandparser.CommandManager:getCommand(...)@219: Addr_Set{null}, Inverse{null}
* com.dmdirc.config.prefs.validator.ValidationResponse:isFailure(...)@226: {0}, {1}
*/
214 final String text = target.getText();
215
216 final CommandArguments args = new CommandArguments(text);
217
218 if (args.isCommand()) {
219 final Map.Entry<CommandInfo, Command> command
220 = CommandManager.getCommand(args.getCommandName());
221
222 if (command != null && command.getValue() instanceof ValidatingCommand) {
223 final ValidationResponse vr = ((ValidatingCommand) command.getValue())
224 .validateArguments(parentWindow, args);
225
226 if (vr.isFailure()) {
227 fireCommandFailure(vr.getFailureReason());
228 } else {
229 fireCommandPassed();
230 }
231 }
232
233 if (command != null && command.getValue() instanceof WrappableCommand) {
234 final int count = ((WrappableCommand) command.getValue())
235 .getLineCount(parentWindow, args);
236 fireLineWrap(count);
237 }
238 } else {
239 final int lines = parentWindow.getContainer().getNumLines(text);
240 fireLineWrap(lines);
241 }
242 }
243
244 /**
245 * Fires the "illegalCommand" method of all validation listeners.
246 *
247 * @param reason The reason for the command failure
248 */
249 private void fireCommandFailure(final String reason) {
/*
P/P * Method: void fireCommandFailure(String)
*
* Preconditions:
* this.listeners != null
*
* Presumptions:
* com.dmdirc.util.ListenerList:get(...)@250 != null
* java.util.Iterator:next(...)@250 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@250: {0}, {1}
*/
250 for (InputValidationListener listener : listeners.get(InputValidationListener.class)) {
251 listener.illegalCommand(reason);
252 }
253 }
254
255 /**
256 * Fires the "legalCommand" method of all validation listeners.
257 */
258 private void fireCommandPassed() {
/*
P/P * Method: void fireCommandPassed()
*
* Preconditions:
* this.listeners != null
*
* Presumptions:
* com.dmdirc.util.ListenerList:get(...)@259 != null
* java.util.Iterator:next(...)@259 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@259: {0}, {1}
*/
259 for (InputValidationListener listener : listeners.get(InputValidationListener.class)) {
260 listener.legalCommand();
261 }
262 }
263
264 /**
265 * Fires the "wrappedText" method of all validation listeners.
266 *
267 * @param lines The number of lines that the text will wrap to
268 */
269 private void fireLineWrap(final int lines) {
/*
P/P * Method: void fireLineWrap(int)
*
* Preconditions:
* this.listeners != null
*
* Presumptions:
* com.dmdirc.util.ListenerList:get(...)@270 != null
* java.util.Iterator:next(...)@270 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@270: {0}, {1}
*/
270 for (InputValidationListener listener : listeners.get(InputValidationListener.class)) {
271 listener.wrappedText(lines);
272 }
273 }
274
275 /**
276 * Adds an InputValidationListener to this input handler.
277 *
278 * @param listener The listener to be added
279 */
280 public void addValidationListener(final InputValidationListener listener) {
/*
P/P * Method: void addValidationListener(InputValidationListener)
*
* Preconditions:
* this.listeners != null
*/
281 listeners.add(InputValidationListener.class, listener);
282 }
283
284 /**
285 * Handles the pressing of a key while the control key is pressed.
286 * Inserts control chars as appropriate.
287 *
288 * @param line Text in the target
289 * @param keyCode Keycode for the pressed key
290 * @param shiftPressed Was shift pressed
291 */
292 protected void handleControlKey(final String line, final int keyCode,
293 final boolean shiftPressed) {
/*
P/P * Method: void handleControlKey(String, int, bool)
*
* Preconditions:
* (soft) line != null
* (soft) this.buffer != null
* (soft) this.commandParser != null
* (soft) init'ed(this.flags)
* (soft) this.target != null
*
* Test Vectors:
* keyCode: {10}, {66}, {70}, {73}, {75}, {79}, {85}, {-231..9, 11..65, 67..69, 71,72, 74, 76..78, 80..84, 86..232-1}
* shiftPressed: {0}, {1}
* this.flags & 8: {0}, {1..8}
* java.lang.String:isEmpty(...)@328: {1}, {0}
*/
294 switch (keyCode) {
295 case KeyEvent.VK_B:
296 addControlCode(Styliser.CODE_BOLD, POSITION_END);
297 break;
298
299 case KeyEvent.VK_U:
300 addControlCode(Styliser.CODE_UNDERLINE, POSITION_END);
301 break;
302
303 case KeyEvent.VK_O:
304 addControlCode(Styliser.CODE_STOP, POSITION_END);
305 break;
306
307 case KeyEvent.VK_I:
308 addControlCode(Styliser.CODE_ITALIC, POSITION_END);
309 break;
310
311 case KeyEvent.VK_F:
312 if (shiftPressed) {
313 addControlCode(Styliser.CODE_FIXED, POSITION_END);
314 }
315 break;
316
317 case KeyEvent.VK_K:
318 if (shiftPressed) {
319 addControlCode(Styliser.CODE_HEXCOLOUR, POSITION_START);
320 target.showColourPicker(false, true);
321 } else {
322 addControlCode(Styliser.CODE_COLOUR, POSITION_START);
323 target.showColourPicker(true, false);
324 }
325 break;
326
327 case KeyEvent.VK_ENTER:
328 if ((flags & HANDLE_RETURN) != 0 && !line.isEmpty()) {
329 commandParser.parseCommandCtrl(parentWindow, line);
330 addToBuffer(line);
331 }
332 break;
333
334 default:
335 /* Do nothing. */
336 break;
337 }
338 }
339
340 /**
341 * Calls when the user presses the up key.
342 * Handles cycling through the input buffer.
343 */
344 protected void doBufferUp() {
/*
P/P * Method: void doBufferUp()
*
* Preconditions:
* init'ed(this.flags)
* this.target != null
* (soft) this.buffer != null
* (soft) this.listeners != null
* (soft) this.parentWindow != null
*
* Presumptions:
* java.awt.Toolkit:getDefaultToolkit(...)@349 != null
*
* Test Vectors:
* this.flags & 2: {0}, {1,2}
* com.dmdirc.util.RollingList:hasPrevious(...)@346: {0}, {1}
*/
345 if ((flags & HANDLE_BACKBUFFER) != 0) {
346 if (buffer.hasPrevious()) {
347 target.setText(buffer.getPrevious());
348 } else {
349 Toolkit.getDefaultToolkit().beep();
350 }
351 }
352 validateText();
353 }
354
355 /**
356 * Called when the user presses the down key.
357 * Handles cycling through the input buffer, and storing incomplete lines.
358 */
359 protected void doBufferDown() {
/*
P/P * Method: void doBufferDown()
*
* Preconditions:
* init'ed(this.flags)
* this.target != null
* (soft) this.buffer != null
* (soft) this.listeners != null
* (soft) this.parentWindow != null
*
* Presumptions:
* com.dmdirc.ui.interfaces.InputField:getText(...)@363 != null
* java.awt.Toolkit:getDefaultToolkit(...)@364 != null
*
* Test Vectors:
* this.flags & 2: {0}, {1,2}
* com.dmdirc.util.RollingList:hasNext(...)@361: {0}, {1}
* java.lang.String:isEmpty(...)@363: {0}, {1}
*/
360 if ((flags & HANDLE_BACKBUFFER) != 0) {
361 if (buffer.hasNext()) {
362 target.setText(buffer.getNext());
363 } else if (target.getText().isEmpty()) {
364 Toolkit.getDefaultToolkit().beep();
365 } else {
366 addToBuffer(target.getText());
367 target.setText("");
368 }
369 }
370 validateText();
371 }
372
373 /**
374 * Retrieves a list of all known entries in the input backbuffer.
375 *
376 * @since 0.6
377 * @return A copy of the input backbuffer.
378 */
379 public List<String> getBackBuffer() {
/*
P/P * Method: List getBackBuffer()
*
* Preconditions:
* this.buffer != null
*
* Postconditions:
* return_value == &new ArrayList(getBackBuffer#1)
* new ArrayList(getBackBuffer#1) num objects == 1
*/
380 return new ArrayList<String>(buffer.getList());
381 }
382
383 /**
384 * Handles tab completion of a string. Called when the user presses tab.
385 */
386 protected void doTabCompletion() {
/*
P/P * Method: void doTabCompletion()
*
* Preconditions:
* init'ed(this.tabCompleter)
* (soft) init'ed(this.flags)
* (soft) this.style != null
* (soft) this.target != null
*
* Presumptions:
* com.dmdirc.ui.interfaces.InputField:getCaretPosition(...)@398 >= -231+1
* com.dmdirc.ui.interfaces.InputField:getText(...)@391 != null
*
* Test Vectors:
* this.flags & 2: {1,2}, {0}
* this.tabCompleter: Addr_Set{null}, Inverse{null}
* java.lang.String:charAt(...)@403: {32}, {0..31, 33..216-1}
* java.lang.String:charAt(...)@406: {0..31, 33..216-1}, {32}
* java.lang.String:charAt(...)@411: {32}, {0..31, 33..216-1}
* java.lang.String:isEmpty(...)@393: {0}, {1}
*/
387 if (tabCompleter == null || (flags & HANDLE_BACKBUFFER) == 0) {
388 return;
389 }
390
391 final String text = target.getText();
392
393 if (text.isEmpty()) {
394 doNormalTabCompletion(text, 0, 0, null);
395 return;
396 }
397
398 final int pos = target.getCaretPosition() - 1;
399 int start = (pos < 0) ? 0 : pos;
400 int end = (pos < 0) ? 0 : pos;
401
402 // Traverse backwards
403 while (start > 0 && text.charAt(start) != ' ') {
404 start--;
405 }
406 if (text.charAt(start) == ' ') {
407 start++;
408 }
409
410 // And forwards
411 while (end < text.length() && text.charAt(end) != ' ') {
412 end++;
413 }
414
415 if (start > end) {
416 end = start;
417 }
418
419 if (start > 0 && text.charAt(0) == CommandManager.getCommandChar()) {
420 doCommandTabCompletion(text, start, end);
421 } else {
422 doNormalTabCompletion(text, start, end, null);
423 }
424 }
425
426 /**
427 * Handles potentially intelligent tab completion.
428 *
429 * @param text The text that is being completed
430 * @param start The start index of the word we're completing
431 * @param end The end index of the word we're completing
432 */
433 private void doCommandTabCompletion(final String text, final int start,
434 final int end) {
/*
P/P * Method: void doCommandTabCompletion(String, int, int)
*
* Preconditions:
* text != null
* this.style != null
* (soft) this.target != null
*/
435 doNormalTabCompletion(text, start, end,
436 TabCompleter.getIntelligentResults(text.substring(0, start)));
437 }
438
439 /**
440 * Handles normal (non-intelligent-command) tab completion.
441 *
442 * @param text The text that is being completed
443 * @param start The start index of the word we're completing
444 * @param end The end index of the word we're completing
445 * @param additional A list of additional strings to use
446 */
447 private void doNormalTabCompletion(final String text, final int start,
448 final int end, final AdditionalTabTargets additional) {
/*
P/P * Method: void doNormalTabCompletion(String, int, int, AdditionalTabTargets)
*
* Preconditions:
* this.style != null
* (soft) this.target != null
*
* Test Vectors:
* com.dmdirc.ui.input.tabstyles.TabCompletionStyle:getResult(...)@449: Addr_Set{null}, Inverse{null}
*/
449 final TabCompletionResult res = style.getResult(text, start, end,
450 additional);
451
452 if (res != null) {
453 target.setText(res.getText());
454 target.setCaretPosition(res.getPosition());
455 }
456 }
457
458 /**
459 * Called when the user presses return in the text area. The line they
460 * typed is added to the buffer for future use.
461 * @param line The event that was fired
462 */
463 public void enterPressed(final String line) {
/*
P/P * Method: void enterPressed(String)
*
* Preconditions:
* line != null
* this.listeners != null
* (soft) this.buffer != null
* (soft) this.commandParser != null
* (soft) this.parentWindow != null
*
* Presumptions:
* init'ed(com.dmdirc.actions.CoreActionType.CLIENT_USER_INPUT)
*
* Test Vectors:
* java.lang.String:isEmpty(...)@464: {1}, {0}
*/
464 if (!line.isEmpty()) {
465 final StringBuffer thisBuffer = new StringBuffer(line);
466
467 ActionManager.processEvent(CoreActionType.CLIENT_USER_INPUT, null,
468 parentWindow.getContainer(), thisBuffer);
469
470 addToBuffer(thisBuffer.toString());
471
472 commandParser.parseCommand(parentWindow, thisBuffer.toString());
473 }
474 fireLineWrap(0);
475 fireCommandPassed();
476 }
477
478 /**
479 * Adds the specified control code to the textarea. If the user has a range
480 * of text selected, the characters are added before and after, and the
481 * caret is positioned based on the position argument.
482 * @param code The control code to add
483 * @param position The position of the caret after a selection is altered
484 */
485 protected void addControlCode(final int code, final int position) {
/*
P/P * Method: void addControlCode(int, int)
*
* Preconditions:
* code in {0..216-1}
* this.target != null
*
* Presumptions:
* com.dmdirc.ui.interfaces.InputField:getCaretPosition(...)@502 <= 232-2
* com.dmdirc.ui.interfaces.InputField:getSelectionEnd(...)@487 <= 232-3
* com.dmdirc.ui.interfaces.InputField:getText(...)@490 != null
* com.dmdirc.ui.interfaces.InputField:getText(...)@503 != null
* com.dmdirc.ui.interfaces.InputField:getText(...)@504 != null
* ...
*
* Test Vectors:
* position: {-231..0, 3..232-1}, {2}, {1}
*/
486 final String insert = String.valueOf((char) code);
487 final int selectionEnd = target.getSelectionEnd();
488 final int selectionStart = target.getSelectionStart();
489 if (selectionStart < selectionEnd) {
490 final String source = target.getText();
491 final String before = source.substring(0, selectionStart);
492 final String selected = target.getSelectedText();
493 final String after =
494 source.substring(selectionEnd, source.length());
495 target.setText(before + insert + selected + insert + after);
496 if (position == POSITION_START) {
497 target.setCaretPosition(selectionStart + 1);
498 } else if (position == POSITION_END) {
499 target.setCaretPosition(selectionEnd + 2);
500 }
501 } else {
502 final int offset = target.getCaretPosition();
503 final String source = target.getText();
504 final String before = target.getText().substring(0, offset);
505 final String after = target.getText().substring(offset,
506 source.length());
507 target.setText(before + insert + after);
508 target.setCaretPosition(offset + 1);
509 }
510 }
511
512 /**
513 * Adds all items in the string array to the buffer.
514 *
515 * @param lines lines to add to the buffer
516 */
517 public void addToBuffer(final String[] lines) {
/*
P/P * Method: void addToBuffer(String[])
*
* Preconditions:
* lines != null
* lines.length <= 232-1
* (soft) init'ed(lines[...])
* (soft) this.buffer != null
*/
518 for (String line : lines) {
519 addToBuffer(line);
520 }
521 }
522
523 /**
524 * Adds the specified string to the buffer.
525 *
526 * @param line The line to be added to the buffer
527 */
528 public void addToBuffer(final String line) {
/*
P/P * Method: void addToBuffer(String)
*
* Preconditions:
* this.buffer != null
*/
529 buffer.add(line);
530 buffer.seekToEnd();
531 }
532
533 /** {@inheritDoc} */
534 @Override
535 public void configChanged(final String domain, final String key) {
/*
P/P * Method: void configChanged(String, String)
*
* Postconditions:
* this.style == old this.style
*/
536 setStyle();
537 }
538 }
SofCheck Inspector Build Version : 2.17854
| InputHandler.java |
2009-Jun-25 01:54:24 |
| InputHandler.class |
2009-Sep-02 17:04:12 |