This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH]: GetLayoutInfo in java.awt.GridBagLayout


On Fri, 2004-02-06 at 12:02, David Jee wrote:
> The following patch reimplements the GetLayoutInfo() method in
> java.awt.GridBagLayout, and fixes a few other things in that class. 

I found an error in my original patch.  The patch calls upon deprecated
methods (namely preferredSize() and minimumSize()).  It should use the
new alias methods instead.  Here is a repost of the corrected patch.

-David Jee

2004-02-06  David Jee  <djee@redhat.com>

        * java/awt/GridBagLayout.java
        (GridBagLayout): New private field, internalcomptable.
        (lookupInternalConstraints): New method.
        (ArrangeGrid): Use components' MINSIZE. Use internalcomptable.
        (GetLayoutInfo): Reimplement.
        (calcCellSizes): Ignore rows/columns with size 0.


Index: java/awt/GridBagLayout.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/GridBagLayout.java,v
retrieving revision 1.7
diff -u -r1.7 GridBagLayout.java
--- java/awt/GridBagLayout.java	3 Feb 2004 17:10:53 -0000	1.7
+++ java/awt/GridBagLayout.java	6 Feb 2004 16:27:21 -0000
@@ -40,6 +40,7 @@
 
 import java.io.Serializable;
 import java.util.Hashtable;
+import java.util.HashMap;
 
 /**
  * @author Michael Koch <konqueror@gmx.de>
@@ -54,7 +55,14 @@
     protected static final int PREFERREDSIZE = 2;
     protected static final int MAXGRIDSIZE = 512;
 
+    // comptable remembers the original contraints given to us.
+    // internalcomptable is used to keep track of modified constraint values
+    // that we calculate, particularly when we are given RELATIVE and
+    // REMAINDER constraints.
+    // Constraints kept in comptable are never modified, and constraints
+    // kept in internalcomptable can be modified internally only.
     protected Hashtable comptable;
+    private Hashtable internalcomptable;
     protected GridBagLayoutInfo layoutInfo;
     protected GridBagConstraints defaultConstraints;
 
@@ -66,6 +74,7 @@
     public GridBagLayout ()
     {
 	this.comptable = new Hashtable();
+	this.internalcomptable = new Hashtable();
 	this.defaultConstraints= new GridBagConstraints();
     }
 
@@ -213,6 +222,20 @@
 	return result;
     }
 
+    private GridBagConstraints lookupInternalConstraints (Component component)
+    {
+	GridBagConstraints result =
+            (GridBagConstraints) internalcomptable.get (component);
+
+	if (result == null)
+	{
+	    result = (GridBagConstraints) lookupConstraints(component).clone();
+	    internalcomptable.put (component, result);
+	}
+    
+	return result;
+    }
+
     /**
      * @since 1.1
      */
@@ -316,7 +339,7 @@
       if (components.length == 0)
         return;
 
-      GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
+      GridBagLayoutInfo info = getLayoutInfo (parent, MINSIZE);
       if (info.cols == 0 && info.rows == 0)
         return;
       layoutInfo = info;
@@ -332,7 +355,8 @@
           if (!component.isVisible())
             continue;
 		
-          GridBagConstraints constraints = lookupConstraints (component);
+          GridBagConstraints constraints =
+              lookupInternalConstraints(component);
 
           int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx);
           int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy);
@@ -435,12 +459,16 @@
       parentDim.width -= parentInsets.left + parentInsets.right;
       parentDim.height -= parentInsets.top + parentInsets.bottom;
    
-      int x = 0;
-      int y = 0;
+      int current_y = 0;
       int max_x = 0;
       int max_y = 0;
 
-      // first we figure out how many rows/columns
+      // Guaranteed to contain the last component added to the given row
+      // or column, whose gridwidth/height is not REMAINDER.
+      HashMap lastInRow = new HashMap();
+      HashMap lastInCol = new HashMap();
+
+      // STEP 1: first we figure out how many rows/columns
       Component[] components = parent.getComponents();
       for (int i = 0; i < components.length; i++)
 	{
@@ -450,124 +478,338 @@
           if (!component.isVisible())
             continue;
 		
-          GridBagConstraints constraints = lookupConstraints (component);
-		
+          // When looking up the constraint for the first time, check the
+          // original unmodified constraint.  After the first time, always
+          // refer to the internal modified constraint.
+          GridBagConstraints originalConstraints = lookupConstraints (component);
+          GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone();
+          internalcomptable.put(component, constraints);
+
+          // Cases:
+          //
+          // 1. gridy == RELATIVE, gridx == RELATIVE
+          //
+          //       use y as the row number; check for the next
+          //       available slot at row y
+          //
+          // 2. only gridx == RELATIVE
+          //
+          //       check for the next available slot at row gridy
+          //
+          // 3. only gridy == RELATIVE
+          //
+          //       check for the next available slot at column gridx
+          //
+          // 4. neither gridx or gridy == RELATIVE
+          //
+          //       nothing to check; just add it
+
+
+          // cases 1 and 2
           if(constraints.gridx == GridBagConstraints.RELATIVE)
-            constraints.gridx = x;
+            {
+              if (constraints.gridy == GridBagConstraints.RELATIVE)
+              constraints.gridy = current_y;
+
+              int x;
+
+              // Check the component that occupies the right-most spot in this
+              // row. We want to add this component after it.
+              // If this row is empty, add to the 0 position.
+              if (!lastInRow.containsKey(new Integer(constraints.gridy))) 
+                x = 0;
+              else
+                {
+                  Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy));
+                  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+                  x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth);
+                }
+
+              // Determine if this component will fit in the slot vertically.
+              // If not, bump it over to where it does fit.
+              for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+                {
+                  if (lastInRow.containsKey(new Integer(y)))
+                    {
+                      Component lastComponent = (Component) lastInRow.get(new Integer(y));
+                      GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+                      x = Math.max (x,
+                                    lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth));
+                    }
+                }
+
+              constraints.gridx = x;
+            }
+          // case 3
+          else if(constraints.gridy == GridBagConstraints.RELATIVE)
+            {
+              int y;
+              // Check the component that occupies the bottom-most spot in
+              // this column. We want to add this component below it.
+              // If this column is empty, add to the 0 position.
+              if (!lastInCol.containsKey(new Integer(constraints.gridx))) 
+                y = 0;
+              else
+                {
+                  Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx));
+                  GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+                  y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight);
+                }
+
+              // Determine if this component will fit in the slot horizontally.
+              // If not, bump it down to where it does fit.
+              for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+                {
+                  if (lastInCol.containsKey(new Integer(x)))
+                    {
+                      Component lastComponent = (Component) lastInCol.get(new Integer(x));
+                      GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+                      y = Math.max (y,
+                                    lastConstraints.gridy + Math.max(1, lastConstraints.gridheight));
+                    }
+                }
+
+              constraints.gridy = y;
+            }
+          // case 4: do nothing
 
-          if(constraints.gridy == GridBagConstraints.RELATIVE)
-            constraints.gridy = y;
-		
           max_x = Math.max(max_x, 
                            constraints.gridx + Math.max(1, constraints.gridwidth));
           max_y = Math.max(max_y,
                            constraints.gridy + Math.max(1, constraints.gridheight));
 
+          // Update our reference points for RELATIVE gridx and gridy.
           if(constraints.gridwidth == GridBagConstraints.REMAINDER)
 	    {
-              x = 0;
-              y++;
+              current_y = constraints.gridy + Math.max(1, constraints.gridheight);
 	    }
-          else
+          else if (constraints.gridwidth != GridBagConstraints.REMAINDER)
 	    {
-              x = constraints.gridx + Math.max(1, constraints.gridwidth);
-              y = constraints.gridy;
+              for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+                {
+                  if(lastInRow.containsKey(new Integer(y)))
+                    {
+                      Component lastComponent = (Component) lastInRow.get(new Integer(y));
+                      GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+                      if (constraints.gridx > lastConstraints.gridx)
+                        {
+                          lastInRow.put(new Integer(y), component);
+                        }
+                    }
+                  else
+                    {
+                      lastInRow.put(new Integer(y), component);
+                    }
+                }
+
+              for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+                {
+                  if(lastInCol.containsKey(new Integer(x)))
+                    {
+                      Component lastComponent = (Component) lastInCol.get(new Integer(x));
+                      GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+                      if (constraints.gridy > lastConstraints.gridy)
+                        {
+                          lastInCol.put(new Integer(x), component);
+                        }
+                    }
+                  else
+                    {
+                      lastInCol.put(new Integer(x), component);
+                    }
+                }
 	    }
-	}
+	} // end of STEP 1
 	
-      GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
+      boolean[] colIsOccupied = new boolean[max_x];
+      boolean[] rowIsOccupied = new boolean[max_y];
 
-      for (x = 0; x <= max_x; x++)
-	{
-          if(columnWidths != null && columnWidths.length > x)
-	    {
-              info.colWidths[x] = columnWidths[x];
-	    }
-          if(columnWeights != null && columnWeights.length > x)
-	    {
-              info.colWeights[x] = columnWeights[x];
-	    }
-          for (int i = 0; i < components.length; i++)
-	    {
-              Component component = components [i];
+      // STEP 2: Determine which cells the components occupy.
+      for (int i = 0; i < components.length; i++)
+        {
+          Component component = components [i];
 			
-              // If component is not visible we dont have to care about it.
-              if (!component.isVisible())
-                continue;
+          // If component is not visible we dont have to care about it.
+          if (!component.isVisible())
+            continue;
 			
-              GridBagConstraints constraints = lookupConstraints (component);
+          GridBagConstraints constraints = lookupInternalConstraints (component);
 
-              // first we fix up any REMAINDER cells
-              if(constraints.gridwidth == GridBagConstraints.REMAINDER)
-		{
-                  constraints.gridwidth = max_x - constraints.gridx;
-		}
-              if(constraints.gridheight == GridBagConstraints.REMAINDER)
-		{
-                  constraints.gridheight = max_y - constraints.gridy;
-		}
-
-              if(constraints.gridx + constraints.gridwidth - 1 == x)
-		{
-                  int width = (sizeflag == PREFERREDSIZE) ?
-                    component.getPreferredSize().width :
-                    component.getMinimumSize().width;
-                  if(constraints.insets != null)
-		    {
-                      width += constraints.insets.left + constraints.insets.right;
-		    }
-                  width += constraints.ipadx;
-                  for(int w = 1; w < constraints.gridwidth; w++)
-		    {
-                      width -= info.colWidths[x - w];
-		    }
-                  info.colWidths[x] = Math.max(info.colWidths[x], width);
-                  info.colWeights[x] =
-                    Math.max(info.colWeights[x], constraints.weightx);
-		}
-	    }
-	}
+          // Fix up any REMAINDER and RELATIVE cells.
+          if(constraints.gridwidth == GridBagConstraints.REMAINDER)
+            {
+              for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++)
+                {
+                  if (lastInRow.containsKey(new Integer(y)))
+                    {
+                      Component lastComponent = (Component) lastInRow.get(new Integer(y));
+                      GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+
+                      if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE)
+                        {
+                          constraints.gridx = max_x - 1;
+                          break;
+                        }
+                      else
+                        {
+                          constraints.gridx = Math.max (constraints.gridx,
+                                                        lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth));
+                        }
+                    }
+                }
+              constraints.gridwidth = max_x - constraints.gridx;
+            }
+          else if (constraints.gridwidth == GridBagConstraints.RELATIVE)
+            {
+              constraints.gridwidth = max_x - constraints.gridx - 1;
+            }
+
+          if(constraints.gridheight == GridBagConstraints.REMAINDER)
+            {
+              for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++)
+                {
+                  if (lastInCol.containsKey(new Integer(x)))
+                    {
+                      Component lastComponent = (Component) lastInRow.get(new Integer(x));
+                      GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent);
+
+                      if (lastConstraints.gridheight == GridBagConstraints.RELATIVE)
+                        {
+                          constraints.gridy = max_y - 1;
+                          break;
+                        }
+                      else
+                        {
+                          constraints.gridy = Math.max (constraints.gridy,
+                                                        lastConstraints.gridy + Math.max (1, lastConstraints.gridheight));
+                        }
+                    }
+                }
+              constraints.gridheight = max_y - constraints.gridy;
+            }
+          else if (constraints.gridheight == GridBagConstraints.RELATIVE)
+            {
+              constraints.gridheight = max_y - constraints.gridy - 1;
+            }
+
+          // For now, a row or a column is "occupied" iff a component
+          // both begins and ends in that row or column.
+          if (constraints.gridwidth == 1)
+            colIsOccupied[constraints.gridx] = true;
+          if (constraints.gridheight == 1)
+            rowIsOccupied[constraints.gridy] = true;
+        } // end of STEP 2
 
-      for (y = 0; y <= max_y; y++)
-	{
+      GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y);
+
+      // Check if column widths and row heights are overridden.
+
+      for (int x = 0; x < max_x; x++)
+        {
+          if(columnWidths != null && columnWidths.length > x)
+            info.colWidths[x] = columnWidths[x];
+          if(columnWeights != null && columnWeights.length > x)
+            info.colWeights[x] = columnWeights[x];
+        }
+
+      for (int y = 0; y < max_y; y++)
+        {
           if(rowHeights != null && rowHeights.length > y)
-	    {
-              info.rowHeights[y] = rowHeights[y];
-	    }
+            info.rowHeights[y] = rowHeights[y];
           if(rowWeights != null && rowWeights.length > y)
-	    {
-              info.rowWeights[y] = rowWeights[y];
-	    }
-          for (int i = 0; i < components.length; i++)
-	    {
-              Component component = components [i];
-			
-              // If component is not visible we dont have to care about it.
-              if (!component.isVisible())
-                continue;
+            info.rowWeights[y] = rowWeights[y];
+        }
+
+      // STEP 3: Distribute the weights and min sizes among rows/columns.
+      for (int i = 0; i < components.length; i++)
+        {
+          Component component = components [i];
 			
-              GridBagConstraints constraints = lookupConstraints (component);
+          // If component is not visible we dont have to care about it.
+          if (!component.isVisible())
+            continue;
 
-              if(constraints.gridy + constraints.gridheight - 1 == y)
-		{
-                  int height = (sizeflag == PREFERREDSIZE) ?
-                    component.getPreferredSize().height :
-                    component.getMinimumSize().height;
-                  if(constraints.insets != null)
-		    {
-                      height += constraints.insets.top + constraints.insets.bottom;
-		    } 
-                  height += constraints.ipady;
-                  for(int h = 1; h < constraints.gridheight; h++)
-		    {
-                      height -= info.rowHeights[y - h];
-		    }
-                  info.rowHeights[y] = Math.max(info.rowHeights[y], height);
-                  info.rowWeights[y] =
-                    Math.max(info.rowWeights[y], constraints.weighty);
-		}
-	    }
-	}
+          GridBagConstraints constraints = lookupInternalConstraints (component);
+          GridBagConstraints originalConstraints = lookupConstraints (component);
+
+          // Distribute the width.
+
+          int width = (sizeflag == PREFERREDSIZE) ?
+                      component.getPreferredSize().width :
+                      component.getMinimumSize().width;
+
+          if(constraints.insets != null)
+            width += constraints.insets.left + constraints.insets.right;
+
+          width += constraints.ipadx;
+
+          int occupiedCols = constraints.gridwidth;
+          int lastOccupiedCol = -1;
+
+          for(int w = constraints.gridx; w < constraints.gridx + constraints.gridwidth; w++)
+            {
+              if(colIsOccupied[w])
+                lastOccupiedCol = w;
+              else
+                occupiedCols--;
+            }
+
+          // A component needs to occupy at least one column.
+          if(occupiedCols == 0)
+            {
+              colIsOccupied[constraints.gridx + constraints.gridwidth - 1] = true;
+              lastOccupiedCol = constraints.gridx + constraints.gridwidth - 1;
+            }
+
+          for(int w = constraints.gridx; w < constraints.gridx + constraints.gridwidth - 1; w++)
+            {
+              if(colIsOccupied[w])
+                width -= info.colWidths[w];
+            }
+
+          info.colWidths[lastOccupiedCol] = Math.max(info.colWidths[lastOccupiedCol], width);
+          info.colWeights[lastOccupiedCol] = Math.max(info.colWeights[lastOccupiedCol], constraints.weightx);
+
+
+          // Distribute the height.
+
+          int height = (sizeflag == PREFERREDSIZE) ?
+                       component.getPreferredSize().height :
+                       component.getMinimumSize().height;
+
+          if(constraints.insets != null)
+            height += constraints.insets.top + constraints.insets.bottom;
+
+          height += constraints.ipady;
+
+          int occupiedRows = constraints.gridheight;
+          int lastOccupiedRow = -1;
+
+          for(int h = constraints.gridy; h < constraints.gridy + constraints.gridheight; h++)
+            {
+              if(rowIsOccupied[h])
+                lastOccupiedRow = h;
+              else
+                occupiedRows--;
+            }
+
+          // A component needs to occupy at least one row.
+          if(occupiedRows == 0)
+            {
+              rowIsOccupied[constraints.gridy + constraints.gridheight - 1] = true;
+              lastOccupiedRow = constraints.gridy + constraints.gridheight - 1;
+            }
+
+          for(int h = constraints.gridy; h < constraints.gridy + constraints.gridheight; h++)
+            {
+              if(rowIsOccupied[h])
+                height -= info.rowHeights[h];
+            }
+
+          info.rowHeights[lastOccupiedRow] = Math.max(info.rowHeights[lastOccupiedRow], height);
+          info.rowWeights[lastOccupiedRow] = Math.max(info.rowWeights[lastOccupiedRow], constraints.weighty);
+
+        } // end of STEP 3
 
       calcCellSizes (info.colWidths, info.colWeights, parentDim.width);
       calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height);
@@ -607,20 +849,32 @@
 
     private void calcCellSizes (int[] sizes, double[] weights, int range)
     {
-	int diff = range - sumIntArray (sizes);
+      int totalSize = sumIntArray (sizes);
+      double totalWeight = sumDoubleArray (weights);
 
-	if (diff == 0)
-	    return;
-    
-	double weight = sumDoubleArray (weights);
+      // Rows or columns with size 0 should not be weighted in the calculation.
+      for (int i = 0; i < weights.length; i++)
+        {
+          if (sizes[i] == 0)
+            totalWeight -= weights[i];
+        }
 
-	for (int i = 0; i < sizes.length; i++)
-	{
-	    sizes [i] += (int) (((double) diff) * weights [i] / weight );
+      int diff = range - totalSize;
 
-	    if (sizes [i] < 0)
-		sizes [i] = 0;
-	}
+      if (diff == 0)
+        return;
+
+      for (int i = 0; i < sizes.length; i++)
+        {
+          // A row or column with zero size cannot all of a sudden gain size.
+          if (sizes[i] != 0.0)
+            {
+              int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight ));
+
+              if (newsize > 0)
+                sizes[i] = newsize;
+            }
+        }
     }
 
     private void dumpLayoutInfo (GridBagLayoutInfo info)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]