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
