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