diff options
Diffstat (limited to 'libjava/javax/swing/text')
-rw-r--r-- | libjava/javax/swing/text/AbstractDocument.java | 323 | ||||
-rw-r--r-- | libjava/javax/swing/text/AttributeSet.java | 23 | ||||
-rw-r--r-- | libjava/javax/swing/text/DefaultCaret.java | 134 | ||||
-rw-r--r-- | libjava/javax/swing/text/DefaultEditorKit.java | 243 | ||||
-rw-r--r-- | libjava/javax/swing/text/DefaultHighlighter.java | 100 | ||||
-rw-r--r-- | libjava/javax/swing/text/FieldView.java | 8 | ||||
-rw-r--r-- | libjava/javax/swing/text/JTextComponent.java | 584 | ||||
-rw-r--r-- | libjava/javax/swing/text/PlainView.java | 100 | ||||
-rw-r--r-- | libjava/javax/swing/text/Segment.java | 143 | ||||
-rw-r--r-- | libjava/javax/swing/text/TextAction.java | 8 | ||||
-rw-r--r-- | libjava/javax/swing/text/View.java | 45 |
11 files changed, 1506 insertions, 205 deletions
diff --git a/libjava/javax/swing/text/AbstractDocument.java b/libjava/javax/swing/text/AbstractDocument.java index c1ea098c0a9..a7c8c907e60 100644 --- a/libjava/javax/swing/text/AbstractDocument.java +++ b/libjava/javax/swing/text/AbstractDocument.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.text; import java.io.Serializable; +import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import java.util.EventListener; @@ -63,33 +64,37 @@ public abstract class AbstractDocument public static final String ParagraphElementName = "paragraph"; public static final String SectionElementName = "section"; public static final String ElementNameAttribute = "$ename"; + Content content; + AttributeContext context; protected EventListenerList listenerList = new EventListenerList(); protected AbstractDocument(Content doc) { - this(doc, null); + this(doc, StyleContext.getDefaultStyleContext()); } - protected AbstractDocument(Content doc, AttributeContext context) + protected AbstractDocument(Content doc, AttributeContext ctx) { content = doc; + context = ctx; } - // these still need to be implemented by a derived class: + // These still need to be implemented by a derived class: public abstract Element getParagraphElement(int pos); public abstract Element getDefaultRootElement(); - protected Element createBranchElement(Element parent, AttributeSet a) + protected Element createBranchElement(Element parent, + AttributeSet attributes) { - return new BranchElement(parent, a, 0, 0); + return new BranchElement(parent, attributes); } - protected Element createLeafElement(Element parent, AttributeSet a, int p0, - int p1) + protected Element createLeafElement(Element parent, AttributeSet attributes, + int start, int end) { - return new LeafElement(parent, a, p0, p1 - p0); + return new LeafElement(parent, attributes, start, end); } public Position createPosition(final int offset) throws BadLocationException @@ -145,7 +150,7 @@ public abstract class AbstractDocument protected AttributeContext getAttributeContext() { - return null; + return context; } public Element getBidiRootElement() @@ -170,7 +175,13 @@ public abstract class AbstractDocument public Position getEndPosition() { - return null; + return new Position() + { + public int getOffset() + { + return getLength(); + } + }; } public int getLength() @@ -190,12 +201,20 @@ public abstract class AbstractDocument public Element[] getRootElements() { - return null; + Element[] elements = new Element[1]; + elements[0] = getDefaultRootElement(); + return elements; } public Position getStartPosition() { - return null; + return new Position() + { + public int getOffset() + { + return 0; + } + }; } public String getText(int offset, int length) throws BadLocationException @@ -203,34 +222,25 @@ public abstract class AbstractDocument return content.getString(offset, length); } - public void getText(int offset, int length, Segment txt) + public void getText(int offset, int length, Segment segment) throws BadLocationException { - String a = getText(offset, length); - - if (a == null) - { - txt.offset = 0; - txt.count = 0; - txt.array = new char[0]; - - return; - } - - txt.offset = offset; - txt.count = length; - - char[] chars = new char[a.length()]; - - a.getChars(0, a.length(), chars, 0); - - txt.array = chars; + content.getChars(offset, length, segment); } - public void insertString(int offs, String str, AttributeSet a) + public void insertString(int offset, String text, AttributeSet attributes) throws BadLocationException { - content.insertString(offs, str); + // Just return when no text to insert was given. + if (text == null || text.length() == 0) + return; + + DefaultDocumentEvent event = + new DefaultDocumentEvent(offset, text.length(), + DocumentEvent.EventType.INSERT); + content.insertString(offset, text); + insertUpdate(event, attributes); + fireInsertUpdate(event); } protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr) @@ -255,6 +265,26 @@ public abstract class AbstractDocument public void remove(int offset, int length) throws BadLocationException { + DefaultDocumentEvent event = + new DefaultDocumentEvent(offset, length, + DocumentEvent.EventType.REMOVE); + removeUpdate(event); + content.remove(offset, length); + postRemoveUpdate(event); + fireRemoveUpdate(event); + } + + /** + * Replaces some text in the document. + * + * @since 1.4 + */ + public void replace(int offset, int length, String text, + AttributeSet attributes) + throws BadLocationException + { + remove(offset, length); + insertString(offset, text, attributes); } /** @@ -375,47 +405,51 @@ public abstract class AbstractDocument } public abstract class AbstractElement - implements Element, TreeNode, Serializable + implements Element, MutableAttributeSet, TreeNode, Serializable { private static final long serialVersionUID = 1265312733007397733L; int count; int offset; - AttributeSet attr; - Vector elts = new Vector(); - String name; - Element parent; - Vector kids = new Vector(); + + AttributeSet attributes; + + Element element_parent; + Vector element_children; + TreeNode tree_parent; + Vector tree_children; public AbstractElement(Element p, AttributeSet s) { - parent = p; - attr = s; + element_parent = p; + attributes = s; } + // TreeNode implementation + public Enumeration children() { - return kids.elements(); + return Collections.enumeration(tree_children); } - + public boolean getAllowsChildren() { return true; } - + public TreeNode getChildAt(int index) { - return (TreeNode) kids.elementAt(index); + return (TreeNode) tree_children.get(index); } - + public int getChildCount() { - return kids.size(); + return tree_children.size(); } - + public int getIndex(TreeNode node) { - return kids.indexOf(node); + return tree_children.indexOf(node); } public TreeNode getParent() @@ -423,55 +457,134 @@ public abstract class AbstractDocument return tree_parent; } + public abstract boolean isLeaf(); + + + // MutableAttributeSet support + + public void addAttribute(Object name, Object value) + { + attributes = getAttributeContext().addAttribute(attributes, name, value); + } + + public void addAttributes(AttributeSet attrs) + { + attributes = getAttributeContext().addAttributes(attributes, attrs); + } + + public void removeAttribute(Object name) + { + attributes = getAttributeContext().removeAttribute(attributes, name); + } + + public void removeAttributes(AttributeSet attrs) + { + attributes = getAttributeContext().removeAttributes(attributes, attrs); + } + + public void removeAttributes(Enumeration names) + { + attributes = getAttributeContext().removeAttributes(attributes, names); + } + + public void setResolveParent(AttributeSet parent) + { + attributes = getAttributeContext().addAttribute(attributes, ResolveAttribute, parent); + } + + + // AttributeSet interface support + + public boolean containsAttribute(Object name, Object value) + { + return attributes.containsAttribute(name, value); + } + + public boolean containsAttributes(AttributeSet attrs) + { + return attributes.containsAttributes(attrs); + } + + public AttributeSet copyAttributes() + { + return attributes.copyAttributes(); + } + + public Object getAttribute(Object key) + { + return attributes.getAttribute(key); + } + + public int getAttributeCount() + { + return attributes.getAttributeCount(); + } + + public Enumeration getAttributeNames() + { + return attributes.getAttributeNames(); + } + + public AttributeSet getResolveParent() + { + return attributes.getResolveParent(); + } + + public boolean isDefined(Object attrName) + { + return attributes.isDefined(attrName); + } + + public boolean isEqual(AttributeSet attrs) + { + return attributes.isEqual(attrs); + } + + // Element interface support + public AttributeSet getAttributes() { - return attr; + return attributes; } public Document getDocument() { return AbstractDocument.this; } - + public Element getElement(int index) { - return (Element) elts.elementAt(index); + return (Element) element_children.get(index); } - + public String getName() { - return name; + return (String) getAttribute(NameAttribute); } - + public Element getParentElement() { - return parent; + return element_parent; } - - public abstract boolean isLeaf(); - + public abstract int getEndOffset(); - + public abstract int getElementCount(); - + public abstract int getElementIndex(int offset); - + public abstract int getStartOffset(); } public class BranchElement extends AbstractElement { private static final long serialVersionUID = -8595176318868717313L; - private int start; - private int end; + private Vector children = new Vector(); - public BranchElement(Element parent, AttributeSet attributes, int start, - int end) + public BranchElement(Element parent, AttributeSet attributes) { super(parent, attributes); - this.start = start; - this.end = end; } public Enumeration children() @@ -486,6 +599,9 @@ public abstract class AbstractDocument public Element getElement(int index) { + if (index < 0 || index >= children.size()) + return null; + return (Element) children.get(index); } @@ -496,12 +612,20 @@ public abstract class AbstractDocument public int getElementIndex(int offset) { - return children.indexOf(positionToElement(offset)); + if (children.size() == 0) + return 0; + + Element element = positionToElement(offset); + + if (element == null) + return 0; + + return children.indexOf(element); } public int getEndOffset() { - return end; + return ((Element) children.lastElement()).getEndOffset(); } public String getName() @@ -511,7 +635,7 @@ public abstract class AbstractDocument public int getStartOffset() { - return start; + return ((Element) children.firstElement()).getStartOffset(); } public boolean isLeaf() @@ -554,8 +678,18 @@ public abstract class AbstractDocument implements DocumentEvent { private static final long serialVersionUID = -7406103236022413522L; - public int len; - public int off; + + private int offset; + private int length; + private DocumentEvent.EventType type; + + public DefaultDocumentEvent(int offset, int length, + DocumentEvent.EventType type) + { + this.offset = offset; + this.length = length; + this.type = type; + } public Document getDocument() { @@ -564,17 +698,17 @@ public abstract class AbstractDocument public int getLength() { - return len; + return length; } public int getOffset() { - return off; + return offset; } public DocumentEvent.EventType getType() { - return null; + return type; } public DocumentEvent.ElementChange getChange(Element elem) @@ -584,8 +718,43 @@ public abstract class AbstractDocument } public static class ElementEdit extends AbstractUndoableEdit + implements DocumentEvent.ElementChange { private static final long serialVersionUID = -1216620962142928304L; + + private Element elem; + private int index; + private Element[] removed; + private Element[] added; + + public ElementEdit(Element elem, int index, + Element[] removed, Element[] added) + { + this.elem = elem; + this.index = index; + this.removed = removed; + this.added = added; + } + + public Element[] getChildrenAdded() + { + return added; + } + + public Element[] getChildrenRemoved() + { + return removed; + } + + public Element getElement() + { + return elem; + } + + public int getIndex() + { + return index; + } } public class LeafElement extends AbstractElement diff --git a/libjava/javax/swing/text/AttributeSet.java b/libjava/javax/swing/text/AttributeSet.java index 3c31767cf3a..3f38a4cd249 100644 --- a/libjava/javax/swing/text/AttributeSet.java +++ b/libjava/javax/swing/text/AttributeSet.java @@ -56,14 +56,17 @@ public interface AttributeSet static interface ParagraphAttribute { } - - boolean containsAttribute(Object name, Object value); - boolean containsAttributes(AttributeSet attributes); - AttributeSet copyAttributes(); - Object getAttribute(Object key); - int getAttributeCount(); - Enumeration getAttributeNames(); - AttributeSet getResolveParent(); - boolean isDefined(Object attrName); - boolean isEqual(AttributeSet attr); + + static Object NameAttribute = StyleConstants.NameAttribute; + static Object ResolveAttribute = StyleConstants.ResolveAttribute; + + boolean containsAttribute(Object name, Object value); + boolean containsAttributes(AttributeSet attributes); + AttributeSet copyAttributes(); + Object getAttribute(Object key); + int getAttributeCount(); + Enumeration getAttributeNames(); + AttributeSet getResolveParent(); + boolean isDefined(Object attrName); + boolean isEqual(AttributeSet attr); } diff --git a/libjava/javax/swing/text/DefaultCaret.java b/libjava/javax/swing/text/DefaultCaret.java index 968bf1ffdf6..516f0726ba0 100644 --- a/libjava/javax/swing/text/DefaultCaret.java +++ b/libjava/javax/swing/text/DefaultCaret.java @@ -61,15 +61,15 @@ public class DefaultCaret extends Rectangle protected ChangeEvent changeEvent = new ChangeEvent(this); protected EventListenerList listenerList = new EventListenerList(); - Color color = new Color(0, 0, 0); - JTextComponent parent; - Point magic = null; - int mark = 0; - boolean vis_sel = true; - int blink = 500; - int dot = 0; - boolean vis = true; - + private JTextComponent textComponent; + + private boolean selectionVisible = true; + private int blinkRate = 0; + private int dot = 0; + private int mark = 0; + private Point magicCaretPosition = null; + private boolean visible = true; + private Object highlightEntry; public void mouseDragged(MouseEvent event) { @@ -117,27 +117,29 @@ public class DefaultCaret extends Rectangle public void deinstall(JTextComponent c) { - parent.removeFocusListener(this); - parent.removeMouseListener(this); - parent = null; + textComponent.removeFocusListener(this); + textComponent.removeMouseListener(this); + textComponent.removeMouseMotionListener(this); + textComponent = null; } public void install(JTextComponent c) { - parent.addFocusListener(this); - parent.addMouseListener(this); - parent = c; + textComponent = c; + textComponent.addFocusListener(this); + textComponent.addMouseListener(this); + textComponent.addMouseMotionListener(this); repaint(); } public void setMagicCaretPosition(Point p) { - magic = p; + magicCaretPosition = p; } public Point getMagicCaretPosition() { - return magic; + return magicCaretPosition; } public int getMark() @@ -145,27 +147,92 @@ public class DefaultCaret extends Rectangle return mark; } + private void handleHighlight() + { + Highlighter highlighter = textComponent.getHighlighter(); + + if (highlighter == null) + return; + + int p0 = Math.min(dot, mark); + int p1 = Math.max(dot, mark); + + if (selectionVisible && p0 != p1) + { + try + { + if (highlightEntry == null) + highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter()); + else + highlighter.changeHighlight(highlightEntry, p0, p1); + } + catch (BadLocationException e) + { + // This should never happen. + throw new InternalError(); + } + } + else + { + if (highlightEntry != null) + { + highlighter.removeHighlight(highlightEntry); + highlightEntry = null; + } + } + } + public void setSelectionVisible(boolean v) { - vis_sel = v; + if (selectionVisible == v) + return; + + selectionVisible = v; + handleHighlight(); repaint(); } public boolean isSelectionVisible() { - return vis_sel; + return selectionVisible; } protected final void repaint() { - if (parent != null) - parent.repaint(); + if (textComponent != null) + textComponent.repaint(); } public void paint(Graphics g) { - g.setColor(color); - g.drawLine(x, y, x, y + height); + if (textComponent == null) + return; + + int dot = getDot(); + Rectangle rect = null; + + try + { + rect = textComponent.modelToView(dot); + } + catch (BadLocationException e) + { + // This should never happen as dot should be always valid. + return; + } + + if (rect == null) + return; + + // First we need to delete the old caret. + // FIXME: Implement deleting of old caret. + + // Now draw the caret on the new position if visible. + if (visible) + { + g.setColor(textComponent.getCaretColor()); + g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height); + } } public EventListener[] getListeners(Class listenerType) @@ -198,17 +265,17 @@ public class DefaultCaret extends Rectangle protected final JTextComponent getComponent() { - return parent; + return textComponent; } public int getBlinkRate() { - return blink; + return blinkRate; } public void setBlinkRate(int rate) { - blink = rate; + blinkRate = rate; } public int getDot() @@ -218,23 +285,32 @@ public class DefaultCaret extends Rectangle public void moveDot(int dot) { - setDot(dot); + this.dot = dot; + handleHighlight(); + repaint(); } public void setDot(int dot) { this.dot = dot; + this.mark = dot; + handleHighlight(); repaint(); } public boolean isVisible() { - return vis; + return visible; } public void setVisible(boolean v) { - vis = v; + visible = v; repaint(); } + + protected Highlighter.HighlightPainter getSelectionPainter() + { + return DefaultHighlighter.DefaultPainter; + } } diff --git a/libjava/javax/swing/text/DefaultEditorKit.java b/libjava/javax/swing/text/DefaultEditorKit.java index 8611de5a0eb..03d4ef3040e 100644 --- a/libjava/javax/swing/text/DefaultEditorKit.java +++ b/libjava/javax/swing/text/DefaultEditorKit.java @@ -37,6 +37,8 @@ exception statement from your version. */ package javax.swing.text; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; @@ -48,7 +50,121 @@ import javax.swing.JEditorPane; public class DefaultEditorKit extends EditorKit { + public static class BeepAction + extends TextAction + { + public BeepAction() + { + super(beepAction); + } + + public void actionPerformed(ActionEvent event) + { + Toolkit.getDefaultToolkit().beep(); + } + } + + public static class CopyAction + extends TextAction + { + public CopyAction() + { + super(copyAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class CutAction + extends TextAction + { + public CutAction() + { + super(cutAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class DefaultKeyTypedAction + extends TextAction + { + public DefaultKeyTypedAction() + { + super(defaultKeyTypedAction); + } + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + t.getDocument().insertString(t.getCaret().getDot(), event.getActionCommand(), null); + t.getCaret().setDot(Math.min(t.getCaret().getDot() + 1, + t.getDocument().getEndPosition().getOffset())); + t.repaint(); + } + catch (BadLocationException be) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + } + + public static class InsertBreakAction + extends TextAction + { + public InsertBreakAction() + { + super(insertBreakAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class InsertContentAction + extends TextAction + { + public InsertContentAction() + { + super(insertContentAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class InsertTabAction + extends TextAction + { + public InsertTabAction() + { + super(insertTabAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + + public static class PasteAction + extends TextAction + { + public PasteAction() + { + super(pasteAction); + } + public void actionPerformed(ActionEvent event) + { + } + } + private static final long serialVersionUID = 9017245433028523428L; + public static final String backwardAction = "caret-backward"; public static final String beepAction = "beep"; public static final String beginAction = "caret-begin"; @@ -104,6 +220,113 @@ public class DefaultEditorKit extends EditorKit { } + private static Action[] defaultActions = + new Action[] { + new BeepAction(), + new CopyAction(), + new CutAction(), + new DefaultKeyTypedAction(), + new InsertBreakAction(), + new InsertContentAction(), + new InsertTabAction(), + new PasteAction(), + new TextAction(deleteNextCharAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + int pos = t.getCaret().getDot(); + if (pos < t.getDocument().getEndPosition().getOffset()) + { + t.getDocument().remove(t.getCaret().getDot(), 1); + t.repaint(); + } + } + catch (BadLocationException e) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + }, + new TextAction(deletePrevCharAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + int pos = t.getCaret().getDot(); + if (pos > t.getDocument().getStartPosition().getOffset()) + { + t.getDocument().remove(pos - 1, 1); + t.getCaret().setDot(pos - 1); + t.repaint(); + } + } + catch (BadLocationException e) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + }, + new TextAction(backwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().setDot(Math.max(t.getCaret().getDot() - 1, + t.getDocument().getStartPosition().getOffset())); + } + } + }, + new TextAction(forwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().setDot(Math.min(t.getCaret().getDot() + 1, + t.getDocument().getEndPosition().getOffset())); + } + } + }, + new TextAction(selectionBackwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().moveDot(Math.max(t.getCaret().getDot() - 1, + t.getDocument().getStartPosition().getOffset())); + } + } + }, + new TextAction(selectionForwardAction) + { + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + t.getCaret().moveDot(Math.min(t.getCaret().getDot() + 1, + t.getDocument().getEndPosition().getOffset())); + } + } + }, + }; + /** * Called when the kit is being removed from the JEditorPane. */ @@ -116,19 +339,19 @@ public class DefaultEditorKit extends EditorKit } public Caret createCaret() - { - return null; - } + { + return new DefaultCaret(); + } public Document createDefaultDocument() - { - return new PlainDocument(); - } - + { + return new PlainDocument(); + } + public Action[] getActions() - { - return null; - } + { + return defaultActions; + } public String getContentType() { diff --git a/libjava/javax/swing/text/DefaultHighlighter.java b/libjava/javax/swing/text/DefaultHighlighter.java index 003d17d1a8e..234fcad60ff 100644 --- a/libjava/javax/swing/text/DefaultHighlighter.java +++ b/libjava/javax/swing/text/DefaultHighlighter.java @@ -38,7 +38,9 @@ exception statement from your version. */ package javax.swing.text; +import java.awt.Color; import java.awt.Graphics; +import java.awt.Rectangle; import java.awt.Shape; import java.util.Vector; @@ -48,6 +50,87 @@ import javax.swing.text.View; public class DefaultHighlighter extends LayeredHighlighter { + public static class DefaultHighlightPainter + extends LayerPainter + { + private Color color; + + public DefaultHighlightPainter(Color c) + { + super(); + color = c; + } + + public Color getColor() + { + return color; + } + + private void paintHighlight(Graphics g, Rectangle rect) + { + g.fillRect(rect.x, rect.y, rect.width, rect.height); + } + + public void paint(Graphics g, int p0, int p1, Shape bounds, + JTextComponent c) + { + Rectangle r0 = null; + Rectangle r1 = null; + Rectangle rect = bounds.getBounds(); + + try + { + r0 = c.modelToView(p0); + r1 = c.modelToView(p1); + } + catch (BadLocationException e) + { + // This should never occur. + return; + } + + if (r0 == null || r1 == null) + return; + + if (color == null) + g.setColor(c.getSelectionColor()); + else + g.setColor(color); + + // Check if only one line to highlight. + if (r0.y == r1.y) + { + r0.width = r1.x - r0.x; + paintHighlight(g, r0); + return; + } + + // First line, from p0 to end-of-line. + r0.width = rect.x + rect.width - r0.x; + paintHighlight(g, r0); + + // FIXME: All the full lines in between, if any (assumes that all lines + // have the same height -- not a good assumption with JEditorPane/JTextPane). + r0.y += r0.height; + r0.x = rect.x; + + while (r0.y < r1.y) + { + paintHighlight(g, r0); + r0.y += r0.height; + } + + // Last line, from beginnin-of-line to p1. + paintHighlight(g, r1); + } + + public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds, + JTextComponent c, View view) + { + throw new InternalError(); + } + } + private class HighlightEntry { int p0; @@ -77,6 +160,12 @@ public class DefaultHighlighter extends LayeredHighlighter } } + /** + * @specnote final as of 1.4 + */ + public static final LayeredHighlighter.LayerPainter DefaultPainter = + new DefaultHighlightPainter(null); + private JTextComponent textComponent; private Vector highlights = new Vector(); @@ -146,5 +235,16 @@ public class DefaultHighlighter extends LayeredHighlighter public void paint(Graphics g) { + // Check if there are any highlights. + if (highlights.size() == 0) + return; + + Shape bounds = textComponent.getBounds(); + + for (int index = 0; index < highlights.size(); ++index) + { + HighlightEntry entry = (HighlightEntry) highlights.get(index); + entry.painter.paint(g, entry.p0, entry.p1, bounds, textComponent); + } } } diff --git a/libjava/javax/swing/text/FieldView.java b/libjava/javax/swing/text/FieldView.java index 29a00acfa3c..06514b73f14 100644 --- a/libjava/javax/swing/text/FieldView.java +++ b/libjava/javax/swing/text/FieldView.java @@ -90,8 +90,14 @@ public class FieldView extends PlainView return axis = axis == X_AXIS ? 1 : 0; } + public Shape modelToView(int pos, Shape a, Position.Bias bias) + throws BadLocationException + { + return super.modelToView(pos, a, bias); + } + public void paint(Graphics g, Shape s) { - drawLine(0, g, 0, 0); + super.paint(g, s); } } diff --git a/libjava/javax/swing/text/JTextComponent.java b/libjava/javax/swing/text/JTextComponent.java index e44c5296d86..ea69f5d16d9 100644 --- a/libjava/javax/swing/text/JTextComponent.java +++ b/libjava/javax/swing/text/JTextComponent.java @@ -46,13 +46,20 @@ import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.InputMethodListener; +import java.awt.event.KeyEvent; + +import java.util.Enumeration; +import java.util.Hashtable; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleText; +import javax.swing.Action; +import javax.swing.ActionMap; import javax.swing.Icon; +import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JViewport; import javax.swing.KeyStroke; @@ -62,6 +69,8 @@ import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TextUI; @@ -283,11 +292,505 @@ public abstract class JTextComponent extends JComponent } } + /** + * According to <a + * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this + * report</a>, a pair of private classes wraps a {@link + * javax.swing.text.Keymap} in the new {@link InputMap} / {@link + * ActionMap} interfaces, such that old Keymap-using code can make use of + * the new framework.</p> + * + * <p>A little bit of experimentation with these classes reveals the following + * structure: + * + * <ul> + * + * <li>KeymapWrapper extends {@link InputMap} and holds a reference to + * the underlying {@link Keymap}.</li> + * + * <li>KeymapWrapper maps {@link KeyStroke} objects to {@link Action} + * objects, by delegation to the underlying {@link Keymap}.</li> + * + * <li>KeymapActionMap extends {@link ActionMap} also holds a reference to + * the underlying {@link Keymap} but only appears to use it for listing + * its keys. </li> + * + * <li>KeymapActionMap maps all {@link Action} objects to + * <em>themselves</em>, whether they exist in the underlying {@link + * Keymap} or not, and passes other objects to the parent {@link + * ActionMap} for resolving. + * + * </ul> + */ + + private class KeymapWrapper extends InputMap + { + Keymap map; + + public KeymapWrapper(Keymap k) + { + map = k; + } + + public int size() + { + return map.getBoundKeyStrokes().length + super.size(); + } + + public Object get(KeyStroke ks) + { + Action mapped = null; + Keymap m = map; + while(mapped == null && m != null) + { + mapped = m.getAction(ks); + if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED) + mapped = m.getDefaultAction(); + if (mapped == null) + m = m.getResolveParent(); + } + + if (mapped == null) + return super.get(ks); + else + return mapped; + } + + public KeyStroke[] keys() + { + KeyStroke[] superKeys = super.keys(); + KeyStroke[] mapKeys = map.getBoundKeyStrokes(); + KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + + public KeyStroke[] allKeys() + { + KeyStroke[] superKeys = super.allKeys(); + KeyStroke[] mapKeys = map.getBoundKeyStrokes(); + KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + } + + private class KeymapActionMap extends ActionMap + { + Keymap map; + + public KeymapActionMap(Keymap k) + { + map = k; + } + + public Action get(Object cmd) + { + if (cmd instanceof Action) + return (Action) cmd; + else + return super.get(cmd); + } + + public int size() + { + return map.getBoundKeyStrokes().length + super.size(); + } + + public Object[] keys() + { + Object[] superKeys = super.keys(); + Object[] mapKeys = map.getBoundKeyStrokes(); + Object[] bothKeys = new Object[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + + public Object[] allKeys() + { + Object[] superKeys = super.allKeys(); + Object[] mapKeys = map.getBoundKeyStrokes(); + Object[] bothKeys = new Object[superKeys.length + mapKeys.length]; + for (int i = 0; i < superKeys.length; ++i) + bothKeys[i] = superKeys[i]; + for (int i = 0; i < mapKeys.length; ++i) + bothKeys[i + superKeys.length] = mapKeys[i]; + return bothKeys; + } + + } + + static class DefaultKeymap implements Keymap + { + String name; + Keymap parent; + Hashtable map; + Action defaultAction; + + public DefaultKeymap(String name) + { + this.name = name; + this.map = new Hashtable(); + } + + public void addActionForKeyStroke(KeyStroke key, Action a) + { + map.put(key, a); + } + + /** + * Looks up a KeyStroke either in the current map or the parent Keymap; + * does <em>not</em> return the default action if lookup fails. + * + * @param key The KeyStroke to look up an Action for. + * + * @return The mapping for <code>key</code>, or <code>null</code> + * if no mapping exists in this Keymap or any of its parents. + */ + public Action getAction(KeyStroke key) + { + if (map.containsKey(key)) + return (Action) map.get(key); + else if (parent != null) + return parent.getAction(key); + else + return null; + } + + public Action[] getBoundActions() + { + Action [] ret = new Action[map.size()]; + Enumeration e = map.elements(); + int i = 0; + while (e.hasMoreElements()) + { + ret[i++] = (Action) e.nextElement(); + } + return ret; + } + + public KeyStroke[] getBoundKeyStrokes() + { + KeyStroke [] ret = new KeyStroke[map.size()]; + Enumeration e = map.keys(); + int i = 0; + while (e.hasMoreElements()) + { + ret[i++] = (KeyStroke) e.nextElement(); + } + return ret; + } + + public Action getDefaultAction() + { + return defaultAction; + } + + public KeyStroke[] getKeyStrokesForAction(Action a) + { + int i = 0; + Enumeration e = map.keys(); + while (e.hasMoreElements()) + { + if (map.get(e.nextElement()).equals(a)) + ++i; + } + KeyStroke [] ret = new KeyStroke[i]; + i = 0; + e = map.keys(); + while (e.hasMoreElements()) + { + KeyStroke k = (KeyStroke) e.nextElement(); + if (map.get(k).equals(a)) + ret[i++] = k; + } + return ret; + } + + public String getName() + { + return name; + } + + public Keymap getResolveParent() + { + return parent; + } + + public boolean isLocallyDefined(KeyStroke key) + { + return map.containsKey(key); + } + + public void removeBindings() + { + map.clear(); + } + + public void removeKeyStrokeBinding(KeyStroke key) + { + map.remove(key); + } + + public void setDefaultAction(Action a) + { + defaultAction = a; + } + + public void setResolveParent(Keymap p) + { + parent = p; + } + + } + private static final long serialVersionUID = -8796518220218978795L; public static final String DEFAULT_KEYMAP = "default"; public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey"; + + private static Hashtable keymaps = new Hashtable(); + private Keymap keymap; + + /** + * Get a Keymap from the global keymap table, by name. + * + * @param n The name of the Keymap to look up + * + * @return A Keymap associated with the provided name, or + * <code>null</code> if no such Keymap exists + * + * @see #addKeymap() + * @see #removeKeymap() + * @see #keymaps + */ + public static Keymap getKeymap(String n) + { + return (Keymap) keymaps.get(n); + } + + /** + * Remove a Keymap from the global Keymap table, by name. + * + * @param n The name of the Keymap to remove + * + * @return The keymap removed from the global table + * + * @see #addKeymap() + * @see #getKeymap() + * @see #keymaps + */ + public static Keymap removeKeymap(String n) + { + Keymap km = (Keymap) keymaps.get(n); + keymaps.remove(n); + return km; + } + + /** + * Create a new Keymap with a specific name and parent, and add the new + * Keymap to the global keymap table. The name may be <code>null</code>, + * in which case the new Keymap will <em>not</em> be added to the global + * Keymap table. The parent may also be <code>null</code>, which is + * harmless. + * + * @param n The name of the new Keymap, or <code>null</code> + * @param parent The parent of the new Keymap, or <code>null</code> + * + * @return The newly created Keymap + * + * @see #removeKeymap() + * @see #getKeymap() + * @see #keymaps + */ + public static Keymap addKeymap(String n, Keymap parent) + { + Keymap k = new DefaultKeymap(n); + k.setResolveParent(parent); + if (n != null) + keymaps.put(n, k); + return k; + } + /** + * Get the current Keymap of this component. + * + * @return The component's current Keymap + * + * @see #setKeymap() + * @see #keymap + */ + Keymap getKeymap() + { + return keymap; + } + + /** + * Set the current Keymap of this component, installing appropriate + * {@link KeymapWrapper} and {@link KeymapActionMap} objects in the + * {@link InputMap} and {@link ActionMap} parent chains, respectively, + * and fire a property change event with name <code>"keymap"</code>. + * + * @see #getKeymap() + * @see #keymap + */ + public void setKeymap(Keymap k) + { + + // phase 1: replace the KeymapWrapper entry in the InputMap chain. + // the goal here is to always maintain the following ordering: + // + // [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]* + // + // that is to say, component-specific InputMaps need to remain children + // of Keymaps, and Keymaps need to remain children of UI-installed + // InputMaps (and the order of each group needs to be preserved, of + // course). + + KeymapWrapper kw = (k == null ? null : new KeymapWrapper(k)); + InputMap childInputMap = getInputMap(JComponent.WHEN_FOCUSED); + if (childInputMap == null) + setInputMap(JComponent.WHEN_FOCUSED, kw); + else + { + while (childInputMap.getParent() != null + && !(childInputMap.getParent() instanceof KeymapWrapper) + && !(childInputMap.getParent() instanceof InputMapUIResource)) + childInputMap = childInputMap.getParent(); + + // option 1: there is nobody to replace at the end of the chain + if (childInputMap.getParent() == null) + childInputMap.setParent(kw); + + // option 2: there is already a KeymapWrapper in the chain which + // needs replacing (possibly with its own parents, possibly without) + else if (childInputMap.getParent() instanceof KeymapWrapper) + { + if (kw == null) + childInputMap.setParent(childInputMap.getParent().getParent()); + else + { + kw.setParent(childInputMap.getParent().getParent()); + childInputMap.setParent(kw); + } + } + + // option 3: there is an InputMapUIResource in the chain, which marks + // the place where we need to stop and insert ourselves + else if (childInputMap.getParent() instanceof InputMapUIResource) + { + if (kw != null) + { + kw.setParent(childInputMap.getParent()); + childInputMap.setParent(kw); + } + } + } + + // phase 2: replace the KeymapActionMap entry in the ActionMap chain + + KeymapActionMap kam = (k == null ? null : new KeymapActionMap(k)); + ActionMap childActionMap = getActionMap(); + if (childActionMap == null) + setActionMap(kam); + else + { + while (childActionMap.getParent() != null + && !(childActionMap.getParent() instanceof KeymapActionMap) + && !(childActionMap.getParent() instanceof ActionMapUIResource)) + childActionMap = childActionMap.getParent(); + + // option 1: there is nobody to replace at the end of the chain + if (childActionMap.getParent() == null) + childActionMap.setParent(kam); + + // option 2: there is already a KeymapActionMap in the chain which + // needs replacing (possibly with its own parents, possibly without) + else if (childActionMap.getParent() instanceof KeymapActionMap) + { + if (kam == null) + childActionMap.setParent(childActionMap.getParent().getParent()); + else + { + kam.setParent(childActionMap.getParent().getParent()); + childActionMap.setParent(kam); + } + } + + // option 3: there is an ActionMapUIResource in the chain, which marks + // the place where we need to stop and insert ourselves + else if (childActionMap.getParent() instanceof ActionMapUIResource) + { + if (kam != null) + { + kam.setParent(childActionMap.getParent()); + childActionMap.setParent(kam); + } + } + } + + // phase 3: update the explicit keymap field + + Keymap old = keymap; + keymap = k; + firePropertyChange("keymap", old, k); + } + + /** + * Resolves a set of bindings against a set of actions and inserts the + * results into a {@link Keymap}. Specifically, for each provided binding + * <code>b</code>, if there exists a provided action <code>a</code> such + * that <code>a.getValue(Action.NAME) == b.ActionName</code> then an + * entry is added to the Keymap mapping <code>b</code> to + * </code>a</code>. + * + * @param map The Keymap to add new mappings to + * @param bindings The set of bindings to add to the Keymap + * @param actions The set of actions to resolve binding names against + * + * @see Action#NAME + * @see Action#getValue() + * @see KeyBinding#ActionName + */ + public static void loadKeymap(Keymap map, + JTextComponent.KeyBinding[] bindings, + Action[] actions) + { + Hashtable acts = new Hashtable(actions.length); + for (int i = 0; i < actions.length; ++i) + acts.put(actions[i].getValue(Action.NAME), actions[i]); + for (int i = 0; i < bindings.length; ++i) + if (acts.containsKey(bindings[i].actionName)) + map.addActionForKeyStroke(bindings[i].key, (Action) acts.get(bindings[i].actionName)); + } + + /** + * Returns the set of available Actions this component's associated + * editor can run. Equivalent to calling + * <code>getUI().getEditorKit().getActions()</code>. This set of Actions + * is a reasonable value to provide as a parameter to {@link + * #loadKeymap()}, when resolving a set of {@link #KeyBinding} objects + * against this component. + * + * @return The set of available Actions on this component's {@link EditorKit} + * + * @see TextUI#getEditorKit() + * @see EditorKit#getActions() + */ + public Action[] getActions() + { + return getUI().getEditorKit(this).getActions(); + } + private Document doc; private Caret caret; private Highlighter highlighter; @@ -296,19 +799,47 @@ public abstract class JTextComponent extends JComponent private Color selectedTextColor; private Color selectionColor; private boolean editable; + private Insets margin; /** * Creates a new <code>JTextComponent</code> instance. */ public JTextComponent() { + Keymap defkeymap = getKeymap(DEFAULT_KEYMAP); + boolean creatingKeymap = false; + if (defkeymap == null) + { + defkeymap = addKeymap(DEFAULT_KEYMAP, null); + defkeymap.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction()); + creatingKeymap = true; + } + + setFocusable(true); enableEvents(AWTEvent.KEY_EVENT_MASK); updateUI(); + + // need to do this after updateUI() + if (creatingKeymap) + loadKeymap(defkeymap, + new KeyBinding[] { + new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), + DefaultEditorKit.backwardAction), + new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), + DefaultEditorKit.forwardAction), + new KeyBinding(KeyStroke.getKeyStroke("typed \b"), + DefaultEditorKit.deletePrevCharAction), + new KeyBinding(KeyStroke.getKeyStroke("typed \u007f"), + DefaultEditorKit.deleteNextCharAction) + }, + getActions()); } - public void setDocument(Document s) + public void setDocument(Document newDoc) { - doc = s; + Document oldDoc = doc; + doc = newDoc; + firePropertyChange("document", oldDoc, newDoc); revalidate(); repaint(); } @@ -328,18 +859,22 @@ public abstract class JTextComponent extends JComponent return null; } + public void setMargin(Insets m) + { + margin = m; + } + public Insets getMargin() { - // FIXME: Not implemented. - return null; + return margin; } public void setText(String text) { try { - getDocument().remove(0, doc.getLength()); - getDocument().insertString(0, text, null); + doc.remove(0, doc.getLength()); + doc.insertString(0, text, null); } catch (BadLocationException e) { @@ -488,8 +1023,16 @@ public abstract class JTextComponent extends JComponent */ public void setCaret(Caret newCaret) { - firePropertyChange("caret", caret, newCaret); + if (caret != null) + caret.deinstall(this); + + Caret oldCaret = caret; caret = newCaret; + + if (caret != null) + caret.install(this); + + firePropertyChange("caret", oldCaret, newCaret); } public Color getCaretColor() @@ -499,8 +1042,9 @@ public abstract class JTextComponent extends JComponent public void setCaretColor(Color newColor) { - firePropertyChange("caretColor", caretColor, newColor); + Color oldCaretColor = caretColor; caretColor = newColor; + firePropertyChange("caretColor", oldCaretColor, newColor); } public Color getDisabledTextColor() @@ -510,8 +1054,9 @@ public abstract class JTextComponent extends JComponent public void setDisabledTextColor(Color newColor) { - firePropertyChange("disabledTextColor", caretColor, newColor); + Color oldColor = disabledTextColor; disabledTextColor = newColor; + firePropertyChange("disabledTextColor", oldColor, newColor); } public Color getSelectedTextColor() @@ -521,8 +1066,9 @@ public abstract class JTextComponent extends JComponent public void setSelectedTextColor(Color newColor) { - firePropertyChange("selectedTextColor", caretColor, newColor); + Color oldColor = selectedTextColor; selectedTextColor = newColor; + firePropertyChange("selectedTextColor", oldColor, newColor); } public Color getSelectionColor() @@ -532,8 +1078,9 @@ public abstract class JTextComponent extends JComponent public void setSelectionColor(Color newColor) { - firePropertyChange("selectionColor", caretColor, newColor); + Color oldColor = selectionColor; selectionColor = newColor; + firePropertyChange("selectionColor", oldColor, newColor); } /** @@ -584,8 +1131,16 @@ public abstract class JTextComponent extends JComponent public void setHighlighter(Highlighter newHighlighter) { - firePropertyChange("highlighter", highlighter, newHighlighter); + if (highlighter != null) + highlighter.deinstall(this); + + Highlighter oldHighlighter = highlighter; highlighter = newHighlighter; + + if (highlighter != null) + highlighter.install(this); + + firePropertyChange("highlighter", oldHighlighter, newHighlighter); } /** @@ -773,4 +1328,9 @@ public abstract class JTextComponent extends JComponent { return (InputMethodListener[]) getListeners(InputMethodListener.class); } + + public Rectangle modelToView(int position) throws BadLocationException + { + return getUI().modelToView(this, position); + } } diff --git a/libjava/javax/swing/text/PlainView.java b/libjava/javax/swing/text/PlainView.java index 229c7e193b0..3dd8fe44842 100644 --- a/libjava/javax/swing/text/PlainView.java +++ b/libjava/javax/swing/text/PlainView.java @@ -39,6 +39,8 @@ exception statement from your version. */ package javax.swing.text; import java.awt.Color; +import java.awt.Component; +import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Rectangle; @@ -48,12 +50,70 @@ import java.awt.Shape; public class PlainView extends View implements TabExpander { + private Color selectedColor; + private Color unselectedColor; + private Font font; + protected FontMetrics metrics; public PlainView(Element elem) { super(elem); } + + /** + * @since 1.4 + */ + protected void updateMetrics() + { + Component component = getContainer(); + Font font = component.getFont(); + + if (this.font != font) + { + this.font = font; + metrics = component.getFontMetrics(font); + } + } + + /** + * @since 1.4 + */ + protected Rectangle lineToRect(Shape a, int line) + { + // Ensure metrics are up-to-date. + updateMetrics(); + + Rectangle rect = a.getBounds(); + int fontHeight = metrics.getHeight(); + return new Rectangle(rect.x, rect.y + (line * fontHeight), + rect.width, fontHeight); + } + + public Shape modelToView(int position, Shape a, Position.Bias b) + throws BadLocationException + { + Document document = getDocument(); + + // Get rectangle of the line containing position. + int lineIndex = getElement().getElementIndex(position); + Rectangle rect = lineToRect(a, lineIndex); + + // Get the rectangle for position. + Element line = getElement().getElement(lineIndex); + int lineStart = line.getStartOffset(); + Segment segment = new Segment(); + document.getText(lineStart, position - lineStart, segment); + int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x, + this, lineStart); + + // Calc the real rectangle. + rect.x += xoffset; + rect.width = 1; + rect.height = metrics.getHeight(); + + return rect; + } public void drawLine(int lineIndex, Graphics g, int x, int y) { @@ -73,30 +133,31 @@ public class PlainView extends View public int drawSelectedText(Graphics g, int x, int y, int p0, int p1) throws BadLocationException { - String text = getDocument().getText(p0, p1); - g.setColor(Color.WHITE); - g.drawString(text, x, y); - return metrics.stringWidth(text); + g.setColor(selectedColor); + Segment segment = new Segment(); + getDocument().getText(p0, p1 - p0, segment); + return Utilities.drawTabbedText(segment, x, y, g, this, 0); } public int drawUnselectedText(Graphics g, int x, int y, int p0, int p1) throws BadLocationException { - String text = getDocument().getText(p0, p1); - g.setColor(Color.BLACK); - g.drawString(text, x, y); - return metrics.stringWidth(text); + g.setColor(unselectedColor); + Segment segment = new Segment(); + getDocument().getText(p0, p1 - p0, segment); + return Utilities.drawTabbedText(segment, x, y, g, this, 0); } public void paint(Graphics g, Shape s) { - System.out.println("Michael: PlainView.paint"); + JTextComponent textComponent = (JTextComponent) getContainer(); + + g.setFont(textComponent.getFont()); + selectedColor = textComponent.getSelectedTextColor(); + unselectedColor = textComponent.getForeground(); Rectangle rect = s.getBounds(); - g.setColor(Color.WHITE); - g.fillRect(rect.x, rect.y, rect.width, rect.height); - // FIXME: Text may be scrolled. drawLine(0, g, rect.x, rect.y); } @@ -106,10 +167,18 @@ public class PlainView extends View return 8; } + /** + * Returns the next tab stop position after a given reference position. + * + * This implementation ignores the <code>tabStop</code> argument. + * + * @param x the current x position in pixels + * @param tabStop the position within the text stream that the tab occured at + */ public float nextTabStop(float x, int tabStop) { - System.out.println("Michael: PlainView.nextTabpStop: missing implementation"); - return x; + float tabSizePixels = getTabSize() + metrics.charWidth('m'); + return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels; } public float getPreferredSpan(int axis) @@ -119,4 +188,5 @@ public class PlainView extends View return 10; } -}
\ No newline at end of file +} + diff --git a/libjava/javax/swing/text/Segment.java b/libjava/javax/swing/text/Segment.java index 69e2fecfc38..218768e05e2 100644 --- a/libjava/javax/swing/text/Segment.java +++ b/libjava/javax/swing/text/Segment.java @@ -39,10 +39,12 @@ package javax.swing.text; import java.text.CharacterIterator; - public class Segment implements Cloneable, CharacterIterator { + private boolean partialReturn; + private int current; + public char[] array; public int count; public int offset; @@ -67,61 +69,108 @@ public class Segment catch (CloneNotSupportedException e) { return null; - } + } } + + public char current() + { + if (count == 0 + || current >= getEndIndex()) + return DONE; - public char current() - { - return array[getIndex()]; - } + return array[current]; + } - public char first() - { - offset = getBeginIndex(); - return array[offset]; - } + public char first() + { + if (count == 0) + return DONE; + + current = getBeginIndex(); + return array[current]; + } + + public int getBeginIndex() + { + return offset; + } + + public int getEndIndex() + { + return offset + count; + } + + public int getIndex() + { + return current; + } + + public char last() + { + if (count == 0) + return DONE; - public int getBeginIndex() - { - return offset; - } + current = getEndIndex() - 1; + return array[current]; + } + + public char next() + { + if (count == 0) + return DONE; + + if ((current + 1) >= getEndIndex()) + { + current = getEndIndex(); + return DONE; + } - public int getEndIndex() - { - return offset + count; - } + current++; + return array[current]; + } - public int getIndex() - { - return offset; - } + public char previous() + { + if (count == 0 + || current == getBeginIndex()) + return DONE; + + current--; + return array[current]; + } - public char last() - { - offset = getEndIndex() - 1; - return array[offset]; - } + public char setIndex(int position) + { + if (position < getBeginIndex() + || position > getEndIndex()) + throw new IllegalArgumentException(); - public char next() - { - offset++; - return array[offset]; - } + current = position; - public char previous() - { - offset--; - return array[offset]; - } + if (position == getEndIndex()) + return DONE; + + return array[current]; + } - public char setIndex(int position) - { - offset = position; - return array[offset]; - } + public String toString() + { + return new String(array, offset, count); + } - public String toString() - { - return new String(array, offset, count); - } + /** + * @since 1.4 + */ + public void setPartialReturn(boolean p) + { + partialReturn = p; + } + + /** + * @since 1.4 + */ + public boolean isPartialReturn() + { + return partialReturn; + } } diff --git a/libjava/javax/swing/text/TextAction.java b/libjava/javax/swing/text/TextAction.java index 5fee0e8640d..029eed9c5e4 100644 --- a/libjava/javax/swing/text/TextAction.java +++ b/libjava/javax/swing/text/TextAction.java @@ -54,7 +54,7 @@ public abstract class TextAction extends AbstractAction */ public TextAction(String name) { - // TODO + super(name); } /** @@ -64,7 +64,11 @@ public abstract class TextAction extends AbstractAction */ protected final JTextComponent getTextComponent(ActionEvent event) { - return null; // TODO + if (event.getSource() != null && + event.getSource() instanceof JTextComponent) + return (JTextComponent) event.getSource(); + else + return getFocusedComponent(); } /** diff --git a/libjava/javax/swing/text/View.java b/libjava/javax/swing/text/View.java index 6c5a9c296dd..730753a342b 100644 --- a/libjava/javax/swing/text/View.java +++ b/libjava/javax/swing/text/View.java @@ -161,8 +161,49 @@ public abstract class View implements SwingConstants public View createFragment(int p0, int p1) { - // The default implementation doesnt support fragmentation. + // The default implementation doesn't support fragmentation. return this; - } + } + + public int getStartOffset() + { + return elt.getStartOffset(); + } + + public int getEndOffset() + { + return elt.getEndOffset(); + } + + public Shape getChildAllocation(int index, Shape a) + { + return null; + } + + /** + * @since 1.4 + */ + public int getViewIndex(float x, float y, Shape allocation) + { + return -1; + } + + /** + * @since 1.4 + */ + public String getToolTipText(float x, float y, Shape allocation) + { + int index = getViewIndex(x, y, allocation); + + if (index < -1) + return null; + + Shape childAllocation = getChildAllocation(index, allocation); + + if (childAllocation.getBounds().contains(x, y)) + return getView(index).getToolTipText(x, y, childAllocation); + + return null; + } } |