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.model.repl;
038:
039: import edu.rice.cs.drjava.model.AbstractDJDocument;
040: import edu.rice.cs.drjava.model.definitions.indent.Indenter;
041: import edu.rice.cs.drjava.model.definitions.reducedmodel.*;
042:
043: import edu.rice.cs.plt.tuple.Pair;
044: import edu.rice.cs.util.UnexpectedException;
045: import edu.rice.cs.util.text.EditDocumentException;
046: import edu.rice.cs.util.text.ConsoleDocumentInterface;
047: import edu.rice.cs.util.text.ConsoleDocument;
048:
049: import java.io.*;
050: import java.awt.*;
051: import java.util.List;
052: import java.util.LinkedList;
053: import javax.swing.text.AbstractDocument;
054:
055: import static edu.rice.cs.drjava.model.definitions.ColoringView.*;
056:
057: /** Represents a Swing-based InteractionsDocument. Extends AbstractDJDocument which contains code shared by
058: * the Swing interactions and definitions documents.
059: */
060: public class InteractionsDJDocument extends AbstractDJDocument
061: implements ConsoleDocumentInterface {
062:
063: /** Whether the document currently has a prompt and is ready to accept input. */
064: private volatile boolean _hasPrompt;
065:
066: /** Holds a flag telling the adapter that the interpreter was recently reset, and to reset the styles list
067: * the next time a style is added. Cannot reset immediately because then the styles would be lost while
068: * the interactions pane is resetting.
069: */
070: private volatile boolean _toClear = false;
071:
072: /** Standard constructor. */
073: public InteractionsDJDocument() {
074: super ();
075: _hasPrompt = false;
076: }
077:
078: public boolean hasPrompt() {
079: return _hasPrompt;
080: }
081:
082: /** Sets the _hasPrompt property.
083: * @param val new boolean value for _hasPrompt.
084: */
085: public void setHasPrompt(boolean val) {
086: acquireWriteLock();
087: _hasPrompt = val;
088: releaseWriteLock();
089: }
090:
091: protected int startCompoundEdit() {
092: return 0; /* Do nothing */
093: }
094:
095: protected void endCompoundEdit(int key) { /* Do nothing */
096: }
097:
098: protected void endLastCompoundEdit() { /* Do nothing */
099: }
100:
101: protected void addUndoRedo(
102: AbstractDocument.DefaultDocumentEvent chng,
103: Runnable undoCommand, Runnable doCommand) {
104: }
105:
106: protected void _styleChanged() { /* Do nothing */
107: }
108:
109: /** Returns a new indenter. Eventually to be used to return an interactions indenter */
110: protected Indenter makeNewIndenter(int indentLevel) {
111: return new Indenter(indentLevel);
112: }
113:
114: /** A list of styles and their locations. This list holds pairs of locations in the document and styles, which
115: * is basically a map of regions where the coloring view that is now attached to the Interactions Pane is not
116: * allowed to use the reduced model to determine the color settings when rendering text. We keep a list of all
117: * places where styles not considered by the reduced model are being used, such as System.out, System.err,
118: * and the various return styles for Strings and other Objects. Since the LinkedList class is not thread safe,
119: * we have to synchronized all methods that access pointers in _stylesList and the associated boolean _toClear.
120: */
121: private List<Pair<Pair<Integer, Integer>, String>> _stylesList = new LinkedList<Pair<Pair<Integer, Integer>, String>>();
122:
123: /** Adds the given coloring style to the styles list. */
124: public void addColoring(int start, int end, String style) {
125: synchronized (_stylesList) {
126: if (_toClear) {
127: _stylesList.clear();
128: _toClear = false;
129: }
130: if (style != null)
131: _stylesList.add(0,
132: new Pair<Pair<Integer, Integer>, String>(
133: new Pair<Integer, Integer>(new Integer(
134: start), new Integer(end)),
135: style));
136: }
137: }
138:
139: /** Package protected accessor method used for test cases */
140: List<Pair<Pair<Integer, Integer>, String>> getStylesList() {
141: return _stylesList;
142: }
143:
144: /** Attempts to set the coloring on the graphics based upon the content of the styles list
145: * returns false if the point is not in the list.
146: */
147: public boolean setColoring(int point, Graphics g) {
148: synchronized (_stylesList) {
149: for (Pair<Pair<Integer, Integer>, String> p : _stylesList) {
150: Pair<Integer, Integer> loc = p.first();
151: if (loc.first() <= point && loc.second() >= point) {
152: if (p.second().equals(
153: InteractionsDocument.ERROR_STYLE)) {
154: //DrJava.consoleErr().println("Error Style");
155: g.setColor(ERROR_COLOR);
156: g.setFont(g.getFont().deriveFont(Font.BOLD));
157: } else if (p.second().equals(
158: InteractionsDocument.DEBUGGER_STYLE)) {
159: //DrJava.consoleErr().println("Debugger Style");
160: g.setColor(DEBUGGER_COLOR);
161: g.setFont(g.getFont().deriveFont(Font.BOLD));
162: } else if (p.second().equals(
163: ConsoleDocument.SYSTEM_OUT_STYLE)) {
164: //DrJava.consoleErr().println("System.out Style");
165: g.setColor(INTERACTIONS_SYSTEM_OUT_COLOR);
166: g.setFont(MAIN_FONT);
167: } else if (p.second().equals(
168: ConsoleDocument.SYSTEM_IN_STYLE)) {
169: //DrJava.consoleErr().println("System.in Style");
170: g.setColor(INTERACTIONS_SYSTEM_IN_COLOR);
171: g.setFont(MAIN_FONT);
172: } else if (p.second().equals(
173: ConsoleDocument.SYSTEM_ERR_STYLE)) {
174: //DrJava.consoleErr().println("System.err Style");
175: g.setColor(INTERACTIONS_SYSTEM_ERR_COLOR);
176: g.setFont(MAIN_FONT);
177: } else if (p.second().equals(
178: InteractionsDocument.OBJECT_RETURN_STYLE)) {
179: g.setColor(NORMAL_COLOR);
180: g.setFont(MAIN_FONT);
181: } else if (p.second().equals(
182: InteractionsDocument.STRING_RETURN_STYLE)) {
183: g.setColor(DOUBLE_QUOTED_COLOR);
184: g.setFont(MAIN_FONT);
185: } else if (p.second().equals(
186: InteractionsDocument.NUMBER_RETURN_STYLE)) {
187: g.setColor(NUMBER_COLOR);
188: g.setFont(MAIN_FONT);
189: } else if (p
190: .second()
191: .equals(
192: InteractionsDocument.CHARACTER_RETURN_STYLE)) {
193: g.setColor(SINGLE_QUOTED_COLOR);
194: g.setFont(MAIN_FONT);
195: } else
196: return false; /* Normal text color */
197:
198: return true;
199: }
200: }
201: return false;
202: }
203: }
204:
205: /** Attempts to set the font on the graphics context based upon the styles held in the styles list. */
206: public void setBoldFonts(int point, Graphics g) {
207: synchronized (_stylesList) {
208: for (Pair<Pair<Integer, Integer>, String> p : _stylesList) {
209: Pair<Integer, Integer> loc = p.first();
210: if (loc.first() <= point && loc.second() >= point) {
211: if (p.second().equals(
212: InteractionsDocument.ERROR_STYLE))
213: g.setFont(g.getFont().deriveFont(Font.BOLD));
214: else if (p.second().equals(
215: InteractionsDocument.DEBUGGER_STYLE))
216: g.setFont(g.getFont().deriveFont(Font.BOLD));
217: else
218: g.setFont(MAIN_FONT);
219: return;
220: }
221: }
222: }
223: }
224:
225: /** Called when the Interactions pane is reset. */
226: public void clearColoring() {
227: synchronized (_stylesList) {
228: _toClear = true;
229: }
230: }
231:
232: /** Returns true iff the end of the current interaction is an open comment block
233: * @return true iff the end of the current interaction is an open comment block
234: */
235: public boolean inCommentBlock() {
236: acquireReadLock();
237: try {
238: synchronized (_reduced) {
239: resetReducedModelLocation();
240: ReducedModelState state = stateAtRelLocation(getLength()
241: - _currentLocation);
242: boolean toReturn = (state
243: .equals(ReducedModelStates.INSIDE_BLOCK_COMMENT));
244: return toReturn;
245: }
246: } finally {
247: releaseReadLock();
248: }
249: }
250:
251: /** Inserts the given exception data into the document with the given style.
252: * @param exceptionClass Name of the exception that was thrown
253: * @param message Message contained in the exception
254: * @param stackTrace String representation of the stack trace
255: * @param styleName name of the style for formatting the exception
256: */
257: public void appendExceptionResult(String exceptionClass,
258: String message, String stackTrace, String styleName) {
259:
260: String c = exceptionClass;
261: if (c.indexOf('.') != -1)
262: c = c.substring(c.lastIndexOf('.') + 1, c.length());
263:
264: acquireWriteLock();
265: try {
266: insertText(getLength(), c + ": " + message + "\n",
267: styleName);
268:
269: // An example stack trace:
270: //
271: // java.lang.IllegalMonitorStateException:
272: // at java.lang.Object.wait(Native Method)
273: // at java.lang.Object.wait(Object.java:425)
274: if (!stackTrace.trim().equals("")) {
275: BufferedReader reader = new BufferedReader(
276: new StringReader(stackTrace));
277:
278: String line;
279: // a line is parsable if it has ( then : then ), with some
280: // text between each of those
281: while ((line = reader.readLine()) != null) {
282: String fileName;
283: int lineNumber;
284:
285: // TODO: Why is this stuff here??
286: int openLoc = line.indexOf('(');
287: if (openLoc != -1) {
288: int closeLoc = line.indexOf(')', openLoc + 1);
289:
290: if (closeLoc != -1) {
291: int colonLoc = line.indexOf(':',
292: openLoc + 1);
293: if ((colonLoc > openLoc)
294: && (colonLoc < closeLoc)) {
295: // ok this line is parsable!
296: String lineNumStr = line.substring(
297: colonLoc + 1, closeLoc);
298: try {
299: lineNumber = Integer
300: .parseInt(lineNumStr);
301: fileName = line.substring(
302: openLoc + 1, colonLoc);
303: } catch (NumberFormatException nfe) {
304: // do nothing; we failed at parsing
305: }
306: }
307: }
308: }
309:
310: insertText(getLength(), line, styleName);
311:
312: // OK, now if fileName != null we did parse out fileName
313: // and lineNumber.
314: // Here's where we'd add the button, etc.
315: /*
316: if (fileName != null) {
317: JButton button = new JButton("go");
318: button.addActionListener(new ExceptionButtonListener(fileName, lineNumber));
319: SimpleAttributeSet buttonSet = new SimpleAttributeSet(set);
320: StyleConstants.setComponent(buttonSet, button);
321: insertString(getLength(), " ", null);
322: insertString(getLength() - 1, " ", buttonSet);
323: JOptionPane.showMessageDialog(null, "button in");
324: insertString(getLength(), " ", null);
325: JOptionPane.showMessageDialog(null, "extra space");
326: }*/
327:
328: //JOptionPane.showMessageDialog(null, "\\n");
329: insertText(getLength(), "\n", styleName);
330:
331: } // end the while
332: }
333: } catch (IOException ioe) {
334: throw new UnexpectedException(ioe);
335: } catch (EditDocumentException ble) {
336: throw new UnexpectedException(ble);
337: } finally {
338: releaseWriteLock();
339: }
340: }
341: }
|