summaryrefslogtreecommitdiff
path: root/javax/swing/text
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2005-09-20 18:46:20 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2005-09-20 18:46:20 +0000
commit3baed5090a8b63218fd8a5808cd38caeb79a0f7d (patch)
treee3d5427d27e9ef1ebb9de69a3fd3639084d196d1 /javax/swing/text
parentd30cf1c6c0de86bac88773529f7071497ce18916 (diff)
downloadclasspath-3baed5090a8b63218fd8a5808cd38caeb79a0f7d.tar.gz
2005-09-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of generics-branch for 2005/09/07 - 2005/09/20 @ 10:05am GMT.
Diffstat (limited to 'javax/swing/text')
-rw-r--r--javax/swing/text/AbstractDocument.java129
-rw-r--r--javax/swing/text/BoxView.java7
-rw-r--r--javax/swing/text/ComponentView.java98
-rw-r--r--javax/swing/text/CompositeView.java3
-rw-r--r--javax/swing/text/DefaultCaret.java6
-rw-r--r--javax/swing/text/DefaultEditorKit.java21
-rw-r--r--javax/swing/text/DefaultFormatter.java10
-rw-r--r--javax/swing/text/DefaultStyledDocument.java677
-rw-r--r--javax/swing/text/GapContent.java206
-rw-r--r--javax/swing/text/GlyphView.java602
-rw-r--r--javax/swing/text/InternationalFormatter.java5
-rw-r--r--javax/swing/text/JTextComponent.java10
-rw-r--r--javax/swing/text/PlainView.java16
-rw-r--r--javax/swing/text/SimpleAttributeSet.java15
-rw-r--r--javax/swing/text/StringContent.java3
-rw-r--r--javax/swing/text/StyleConstants.java2
-rw-r--r--javax/swing/text/StyleContext.java8
-rw-r--r--javax/swing/text/StyledEditorKit.java24
-rw-r--r--javax/swing/text/TabSet.java3
-rw-r--r--javax/swing/text/TabStop.java3
-rw-r--r--javax/swing/text/Utilities.java85
-rw-r--r--javax/swing/text/View.java1
-rw-r--r--javax/swing/text/html/CSS.java426
-rw-r--r--javax/swing/text/html/parser/DTD.java3
24 files changed, 2121 insertions, 242 deletions
diff --git a/javax/swing/text/AbstractDocument.java b/javax/swing/text/AbstractDocument.java
index 3c9a4d497..660cd2b09 100644
--- a/javax/swing/text/AbstractDocument.java
+++ b/javax/swing/text/AbstractDocument.java
@@ -65,11 +65,10 @@ import javax.swing.undo.UndoableEdit;
* @author original author unknown
* @author Roman Kennke (roman@kennke.org)
*/
-public abstract class AbstractDocument
- implements Document, Serializable
+public abstract class AbstractDocument implements Document, Serializable
{
- /** The serial version UID for this class as of JDK1.4. */
- private static final long serialVersionUID = -116069779446114664L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 6842927725919637215L;
/**
* Standard error message to indicate a bad location.
@@ -332,7 +331,7 @@ public abstract class AbstractDocument
* @see GapContent
* @see StringContent
*/
- protected Content getContent()
+ protected final Content getContent()
{
return content;
}
@@ -970,8 +969,8 @@ public abstract class AbstractDocument
public abstract class AbstractElement
implements Element, MutableAttributeSet, TreeNode, Serializable
{
- /** The serial version UID for AbstractElement. */
- private static final long serialVersionUID = 1265312733007397733L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 1712240033321461704L;
/** The number of characters that this Element spans. */
int count;
@@ -1355,49 +1354,6 @@ public abstract class AbstractDocument
public abstract int getStartOffset();
/**
- * Prints diagnostic information to the specified stream.
- *
- * @param stream the stream to dump to
- * @param indent the indentation level
- * @param element the element to be dumped
- */
- private void dumpElement(PrintStream stream, String indent,
- Element element)
- {
- // FIXME: Should the method be removed?
- System.out.println(indent + "<" + element.getName() +">");
-
- if (element.isLeaf())
- {
- int start = element.getStartOffset();
- int end = element.getEndOffset();
- String text = "";
- try
- {
- text = getContent().getString(start, end - start);
- }
- catch (BadLocationException e)
- {
- AssertionError error =
- new AssertionError("BadLocationException should not be "
- + "thrown here. start = " + start
- + ", end = " + end);
- error.initCause(e);
- throw error;
- }
- System.out.println(indent + " ["
- + start + ","
- + end + "]["
- + text + "]");
- }
- else
- {
- for (int i = 0; i < element.getElementCount(); ++i)
- dumpElement(stream, indent + " ", element.getElement(i));
- }
- }
-
- /**
* Prints diagnostic output to the specified stream.
*
* @param stream the stream to write to
@@ -1405,10 +1361,65 @@ public abstract class AbstractDocument
*/
public void dump(PrintStream stream, int indent)
{
- String indentStr = "";
+ StringBuffer b = new StringBuffer();
for (int i = 0; i < indent; ++i)
- indentStr += " ";
- dumpElement(stream, indentStr, this);
+ b.append(' ');
+ b.append('<');
+ b.append(getName());
+ // Dump attributes if there are any.
+ if (getAttributeCount() > 0)
+ {
+ b.append('\n');
+ Enumeration attNames = getAttributeNames();
+ while (attNames.hasMoreElements())
+ {
+ for (int i = 0; i < indent + 2; ++i)
+ b.append(' ');
+ Object attName = attNames.nextElement();
+ b.append(attName);
+ b.append('=');
+ Object attribute = getAttribute(attName);
+ b.append(attribute);
+ b.append('\n');
+ }
+ }
+ b.append(">\n");
+
+ // Dump element content for leaf elements.
+ if (isLeaf())
+ {
+ for (int i = 0; i < indent + 2; ++i)
+ b.append(' ');
+ int start = getStartOffset();
+ int end = getEndOffset();
+ b.append('[');
+ b.append(start);
+ b.append(',');
+ b.append(end);
+ b.append("][");
+ try
+ {
+ b.append(getDocument().getText(start, end - start));
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("BadLocationException "
+ + "must not be thrown "
+ + "here.");
+ err.initCause(ex);
+ }
+ b.append("]\n");
+ }
+ stream.print(b.toString());
+
+ // Dump child elements if any.
+ int count = getElementCount();
+ for (int i = 0; i < count; ++i)
+ {
+ Element el = getElement(i);
+ if (el instanceof AbstractElement)
+ ((AbstractElement) el).dump(stream, indent + 2);
+ }
}
}
@@ -1418,8 +1429,8 @@ public abstract class AbstractDocument
*/
public class BranchElement extends AbstractElement
{
- /** The serial version UID for BranchElement. */
- private static final long serialVersionUID = -8595176318868717313L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6037216547466333183L;
/** The child elements of this BranchElement. */
private Element[] children = new Element[0];
@@ -1642,8 +1653,8 @@ public abstract class AbstractDocument
public class DefaultDocumentEvent extends CompoundEdit
implements DocumentEvent
{
- /** The serial version UID of DefaultDocumentEvent. */
- private static final long serialVersionUID = -7406103236022413522L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 5230037221564563284L;
/** The starting offset of the change. */
private int offset;
@@ -1843,8 +1854,8 @@ public abstract class AbstractDocument
*/
public class LeafElement extends AbstractElement
{
- /** The serial version UID of LeafElement. */
- private static final long serialVersionUID = 5115368706941283802L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -8906306331347768017L;
/** Manages the start offset of this element. */
Position startPos;
diff --git a/javax/swing/text/BoxView.java b/javax/swing/text/BoxView.java
index 0f8ba1ce1..bc08626bd 100644
--- a/javax/swing/text/BoxView.java
+++ b/javax/swing/text/BoxView.java
@@ -221,7 +221,6 @@ public class BoxView
protected void paintChild(Graphics g, Rectangle alloc, int index)
{
View child = getView(index);
- childAllocation(index, alloc);
child.paint(g, alloc);
}
@@ -306,12 +305,8 @@ public class BoxView
int count = getViewCount();
for (int i = 0; i < count; ++i)
{
- // TODO: Figure out if the parameter to paintChild is meant to
- // be the child allocation or the allocation of this BoxView.
- // I assume the second option here.
- // We pass this method a copy of the inside rectangle here because
- // it modifies the actual values.
copy.setBounds(inside);
+ childAllocation(i, copy);
paintChild(g, copy, i);
}
}
diff --git a/javax/swing/text/ComponentView.java b/javax/swing/text/ComponentView.java
index f6feda215..e280e7c0c 100644
--- a/javax/swing/text/ComponentView.java
+++ b/javax/swing/text/ComponentView.java
@@ -1,5 +1,5 @@
/* ComponentView.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,32 +41,82 @@ import java.awt.Component;
import java.awt.Graphics;
import java.awt.Shape;
+/**
+ * A {@link View} implementation that is able to render arbitrary
+ * {@link Components}. This uses the attribute
+ * {@link StyleConstants#ComponentAttribute} to determine the
+ * <code>Component</code> that should be rendered. This <code>Component</code>
+ * becomes a direct child of the <code>JTextComponent</code> that contains
+ * this <code>ComponentView</code>, so this view must not be shared between
+ * multiple <code>JTextComponent</code>s.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman@kennke.org)
+ */
public class ComponentView extends View
{
- public ComponentView(Element elem)
- {
- super(elem);
- }
-
- protected Component createComponent()
- {
- return null;
- }
-
- public float getAlignment(int axis)
- {
- return 0;
- }
+ /**
+ * Creates a new instance of <code>ComponentView</code> for the specified
+ * <code>Element</code>.
+ *
+ * @param elem the element that this <code>View</code> is rendering
+ */
+ public ComponentView(Element elem)
+ {
+ super(elem);
+ }
- public final Component getComponent()
- {
- return null;
- }
-
- public float getMaximumSpan(int axis)
- {
- return 0;
- }
+ /**
+ * Creates the <code>Component</code> that this <code>View</code> is
+ * rendering. The <code>Component</code> is determined using
+ * the {@link StyleConstants#ComponentAttribute} of the associated
+ * <code>Element</code>.
+ *
+ * @return the component that is rendered
+ */
+ protected Component createComponent()
+ {
+ return StyleConstants.getComponent(getElement().getAttributes());
+ }
+
+ /**
+ * Returns the alignment of this <code>View</code> along the specified axis.
+ *
+ * @param axis either {@link View#X_AXIS} or {@link View#Y_AXIS}
+ *
+ * @return the alignment of this <code>View</code> along the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the <code>Component</code> that is rendered by this
+ * <code>ComponentView</code>.
+ *
+ * @return the <code>Component</code> that is rendered by this
+ * <code>ComponentView</code>
+ */
+ public final Component getComponent()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the maximum span of this <code>View</code> along the specified
+ * axis.
+ *
+ * This will return {@link Component#getMaximumSize()} for the specified
+ * axis.
+ *
+ * @return the maximum span of this <code>View</code> along the specified
+ * axis
+ */
+ public float getMaximumSpan(int axis)
+ {
+ return 0;
+ }
public float getMinimumSpan(int axis)
{
diff --git a/javax/swing/text/CompositeView.java b/javax/swing/text/CompositeView.java
index 6776c9572..b3dd6123e 100644
--- a/javax/swing/text/CompositeView.java
+++ b/javax/swing/text/CompositeView.java
@@ -314,6 +314,7 @@ public abstract class CompositeView
*/
public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
int direction, Position.Bias[] biasRet)
+ throws BadLocationException
{
int retVal = -1;
switch (direction)
@@ -594,6 +595,7 @@ public abstract class CompositeView
protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b,
Shape a, int direction,
Position.Bias[] biasRet)
+ throws BadLocationException
{
// FIXME: Implement this correctly.
return pos;
@@ -627,6 +629,7 @@ public abstract class CompositeView
protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b,
Shape a, int direction,
Position.Bias[] biasRet)
+ throws BadLocationException
{
// FIXME: Implement this correctly.
return pos;
diff --git a/javax/swing/text/DefaultCaret.java b/javax/swing/text/DefaultCaret.java
index 33c3ae3bf..c247afcff 100644
--- a/javax/swing/text/DefaultCaret.java
+++ b/javax/swing/text/DefaultCaret.java
@@ -60,10 +60,8 @@ import javax.swing.event.EventListenerList;
public class DefaultCaret extends Rectangle
implements Caret, FocusListener, MouseListener, MouseMotionListener
{
- /**
- * The serial version UID for DefaultCaret.
- */
- private static final long serialVersionUID = 228155774675466193L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 4325555698756477346L;
/**
* The <code>ChangeEvent</code> that is fired by {@link #fireStateChanged()}.
diff --git a/javax/swing/text/DefaultEditorKit.java b/javax/swing/text/DefaultEditorKit.java
index a14f3ff4f..2f901947f 100644
--- a/javax/swing/text/DefaultEditorKit.java
+++ b/javax/swing/text/DefaultEditorKit.java
@@ -66,8 +66,7 @@ public class DefaultEditorKit extends EditorKit
*
* @see Toolkit#beep()
*/
- public static class BeepAction
- extends TextAction
+ public static class BeepAction extends TextAction
{
/**
* Creates a new <code>BeepAction</code>.
@@ -95,8 +94,7 @@ public class DefaultEditorKit extends EditorKit
* @see CutAction
* @see PasteAction
*/
- public static class CopyAction
- extends TextAction
+ public static class CopyAction extends TextAction
{
/**
@@ -128,8 +126,7 @@ public class DefaultEditorKit extends EditorKit
* @see CopyAction
* @see PasteAction
*/
- public static class CutAction
- extends TextAction
+ public static class CutAction extends TextAction
{
/**
@@ -159,8 +156,7 @@ public class DefaultEditorKit extends EditorKit
* @see CopyAction
* @see CutAction
*/
- public static class PasteAction
- extends TextAction
+ public static class PasteAction extends TextAction
{
/**
@@ -243,8 +239,7 @@ public class DefaultEditorKit extends EditorKit
* of the text component. This is typically triggered by hitting
* ENTER on the keyboard.
*/
- public static class InsertBreakAction
- extends TextAction
+ public static class InsertBreakAction extends TextAction
{
/**
@@ -273,8 +268,7 @@ public class DefaultEditorKit extends EditorKit
*/
// FIXME: Figure out what this Action is supposed to do. Obviously text
// that is entered by the user is inserted through DefaultKeyTypedAction.
- public static class InsertContentAction
- extends TextAction
+ public static class InsertContentAction extends TextAction
{
/**
@@ -298,8 +292,7 @@ public class DefaultEditorKit extends EditorKit
/**
* Inserts a TAB character into the text editor.
*/
- public static class InsertTabAction
- extends TextAction
+ public static class InsertTabAction extends TextAction
{
/**
diff --git a/javax/swing/text/DefaultFormatter.java b/javax/swing/text/DefaultFormatter.java
index c97d90703..16d40c24b 100644
--- a/javax/swing/text/DefaultFormatter.java
+++ b/javax/swing/text/DefaultFormatter.java
@@ -57,8 +57,7 @@ import javax.swing.JFormattedTextField;
*
* @author Roman Kennke (roman@kennke.org)
*/
-public class DefaultFormatter
- extends JFormattedTextField.AbstractFormatter
+public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
implements Cloneable, Serializable
{
@@ -156,9 +155,6 @@ public class DefaultFormatter
* Checks if the value in the input field is valid. If the
* property allowsInvalid is set to <code>false</code>, then
* the string in the input field is not allowed to be entered.
- *
- * @param doc the document of the input field
- * @param value the current (old) value of the input field
*/
private void checkValidInput()
{
@@ -186,8 +182,8 @@ public class DefaultFormatter
}
}
- /** The serialVersoinUID. */
- private static final long serialVersionUID = -7369196326612908900L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -355018354457785329L;
/**
* Indicates if the value should be committed after every
diff --git a/javax/swing/text/DefaultStyledDocument.java b/javax/swing/text/DefaultStyledDocument.java
index 3545e52c4..765477507 100644
--- a/javax/swing/text/DefaultStyledDocument.java
+++ b/javax/swing/text/DefaultStyledDocument.java
@@ -1,5 +1,5 @@
/* DefaultStyledDocument.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,6 +41,7 @@ package javax.swing.text;
import java.awt.Color;
import java.awt.Font;
import java.io.Serializable;
+import java.util.Vector;
import javax.swing.event.DocumentEvent;
@@ -60,12 +61,278 @@ public class DefaultStyledDocument extends AbstractDocument
implements StyledDocument
{
/**
+ * Carries specification information for new {@link Element}s that should
+ * be created in {@link ElementBuffer}. This allows the parsing process
+ * to be decoupled from the <code>Element</code> creation process.
+ */
+ public static class ElementSpec
+ {
+ /**
+ * This indicates a start tag. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short StartTagType = 1;
+
+ /**
+ * This indicates an end tag. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short EndTagType = 2;
+
+ /**
+ * This indicates a content element. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short ContentType = 3;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * with what precedes it. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinPreviousDirection = 4;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * with what follows it. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinNextDirection = 5;
+
+ /**
+ * This indicates that the data associated with this spec should be used
+ * to create a new element. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short OriginateDirection = 6;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * to the fractured element. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinFractureDirection = 7;
+
+ /**
+ * The type of the tag.
+ */
+ short type;
+
+ /**
+ * The direction of the tag.
+ */
+ short direction;
+
+ /**
+ * The offset of the content.
+ */
+ int offset;
+
+ /**
+ * The length of the content.
+ */
+ int length;
+
+ /**
+ * The actual content.
+ */
+ char[] content;
+
+ /**
+ * The attributes for the tag.
+ */
+ AttributeSet attributes;
+
+ /**
+ * Creates a new <code>ElementSpec</code> with no content, length or
+ * offset. This is most useful for start and end tags.
+ *
+ * @param a the attributes for the element to be created
+ * @param type the type of the tag
+ */
+ public ElementSpec(AttributeSet a, short type)
+ {
+ this(a, type, 0);
+ }
+
+ /**
+ * Creates a new <code>ElementSpec</code> that specifies the length but
+ * not the offset of an element. Such <code>ElementSpec</code>s are
+ * processed sequentially from a known starting point.
+ *
+ * @param a the attributes for the element to be created
+ * @param type the type of the tag
+ * @param len the length of the element
+ */
+ public ElementSpec(AttributeSet a, short type, int len)
+ {
+ this(a, type, null, 0, len);
+ }
+
+ /**
+ * Creates a new <code>ElementSpec</code> with document content.
+ *
+ * @param a the attributes for the element to be created
+ * @param type the type of the tag
+ * @param txt the actual content
+ * @param offs the offset into the <code>txt</code> array
+ * @param len the length of the element
+ */
+ public ElementSpec(AttributeSet a, short type, char[] txt, int offs,
+ int len)
+ {
+ attributes = a;
+ this.type = type;
+ offset = offs;
+ length = len;
+ content = txt;
+ direction = OriginateDirection;
+ }
+
+ /**
+ * Sets the type of the element.
+ *
+ * @param type the type of the element to be set
+ */
+ public void setType(short type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of the element.
+ *
+ * @return the type of the element
+ */
+ public short getType()
+ {
+ return type;
+ }
+
+ /**
+ * Sets the direction of the element.
+ *
+ * @param dir the direction of the element to be set
+ */
+ public void setDirection(short dir)
+ {
+ direction = dir;
+ }
+
+ /**
+ * Returns the direction of the element.
+ *
+ * @return the direction of the element
+ */
+ public short getDirection()
+ {
+ return direction;
+ }
+
+ /**
+ * Returns the attributes of the element.
+ *
+ * @return the attributes of the element
+ */
+ public AttributeSet getAttributes()
+ {
+ return attributes;
+ }
+
+ /**
+ * Returns the actual content of the element.
+ *
+ * @return the actual content of the element
+ */
+ public char[] getArray()
+ {
+ return content;
+ }
+
+ /**
+ * Returns the offset of the content.
+ *
+ * @return the offset of the content
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length of the content
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Returns a String representation of this <code>ElementSpec</code>
+ * describing the type, direction and length of this
+ * <code>ElementSpec</code>.
+ *
+ * @return a String representation of this <code>ElementSpec</code>
+ */
+ public String toString()
+ {
+ StringBuilder b = new StringBuilder();
+ b.append('<');
+ switch (type)
+ {
+ case StartTagType:
+ b.append("StartTag");
+ break;
+ case EndTagType:
+ b.append("EndTag");
+ break;
+ case ContentType:
+ b.append("Content");
+ break;
+ default:
+ b.append("??");
+ break;
+ }
+
+ b.append(':');
+
+ switch (direction)
+ {
+ case JoinPreviousDirection:
+ b.append("JoinPrevious");
+ break;
+ case JoinNextDirection:
+ b.append("JoinNext");
+ break;
+ case OriginateDirection:
+ b.append("Originate");
+ break;
+ case JoinFractureDirection:
+ b.append("Fracture");
+ break;
+ default:
+ b.append("??");
+ break;
+ }
+
+ b.append(':');
+ b.append(length);
+
+ return b.toString();
+ }
+ }
+
+ /**
* Performs all <em>structural</code> changes to the <code>Element</code>
* hierarchy.
*/
- public class ElementBuffer
- implements Serializable
+ public class ElementBuffer implements Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 1688745877691146623L;
+
/** The root element of the hierarchy. */
private Element root;
@@ -76,6 +343,19 @@ public class DefaultStyledDocument extends AbstractDocument
private int length;
/**
+ * Holds fractured elements during insertion of end and start tags.
+ * Inserting an end tag may lead to fracturing of the current paragraph
+ * element. The elements that have been cut off may be added to the
+ * next paragraph that is created in the next start tag.
+ */
+ Element[] fracture;
+
+ /**
+ * The ElementChange that describes the latest changes.
+ */
+ DefaultDocumentEvent documentEvent;
+
+ /**
* Creates a new <code>ElementBuffer</code> for the specified
* <code>root</code> element.
*
@@ -114,6 +394,7 @@ public class DefaultStyledDocument extends AbstractDocument
{
this.offset = offset;
this.length = length;
+ documentEvent = ev;
changeUpdate();
}
@@ -158,7 +439,11 @@ public class DefaultStyledDocument extends AbstractDocument
Element child2 = createLeafElement(par, ael, offset,
endOffset);
int index = par.getElementIndex(startOffset);
- par.replace(index, 1, new Element[]{ child1, child2 });
+ Element[] add = new Element[]{ child1, child2 };
+ par.replace(index, 1, add);
+ documentEvent.addEdit(new ElementEdit(par, index,
+ new Element[]{ el },
+ add));
}
else
throw new AssertionError("paragraph elements are expected to "
@@ -171,8 +456,267 @@ public class DefaultStyledDocument extends AbstractDocument
+ "instances of "
+ "javax.swing.text.AbstractDocument.AbstractElement");
}
+
+ /**
+ * Inserts new <code>Element</code> in the document at the specified
+ * position.
+ *
+ * Most of the work is done by {@link #insertUpdate}, after some fields
+ * have been prepared for it.
+ *
+ * @param offset the location in the document at which the content is
+ * inserted
+ * @param length the length of the inserted content
+ * @param data the element specifications for the content to be inserted
+ * @param ev the document event that is updated to reflect the structural
+ * changes
+ */
+ public void insert(int offset, int length, ElementSpec[] data,
+ DefaultDocumentEvent ev)
+ {
+ this.offset = offset;
+ this.length = length;
+ documentEvent = ev;
+ insertUpdate(data);
+ }
+
+ /**
+ * Performs the actual structural change for {@link #insert}. This
+ * creates a bunch of {@link Element}s as specified by <code>data</code>
+ * and inserts it into the document as specified in the arguments to
+ * {@link #insert}.
+ *
+ * @param data the element specifications for the elements to be inserte
+ */
+ protected void insertUpdate(ElementSpec[] data)
+ {
+ for (int i = 0; i < data.length; i++)
+ {
+ switch (data[i].getType())
+ {
+ case ElementSpec.StartTagType:
+ insertStartTag(data[i]);
+ break;
+ case ElementSpec.EndTagType:
+ insertEndTag(data[i]);
+ break;
+ default:
+ insertContentTag(data[i]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Insert a new paragraph after the paragraph at the current position.
+ *
+ * @param tag the element spec that describes the element to be inserted
+ */
+ void insertStartTag(ElementSpec tag)
+ {
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ int index = root.getElementIndex(offset);
+ if (index == -1)
+ index = 0;
+
+ BranchElement newParagraph =
+ (BranchElement) createBranchElement(root, tag.getAttributes());
+ newParagraph.setResolveParent(getStyle(StyleContext.DEFAULT_STYLE));
+
+ // Add new paragraph into document structure.
+ Element[] added = new Element[]{newParagraph};
+ root.replace(index + 1, 0, added);
+ ElementEdit edit = new ElementEdit(root, index + 1, new Element[0],
+ added);
+ documentEvent.addEdit(edit);
+
+ // Maybe add fractured elements.
+ if (tag.getDirection() == ElementSpec.JoinFractureDirection)
+ {
+ Element[] newFracture = new Element[fracture.length];
+ for (int i = 0; i < fracture.length; i++)
+ {
+ Element oldLeaf = fracture[i];
+ Element newLeaf = createLeafElement(newParagraph,
+ oldLeaf.getAttributes(),
+ oldLeaf.getStartOffset(),
+ oldLeaf.getEndOffset());
+ newFracture[i] = newLeaf;
+ }
+ newParagraph.replace(0, 0, newFracture);
+ edit = new ElementEdit(newParagraph, 0, new Element[0],
+ fracture);
+ documentEvent.addEdit(edit);
+ fracture = new Element[0];
+ }
+ }
+
+ /**
+ * Inserts an end tag into the document structure. This cuts of the
+ * current paragraph element, possibly fracturing it's child elements.
+ * The fractured elements are saved so that they can be joined later
+ * with a new paragraph element.
+ */
+ void insertEndTag(ElementSpec tag)
+ {
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ int parIndex = root.getElementIndex(offset);
+ BranchElement paragraph = (BranchElement) root.getElement(parIndex);
+
+ int index = paragraph.getElementIndex(offset);
+ LeafElement content = (LeafElement) paragraph.getElement(index);
+ // We might have to split the element at offset.
+ split(content, offset);
+ index = paragraph.getElementIndex(offset);
+
+ int count = paragraph.getElementCount();
+ // Store fractured elements.
+ fracture = new Element[count - index];
+ for (int i = index; i < count; ++i)
+ fracture[i - index] = paragraph.getElement(i);
+
+ // Delete fractured elements.
+ paragraph.replace(index, count - index, new Element[0]);
+
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(paragraph, index, fracture,
+ new Element[0]);
+ documentEvent.addEdit(edit);
+ }
+
+ /**
+ * Inserts a content element into the document structure.
+ *
+ * @param tag the element spec
+ */
+ void insertContentTag(ElementSpec tag)
+ {
+ int len = tag.getLength();
+ int dir = tag.getDirection();
+ if (dir == ElementSpec.JoinPreviousDirection)
+ {
+ Element prev = getCharacterElement(offset);
+ BranchElement prevParent = (BranchElement) prev.getParentElement();
+ Element join = createLeafElement(prevParent, tag.getAttributes(),
+ prev.getStartOffset(),
+ Math.max(prev.getEndOffset(),
+ offset + len));
+ int ind = prevParent.getElementIndex(offset);
+ if (ind == -1)
+ ind = 0;
+ Element[] add = new Element[]{join};
+ prevParent.replace(ind, 1, add);
+
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(prevParent, ind,
+ new Element[]{prev}, add);
+ documentEvent.addEdit(edit);
+ }
+ else if (dir == ElementSpec.JoinNextDirection)
+ {
+ Element next = getCharacterElement(offset + len);
+ BranchElement nextParent = (BranchElement) next.getParentElement();
+ Element join = createLeafElement(nextParent, tag.getAttributes(),
+ offset,
+ next.getEndOffset());
+ int ind = nextParent.getElementIndex(offset + len);
+ if (ind == -1)
+ ind = 0;
+ Element[] add = new Element[]{join};
+ nextParent.replace(ind, 1, add);
+
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(nextParent, ind,
+ new Element[]{next}, add);
+ documentEvent.addEdit(edit);
+ }
+ else
+ {
+ BranchElement par = (BranchElement) getParagraphElement(offset);
+
+ int ind = par.getElementIndex(offset);
+
+ // Make room for the element.
+ // Cut previous element.
+ Element prev = par.getElement(ind);
+ if (prev != null && prev.getStartOffset() < offset)
+ {
+ Element cutPrev = createLeafElement(par, prev.getAttributes(),
+ prev.getStartOffset(),
+ offset);
+ Element[] remove = new Element[]{prev};
+ Element[] add = new Element[]{cutPrev};
+ if (prev.getEndOffset() > offset + len)
+ {
+ Element rem = createLeafElement(par, prev.getAttributes(),
+ offset + len,
+ prev.getEndOffset());
+ add = new Element[]{cutPrev, rem};
+ }
+
+ par.replace(ind, 1, add);
+ documentEvent.addEdit(new ElementEdit(par, ind, remove, add));
+ ind++;
+ }
+ // ind now points to the next element.
+
+ // Cut next element if necessary.
+ Element next = par.getElement(ind);
+ if (next != null && next.getStartOffset() < offset + len)
+ {
+ Element cutNext = createLeafElement(par, next.getAttributes(),
+ offset + len,
+ next.getEndOffset());
+ Element[] remove = new Element[]{next};
+ Element[] add = new Element[]{cutNext};
+ par.replace(ind, 1, add);
+ documentEvent.addEdit(new ElementEdit(par, ind, remove,
+ add));
+ }
+
+ // Insert new element.
+ Element newEl = createLeafElement(par, tag.getAttributes(),
+ offset, offset + len);
+ Element[] added = new Element[]{newEl};
+ par.replace(ind, 0, added);
+ // Add this action to the document event.
+ ElementEdit edit = new ElementEdit(par, ind, new Element[0],
+ added);
+ documentEvent.addEdit(edit);
+ }
+ offset += len;
+ }
+ }
+
+ /**
+ * An element type for sections. This is a simple BranchElement with
+ * a unique name.
+ */
+ protected class SectionElement extends BranchElement
+ {
+ /**
+ * Creates a new SectionElement.
+ */
+ public SectionElement()
+ {
+ super(null, null);
+ }
+
+ /**
+ * Returns the name of the element. This method always returns
+ * &quot;section&quot;.
+ *
+ * @return the name of the element
+ */
+ public String getName()
+ {
+ return "section";
+ }
}
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 940485415728614849L;
+
/**
* The default size to use for new content buffers.
*/
@@ -250,9 +794,11 @@ public class DefaultStyledDocument extends AbstractDocument
Element[] tmp;
// FIXME: Create a SecionElement here instead of a BranchElement.
// Use createBranchElement() and createLeafElement instead.
- BranchElement section = new BranchElement(null, null);
-
- BranchElement paragraph = new BranchElement(section, null);
+ SectionElement section = new SectionElement();
+
+ BranchElement paragraph =
+ (BranchElement) createBranchElement(section, null);
+ paragraph.setResolveParent(getStyle(StyleContext.DEFAULT_STYLE));
tmp = new Element[1];
tmp[0] = paragraph;
section.replace(0, 0, tmp);
@@ -261,7 +807,7 @@ public class DefaultStyledDocument extends AbstractDocument
tmp = new Element[1];
tmp[0] = leaf;
paragraph.replace(0, 0, tmp);
-
+
return section;
}
@@ -360,8 +906,9 @@ public class DefaultStyledDocument extends AbstractDocument
*/
public Element getParagraphElement(int position)
{
- Element element = getCharacterElement(position);
- return element.getParentElement();
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ Element par = root.positionToElement(position);
+ return par;
}
/**
@@ -445,6 +992,8 @@ public class DefaultStyledDocument extends AbstractDocument
+ "javax.swing.text.AbstractDocument.AbstractElement");
}
}
+
+ fireChangedUpdate(ev);
}
/**
@@ -476,10 +1025,110 @@ public class DefaultStyledDocument extends AbstractDocument
* selection are overridden, otherwise they are merged
*/
public void setParagraphAttributes(int offset, int length,
- AttributeSet attributes,
- boolean replace)
+ AttributeSet attributes,
+ boolean replace)
{
- // FIXME: Implement me.
- throw new Error("not implemented");
+ int index = offset;
+ while (index < offset + length)
+ {
+ AbstractElement par = (AbstractElement) getParagraphElement(index);
+ AttributeContext ctx = getAttributeContext();
+ if (replace)
+ par.removeAttributes(par);
+ par.addAttributes(attributes);
+ index = par.getElementCount();
+ }
}
+
+ /**
+ * Called in response to content insert actions. This is used to
+ * update the element structure.
+ *
+ * @param ev the <code>DocumentEvent</code> describing the change
+ * @param attr the attributes for the change
+ */
+ protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
+ {
+ super.insertUpdate(ev, attr);
+ int offset = ev.getOffset();
+ int length = ev.getLength();
+ int endOffset = offset + length;
+ Segment txt = new Segment();
+ try
+ {
+ getText(offset, length, txt);
+ }
+ catch (BadLocationException ex)
+ {
+ throw new AssertionError("BadLocationException must not be thrown "
+ + "here.");
+ }
+
+ int len = 0;
+ Vector specs = new Vector();
+
+ Element prev = getCharacterElement(offset);
+ Element next = getCharacterElement(endOffset);
+
+ for (int i = offset; i < endOffset; ++i)
+ {
+ len++;
+ if (txt.array[i] == '\n')
+ {
+ ElementSpec spec = new ElementSpec(attr, ElementSpec.ContentType,
+ len);
+
+ // If we are at the last index, then check if we could probably be
+ // joined with the next element.
+ if (i == endOffset - 1)
+ {
+ if (next.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinNextDirection);
+ }
+ // If we are at the first new element, then check if it could be
+ // joined with the previous element.
+ else if (specs.size() == 0)
+ {
+ if (prev.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinPreviousDirection);
+ }
+
+ specs.add(spec);
+
+ // Add ElementSpecs for the newline.
+ ElementSpec endTag = new ElementSpec(null, ElementSpec.EndTagType);
+ specs.add(endTag);
+ ElementSpec startTag = new ElementSpec(null,
+ ElementSpec.StartTagType);
+ startTag.setDirection(ElementSpec.JoinFractureDirection);
+ specs.add(startTag);
+
+ len = 0;
+ offset += len;
+ }
+ }
+
+ // Create last element if last character hasn't been a newline.
+ if (len > 0)
+ {
+ ElementSpec spec = new ElementSpec(attr, ElementSpec.ContentType, len);
+ // If we are at the first new element, then check if it could be
+ // joined with the previous element.
+ if (specs.size() == 0)
+ {
+ if (prev.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinPreviousDirection);
+ }
+ // Check if we could probably be joined with the next element.
+ else if (next.getAttributes().isEqual(attr))
+ spec.setDirection(ElementSpec.JoinNextDirection);
+
+ specs.add(spec);
+ }
+
+ ElementSpec[] elSpecs =
+ (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
+
+ buffer.insert(offset, length, elSpecs, ev);
+ }
}
diff --git a/javax/swing/text/GapContent.java b/javax/swing/text/GapContent.java
index 8e408f36c..5c8f81865 100644
--- a/javax/swing/text/GapContent.java
+++ b/javax/swing/text/GapContent.java
@@ -39,9 +39,11 @@ exception statement from your version. */
package javax.swing.text;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.LinkedList;
+import java.util.Iterator;
import java.util.ListIterator;
+import java.util.Vector;
import javax.swing.undo.UndoableEdit;
@@ -59,7 +61,6 @@ import javax.swing.undo.UndoableEdit;
public class GapContent
implements AbstractDocument.Content, Serializable
{
-
/**
* A {@link Position} implementation for <code>GapContent</code>.
*/
@@ -114,6 +115,11 @@ public class GapContent
*/
public int getOffset()
{
+ // Check precondition.
+ assert mark <= gapStart || mark > gapEnd : "mark: " + mark
+ + ", gapStart: " + gapStart
+ + ", gapEnd: " + gapEnd;
+
if (mark <= gapEnd)
return mark;
else
@@ -121,13 +127,14 @@ public class GapContent
}
}
- private static final long serialVersionUID = 8374645204155842629L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6226052713477823730L;
/**
* This is the default buffer size and the amount of bytes that a buffer is
* extended if it is full.
*/
- static final int DEFAULT_BUFSIZE = 64;
+ static final int DEFAULT_BUFSIZE = 10;
/**
* The text buffer.
@@ -148,7 +155,7 @@ public class GapContent
* The positions generated by this GapContent. They are kept in an ordered
* fashion, so they can be looked up easily.
*/
- LinkedList positions;
+ ArrayList positions;
/**
* Creates a new GapContent object.
@@ -166,10 +173,10 @@ public class GapContent
public GapContent(int size)
{
buffer = (char[]) allocateArray(size);
- gapStart = 0;
- gapEnd = size - 1;
- buffer[size - 1] = '\n';
- positions = new LinkedList();
+ gapStart = 1;
+ gapEnd = size;
+ buffer[0] = '\n';
+ positions = new ArrayList();
}
/**
@@ -386,7 +393,19 @@ public class GapContent
*/
protected void shiftEnd(int newSize)
{
- int delta = (gapEnd - gapStart) - newSize;
+ assert newSize > (gapEnd - gapStart) : "The new gap size must be greater "
+ + "than the old gap size";
+
+ int delta = newSize - gapEnd + gapStart;
+ // Update the marks after the gapEnd.
+ Vector v = getPositionsInRange(null, gapEnd, buffer.length - gapEnd);
+ for (Iterator i = v.iterator(); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ p.mark += delta;
+ }
+
+ // Copy the data around.
char[] newBuf = (char[]) allocateArray(length() + newSize);
System.arraycopy(buffer, 0, newBuf, 0, gapStart);
System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize, buffer.length
@@ -394,18 +413,6 @@ public class GapContent
gapEnd = gapStart + newSize;
buffer = newBuf;
- // Update the marks after the gapEnd.
- int index = Collections.binarySearch(positions, new GapContentPosition(
- gapEnd));
- if (index < 0)
- {
- index = -(index + 1);
- }
- for (ListIterator i = positions.listIterator(index); i.hasNext();)
- {
- GapContentPosition p = (GapContentPosition) i.next();
- p.mark += delta;
- }
}
/**
@@ -415,32 +422,22 @@ public class GapContent
*/
protected void shiftGap(int newGapStart)
{
- int newGapEnd = newGapStart + (gapEnd - gapStart);
+ if (newGapStart == gapStart)
+ return;
- // Update the positions between newGapEnd and (old) gapEnd. The marks
- // must be shifted by (gapEnd - newGapEnd).
- int index1 = Collections.binarySearch(positions,
- new GapContentPosition(gapEnd));
- int index2 = Collections.binarySearch(positions,
- new GapContentPosition(newGapEnd));
- if (index1 > 0 && index2 > 0)
+ int newGapEnd = newGapStart + gapEnd - gapStart;
+
+ if (newGapStart < gapStart)
{
- int i1 = Math.min(index1, index2);
- int i2 = Math.max(index1, index2);
- for (ListIterator i = positions.listIterator(i1); i.hasNext();)
+ // Update the positions between newGapStart and (old) gapStart. The marks
+ // must be shifted by (gapEnd - gapStart).
+ Vector v = getPositionsInRange(null, newGapStart + 1,
+ gapStart - newGapStart + 1);
+ for (Iterator i = v.iterator(); i.hasNext();)
{
- if (i.nextIndex() > i2)
- break;
-
GapContentPosition p = (GapContentPosition) i.next();
- p.mark += gapEnd - newGapEnd;
+ p.mark += gapEnd - gapStart;
}
- }
-
- if (newGapStart == gapStart)
- return;
- else if (newGapStart < gapStart)
- {
System.arraycopy(buffer, newGapStart, buffer, newGapEnd, gapStart
- newGapStart);
gapStart = newGapStart;
@@ -448,6 +445,15 @@ public class GapContent
}
else
{
+ // Update the positions between newGapEnd and (old) gapEnd. The marks
+ // must be shifted by (gapEnd - gapStart).
+ Vector v = getPositionsInRange(null, gapEnd,
+ newGapEnd - gapEnd);
+ for (Iterator i = v.iterator(); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ p.mark -= gapEnd - gapStart;
+ }
System.arraycopy(buffer, gapEnd, buffer, gapStart, newGapStart
- gapStart);
gapStart = newGapStart;
@@ -456,6 +462,54 @@ public class GapContent
}
/**
+ * Shifts the gap start downwards. This does not affect the content of the
+ * buffer. This only updates the gap start and all the marks that are between
+ * the old gap start and the new gap start. They all are squeezed to the start
+ * of the gap, because their location has been removed.
+ *
+ * @param newGapStart the new gap start
+ */
+ protected void shiftGapStartDown(int newGapStart)
+ {
+ if (newGapStart == gapStart)
+ return;
+
+ assert newGapStart < gapStart : "The new gap start must be less than the "
+ + "old gap start.";
+ Vector v = getPositionsInRange(null, newGapStart, gapStart - newGapStart);
+ for (Iterator i = v.iterator(); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ p.mark = gapStart;
+ }
+ gapStart = newGapStart;
+ }
+
+ /**
+ * Shifts the gap end upwards. This does not affect the content of the
+ * buffer. This only updates the gap end and all the marks that are between
+ * the old gap end and the new end start. They all are squeezed to the end
+ * of the gap, because their location has been removed.
+ *
+ * @param newGapEnd the new gap start
+ */
+ protected void shiftGapEndUp(int newGapEnd)
+ {
+ if (newGapEnd == gapEnd)
+ return;
+
+ assert newGapEnd > gapEnd : "The new gap end must be greater than the "
+ + "old gap end.";
+ Vector v = getPositionsInRange(null, gapEnd, newGapEnd - gapEnd);
+ for (Iterator i = v.iterator(); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ p.mark = newGapEnd + 1;
+ }
+ gapEnd = newGapEnd;
+ }
+
+ /**
* Returns the allocated buffer array.
*
* @return the allocated buffer array
@@ -478,11 +532,11 @@ public class GapContent
{
// Remove content
shiftGap(position);
- gapEnd += rmSize;
+ shiftGapEndUp(gapEnd + rmSize);
// If gap is too small, enlarge the gap.
- if ((gapEnd - gapStart) < addSize)
- shiftEnd(addSize);
+ if ((gapEnd - gapStart) <= addSize)
+ shiftEnd((addSize - gapEnd + gapStart + 1) * 2 + gapEnd + DEFAULT_BUFSIZE);
// Add new items to the buffer.
if (addItems != null)
@@ -491,4 +545,64 @@ public class GapContent
gapStart += addSize;
}
}
+
+ /**
+ * Returns the start index of the gap within the buffer array.
+ *
+ * @return the start index of the gap within the buffer array
+ */
+ protected final int getGapStart()
+ {
+ return gapStart;
+ }
+
+ /**
+ * Returns the end index of the gap within the buffer array.
+ *
+ * @return the end index of the gap within the buffer array
+ */
+ protected final int getGapEnd()
+ {
+ return gapEnd;
+ }
+
+ /**
+ * Returns all <code>Position</code>s that are in the range specified by
+ * <code>offset</code> and </code>length</code> within the buffer array.
+ *
+ * @param v the vector to use; if <code>null</code>, a new Vector is allocated
+ * @param offset the start offset of the range to search
+ * @param length the length of the range to search
+ *
+ * @return the positions within the specified range
+ */
+ protected Vector getPositionsInRange(Vector v, int offset, int length)
+ {
+ Vector res = v;
+ if (res == null)
+ res = new Vector();
+ else
+ res.clear();
+
+ int endOffset = offset + length;
+
+ int index1 = Collections.binarySearch(positions,
+ new GapContentPosition(offset));
+ int index2 = Collections.binarySearch(positions,
+ new GapContentPosition(endOffset));
+ if (index1 < 0)
+ index1 = -(index1 + 1);
+ if (index2 < 0)
+ index2 = -(index2 + 1);
+ for (ListIterator i = positions.listIterator(index1); i.hasNext();)
+ {
+ if (i.nextIndex() > index2)
+ break;
+
+ GapContentPosition p = (GapContentPosition) i.next();
+ if (p.mark >= offset && p.mark <= endOffset)
+ res.add(p);
+ }
+ return res;
+ }
}
diff --git a/javax/swing/text/GlyphView.java b/javax/swing/text/GlyphView.java
index f9e60972d..6ffab23c4 100644
--- a/javax/swing/text/GlyphView.java
+++ b/javax/swing/text/GlyphView.java
@@ -44,6 +44,11 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.text.BreakIterator;
+
+import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
/**
* Renders a run of styled text. This {@link View} subclass paints the
@@ -52,9 +57,7 @@ import java.awt.Shape;
*
* @author Roman Kennke (roman@kennke.org)
*/
-public class GlyphView
- extends View
- implements TabableView, Cloneable
+public class GlyphView extends View implements TabableView, Cloneable
{
/**
@@ -71,12 +74,43 @@ public class GlyphView
}
/**
+ * Returns the ascent of the font that is used by this glyph painter.
+ *
+ * @param v the glyph view
+ *
+ * @return the ascent of the font that is used by this glyph painter
+ */
+ public abstract float getAscent(GlyphView v);
+
+ /**
+ * Returns the descent of the font that is used by this glyph painter.
+ *
+ * @param v the glyph view
+ *
+ * @return the descent of the font that is used by this glyph painter
+ */
+ public abstract float getDescent(GlyphView v);
+
+ /**
* Returns the full height of the rendered text.
*
* @return the full height of the rendered text
*/
public abstract float getHeight(GlyphView view);
-
+
+ /**
+ * Determines the model offset, so that the text between <code>p0</code>
+ * and this offset fits within the span starting at <code>x</code> with
+ * the length of <code>len</code>.
+ *
+ * @param v the glyph view
+ * @param p0 the starting offset in the model
+ * @param x the start location in the view
+ * @param len the length of the span in the view
+ */
+ public abstract int getBoundedPosition(GlyphView v, int p0, float x,
+ float len);
+
/**
* Paints the glyphs.
*
@@ -97,8 +131,8 @@ public class GlyphView
* @param view the glyph view
* @param pos the position of the character in the model
* @param a the area that is occupied by the view
- * @param bias either {@link Position.Bias.Forward} or
- * {@link Position.Bias.Backward} depending on the preferred
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
* direction bias. If <code>null</code> this defaults to
* <code>Position.Bias.Forward</code>
*
@@ -114,6 +148,20 @@ public class GlyphView
throws BadLocationException;
/**
+ * Maps a visual position into a document location.
+ *
+ * @param v the glyph view
+ * @param x the X coordinate of the visual position
+ * @param y the Y coordinate of the visual position
+ * @param a the allocated region
+ * @param biasRet filled with the bias of the model location on method exit
+ *
+ * @return the model location that represents the specified view location
+ */
+ public abstract int viewToModel(GlyphView v, float x, float y, Shape a,
+ Position.Bias[] biasRet);
+
+ /**
* Determine the span of the glyphs from location <code>p0</code> to
* location <code>p1</code>. If <code>te</code> is not <code>null</code>,
* then TABs are expanded using this <code>TabExpander</code>.
@@ -122,7 +170,7 @@ public class GlyphView
*
* @param view the glyph view
* @param p0 the starting location in the document model
- * @param p0 the end location in the document model
+ * @param p1 the end location in the document model
* @param te the tab expander to use
* @param x the location at which the view is located
*
@@ -132,6 +180,69 @@ public class GlyphView
public abstract float getSpan(GlyphView view, int p0, int p1,
TabExpander te, float x);
+
+ /**
+ * Returns the model location that should be used to place a caret when
+ * moving the caret through the document.
+ *
+ * @param v the glyph view
+ * @param pos the current model location
+ * @param b the bias for <code>p</code>
+ * @param a the allocated region for the glyph view
+ * @param direction the direction from the current position; Must be one of
+ * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+ * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+ * @param biasRet filled with the bias of the resulting location when method
+ * returns
+ *
+ * @return the location within the document that should be used to place the
+ * caret when moving the caret around the document
+ *
+ * @throws BadLocationException if <code>pos</code> is an invalid model
+ * location
+ * @throws IllegalArgumentException if <code>d</code> is invalid
+ */
+ public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b,
+ Shape a, int direction,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+
+ {
+ int result = pos;
+ switch (direction)
+ {
+ case SwingConstants.EAST:
+ result = pos + 1;
+ break;
+ case SwingConstants.WEST:
+ result = pos - 1;
+ break;
+ case SwingConstants.NORTH:
+ case SwingConstants.SOUTH:
+ default:
+ // This should be handled in enclosing view, since the glyph view
+ // does not layout vertically.
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Returns a painter that can be used to render the specified glyph view.
+ * If this glyph painter is stateful, then it should return a new instance.
+ * However, if this painter is stateless it should return itself. The
+ * default behaviour is to return itself.
+ *
+ * @param v the glyph view for which to create a painter
+ * @param p0 the start offset of the rendered area
+ * @param p1 the end offset of the rendered area
+ *
+ * @return a painter that can be used to render the specified glyph view
+ */
+ public GlyphPainter getPainter(GlyphView v, int p0, int p1)
+ {
+ return this;
+ }
}
/**
@@ -173,11 +284,40 @@ public class GlyphView
if (parent instanceof TabExpander)
tabEx = (TabExpander) parent;
- // FIXME: Set character attributes like font-family, font-size, colors.
- Color foreground = view.getForeground();
- g.setColor(foreground);
- Utilities.drawTabbedText(txt, bounds.x, bounds.y, g, tabEx,
- txt.offset);
+ // Fill the background of the text run.
+ Color background = view.getBackground();
+ g.setColor(background);
+ int width = Utilities.getTabbedTextWidth(txt, g.getFontMetrics(),
+ bounds.x, tabEx, txt.offset);
+ g.fillRect(bounds.x, bounds.y, width, height);
+
+ // Draw the actual text.
+ g.setColor(view.getForeground());
+ g.setFont(view.getFont());
+ if (view.isSuperscript())
+ // TODO: Adjust font for superscripting.
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y - height / 2, g, tabEx,
+ txt.offset);
+ else if (view.isSubscript())
+ // TODO: Adjust font for subscripting.
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y + height / 2, g, tabEx,
+ txt.offset);
+ else
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y, g, tabEx,
+ txt.offset);
+
+ if (view.isStikeThrough())
+ {
+ int strikeHeight = (int) (getAscent(view) / 2);
+ g.drawLine(bounds.x, bounds.y + strikeHeight, bounds.height + width,
+ bounds.y + strikeHeight);
+ }
+ if (view.isUnderline())
+ {
+ int lineHeight = (int) getAscent(view);
+ g.drawLine(bounds.x, bounds.y + lineHeight, bounds.height + width,
+ bounds.y + lineHeight);
+ }
}
/**
@@ -188,8 +328,8 @@ public class GlyphView
* @param view the glyph view
* @param pos the position of the character in the model
* @param a the area that is occupied by the view
- * @param bias either {@link Position.Bias.Forward} or
- * {@link Position.Bias.Backward} depending on the preferred
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
* direction bias. If <code>null</code> this defaults to
* <code>Position.Bias.Forward</code>
*
@@ -225,7 +365,7 @@ public class GlyphView
*
* @param view the glyph view
* @param p0 the starting location in the document model
- * @param p0 the end location in the document model
+ * @param p1 the end location in the document model
* @param te the tab expander to use
* @param x the location at which the view is located
*
@@ -242,6 +382,85 @@ public class GlyphView
int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
return span;
}
+
+ /**
+ * Returns the ascent of the text run that is rendered by this
+ * <code>GlyphPainter</code>.
+ *
+ * @param v the glyph view
+ *
+ * @return the ascent of the text run that is rendered by this
+ * <code>GlyphPainter</code>
+ *
+ * @see FontMetrics#getAscent()
+ */
+ public float getAscent(GlyphView v)
+ {
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ return fm.getAscent();
+ }
+
+ /**
+ * Returns the descent of the text run that is rendered by this
+ * <code>GlyphPainter</code>.
+ *
+ * @param v the glyph view
+ *
+ * @return the descent of the text run that is rendered by this
+ * <code>GlyphPainter</code>
+ *
+ * @see FontMetrics#getDescent()
+ */
+ public float getDescent(GlyphView v)
+ {
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ return fm.getDescent();
+ }
+
+ /**
+ * Determines the model offset, so that the text between <code>p0</code>
+ * and this offset fits within the span starting at <code>x</code> with
+ * the length of <code>len</code>.
+ *
+ * @param v the glyph view
+ * @param p0 the starting offset in the model
+ * @param x the start location in the view
+ * @param len the length of the span in the view
+ */
+ public int getBoundedPosition(GlyphView v, int p0, float x, float len)
+ {
+ TabExpander te = v.getTabExpander();
+ Segment txt = v.getText(p0, v.getEndOffset());
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
+ (int) (x + len), te, p0, false);
+ return pos;
+ }
+
+ /**
+ * Maps a visual position into a document location.
+ *
+ * @param v the glyph view
+ * @param x the X coordinate of the visual position
+ * @param y the Y coordinate of the visual position
+ * @param a the allocated region
+ * @param biasRet filled with the bias of the model location on method exit
+ *
+ * @return the model location that represents the specified view location
+ */
+ public int viewToModel(GlyphView v, float x, float y, Shape a,
+ Bias[] biasRet)
+ {
+ Rectangle b = a.getBounds();
+ assert b.contains(x, y) : "The coordinates are expected to be within the "
+ + "view's bounds: x=" + x + ", y=" + y
+ + "a=" + a;
+ int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
+ return pos;
+ }
}
/**
@@ -250,6 +469,16 @@ public class GlyphView
GlyphPainter glyphPainter;
/**
+ * The start offset within the document for this view.
+ */
+ int startOffset;
+
+ /**
+ * The end offset within the document for this view.
+ */
+ int endOffset;
+
+ /**
* Creates a new <code>GlyphView</code> for the given <code>Element</code>.
*
* @param element the element that is rendered by this GlyphView
@@ -257,6 +486,8 @@ public class GlyphView
public GlyphView(Element element)
{
super(element);
+ startOffset = element.getStartOffset();
+ endOffset = element.getEndOffset();
}
/**
@@ -319,16 +550,21 @@ public class GlyphView
*/
public float getPreferredSpan(int axis)
{
- Element el = getElement();
+ float span = 0;
checkPainter();
GlyphPainter painter = getGlyphPainter();
- TabExpander tabEx = null;
- View parent = getParent();
- if (parent instanceof TabExpander)
- tabEx = (TabExpander) parent;
- // FIXME: Figure out how to determine the x parameter.
- float span = painter.getSpan(this, el.getStartOffset(), el.getEndOffset(),
- tabEx, 0.F);
+ if (axis == X_AXIS)
+ {
+ Element el = getElement();
+ TabExpander tabEx = null;
+ View parent = getParent();
+ if (parent instanceof TabExpander)
+ tabEx = (TabExpander) parent;
+ span = painter.getSpan(this, getStartOffset(), getEndOffset(),
+ tabEx, 0.F);
+ }
+ else
+ span = painter.getHeight(this);
return span;
}
@@ -372,8 +608,9 @@ public class GlyphView
*/
public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
{
- // FIXME: not implemented
- return 0;
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ return painter.viewToModel(this, x, y, a, b);
}
/**
@@ -383,12 +620,11 @@ public class GlyphView
*/
public TabExpander getTabExpander()
{
- // TODO: Figure out if this is correct.
TabExpander te = null;
View parent = getParent();
- if (parent instanceof ParagraphView)
- te = (ParagraphView) parent;
+ if (parent instanceof TabExpander)
+ te = (TabExpander) parent;
return te;
}
@@ -436,15 +672,15 @@ public class GlyphView
}
/**
- * Returns the starting offset in the document model of the portion
+ * Returns the start offset in the document model of the portion
* of text that this view is responsible for.
*
- * @return the starting offset in the document model of the portion
+ * @return the start offset in the document model of the portion
* of text that this view is responsible for
*/
- public int getBeginIndex()
+ public int getStartOffset()
{
- return getElement().getStartOffset();
+ return startOffset;
}
/**
@@ -454,9 +690,9 @@ public class GlyphView
* @return the end offset in the document model of the portion
* of text that this view is responsible for
*/
- public int getEndIndex()
+ public int getEndOffset()
{
- return getElement().getEndOffset();
+ return endOffset;
}
/**
@@ -518,4 +754,302 @@ public class GlyphView
AttributeSet atts = el.getAttributes();
return StyleConstants.getForeground(atts);
}
+
+ /**
+ * Returns the background color which should be used to paint the text.
+ * This is fetched from the associated element's text attributes using
+ * {@link StyleConstants#getBackground}.
+ *
+ * @return the background color which should be used to paint the text
+ */
+ public Color getBackground()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.getBackground(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered strike-through or not. This
+ * is determined using the method
+ * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered strike-through or not
+ */
+ public boolean isStikeThrough()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isStrikeThrough(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as subscript or not. This
+ * is determined using the method
+ * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as subscript or not
+ */
+ public boolean isSubscript()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isSubscript(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as superscript or not. This
+ * is determined using the method
+ * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as superscript or not
+ */
+ public boolean isSuperscript()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isSuperscript(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as underlined or not. This
+ * is determined using the method
+ * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as underlined or not
+ */
+ public boolean isUnderline()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isUnderline(atts);
+ }
+
+ /**
+ * Creates and returns a shallow clone of this GlyphView. This is used by
+ * the {@link #createFragment} and {@link #breakView} methods.
+ *
+ * @return a shallow clone of this GlyphView
+ */
+ protected final Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ AssertionError err = new AssertionError("CloneNotSupportedException "
+ + "must not be thrown here");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ /**
+ * Tries to break the view near the specified view span <code>len</code>.
+ * The glyph view can only be broken in the X direction. For Y direction it
+ * returns itself.
+ *
+ * @param axis the axis for breaking, may be {@link View#X_AXIS} or
+ * {@link View#Y_AXIS}
+ * @param p0 the model location where the fragment should start
+ * @param pos the view position along the axis where the fragment starts
+ * @param len the desired length of the fragment view
+ *
+ * @return the fragment view, or <code>this</code> if breaking was not
+ * possible
+ */
+ public View breakView(int axis, int p0, float pos, float len)
+ {
+ if (axis == Y_AXIS)
+ return this;
+
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ int breakLocation = painter.getBoundedPosition(this, p0, pos, len);
+ // Try to find a suitable line break.
+ BreakIterator lineBreaker = BreakIterator.getLineInstance();
+ Segment txt = new Segment();
+ try
+ {
+ getDocument().getText(getStartOffset(), getEndOffset(), txt);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("BadLocationException must not "
+ + "be thrown here.");
+ err.initCause(ex);
+ throw err;
+ }
+ lineBreaker.setText(txt);
+ int goodBreakLocation = lineBreaker.previous();
+ if (goodBreakLocation != BreakIterator.DONE)
+ breakLocation = goodBreakLocation;
+
+ View brokenView = createFragment(p0, breakLocation);
+ return brokenView;
+ }
+
+ /**
+ * Determines how well the specified view location is suitable for inserting
+ * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
+ * this method forwards to the superclass, if <code>axis</code> is
+ * <code>View.X_AXIS</code> then this method returns
+ * {@link View#ExcellentBreakWeight} if there is a suitable break location
+ * (usually whitespace) within the specified view span, or
+ * {@link View#GoodBreakWeight} if not.
+ *
+ * @param axis the axis along which the break weight is requested
+ * @param pos the starting view location
+ * @param len the length of the span at which the view should be broken
+ *
+ * @return the break weight
+ */
+ public int getBreakWeight(int axis, float pos, float len)
+ {
+ int weight;
+ if (axis == Y_AXIS)
+ weight = super.getBreakWeight(axis, pos, len);
+ else
+ {
+ // Determine the model locations at pos and pos + len.
+ int spanX = (int) getPreferredSpan(X_AXIS);
+ int spanY = (int) getPreferredSpan(Y_AXIS);
+ Rectangle dummyAlloc = new Rectangle(0, 0, spanX, spanY);
+ Position.Bias[] biasRet = new Position.Bias[1];
+ int offset1 = viewToModel(pos, spanY / 2, dummyAlloc, biasRet);
+ int offset2 = viewToModel(pos, spanY / 2, dummyAlloc, biasRet);
+ Segment txt = getText(offset1, offset2);
+ BreakIterator lineBreaker = BreakIterator.getLineInstance();
+ lineBreaker.setText(txt);
+ int breakLoc = lineBreaker.previous();
+ if (breakLoc == offset1)
+ weight = View.BadBreakWeight;
+ else if(breakLoc == BreakIterator.DONE)
+ weight = View.GoodBreakWeight;
+ else
+ weight = View.ExcellentBreakWeight;
+ }
+ return weight;
+ }
+
+ /**
+ * Receives notification that some text attributes have changed within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * both width and height.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ getParent().preferenceChanged(this, true, true);
+ }
+
+ /**
+ * Receives notification that some text has been inserted within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * width.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void insertUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ getParent().preferenceChanged(this, true, false);
+ }
+
+ /**
+ * Receives notification that some text has been removed within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * width.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void removeUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ getParent().preferenceChanged(this, true, false);
+ }
+
+ /**
+ * Creates a fragment view of this view that starts at <code>p0</code> and
+ * ends at <code>p1</code>.
+ *
+ * @param p0 the start location for the fragment view
+ * @param p1 the end location for the fragment view
+ *
+ * @return the fragment view
+ */
+ public View createFragment(int p0, int p1)
+ {
+ GlyphView fragment = (GlyphView) clone();
+ fragment.startOffset = p0;
+ fragment.endOffset = p1;
+ return fragment;
+ }
+
+ /**
+ * Returns the alignment of this view along the specified axis. For the Y
+ * axis this is <code>(height - descent) / height</code> for the used font,
+ * so that it is aligned along the baseline.
+ * For the X axis the superclass is called.
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == Y_AXIS)
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ float height = painter.getHeight(this);
+ float descent = painter.getDescent(this);
+ align = (height - descent) / height;
+ }
+ else
+ align = super.getAlignment(axis);
+
+ return align;
+ }
+
+ /**
+ * Returns the model location that should be used to place a caret when
+ * moving the caret through the document.
+ *
+ * @param pos the current model location
+ * @param bias the bias for <code>p</code>
+ * @param a the allocated region for the glyph view
+ * @param direction the direction from the current position; Must be one of
+ * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+ * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+ * @param biasRet filled with the bias of the resulting location when method
+ * returns
+ *
+ * @return the location within the document that should be used to place the
+ * caret when moving the caret around the document
+ *
+ * @throws BadLocationException if <code>pos</code> is an invalid model
+ * location
+ * @throws IllegalArgumentException if <code>d</code> is invalid
+ */
+ public int getNextVisualPositionFrom(int pos, Position.Bias bias, Shape a,
+ int direction, Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
+ biasRet);
+ }
}
diff --git a/javax/swing/text/InternationalFormatter.java b/javax/swing/text/InternationalFormatter.java
index cedaf59fe..86300a70d 100644
--- a/javax/swing/text/InternationalFormatter.java
+++ b/javax/swing/text/InternationalFormatter.java
@@ -57,9 +57,8 @@ import javax.swing.JFormattedTextField;
public class InternationalFormatter
extends DefaultFormatter
{
-
- /** The serialVersoinUID. */
- private static final long serialVersionUID = 6941977820906408656L;
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 2436068675711756856L;
/** The format that handles value to string conversion. */
Format format;
diff --git a/javax/swing/text/JTextComponent.java b/javax/swing/text/JTextComponent.java
index b3fad7912..63dbf2a4b 100644
--- a/javax/swing/text/JTextComponent.java
+++ b/javax/swing/text/JTextComponent.java
@@ -303,9 +303,7 @@ public abstract class JTextComponent extends JComponent
/**
* The timer that lets the caret blink.
*/
- private class CaretBlinkTimer
- extends Timer
- implements ActionListener
+ private class CaretBlinkTimer extends Timer implements ActionListener
{
/**
* Creates a new CaretBlinkTimer object with a default delay of 1 second.
@@ -604,8 +602,7 @@ public abstract class JTextComponent extends JComponent
}
}
- class DefaultTransferHandler
- extends TransferHandler
+ class DefaultTransferHandler extends TransferHandler
{
public boolean canImport(JComponent component, DataFlavor[] flavors)
{
@@ -1105,7 +1102,8 @@ public abstract class JTextComponent extends JComponent
*/
protected String paramString()
{
- return "JTextComponent";
+ // TODO: Do something useful here.
+ return super.paramString();
}
/**
diff --git a/javax/swing/text/PlainView.java b/javax/swing/text/PlainView.java
index 91d7547e7..b93d9a4f1 100644
--- a/javax/swing/text/PlainView.java
+++ b/javax/swing/text/PlainView.java
@@ -51,6 +51,12 @@ public class PlainView extends View
{
Color selectedColor;
Color unselectedColor;
+
+ /**
+ * The color that is used to draw disabled text fields.
+ */
+ Color disabledColor;
+
Font font;
protected FontMetrics metrics;
@@ -145,7 +151,12 @@ public class PlainView extends View
protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
throws BadLocationException
{
- g.setColor(unselectedColor);
+ JTextComponent textComponent = (JTextComponent) getContainer();
+ if (textComponent.isEnabled())
+ g.setColor(unselectedColor);
+ else
+ g.setColor(disabledColor);
+
Segment segment = new Segment();
getDocument().getText(p0, p1 - p0, segment);
return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
@@ -161,7 +172,8 @@ public class PlainView extends View
g.setFont(textComponent.getFont());
selectedColor = textComponent.getSelectedTextColor();
unselectedColor = textComponent.getForeground();
-
+ disabledColor = textComponent.getDisabledTextColor();
+
Rectangle rect = s.getBounds();
// FIXME: Text may be scrolled.
diff --git a/javax/swing/text/SimpleAttributeSet.java b/javax/swing/text/SimpleAttributeSet.java
index 3ef5db61d..61cf5e97c 100644
--- a/javax/swing/text/SimpleAttributeSet.java
+++ b/javax/swing/text/SimpleAttributeSet.java
@@ -45,6 +45,9 @@ import java.util.Hashtable;
public class SimpleAttributeSet
implements MutableAttributeSet, Serializable, Cloneable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 8267656273837665219L;
+
public static final AttributeSet EMPTY = new SimpleAttributeSet();
Hashtable tab;
@@ -89,7 +92,7 @@ public class SimpleAttributeSet
return tab.containsKey(name)
&& tab.get(name).equals(value);
}
-
+
public boolean containsAttributes(AttributeSet attributes)
{
Enumeration e = attributes.getAttributeNames();
@@ -110,9 +113,9 @@ public class SimpleAttributeSet
public boolean equals(Object obj)
{
- return (obj != null)
- && (obj instanceof SimpleAttributeSet)
- && ((SimpleAttributeSet)obj).tab.equals(this.tab);
+ return
+ (obj instanceof AttributeSet)
+ && this.isEqual((AttributeSet) obj);
}
public Object getAttribute(Object name)
@@ -160,7 +163,9 @@ public class SimpleAttributeSet
public boolean isEqual(AttributeSet attr)
{
- return this.equals(attr);
+ return attr != null
+ && attr.containsAttributes(this)
+ && this.containsAttributes(attr);
}
public void removeAttribute(Object name)
diff --git a/javax/swing/text/StringContent.java b/javax/swing/text/StringContent.java
index bedf480d4..7db377a1c 100644
--- a/javax/swing/text/StringContent.java
+++ b/javax/swing/text/StringContent.java
@@ -56,6 +56,9 @@ import javax.swing.undo.UndoableEdit;
*/
public final class StringContent implements AbstractDocument.Content, Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 4755994433709540381L;
+
// This is package-private to avoid an accessor method.
char[] content;
diff --git a/javax/swing/text/StyleConstants.java b/javax/swing/text/StyleConstants.java
index 3f973f226..7d8f9bb63 100644
--- a/javax/swing/text/StyleConstants.java
+++ b/javax/swing/text/StyleConstants.java
@@ -109,7 +109,7 @@ public class StyleConstants
if (a.isDefined(Background))
return (Color) a.getAttribute(Background);
else
- return Color.BLACK;
+ return Color.WHITE;
}
public static int getBidiLevel(AttributeSet a)
diff --git a/javax/swing/text/StyleContext.java b/javax/swing/text/StyleContext.java
index ae11622ff..eda13e744 100644
--- a/javax/swing/text/StyleContext.java
+++ b/javax/swing/text/StyleContext.java
@@ -57,9 +57,15 @@ import javax.swing.event.EventListenerList;
public class StyleContext
implements Serializable, AbstractDocument.AttributeContext
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 8042858831190784241L;
+
public class NamedStyle
implements Serializable, Style
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6690628971806226374L;
+
protected ChangeEvent changeEvent;
protected EventListenerList listenerList;
@@ -288,7 +294,7 @@ public class StyleContext
public boolean equals(Object obj)
{
return
- (obj instanceof SmallAttributeSet)
+ (obj instanceof AttributeSet)
&& this.isEqual((AttributeSet)obj);
}
diff --git a/javax/swing/text/StyledEditorKit.java b/javax/swing/text/StyledEditorKit.java
index 89c4cf18e..e71f992b5 100644
--- a/javax/swing/text/StyledEditorKit.java
+++ b/javax/swing/text/StyledEditorKit.java
@@ -40,13 +40,9 @@ package javax.swing.text;
import java.awt.Color;
import java.awt.event.ActionEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.Serializable;
import javax.swing.Action;
import javax.swing.JEditorPane;
-import javax.swing.JTextPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
@@ -460,11 +456,11 @@ public class StyledEditorKit extends DefaultEditorKit
* <code>StyledEditorKit</code>, namely the following types of Elements:
*
* <ul>
- * <li>{@link AbstractDocument.ContentElementName}</li>
- * <li>{@link AbstractDocument.ParagraphElementName}</li>
- * <li>{@link AbstractDocument.SectionElementName}</li>
- * <li>{@link StyleContext.ComponentElementName}</li>
- * <li>{@link StyleContext.IconElementName}</li>
+ * <li>{@link AbstractDocument#ContentElementName}</li>
+ * <li>{@link AbstractDocument#ParagraphElementName}</li>
+ * <li>{@link AbstractDocument#SectionElementName}</li>
+ * <li>{@link StyleConstants#ComponentElementName}</li>
+ * <li>{@link StyleConstants#IconElementName}</li>
* </ul>
*/
static class StyledViewFactory
@@ -667,11 +663,11 @@ public class StyledEditorKit extends DefaultEditorKit
* namely the following types of <code>Element</code>s:
*
* <ul>
- * <li>{@link AbstractDocument.ContentElementName}</li>
- * <li>{@link AbstractDocument.ParagraphElementName}</li>
- * <li>{@link AbstractDocument.SectionElementName}</li>
- * <li>{@link StyleContext.ComponentElementName}</li>
- * <li>{@link StyleContext.IconElementName}</li>
+ * <li>{@link AbstractDocument#ContentElementName}</li>
+ * <li>{@link AbstractDocument#ParagraphElementName}</li>
+ * <li>{@link AbstractDocument#SectionElementName}</li>
+ * <li>{@link StyleConstants#ComponentElementName}</li>
+ * <li>{@link StyleConstants#IconElementName}</li>
* </ul>
*
* @return a {@link ViewFactory} that is able to create {@link View}s
diff --git a/javax/swing/text/TabSet.java b/javax/swing/text/TabSet.java
index 146f545aa..ecad9444e 100644
--- a/javax/swing/text/TabSet.java
+++ b/javax/swing/text/TabSet.java
@@ -41,6 +41,9 @@ import java.io.Serializable;
public class TabSet implements Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 2367703481999080593L;
+
TabStop[] tabs;
public TabSet(TabStop[] t)
diff --git a/javax/swing/text/TabStop.java b/javax/swing/text/TabStop.java
index 032da8bca..56f862fda 100644
--- a/javax/swing/text/TabStop.java
+++ b/javax/swing/text/TabStop.java
@@ -41,6 +41,9 @@ import java.io.Serializable;
public class TabStop implements Serializable
{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -5381995917363605058L;
+
public static final int ALIGN_LEFT = 0;
public static final int ALIGN_RIGHT = 1;
public static final int ALIGN_CENTER = 2;
diff --git a/javax/swing/text/Utilities.java b/javax/swing/text/Utilities.java
index d40408ddc..02d98c3b2 100644
--- a/javax/swing/text/Utilities.java
+++ b/javax/swing/text/Utilities.java
@@ -195,4 +195,89 @@ public class Utilities
return maxWidth;
}
+
+ /**
+ * Provides a facility to map screen coordinates into a model location. For a
+ * given text fragment and start location within this fragment, this method
+ * determines the model location so that the resulting fragment fits best
+ * into the span <code>[x0, x]</code>.
+ *
+ * The parameter <code>round</code> controls which model location is returned
+ * if the view coordinates are on a character: If <code>round</code> is
+ * <code>true</code>, then the result is rounded up to the next character, so
+ * that the resulting fragment is the smallest fragment that is larger than
+ * the specified span. If <code>round</code> is <code>false</code>, then the
+ * resulting fragment is the largest fragment that is smaller than the
+ * specified span.
+ *
+ * @param s the text segment
+ * @param fm the font metrics to use
+ * @param x0 the starting screen location
+ * @param x the target screen location at which the requested fragment should
+ * end
+ * @param te the tab expander to use; if this is <code>null</code>, TABs are
+ * expanded to one space character
+ * @param p0 the starting model location
+ * @param round if <code>true</code> round up to the next location, otherwise
+ * round down to the current location
+ *
+ * @return the model location, so that the resulting fragment fits within the
+ * specified span
+ */
+ public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0,
+ int x, TabExpander te, int p0,
+ boolean round)
+ {
+ // At the end of the for loop, this holds the requested model location
+ int pos;
+ int currentX = x0;
+ for (pos = p0; pos < s.getEndIndex(); pos++)
+ {
+ char nextChar = s.array[pos];
+ if (nextChar != '\n')
+ currentX += fm.charWidth(nextChar);
+ else
+ {
+ if (te == null)
+ currentX += fm.charWidth(' ');
+ else
+ currentX = (int) te.nextTabStop(currentX, pos);
+ }
+ if (currentX >= x)
+ {
+ if (! round)
+ pos--;
+ break;
+ }
+ }
+ return pos;
+ }
+
+ /**
+ * Provides a facility to map screen coordinates into a model location. For a
+ * given text fragment and start location within this fragment, this method
+ * determines the model location so that the resulting fragment fits best
+ * into the span <code>[x0, x]</code>.
+ *
+ * This method rounds up to the next location, so that the resulting fragment
+ * will be the smallest fragment of the text, that is greater than the
+ * specified span.
+ *
+ * @param s the text segment
+ * @param fm the font metrics to use
+ * @param x0 the starting screen location
+ * @param x the target screen location at which the requested fragment should
+ * end
+ * @param te the tab expander to use; if this is <code>null</code>, TABs are
+ * expanded to one space character
+ * @param p0 the starting model location
+ *
+ * @return the model location, so that the resulting fragment fits within the
+ * specified span
+ */
+ public static final int getTabbedTextOffset(Segment s, FontMetrics fm, int x0,
+ int x, TabExpander te, int p0)
+ {
+ return getTabbedTextOffset(s, fm, x0, x, te, p0, true);
+ }
}
diff --git a/javax/swing/text/View.java b/javax/swing/text/View.java
index 24efba9a1..9cea4ecb0 100644
--- a/javax/swing/text/View.java
+++ b/javax/swing/text/View.java
@@ -43,7 +43,6 @@ import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
-import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
diff --git a/javax/swing/text/html/CSS.java b/javax/swing/text/html/CSS.java
new file mode 100644
index 000000000..f02ceb89b
--- /dev/null
+++ b/javax/swing/text/html/CSS.java
@@ -0,0 +1,426 @@
+/* CSS.java -- Provides CSS attributes
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+package javax.swing.text.html;
+
+/**
+ * Provides CSS attributes to be used by the HTML view classes. The constants
+ * defined here are used as keys for text attributes for use in
+ * {@link javax.swing.text.AttributeSet}s of {@link javax.swing.text.Element}s.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class CSS
+{
+
+ public static final class Attribute
+ {
+ /**
+ * The CSS attribute 'background'.
+ */
+ public static final Attribute BACKGROUND =
+ new Attribute("background", false, null);
+
+ /**
+ * The CSS attribute 'background-attachment'.
+ */
+ public static final Attribute BACKGROUND_ATTACHMENT =
+ new Attribute("background-attachment", false, "scroll");
+
+ /**
+ * The CSS attribute 'background-color'.
+ */
+ public static final Attribute BACKGROUND_COLOR =
+ new Attribute("background-color", false, "transparent");
+
+ /**
+ * The CSS attribute 'background-image'.
+ */
+ public static final Attribute BACKGROUND_IMAGE =
+ new Attribute("background-image", false, "none");
+
+ /**
+ * The CSS attribute 'background-position'.
+ */
+ public static final Attribute BACKGROUND_POSITION =
+ new Attribute("background-position", false, null);
+
+ /**
+ * The CSS attribute 'background-repeat'.
+ */
+ public static final Attribute BACKGROUND_REPEAT =
+ new Attribute("background-repeat", false, "repeat");
+
+ /**
+ * The CSS attribute 'border'.
+ */
+ public static final Attribute BORDER = new Attribute("border", false, null);
+
+ /**
+ * The CSS attribute 'border-bottom'.
+ */
+ public static final Attribute BORDER_BOTTOM =
+ new Attribute("border-bottom", false, null);
+
+ /**
+ * The CSS attribute 'border-bottom-width'.
+ */
+ public static final Attribute BORDER_BOTTOM_WIDTH =
+ new Attribute("border-bottom-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-color'.
+ */
+ public static final Attribute BORDER_COLOR =
+ new Attribute("border-color", false, "black");
+
+ /**
+ * The CSS attribute 'border-left'.
+ */
+ public static final Attribute BORDER_LEFT =
+ new Attribute("border-left", false, null);
+
+ /**
+ * The CSS attribute 'border-left-width'.
+ */
+ public static final Attribute BORDER_LEFT_WIDTH =
+ new Attribute("border-left-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-right'.
+ */
+ public static final Attribute BORDER_RIGHT =
+ new Attribute("border-right", false, null);
+
+ /**
+ * The CSS attribute 'border-right-width'.
+ */
+ public static final Attribute BORDER_RIGHT_WIDTH =
+ new Attribute("border-right-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-style'.
+ */
+ public static final Attribute BORDER_STYLE =
+ new Attribute("border-style", false, "none");
+
+ /**
+ * The CSS attribute 'border-top'.
+ */
+ public static final Attribute BORDER_TOP =
+ new Attribute("border-top", false, null);
+
+ /**
+ * The CSS attribute 'border-top-width'.
+ */
+ public static final Attribute BORDER_TOP_WIDTH =
+ new Attribute("border-top-width", false, "medium");
+
+ /**
+ * The CSS attribute 'border-width'.
+ */
+ public static final Attribute BORDER_WIDTH =
+ new Attribute("border-width", false, "medium");
+
+ /**
+ * The CSS attribute 'clear'.
+ */
+ public static final Attribute CLEAR = new Attribute("clear", false, "none");
+
+ /**
+ * The CSS attribute 'color'.
+ */
+ public static final Attribute COLOR = new Attribute("color", true, "black");
+
+ /**
+ * The CSS attribute 'display'.
+ */
+ public static final Attribute DISPLAY =
+ new Attribute("display", false, "block");
+
+ /**
+ * The CSS attribute 'float'.
+ */
+ public static final Attribute FLOAT = new Attribute("float", false, "none");
+
+ /**
+ * The CSS attribute 'font'.
+ */
+ public static final Attribute FONT = new Attribute("font", true, null);
+
+ /**
+ * The CSS attribute 'font-family'.
+ */
+ public static final Attribute FONT_FAMILY =
+ new Attribute("font-family", true, null);
+
+ /**
+ * The CSS attribute 'font-size'.
+ */
+ public static final Attribute FONT_SIZE =
+ new Attribute("font-size", true, "medium");
+
+ /**
+ * The CSS attribute 'font-style'.
+ */
+ public static final Attribute FONT_STYLE =
+ new Attribute("font-style", true, "normal");
+
+ /**
+ * The CSS attribute 'font-variant'.
+ */
+ public static final Attribute FONT_VARIANT =
+ new Attribute("font-variant", true, "normal");
+
+ /**
+ * The CSS attribute 'font-weight'.
+ */
+ public static final Attribute FONT_WEIGHT =
+ new Attribute("font-weight", true, "normal");
+
+ /**
+ * The CSS attribute 'height'.
+ */
+ public static final Attribute HEIGHT =
+ new Attribute("height", false, "auto");
+
+ /**
+ * The CSS attribute 'letter-spacing'.
+ */
+ public static final Attribute LETTER_SPACING =
+ new Attribute("letter-spacing", true, "normal");
+
+ /**
+ * The CSS attribute 'line-height'.
+ */
+ public static final Attribute LINE_HEIGHT =
+ new Attribute("line-height", true, "normal");
+
+ /**
+ * The CSS attribute 'list-style'.
+ */
+ public static final Attribute LIST_STYLE =
+ new Attribute("list-style", true, null);
+
+ /**
+ * The CSS attribute 'list-style-image'.
+ */
+ public static final Attribute LIST_STYLE_IMAGE =
+ new Attribute("list-style-image", true, "none");
+
+ /**
+ * The CSS attribute 'list-style-position'.
+ */
+ public static final Attribute LIST_STYLE_POSITION =
+ new Attribute("list-style-position", true, "outside");
+
+ /**
+ * The CSS attribute 'list-style-type'.
+ */
+ public static final Attribute LIST_STYLE_TYPE =
+ new Attribute("list-style-type", true, "disc");
+
+ /**
+ * The CSS attribute 'margin'.
+ */
+ public static final Attribute MARGIN = new Attribute("margin", false, null);
+
+ /**
+ * The CSS attribute 'margin-bottom'.
+ */
+ public static final Attribute MARGIN_BOTTOM =
+ new Attribute("margin-bottom", false, "0");
+
+ /**
+ * The CSS attribute 'margin-left'.
+ */
+ public static final Attribute MARGIN_LEFT =
+ new Attribute("margin-left", false, "0");
+
+ /**
+ * The CSS attribute 'margin-right'.
+ */
+ public static final Attribute MARGIN_RIGHT =
+ new Attribute("margin-right", false, "0");
+
+ /**
+ * The CSS attribute 'margin-top'.
+ */
+ public static final Attribute MARGIN_TOP =
+ new Attribute("margin-top", false, "0");
+
+ /**
+ * The CSS attribute 'padding'.
+ */
+ public static final Attribute PADDING =
+ new Attribute("padding", false, null);
+
+ /**
+ * The CSS attribute 'padding-bottom'.
+ */
+ public static final Attribute PADDING_BOTTOM =
+ new Attribute("padding-bottom", false, "0");
+
+ /**
+ * The CSS attribute 'padding-left'.
+ */
+ public static final Attribute PADDING_LEFT =
+ new Attribute("padding-left", false, "0");
+
+ /**
+ * The CSS attribute 'padding-right'.
+ */
+ public static final Attribute PADDING_RIGHT =
+ new Attribute("padding-right", false, "0");
+
+ /**
+ * The CSS attribute 'padding-top'.
+ */
+ public static final Attribute PADDING_TOP =
+ new Attribute("padding-top", false, "0");
+
+ /**
+ * The CSS attribute 'text-align'.
+ */
+ public static final Attribute TEXT_ALIGN =
+ new Attribute("text-align", true, null);
+
+ /**
+ * The CSS attribute 'text-decoration'.
+ */
+ public static final Attribute TEXT_DECORATION =
+ new Attribute("text-decoration", true, "none");
+
+ /**
+ * The CSS attribute 'text-indent'.
+ */
+ public static final Attribute TEXT_INDENT =
+ new Attribute("text-indent", true, "0");
+
+ /**
+ * The CSS attribute 'text-transform'.
+ */
+ public static final Attribute TEXT_TRANSFORM =
+ new Attribute("text-transform", true, "none");
+
+ /**
+ * The CSS attribute 'vertical-align'.
+ */
+ public static final Attribute VERTICAL_ALIGN =
+ new Attribute("vertical-align", false, "baseline");
+
+ /**
+ * The CSS attribute 'white-space'.
+ */
+ public static final Attribute WHITE_SPACE =
+ new Attribute("white-space", true, "normal");
+
+ /**
+ * The CSS attribute 'width'.
+ */
+ public static final Attribute WIDTH =
+ new Attribute("width", false, "auto");
+
+ /**
+ * The CSS attribute 'word-spacing'.
+ */
+ public static final Attribute WORD_SPACING =
+ new Attribute("word-spacing", true, "normal");
+
+ /**
+ * The attribute string.
+ */
+ String attStr;
+
+ /**
+ * Indicates if this attribute should be inherited from it's parent or
+ * not.
+ */
+ boolean isInherited;
+
+ /**
+ * A default value for this attribute if one exists, otherwise null.
+ */
+ String defaultValue;
+
+ /**
+ * Creates a new Attribute instance with the specified values.
+ *
+ * @param attr the attribute string
+ * @param inherited if the attribute should be inherited or not
+ * @param def a default value; may be <code>null</code>
+ */
+ Attribute(String attr, boolean inherited, String def)
+ {
+ attStr = attr;
+ isInherited = inherited;
+ defaultValue = def;
+ }
+
+ /**
+ * Returns the string representation of this attribute as specified
+ * in the CSS specification.
+ */
+ public String toString()
+ {
+ return attStr;
+ }
+
+ /**
+ * Returns <code>true</code> if the attribute should be inherited from
+ * the parent, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the attribute should be inherited from
+ * the parent, <code>false</code> otherwise
+ */
+ public boolean isInherited()
+ {
+ return isInherited;
+ }
+
+ /**
+ * Returns the default value of this attribute if one exists,
+ * <code>null</code> otherwise.
+ *
+ * @return the default value of this attribute if one exists,
+ * <code>null</code> otherwise
+ */
+ public String getDefaultValue()
+ {
+ return defaultValue;
+ }
+ }
+}
diff --git a/javax/swing/text/html/parser/DTD.java b/javax/swing/text/html/parser/DTD.java
index f17ca011e..1ede342de 100644
--- a/javax/swing/text/html/parser/DTD.java
+++ b/javax/swing/text/html/parser/DTD.java
@@ -81,8 +81,9 @@ public class DTD
{
/**
* The version of the persistent data format.
+ * @specnote This was made <code>final</code> in 1.5.
*/
- public static int FILE_VERSION = 1;
+ public static final int FILE_VERSION = 1;
/**
* The table of existing available DTDs.