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)
>        {

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to