There was a strange (but documented) rule in the javax/swing/ViewportLayout.java: If the port is larger than the view's minimum size, put the port at view position (0,0). For the view port in the scroll pane this near always means scrolling to the top left corner each time the component is revalidated (by adding/removing tree nodes or just by resizing the window).

Normally, the views minimum size is rather small, the port is larger, so this scrolling operation occurs near always. The problem can be fixed by rewriting the layoutContainer, as described in the patch.

Despite it seems not introducing regressions in our Swing activity board, the patch may need additional attention as it alters the commented (in our code) behavior of this class.

2006-01-28  Audrius Meskauskas  <[EMAIL PROTECTED]>

  * javax/swing/ViewportLayout.java (layoutContainer): Rewritten.



Index: ViewportLayout.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/ViewportLayout.java,v
retrieving revision 1.23
diff -u -r1.23 ViewportLayout.java
--- ViewportLayout.java	10 Jan 2006 13:38:59 -0000	1.23
+++ ViewportLayout.java	28 Jan 2006 20:58:12 -0000
@@ -1,5 +1,5 @@
 /* ViewportLayout.java --
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -46,9 +46,16 @@
 import java.io.Serializable;
 
 /**
- * ViewportLayout
- * @author	Andrew Selkirk
- * @author	Graydon Hoare
+ * The default layout for [EMAIL PROTECTED] JViewport}. The viewport makes its view the 
+ * same size as itself, but not smaller than its minimum size. 
+ * 
+ * If the port extends extends into space <em>past</em> the edge of the view,
+ * this layout manager moves the port up or to the left, in view space, by the
+ * amount of empty space (keep the lower and right edges lined up).
+ * 
+ * @author  Andrew Selkirk
+ * @author  Graydon Hoare
+ * @author  Audrius Meskauskas ([EMAIL PROTECTED])
  */
 public class ViewportLayout implements LayoutManager, Serializable
 {
@@ -58,17 +65,31 @@
   {
     // Nothing to do here.
   }
-
+  
+  /**
+   * The method is not used with this manager.
+   */
   public void addLayoutComponent(String name, Component c) 
   {
     // Nothing to do here.
   }
 
+  /**
+   * The method is not used with this manager.
+   */
   public void removeLayoutComponent(Component c) 
   {
     // Nothing to do here.
   }
-
+  
+  /**
+   * Get the preferred layout size. If the view implements
+   * [EMAIL PROTECTED] Scrollable}, this method returns 
+   * [EMAIL PROTECTED] Scrollable#getPreferredScrollableViewportSize}.
+   * Otherwise, it returns [EMAIL PROTECTED] Component#getPreferredSize()}.
+   * 
+   * @return the preferred layout size, as described about.
+   */
   public Dimension preferredLayoutSize(Container parent) 
   {
     JViewport vp = (JViewport)parent;
@@ -83,6 +104,14 @@
       return new Dimension();
   }
 
+  /**
+   * Get the minimum layout size. Normally this method returns the value,
+   * returned by the view method [EMAIL PROTECTED] Component#getMinimumSize()}.
+   * 
+   * If the view is not set, the zero size is returned.  
+   * 
+   * @return the minimum layout size.
+   */
   public Dimension minimumLayoutSize(Container parent) 
   {
     JViewport vp = (JViewport)parent;
@@ -101,15 +130,13 @@
    *
    * <ol> 
    * 
-   * <li>If the port is larger than the view's minimum size, put the port
-   * at view position <code>(0,0)</code> and make the view's size equal to
-   * the port's.</li>
-   *
    * <li>If the port is smaller than the view, leave the view at its
-   * minimum size. also, do not move the port, <em>unless</em> the port
+   * current size. Also, do not move the port, <em>unless</em> the port
    * extends into space <em>past</em> the edge of the view. If so, move the
    * port up or to the left, in view space, by the amount of empty space
    * (keep the lower and right edges lined up)</li>
+   * <li>In [EMAIL PROTECTED] JViewport#setViewSize(Dimension)}, the view size is never
+   * set smaller that its minimum size.</li>
    *
    * </ol>
    *
@@ -141,23 +168,22 @@
     Rectangle portBounds = port.getViewRect();
     Dimension viewPref = view.getPreferredSize();
     Dimension viewMinimum = view.getMinimumSize();
+
     Point portLowerRight = new Point(portBounds.x + portBounds.width,
                                      portBounds.y + portBounds.height);
+    int overextension;
 
     // vertical implementation of the above rules
     if ((! (view instanceof Scrollable) && viewPref.height < portBounds.height
          || (view instanceof Scrollable
             && ((Scrollable) view).getScrollableTracksViewportHeight())))
       viewPref.height = portBounds.height;
-
-    if (portBounds.height >= viewMinimum.height)
-      portBounds.y = 0;
-    else
-      {
-        int overextension = portLowerRight.y - viewPref.height;
-        if (overextension > 0)
-            portBounds.y -= overextension;
-      }
+   
+    // If the view is larger than the port, and port is partly outside
+    // the view, it is moved fully into the view area.
+    overextension = portLowerRight.y - viewPref.height;
+    if (overextension > 0)
+      portBounds.y -= overextension;
 
     // horizontal implementation of the above rules
     if ((! (view instanceof Scrollable) && viewPref.width < portBounds.width
@@ -165,16 +191,27 @@
          && ((Scrollable) view).getScrollableTracksViewportWidth())))
       viewPref.width = portBounds.width;
 
-    if (portBounds.width >= viewMinimum.width)
-      portBounds.x = 0;
-    else
+    // If the view is larger than the port, and port is partly outside
+    // the view, it is moved fully into the view area.
+    overextension = portLowerRight.x - viewPref.width;
+    if (overextension > 0)
+      portBounds.x -= overextension;
+
+    // If the calculated view size was smaller than the minimum size,
+    // extend till the minimum size.
+    if (viewPref.height<viewMinimum.height)
+      {
+        viewPref.height = viewMinimum.height;
+        portBounds.x = 0;
+      }
+    
+    if (viewPref.width<viewMinimum.width)
       {
-        int overextension = portLowerRight.x - viewPref.width;
-        if (overextension > 0)
-            portBounds.x -= overextension;
+        viewPref.width = viewMinimum.width;
+        portBounds.y = 0;
       }
 
-    port.setViewPosition(portBounds.getLocation());
     port.setViewSize(viewPref);
+    port.setViewPosition(portBounds.getLocation());
   }
 }

Reply via email to