Hi.

Roman Kennke wrote:
> Am Mittwoch, den 22.02.2006, 09:08 +0100 schrieb Robert Schuster:
> 
>>Hi,
>>as mentioned in PR 26157[0] I observed that the JDK's JTextArea adjusts its 
>>size
>>automatically when the characters leave the allocation area of the component.
>>Our JTextArea did not have this functionality until now.
>>
>>It took me a while to find out where to place the code that could do the
>>neccessary checks which should prevent unneeded revalidate() calls.
>>
>>While implementing this I found and fixed two problems in PlainView:
>>
>>1) The switch statement in getPreferredSpan always fell into the Y_AXIS case.
>>
>>2) In changeUpdate() the maxLineLength value could never shrink when 
>>characters
>>are removed on one line only. I added a check whether the characters are 
>>removed
>>from the current longest line and update the maxLineLength value if that is 
>>the
>>case.
> 
> 
> Great!
> 
> <<
>      switch (axis)
>        {
>        case X_AXIS:
> -        span = determineMaxLineLength();
> +        return determineMaxLineLength();
>        case Y_AXIS:
>        default:
> -        span = metrics.getHeight() * el.getElementCount();
> -        break;
> +        return metrics.getHeight() * el.getElementCount();
>        }
> -    return span;
> 
Done so.
> 
> -  private class RootView extends View
> +  class RootView extends View
> 
Not neccessary any more.

> 
> +  /** Extends the RootView of BasicTextUI with the ability to adjust
> the size
> +   * of the component after text was inserted, removed or changed.
> +   */
> +  class TextAreaRootView extends BasicTextUI.RootView
> +  {
> 
As explained on IRC I added the appropriate preferenceChanged() calls into
PlainView.

The new ChangeLog:

2006-02-21  Robert Schuster  <[EMAIL PROTECTED]>

        * javax/swing/text/PlainDocument.java:
        (getPreferredSpan): Added missing 'break'.
        statement which corrects an unwanted fall through.
        (updateDamage): Update maxLineLength correctly when text is
        removed, call preferenceChanged accordingly.
        (viewToModel): Restrict line number to be within 0 and the
        number of elements-1.


What is the last entry? A fix for a small problem I stepped upon when selecting
text with the mouse while hovering far above the component. I think it is a
minor glitch and the fix is appropriate that is why it is included in this 
patch.

cya
Robert
Index: javax/swing/text/PlainView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/PlainView.java,v
retrieving revision 1.36
diff -u -r1.36 PlainView.java
--- javax/swing/text/PlainView.java	8 Feb 2006 15:57:41 -0000	1.36
+++ javax/swing/text/PlainView.java	22 Feb 2006 09:48:51 -0000
@@ -307,18 +307,20 @@
     // make sure we have the metrics
     updateMetrics();
 
-    float span = 0;
     Element el = getElement();
+    float span;
 
     switch (axis)
       {
       case X_AXIS:
         span = determineMaxLineLength();
+        break;
       case Y_AXIS:
       default:
         span = metrics.getHeight() * el.getElementCount();
         break;
       }
+    
     return span;
   }
 
@@ -341,12 +343,19 @@
     Element root = doc.getDefaultRootElement();
     
     // PlainView doesn't support line-wrapping so we can find out which
-    // Element was clicked on just by the y-position    
-    int lineClicked = (int) (y - rec.y) / metrics.getHeight();
-    if (lineClicked >= root.getElementCount())
-      return getEndOffset() - 1;
+    // Element was clicked on just by the y-position.    
+    // Since the coordinates may be outside of the coordinate space
+    // of the allocation area (e.g. user dragged mouse outside
+    // the component) we have to limit the values.
+    // This has the nice effect that the user can drag the
+    // mouse above or below the component and it will still
+    // react to the x values (e.g. when selecting).
+    int lineClicked
+      = Math.min(Math.max((int) (y - rec.y) / metrics.getHeight(), 0),
+                          root.getElementCount() - 1);
     
     Element line = root.getElement(lineClicked);
+    
     Segment s = getLineBuffer();
     int start = line.getStartOffset();
     // We don't want the \n at the end of the line.
@@ -376,6 +385,8 @@
    */
   protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
   {
+    float oldMaxLineLength = maxLineLength; 
+    Rectangle alloc = a.getBounds();
     Element el = getElement();
     ElementChange ec = changes.getChange(el);
     
@@ -383,7 +394,19 @@
     // repaint the changed line
     if (ec == null)
       {
-        int line = getElement().getElementIndex(changes.getOffset());
+        int line = el.getElementIndex(changes.getOffset());
+        
+        // If characters have been removed from the current longest line
+        // we have to find out which one is the longest now otherwise
+        // the preferred x-axis span will not shrink.
+        if (changes.getType() == DocumentEvent.EventType.REMOVE
+            && el.getElement(line) == longestLine)
+          {
+            maxLineLength = -1;
+            if (determineMaxLineLength() != alloc.width)
+              preferenceChanged(this, true, false);
+          }
+        
         damageLineRange(line, line, a, getContainer());
         return;
       }
@@ -396,12 +419,13 @@
     if (removed == null && newElements == null)
       {
         int line = getElement().getElementIndex(changes.getOffset());
+        
         damageLineRange(line, line, a, getContainer());
         return;
       }
 
     // Check to see if we removed the longest line, if so we have to
-    // search through all lines and find the longest one again
+    // search through all lines and find the longest one again.
     if (removed != null)
       {
         for (int i = 0; i < removed.length; i++)
@@ -409,8 +433,11 @@
             {
               // reset maxLineLength and search through all lines for longest one
               maxLineLength = -1;
-              determineMaxLineLength();
+              if (determineMaxLineLength() != alloc.width)
+                preferenceChanged(this, true, removed.length != newElements.length);
+              
               ((JTextComponent)getContainer()).repaint();
+              
               return;
             }
       }
@@ -420,6 +447,7 @@
       {
         // No lines were added, just repaint the container and exit
         ((JTextComponent)getContainer()).repaint();
+        
         return;
       }
 
@@ -468,6 +496,14 @@
         maxLineLength = longestNewLength;
         longestLine = longestNewLine;
       }
+    
+    // Report any changes to the preferred sizes of the view
+    // which may cause the underlying component to be revalidated.
+    boolean widthChanged = oldMaxLineLength != maxLineLength;
+    boolean heightChanged = removed.length != newElements.length; 
+    if (widthChanged || heightChanged)
+      preferenceChanged(this, widthChanged, heightChanged);
+    
     // Repaint the container
     ((JTextComponent)getContainer()).repaint();
   }

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to