Committed - Roman reviewed the first version. cya Robert
Robert Schuster wrote:
> Hi all.
>
> I fixed to small errors in this patch that lead to strange behavior:
>
>
>>+ // Last line, from beginning-of-line to p1.
>>+ r0.width = r1.x + r1.width;
>
> Had to add -1 to the calculation above otherwise there were drawing
> differences
> between single line and multi line selections.
>
>
>>+ paintHighlight(g, r0);
>> }
>>+
>>+ // Prevent useless write & repaint operations.
>>+ if (o0 == o1 && o1 == p1)
>>+ return;
>>+
>
> This expression wanted to be
>
>
>>+ if (o0 == p0 && o1 == p1)
>
>
> Apart from that I updated the copyright headers in the affected files.
>
> After fixing that I cannot see any more problems with the highlighting
> mechanism.
>
>
> ChangeLog stays the same:
>
> 2006-02-21 Robert Schuster <[EMAIL PROTECTED]>
>
> * javax/swing/plaf/basic/BasicTextUI.java:
> (paint): Remove unneccessary part of the if-expression.
> (damageRange): Added case where the range spans multiple lines.
> * javax/swing/text/DefaultCaret.java:
> (clearHighlight): New method.
> (handleHighlight): Removed unneccessary part of the if-expression.
> (setDot): Use clearHighlight method.
> * javax/swing/text/DefaultHighlighter.java: Use ArrayList instead
> of Vector.
> (paint): Prevented calling size() on every loop iteration, fixed
> calculation of allocation area bounds.
> (getHighlights): Implemented.
> (removeHighlight): Mark damaged area in textcomponent.
> (addHighlight): Mark damaged area in textcomponent.
> (changeHighlight): Mark damaged area in textcomponent.
> (DefaultHighlighter.HighlightEntry): Made it a real
> Highlighter.Highlight implementation.
> (DefaultHighlighter.DefaultHighlightPainter.paint): Fixed
> calculations.
>
> cya
> Robert
>
>
>
> ------------------------------------------------------------------------
>
> Index: javax/swing/text/DefaultCaret.java
> ===================================================================
> RCS file: /cvsroot/classpath/classpath/javax/swing/text/DefaultCaret.java,v
> retrieving revision 1.30
> diff -u -r1.30 DefaultCaret.java
> --- javax/swing/text/DefaultCaret.java 9 Feb 2006 17:15:33 -0000
> 1.30
> +++ javax/swing/text/DefaultCaret.java 21 Feb 2006 10:25:59 -0000
> @@ -577,7 +577,39 @@
> {
> return mark;
> }
> -
> +
> + private void clearHighlight()
> + {
> + Highlighter highlighter = textComponent.getHighlighter();
> +
> + if (highlighter == null)
> + return;
> +
> + if (selectionVisible)
> + {
> + try
> + {
> + if (highlightEntry == null)
> + highlightEntry = highlighter.addHighlight(0, 0,
> getSelectionPainter());
> + else
> + highlighter.changeHighlight(highlightEntry, 0, 0);
> + }
> + catch (BadLocationException e)
> + {
> + // This should never happen.
> + throw new InternalError();
> + }
> + }
> + else
> + {
> + if (highlightEntry != null)
> + {
> + highlighter.removeHighlight(highlightEntry);
> + highlightEntry = null;
> + }
> + }
> + }
> +
> private void handleHighlight()
> {
> Highlighter highlighter = textComponent.getHighlighter();
> @@ -588,7 +620,7 @@
> int p0 = Math.min(dot, mark);
> int p1 = Math.max(dot, mark);
>
> - if (selectionVisible && p0 != p1)
> + if (selectionVisible)
> {
> try
> {
> @@ -818,6 +850,7 @@
> if (doc != null)
> this.dot = Math.min(dot, doc.getLength());
> this.dot = Math.max(this.dot, 0);
> +
> handleHighlight();
> adjustVisibility(this);
> appear();
> @@ -842,7 +875,8 @@
> this.dot = Math.min(dot, doc.getLength());
> this.dot = Math.max(this.dot, 0);
> this.mark = this.dot;
> - handleHighlight();
> +
> + clearHighlight();
> adjustVisibility(this);
> appear();
> }
> Index: javax/swing/text/DefaultHighlighter.java
> ===================================================================
> RCS file:
> /cvsroot/classpath/classpath/javax/swing/text/DefaultHighlighter.java,v
> retrieving revision 1.6
> diff -u -r1.6 DefaultHighlighter.java
> --- javax/swing/text/DefaultHighlighter.java 19 Oct 2005 14:57:30 -0000
> 1.6
> +++ javax/swing/text/DefaultHighlighter.java 21 Feb 2006 10:25:59 -0000
> @@ -1,5 +1,5 @@
> /* DefaultHighlighter.java --
> - Copyright (C) 2004 Free Software Foundation, Inc.
> + Copyright (C) 2004, 2006 Free Software Foundation, Inc.
>
> This file is part of GNU Classpath.
>
> @@ -40,9 +40,10 @@
>
> import java.awt.Color;
> import java.awt.Graphics;
> +import java.awt.Insets;
> import java.awt.Rectangle;
> import java.awt.Shape;
> -import java.util.Vector;
> +import java.util.ArrayList;
>
> public class DefaultHighlighter extends LayeredHighlighter
> {
> @@ -84,7 +85,7 @@
> // This should never occur.
> return;
> }
> -
> +
> if (r0 == null || r1 == null)
> return;
>
> @@ -100,7 +101,7 @@
> paintHighlight(g, r0);
> return;
> }
> -
> +
> // First line, from p0 to end-of-line.
> r0.width = rect.x + rect.width - r0.x;
> paintHighlight(g, r0);
> @@ -109,15 +110,19 @@
> // have the same height -- not a good assumption with
> JEditorPane/JTextPane).
> r0.y += r0.height;
> r0.x = rect.x;
> -
> + r0.width = rect.width;
> +
> while (r0.y < r1.y)
> {
> paintHighlight(g, r0);
> r0.y += r0.height;
> }
>
> - // Last line, from beginnin-of-line to p1.
> - paintHighlight(g, r1);
> + // 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);
> }
>
> public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds,
> @@ -127,7 +132,7 @@
> }
> }
>
> - private class HighlightEntry
> + private class HighlightEntry implements Highlighter.Highlight
> {
> int p0;
> int p1;
> @@ -140,12 +145,12 @@
> this.painter = painter;
> }
>
> - public int getStartPosition()
> + public int getStartOffset()
> {
> return p0;
> }
>
> - public int getEndPosition()
> + public int getEndOffset()
> {
> return p1;
> }
> @@ -163,7 +168,7 @@
> new DefaultHighlightPainter(null);
>
> private JTextComponent textComponent;
> - private Vector highlights = new Vector();
> + private ArrayList highlights = new ArrayList();
> private boolean drawsLayeredHighlights = true;
>
> public DefaultHighlighter()
> @@ -208,12 +213,20 @@
> checkPositions(p0, p1);
> HighlightEntry entry = new HighlightEntry(p0, p1, painter);
> highlights.add(entry);
> +
> + textComponent.getUI().damageRange(textComponent, p0, p1);
> +
> return entry;
> }
>
> public void removeHighlight(Object tag)
> {
> highlights.remove(tag);
> +
> + HighlightEntry entry = (HighlightEntry) tag;
> + textComponent.getUI().damageRange(textComponent,
> + entry.p0,
> + entry.p1);
> }
>
> public void removeAllHighlights()
> @@ -223,16 +236,30 @@
>
> public Highlighter.Highlight[] getHighlights()
> {
> - return null;
> + return (Highlighter.Highlight[])
> + highlights.toArray(new Highlighter.Highlight[highlights.size()]);
> }
>
> public void changeHighlight(Object tag, int p0, int p1)
> throws BadLocationException
> {
> + int o0, o1;
> +
> checkPositions(p0, p1);
> HighlightEntry entry = (HighlightEntry) tag;
> + o0 = entry.p0;
> + o1 = entry.p1;
> +
> + // Prevent useless write & repaint operations.
> + if (o0 == p0 && o1 == p1)
> + return;
> +
> entry.p0 = p0;
> entry.p1 = p1;
> +
> + textComponent.getUI().damageRange(textComponent,
> + Math.min(p0, o0),
> + Math.max(p1, o1));
> }
>
> public void paintLayeredHighlights(Graphics g, int p0, int p1,
> @@ -244,13 +271,21 @@
>
> public void paint(Graphics g)
> {
> + int size = highlights.size();
> +
> // Check if there are any highlights.
> - if (highlights.size() == 0)
> + if (size == 0)
> return;
> +
> + // Prepares the rectangle of the inner drawing area.
> + Insets insets = textComponent.getInsets();
> + Shape bounds =
> + new Rectangle(insets.left,
> + insets.top,
> + textComponent.getWidth() - insets.left - insets.right,
> + textComponent.getHeight() - insets.top - insets.bottom);
>
> - Shape bounds = textComponent.getBounds();
> -
> - for (int index = 0; index < highlights.size(); ++index)
> + for (int index = 0; index < size; ++index)
> {
> HighlightEntry entry = (HighlightEntry) highlights.get(index);
> entry.painter.paint(g, entry.p0, entry.p1, bounds, textComponent);
> Index: javax/swing/plaf/basic/BasicTextUI.java
> ===================================================================
> RCS file:
> /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTextUI.java,v
> retrieving revision 1.69
> diff -u -r1.69 BasicTextUI.java
> --- javax/swing/plaf/basic/BasicTextUI.java 20 Feb 2006 12:40:42 -0000
> 1.69
> +++ javax/swing/plaf/basic/BasicTextUI.java 21 Feb 2006 10:25:59 -0000
> @@ -1,5 +1,5 @@
> /* BasicTextUI.java --
> - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
> + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
>
> This file is part of GNU Classpath.
>
> @@ -79,6 +79,7 @@
> import javax.swing.text.JTextComponent;
> import javax.swing.text.Keymap;
> import javax.swing.text.Position;
> +import javax.swing.text.Utilities;
> import javax.swing.text.View;
> import javax.swing.text.ViewFactory;
>
> @@ -875,9 +876,19 @@
> if (textComponent.isOpaque())
> paintBackground(g);
>
> - if (highlighter != null
> - && textComponent.getSelectionStart() !=
> textComponent.getSelectionEnd())
> - highlighter.paint(g);
> + // Try painting with the highlighter without checking whether there
> + // is a selection because a highlighter can be used to do more than
> + // marking selected text.
> + if (highlighter != null)
> + {
> + // Handle restoring of the color here to prevent
> + // drawing problems when the Highlighter implementor
> + // forgets to restore it.
> + Color oldColor = g.getColor();
> + highlighter.paint(g);
> + g.setColor(oldColor);
> + }
> +
>
> rootView.paint(g, getVisibleEditorRect());
>
> @@ -945,9 +956,75 @@
> {
> try
> {
> + // Limit p0 and p1 to sane values to prevent unfriendly
> + // BadLocationExceptions. This makes it possible for the highlighter
> + // to send us illegal values which can happen when a large number
> + // of selected characters are removed (eg. by pressing delete
> + // or backspace).
> + // The reference implementation does not throw an exception, too.
> + p0 = Math.min(p0, t.getDocument().getLength());
> + p1 = Math.min(p1, t.getDocument().getLength());
> +
> Rectangle l1 = modelToView(t, p0, firstBias);
> Rectangle l2 = modelToView(t, p1, secondBias);
> - t.repaint(l1.union(l2));
> + if (l1.y == l2.y)
> + t.repaint(l1.union(l2));
> + else
> + {
> + // The two rectangles lie on different lines and we need a
> + // different algorithm to calculate the damaged area:
> + // 1. The line of p0 is damaged from the position of p0
> + // to the right border.
> + // 2. All lines between the ones where p0 and p1 lie on
> + // are completely damaged. Use the allocation area to find
> + // out the bounds.
> + // 3. The final line is damaged from the left bound to the
> + // position of p1.
> + Insets insets = t.getInsets();
> +
> + // Damage first line until the end.
> + l1.width = insets.right + t.getWidth() - l1.x;
> + t.repaint(l1);
> +
> + // Note: Utilities.getPositionBelow() may return the offset
> + // that was put in. In that case there is no next line and
> + // we should stop searching for one.
> +
> + int posBelow = Utilities.getPositionBelow(t, p0, l1.x);
> + if (posBelow < p1 && posBelow != -1 && posBelow != p0)
> + {
> + // Take the rectangle of the offset we just found and grow it
> + // to the maximum width. Retain y because this is our start
> + // height.
> + Rectangle grow = modelToView(t, posBelow);
> + grow.x = insets.left;
> + grow.width = t.getWidth() + insets.right;
> +
> + // Find further lines which have to be damaged completely.
> + int nextPosBelow = posBelow;
> + while (nextPosBelow < p1 && nextPosBelow != -1 && posBelow
> != nextPosBelow)
> + {
> + posBelow = nextPosBelow;
> + nextPosBelow = Utilities.getPositionBelow(t, posBelow,
> l1.x);
> + }
> + // Now posBelow is an offset on the last line which has to
> be damaged
> + // 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 = modelToView(t, posBelow);
> + grow.height = end.y + end.height - grow.y;
> +
> + // Mark that area as damage.
> + t.repaint(grow);
> + }
> +
> + // Damage last line from its beginning to the position of p1.
> + l2.width += l2.x;
> + l2.x = insets.left;
> + t.repaint(l2);
> + }
> }
> catch (BadLocationException ex)
> {
signature.asc
Description: OpenPGP digital signature
