This implements insertUpdate and removeUpdate for PlainView.

I did this work in response to bug 24152:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24152

Basically, this allows us to cache the length of the longest line (and
which line it is) so that calls to getPreferredSpan don't take a
ridiculously long time.  These 2 methods allow us to calculate the
length on the fly as text is inserted and deleted.

The test program in the bug report used to be unrunnable under classpath
because the delay was (much much much) too long, but it is runnable
now.  

However, the method getDemoText (in the test case attached to the bug
report) still runs orders of magnitude slower on classpath than on the
JDK.  The calls in the method are to Math.random and to
StringBuffer.append.  Someone may want to look into this.

2005-10-05  Anthony Balkissoon  <[EMAIL PROTECTED]>

        * javax/swing/text/PlainView.java:
        (insertOrRemoveUpdate): New method.
        (insertUpdate): New method.
        (removeUpdate): New method.

--Tony

Index: javax/swing/text/PlainView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/PlainView.java,v
retrieving revision 1.14
diff -u -r1.14 PlainView.java
--- javax/swing/text/PlainView.java	4 Oct 2005 19:37:20 -0000	1.14
+++ javax/swing/text/PlainView.java	5 Oct 2005 18:07:29 -0000
@@ -46,6 +46,9 @@
 import java.awt.Rectangle;
 import java.awt.Shape;
 
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentEvent.ElementChange;
+
 public class PlainView extends View
   implements TabExpander
 {
@@ -289,6 +292,101 @@
   {
     // FIXME: not implemented
     return 0;
+  }
+  
+  /**
+   * Since insertUpdate and removeUpdate each deal with children
+   * Elements being both added and removed, they both have to perform
+   * the same checks.  So they both simply call this method.
+   * @param changes the DocumentEvent for the changes to the Document.
+   * @param a the allocation of the View.
+   * @param f the ViewFactory to use for rebuilding.
+   */
+  void insertOrRemoveUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    Element el = getElement();
+    ElementChange ec = changes.getChange(el);
+    if (ec == null)
+      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
+    Element[] removed = ec.getChildrenRemoved();
+    if (removed != null)
+      {
+        for (int i = 0; i < removed.length; i++)
+          if (removed[i].equals(longestLine))
+            {
+              // reset maxLineLength and search through all lines for longest one
+              maxLineLength = -1;
+              determineMaxLineLength();
+              return;
+            }
+      }
+    
+    //  Make sure we have the metrics
+    updateMetrics();
+        
+    // Since we didn't remove the longest line, we can just compare it to 
+    // the new lines to see if any of them are longer
+    Element[] newElements = ec.getChildrenAdded();    
+    Segment seg = new Segment();
+    float longestNewLength = 0;
+    Element longestNewLine = null;
+    
+    if (newElements == null)
+      return;
+    for (int i = 0; i < newElements.length; i++)
+      {
+        Element child = newElements[i];
+        int start = child.getStartOffset();
+        int end = child.getEndOffset();
+        try
+          {
+            el.getDocument().getText(start, start + end, seg);
+          }
+        catch (BadLocationException ex)
+          {
+          }
+        
+        int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
+        if (width > longestNewLength)
+          {
+            longestNewLine = child;
+            longestNewLength = width;
+          }
+      }
+    if (longestNewLength > maxLineLength)
+      {
+        maxLineLength = longestNewLength;
+        longestLine = longestNewLine;
+      }      
+  }
+
+  /**
+   * This method is called when something is inserted into the Document
+   * that this View is displaying.
+   * 
+   * @param changes the DocumentEvent for the changes.
+   * @param a the allocation of the View
+   * @param f the ViewFactory used to rebuild
+   */
+  public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    insertOrRemoveUpdate(changes, a, f);
+  }
+
+  /**
+   * This method is called when something is removed from the Document
+   * that this View is displaying.
+   * 
+   * @param changes the DocumentEvent for the changes.
+   * @param a the allocation of the View
+   * @param f the ViewFactory used to rebuild
+   */
+  public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+  {
+    insertOrRemoveUpdate(changes, a, f);
   }
 }
 
_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to