diff options
author | Mark Wielaard <mark@gcc.gnu.org> | 2006-05-18 17:29:21 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2006-05-18 17:29:21 +0000 |
commit | 4f9533c7722fa07511a94d005227961f4a4dec23 (patch) | |
tree | 9f9c470de62ee62fba1331a396450d728d2b1fad /libjava/classpath/javax/swing/text | |
parent | eaec4980e139903ae9b274d1abcf3a13946603a8 (diff) | |
download | gcc-4f9533c7722fa07511a94d005227961f4a4dec23.zip gcc-4f9533c7722fa07511a94d005227961f4a4dec23.tar.gz gcc-4f9533c7722fa07511a94d005227961f4a4dec23.tar.bz2 |
Imported GNU Classpath 0.90
Imported GNU Classpath 0.90
* scripts/makemake.tcl: LocaleData.java moved to gnu/java/locale.
* sources.am: Regenerated.
* gcj/javaprims.h: Regenerated.
* Makefile.in: Regenerated.
* gcj/Makefile.in: Regenerated.
* include/Makefile.in: Regenerated.
* testsuite/Makefile.in: Regenerated.
* gnu/java/lang/VMInstrumentationImpl.java: New override.
* gnu/java/net/local/LocalSocketImpl.java: Likewise.
* gnu/classpath/jdwp/VMMethod.java: Likewise.
* gnu/classpath/jdwp/VMVirtualMachine.java: Update to latest
interface.
* java/lang/Thread.java: Add UncaughtExceptionHandler.
* java/lang/reflect/Method.java: Implements GenericDeclaration and
isSynthetic(),
* java/lang/reflect/Field.java: Likewise.
* java/lang/reflect/Constructor.java
* java/lang/Class.java: Implements Type, GenericDeclaration,
getSimpleName() and getEnclosing*() methods.
* java/lang/Class.h: Add new public methods.
* java/lang/Math.java: Add signum(), ulp() and log10().
* java/lang/natMath.cc (log10): New function.
* java/security/VMSecureRandom.java: New override.
* java/util/logging/Logger.java: Updated to latest classpath
version.
* java/util/logging/LogManager.java: New override.
From-SVN: r113887
Diffstat (limited to 'libjava/classpath/javax/swing/text')
27 files changed, 1948 insertions, 699 deletions
diff --git a/libjava/classpath/javax/swing/text/AbstractDocument.java b/libjava/classpath/javax/swing/text/AbstractDocument.java index a3e8c46..1ef8173 100644 --- a/libjava/classpath/javax/swing/text/AbstractDocument.java +++ b/libjava/classpath/javax/swing/text/AbstractDocument.java @@ -51,6 +51,7 @@ import javax.swing.event.DocumentListener; import javax.swing.event.EventListenerList; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; +import javax.swing.text.DocumentFilter; import javax.swing.tree.TreeNode; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CompoundEdit; @@ -148,6 +149,11 @@ public abstract class AbstractDocument implements Document, Serializable */ Object documentCV = new Object(); + /** An instance of a DocumentFilter.FilterBypass which allows calling + * the insert, remove and replace method without checking for an installed + * document filter. + */ + DocumentFilter.FilterBypass bypass; /** * Creates a new <code>AbstractDocument</code> with the specified @@ -180,6 +186,19 @@ public abstract class AbstractDocument implements Document, Serializable content = doc; context = ctx; } + + /** Returns the DocumentFilter.FilterBypass instance for this + * document and create it if it does not exist yet. + * + * @return This document's DocumentFilter.FilterBypass instance. + */ + private DocumentFilter.FilterBypass getBypass() + { + if (bypass == null) + bypass = new Bypass(); + + return bypass; + } /** * Returns the paragraph {@link Element} that holds the specified position. @@ -329,7 +348,7 @@ public abstract class AbstractDocument implements Document, Serializable * * @return the {@link AttributeContext} used in this <code>Document</code> */ - protected AttributeContext getAttributeContext() + protected final AttributeContext getAttributeContext() { return context; } @@ -366,7 +385,7 @@ public abstract class AbstractDocument implements Document, Serializable * @return the thread that currently modifies this <code>Document</code> * if there is one, otherwise <code>null</code> */ - protected Thread getCurrentWriter() + protected final Thread getCurrentWriter() { return currentWriter; } @@ -392,7 +411,7 @@ public abstract class AbstractDocument implements Document, Serializable * @return a {@link Position} which will always mark the end of the * <code>Document</code> */ - public Position getEndPosition() + public final Position getEndPosition() { // FIXME: Properly implement this by calling Content.createPosition(). return new Position() @@ -437,7 +456,7 @@ public abstract class AbstractDocument implements Document, Serializable * @return the property for <code>key</code> or <code>null</code> if there * is no such property stored */ - public Object getProperty(Object key) + public final Object getProperty(Object key) { // FIXME: make me thread-safe Object value = null; @@ -470,7 +489,7 @@ public abstract class AbstractDocument implements Document, Serializable * @return a {@link Position} which will always mark the beginning of the * <code>Document</code> */ - public Position getStartPosition() + public final Position getStartPosition() { // FIXME: Properly implement this using Content.createPosition(). return new Position() @@ -521,6 +540,13 @@ public abstract class AbstractDocument implements Document, Serializable /** * Inserts a String into this <code>Document</code> at the specified * position and assigning the specified attributes to it. + * + * <p>If a {@link DocumentFilter} is installed in this document, the + * corresponding method of the filter object is called.</p> + * + * <p>The method has no effect when <code>text</code> is <code>null</code> + * or has a length of zero.</p> + * * * @param offset the location at which the string should be inserted * @param text the content to be inserted @@ -532,6 +558,19 @@ public abstract class AbstractDocument implements Document, Serializable public void insertString(int offset, String text, AttributeSet attributes) throws BadLocationException { + // Bail out if we have a bogus insertion (Behavior observed in RI). + if (text == null || text.length() == 0) + return; + + if (documentFilter == null) + insertStringImpl(offset, text, attributes); + else + documentFilter.insertString(getBypass(), offset, text, attributes); + } + + void insertStringImpl(int offset, String text, AttributeSet attributes) + throws BadLocationException + { // Just return when no text to insert was given. if (text == null || text.length() == 0) return; @@ -589,7 +628,7 @@ public abstract class AbstractDocument implements Document, Serializable * @param key the key of the property to be stored * @param value the value of the property to be stored */ - public void putProperty(Object key, Object value) + public final void putProperty(Object key, Object value) { // FIXME: make me thread-safe if (properties == null) @@ -602,7 +641,7 @@ public abstract class AbstractDocument implements Document, Serializable * Blocks until a read lock can be obtained. Must block if there is * currently a writer modifying the <code>Document</code>. */ - public void readLock() + public final void readLock() { if (currentWriter != null && currentWriter.equals(Thread.currentThread())) return; @@ -627,7 +666,7 @@ public abstract class AbstractDocument implements Document, Serializable * Releases the read lock. If this was the only reader on this * <code>Document</code>, writing may begin now. */ - public void readUnlock() + public final void readUnlock() { // Note we could have a problem here if readUnlock was called without a // prior call to readLock but the specs simply warn users to ensure that @@ -673,7 +712,16 @@ public abstract class AbstractDocument implements Document, Serializable /** * Removes a piece of content from this <code>Document</code>. - * + * + * <p>If a {@link DocumentFilter} is installed in this document, the + * corresponding method of the filter object is called. The + * <code>DocumentFilter</code> is called even if <code>length</code> + * is zero. This is different from {@link #replace}.</p> + * + * <p>Note: When <code>length</code> is zero or below the call is not + * forwarded to the underlying {@link AbstractDocument.Content} instance + * of this document and no exception is thrown.</p> + * * @param offset the start offset of the fragment to be removed * @param length the length of the fragment to be removed * @@ -683,6 +731,18 @@ public abstract class AbstractDocument implements Document, Serializable */ public void remove(int offset, int length) throws BadLocationException { + if (documentFilter == null) + removeImpl(offset, length); + else + documentFilter.remove(getBypass(), offset, length); + } + + void removeImpl(int offset, int length) throws BadLocationException + { + // Prevent some unneccessary method invocation (observed in the RI). + if (length <= 0) + return; + DefaultDocumentEvent event = new DefaultDocumentEvent(offset, length, DocumentEvent.EventType.REMOVE); @@ -707,6 +767,13 @@ public abstract class AbstractDocument implements Document, Serializable /** * Replaces a piece of content in this <code>Document</code> with * another piece of content. + * + * <p>If a {@link DocumentFilter} is installed in this document, the + * corresponding method of the filter object is called.</p> + * + * <p>The method has no effect if <code>length</code> is zero (and + * only zero) and, at the same time, <code>text</code> is + * <code>null</code> or has zero length.</p> * * @param offset the start offset of the fragment to be removed * @param length the length of the fragment to be removed @@ -720,11 +787,36 @@ public abstract class AbstractDocument implements Document, Serializable * @since 1.4 */ public void replace(int offset, int length, String text, + AttributeSet attributes) + throws BadLocationException + { + // Bail out if we have a bogus replacement (Behavior observed in RI). + if (length == 0 + && (text == null || text.length() == 0)) + return; + + if (documentFilter == null) + { + // It is important to call the methods which again do the checks + // of the arguments and the DocumentFilter because subclasses may + // have overridden these methods and provide crucial behavior + // which would be skipped if we call the non-checking variants. + // An example for this is PlainDocument where insertString can + // provide a filtering of newlines. + remove(offset, length); + insertString(offset, text, attributes); + } + else + documentFilter.replace(getBypass(), offset, length, text, attributes); + + } + + void replaceImpl(int offset, int length, String text, AttributeSet attributes) throws BadLocationException { - remove(offset, length); - insertString(offset, text, attributes); + removeImpl(offset, length); + insertStringImpl(offset, text, attributes); } /** @@ -854,7 +946,7 @@ public abstract class AbstractDocument implements Document, Serializable * Blocks until a write lock can be obtained. Must wait if there are * readers currently reading or another thread is currently writing. */ - protected void writeLock() + protected final void writeLock() { if (currentWriter != null && currentWriter.equals(Thread.currentThread())) return; @@ -881,7 +973,7 @@ public abstract class AbstractDocument implements Document, Serializable * Releases the write lock. This allows waiting readers or writers to * obtain the lock. */ - protected void writeUnlock() + protected final void writeUnlock() { synchronized (documentCV) { @@ -2239,4 +2331,37 @@ public abstract class AbstractDocument implements Document, Serializable + getStartOffset() + "," + getEndOffset() + "\n"); } } + + /** A class whose methods delegate to the insert, remove and replace methods + * of this document which do not check for an installed DocumentFilter. + */ + class Bypass extends DocumentFilter.FilterBypass + { + + public Document getDocument() + { + return AbstractDocument.this; + } + + public void insertString(int offset, String string, AttributeSet attr) + throws BadLocationException + { + AbstractDocument.this.insertStringImpl(offset, string, attr); + } + + public void remove(int offset, int length) + throws BadLocationException + { + AbstractDocument.this.removeImpl(offset, length); + } + + public void replace(int offset, int length, String string, + AttributeSet attrs) + throws BadLocationException + { + AbstractDocument.this.replaceImpl(offset, length, string, attrs); + } + + } + } diff --git a/libjava/classpath/javax/swing/text/AsyncBoxView.java b/libjava/classpath/javax/swing/text/AsyncBoxView.java index 1988bba..90447f8 100644 --- a/libjava/classpath/javax/swing/text/AsyncBoxView.java +++ b/libjava/classpath/javax/swing/text/AsyncBoxView.java @@ -1030,7 +1030,7 @@ public class AsyncBoxView * * @since 1.4 */ - public void setEstimatedMajorSpan(boolean estimated) + protected void setEstimatedMajorSpan(boolean estimated) { estimatedMajorSpan = estimated; } @@ -1045,7 +1045,7 @@ public class AsyncBoxView * * @since 1.4 */ - public boolean getEstimatedMajorSpan() + protected boolean getEstimatedMajorSpan() { return estimatedMajorSpan; } @@ -1367,7 +1367,7 @@ public class AsyncBoxView /** * Updates the layout for this view. This is implemented to trigger - * {link ChildLocator#childChanged} for the changed view, if there is + * {@link ChildLocator#childChanged} for the changed view, if there is * any. * * @param ec the element change, may be <code>null</code> if there were diff --git a/libjava/classpath/javax/swing/text/BoxView.java b/libjava/classpath/javax/swing/text/BoxView.java index b5907dc..a184a81 100644 --- a/libjava/classpath/javax/swing/text/BoxView.java +++ b/libjava/classpath/javax/swing/text/BoxView.java @@ -1,5 +1,5 @@ /* BoxView.java -- An composite view - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -591,9 +591,12 @@ public class BoxView for (int i = 0; i < count; ++i) { copy.setBounds(r); - childAllocation(i, r); + // The next call modifies copy. + childAllocation(i, copy); if (copy.contains(x, y)) { + // Modify r on success. + r.setBounds(copy); result = getView(i); break; } @@ -919,7 +922,7 @@ public class BoxView return super.viewToModel(x, y, a, bias); } - protected boolean flipEastAndWestEnds(int position, Position.Bias bias) + protected boolean flipEastAndWestAtEnds(int position, Position.Bias bias) { // FIXME: What to do here? return super.flipEastAndWestAtEnds(position, bias); diff --git a/libjava/classpath/javax/swing/text/CompositeView.java b/libjava/classpath/javax/swing/text/CompositeView.java index a10aca7..17f13db 100644 --- a/libjava/classpath/javax/swing/text/CompositeView.java +++ b/libjava/classpath/javax/swing/text/CompositeView.java @@ -1,5 +1,5 @@ /* CompositeView.java -- An abstract view that manages child views - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -218,21 +218,24 @@ public abstract class CompositeView throws BadLocationException { int childIndex = getViewIndex(pos, bias); + if (childIndex == -1) + throw new BadLocationException("Position " + pos + " is not represented by view.", pos); + Shape ret = null; - if (childIndex != -1) - { - View child = getView(childIndex); - Shape childAlloc = getChildAllocation(childIndex, a); - if (childAlloc == null) - ret = createDefaultLocation(a, bias); - Shape result = child.modelToView(pos, childAlloc, bias); - if (result != null) - ret = result; - else - ret = createDefaultLocation(a, bias); - } - else + + View child = getView(childIndex); + Shape childAlloc = getChildAllocation(childIndex, a); + + if (childAlloc == null) ret = createDefaultLocation(a, bias); + + Shape result = child.modelToView(pos, childAlloc, bias); + + if (result != null) + ret = result; + else + ret = createDefaultLocation(a, bias); + return ret; } @@ -301,7 +304,7 @@ public abstract class CompositeView { Rectangle r = getInsideAllocation(a); View view = getViewAtPoint((int) x, (int) y, r); - return view.viewToModel(x, y, a, b); + return view.viewToModel(x, y, r, b); } return 0; } @@ -630,8 +633,51 @@ public abstract class CompositeView Position.Bias[] biasRet) throws BadLocationException { - // FIXME: Implement this correctly. - return pos; + // TODO: It is unknown to me how this method has to be implemented and + // there is no specification telling me how to do it properly. Therefore + // the implementation was done for cases that are known. + // + // If this method ever happens to act silly for your particular case then + // it is likely that it is a cause of not knowing about your case when it + // was implemented first. You are free to fix the behavior. + // + // Here are the assumptions that lead to the implementation: + // If direction is NORTH chose the View preceding the one that contains the + // offset 'pos' (imagine the views are stacked on top of each other where + // the top is 0 and the bottom is getViewCount()-1. + // Consecutively when the direction is SOUTH the View following the one + // the offset 'pos' lies in is questioned. + // + // This limitation is described as PR 27345. + int index = getViewIndex(pos, b); + View v = null; + + if (index == -1) + return pos; + + switch (direction) + { + case NORTH: + // If we cannot calculate a proper offset return the one that was + // provided. + if (index <= 0) + return pos; + + v = getView(index - 1); + break; + case SOUTH: + // If we cannot calculate a proper offset return the one that was + // provided. + if (index >= getViewCount() - 1) + return pos; + + v = getView(index + 1); + break; + default: + throw new IllegalArgumentException(); + } + + return v.getNextVisualPositionFrom(pos, b, a, direction, biasRet); } /** @@ -664,8 +710,55 @@ public abstract class CompositeView Position.Bias[] biasRet) throws BadLocationException { - // FIXME: Implement this correctly. - return pos; + // TODO: It is unknown to me how this method has to be implemented and + // there is no specification telling me how to do it properly. Therefore + // the implementation was done for cases that are known. + // + // If this method ever happens to act silly for your particular case then + // it is likely that it is a cause of not knowing about your case when it + // was implemented first. You are free to fix the behavior. + // + // Here are the assumptions that lead to the implementation: + // If direction is EAST increase the offset by one and ask the View to + // which that index belong to calculate the 'next visual position'. + // If the direction is WEST do the same with offset 'pos' being decreased + // by one. + // This behavior will fail in a right-to-left or bidi environment! + // + // This limitation is described as PR 27346. + int index; + + View v = null; + + switch (direction) + { + case EAST: + index = getViewIndex(pos + 1, b); + // If we cannot calculate a proper offset return the one that was + // provided. + if (index == -1) + return pos; + + v = getView(index); + break; + case WEST: + index = getViewIndex(pos - 1, b); + // If we cannot calculate a proper offset return the one that was + // provided. + if (index == -1) + return pos; + + v = getView(index); + break; + default: + throw new IllegalArgumentException(); + } + + return v.getNextVisualPositionFrom(pos, + b, + a, + direction, + biasRet); } /** diff --git a/libjava/classpath/javax/swing/text/DefaultCaret.java b/libjava/classpath/javax/swing/text/DefaultCaret.java index f2a68c0..c9369af 100644 --- a/libjava/classpath/javax/swing/text/DefaultCaret.java +++ b/libjava/classpath/javax/swing/text/DefaultCaret.java @@ -59,17 +59,48 @@ import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.EventListenerList; +import javax.swing.text.Position.Bias; /** * The default implementation of the {@link Caret} interface. * - * @author orgininal author unknown + * @author original author unknown * @author Roman Kennke (roman@kennke.org) */ public class DefaultCaret extends Rectangle implements Caret, FocusListener, MouseListener, MouseMotionListener { + + /** A text component in the current VM which currently has a + * text selection or <code>null</code>. + */ + static JTextComponent componentWithSelection; + + /** An implementation of NavigationFilter.FilterBypass which delegates + * to the corresponding methods of the <code>DefaultCaret</code>. + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ + class Bypass extends NavigationFilter.FilterBypass + { + + public Caret getCaret() + { + return DefaultCaret.this; + } + public void moveDot(int dot, Bias bias) + { + DefaultCaret.this.moveDotImpl(dot); + } + + public void setDot(int dot, Bias bias) + { + DefaultCaret.this.setDotImpl(dot); + } + + } + /** * Controls the blinking of the caret. * @@ -294,12 +325,29 @@ public class DefaultCaret extends Rectangle private BlinkTimerListener blinkListener; /** + * A <code>NavigationFilter.FilterBypass</code> instance which + * is provided to the a <code>NavigationFilter</code> to + * unconditionally set or move the caret. + */ + NavigationFilter.FilterBypass bypass; + + /** * Creates a new <code>DefaultCaret</code> instance. */ public DefaultCaret() { // Nothing to do here. } + + /** Returns the caret's <code>NavigationFilter.FilterBypass</code> instance + * and creates it if it does not yet exist. + * + * @return The caret's <code>NavigationFilter.FilterBypass</code> instance. + */ + private NavigationFilter.FilterBypass getBypass() + { + return (bypass == null) ? bypass = new Bypass() : bypass; + } /** * Sets the Caret update policy. @@ -346,7 +394,8 @@ public class DefaultCaret extends Rectangle */ public void mouseDragged(MouseEvent event) { - moveCaret(event); + if (event.getButton() == MouseEvent.BUTTON1) + moveCaret(event); } /** @@ -379,7 +428,7 @@ public class DefaultCaret extends Rectangle { int count = event.getClickCount(); - if (count >= 2) + if (event.getButton() == MouseEvent.BUTTON1 && count >= 2) { int newDot = getComponent().viewToModel(event.getPoint()); JTextComponent t = getComponent(); @@ -387,29 +436,42 @@ public class DefaultCaret extends Rectangle try { if (count == 3) - t.select(Utilities.getRowStart(t, newDot), Utilities.getRowEnd(t, newDot)); + { + setDot(Utilities.getRowStart(t, newDot)); + moveDot( Utilities.getRowEnd(t, newDot)); + } else { - int nextWord = Utilities.getNextWord(t, newDot); + int wordStart = Utilities.getWordStart(t, newDot); // When the mouse points at the offset of the first character // in a word Utilities().getPreviousWord will not return that // word but we want to select that. We have to use - // Utilities.nextWord() to get it. - if (newDot == nextWord) - t.select(nextWord, Utilities.getNextWord(t, nextWord)); + // Utilities.getWordStart() to get it. + if (newDot == wordStart) + { + setDot(wordStart); + moveDot(Utilities.getWordEnd(t, wordStart)); + } else { + int nextWord = Utilities.getNextWord(t, newDot); int previousWord = Utilities.getPreviousWord(t, newDot); int previousWordEnd = Utilities.getWordEnd(t, previousWord); // If the user clicked in the space between two words, // then select the space. if (newDot >= previousWordEnd && newDot <= nextWord) - t.select(previousWordEnd, nextWord); + { + setDot(previousWordEnd); + moveDot(nextWord); + } // Otherwise select the word under the mouse pointer. else - t.select(previousWord, previousWordEnd); + { + setDot(previousWord); + moveDot(previousWordEnd); + } } } } @@ -417,8 +479,6 @@ public class DefaultCaret extends Rectangle { // TODO: Swallowing ok here? } - - dot = newDot; } } @@ -455,10 +515,35 @@ public class DefaultCaret extends Rectangle */ public void mousePressed(MouseEvent event) { - if (event.isShiftDown()) - moveCaret(event); - else - positionCaret(event); + int button = event.getButton(); + + // The implementation assumes that consuming the event makes the AWT event + // mechanism forget about this event instance and not transfer focus. + // By observing how the RI reacts the following behavior has been + // implemented (in regard to text components): + // - a left-click moves the caret + // - a left-click when shift is held down expands the selection + // - a right-click or click with any additionaly mouse button + // on a text component is ignored + // - a middle-click positions the caret and pastes the clipboard + // contents. + // - a middle-click when shift is held down is ignored + + if (button == MouseEvent.BUTTON1) + if (event.isShiftDown()) + moveCaret(event); + else + positionCaret(event); + else if(button == MouseEvent.BUTTON2) + if (event.isShiftDown()) + event.consume(); + else + { + positionCaret(event); + textComponent.paste(); + } + else + event.consume(); } /** @@ -636,10 +721,13 @@ public class DefaultCaret extends Rectangle { try { - if (highlightEntry == null) - highlightEntry = highlighter.addHighlight(0, 0, getSelectionPainter()); - else + if (highlightEntry != null) highlighter.changeHighlight(highlightEntry, 0, 0); + + // Free the global variable which stores the text component with an active + // selection. + if (componentWithSelection == textComponent) + componentWithSelection = null; } catch (BadLocationException e) { @@ -675,6 +763,17 @@ public class DefaultCaret extends Rectangle highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter()); else highlighter.changeHighlight(highlightEntry, p0, p1); + + // If another component currently has a text selection clear that selection + // first. + if (componentWithSelection != null) + if (componentWithSelection != textComponent) + { + Caret c = componentWithSelection.getCaret(); + c.setDot(c.getDot()); + } + componentWithSelection = textComponent; + } catch (BadLocationException e) { @@ -776,7 +875,7 @@ public class DefaultCaret extends Rectangle if (visible) { g.setColor(textComponent.getCaretColor()); - g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height); + g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height - 1); } } @@ -888,12 +987,24 @@ public class DefaultCaret extends Rectangle * Moves the <code>dot</code> location without touching the * <code>mark</code>. This is used when making a selection. * + * <p>If the underlying text component has a {@link NavigationFilter} + * installed the caret will call the corresponding method of that object.</p> + * * @param dot the location where to move the dot * * @see #setDot(int) */ public void moveDot(int dot) { + NavigationFilter filter = textComponent.getNavigationFilter(); + if (filter != null) + filter.moveDot(getBypass(), dot, Bias.Forward); + else + moveDotImpl(dot); + } + + void moveDotImpl(int dot) + { if (dot >= 0) { Document doc = textComponent.getDocument(); @@ -902,8 +1013,8 @@ public class DefaultCaret extends Rectangle this.dot = Math.max(this.dot, 0); handleHighlight(); - adjustVisibility(this); appear(); + adjustVisibility(this); } } @@ -912,12 +1023,24 @@ public class DefaultCaret extends Rectangle * <code>Document</code>. This also sets the <code>mark</code> to the new * location. * + * <p>If the underlying text component has a {@link NavigationFilter} + * installed the caret will call the corresponding method of that object.</p> + * * @param dot * the new position to be set * @see #moveDot(int) */ public void setDot(int dot) { + NavigationFilter filter = textComponent.getNavigationFilter(); + if (filter != null) + filter.setDot(getBypass(), dot, Bias.Forward); + else + setDotImpl(dot); + } + + void setDotImpl(int dot) + { if (dot >= 0) { Document doc = textComponent.getDocument(); @@ -927,8 +1050,8 @@ public class DefaultCaret extends Rectangle this.mark = this.dot; clearHighlight(); - adjustVisibility(this); appear(); + adjustVisibility(this); } } @@ -1043,7 +1166,16 @@ public class DefaultCaret extends Rectangle // must set a valid value here, since otherwise the painting mechanism // sets a zero clip and never calls paint. if (height <= 0) - height = getComponent().getHeight(); + try + { + height = textComponent.modelToView(dot).height; + } + catch (BadLocationException ble) + { + // Should not happen. + throw new InternalError("Caret location not within document range."); + } + repaint(); } @@ -1068,4 +1200,5 @@ public class DefaultCaret extends Rectangle blinkTimer = new Timer(getBlinkRate(), blinkListener); blinkTimer.setRepeats(true); } + } diff --git a/libjava/classpath/javax/swing/text/DefaultEditorKit.java b/libjava/classpath/javax/swing/text/DefaultEditorKit.java index c005696..1b68618 100644 --- a/libjava/classpath/javax/swing/text/DefaultEditorKit.java +++ b/libjava/classpath/javax/swing/text/DefaultEditorKit.java @@ -63,6 +63,663 @@ import javax.swing.Action; */ public class DefaultEditorKit extends EditorKit { + static class SelectionPreviousWordAction + extends TextAction + { + SelectionPreviousWordAction() + { + super(selectionPreviousWordAction); + } + + public void actionPerformed(ActionEvent event) + { + try + { + JTextComponent t = getTextComponent(event); + + if (t != null) + { + int offs = Utilities.getPreviousWord(t, t.getCaretPosition()); + + Caret c = t.getCaret(); + c.moveDot(offs); + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class SelectionNextWordAction + extends TextAction + { + SelectionNextWordAction() + { + super(selectionNextWordAction); + } + + public void actionPerformed(ActionEvent event) + { + try + { + JTextComponent t = getTextComponent(event); + + if (t != null) + { + int offs = Utilities.getNextWord(t, t.getCaretPosition()); + + Caret c = t.getCaret(); + c.moveDot(offs); + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class PreviousWordAction + extends TextAction + { + PreviousWordAction() + { + super(previousWordAction); + } + + public void actionPerformed(ActionEvent event) + { + try + { + JTextComponent t = getTextComponent(event); + + if (t != null) + { + int offs = Utilities.getPreviousWord(t, t.getCaretPosition()); + + Caret c = t.getCaret(); + c.setDot(offs); + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class NextWordAction + extends TextAction + { + NextWordAction() + { + super(nextWordAction); + } + + public void actionPerformed(ActionEvent event) + { + try + { + JTextComponent t = getTextComponent(event); + + if (t != null) + { + int offs = Utilities.getNextWord(t, t.getCaretPosition()); + + Caret c = t.getCaret(); + c.setDot(offs); + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class SelectAllAction + extends TextAction + { + SelectAllAction() + { + super(selectAllAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + int offs = t.getDocument().getLength(); + Caret c = t.getCaret(); + c.setDot(0); + c.moveDot(offs); + + try + { + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class SelectionBeginAction + extends TextAction + { + SelectionBeginAction() + { + super(selectionBeginAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + Caret c = t.getCaret(); + c.moveDot(0); + try + { + c.setMagicCaretPosition(t.modelToView(0).getLocation()); + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class SelectionEndAction + extends TextAction + { + SelectionEndAction() + { + super(selectionEndAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + int offs = t.getDocument().getLength(); + Caret c = t.getCaret(); + c.moveDot(offs); + try + { + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + + static class SelectionEndLineAction + extends TextAction + { + SelectionEndLineAction() + { + super(selectionEndLineAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + Point p = t.modelToView(t.getCaret().getDot()).getLocation(); + int cur = t.getCaretPosition(); + int y = p.y; + int length = t.getDocument().getLength(); + while (y == p.y && cur < length) + y = t.modelToView(++cur).getLocation().y; + if (cur != length) + cur--; + + Caret c = t.getCaret(); + c.moveDot(cur); + c.setMagicCaretPosition(t.modelToView(cur).getLocation()); + } + catch (BadLocationException ble) + { + // Nothing to do here + } + } + } + + static class SelectionBeginLineAction + extends TextAction + { + SelectionBeginLineAction() + { + super(selectionBeginLineAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + + try + { + // TODO: There is a more efficent solution, but + // viewToModel doesn't work properly. + Point p = t.modelToView(t.getCaret().getDot()).getLocation(); + + int cur = t.getCaretPosition(); + int y = p.y; + + while (y == p.y && cur > 0) + y = t.modelToView(--cur).getLocation().y; + if (cur != 0) + cur++; + + Caret c = t.getCaret(); + c.moveDot(cur); + c.setMagicCaretPosition(t.modelToView(cur).getLocation()); + } + catch (BadLocationException ble) + { + // Do nothing here. + } + } + } + + static class SelectionDownAction + extends TextAction + { + SelectionDownAction() + { + super(selectionDownAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + if (t != null) + { + Caret c = t.getCaret(); + // The magic caret position may be null when the caret + // has not moved yet. + Point mcp = c.getMagicCaretPosition(); + int x = (mcp != null) ? mcp.x : 0; + int pos = Utilities.getPositionBelow(t, t.getCaretPosition(), x); + + if (pos > -1) + t.moveCaretPosition(pos); + } + } + catch(BadLocationException ble) + { + // FIXME: Swallowing allowed? + } + } + } + + static class SelectionUpAction + extends TextAction + { + SelectionUpAction() + { + super(selectionUpAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + if (t != null) + { + Caret c = t.getCaret(); + // The magic caret position may be null when the caret + // has not moved yet. + Point mcp = c.getMagicCaretPosition(); + int x = (mcp != null) ? mcp.x : 0; + int pos = Utilities.getPositionAbove(t, t.getCaretPosition(), x); + + if (pos > -1) + t.moveCaretPosition(pos); + } + } + catch(BadLocationException ble) + { + // FIXME: Swallowing allowed? + } + } + } + + static class SelectionForwardAction + extends TextAction + { + SelectionForwardAction() + { + super(selectionForwardAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + int offs = t.getCaretPosition() + 1; + + if(offs <= t.getDocument().getLength()) + { + Caret c = t.getCaret(); + c.moveDot(offs); + try + { + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + } + } + + static class SelectionBackwardAction + extends TextAction + { + SelectionBackwardAction() + { + super(selectionBackwardAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + int offs = t.getCaretPosition() - 1; + + if(offs >= 0) + { + Caret c = t.getCaret(); + c.moveDot(offs); + try + { + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + catch(BadLocationException ble) + { + // Can't happen. + } + } + } + } + } + + static class DownAction + extends TextAction + { + DownAction() + { + super(downAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + if (t != null) + { + Caret c = t.getCaret(); + // The magic caret position may be null when the caret + // has not moved yet. + Point mcp = c.getMagicCaretPosition(); + int x = (mcp != null) ? mcp.x : 0; + int pos = Utilities.getPositionBelow(t, t.getCaretPosition(), x); + + if (pos > -1) + t.setCaretPosition(pos); + } + } + catch(BadLocationException ble) + { + // FIXME: Swallowing allowed? + } + } + } + + static class UpAction + extends TextAction + { + UpAction() + { + super(upAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + if (t != null) + { + Caret c = t.getCaret(); + // The magic caret position may be null when the caret + // has not moved yet. + Point mcp = c.getMagicCaretPosition(); + int x = (mcp != null) ? mcp.x : 0; + int pos = Utilities.getPositionAbove(t, t.getCaretPosition(), x); + + if (pos > -1) + t.setCaretPosition(pos); + } + } + catch(BadLocationException ble) + { + // FIXME: Swallowing allowed? + } + } + } + + static class ForwardAction + extends TextAction + { + ForwardAction() + { + super(forwardAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + int offs = t.getCaretPosition() + 1; + if (offs <= t.getDocument().getLength()) + { + Caret c = t.getCaret(); + c.setDot(offs); + + try + { + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + catch (BadLocationException ble) + { + // Should not happen. + } + } + } + + } + } + + static class BackwardAction + extends TextAction + { + BackwardAction() + { + super(backwardAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + int offs = t.getCaretPosition() - 1; + if (offs >= 0) + { + Caret c = t.getCaret(); + c.setDot(offs); + + try + { + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + catch (BadLocationException ble) + { + // Should not happen. + } + } + } + } + } + + static class DeletePrevCharAction + extends TextAction + { + DeletePrevCharAction() + { + super(deletePrevCharAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + int pos = t.getSelectionStart(); + int len = t.getSelectionEnd() - pos; + + if (len > 0) + t.getDocument().remove(pos, len); + else if (pos > 0) + { + pos--; + t.getDocument().remove(pos, 1); + Caret c = t.getCaret(); + c.setDot(pos); + c.setMagicCaretPosition(t.modelToView(pos).getLocation()); + } + } + catch (BadLocationException e) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + } + + static class DeleteNextCharAction + extends TextAction + { + DeleteNextCharAction() + { + super(deleteNextCharAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + if (t != null) + { + try + { + int pos = t.getSelectionStart(); + int len = t.getSelectionEnd() - pos; + + if (len > 0) + t.getDocument().remove(pos, len); + else if (pos < t.getDocument().getLength()) + t.getDocument().remove(pos, 1); + + Caret c = t.getCaret(); + c.setDot(pos); + c.setMagicCaretPosition(t.modelToView(pos).getLocation()); + } + catch (BadLocationException e) + { + // FIXME: we're not authorized to throw this.. swallow it? + } + } + } + } + + static class EndLineAction + extends TextAction + { + EndLineAction() + { + super(endLineAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + int offs = Utilities.getRowEnd(t, t.getCaretPosition()); + + if (offs > -1) + { + Caret c = t.getCaret(); + c.setDot(offs); + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + } + catch (BadLocationException ble) + { + // Nothing to do here + } + } + } + + static class BeginLineAction + extends TextAction + { + BeginLineAction() + { + super(beginLineAction); + } + + public void actionPerformed(ActionEvent event) + { + JTextComponent t = getTextComponent(event); + try + { + int offs = Utilities.getRowStart(t, t.getCaretPosition()); + + if (offs > -1) + { + Caret c = t.getCaret(); + c.setDot(offs); + c.setMagicCaretPosition(t.modelToView(offs).getLocation()); + } + } + catch (BadLocationException ble) + { + // Do nothing here. + } + } + } + /** * Creates a beep on the PC speaker. * @@ -692,6 +1349,7 @@ public class DefaultEditorKit extends EditorKit // to handle this. private static Action[] defaultActions = new Action[] { + // These classes are public because they are so in the RI. new BeepAction(), new CopyAction(), new CutAction(), @@ -700,404 +1358,38 @@ public class DefaultEditorKit extends EditorKit new InsertContentAction(), new InsertTabAction(), new PasteAction(), - new TextAction(beginLineAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - int offs = Utilities.getRowStart(t, t.getCaretPosition()); - - if (offs > -1) - { - Caret c = t.getCaret(); - c.setDot(offs); - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - } - catch (BadLocationException ble) - { - // Do nothing here. - } - } - }, - new TextAction(endLineAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - int offs = Utilities.getRowEnd(t, t.getCaretPosition()); - - if (offs > -1) - { - Caret c = t.getCaret(); - c.setDot(offs); - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - } - catch (BadLocationException ble) - { - // Nothing to do here - } - } - }, - new TextAction(deleteNextCharAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - if (t != null) - { - try - { - int pos = t.getSelectionStart(); - int len = t.getSelectionEnd() - pos; - - if (len > 0) - t.getDocument().remove(pos, len); - else if (pos < t.getDocument().getLength()) - t.getDocument().remove(pos, 1); - - Caret c = t.getCaret(); - c.setDot(pos); - c.setMagicCaretPosition(t.modelToView(pos).getLocation()); - } - 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.getSelectionStart(); - int len = t.getSelectionEnd() - pos; - - if (len > 0) - t.getDocument().remove(pos, len); - else if (pos > 0) - { - pos--; - t.getDocument().remove(pos, 1); - Caret c = t.getCaret(); - c.setDot(pos); - c.setMagicCaretPosition(t.modelToView(pos).getLocation()); - } - } - 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) - { - int offs = t.getCaretPosition() - 1; - if (offs >= 0) - { - Caret c = t.getCaret(); - c.setDot(offs); - - try - { - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - catch (BadLocationException ble) - { - // Should not happen. - } - } - } - } - }, - new TextAction(forwardAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - if (t != null) - { - int offs = t.getCaretPosition() + 1; - if (offs <= t.getDocument().getLength()) - { - Caret c = t.getCaret(); - c.setDot(offs); - - try - { - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - catch (BadLocationException ble) - { - // Should not happen. - } - } - } - - } - }, - new TextAction(upAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - if (t != null) - { - Caret c = t.getCaret(); - // The magic caret position may be null when the caret - // has not moved yet. - Point mcp = c.getMagicCaretPosition(); - int x = (mcp != null) ? mcp.x : 0; - int pos = Utilities.getPositionAbove(t, t.getCaretPosition(), x); - - if (pos > -1) - t.setCaretPosition(pos); - } - } - catch(BadLocationException ble) - { - // FIXME: Swallowing allowed? - } - } - }, - new TextAction(downAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - if (t != null) - { - Caret c = t.getCaret(); - // The magic caret position may be null when the caret - // has not moved yet. - Point mcp = c.getMagicCaretPosition(); - int x = (mcp != null) ? mcp.x : 0; - int pos = Utilities.getPositionBelow(t, t.getCaretPosition(), x); - - if (pos > -1) - t.setCaretPosition(pos); - } - } - catch(BadLocationException ble) - { - // FIXME: Swallowing allowed? - } - } - }, - new TextAction(selectionBackwardAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - if (t != null) - { - int offs = t.getCaretPosition() - 1; - - if(offs >= 0) - { - Caret c = t.getCaret(); - c.moveDot(offs); - try - { - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - catch(BadLocationException ble) - { - // Can't happen. - } - } - } - } - }, - new TextAction(selectionForwardAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - if (t != null) - { - int offs = t.getCaretPosition() + 1; - - if(offs <= t.getDocument().getLength()) - { - Caret c = t.getCaret(); - c.moveDot(offs); - try - { - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - catch(BadLocationException ble) - { - // Can't happen. - } - } - } - } - }, - new TextAction(selectionUpAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - if (t != null) - { - Caret c = t.getCaret(); - // The magic caret position may be null when the caret - // has not moved yet. - Point mcp = c.getMagicCaretPosition(); - int x = (mcp != null) ? mcp.x : 0; - int pos = Utilities.getPositionAbove(t, t.getCaretPosition(), x); - - if (pos > -1) - t.moveCaretPosition(pos); - } - } - catch(BadLocationException ble) - { - // FIXME: Swallowing allowed? - } - } - }, - new TextAction(selectionDownAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - if (t != null) - { - Caret c = t.getCaret(); - // The magic caret position may be null when the caret - // has not moved yet. - Point mcp = c.getMagicCaretPosition(); - int x = (mcp != null) ? mcp.x : 0; - int pos = Utilities.getPositionBelow(t, t.getCaretPosition(), x); - - if (pos > -1) - t.moveCaretPosition(pos); - } - } - catch(BadLocationException ble) - { - // FIXME: Swallowing allowed? - } - } - }, - new TextAction(selectionBeginLineAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - - try - { - // TODO: There is a more efficent solution, but - // viewToModel doesn't work properly. - Point p = t.modelToView(t.getCaret().getDot()).getLocation(); - - int cur = t.getCaretPosition(); - int y = p.y; - - while (y == p.y && cur > 0) - y = t.modelToView(--cur).getLocation().y; - if (cur != 0) - cur++; - - Caret c = t.getCaret(); - c.moveDot(cur); - c.setMagicCaretPosition(t.modelToView(cur).getLocation()); - } - catch (BadLocationException ble) - { - // Do nothing here. - } - } - }, - new TextAction(selectionEndLineAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - try - { - Point p = t.modelToView(t.getCaret().getDot()).getLocation(); - int cur = t.getCaretPosition(); - int y = p.y; - int length = t.getDocument().getLength(); - while (y == p.y && cur < length) - y = t.modelToView(++cur).getLocation().y; - if (cur != length) - cur--; - - Caret c = t.getCaret(); - c.moveDot(cur); - c.setMagicCaretPosition(t.modelToView(cur).getLocation()); - } - catch (BadLocationException ble) - { - // Nothing to do here - } - } - }, - new TextAction(selectionEndAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - int offs = t.getDocument().getLength(); - Caret c = t.getCaret(); - c.moveDot(offs); - try - { - c.setMagicCaretPosition(t.modelToView(offs).getLocation()); - } - catch(BadLocationException ble) - { - // Can't happen. - } - } - }, - new TextAction(selectionBeginAction) - { - public void actionPerformed(ActionEvent event) - { - JTextComponent t = getTextComponent(event); - Caret c = t.getCaret(); - c.moveDot(0); - try - { - c.setMagicCaretPosition(t.modelToView(0).getLocation()); - } - catch(BadLocationException ble) - { - // Can't happen. - } - } - } + + // These are (package-)private inner classes. + new DeleteNextCharAction(), + new DeletePrevCharAction(), + + new BeginLineAction(), + new SelectionBeginLineAction(), + + new EndLineAction(), + new SelectionEndLineAction(), + + new BackwardAction(), + new SelectionBackwardAction(), + + new ForwardAction(), + new SelectionForwardAction(), + + new UpAction(), + new SelectionUpAction(), + + new DownAction(), + new SelectionDownAction(), + + new NextWordAction(), + new SelectionNextWordAction(), + + new PreviousWordAction(), + new SelectionPreviousWordAction(), + + new SelectionBeginAction(), + new SelectionEndAction(), + new SelectAllAction(), }; /** diff --git a/libjava/classpath/javax/swing/text/DefaultHighlighter.java b/libjava/classpath/javax/swing/text/DefaultHighlighter.java index 33b5fca..59f7731 100644 --- a/libjava/classpath/javax/swing/text/DefaultHighlighter.java +++ b/libjava/classpath/javax/swing/text/DefaultHighlighter.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.text; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Graphics; import java.awt.Insets; @@ -45,6 +47,7 @@ import java.awt.Rectangle; import java.awt.Shape; import java.util.ArrayList; +import javax.swing.SwingUtilities; import javax.swing.plaf.TextUI; public class DefaultHighlighter extends LayeredHighlighter @@ -71,60 +74,102 @@ public class DefaultHighlighter extends LayeredHighlighter } public void paint(Graphics g, int p0, int p1, Shape bounds, - JTextComponent c) + JTextComponent t) { - 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 (p0 == p1) + return; - if (r0 == null || r1 == null) - return; + Rectangle rect = bounds.getBounds(); if (color == null) - g.setColor(c.getSelectionColor()); + g.setColor(t.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; - r0.width = rect.width; + g.setColor(color); + + TextUI ui = t.getUI(); - while (r0.y < r1.y) - { - paintHighlight(g, r0); - r0.y += r0.height; - } - - // Last line, from beginning-of-line to p1. - // The "-1" is neccessary else we would paint one pixel column more - // than in the case where the selection is only on one line. - r0.width = r1.x + r1.width - 1; - paintHighlight(g, r0); + try + { + + Rectangle l0 = ui.modelToView(t, p0, null); + Rectangle l1 = ui.modelToView(t, p1, null); + + // Note: The computed locations may lie outside of the allocation + // area if the text is scrolled. + + if (l0.y == l1.y) + { + SwingUtilities.computeUnion(l0.x, l0.y, l0.width, l0.height, l1); + + // Paint only inside the allocation area. + SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height, l1); + + paintHighlight(g, l1); + } + else + { + // 1. The line of p0 is painted from the position of p0 + // to the right border. + // 2. All lines between the ones where p0 and p1 lie on + // are completely highlighted. The allocation area is used to find + // out the bounds. + // 3. The final line is painted from the left border to the + // position of p1. + + // Highlight first line until the end. + // If rect.x is non-zero the calculation will properly adjust the + // area to be painted. + l0.x -= rect.x; + l0.width = rect.width - l0.x - rect.x; + + paintHighlight(g, l0); + + int posBelow = Utilities.getPositionBelow(t, p0, l0.x); + int p1RowStart = Utilities.getRowStart(t, p1); + if (posBelow != -1 + && posBelow != p0 + && Utilities.getRowStart(t, posBelow) + != p1RowStart) + { + Rectangle grow = ui.modelToView(t, posBelow); + grow.x = rect.x; + grow.width = rect.width; + + // Find further lines which have to be highlighted completely. + int nextPosBelow = posBelow; + while (nextPosBelow != -1 + && Utilities.getRowStart(t, nextPosBelow) != p1RowStart) + { + posBelow = nextPosBelow; + nextPosBelow = Utilities.getPositionBelow(t, posBelow, l0.x); + + if (nextPosBelow == posBelow) + break; + } + // Now posBelow is an offset on the last line which has to be painted + // completely. (newPosBelow is on the same line as p1) + + // Retrieve the rectangle of posBelow and use its y and height + // value to calculate the final height of the multiple line + // spanning rectangle. + Rectangle end = ui.modelToView(t, posBelow); + grow.height = end.y + end.height - grow.y; + + paintHighlight(g, grow); + } + + // Paint last line from its beginning to the position of p1. + l1.width = l1.x + l1.width - rect.x; + l1.x = rect.x; + paintHighlight(g, l1); + } + } + catch (BadLocationException ex) + { + AssertionError err = new AssertionError("Unexpected bad location exception"); + err.initCause(ex); + throw err; + } } public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds, @@ -330,6 +375,7 @@ public class DefaultHighlighter extends LayeredHighlighter public void paintLayeredHighlights(Graphics g, int p0, int p1, Shape viewBounds, JTextComponent editor, View view) + throws NotImplementedException { // TODO: Implement this properly. } diff --git a/libjava/classpath/javax/swing/text/FieldView.java b/libjava/classpath/javax/swing/text/FieldView.java index 2496418..0c2f0fe 100644 --- a/libjava/classpath/javax/swing/text/FieldView.java +++ b/libjava/classpath/javax/swing/text/FieldView.java @@ -1,5 +1,5 @@ /* FieldView.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,20 +39,86 @@ exception statement from your version. */ package javax.swing.text; import java.awt.Component; -import java.awt.ComponentOrientation; +import java.awt.Container; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Rectangle; import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.BoundedRangeModel; import javax.swing.JTextField; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; public class FieldView extends PlainView { + BoundedRangeModel horizontalVisibility; + + /** Caches the preferred span of the X axis. It is invalidated by + * setting it to -1f. This is done when text in the document + * is inserted, removed or changed. The value is corrected as + * soon as calculateHorizontalSpan() is called. + */ + float cachedSpan = -1f; + public FieldView(Element elem) { super(elem); + + } + + /** Checks whether the given container is a JTextField. If so + * it retrieves the textfield's horizontalVisibility instance. + * + * <p>This method should be only called when the view's container + * is valid. Naturally that would be the setParent() method however + * that method is not overridden in the RI and that is why we chose + * paint() instead.</p> + */ + private void checkContainer() + { + Container c = getContainer(); + + if (c instanceof JTextField) + { + horizontalVisibility = ((JTextField) c).getHorizontalVisibility(); + + // Provokes a repaint when the BoundedRangeModel's values change + // (which is what the RI does). + horizontalVisibility.addChangeListener(new ChangeListener(){ + public void stateChanged(ChangeEvent event) { + getContainer().repaint(); + }; + }); + + // It turned out that the span calculated at this point is wrong + // and needs to be recalculated (e.g. a different font setting is + // not taken into account). + calculateHorizontalSpan(); + + // Initializes the BoundedRangeModel properly. + updateVisibility(); + } + + } + + private void updateVisibility() + { + JTextField tf = (JTextField) getContainer(); + Insets insets = tf.getInsets(); + + int width = tf.getWidth() - insets.left - insets.right; + + horizontalVisibility.setMaximum(Math.max((int) ((cachedSpan != -1f) + ? cachedSpan + : calculateHorizontalSpan()), + width)); + + horizontalVisibility.setExtent(width - 1); } protected FontMetrics getFontMetrics() @@ -72,41 +138,47 @@ public class FieldView extends PlainView */ protected Shape adjustAllocation(Shape shape) { + // Return null when the original allocation is null (like the RI). + if (shape == null) + return null; + Rectangle rectIn = shape.getBounds(); // vertical adjustment int height = (int) getPreferredSpan(Y_AXIS); int y = rectIn.y + (rectIn.height - height) / 2; // horizontal adjustment JTextField textField = (JTextField) getContainer(); - int halign = textField.getHorizontalAlignment(); - int width = (int) getPreferredSpan(X_AXIS); + int width = (int) ((cachedSpan != -1f) ? cachedSpan : calculateHorizontalSpan()); int x; - ComponentOrientation orientation = textField.getComponentOrientation(); - switch (halign) - { - case JTextField.CENTER: - x = rectIn.x + (rectIn.width - width) / 2; - break; - case JTextField.RIGHT: - x = rectIn.x + (rectIn.width - width); - break; - case JTextField.TRAILING: - if (orientation.isLeftToRight()) - x = rectIn.x + (rectIn.width - width); - else - x = rectIn.x; - break; - case JTextField.LEADING: - if (orientation.isLeftToRight()) + if (horizontalVisibility != null && horizontalVisibility.getExtent() < width) + x = rectIn.x - horizontalVisibility.getValue(); + else + switch (textField.getHorizontalAlignment()) + { + case JTextField.CENTER: + x = rectIn.x + (rectIn.width - width) / 2; + break; + case JTextField.RIGHT: + x = rectIn.x + (rectIn.width - width - 1); + break; + case JTextField.TRAILING: + if (textField.getComponentOrientation().isLeftToRight()) + x = rectIn.x + (rectIn.width - width - 1); + else + x = rectIn.x; + break; + case JTextField.LEADING: + if (textField.getComponentOrientation().isLeftToRight()) + x = rectIn.x; + else + x = rectIn.x + (rectIn.width - width - 1); + break; + case JTextField.LEFT: + default: x = rectIn.x; - else - x = rectIn.x + (rectIn.width - width); - break; - case JTextField.LEFT: - default: - x = rectIn.x; - break; - } + break; + } + return new Rectangle(x, y, width, height); } @@ -115,18 +187,31 @@ public class FieldView extends PlainView if (axis != X_AXIS && axis != Y_AXIS) throw new IllegalArgumentException(); - FontMetrics fm = getFontMetrics(); if (axis == Y_AXIS) return super.getPreferredSpan(axis); - String text; + if (cachedSpan != -1f) + return cachedSpan; + + return calculateHorizontalSpan(); + } + + /** Calculates and sets the horizontal span and stores the value + * in cachedSpan. + */ + private float calculateHorizontalSpan() + { + Segment s = getLineBuffer(); Element elem = getElement(); try { - text = elem.getDocument().getText(elem.getStartOffset(), - elem.getEndOffset()); + elem.getDocument().getText(elem.getStartOffset(), + elem.getEndOffset() - 1, + s); + + return cachedSpan = Utilities.getTabbedTextWidth(s, getFontMetrics(), 0, this, s.offset); } catch (BadLocationException e) { @@ -135,8 +220,6 @@ public class FieldView extends PlainView ae.initCause(e); throw ae; } - - return fm.stringWidth(text); } public int getResizeWeight(int axis) @@ -153,19 +236,39 @@ public class FieldView extends PlainView public void paint(Graphics g, Shape s) { + if (horizontalVisibility == null) + checkContainer(); + Shape newAlloc = adjustAllocation(s); + + // Set a clip to prevent drawing outside of the allocation area. + // TODO: Is there a better way to achieve this? + Shape clip = g.getClip(); + g.setClip(s); super.paint(g, newAlloc); + g.setClip(clip); } public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) { + cachedSpan = -1f; + + if (horizontalVisibility != null) + updateVisibility(); + Shape newAlloc = adjustAllocation(shape); + super.insertUpdate(ev, newAlloc, vf); getContainer().repaint(); } public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) { + cachedSpan = -1f; + + if (horizontalVisibility != null) + updateVisibility(); + Shape newAlloc = adjustAllocation(shape); super.removeUpdate(ev, newAlloc, vf); getContainer().repaint(); @@ -173,14 +276,19 @@ public class FieldView extends PlainView public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) { + cachedSpan = -1f; + + if (horizontalVisibility != null) + updateVisibility(); + Shape newAlloc = adjustAllocation(shape); - super.removeUpdate(ev, newAlloc, vf); + super.changedUpdate(ev, newAlloc, vf); getContainer().repaint(); } public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) { - return super.viewToModel(fx, fy, a, bias); + return super.viewToModel(fx, fy, adjustAllocation(a), bias); } } diff --git a/libjava/classpath/javax/swing/text/FlowView.java b/libjava/classpath/javax/swing/text/FlowView.java index 8be8f41..8ca55d8 100644 --- a/libjava/classpath/javax/swing/text/FlowView.java +++ b/libjava/classpath/javax/swing/text/FlowView.java @@ -433,7 +433,7 @@ public abstract class FlowView extends BoxView /** * Loads the children of this view. The <code>FlowView</code> does not * directly load its children. Instead it creates a logical view - * (@{link #layoutPool}) which is filled by the logical child views. + * ({@link #layoutPool}) which is filled by the logical child views. * The real children are created at layout time and each represent one * row. * diff --git a/libjava/classpath/javax/swing/text/GapContent.java b/libjava/classpath/javax/swing/text/GapContent.java index 28d1d6e..219accb 100644 --- a/libjava/classpath/javax/swing/text/GapContent.java +++ b/libjava/classpath/javax/swing/text/GapContent.java @@ -289,6 +289,7 @@ public class GapContent */ public GapContent(int size) { + size = Math.max(size, 2); buffer = (char[]) allocateArray(size); gapStart = 1; gapEnd = size; @@ -351,7 +352,7 @@ public class GapContent throw new BadLocationException("The where argument cannot be smaller" + " than the zero", where); - if (where >= length) + if (where > length) throw new BadLocationException("The where argument cannot be greater" + " than the content length", where); @@ -375,14 +376,11 @@ public class GapContent { // check arguments int length = length(); - - if (where >= length) - throw new BadLocationException("the where argument cannot be greater" - + " than the content length", where); - if ((where + nitems) > length) + + if ((where + nitems) >= length) throw new BadLocationException("where + nitems cannot be greater" + " than the content length", where + nitems); - + String removedText = getString(where, nitems); replace(where, nitems, null, 0); @@ -439,6 +437,8 @@ public class GapContent { // check arguments int length = length(); + if (where < 0) + throw new BadLocationException("the where argument may not be below zero", where); if (where >= length) throw new BadLocationException("the where argument cannot be greater" + " than the content length", where); @@ -642,6 +642,10 @@ public class GapContent if (addItems != null) { System.arraycopy(addItems, 0, buffer, gapStart, addSize); + + + resetMarksAtZero(); + gapStart += addSize; } } diff --git a/libjava/classpath/javax/swing/text/InternationalFormatter.java b/libjava/classpath/javax/swing/text/InternationalFormatter.java index ba3cffa..8db435c 100644 --- a/libjava/classpath/javax/swing/text/InternationalFormatter.java +++ b/libjava/classpath/javax/swing/text/InternationalFormatter.java @@ -350,7 +350,7 @@ public class InternationalFormatter * There is no such method in the whole API! So we just call * super.getActions here. */ - public Action[] getActions() + protected Action[] getActions() { return super.getActions(); } diff --git a/libjava/classpath/javax/swing/text/JTextComponent.java b/libjava/classpath/javax/swing/text/JTextComponent.java index 6b8348c..1103de9 100644 --- a/libjava/classpath/javax/swing/text/JTextComponent.java +++ b/libjava/classpath/javax/swing/text/JTextComponent.java @@ -1138,6 +1138,7 @@ public abstract class JTextComponent extends JComponent setFocusable(true); setEditable(true); enableEvents(AWTEvent.KEY_EVENT_MASK); + setOpaque(true); updateUI(); } @@ -1190,6 +1191,7 @@ public abstract class JTextComponent extends JComponent catch (BadLocationException e) { // This can never happen. + throw (InternalError) new InternalError().initCause(e); } } diff --git a/libjava/classpath/javax/swing/text/PlainView.java b/libjava/classpath/javax/swing/text/PlainView.java index 4bb3a8e..18818c0 100644 --- a/libjava/classpath/javax/swing/text/PlainView.java +++ b/libjava/classpath/javax/swing/text/PlainView.java @@ -59,6 +59,18 @@ public class PlainView extends View implements TabExpander * The color that is used to draw disabled text fields. */ Color disabledColor; + + /** + * While painting this is the textcomponent's current start index + * of the selection. + */ + int selectionStart; + + /** + * While painting this is the textcomponent's current end index + * of the selection. + */ + int selectionEnd; Font font; @@ -150,12 +162,47 @@ public class PlainView extends View implements TabExpander { try { - metrics = g.getFontMetrics(); - // FIXME: Selected text are not drawn yet. Element line = getElement().getElement(lineIndex); - drawUnselectedText(g, x, y, line.getStartOffset(), - line.getEndOffset() - 1); - //drawSelectedText(g, , , , ); + int startOffset = line.getStartOffset(); + int endOffset = line.getEndOffset() - 1; + + if (selectionStart <= startOffset) + // Selection starts before the line ... + if (selectionEnd <= startOffset) + { + // end ends before the line: Draw completely unselected text. + drawUnselectedText(g, x, y, startOffset, endOffset); + } + else if (selectionEnd <= endOffset) + { + // and ends within the line: First part is selected, + // second is not. + x = drawSelectedText(g, x, y, startOffset, selectionEnd); + drawUnselectedText(g, x, y, selectionEnd, endOffset); + } + else + // and ends behind the line: Draw completely selected text. + drawSelectedText(g, x, y, startOffset, endOffset); + else if (selectionStart < endOffset) + // Selection starts within the line .. + if (selectionEnd < endOffset) + { + // and ends within it: First part unselected, second part + // selected, third part unselected. + x = drawUnselectedText(g, x, y, startOffset, selectionStart); + x = drawSelectedText(g, x, y, selectionStart, selectionEnd); + drawUnselectedText(g, x, y, selectionEnd, endOffset); + } + else + { + // and ends behind the line: First part unselected, second + // part selected. + x = drawUnselectedText(g, x, y, startOffset, selectionStart); + drawSelectedText(g, x, y, selectionStart, endOffset); + } + else + // Selection is behind this line: Draw completely unselected text. + drawUnselectedText(g, x, y, startOffset, endOffset); } catch (BadLocationException e) { @@ -171,7 +218,7 @@ public class PlainView extends View implements TabExpander g.setColor(selectedColor); Segment segment = getLineBuffer(); getDocument().getText(p0, p1 - p0, segment); - return Utilities.drawTabbedText(segment, x, y, g, this, 0); + return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset); } /** @@ -212,6 +259,8 @@ public class PlainView extends View implements TabExpander selectedColor = textComponent.getSelectedTextColor(); unselectedColor = textComponent.getForeground(); disabledColor = textComponent.getDisabledTextColor(); + selectionStart = textComponent.getSelectionStart(); + selectionEnd = textComponent.getSelectionEnd(); Rectangle rect = s.getBounds(); @@ -219,11 +268,13 @@ public class PlainView extends View implements TabExpander Document document = textComponent.getDocument(); Element root = document.getDefaultRootElement(); int y = rect.y + metrics.getAscent(); + int height = metrics.getHeight(); - for (int i = 0; i < root.getElementCount(); i++) + int count = root.getElementCount(); + for (int i = 0; i < count; i++) { drawLine(i, g, rect.x, y); - y += metrics.getHeight(); + y += height; } } @@ -274,7 +325,7 @@ public class PlainView extends View implements TabExpander { Element child = el.getElement(i); int start = child.getStartOffset(); - int end = child.getEndOffset(); + int end = child.getEndOffset() - 1; try { el.getDocument().getText(start, end - start, seg); @@ -386,6 +437,11 @@ public class PlainView extends View implements TabExpander */ protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) { + // Return early and do no updates if the allocation area is null + // (like the RI). + if (a == null) + return; + float oldMaxLineLength = maxLineLength; Rectangle alloc = a.getBounds(); Element el = getElement(); @@ -467,7 +523,7 @@ public class PlainView extends View implements TabExpander { Element child = newElements[i]; int start = child.getStartOffset(); - int end = child.getEndOffset(); + int end = child.getEndOffset() - 1; try { el.getDocument().getText(start, end - start, seg); @@ -586,7 +642,7 @@ public class PlainView extends View implements TabExpander * @returna {@link Segment} object, that can be used to fetch text from * the document */ - protected Segment getLineBuffer() + protected final Segment getLineBuffer() { if (lineBuffer == null) lineBuffer = new Segment(); diff --git a/libjava/classpath/javax/swing/text/Position.java b/libjava/classpath/javax/swing/text/Position.java index a9d3d09..bb1449e 100644 --- a/libjava/classpath/javax/swing/text/Position.java +++ b/libjava/classpath/javax/swing/text/Position.java @@ -40,7 +40,7 @@ package javax.swing.text; public interface Position { - static class Bias + static final class Bias { public static final Bias Backward = new Bias("backward"); public static final Bias Forward = new Bias("forward"); diff --git a/libjava/classpath/javax/swing/text/Segment.java b/libjava/classpath/javax/swing/text/Segment.java index 875d996..d2364e0 100644 --- a/libjava/classpath/javax/swing/text/Segment.java +++ b/libjava/classpath/javax/swing/text/Segment.java @@ -245,7 +245,8 @@ public class Segment implements Cloneable, CharacterIterator || position > getEndIndex()) throw new IllegalArgumentException("position: " + position + ", beginIndex: " + getBeginIndex() - + ", endIndex: " + getEndIndex()); + + ", endIndex: " + getEndIndex() + + ", text: " + toString()); current = position; @@ -264,7 +265,7 @@ public class Segment implements Cloneable, CharacterIterator */ public String toString() { - return new String(array, offset, count); + return (array != null) ? new String(array, offset, count) : ""; } /** diff --git a/libjava/classpath/javax/swing/text/StyleContext.java b/libjava/classpath/javax/swing/text/StyleContext.java index e2643a2..8ef3440 100644 --- a/libjava/classpath/javax/swing/text/StyleContext.java +++ b/libjava/classpath/javax/swing/text/StyleContext.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.text; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; @@ -711,35 +713,37 @@ public class StyleContext // have left incomplete; I'm not sure I understand the intent properly. public static Object getStaticAttribute(Object key) + throws NotImplementedException { throw new InternalError("not implemented"); } public static Object getStaticAttributeKey(Object key) + throws NotImplementedException { throw new InternalError("not implemented"); } public static void readAttributeSet(ObjectInputStream in, MutableAttributeSet a) - throws ClassNotFoundException, IOException + throws ClassNotFoundException, IOException, NotImplementedException { throw new InternalError("not implemented"); } public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a) - throws IOException + throws IOException, NotImplementedException { throw new InternalError("not implemented"); } public void readAttributes(ObjectInputStream in, MutableAttributeSet a) - throws ClassNotFoundException, IOException + throws ClassNotFoundException, IOException, NotImplementedException { throw new InternalError("not implemented"); } public void writeAttributes(ObjectOutputStream out, AttributeSet a) - throws IOException + throws IOException, NotImplementedException { throw new InternalError("not implemented"); } diff --git a/libjava/classpath/javax/swing/text/Utilities.java b/libjava/classpath/javax/swing/text/Utilities.java index d109a4a..f154e55 100644 --- a/libjava/classpath/javax/swing/text/Utilities.java +++ b/libjava/classpath/javax/swing/text/Utilities.java @@ -1,5 +1,5 @@ /* Utilities.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,6 +48,7 @@ import java.text.BreakIterator; * inside this package. * * @author Roman Kennke (roman@ontographics.com) + * @author Robert Schuster (robertschuster@fsfe.org) */ public class Utilities { @@ -99,8 +100,10 @@ public class Utilities int pixelWidth = 0; int pos = s.offset; int len = 0; + + int end = s.offset + s.count; - for (int offset = s.offset; offset < (s.offset + s.count); ++offset) + for (int offset = s.offset; offset < end; ++offset) { char c = buffer[offset]; if (c == '\t' || c == '\n') @@ -140,7 +143,7 @@ public class Utilities if (len > 0) g.drawChars(buffer, pos, len, pixelX, pixelY + ascent); - return pixelX; + return pixelX + pixelWidth; } /** @@ -236,35 +239,39 @@ public class Utilities // At the end of the for loop, this holds the requested model location int pos; int currentX = x0; - + int width = 0; + for (pos = 0; pos < s.count; pos++) { char nextChar = s.array[s.offset+pos]; if (nextChar == 0) - { - if (! round) - pos--; break; - } + if (nextChar != '\t') - currentX += fm.charWidth(nextChar); + width = fm.charWidth(nextChar); else { if (te == null) - currentX += fm.charWidth(' '); + width = fm.charWidth(' '); else - currentX = (int) te.nextTabStop(currentX, pos); + width = ((int) te.nextTabStop(currentX, pos)) - currentX; } - if (currentX > x) + if (round) { - if (! round) - pos--; - break; + if (currentX + (width>>1) > x) + break; + } + else + { + if (currentX + width > x) + break; } + + currentX += width; } - + return pos + p0; } @@ -315,21 +322,31 @@ public class Utilities String text = c.getText(); BreakIterator wb = BreakIterator.getWordInstance(); wb.setText(text); + int last = wb.following(offs); int current = wb.next(); + int cp; + while (current != BreakIterator.DONE) { for (int i = last; i < current; i++) { - // FIXME: Should use isLetter(int) and text.codePointAt(int) - // instead, but isLetter(int) isn't implemented yet - if (Character.isLetter(text.charAt(i))) + cp = text.codePointAt(i); + + // Return the last found bound if there is a letter at the current + // location or is not whitespace (meaning it is a number or + // punctuation). The first case means that 'last' denotes the + // beginning of a word while the second case means it is the start + // of some else. + if (Character.isLetter(cp) + || !Character.isWhitespace(cp)) return last; } last = current; current = wb.next(); } - return BreakIterator.DONE; + + throw new BadLocationException("no more word", offs); } /** @@ -358,9 +375,7 @@ public class Utilities { for (int i = last; i < offs; i++) { - // FIXME: Should use isLetter(int) and text.codePointAt(int) - // instead, but isLetter(int) isn't implemented yet - if (Character.isLetter(text.charAt(i))) + if (Character.isLetter(text.codePointAt(i))) return last; } last = current; @@ -510,24 +525,28 @@ public class Utilities int x0, int x, TabExpander e, int startOffset) { - int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset); + int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset, false); BreakIterator breaker = BreakIterator.getWordInstance(); breaker.setText(s); - // If mark is equal to the end of the string, just use that position - if (mark == s.count + s.offset) + // If startOffset and s.offset differ then we need to use + // that difference two convert the offset between the two metrics. + int shift = startOffset - s.offset; + + // If mark is equal to the end of the string, just use that position. + if (mark >= shift + s.count) return mark; // Try to find a word boundary previous to the mark at which we - // can break the text - int preceding = breaker.preceding(mark + 1); + // can break the text. + int preceding = breaker.preceding(mark + 1 - shift); if (preceding != 0) - return preceding; - else - // If preceding is 0 we couldn't find a suitable word-boundary so - // just break it on the character boundary - return mark; + return preceding + shift; + + // If preceding is 0 we couldn't find a suitable word-boundary so + // just break it on the character boundary + return mark; } /** @@ -619,8 +638,22 @@ public class Utilities if(offs == -1) return -1; - // Effectively calculates the y value of the previous line. - Point pt = c.modelToView(offs+1).getLocation(); + Point pt = null; + + // Note: Some views represent the position after the last + // typed character others do not. Converting offset 3 in "a\nb" + // in a PlainView will return a valid rectangle while in a + // WrappedPlainView this will throw a BadLocationException. + // This behavior has been observed in the RI. + try + { + // Effectively calculates the y value of the next line. + pt = c.modelToView(offs+1).getLocation(); + } + catch(BadLocationException ble) + { + return offset; + } pt.x = x; diff --git a/libjava/classpath/javax/swing/text/View.java b/libjava/classpath/javax/swing/text/View.java index 2feaf29..d8ad5f5 100644 --- a/libjava/classpath/javax/swing/text/View.java +++ b/libjava/classpath/javax/swing/text/View.java @@ -1,5 +1,5 @@ /* View.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -733,23 +733,38 @@ public abstract class View implements SwingConstants throws BadLocationException { int ret = pos; + Rectangle r; + View parent; + switch (d) { - case WEST: - ret = pos - 1; - break; case EAST: - ret = pos + 1; + // TODO: take component orientation into account? + // Note: If pos is below zero the implementation will return + // pos + 1 regardless of whether that value is a correct offset + // in the document model. However this is what the RI does. + ret = Math.min(pos + 1, getEndOffset()); + break; + case WEST: + // TODO: take component orientation into account? + ret = Math.max(pos - 1, getStartOffset()); break; case NORTH: - // TODO: Implement this + // Try to find a suitable offset by examining the area above. + parent = getParent(); + r = parent.modelToView(pos, a, b).getBounds(); + ret = parent.viewToModel(r.x, r.y - 1, a, biasRet); break; case SOUTH: - // TODO: Implement this + // Try to find a suitable offset by examining the area below. + parent = getParent(); + r = parent.modelToView(pos, a, b).getBounds(); + ret = parent.viewToModel(r.x + r.width, r.y + r.height, a, biasRet); break; default: throw new IllegalArgumentException("Illegal value for d"); } + return ret; } } diff --git a/libjava/classpath/javax/swing/text/WrappedPlainView.java b/libjava/classpath/javax/swing/text/WrappedPlainView.java index e2790a0..a6c369a 100644 --- a/libjava/classpath/javax/swing/text/WrappedPlainView.java +++ b/libjava/classpath/javax/swing/text/WrappedPlainView.java @@ -1,5 +1,5 @@ /* WrappedPlainView.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,7 +45,6 @@ import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Shape; -import javax.swing.SwingConstants; import javax.swing.event.DocumentEvent; import javax.swing.text.Position.Bias; @@ -64,8 +63,11 @@ public class WrappedPlainView extends BoxView implements TabExpander /** The color for disabled components **/ Color disabledColor; - /** Stores the font metrics **/ - protected FontMetrics metrics; + /** + * Stores the font metrics. This is package private to avoid synthetic + * accessor method. + */ + FontMetrics metrics; /** Whether or not to wrap on word boundaries **/ boolean wordWrap; @@ -79,6 +81,9 @@ public class WrappedPlainView extends BoxView implements TabExpander /** The end of the selected text **/ int selectionEnd; + /** The height of the line (used while painting) **/ + int lineHeight; + /** * The instance returned by {@link #getLineBuffer()}. */ @@ -270,8 +275,20 @@ public class WrappedPlainView extends BoxView implements TabExpander protected int calculateBreakPosition(int p0, int p1) { Container c = getContainer(); - Rectangle alloc = new Rectangle(0, 0, getWidth(), getHeight()); + + int li = getLeftInset(); + int ti = getTopInset(); + + Rectangle alloc = new Rectangle(li, ti, + getWidth()-getRightInset()-li, + getHeight()-getBottomInset()-ti); + + // Mimic a behavior observed in the RI. + if (alloc.isEmpty()) + return 0; + updateMetrics(); + try { getDocument().getText(p0, p1 - p0, getLineBuffer()); @@ -279,18 +296,16 @@ public class WrappedPlainView extends BoxView implements TabExpander catch (BadLocationException ble) { // this shouldn't happen + throw new InternalError("Invalid offsets p0: " + p0 + " - p1: " + p1); } - // FIXME: Should we account for the insets of the container? + if (wordWrap) - return p0 - + Utilities.getBreakLocation(lineBuffer, metrics, alloc.x, - alloc.x + alloc.width, this, 0); + return Utilities.getBreakLocation(lineBuffer, metrics, alloc.x, + alloc.x + alloc.width, this, p0); else - { - return p0 - + Utilities.getTabbedTextOffset(lineBuffer, metrics, alloc.x, - alloc.x + alloc.width, this, 0); - } + return p0 + Utilities.getTabbedTextOffset(lineBuffer, metrics, alloc.x, + alloc.x + alloc.width, this, 0, + true); } void updateMetrics() @@ -336,8 +351,8 @@ public class WrappedPlainView extends BoxView implements TabExpander public void insertUpdate (DocumentEvent e, Shape a, ViewFactory f) { super.insertUpdate(e, a, viewFactory); - // FIXME: could improve performance by repainting only the necessary area - getContainer().repaint(); + + // No repaint needed, as this is done by the WrappedLine instances. } /** @@ -347,8 +362,8 @@ public class WrappedPlainView extends BoxView implements TabExpander public void removeUpdate (DocumentEvent e, Shape a, ViewFactory f) { super.removeUpdate(e, a, viewFactory); - // FIXME: could improve performance by repainting only the necessary area - getContainer().repaint(); + + // No repaint needed, as this is done by the WrappedLine instances. } /** @@ -359,8 +374,8 @@ public class WrappedPlainView extends BoxView implements TabExpander public void changedUpdate (DocumentEvent e, Shape a, ViewFactory f) { super.changedUpdate(e, a, viewFactory); - // FIXME: could improve performance by repainting only the necessary area - getContainer().repaint(); + + // No repaint needed, as this is done by the WrappedLine instances. } class WrappedLineCreator implements ViewFactory @@ -383,9 +398,19 @@ public class WrappedPlainView extends BoxView implements TabExpander public void paint(Graphics g, Shape a) { JTextComponent comp = (JTextComponent)getContainer(); + // Ensure metrics are up-to-date. + updateMetrics(); + selectionStart = comp.getSelectionStart(); selectionEnd = comp.getSelectionEnd(); - updateMetrics(); + + selectedColor = comp.getSelectedTextColor(); + unselectedColor = comp.getForeground(); + disabledColor = comp.getDisabledTextColor(); + selectedColor = comp.getSelectedTextColor(); + lineHeight = metrics.getHeight(); + g.setFont(comp.getFont()); + super.paint(g, a); } @@ -404,7 +429,7 @@ public class WrappedPlainView extends BoxView implements TabExpander class WrappedLine extends View { /** Used to cache the number of lines for this View **/ - int numLines; + int numLines = 1; public WrappedLine(Element elem) { @@ -418,48 +443,47 @@ public class WrappedPlainView extends BoxView implements TabExpander */ public void paint(Graphics g, Shape s) { - // Ensure metrics are up-to-date. - updateMetrics(); - JTextComponent textComponent = (JTextComponent) getContainer(); - - g.setFont(textComponent.getFont()); - selectedColor = textComponent.getSelectedTextColor(); - unselectedColor = textComponent.getForeground(); - disabledColor = textComponent.getDisabledTextColor(); - - // FIXME: this is a hack, for some reason textComponent.getSelectedColor - // was returning black, which is not visible against a black background - selectedColor = Color.WHITE; - Rectangle rect = s.getBounds(); - int lineHeight = metrics.getHeight(); int end = getEndOffset(); int currStart = getStartOffset(); - int currEnd; + int currEnd; + int count = 0; while (currStart < end) { currEnd = calculateBreakPosition(currStart, end); - drawLine(currStart, currEnd, g, rect.x, rect.y); + + drawLine(currStart, currEnd, g, rect.x, rect.y + metrics.getAscent()); + rect.y += lineHeight; if (currEnd == currStart) currStart ++; else - currStart = currEnd; + currStart = currEnd; + + count++; + } + + if (count != numLines) + { + numLines = count; + preferenceChanged(this, false, true); + } + } /** - * Determines the number of logical lines that the Element - * needs to be displayed - * @return the number of lines needed to display the Element + * Calculates the number of logical lines that the Element + * needs to be displayed and updates the variable numLines + * accordingly. */ - int determineNumLines() + void determineNumLines() { numLines = 0; int end = getEndOffset(); if (end == 0) - return 0; + return; int breakPoint; for (int i = getStartOffset(); i < end;) @@ -468,12 +492,17 @@ public class WrappedPlainView extends BoxView implements TabExpander // careful: check that there's no off-by-one problem here // depending on which position calculateBreakPosition returns breakPoint = calculateBreakPosition(i, end); + + if (breakPoint == 0) + return; + + // If breakPoint is equal to the current index no further + // line is needed and we can end the loop. if (breakPoint == i) - i ++; + break; else i = breakPoint; } - return numLines; } /** @@ -489,7 +518,11 @@ public class WrappedPlainView extends BoxView implements TabExpander if (axis == X_AXIS) return getWidth(); else if (axis == Y_AXIS) - return numLines * metrics.getHeight(); + { + if (metrics == null) + updateMetrics(); + return numLines * metrics.getHeight(); + } throw new IllegalArgumentException("Invalid axis for getPreferredSpan: " + axis); @@ -509,9 +542,15 @@ public class WrappedPlainView extends BoxView implements TabExpander public Shape modelToView(int pos, Shape a, Bias b) throws BadLocationException { + Rectangle rect = a.getBounds(); + + // Throwing a BadLocationException is an observed behavior of the RI. + if (rect.isEmpty()) + throw new BadLocationException("Unable to calculate view coordinates " + + "when allocation area is empty.", 5); + Segment s = getLineBuffer(); int lineHeight = metrics.getHeight(); - Rectangle rect = a.getBounds(); // Return a rectangle with width 1 and height equal to the height // of the text @@ -530,7 +569,7 @@ public class WrappedPlainView extends BoxView implements TabExpander // If pos is between currLineStart and currLineEnd then just find // the width of the text from currLineStart to pos and add that // to rect.x - if (pos >= currLineStart && pos < currLineEnd || pos == end - 1) + if (pos >= currLineStart && pos < currLineEnd) { try { @@ -574,68 +613,93 @@ public class WrappedPlainView extends BoxView implements TabExpander Segment s = getLineBuffer(); Rectangle rect = a.getBounds(); int currLineStart = getStartOffset(); + + // Although calling modelToView with the last possible offset will + // cause a BadLocationException in CompositeView it is allowed + // to return that offset in viewToModel. int end = getEndOffset(); + int lineHeight = metrics.getHeight(); if (y < rect.y) return currLineStart; + if (y > rect.y + rect.height) - return end - 1; + return end; + + // Note: rect.x and rect.width do not represent the width of painted + // text but the area where text *may* be painted. This means the width + // is most of the time identical to the component's width. - while (true) + while (currLineStart != end) { int currLineEnd = calculateBreakPosition(currLineStart, end); + // If we're at the right y-position that means we're on the right // logical line and we should look for the character if (y >= rect.y && y < rect.y + lineHeight) { - // Check if the x position is to the left or right of the text - if (x < rect.x) - return currLineStart; - if (x > rect.x + rect.width) - return currLineEnd - 1; - try { - getDocument().getText(currLineStart, end - currLineStart, s); + getDocument().getText(currLineStart, currLineEnd - currLineStart, s); } catch (BadLocationException ble) { // Shouldn't happen } - int mark = Utilities.getTabbedTextOffset(s, metrics, rect.x, - (int) x, - WrappedPlainView.this, - currLineStart); - return currLineStart + mark; + + int offset = Utilities.getTabbedTextOffset(s, metrics, rect.x, + (int) x, + WrappedPlainView.this, + currLineStart); + // If the calculated offset is the end of the line (in the + // document (= start of the next line) return the preceding + // offset instead. This makes sure that clicking right besides + // the last character in a line positions the cursor after the + // last character and not in the beginning of the next line. + return (offset == currLineEnd) ? offset - 1 : offset; } // Increment rect.y so we're checking the next logical line rect.y += lineHeight; // Increment currLineStart to the model position of the start - // of the next logical line - if (currLineEnd == currLineStart) - currLineStart = end; - else - currLineStart = currLineEnd; + // of the next logical line. + currLineStart = currLineEnd; + } + + return end; } /** - * This method is called from insertUpdate and removeUpdate. - * If the number of lines in the document has changed, just repaint + * <p>This method is called from insertUpdate and removeUpdate.</p> + * + * <p>If the number of lines in the document has changed, just repaint * the whole thing (note, could improve performance by not repainting * anything above the changes). If the number of lines hasn't changed, - * just repaint the given Rectangle. + * just repaint the given Rectangle.</p> + * + * <p>Note that the <code>Rectangle</code> argument may be <code>null</code> + * when the allocation area is empty.</code> + * * @param a the Rectangle to repaint if the number of lines hasn't changed */ void updateDamage (Rectangle a) { - int newNumLines = determineNumLines(); - if (numLines != newNumLines) + // If the allocation area is empty we can't do anything useful. + // As determining the number of lines is impossible in that state we + // reset it to an invalid value which can then be recalculated at a + // later point. + if (a == null || a.isEmpty()) { - numLines = newNumLines; - getContainer().repaint(); + numLines = 1; + return; } + + int oldNumLines = numLines; + determineNumLines(); + + if (numLines != oldNumLines) + preferenceChanged(this, false, true); else getContainer().repaint(a.x, a.y, a.width, a.height); } @@ -663,6 +727,15 @@ public class WrappedPlainView extends BoxView implements TabExpander */ public void removeUpdate (DocumentEvent changes, Shape a, ViewFactory f) { + // Note: This method is not called when characters from the + // end of the document are removed. The reason for this + // can be found in the implementation of View.forwardUpdate: + // The document event will denote offsets which do not exist + // any more, getViewIndex() will therefore return -1 and this + // makes View.forwardUpdate() skip this method call. + // However this seems to cause no trouble and as it reduces the + // number of method calls it can stay this way. + updateDamage((Rectangle)a); } } diff --git a/libjava/classpath/javax/swing/text/html/FormView.java b/libjava/classpath/javax/swing/text/html/FormView.java index b85c694..d540210 100644 --- a/libjava/classpath/javax/swing/text/html/FormView.java +++ b/libjava/classpath/javax/swing/text/html/FormView.java @@ -39,8 +39,11 @@ exception statement from your version. */ package javax.swing.text.html; import java.awt.Component; +import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import javax.swing.JButton; import javax.swing.JCheckBox; @@ -83,6 +86,24 @@ public class FormView implements ActionListener { + protected class MouseEventListener + extends MouseAdapter + { + /** + * Creates a new <code>MouseEventListener</code>. + */ + protected MouseEventListener() + { + // Nothing to do here. + } + + public void mouseReleased(MouseEvent ev) + { + String data = getImageData(ev.getPoint()); + imageSubmit(data); + } + } + /** * If the value attribute of an <code><input type="submit">> * tag is not specified, then this string is used. @@ -227,4 +248,28 @@ public class FormView { // FIXME: Implement this. } + + /** + * Determines the image data that should be submitted in response to a + * mouse click on a image. This is either 'x=<p.x>&y=<p.y>' if the name + * attribute of the element is null or '' or + * <name>.x=<p.x>&<name>.y=<p.y>' when the name attribute is not empty. + * + * @param p the coordinates of the mouseclick + */ + String getImageData(Point p) + { + String name = (String) getElement().getAttributes() + .getAttribute(HTML.Attribute.NAME); + String data; + if (name == null || name.equals("")) + { + data = "x=" + p.x + "&y=" + p.y; + } + else + { + data = name + ".x=" + p.x + "&" + name + ".y=" + p.y; + } + return data; + } } diff --git a/libjava/classpath/javax/swing/text/html/HTML.java b/libjava/classpath/javax/swing/text/html/HTML.java index 2b521cd..2c908f6 100644 --- a/libjava/classpath/javax/swing/text/html/HTML.java +++ b/libjava/classpath/javax/swing/text/html/HTML.java @@ -292,7 +292,7 @@ public class HTML /** * The media attribute */ - public static final Attribute MEDIA = new Attribute("media"); + static final Attribute MEDIA = new Attribute("media"); /** * The method attribute @@ -758,7 +758,7 @@ public class HTML /** * The <nobr> tag */ - public static final Tag NOBR = new Tag("nobr"); + static final Tag NOBR = new Tag("nobr"); /** * The <noframes> tag , breaks flow, block tag. diff --git a/libjava/classpath/javax/swing/text/html/HTMLDocument.java b/libjava/classpath/javax/swing/text/html/HTMLDocument.java index 2a96953..fba6cad 100644 --- a/libjava/classpath/javax/swing/text/html/HTMLDocument.java +++ b/libjava/classpath/javax/swing/text/html/HTMLDocument.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.text.html; +import gnu.classpath.NotImplementedException; + import java.io.IOException; import java.net.URL; import java.util.HashMap; @@ -667,6 +669,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("FormAction.start not implemented"); @@ -677,6 +680,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("FormAction.end not implemented"); @@ -690,6 +694,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("HiddenAction.start not implemented"); @@ -700,6 +705,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("HiddenAction.end not implemented"); @@ -713,6 +719,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("IsindexAction.start not implemented"); @@ -723,6 +730,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("IsindexAction.end not implemented"); @@ -759,6 +767,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("PreAction.start not implemented"); @@ -769,6 +778,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("PreAction.end not implemented"); @@ -782,6 +792,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("SpecialAction.start not implemented"); @@ -792,6 +803,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("SpecialAction.end not implemented"); @@ -805,6 +817,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("AreaAction.start not implemented"); @@ -815,6 +828,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("AreaAction.end not implemented"); @@ -828,6 +842,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("BaseAction.start not implemented"); @@ -838,6 +853,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("BaseAction.end not implemented"); @@ -851,6 +867,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("HeadAction.start not implemented: "+t); @@ -862,6 +879,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("HeadAction.end not implemented: "+t); @@ -876,6 +894,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("LinkAction.start not implemented"); @@ -886,6 +905,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("LinkAction.end not implemented"); @@ -899,6 +919,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("MapAction.start not implemented"); @@ -909,6 +930,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("MapAction.end not implemented"); @@ -922,6 +944,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("MetaAction.start not implemented"); @@ -932,6 +955,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("MetaAction.end not implemented"); @@ -945,6 +969,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("StyleAction.start not implemented"); @@ -955,6 +980,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("StyleAction.end not implemented"); @@ -968,6 +994,7 @@ public class HTMLDocument extends DefaultStyledDocument * of tags associated with this Action. */ public void start(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement. print ("TitleAction.start not implemented"); @@ -978,6 +1005,7 @@ public class HTMLDocument extends DefaultStyledDocument * with this Action. */ public void end(HTML.Tag t) + throws NotImplementedException { // FIXME: Implement. print ("TitleAction.end not implemented"); @@ -1253,6 +1281,7 @@ public class HTMLDocument extends DefaultStyledDocument * @since 1.3 */ public void handleEndOfLineString(String eol) + throws NotImplementedException { // FIXME: Implement. print ("HTMLReader.handleEndOfLineString not implemented yet"); @@ -1265,6 +1294,7 @@ public class HTMLDocument extends DefaultStyledDocument * @param data the text to add to the textarea */ protected void textAreaContent(char[] data) + throws NotImplementedException { // FIXME: Implement. print ("HTMLReader.textAreaContent not implemented yet"); @@ -1276,6 +1306,7 @@ public class HTMLDocument extends DefaultStyledDocument * @param data the text */ protected void preContent(char[] data) + throws NotImplementedException { // FIXME: Implement print ("HTMLReader.preContent not implemented yet"); @@ -1447,6 +1478,7 @@ public class HTMLDocument extends DefaultStyledDocument * @param a the attribute set specifying the special content */ protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a) + throws NotImplementedException { // FIXME: Implement print ("HTMLReader.addSpecialElement not implemented yet"); @@ -1550,7 +1582,7 @@ public class HTMLDocument extends DefaultStyledDocument * @throws IllegalStateException - if an HTMLEditorKit.Parser has not been set */ public void setInnerHTML(Element elem, String htmlText) - throws BadLocationException, IOException + throws BadLocationException, IOException, NotImplementedException { if (elem.isLeaf()) throw new IllegalArgumentException("Element is a leaf"); @@ -1574,7 +1606,7 @@ public class HTMLDocument extends DefaultStyledDocument * @throws IllegalStateException - if parser is not set */ public void setOuterHTML(Element elem, String htmlText) - throws BadLocationException, IOException + throws BadLocationException, IOException, NotImplementedException { if (parser == null) throw new IllegalStateException("Parser has not been set"); @@ -1593,7 +1625,7 @@ public class HTMLDocument extends DefaultStyledDocument * @throws IllegalStateException - if parser has not been set */ public void insertBeforeStart(Element elem, String htmlText) - throws BadLocationException, IOException + throws BadLocationException, IOException, NotImplementedException { if (parser == null) throw new IllegalStateException("Parser has not been set"); @@ -1613,7 +1645,7 @@ public class HTMLDocument extends DefaultStyledDocument * @throws IllegalStateException - if parser is not set */ public void insertBeforeEnd(Element elem, String htmlText) - throws BadLocationException, IOException + throws BadLocationException, IOException, NotImplementedException { if (parser == null) throw new IllegalStateException("Parser has not been set"); @@ -1632,7 +1664,7 @@ public class HTMLDocument extends DefaultStyledDocument * @throws IllegalStateException - if parser is not set */ public void insertAfterEnd(Element elem, String htmlText) - throws BadLocationException, IOException + throws BadLocationException, IOException, NotImplementedException { if (parser == null) throw new IllegalStateException("Parser has not been set"); @@ -1651,7 +1683,7 @@ public class HTMLDocument extends DefaultStyledDocument * @throws IllegalStateException - if parser is not set */ public void insertAfterStart(Element elem, String htmlText) - throws BadLocationException, IOException + throws BadLocationException, IOException, NotImplementedException { if (parser == null) throw new IllegalStateException("Parser has not been set"); @@ -1676,6 +1708,7 @@ public class HTMLDocument extends DefaultStyledDocument */ public void setParagraphAttributes(int offset, int length, AttributeSet s, boolean replace) + throws NotImplementedException { // FIXME: Not implemented. System.out.println("setParagraphAttributes not implemented"); @@ -1688,6 +1721,7 @@ public class HTMLDocument extends DefaultStyledDocument * @param e - the Document event */ protected void fireChangedUpdate(DocumentEvent e) + throws NotImplementedException { // FIXME: Not implemented. System.out.println("fireChangedUpdate not implemented"); diff --git a/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java index 2d5d1eb..92d9de9 100644 --- a/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java +++ b/libjava/classpath/javax/swing/text/html/HTMLEditorKit.java @@ -39,6 +39,8 @@ exception statement from your version. */ package javax.swing.text.html; +import gnu.classpath.NotImplementedException; + import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -298,6 +300,7 @@ public class HTMLEditorKit Element insertElement, String html, HTML.Tag parentTag, HTML.Tag addTag) + throws NotImplementedException { /* As its name implies, this protected method is used when HTML is inserted at a diff --git a/libjava/classpath/javax/swing/text/html/ListView.java b/libjava/classpath/javax/swing/text/html/ListView.java new file mode 100644 index 0000000..c07d359 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/ListView.java @@ -0,0 +1,131 @@ +/* ListView.java -- + Copyright (C) 2006 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; + +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; + +import javax.swing.text.Element; + +/** + * A View to render HTML lists, like the <code><ul></code> and + * <code><ol></code> tags. + * + * @author Roman Kennke (kennke@aicas.com) + */ +public class ListView + extends BlockView +{ + + /** + * The painter used to paint the list items. + */ + private StyleSheet.ListPainter painter; + + /** + * Creates a new <code>ListView</code> for the specified element. + * + * @param el the element to create a list view for + */ + public ListView(Element el) + { + super(el, Y_AXIS); + } + + /** + * Returns the alignment of this view along the specified axis. + * + * This returns <code>0.5</code> unconditionally. + * + * @param axis the axis + * + * @return the alignment of this view along the specified axis + */ + public float getAlignment(int axis) + { + if (axis != X_AXIS && axis != Y_AXIS) + throw new IllegalArgumentException("Illegal axis parameter: " + axis); + + return 0.5F; + } + + /** + * Paints the <code>ListView</code>. + * + * @param g the graphics context to use for painting + * @param allocation the allocation given to this view + */ + public void paint(Graphics g, Shape allocation) + { + super.paint(g, allocation); + // FIXME: Why is this overridden? I think that painting would be done + // by the superclass and the stylesheet... Maybe find out when this + // stuff is implemented properly. + } + + /** + * Paints the child with the specified index into the specified allocation. + * + * This implementation forwards to the list painter fetched from the + * {@link StyleSheet} and then calls + * <code>super.paintChild(g, a, index)</code>. + * + * @param g the graphics context to use + * @param a the allocation for the child + * @param index the child index + */ + protected void paintChild(Graphics g, Rectangle a, int index) + { + painter.paint(g, a.x, a.y, a.width, a.height, this, index); + super.paintChild(g, a, index); + } + + /** + * Fetches this view's properties from the style attributes of this view's + * element. + * + * This forwards to super and then fetches a {@link StyleSheet.ListPainter} + * from the stylesheet suitable for painting the list. + */ + protected void setPropertiesFromAttributes() + { + super.setPropertiesFromAttributes(); + painter = getStyleSheet().getListPainter(getAttributes()); + } +} diff --git a/libjava/classpath/javax/swing/text/html/NullView.java b/libjava/classpath/javax/swing/text/html/NullView.java index 4b66c5a..86ce0c1 100644 --- a/libjava/classpath/javax/swing/text/html/NullView.java +++ b/libjava/classpath/javax/swing/text/html/NullView.java @@ -52,8 +52,8 @@ import javax.swing.text.Position.Bias; * * @author Roman Kennke (kennke@aicas.com) */ -public class NullView - extends View +class NullView + extends View { /** diff --git a/libjava/classpath/javax/swing/text/html/parser/Entity.java b/libjava/classpath/javax/swing/text/html/parser/Entity.java index 766984f..cf294c7 100644 --- a/libjava/classpath/javax/swing/text/html/parser/Entity.java +++ b/libjava/classpath/javax/swing/text/html/parser/Entity.java @@ -54,7 +54,7 @@ import java.io.Serializable; * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) */ public final class Entity - implements DTDConstants, Serializable + implements DTDConstants { /** * Package level mapper between type names and they string values. diff --git a/libjava/classpath/javax/swing/text/rtf/package.html b/libjava/classpath/javax/swing/text/rtf/package.html new file mode 100644 index 0000000..c695aef --- /dev/null +++ b/libjava/classpath/javax/swing/text/rtf/package.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.swing.text.rtf package. + Copyright (C) 2006 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. --> + +<html> +<head><title>GNU Classpath - javax.swing.text.rtf</title></head> + +<body> +<p>Provides support for Rich Text Format (RTF) data to be used with the +{@link JEditorPane} component. +</p> + +</body> +</html> |