1
2
3
4
5
6
7
8
9
10
11 package de.jaret.util.ui.console;
12
13 import java.io.IOException;
14 import java.io.OutputStream;
15 import java.io.PrintStream;
16 import java.util.ArrayList;
17 import java.util.Iterator;
18 import java.util.List;
19
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.custom.StyledText;
22 import org.eclipse.swt.custom.VerifyKeyListener;
23 import org.eclipse.swt.events.VerifyEvent;
24 import org.eclipse.swt.layout.FillLayout;
25 import org.eclipse.swt.widgets.Composite;
26
27 /***
28 * Simple widget that acts like a shell window. Entered lines are reported to attched <code>ConsoleListeners</code>.
29 * A simple history allows reusing previously entered lines. Technically the widget wraps a <code>StyledText</code>.
30 *
31 * @author Peter Kliem
32 * @version $Id: ConsoleControl.java 242 2007-02-11 21:05:07Z olk $ ddd
33 */
34 public class ConsoleControl extends Composite implements VerifyKeyListener {
35 private List _enteredLines = new ArrayList();
36 private int _currentEnteredLineIdx = -1;
37 private List _listeners;
38 private String _prompt;
39 private int _promptEndIdx;
40 private int _promptEndOffset;
41 private StyledText _styledText;
42
43 /***
44 * Contructor
45 *
46 * @param parent parent composite
47 * @param style style
48 * @param prompt prompt to be displayed
49 * @param message startup message (<code>null</code> for no message)
50 */
51 public ConsoleControl(Composite parent, int style, String prompt, String message) {
52 super(parent, style);
53 _prompt = prompt;
54 createControls();
55 if (message != null && message.length() > 0) {
56 _styledText.append(message);
57 _styledText.setCaretOffset(_styledText.getCharCount());
58 writePrompt(true);
59 } else {
60 writePrompt(false);
61 }
62 }
63
64 /***
65 * Create the controls
66 */
67 private void createControls() {
68 setLayout(new FillLayout());
69 _styledText = new StyledText(this, SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
70 _styledText.addVerifyKeyListener(this);
71 }
72
73 /***
74 * Write the prompt and store the end index of the prompt.
75 *
76 * @param newLine if <code>true</code> prepend a newline
77 */
78 private void writePrompt(boolean newLine) {
79 if (newLine) {
80 _styledText.append(_styledText.getLineDelimiter());
81 }
82 _styledText.append(_prompt + " ");
83 _promptEndIdx = _prompt.length() + 1;
84 _promptEndOffset = _styledText.getCaretOffset() + _promptEndIdx + _styledText.getLineDelimiter().length();
85 _styledText.setCaretOffset(_promptEndOffset);
86 _styledText.showSelection();
87 }
88
89 /***
90 * Retrieve the caret offset in the line it is in.
91 *
92 * @return caret ofsfet in the current line
93 */
94 private int offsetInLine() {
95 int caretOffset = _styledText.getCaretOffset();
96 int lineidx = _styledText.getLineAtOffset(caretOffset);
97 int lineoffset = _styledText.getOffsetAtLine(lineidx);
98 int posInLine = caretOffset - lineoffset;
99 return posInLine;
100 }
101
102 /***
103 * Get the last line without the prompt.
104 *
105 * @return last line without prompt or <code>null</code> if the line is empty.
106 */
107 private String getEnteredLine() {
108 if (_promptEndOffset <= _styledText.getCharCount() - 1) {
109 return _styledText.getText(_promptEndOffset, _styledText.getCharCount() - 1);
110 } else {
111 return null;
112 }
113 }
114
115 /***
116 * Set the prompt to be used.
117 *
118 * @param prompt the new prompt
119 */
120 public void setPrompt(String prompt) {
121 _prompt = prompt;
122 }
123
124 /***
125 * Get the prompt
126 *
127 * @return currently set prompt
128 */
129 public String getPrompt() {
130 return _prompt;
131 }
132
133 /***
134 * Add a <code>ConsoleListener</code> to be informed about entered lines.
135 *
136 * @param listener listener to be added
137 */
138 public void addConsoleListener(ConsoleListener listener) {
139 if (_listeners == null) {
140 _listeners = new ArrayList();
141 }
142 _listeners.add(listener);
143 }
144
145 /***
146 * Remove a <code>ConsoleListener</code>.
147 *
148 * @param listener listener to be removed
149 */
150 public void remConsoleListener(ConsoleListener listener) {
151 if (_listeners != null) {
152 _listeners.remove(listener);
153 }
154 }
155
156 /***
157 * Inform all registered listeners about an entered line. The resulting Strings are concatenated to form the output
158 * of the listeners.
159 *
160 * @param line line entered
161 * @return concatenated results from the listeners or <code>null/code> if no listener did respond with a String
162 */
163 protected String fireLineEntered(String line) {
164 if (_listeners != null) {
165 StringBuffer result = new StringBuffer();
166 Iterator it = _listeners.iterator();
167 while (it.hasNext()) {
168 ConsoleListener listener = (ConsoleListener) it.next();
169 String r = listener.lineEntered(this, line);
170 if (r != null) {
171 result.append(r);
172 }
173 }
174 return result.toString();
175 } else {
176 return null;
177 }
178 }
179
180
181
182
183
184
185 public void verifyKey(VerifyEvent verifyEvent) {
186 switch (verifyEvent.keyCode) {
187 case SWT.ARROW_LEFT:
188 case SWT.BS:
189 System.out.println("left " + _promptEndIdx + " " + offsetInLine());
190 if (offsetInLine() <= _promptEndIdx) {
191 System.out.println("ignore");
192 verifyEvent.doit = false;
193 }
194 break;
195 case SWT.ARROW_UP:
196 int idx = _currentEnteredLineIdx - 1;
197 if (idx >= 0) {
198 replaceEnteredLineWith((String) _enteredLines.get(idx));
199 _currentEnteredLineIdx = idx;
200 }
201 verifyEvent.doit = false;
202 break;
203 case SWT.ARROW_DOWN:
204 int idx2 = _currentEnteredLineIdx + 1;
205 if (idx2 <= _enteredLines.size() - 1) {
206 replaceEnteredLineWith((String) _enteredLines.get(idx2));
207 _currentEnteredLineIdx = idx2;
208 }
209 verifyEvent.doit = false;
210 break;
211 case SWT.CR:
212 String line = getEnteredLine();
213 _styledText.setCaretOffset(_styledText.getCharCount());
214 if (line != null) {
215 _enteredLines.add(line);
216 _currentEnteredLineIdx = _enteredLines.size();
217 String result = fireLineEntered(line);
218 if (result != null && result.length() > 0) {
219 _styledText.append(_styledText.getLineDelimiter());
220 _styledText.append(result);
221 _styledText.setCaretOffset(_styledText.getCharCount());
222 }
223 } else {
224
225 }
226 writePrompt(true);
227 verifyEvent.doit = false;
228 break;
229
230 default:
231 break;
232 }
233 }
234
235 /***
236 * Append the given text to the console output
237 *
238 * @param text text to be appended
239 */
240 public void output(String text) {
241 _styledText.append(text);
242 _styledText.setCaretOffset(_styledText.getCaretOffset() + text.length());
243 _styledText.showSelection();
244 }
245
246 /***
247 * Get a <code>PrintStream</code> that prints to the console.
248 *
249 * @return a PrintStream printing to the console
250 */
251 public PrintStream getPrintStream() {
252 return new PrintStream(new ConsoleOutStream(this));
253 }
254
255 /***
256 * Replace the currently entered line with the given string
257 *
258 * @param string text to be set in the current line
259 */
260 private void replaceEnteredLineWith(String string) {
261 _styledText.replaceTextRange(_promptEndOffset, _styledText.getCharCount() - _promptEndOffset, string);
262 _styledText.setCaretOffset(_styledText.getCharCount());
263 }
264
265 /***
266 * An implemenation of an <code>OutputStream</code> writing to the console.
267 *
268 * @author Peter Kliem
269 */
270 public class ConsoleOutStream extends OutputStream {
271 ConsoleControl _consoleControl;
272
273 /***
274 * @param control ConsoleControl to write to
275 */
276 public ConsoleOutStream(ConsoleControl control) {
277 super();
278 _consoleControl = control;
279 }
280
281
282
283
284
285
286 public void write(int b) throws IOException {
287 _consoleControl.output("" + (char) b);
288 }
289 }
290
291 }