Index: javax/swing/text/DefaultStyledDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/DefaultStyledDocument.java,v
retrieving revision 1.14
diff -u -r1.14 DefaultStyledDocument.java
--- javax/swing/text/DefaultStyledDocument.java 30 Oct 2005 18:02:53 -0000 1.14
+++ javax/swing/text/DefaultStyledDocument.java 3 Nov 2005 15:39:35 -0000
@@ -41,9 +41,14 @@
import java.awt.Color;
import java.awt.Font;
import java.io.Serializable;
+import java.util.Enumeration;
import java.util.Vector;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.UndoableEdit;
/**
* The default implementation of address@hidden StyledDocument}.
@@ -61,6 +66,87 @@
implements StyledDocument
{
/**
+ * An address@hidden UndoableEdit} that can undo attribute changes to an element.
+ *
+ * @author Roman Kennke (address@hidden)
+ */
+ public static class AttributeUndoableEdit
+ extends AbstractUndoableEdit
+ {
+ /**
+ * A copy of the old attributes.
+ */
+ protected AttributeSet copy;
+
+ /**
+ * The new attributes.
+ */
+ protected AttributeSet newAttributes;
+
+ /**
+ * If the new attributes replaced the old attributes or if they only were
+ * added to them.
+ */
+ protected boolean isReplacing;
+
+ /**
+ * The element that has changed.
+ */
+ protected Element element;
+
+ /**
+ * Creates a new AttributeUndoableEdit
.
+ *
+ * @param el the element that changes attributes
+ * @param newAtts the new attributes
+ * @param replacing if the new attributes replace the old or only append to
+ * them
+ */
+ public AttributeUndoableEdit(Element el, AttributeSet newAtts,
+ boolean replacing)
+ {
+ element = el;
+ newAttributes = newAtts;
+ isReplacing = replacing;
+ copy = el.getAttributes().copyAttributes();
+ }
+
+ /**
+ * Undos the attribute change. The copy
field is set as
+ * attributes on element
.
+ */
+ public void undo()
+ {
+ super.undo();
+ AttributeSet atts = element.getAttributes();
+ if (atts instanceof MutableAttributeSet)
+ {
+ MutableAttributeSet mutable = (MutableAttributeSet) atts;
+ mutable.removeAttributes(atts);
+ mutable.addAttributes(copy);
+ }
+ }
+
+ /**
+ * Redos an attribute change. This adds newAttributes
to the
+ * element
's attribute set, possibly clearing all attributes
+ * if isReplacing
is true.
+ */
+ public void redo()
+ {
+ super.undo();
+ AttributeSet atts = element.getAttributes();
+ if (atts instanceof MutableAttributeSet)
+ {
+ MutableAttributeSet mutable = (MutableAttributeSet) atts;
+ if (isReplacing)
+ mutable.removeAttributes(atts);
+ mutable.addAttributes(newAttributes);
+ }
+ }
+ }
+
+ /**
* Carries specification information for new address@hidden Element}s that should
* be created in address@hidden ElementBuffer}. This allows the parsing process
* to be decoupled from the Element
creation process.
@@ -714,6 +800,29 @@
}
}
+ /**
+ * Receives notification when any of the document's style changes and calls
+ * address@hidden DefaultStyledDocument#styleChanged(Style)}.
+ *
+ * @author Roman Kennke (address@hidden)
+ */
+ private class StyleChangeListener
+ implements ChangeListener
+ {
+
+ /**
+ * Receives notification when any of the document's style changes and calls
+ * address@hidden DefaultStyledDocument#styleChanged(Style)}.
+ *
+ * @param event the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ Style style = (Style) event.getSource();
+ styleChanged(style);
+ }
+ }
+
/** The serialization UID (compatible with JDK1.5). */
private static final long serialVersionUID = 940485415728614849L;
@@ -729,6 +838,11 @@
protected DefaultStyledDocument.ElementBuffer buffer;
/**
+ * Listens for changes on this document's styles and notifies styleChanged().
+ */
+ private StyleChangeListener styleChangeListener;
+
+ /**
* Creates a new DefaultStyledDocument
.
*/
public DefaultStyledDocument()
@@ -781,7 +895,14 @@
public Style addStyle(String nm, Style parent)
{
StyleContext context = (StyleContext) getAttributeContext();
- return context.addStyle(nm, parent);
+ Style newStyle = context.addStyle(nm, parent);
+
+ // Register change listener.
+ if (styleChangeListener == null)
+ styleChangeListener = new StyleChangeListener();
+ newStyle.addChangeListener(styleChangeListener);
+
+ return newStyle;
}
/**
@@ -1144,5 +1265,93 @@
(ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
buffer.insert(offset, length, elSpecs, ev);
- }
+ }
+
+ /**
+ * Returns an enumeration of all style names.
+ *
+ * @return an enumeration of all style names
+ */
+ public Enumeration getStyleNames()
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getStyleNames();
+ }
+
+ /**
+ * Called when any of this document's styles changes.
+ *
+ * @param style the style that changed
+ */
+ protected void styleChanged(Style style)
+ {
+ // Nothing to do here. This is intended to be overridden by subclasses.
+ }
+
+ /**
+ * Inserts a bulk of structured content at once.
+ *
+ * @param offset the offset at which the content should be inserted
+ * @param data the actual content spec to be inserted
+ */
+ protected void insert(int offset, ElementSpec[] data)
+ throws BadLocationException
+ {
+ writeLock();
+ // First we insert the content.
+ int index = offset;
+ for (int i = 0; i < data.length; i++)
+ {
+ ElementSpec spec = data[i];
+ if (spec.getArray() != null && spec.getLength() > 0)
+ {
+ String insertString = new String(spec.getArray(), spec.getOffset(),
+ spec.getLength());
+ content.insertString(index, insertString);
+ }
+ index += spec.getLength();
+ }
+ // Update the view structure.
+ DefaultDocumentEvent ev = new DefaultDocumentEvent(offset, index - offset,
+ DocumentEvent.EventType.INSERT);
+ for (int i = 0; i < data.length; i++)
+ {
+ ElementSpec spec = data[i];
+ AttributeSet atts = spec.getAttributes();
+ if (atts != null)
+ insertUpdate(ev, atts);
+ }
+
+ // Finally we must update the document structure and fire the insert update
+ // event.
+ buffer.insert(offset, index - offset, data, ev);
+ fireInsertUpdate(ev);
+ writeUnlock();
+ }
+
+ /**
+ * Initializes the DefaultStyledDocument
with the specified
+ * data.
+ *
+ * @param data the specification of the content with which the document is
+ * initialized
+ */
+ protected void create(ElementSpec[] data)
+ {
+ try
+ {
+ // Clear content.
+ content.remove(0, content.length());
+ // Clear buffer and root element.
+ buffer = new ElementBuffer(createDefaultRoot());
+ // Insert the data.
+ insert(0, data);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("Unexpected bad location");
+ err.initCause(ex);
+ throw err;
+ }
+ }
}