001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.ui;
038:
039: import javax.swing.*;
040: import java.awt.event.ActionEvent;
041: import java.awt.event.KeyEvent;
042: import java.awt.Toolkit;
043: import java.awt.Event;
044: import javax.swing.text.DefaultEditorKit;
045: import java.io.Serializable;
046:
047: import edu.rice.cs.drjava.DrJava;
048: import edu.rice.cs.drjava.config.*;
049: import edu.rice.cs.drjava.model.repl.*;
050: import edu.rice.cs.util.text.ConsoleDocument;
051: import edu.rice.cs.util.swing.Utilities;
052:
053: /** @version $Id: ConsoleController.java 4255 2007-08-28 19:17:37Z mgricken $ */
054: public class ConsoleController extends AbstractConsoleController
055: implements Serializable {
056: protected ConsoleDocument _doc;
057:
058: /** Object to wait on for input from System.in. */
059: private Object _inputWaitObject = new Object();
060:
061: /** State so that the Enter action will only take place if the console is actually waiting for input. */
062: private volatile boolean _blockedForConsoleInput;
063:
064: public ConsoleController(final ConsoleDocument doc,
065: InteractionsDJDocument adapter) {
066: super (adapter, new InteractionsPane("CONSOLE_KEYMAP", adapter) {
067: public int getPromptPos() {
068: return doc.getPromptPos();
069: }
070: });
071: _doc = doc;
072: _blockedForConsoleInput = false;
073: _pane.setEditable(false);
074: // _pane.getCaret().setVisible(false);
075:
076: _init();
077: }
078:
079: /** Gets the ConsoleDocument. */
080: public ConsoleDocument getConsoleDoc() {
081: return _doc;
082: }
083:
084: /** Allows the main controller to install the input listener into the model. */
085: public InputListener getInputListener() {
086: return _inputListener;
087: }
088:
089: protected void _setupModel() {
090: _adapter.addDocumentListener(new CaretUpdateListener());
091: _doc.setBeep(_pane.getBeep());
092: }
093:
094: /** Listens for input from System.in. */
095: protected InputListener _inputListener = new InputListener() {
096: public String getConsoleInput() {
097: // return JOptionPane.showInputDialog(MainFrame.this, "Please enter System.in:",
098: // "System.in", JOptionPane.QUESTION_MESSAGE);
099: Utilities.invokeAndWait(new Runnable() {
100: public void run() {
101: _pane.setEditable(true);
102: }
103: });
104: //_pane.getCaret().setVisible(true);
105: _waitForInput();
106: String s = _doc.getCurrentInput();
107: _doc.disablePrompt();
108: return s;
109: }
110: };
111:
112: /** @return the Object that the console waits on. */
113: Object getInputWaitObject() {
114: return _inputWaitObject;
115: }
116:
117: /** Waits for _inputWaitObject to be notified. */
118: protected void _waitForInput() {
119: synchronized (_inputWaitObject) {
120: try {
121: _blockedForConsoleInput = true;
122: while (_blockedForConsoleInput)
123: _inputWaitObject.wait();
124: } catch (InterruptedException ie) {
125: /* do nothing */
126: }
127: }
128: }
129:
130: /** Adds actions to the view. */
131: protected void _setupView() {
132: super ._setupView();
133:
134: // Get proper cross-platform mask.
135: int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
136:
137: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
138: KeyEvent.VK_ENTER, 0), enterAction);
139: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
140: KeyEvent.VK_ENTER, Event.SHIFT_MASK), newLineAction);
141:
142: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
143: KeyEvent.VK_B, mask), clearCurrentAction);
144:
145: // Left needs to be prevented from rolling cursor back before the prompt.
146: // Both left and right should lock when caret is before the prompt.
147: // Caret is allowed before the prompt for the purposes of mouse-based copy-
148: // and-paste.
149: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
150: KeyEvent.VK_KP_LEFT, 0), moveLeftAction);
151: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
152: KeyEvent.VK_LEFT, 0), moveLeftAction);
153:
154: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
155: KeyEvent.VK_KP_RIGHT, 0), moveRightAction);
156: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
157: KeyEvent.VK_RIGHT, 0), moveRightAction);
158:
159: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
160: KeyEvent.VK_KP_UP, 0), moveUpDownAction);
161: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
162: KeyEvent.VK_UP, 0), moveUpDownAction);
163: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
164: KeyEvent.VK_KP_DOWN, 0), moveUpDownAction);
165: _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
166: KeyEvent.VK_DOWN, 0), moveUpDownAction);
167: _pane.addActionForKeyStroke(DrJava.getConfig().getSetting(
168: OptionConstants.KEY_PASTE_FROM_HISTORY), pasteAction);
169: }
170:
171: /** No-op paste action. */
172: Action pasteAction = new DefaultEditorKit.PasteAction() {
173: public void actionPerformed(ActionEvent e) {
174: }
175: };
176:
177: AbstractAction enterAction = new EnterAction();
178:
179: private class EnterAction extends AbstractAction implements
180: Serializable {
181: public void actionPerformed(ActionEvent e) {
182: synchronized (_inputWaitObject) {
183: if (_blockedForConsoleInput) {
184: _pane.setEditable(false);
185: _pane.getCaret().setVisible(false);
186: _doc.insertNewLine(_doc.getLength());
187: _blockedForConsoleInput = false;
188: _inputWaitObject.notify(); // notify waiting thread that input is available
189: }
190: }
191: }
192: }
193:
194: /** Moves the caret left or beeps at the edge. */
195: AbstractAction moveLeftAction = new LeftAction();
196:
197: private class LeftAction extends AbstractAction implements
198: Serializable {
199: public void actionPerformed(ActionEvent e) {
200: _doc.acquireReadLock();
201: try {
202: int position = _pane.getCaretPosition();
203: if (position < _doc.getPromptPos())
204: moveToPrompt();
205: else if (position == _doc.getPromptPos())
206: _pane.getBeep().run();
207: else
208: // position > _doc.getPromptPos()
209: _pane.setCaretPosition(position - 1);
210: } finally {
211: _doc.releaseReadLock();
212: }
213: }
214: }
215:
216: /** Moves the caret right or beeps at the edge. */
217: AbstractAction moveRightAction = new RightAction();
218:
219: private class RightAction extends AbstractAction implements
220: Serializable {
221: public void actionPerformed(ActionEvent e) {
222: _doc.acquireReadLock();
223: try {
224: int position = _pane.getCaretPosition();
225: if (position < _doc.getPromptPos())
226: moveToEnd();
227: else if (position >= _doc.getLength())
228: _pane.getBeep().run();
229: else
230: // position between prompt and end
231: _pane.setCaretPosition(position + 1);
232: } finally {
233: _doc.releaseReadLock();
234: }
235: }
236: }
237:
238: /** Cannot move up or down at console. Just move to the prompt if not in editable area, or beep if already after
239: * the prompt.
240: */
241: AbstractAction moveUpDownAction = new UpDownAction();
242:
243: private class UpDownAction extends AbstractAction implements
244: Serializable {
245: public void actionPerformed(ActionEvent e) {
246: _doc.acquireReadLock();
247: try {
248: int position = _pane.getCaretPosition();
249: if (position < _doc.getPromptPos())
250: moveToPrompt();
251: else
252: _pane.getBeep().run();
253: } finally {
254: _doc.releaseReadLock();
255: }
256: }
257: }
258: }
|