PlainDocumentpublic class PlainDocument extends AbstractDocument A plain document that maintains no character attributes. The
default element structure for this document is a map of the lines in
the text. The Element returned by getDefaultRootElement is
a map of the lines, and each child element represents a line.
This model does not maintain any character level attributes,
but each line can be tagged with an arbitrary set of attributes.
Line to offset, and offset to line translations can be quickly
performed using the default root element. The structure information
of the DocumentEvent's fired by edits will indicate the line
structure changes.
The default content storage management is performed by a
gapped buffer implementation (GapContent). It supports
editing reasonably large documents with good efficiency when
the edits are contiguous or clustered, as is typical.
Warning:
Serialized objects of this class will not be compatible with
future Swing releases. The current serialization support is
appropriate for short term storage or RMI between applications running
the same version of Swing. As of 1.4, support for long term storage
of all JavaBeansTM
has been added to the java.beans package.
Please see {@link java.beans.XMLEncoder}. |
Fields Summary |
---|
public static final String | tabSizeAttributeName of the attribute that specifies the tab
size for tabs contained in the content. The
type for the value is Integer. | public static final String | lineLimitAttributeName of the attribute that specifies the maximum
length of a line, if there is a maximum length.
The type for the value is Integer. | private AbstractElement | defaultRoot | private Vector | added | private Vector | removed | private transient Segment | s |
Constructors Summary |
---|
public PlainDocument()Constructs a plain text document. A default model using
GapContent is constructed and set.
this(new GapContent());
| public PlainDocument(Content c)Constructs a plain text document. A default root element is created,
and the tab size set to 8.
super(c);
putProperty(tabSizeAttribute, new Integer(8));
defaultRoot = createDefaultRoot();
|
Methods Summary |
---|
protected AbstractElement | createDefaultRoot()Creates the root element to be used to represent the
default document structure.
BranchElement map = (BranchElement) createBranchElement(null, null);
Element line = createLeafElement(map, null, 0, 1);
Element[] lines = new Element[1];
lines[0] = line;
map.replace(0, 0, lines);
return map;
| public javax.swing.text.Element | getDefaultRootElement()Gets the default root element for the document model.
return defaultRoot;
| public javax.swing.text.Element | getParagraphElement(int pos)Get the paragraph element containing the given position. Since this
document only models lines, it returns the line instead.
Element lineMap = getDefaultRootElement();
return lineMap.getElement( lineMap.getElementIndex( pos ) );
| private void | insertComposedTextUpdate(DefaultDocumentEvent chng, javax.swing.text.AttributeSet attr)
added.removeAllElements();
BranchElement lineMap = (BranchElement) getDefaultRootElement();
int offset = chng.getOffset();
int length = chng.getLength();
int index = lineMap.getElementIndex(offset);
Element elem = lineMap.getElement(index);
int elemStart = elem.getStartOffset();
int elemEnd = elem.getEndOffset();
BranchElement[] abelem = new BranchElement[1];
abelem[0] = (BranchElement) createBranchElement(lineMap, null);
Element[] relem = new Element[1];
relem[0] = elem;
if (elemStart != offset)
added.addElement(createLeafElement(abelem[0], null, elemStart, offset));
added.addElement(createLeafElement(abelem[0], attr, offset, offset+length));
if (elemEnd != offset+length)
added.addElement(createLeafElement(abelem[0], null, offset+length, elemEnd));
Element[] alelem = new Element[added.size()];
added.copyInto(alelem);
ElementEdit ee = new ElementEdit(lineMap, index, relem, abelem);
chng.addEdit(ee);
abelem[0].replace(0, 0, alelem);
lineMap.replace(index, 1, abelem);
| public void | insertString(int offs, java.lang.String str, javax.swing.text.AttributeSet a)Inserts some content into the document.
Inserting content causes a write lock to be held while the
actual changes are taking place, followed by notification
to the observers on the thread that grabbed the write lock.
This method is thread safe, although most Swing methods
are not. Please see
How
to Use Threads for more information.
// fields don't want to have multiple lines. We may provide a field-specific
// model in the future in which case the filtering logic here will no longer
// be needed.
Object filterNewlines = getProperty("filterNewlines");
if ((filterNewlines instanceof Boolean) && filterNewlines.equals(Boolean.TRUE)) {
if ((str != null) && (str.indexOf('\n") >= 0)) {
StringBuffer filtered = new StringBuffer(str);
int n = filtered.length();
for (int i = 0; i < n; i++) {
if (filtered.charAt(i) == '\n") {
filtered.setCharAt(i, ' ");
}
}
str = filtered.toString();
}
}
super.insertString(offs, str, a);
| protected void | insertUpdate(DefaultDocumentEvent chng, javax.swing.text.AttributeSet attr)Updates document structure as a result of text insertion. This
will happen within a write lock. Since this document simply
maps out lines, we refresh the line map.
removed.removeAllElements();
added.removeAllElements();
BranchElement lineMap = (BranchElement) getDefaultRootElement();
int offset = chng.getOffset();
int length = chng.getLength();
if (offset > 0) {
offset -= 1;
length += 1;
}
int index = lineMap.getElementIndex(offset);
Element rmCandidate = lineMap.getElement(index);
int rmOffs0 = rmCandidate.getStartOffset();
int rmOffs1 = rmCandidate.getEndOffset();
int lastOffset = rmOffs0;
try {
if (s == null) {
s = new Segment();
}
getContent().getChars(offset, length, s);
boolean hasBreaks = false;
for (int i = 0; i < length; i++) {
char c = s.array[s.offset + i];
if (c == '\n") {
int breakOffset = offset + i + 1;
added.addElement(createLeafElement(lineMap, null, lastOffset, breakOffset));
lastOffset = breakOffset;
hasBreaks = true;
}
}
if (hasBreaks) {
int rmCount = 1;
removed.addElement(rmCandidate);
if ((offset + length == rmOffs1) && (lastOffset != rmOffs1) &&
((index+1) < lineMap.getElementCount())) {
rmCount += 1;
Element e = lineMap.getElement(index+1);
removed.addElement(e);
rmOffs1 = e.getEndOffset();
}
if (lastOffset < rmOffs1) {
added.addElement(createLeafElement(lineMap, null, lastOffset, rmOffs1));
}
Element[] aelems = new Element[added.size()];
added.copyInto(aelems);
Element[] relems = new Element[removed.size()];
removed.copyInto(relems);
ElementEdit ee = new ElementEdit(lineMap, index, relems, aelems);
chng.addEdit(ee);
lineMap.replace(index, relems.length, aelems);
}
if (Utilities.isComposedTextAttributeDefined(attr)) {
insertComposedTextUpdate(chng, attr);
}
} catch (BadLocationException e) {
throw new Error("Internal error: " + e.toString());
}
super.insertUpdate(chng, attr);
| protected void | removeUpdate(DefaultDocumentEvent chng)Updates any document structure as a result of text removal.
This will happen within a write lock. Since the structure
represents a line map, this just checks to see if the
removal spans lines. If it does, the two lines outside
of the removal area are joined together.
removed.removeAllElements();
BranchElement map = (BranchElement) getDefaultRootElement();
int offset = chng.getOffset();
int length = chng.getLength();
int line0 = map.getElementIndex(offset);
int line1 = map.getElementIndex(offset + length);
if (line0 != line1) {
// a line was removed
for (int i = line0; i <= line1; i++) {
removed.addElement(map.getElement(i));
}
int p0 = map.getElement(line0).getStartOffset();
int p1 = map.getElement(line1).getEndOffset();
Element[] aelems = new Element[1];
aelems[0] = createLeafElement(map, null, p0, p1);
Element[] relems = new Element[removed.size()];
removed.copyInto(relems);
ElementEdit ee = new ElementEdit(map, line0, relems, aelems);
chng.addEdit(ee);
map.replace(line0, relems.length, aelems);
} else {
//Check for the composed text element
Element line = map.getElement(line0);
if (!line.isLeaf()) {
Element leaf = line.getElement(line.getElementIndex(offset));
if (Utilities.isComposedTextElement(leaf)) {
Element[] aelem = new Element[1];
aelem[0] = createLeafElement(map, null,
line.getStartOffset(), line.getEndOffset());
Element[] relem = new Element[1];
relem[0] = line;
ElementEdit ee = new ElementEdit(map, line0, relem, aelem);
chng.addEdit(ee);
map.replace(line0, 1, aelem);
}
}
}
super.removeUpdate(chng);
|
|