|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| SwingDocument.java | 92.9% | 72.9% | 73.9% | 76.5% |
|
||||||||||||||
| 1 | /*BEGIN_COPYRIGHT_BLOCK | |
| 2 | * | |
| 3 | * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu) | |
| 4 | * All rights reserved. | |
| 5 | * | |
| 6 | * Redistribution and use in source and binary forms, with or without | |
| 7 | * modification, are permitted provided that the following conditions are met: | |
| 8 | * * Redistributions of source code must retain the above copyright | |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 10 | * * Redistributions in binary form must reproduce the above copyright | |
| 11 | * notice, this list of conditions and the following disclaimer in the | |
| 12 | * documentation and/or other materials provided with the distribution. | |
| 13 | * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the | |
| 14 | * names of its contributors may be used to endorse or promote products | |
| 15 | * derived from this software without specific prior written permission. | |
| 16 | * | |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 18 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 20 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
| 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 28 | * | |
| 29 | * This software is Open Source Initiative approved Open Source Software. | |
| 30 | * Open Source Initative Approved is a trademark of the Open Source Initiative. | |
| 31 | * | |
| 32 | * This file is part of DrJava. Download the current version of this project | |
| 33 | * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/ | |
| 34 | * | |
| 35 | * END_COPYRIGHT_BLOCK*/ | |
| 36 | ||
| 37 | package edu.rice.cs.util.text; | |
| 38 | ||
| 39 | import java.awt.EventQueue; | |
| 40 | import java.awt.print.Pageable; | |
| 41 | ||
| 42 | import javax.swing.text.DefaultStyledDocument; | |
| 43 | import javax.swing.text.AttributeSet; | |
| 44 | import javax.swing.text.Position; | |
| 45 | import javax.swing.text.BadLocationException; | |
| 46 | ||
| 47 | import edu.rice.cs.util.UnexpectedException; | |
| 48 | import edu.rice.cs.util.swing.Utilities; | |
| 49 | ||
| 50 | import java.util.HashMap; | |
| 51 | ||
| 52 | /** A swing implementation of the toolkit-independent EditDocumentInterface. This document should use the | |
| 53 | * readers/writers locking protocol established in its superclasses but it does not. Under unfavorable | |
| 54 | * schedules, methods like append will generate run-time errors because the document can change between the | |
| 55 | * determination of its length and the insertion of the appended text. An operation in the document is safe | |
| 56 | * only if the proper lock is held before it is called OR all update and operations involving multiple reads | |
| 57 | * are performed in the event thread. | |
| 58 | * | |
| 59 | * TODO: create a separate DummySwingDocument class for testing and make SwingDocument abstract. | |
| 60 | * @version $Id: SwingDocument.java 5444 2011-08-17 07:54:58Z rcartwright $ | |
| 61 | */ | |
| 62 | public class SwingDocument extends DefaultStyledDocument implements EditDocumentInterface, AbstractDocumentInterface { | |
| 63 | ||
| 64 | /** The modified state. */ | |
| 65 | protected volatile boolean _isModifiedSinceSave = false; | |
| 66 | ||
| 67 | /** Maps names to attribute sets */ | |
| 68 | final protected HashMap<String, AttributeSet> _styles; | |
| 69 | ||
| 70 | /** Determines which edits are legal on this document. */ | |
| 71 | protected DocumentEditCondition _condition; | |
| 72 | ||
| 73 | /** Creates a new document adapter for a Swing StyledDocument. TODO: convert _styles and _condition to lazily | |
| 74 | * initialized volatiles as soon as support for Java 1.4 is dropped and the double-check idiom is safe. */ | |
| 75 | 1907 | public SwingDocument() { |
| 76 | 1907 | _styles = new HashMap<String, AttributeSet>(); |
| 77 | 1907 | _condition = new DocumentEditCondition(); |
| 78 | } | |
| 79 | ||
| 80 | /** Adds the given AttributeSet as a style with the given name. It can then be used in insertString. | |
| 81 | * @param name Name of the style, to be passed to insertString | |
| 82 | * @param s AttributeSet to use for the style | |
| 83 | */ | |
| 84 | 940 | public void setDocStyle(String name, AttributeSet s) { |
| 85 | 940 | _styles.put(name, s); // no locking necessary: _styles is final and Hashtable is thread-safe |
| 86 | } | |
| 87 | ||
| 88 | /** Returns the style with the given name, or null if no such named style exists. */ | |
| 89 | 689 | public AttributeSet getDocStyle(String name) { |
| 90 | 689 | return _styles.get(name); // no locking necessary: _styles is final and Hashtable is thread-safe |
| 91 | } | |
| 92 | ||
| 93 | /** Adds the given coloring style to the styles list. Not supported in SwingDocument. ONly runs in event thread. */ | |
| 94 | 0 | public void addColoring(int start, int end, String style) { } |
| 95 | ||
| 96 | /** Gets the object which can determine whether an insert or remove edit should be applied, based on the inputs. | |
| 97 | * @return an Object to determine legality of inputs | |
| 98 | */ | |
| 99 | 0 | public DocumentEditCondition getEditCondition() { return _condition; } |
| 100 | ||
| 101 | /** Provides an object which can determine whether an insert or remove edit should be applied, based on the inputs. | |
| 102 | * @param condition Object to determine legality of inputs | |
| 103 | */ | |
| 104 | 358 | public void setEditCondition(DocumentEditCondition condition) { _condition = condition; } |
| 105 | ||
| 106 | /* Clears the document. */ | |
| 107 | 0 | public void clear() { |
| 108 | 0 | try { remove(0, getLength()); } |
| 109 | 0 | catch(BadLocationException e) { throw new UnexpectedException(e); } |
| 110 | } | |
| 111 | ||
| 112 | /** Inserts a string into the document at the given offset and style, if the edit condition allows it. | |
| 113 | * @param offs Offset into the document | |
| 114 | * @param str String to be inserted | |
| 115 | * @param style Name of the style to use. Must have been added using addStyle. | |
| 116 | * @throws EditDocumentException if the offset is illegal | |
| 117 | */ | |
| 118 | 383 | public void insertText(int offs, String str, String style) { |
| 119 | 379 | if (_condition.canInsertText(offs)) forceInsertText(offs, str, style); |
| 120 | } | |
| 121 | ||
| 122 | /** Inserts a string into the document at the given offset and style, regardless of the edit condition. | |
| 123 | * @param offs Offset into the document | |
| 124 | * @param str String to be inserted | |
| 125 | * @param style Name of the style to use. Must have been added using addStyle. | |
| 126 | * @throws EditDocumentException if the offset is illegal | |
| 127 | */ | |
| 128 | 708 | public void forceInsertText(int offs, String str, String style) { |
| 129 | 708 | int len = getLength(); |
| 130 | 708 | if ((offs < 0) || (offs > len)) { |
| 131 | 2 | String msg = "Offset " + offs + " passed to SwingDocument.forceInsertText is out of bounds [0, " + len + "]"; |
| 132 | 2 | throw new EditDocumentException(null, msg); |
| 133 | } | |
| 134 | 706 | AttributeSet s = null; |
| 135 | 689 | if (style != null) s = getDocStyle(style); |
| 136 | 706 | try { super.insertString(offs, str, s); } |
| 137 | 0 | catch (BadLocationException e) { throw new EditDocumentException(e); } // should never happen |
| 138 | } | |
| 139 | ||
| 140 | /** Overrides superclass's insertString to impose the edit condition. The AttributeSet is ignored in the condition, | |
| 141 | * which sees a null style name. | |
| 142 | */ | |
| 143 | 973 | public void insertString(int offs, String str, AttributeSet set) throws BadLocationException { |
| 144 | // Assertion commented out because it does not hold at startup. See DrJava bug 2321815. | |
| 145 | /* assert Utilities.TEST_MODE || EventQueue.isDispatchThread(); */ | |
| 146 | 972 | if (_condition.canInsertText(offs)) super.insertString(offs, str, set); |
| 147 | } | |
| 148 | ||
| 149 | /** Removes a portion of the document, if the edit condition allows it. | |
| 150 | * @param offs Offset to start deleting from | |
| 151 | * @param len Number of characters to remove | |
| 152 | * @throws EditDocumentException if the offset or length are illegal | |
| 153 | */ | |
| 154 | 54 | public void removeText(int offs, int len) { |
| 155 | 51 | if (_condition.canRemoveText(offs)) forceRemoveText(offs, len); |
| 156 | } | |
| 157 | ||
| 158 | /** Removes a portion of the document, regardless of the edit condition. | |
| 159 | * @param offs Offset to start deleting from | |
| 160 | * @param len Number of characters to remove | |
| 161 | * @throws EditDocumentException if the offset or length are illegal | |
| 162 | */ | |
| 163 | 59 | public void forceRemoveText(int offs, int len) { |
| 164 | 59 | try { super.remove(offs, len); } |
| 165 | 0 | catch (BadLocationException e) { throw new EditDocumentException(e); } |
| 166 | } | |
| 167 | ||
| 168 | /** Overrides superclass's remove to impose the edit condition. */ | |
| 169 | 397 | public void remove(int offs, int len) throws BadLocationException { |
| 170 | 396 | if (_condition.canRemoveText(offs)) super.remove(offs, len); |
| 171 | } | |
| 172 | ||
| 173 | // /** Returns the length of the document. */ | |
| 174 | // public int getDocLength() { return getLength(); } // locking is unnecessary because getLength is already thread-safe | |
| 175 | ||
| 176 | /** Returns a portion of the document. | |
| 177 | * @param offs First offset of the desired text | |
| 178 | * @param len Number of characters to return | |
| 179 | * @throws EditDocumentException if the offset or length are illegal | |
| 180 | */ | |
| 181 | 151 | public String getDocText(int offs, int len) { |
| 182 | 151 | try { return getText(offs, len); } // locking is unnecessary because getText is already thread-safe |
| 183 | 0 | catch (BadLocationException e) { throw new EditDocumentException(e); } |
| 184 | } | |
| 185 | ||
| 186 | /** Gets the document text; this method is threadsafe. */ | |
| 187 | 9509 | public String getText() { |
| 188 | 9509 | try { return getText(0, getLength()); } // calls method defined in DefaultStyledDocument |
| 189 | 0 | catch (BadLocationException e) { throw new UnexpectedException(e); } // impossible if read lock is already held |
| 190 | } | |
| 191 | ||
| 192 | /** Sanitized version of getText(int, int) that converts BadLocationException to UnexpectedException. */ | |
| 193 | 29180 | public String _getText(int pos, int len) { |
| 194 | 29180 | try { return getText(pos, len); } // calls method defined in DefaultStyledDocument |
| 195 | 0 | catch (BadLocationException e) { throw new UnexpectedException(e); } |
| 196 | } | |
| 197 | ||
| 198 | /** Appends given string with specified attributes to end of this document. */ | |
| 199 | 175 | public void append(String str, AttributeSet set) { |
| 200 | 175 | try { insertString(getLength(), str, set); } |
| 201 | 0 | catch (BadLocationException e) { throw new UnexpectedException(e); } // impossible |
| 202 | } | |
| 203 | ||
| 204 | /** Appends given string with specified named style to end of this document. */ | |
| 205 | 2 | public void append(String str, String style) { append(str, style == null ? null : getDocStyle(style)); } |
| 206 | ||
| 207 | /** Appends given string with default style to end of this document. */ | |
| 208 | 4 | public void append(String str) { append(str, (AttributeSet) null); } |
| 209 | ||
| 210 | /** A SwingDocument instance does not have a default style */ | |
| 211 | 0 | public String getDefaultStyle() { return null; } |
| 212 | ||
| 213 | 0 | public void print() { throw new UnsupportedOperationException("Printing not supported"); } |
| 214 | ||
| 215 | 0 | public Pageable getPageable() { throw new UnsupportedOperationException("Printing not supported"); } |
| 216 | ||
| 217 | /** Performs the default behavior for createPosition in DefaultStyledDocument. */ | |
| 218 | 6132 | public Position createUnwrappedPosition(int offs) throws BadLocationException { return super.createPosition(offs); } |
| 219 | } | |
| 220 |
|
||||||||||