Source Code Cross Referenced for InteractionsController.java in  » IDE » DrJava » edu » rice » cs » drjava » ui » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE » DrJava » edu.rice.cs.drjava.ui 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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 java.awt.Toolkit;
040:        import java.awt.Color;
041:        import java.awt.EventQueue;
042:        import java.awt.RenderingHints;
043:        import java.awt.Graphics;
044:        import java.awt.Graphics2D;
045:        import java.awt.event.ActionEvent;
046:        import java.awt.event.KeyEvent;
047:
048:        import java.io.File;
049:
050:        import java.util.EventListener;
051:        import java.util.Vector;
052:
053:        import javax.swing.AbstractAction;
054:        import javax.swing.Action;
055:        import javax.swing.ActionMap;
056:        import javax.swing.BorderFactory;
057:        import javax.swing.InputMap;
058:        import javax.swing.JTextArea;
059:        import javax.swing.KeyStroke;
060:        import javax.swing.SwingUtilities;
061:        import javax.swing.border.Border;
062:        import javax.swing.event.CaretListener;
063:        import javax.swing.event.CaretEvent;
064:        import javax.swing.text.AttributeSet;
065:        import javax.swing.text.BadLocationException;
066:        import javax.swing.text.DefaultEditorKit;
067:        import javax.swing.text.MutableAttributeSet;
068:        import javax.swing.text.SimpleAttributeSet;
069:        import javax.swing.text.StyleConstants;
070:        import javax.swing.text.DefaultStyledDocument;
071:
072:        import edu.rice.cs.drjava.DrJava;
073:        import edu.rice.cs.drjava.config.OptionConstants;
074:        import edu.rice.cs.drjava.config.OptionListener;
075:        import edu.rice.cs.drjava.config.OptionEvent;
076:        import edu.rice.cs.drjava.model.repl.InputListener;
077:        import edu.rice.cs.drjava.model.repl.InteractionsDocument;
078:        import edu.rice.cs.drjava.model.repl.InteractionsDJDocument;
079:        import edu.rice.cs.drjava.model.repl.InteractionsListener;
080:        import edu.rice.cs.drjava.model.repl.InteractionsModel;
081:
082:        import edu.rice.cs.util.swing.Utilities;
083:        import edu.rice.cs.util.text.ConsoleDocument;
084:        import edu.rice.cs.util.CompletionMonitor;
085:        import edu.rice.cs.util.Lambda;
086:        import edu.rice.cs.util.Log;
087:        import edu.rice.cs.util.UnexpectedException;
088:
089:        /** This class installs listeners and actions between an InteractionsDocument (the model) and an InteractionsPane 
090:         *  (the view).  We may want to refactor this class into a different package. <p>
091:         *  (The PopupConsole was introduced in version 1.29 of this file and subsequently removed.)
092:         *
093:         *  @version $Id: InteractionsController.java 4255 2007-08-28 19:17:37Z mgricken $
094:         */
095:        public class InteractionsController extends AbstractConsoleController {
096:
097:            private static final Log _log = new Log("ConsoleController.txt",
098:                    false);
099:
100:            private static final String INPUT_ENTERED_NAME = "Input Entered";
101:            private static final String INSERT_NEWLINE_NAME = "Insert Newline";
102:
103:            /** Style for System.in box */
104:            public static final String INPUT_BOX_STYLE = "input.box.style";
105:
106:            /** The symbol used in the document for the input box. */
107:            public static final String INPUT_BOX_SYMBOL = "[DrJava Input Box]";
108:
109:            /** InteractionsModel to handle interpretation. */
110:            private volatile InteractionsModel _model;
111:
112:            /** Document from the model.*/
113:            private volatile InteractionsDocument _doc;
114:
115:            /** Style to use for error messages. */
116:            private volatile SimpleAttributeSet _errStyle;
117:
118:            /** Style to use for debug messages. */
119:            private final SimpleAttributeSet _debugStyle;
120:
121:            /** Lambda used to input text into the embedded System.in input box */
122:            private volatile Lambda<String, String> _insertTextCommand;
123:
124:            /** Runnable command used to force the System.in input to complete <p>
125:             * <b>NOTE:</b> This command must be executed on swing's event handling thread.
126:             */
127:            private volatile Runnable _inputCompletionCommand;
128:
129:            /** Default implementation of the insert text command */
130:            private static final Lambda<String, String> _defaultInsertTextCommand = new Lambda<String, String>() {
131:                public String apply(String input) {
132:                    throw new UnsupportedOperationException(
133:                            "Cannot insert text. There is no console input in progress");
134:                }
135:            };
136:
137:            /** Default implementation of the input completion command */
138:            private static final Runnable _defaultInputCompletionCommand = new Runnable() {
139:                public void run() { /* Do nothing */
140:                }
141:            };
142:
143:            /** A temporary variable used to hold a box allocated inside getConsoleInput below. */
144:            private volatile InputBox _box;
145:            /** A temporary variable used to hold the text fetched from _box in getConsoleInput below. */
146:            private volatile String _text;
147:
148:            /** Listens for input requests from System.in, displaying an input box as needed. */
149:            protected volatile InputListener _inputListener = new InputListener() {
150:                public String getConsoleInput() {
151:                    final CompletionMonitor completionMonitor = new CompletionMonitor();
152:                    _box = new InputBox();
153:
154:                    // Embed the input box into the interactions pane.
155:                    // This operation must be performed in the UI thread
156:                    SwingUtilities.invokeLater(new Runnable() {
157:                        public void run() {
158:
159:                            // These commands only run in the event thread
160:                            final Lambda<String, String> insertTextCommand = _box
161:                                    .makeInsertTextCommand(); // command for testing
162:
163:                            final Runnable inputCompletionCommand = new Runnable() { // command for terminating each input interaction
164:                                public void run() {
165:                                    assert EventQueue.isDispatchThread();
166:                                    // Reset the commands to their default inactive state
167:                                    _setConsoleInputCommands(
168:                                            _defaultInputCompletionCommand,
169:                                            _defaultInsertTextCommand);
170:
171:                                    _box.disableInputs();
172:                                    _text = _box.getText() + "\n";
173:
174:                                    /* Move the cursor back to the end of the interactions pane while preventing _doc from changing in the 
175:                                     * interim. */
176:                                    _doc.acquireReadLock();
177:                                    try {
178:                                        _pane.setEditable(true);
179:                                        _pane
180:                                                .setCaretPosition(_doc
181:                                                        .getLength());
182:                                    } finally {
183:                                        _doc.releaseReadLock();
184:                                    }
185:                                    _pane.requestFocusInWindow();
186:
187:                                    completionMonitor.set();
188:                                }
189:                            };
190:
191:                            _box
192:                                    .setInputCompletionCommand(inputCompletionCommand);
193:                            _setConsoleInputCommands(inputCompletionCommand,
194:                                    insertTextCommand);
195:                            _pane.setEditable(true);
196:
197:                            // create an empty MutableAttributeSet for _box
198:                            MutableAttributeSet inputAttributes = new SimpleAttributeSet();
199:
200:                            // initialize MutableAttributeSet to the attributes of the _box component
201:                            StyleConstants.setComponent(inputAttributes, _box);
202:
203:                            /* Insert box in document. */
204:                            _doc.acquireWriteLock();
205:                            try {
206:                                _doc.insertBeforeLastPrompt(" ",
207:                                        _doc.DEFAULT_STYLE);
208:
209:                                // bind INPUT_BOX_STYLE to inputAttributes in the associated InteractionsDJDocument 
210:                                _adapter.setDocStyle(INPUT_BOX_STYLE,
211:                                        inputAttributes);
212:
213:                                // and insert the symbol for the input box with the correct style (identifying it as our InputBox)
214:                                _doc.insertBeforeLastPrompt(INPUT_BOX_SYMBOL,
215:                                        INPUT_BOX_STYLE);
216:
217:                                _doc.insertBeforeLastPrompt("\n",
218:                                        _doc.DEFAULT_STYLE);
219:                            } finally {
220:                                _doc.releaseWriteLock();
221:                            }
222:
223:                            _box.setVisible(true);
224:                            SwingUtilities.invokeLater(new Runnable() {
225:                                public void run() {
226:                                    _box.requestFocusInWindow();
227:                                }
228:                            });
229:
230:                            _pane.setEditable(false);
231:                        }
232:                    });
233:                    fireConsoleInputStarted();
234:
235:                    // Wait for the inputCompletionCommand to be invoked
236:                    completionMonitor.waitOne();
237:
238:                    fireConsoleInputCompleted(_text);
239:
240:                    return _text;
241:                }
242:            };
243:
244:            private Vector<ConsoleStateListener> _consoleStateListeners;
245:
246:            private InteractionsListener _viewListener = new InteractionsListener() {
247:                public void interactionStarted() {
248:                }
249:
250:                public void interactionEnded() {
251:                    _pane.requestFocusInWindow();
252:                }
253:
254:                public void interactionErrorOccurred(int offset, int length) {
255:                }
256:
257:                public void interpreterResetting() {
258:                    Utilities.invokeLater(new Runnable() {
259:                        public void run() {
260:                            _adapter.clearColoring();
261:                            //          _pane.resetPrompts();  // NOT USED
262:                        }
263:                    });
264:                }
265:
266:                public void interpreterReady(File wd) {
267:                }
268:
269:                public void interpreterResetFailed(Throwable t) {
270:                }
271:
272:                public void interpreterExited(int status) {
273:                }
274:
275:                public void interpreterChanged(boolean inProgress) {
276:                }
277:
278:                public void interactionIncomplete() {
279:                }
280:
281:                public void slaveJVMUsed() {
282:                }
283:            };
284:
285:            /** Glue together the given model and a new view.
286:             * @param model An InteractionsModel
287:             * @param adapter InteractionsDJDocument being used by the model's doc
288:             */
289:            public InteractionsController(final InteractionsModel model,
290:                    InteractionsDJDocument adapter) {
291:                this (model, adapter, new InteractionsPane(adapter) {
292:                    public int getPromptPos() {
293:                        return model.getDocument().getPromptPos();
294:                    }
295:                });
296:            }
297:
298:            /** Glue together the given model and view.
299:             * @param model An InteractionsModel
300:             * @param adapter InteractionsDJDocument being used by the model's doc
301:             * @param pane An InteractionsPane
302:             */
303:            public InteractionsController(InteractionsModel model,
304:                    InteractionsDJDocument adapter, InteractionsPane pane) {
305:                super (adapter, pane);
306:                DefaultEditorKit d = pane.EDITOR_KIT;
307:
308:                for (Action a : d.getActions()) {
309:                    if (a.getValue(Action.NAME).equals(
310:                            DefaultEditorKit.upAction))
311:                        defaultUpAction = a;
312:                    if (a.getValue(Action.NAME).equals(
313:                            DefaultEditorKit.downAction))
314:                        defaultDownAction = a;
315:                }
316:
317:                _model = model;
318:                _doc = model.getDocument();
319:                _errStyle = new SimpleAttributeSet();
320:                _debugStyle = new SimpleAttributeSet();
321:
322:                _model.setInputListener(_inputListener);
323:                _model.addListener(_viewListener);
324:
325:                _inputCompletionCommand = _defaultInputCompletionCommand;
326:                _insertTextCommand = _defaultInsertTextCommand;
327:                _consoleStateListeners = new Vector<ConsoleStateListener>();
328:                //    _pane.addCaretListener(new CaretListener() {  // Update the cachedCaretPostion 
329:                //      public void caretUpdate(CaretEvent e) { 
330:                //        _log.log("Caret Event: " + e + " from source " + e.getSource());
331:                ////        setCachedCaretPos(e.getDot()); 
332:                //      }
333:                //    }); 
334:
335:                _init(); // residual superclass initialization
336:            }
337:
338:            public void addConsoleStateListener(ConsoleStateListener listener) {
339:                _consoleStateListeners.add(listener);
340:            }
341:
342:            public void removeConsoleStateListener(ConsoleStateListener listener) {
343:                _consoleStateListeners.remove(listener);
344:            }
345:
346:            private void fireConsoleInputStarted() {
347:                for (ConsoleStateListener listener : _consoleStateListeners) {
348:                    listener.consoleInputStarted(this );
349:                }
350:            }
351:
352:            private void fireConsoleInputCompleted(String text) {
353:                for (ConsoleStateListener listener : _consoleStateListeners) {
354:                    listener.consoleInputCompleted(text, this );
355:                }
356:            }
357:
358:            /** Gets the input listener for console input requests.  ONLY used in unit tests.
359:             * @return the input listener for console input requests.
360:             */
361:            public InputListener getInputListener() {
362:                return _inputListener;
363:            }
364:
365:            /** Forces console input to complete without the user hitting <Enter>.  Called by MainFrame when reset is called so 
366:             * that this lock is released.  This method is thread safe.
367:             * @throws UnsupportedOperationException If the interactions pane is not receiving console input
368:             */
369:            public void interruptConsoleInput() {
370:                SwingUtilities.invokeLater(_inputCompletionCommand);
371:            }
372:
373:            /** Inserts text into the console.  Can only be called from the event thread.  ONLY used in unit tests.
374:             * @param input The text to insert into the console input box
375:             * @throws UnsupportedOperationException If the the interactions pane is not receiving console input
376:             */
377:            public void insertConsoleText(String input) {
378:                _insertTextCommand.apply(input);
379:            }
380:
381:            /** Accessor method for the InteractionsModel.
382:             * @return the interactions model
383:             */
384:            public InteractionsModel getInteractionsModel() {
385:                return _model;
386:            }
387:
388:            /** Allows the abstract superclass to use the document.
389:             * @return the InteractionsDocument
390:             */
391:            public ConsoleDocument getConsoleDoc() {
392:                return _doc;
393:            }
394:
395:            /** Accessor method for the InteractionsDocument. */
396:            public InteractionsDocument getDocument() {
397:                return _doc;
398:            }
399:
400:            /** Adds AttributeSets as named styles to the document adapter. */
401:            protected void _addDocumentStyles() {
402:                // Add AbstractConsoleController styles
403:                super ._addDocumentStyles();
404:
405:                // Error
406:                _errStyle.addAttributes(_defaultStyle);
407:                _errStyle.addAttribute(StyleConstants.Foreground, DrJava
408:                        .getConfig().getSetting(
409:                                OptionConstants.INTERACTIONS_ERROR_COLOR));
410:                _errStyle.addAttribute(StyleConstants.Bold, Boolean.TRUE);
411:                _adapter.setDocStyle(InteractionsDocument.ERROR_STYLE,
412:                        _errStyle);
413:                DrJava.getConfig().addOptionListener(
414:                        OptionConstants.INTERACTIONS_ERROR_COLOR,
415:                        new OptionListener<Color>() {
416:                            public void optionChanged(OptionEvent<Color> oe) {
417:                                _errStyle.addAttribute(
418:                                        StyleConstants.Foreground, oe.value);
419:                            }
420:                        });
421:
422:                // Debug
423:                _debugStyle.addAttributes(_defaultStyle);
424:                _debugStyle.addAttribute(StyleConstants.Foreground, DrJava
425:                        .getConfig().getSetting(
426:                                OptionConstants.DEBUG_MESSAGE_COLOR));
427:                _debugStyle.addAttribute(StyleConstants.Bold, Boolean.TRUE);
428:                _adapter.setDocStyle(InteractionsDocument.DEBUGGER_STYLE,
429:                        _debugStyle);
430:                DrJava.getConfig().addOptionListener(
431:                        OptionConstants.DEBUG_MESSAGE_COLOR,
432:                        new OptionListener<Color>() {
433:                            public void optionChanged(OptionEvent<Color> oe) {
434:                                _debugStyle.addAttribute(
435:                                        StyleConstants.Foreground, oe.value);
436:                            }
437:                        });
438:            }
439:
440:            /** Updates all document styles with the attributes contained in newSet.  This behavior is only used in Mac OS X, 
441:             *  JDK 1.4.1, since setFont() works fine on JTextPane on all other tested platforms.
442:             *  @param newSet Style containing new attributes to use.
443:             */
444:            protected void _updateStyles(AttributeSet newSet) {
445:                super ._updateStyles(newSet);
446:                _errStyle.addAttributes(newSet);
447:                StyleConstants.setBold(_errStyle, true); // ensure err is always bold
448:                _debugStyle.addAttributes(newSet);
449:                StyleConstants.setBold(_debugStyle, true); // ensure debug is always bold
450:            }
451:
452:            /** Adds listeners to the model. */
453:            protected void _setupModel() {
454:                _adapter.addDocumentListener(new CaretUpdateListener());
455:                _doc.setBeep(_pane.getBeep());
456:            }
457:
458:            /** Adds actions to the view. */
459:            protected void _setupView() {
460:                super ._setupView();
461:
462:                // Get proper cross-platform mask.
463:                int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
464:
465:                // Add actions with keystrokes
466:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
467:                        KeyEvent.VK_ENTER, 0), evalAction);
468:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
469:                        KeyEvent.VK_ENTER, java.awt.Event.SHIFT_MASK),
470:                        newLineAction);
471:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
472:                        KeyEvent.VK_B, mask), clearCurrentAction);
473:
474:                // Up and down need to be bound both for keypad and not
475:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
476:                        KeyEvent.VK_KP_UP, 0), moveUpAction);
477:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
478:                        KeyEvent.VK_UP, 0), moveUpAction);
479:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
480:                        KeyEvent.VK_UP, mask), historyPrevAction);
481:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
482:                        KeyEvent.VK_KP_DOWN, 0), moveDownAction);
483:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
484:                        KeyEvent.VK_DOWN, 0), moveDownAction);
485:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
486:                        KeyEvent.VK_DOWN, mask), historyNextAction);
487:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
488:                        KeyEvent.VK_TAB, 0), historyReverseSearchAction);
489:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
490:                        KeyEvent.VK_TAB, java.awt.Event.SHIFT_MASK),
491:                        historyForwardSearchAction);
492:
493:                // Left needs to be prevented from rolling cursor back before the prompt.
494:                // Both left and right should lock when caret is before the prompt.
495:                // Caret is allowed before the prompt for the purposes of mouse-based copy-
496:                // and-paste.
497:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
498:                        KeyEvent.VK_KP_LEFT, 0), moveLeftAction);
499:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
500:                        KeyEvent.VK_LEFT, 0), moveLeftAction);
501:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
502:                        KeyEvent.VK_KP_RIGHT, 0), moveRightAction);
503:                _pane.addActionForKeyStroke(KeyStroke.getKeyStroke(
504:                        KeyEvent.VK_RIGHT, 0), moveRightAction);
505:
506:                // Prevent previous word action from going past the prompt
507:                _pane.addActionForKeyStroke(DrJava.getConfig().getSetting(
508:                        OptionConstants.KEY_PREVIOUS_WORD), prevWordAction);
509:                DrJava.getConfig().addOptionListener(
510:                        OptionConstants.KEY_PREVIOUS_WORD,
511:                        new OptionListener<KeyStroke>() {
512:                            public void optionChanged(OptionEvent<KeyStroke> oe) {
513:                                _pane
514:                                        .addActionForKeyStroke(
515:                                                DrJava
516:                                                        .getConfig()
517:                                                        .getSetting(
518:                                                                OptionConstants.KEY_PREVIOUS_WORD),
519:                                                prevWordAction);
520:                            }
521:                        });
522:
523:                _pane.addActionForKeyStroke(DrJava.getConfig().getSetting(
524:                        OptionConstants.KEY_NEXT_WORD), nextWordAction);
525:                DrJava.getConfig().addOptionListener(
526:                        OptionConstants.KEY_NEXT_WORD,
527:                        new OptionListener<KeyStroke>() {
528:                            public void optionChanged(OptionEvent<KeyStroke> oe) {
529:                                _pane.addActionForKeyStroke(DrJava.getConfig()
530:                                        .getSetting(
531:                                                OptionConstants.KEY_NEXT_WORD),
532:                                        nextWordAction);
533:                            }
534:                        });
535:            }
536:
537:            /** Sets the commands used to manipulate the console input process.  Only runs in the event thread. */
538:            private void _setConsoleInputCommands(
539:                    Runnable inputCompletionCommand,
540:                    Lambda<String, String> insertTextCommand) {
541:                _insertTextCommand = insertTextCommand;
542:                _inputCompletionCommand = inputCompletionCommand;
543:            }
544:
545:            // The fields below were made package private for testing purposes.
546:
547:            /** Evaluates the interaction on the current line. */
548:            AbstractAction evalAction = new AbstractAction() {
549:                public void actionPerformed(ActionEvent e) {
550:                    if (!_adapter.inCommentBlock()) {
551:                        Thread command = new Thread("Evaluating Interaction") {
552:                            public void run() {
553:                                _model.interpretCurrentInteraction();
554:                            }
555:                        };
556:                        command.start();
557:                    } else {
558:                        _model.addNewLine();
559:                        _model.interactionContinues();
560:                    }
561:                }
562:            };
563:
564:            /** Recalls the previous command from the history. */
565:            AbstractAction historyPrevAction = new AbstractAction() {
566:                public void actionPerformed(ActionEvent e) {
567:                    if (!_busy()) {
568:                        _doc.acquireWriteLock(); // recall... below acquires WriteLock!
569:                        try {
570:                            if (_doc.recallPreviousInteractionInHistory())
571:                                moveToEnd();
572:                            if (!_isCursorAfterPrompt())
573:                                moveToPrompt();
574:                        } finally {
575:                            _doc.releaseWriteLock();
576:                        }
577:                    }
578:                }
579:            };
580:
581:            /** Recalls the next command from the history. */
582:            AbstractAction historyNextAction = new AbstractAction() {
583:                public void actionPerformed(ActionEvent e) {
584:                    if (!_busy()) {
585:                        _doc.acquireWriteLock();
586:                        try {
587:                            if (_doc.recallNextInteractionInHistory()
588:                                    || !_isCursorAfterPrompt())
589:                                moveToPrompt();
590:                        } finally {
591:                            _doc.releaseWriteLock();
592:                        }
593:                    }
594:                }
595:            };
596:
597:            /** Added feature for up. If the cursor is on the first line of the current interaction, it goes into the history.
598:             * Otherwise, stays within the current interaction
599:             */
600:            AbstractAction moveUpAction = new AbstractAction() {
601:                public void actionPerformed(ActionEvent e) {
602:                    if (!_busy()) {
603:                        _doc.acquireWriteLock();
604:                        try {
605:                            if (_shouldGoIntoHistory(_doc.getPromptPos(), _pane
606:                                    .getCaretPosition()))
607:                                historyPrevAction.actionPerformed(e);
608:                            else {
609:                                defaultUpAction.actionPerformed(e);
610:                                if (!_isCursorAfterPrompt())
611:                                    moveToPrompt();
612:                            }
613:                        } finally {
614:                            _doc.releaseWriteLock();
615:                        }
616:                    }
617:                }
618:            };
619:
620:            /** Added feature for down. If the cursor is on the last line of the current interaction, it goes into the history.
621:             * Otherwise, stays within the current interaction
622:             */
623:            AbstractAction moveDownAction = new AbstractAction() {
624:                public void actionPerformed(ActionEvent e) {
625:                    if (!_busy()) {
626:                        _doc.acquireWriteLock();
627:                        try {
628:                            if (_shouldGoIntoHistory(_pane.getCaretPosition(),
629:                                    _adapter.getLength())) {
630:                                historyNextAction.actionPerformed(e);
631:                            } else {
632:                                defaultDownAction.actionPerformed(e);
633:                            }
634:                        } finally {
635:                            _doc.releaseWriteLock();
636:                        }
637:                    }
638:                }
639:            };
640:
641:            /** Tests whether or not to move into the history
642:             *  @return true iff there are no "\n" characters between the start and the end
643:             */
644:            private boolean _shouldGoIntoHistory(int start, int end) {
645:                if (_isCursorAfterPrompt() && end >= start) {
646:                    String text = "";
647:                    try {
648:                        text = _adapter.getText(start, end - start);
649:                    } catch (BadLocationException ble) {
650:                        throw new UnexpectedException(ble); //The conditional should prevent this from ever happening
651:                    }
652:                    if (text.indexOf("\n") != -1)
653:                        return false;
654:                }
655:                return true;
656:            }
657:
658:            private boolean _isCursorAfterPrompt() {
659:                return _pane.getCaretPosition() >= _doc.getPromptPos();
660:            }
661:
662:            Action defaultUpAction;
663:            Action defaultDownAction;
664:
665:            /** Reverse searches in the history. */
666:            AbstractAction historyReverseSearchAction = new AbstractAction() {
667:                public void actionPerformed(ActionEvent e) {
668:                    if (!_busy()) {
669:                        //        _doc.acquireReadLock();  // may be overkill
670:                        //        try {
671:                        _doc.reverseSearchInteractionsInHistory();
672:                        moveToEnd();
673:                        //        }
674:                        //        finally { _doc.releaseReadLock(); }
675:                    }
676:                }
677:            };
678:
679:            /** Forward searches in the history. */
680:            AbstractAction historyForwardSearchAction = new AbstractAction() {
681:                public void actionPerformed(ActionEvent e) {
682:                    if (!_busy()) {
683:                        //        _doc.acquireReadLock();  // may be overkill
684:                        //        try {
685:                        _doc.forwardSearchInteractionsInHistory();
686:                        moveToEnd();
687:                        //        }
688:                        //        finally { _doc.releaseReadLock(); }
689:                    }
690:                }
691:            };
692:
693:            /** Moves the caret left or wraps around. */
694:            AbstractAction moveLeftAction = new AbstractAction() {
695:                public void actionPerformed(ActionEvent e) {
696:                    if (!_busy()) {
697:                        _doc.acquireReadLock();
698:                        try {
699:                            int promptPos = _doc.getPromptPos();
700:                            int pos = _pane.getCaretPosition();
701:                            if (pos < promptPos)
702:                                moveToPrompt();
703:                            else if (pos == promptPos)
704:                                moveToEnd(); // Wrap around to the end
705:                            else {
706:                                _pane.setCaretPosition(pos - 1); // pos > promptPos
707:                                setCachedCaretPos(pos - 1);
708:                            }
709:                        } finally {
710:                            _doc.releaseReadLock();
711:                        }
712:                    }
713:                }
714:            };
715:
716:            /** Moves the caret right or wraps around. */
717:            AbstractAction moveRightAction = new AbstractAction() {
718:                public void actionPerformed(ActionEvent e) {
719:                    _doc.acquireReadLock();
720:                    try {
721:                        int pos = _pane.getCaretPosition();
722:                        if (pos < _doc.getPromptPos())
723:                            moveToEnd();
724:                        else if (pos >= _doc.getLength())
725:                            moveToPrompt(); // Wrap around to the star
726:                        else {
727:                            _pane.setCaretPosition(pos + 1); // position between prompt and end
728:                            setCachedCaretPos(pos + 1);
729:                        }
730:                    } finally {
731:                        _doc.releaseReadLock();
732:                    }
733:                }
734:            };
735:
736:            /** Skips back one word.  Doesn't move past the prompt. */
737:            AbstractAction prevWordAction = new AbstractAction() {
738:                public void actionPerformed(ActionEvent e) {
739:                    _doc.acquireReadLock();
740:                    try {
741:                        int position = _pane.getCaretPosition();
742:                        int promptPos = _doc.getPromptPos();
743:                        if (position < promptPos)
744:                            moveToPrompt();
745:                        else if (position == promptPos)
746:                            moveToEnd(); // Wrap around to the end
747:                        else
748:                            _pane.getActionMap().get(
749:                                    DefaultEditorKit.previousWordAction)
750:                                    .actionPerformed(e);
751:                    } finally {
752:                        _doc.releaseReadLock();
753:                    }
754:                }
755:            };
756:
757:            /** Skips forward one word.  Doesn't move past the prompt. */
758:            AbstractAction nextWordAction = new AbstractAction() {
759:                public void actionPerformed(ActionEvent e) {
760:                    _doc.acquireReadLock();
761:                    try {
762:                        int position = _pane.getCaretPosition();
763:                        int promptPos = _doc.getPromptPos();
764:                        if (position < promptPos)
765:                            moveToEnd();
766:                        else if (position >= _doc.getLength())
767:                            moveToPrompt(); // Wrap around to the start
768:                        else
769:                            _pane.getActionMap().get(
770:                                    DefaultEditorKit.nextWordAction)
771:                                    .actionPerformed(e);
772:                    } finally {
773:                        _doc.releaseReadLock();
774:                    }
775:                }
776:            };
777:
778:            /** A box that can be inserted into the interactions pane for separate input.  Do not confuse with 
779:             * edu.rice.cs.util.swing.InputBox. */
780:            private static class InputBox extends JTextArea {
781:                private static final int BORDER_WIDTH = 1;
782:                private static final int INNER_BUFFER_WIDTH = 3;
783:                private static final int OUTER_BUFFER_WIDTH = 2;
784:                private volatile Color _bgColor = DrJava.getConfig()
785:                        .getSetting(
786:                                OptionConstants.DEFINITIONS_BACKGROUND_COLOR);
787:                private volatile Color _fgColor = DrJava.getConfig()
788:                        .getSetting(OptionConstants.DEFINITIONS_NORMAL_COLOR);
789:                private volatile Color _sysInColor = DrJava.getConfig()
790:                        .getSetting(OptionConstants.SYSTEM_IN_COLOR);
791:                private volatile boolean _antiAliasText = DrJava.getConfig()
792:                        .getSetting(OptionConstants.TEXT_ANTIALIAS);
793:
794:                public InputBox() {
795:                    setForeground(_sysInColor);
796:                    setBackground(_bgColor);
797:                    setCaretColor(_fgColor);
798:                    setBorder(_createBorder());
799:                    setLineWrap(true);
800:
801:                    DrJava.getConfig().addOptionListener(
802:                            OptionConstants.DEFINITIONS_NORMAL_COLOR,
803:                            new OptionListener<Color>() {
804:                                public void optionChanged(OptionEvent<Color> oe) {
805:                                    _fgColor = oe.value;
806:                                    setBorder(_createBorder());
807:                                    setCaretColor(oe.value);
808:                                }
809:                            });
810:                    DrJava.getConfig().addOptionListener(
811:                            OptionConstants.DEFINITIONS_BACKGROUND_COLOR,
812:                            new OptionListener<Color>() {
813:                                public void optionChanged(OptionEvent<Color> oe) {
814:                                    _bgColor = oe.value;
815:                                    setBorder(_createBorder());
816:                                    setBackground(oe.value);
817:                                }
818:                            });
819:                    DrJava.getConfig().addOptionListener(
820:                            OptionConstants.SYSTEM_IN_COLOR,
821:                            new OptionListener<Color>() {
822:                                public void optionChanged(OptionEvent<Color> oe) {
823:                                    _sysInColor = oe.value;
824:                                    setForeground(oe.value);
825:                                }
826:                            });
827:                    DrJava.getConfig().addOptionListener(
828:                            OptionConstants.TEXT_ANTIALIAS,
829:                            new OptionListener<Boolean>() {
830:                                public void optionChanged(
831:                                        OptionEvent<Boolean> oce) {
832:                                    _antiAliasText = oce.value.booleanValue();
833:                                    InputBox.this .repaint();
834:                                }
835:                            });
836:
837:                    // Add the input listener for <Shift+Enter>
838:                    final Action newLineAction = new AbstractAction() {
839:                        public void actionPerformed(ActionEvent e) {
840:                            insert("\n", getCaretPosition());
841:                        }
842:                    };
843:
844:                    final InputMap im = getInputMap(WHEN_FOCUSED);
845:                    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,
846:                            java.awt.Event.SHIFT_MASK), INSERT_NEWLINE_NAME);
847:
848:                    final ActionMap am = getActionMap();
849:                    am.put(INSERT_NEWLINE_NAME, newLineAction);
850:
851:                }
852:
853:                private Border _createBorder() {
854:                    Border outerouter = BorderFactory.createLineBorder(
855:                            _bgColor, OUTER_BUFFER_WIDTH);
856:                    Border outer = BorderFactory.createLineBorder(_fgColor,
857:                            BORDER_WIDTH);
858:                    Border inner = BorderFactory.createLineBorder(_bgColor,
859:                            INNER_BUFFER_WIDTH);
860:                    Border temp = BorderFactory.createCompoundBorder(outer,
861:                            inner);
862:                    return BorderFactory.createCompoundBorder(outerouter, temp);
863:                }
864:
865:                /** Enable anti-aliased text by overriding paintComponent. */
866:                protected void paintComponent(Graphics g) {
867:                    if (_antiAliasText && g instanceof  Graphics2D) {
868:                        Graphics2D g2d = (Graphics2D) g;
869:                        g2d.setRenderingHint(
870:                                RenderingHints.KEY_TEXT_ANTIALIASING,
871:                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
872:                    }
873:                    super .paintComponent(g);
874:                }
875:
876:                /** Specifies what to do when the <Enter> key is hit. */
877:                void setInputCompletionCommand(final Runnable command) {
878:                    final InputMap im = getInputMap(WHEN_FOCUSED);
879:                    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
880:                            INPUT_ENTERED_NAME);
881:
882:                    final ActionMap am = getActionMap();
883:                    am.put(INPUT_ENTERED_NAME, new AbstractAction() {
884:                        public void actionPerformed(ActionEvent e) {
885:                            command.run();
886:                        }
887:                    });
888:                }
889:
890:                /** Generates a lambda that can be used to insert text into this input box.  Only runs in event thread.
891:                 * @return A lambda that inserts the given text into the textbox when applied
892:                 */
893:                Lambda<String, String> makeInsertTextCommand() {
894:                    return new Lambda<String, String>() {
895:                        public String apply(String input) {
896:                            insert(input, getCaretPosition());
897:                            return input;
898:                        }
899:                    };
900:                }
901:
902:                /** Behaves somewhat like setEnable(false) in that it disables all
903:                 * input to the text box, but it does not change the appearance of the text.
904:                 */
905:                void disableInputs() {
906:                    setEditable(false);
907:
908:                    ActionMap am = getActionMap();
909:                    Action action;
910:
911:                    action = am.get(INPUT_ENTERED_NAME);
912:                    if (action != null)
913:                        action.setEnabled(false);
914:
915:                    action = am.get(INSERT_NEWLINE_NAME);
916:                    if (action != null)
917:                        action.setEnabled(false);
918:
919:                    getCaret().setVisible(false);
920:                }
921:            }
922:
923:            /** A listener interface that allows for others outside the interactions controller to be notified when the input
924:             * console is enabled in the interactions pane.
925:             */
926:            public interface ConsoleStateListener extends EventListener {
927:
928:                /** Called when the input console is started in the interactions pane. <p>
929:                 * This method is called from the thread that initiated the console input,
930:                 */
931:                public void consoleInputStarted(InteractionsController c);
932:
933:                /** Called when the console input is complete. <p>
934:                 * This method is called from the thread that initiated the console input.
935:                 * @param result The text that was inputted to the console
936:                 */
937:                public void consoleInputCompleted(String result,
938:                        InteractionsController c);
939:
940:            }
941:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.