1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * ident	"%Z%%M%	%I%	%E% SMI"
24 *
25 * @(#)GBLayout.java	1.23 97/09/03 Doug Stein
26 *
27 * Copyright (c) 1996, 2001 by Sun Microsystems, Inc.
28 * All rights reserved.
29 *
30 * Permission to use, copy, modify, and distribute this software
31 * and its documentation for NON-COMMERCIAL purposes and without
32 * fee is hereby granted provided that this copyright notice
33 * appears in all copies. Please refer to the file "copyright.html"
34 * for further important copyright and licensing information.
35 *
36 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
37 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
38 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
39 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
40 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
41 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
42 */
43package sunsoft.jws.visual.rt.awt;
44
45import sunsoft.jws.visual.rt.base.Global;
46
47import java.awt.*;
48import java.util.Hashtable;
49
50class GBLayoutInfo {
51    int width, height;	/* number of cells horizontally, vertically */
52    int startx, starty;		/* starting point for layout */
53    int minWidth[];		/* largest minWidth in each column */
54    int minHeight[];		/* largest minHeight in each row */
55    double weightX[];		/* largest weight in each column */
56    double weightY[];		/* largest weight in each row */
57
58    GBLayoutInfo(int w, int h) {
59        width = w;
60        height = h;
61        minWidth = new int[w];
62        minHeight = new int[h];
63        weightX = new double[w];
64        weightY = new double[h];
65    }
66}
67
68/* BEGIN JSTYLED */
69/**
70   GBLayout is a flexible layout manager
71   that aligns components vertically and horizontally,
72   without requiring that the components be the same size.
73   Each GBLayout uses a rectangular grid of cells,
74   with each component occupying one or more cells
75   (called its  < em >display area</em>).
76   Each component managed by a GBLayout
77   is associated with a
78   < a href = java.awt.GBConstraints.html >GBConstraints</a>  instance
79   that specifies how the component is laid out
80   within its display area.
81   How a GBLayout places a set of components
82   depends on each component's GBConstraints and minimum size,
83   as well as the preferred size of the components' container.
84   < p>
85
86   To use a GBLayout effectively,
87   you must customize one or more of its components' GBConstraints.
88   You customize a GBConstraints object by setting one or more
89   of its instance variables:
90   < dl>
91   < dt > <a href = java.awt.GBConstraints.html#gridx> gridx</a>,
92   < a href = java.awt.GBConstraints.html#gridy> gridy</a>
93   < dd>  Specifies the cell at the upper left of the component's display area,
94   where the upper-left-most cell has address gridx  =  0, gridy=0.
95   Use GBConstraints.RELATIVE(the default value)
96   to specify that the component be just placed
97   just to the right of(for gridx)
98   or just below(for gridy)
99   the component that was added to the container
100   just before this component was added.
101   < dt > <a href = java.awt.GBConstraints.html#gridwidth> gridwidth</a>,
102   < a href = java.awt.GBConstraints.html#gridheight> gridheight</a>
103   < dd>  Specifies the number of cells in a row(for gridwidth)
104   or column(for gridheight)
105   in the component's display area.
106   The default value is 1.
107   Use GBConstraints.REMAINDER to specify
108   that the component be the last one in its row(for gridwidth)
109   or column(for gridheight).
110   Use GBConstraints.RELATIVE to specify
111   that the component be the next to last one
112   in its row(for gridwidth) or column (for gridheight).
113   < dt>  <a href = java.awt.GBConstraints.html#fill>fill</a>
114   < dd>  Used when the component's display area
115   is larger than the component's requested size
116   to determine whether(and how) to resize the component.
117   Valid values are
118   GBConstraints.NONE
119   (the default),
120   GBConstraints.HORIZONTAL
121   (make the component wide enough to fill its display area
122   horizontally, but don't change its height),
123   GBConstraints.VERTICAL
124   (make the component tall enough to fill its display area
125   vertically, but don't change its width),
126   and
127   GBConstraints.BOTH
128   (make the component fill its display area entirely).
129   < dt > <a href = java.awt.GBConstraints.html#ipadx> ipadx</a>,
130   < a href = java.awt.GBConstraints.html#ipady> ipady</a>
131   < dd>  Specifies the internal padding:
132   how much to add to the minimum size of the component.
133   The width of the component will be at least
134   its minimum width plus ipadx*2 pixels
135   (since the padding applies to both sides of the component).
136   Similarly, the height of the component will be at least
137   the minimum height plus ipady*2 pixels.
138   < dt>  <a href = java.awt.GBConstraints.html#insets>insets</a>
139   < dd>  Specifies the external padding of the component --
140   the minimum amount of space between the component
141   and the edges of its display area.
142   < dt>  <a href = java.awt.GBConstraints.html#anchor>anchor</a>
143   < dd>  Used when the component is smaller than its display area
144   to determine where(within the area) to place the component.
145   Valid values are
146   GBConstraints.CENTER(the default),
147   GBConstraints.NORTH,
148   GBConstraints.NORTHEAST,
149   GBConstraints.EAST,
150   GBConstraints.SOUTHEAST,
151   GBConstraints.SOUTH,
152   GBConstraints.SOUTHWEST,
153   GBConstraints.WEST, and
154   GBConstraints.NORTHWEST.
155   < dt > <a href = java.awt.GBConstraints.html#weightx> weightx</a>,
156   < a href = java.awt.GBConstraints.html#weighty> weighty</a>
157   < dd>  Used to determine how to distribute space;
158   this is important for specifying resizing behavior.
159   Unless you specify a weight
160   for at least one component in a row(weightx)
161   and column(weighty),
162   all the components clump together in the center of
163   their container.
164   This is because when the weight is zero(the default),
165   the GBLayout puts any extra space
166   between its grid of cells and the edges of the container.
167   < /dl>
168
169   The following figure shows ten components(all buttons)
170   managed by a GBLayout:
171   < blockquote>
172   < img src  =  images/java.awt/GridBagEx.gif width=262 height=155>
173   < /blockquote>
174
175   All the components have fill = GBConstraints.BOTH.
176   In addition, the components have the following non-default constraints:
177   < ul>
178   < li >Button1, Button2, Button3:
179   weightx = 1.0
180   < li >Button4:
181   weightx = 1.0,
182   gridwidth = GBConstraints.REMAINDER
183   < li >Button5:
184   gridwidth = GBConstraints.REMAINDER
185   < li >Button6:
186   gridwidth = GBConstraints.RELATIVE
187   < li >Button7:
188   gridwidth = GBConstraints.REMAINDER
189   < li >Button8:
190   gridheight  =  2, weighty=1.0,
191   < li >Button9, Button 10:
192   gridwidth = GBConstraints.REMAINDER
193   < /ul>
194
195   Here is the code that implements the example shown above:
196   < blockquote>
197   < pre>
198   import java.awt.*;
199   import java.util.*;
200   import java.applet.Applet;
201
202   public class GridBagEx1 extends Applet {
203
204   protected void makebutton(String name,
205   GBLayout gridbag,
206   GBConstraints c) {
207   Button button = new Button(name);
208   gridbag.setConstraints(button, c);
209   add(button);
210   }
211
212   public void init() {
213   GBLayout gridbag = new GBLayout();
214   GBConstraints c = new GBConstraints();
215
216   setFont(new Font("Sansserif", Font.PLAIN, 14));
217   setLayout(gridbag);
218
219   c.fill = GBConstraints.BOTH;
220   c.weightx = 1.0;
221   makebutton("Button1", gridbag, c);
222   makebutton("Button2", gridbag, c);
223   makebutton("Button3", gridbag, c);
224
225   c.gridwidth = GBConstraints.REMAINDER; // end row
226   makebutton("Button4", gridbag, c);
227
228   c.weightx = 0.0;		   // reset to the default
229   makebutton("Button5", gridbag, c); // another row
230
231   c.gridwidth = GBConstraints.RELATIVE; // next-to-last in row
232   makebutton("Button6", gridbag, c);
233
234   c.gridwidth = GBConstraints.REMAINDER; // end row
235   makebutton("Button7", gridbag, c);
236
237   c.gridwidth = 1;	   	   // reset to the default
238   c.gridheight = 2;
239   c.weighty = 1.0;
240   makebutton("Button8", gridbag, c);
241
242   c.weighty = 0.0;		   // reset to the default
243   c.gridwidth = GBConstraints.REMAINDER; // end row
244   c.gridheight = 1;		   // reset to the default
245   makebutton("Button9", gridbag, c);
246   makebutton("Button10", gridbag, c);
247
248   resize(300, 100);
249   }
250
251   public static void main(String args[]) {
252   Frame f = new Frame("GridBag Layout Example");
253   GridBagEx1 ex1 = new GridBagEx1();
254
255   ex1.init();
256
257   f.add("Center", ex1);
258   f.pack();
259   f.resize(f.getPreferredSize());
260   f.show();
261   }
262   }
263   < /pre>
264   < /blockquote>
265   *
266   * @version 1.23, 08/06/97
267   * @author Doug Stein
268   */
269/* END JSTYLED */
270public class GBLayout implements LayoutManager {
271
272    /**
273     * Determines the minimum widths for the grid columns.
274     */
275    public int columnWidths[];
276
277    /**
278     * Determines the minimum heights for the grid rows.
279     */
280    public int rowHeights[];
281
282    /**
283     * Determines the minimum weights for the grid columns.
284     */
285    public double columnWeights[];
286
287    /**
288     * Determines the minimum weights for the grid rows.
289     */
290    public double rowWeights[];
291
292    protected static final int INITGRIDSIZE = 16;
293    protected static final int MINSIZE = 1;
294    protected static final int PREFERREDSIZE = 2;
295    protected static final int TINYSIZE = 3;
296
297    protected Hashtable comptable;
298    protected GBConstraints defaultConstraints;
299    protected GBLayoutInfo layoutInfo;
300
301    protected int anchor;
302    protected int clipAnchor;
303
304    private static boolean layoutDisabled = false;
305    private static int disableCount = 0;
306    private static Insets windowInsets = new Insets(0, 0, 0, 0);
307
308    /**
309     * Globally enable gridbag layout.  The
310     * default is for gridbag layout to
311     * be enabled.
312     */
313    public synchronized static void enable() {
314        disableCount--;
315        if (disableCount <= 0)
316            layoutDisabled = false;
317    }
318
319    /**
320     * Globally disable gridbag layout.  This can be used to improve
321     * performance by temporarily disabling layout during
322     * spurious calls to validate.
323     */
324    public synchronized static void disable() {
325        disableCount++;
326        if (disableCount > 0)
327            layoutDisabled = true;
328    }
329
330    /**
331     * Set the window insets.  The window insets default to (0,0,0,0).
332     */
333    public synchronized static void setWindowInsets(Insets insets) {
334        if (insets == null)
335            windowInsets = new Insets(0, 0, 0, 0);
336        else
337            windowInsets = (Insets)insets.clone();
338    }
339
340    /**
341     * Get the window insets.
342     */
343    public synchronized static Insets getWindowInsets() {
344        return (Insets)windowInsets.clone();
345    }
346
347    /**
348     * Creates a gridbag layout.
349     */
350    public GBLayout() {
351        comptable = new Hashtable();
352        defaultConstraints = new GBConstraints();
353
354        anchor = GBConstraints.CENTER;
355        clipAnchor = GBConstraints.NORTHWEST;
356    }
357
358    /**
359     * Sets the constraints for the specified component.
360     * @param comp the component to be modified
361     * @param constraints the constraints to be applied
362     */
363    public void setConstraints(Component comp,
364			       GBConstraints constraints) {
365        GBConstraints c = (GBConstraints)constraints.clone();
366        if (c.insets == null)
367            c.insets = new Insets(0, 0, 0, 0);
368        if (c.hardinsets == null)
369            c.hardinsets = new Insets(0, 0, 0, 0);
370
371        comptable.put(comp, c);
372    }
373
374    /**
375     * Sets the constraints from an option string.
376     * Each option has the form key=value. Options are separated by
377     * semicolons (;).
378     * @param comp the component to be modified
379     * @param constraints the constraints string
380     */
381    public void setConstraints(Component comp, String constraints) {
382        if (constraints == null)
383            return;
384
385        comptable.put(comp, new GBConstraints(constraints));
386    }
387
388    /**
389     * Retrieves the constraints for the specified component.  A copy of
390     * the constraints is returned.
391     * @param comp the component to be queried
392     */
393    public GBConstraints getConstraints(Component comp) {
394        GBConstraints constraints = (GBConstraints)comptable.get(comp);
395        if (constraints == null) {
396            setConstraints(comp, defaultConstraints);
397            constraints = (GBConstraints)comptable.get(comp);
398        }
399        return (GBConstraints)constraints.clone();
400    }
401
402    /**
403     * Retrieves the constraints for the specified
404     * component.  The return
405     * value is not a copy, but is the actual constraints
406     * class used by the
407     * layout mechanism.
408     * @param comp the component to be queried
409     */
410    protected GBConstraints lookupConstraints(Component comp) {
411        GBConstraints constraints = (GBConstraints)comptable.get(comp);
412        if (constraints == null) {
413            setConstraints(comp, defaultConstraints);
414            constraints = (GBConstraints)comptable.get(comp);
415        }
416        return constraints;
417    }
418
419    /**
420     * Returns the coordinates of the upper-left corner of the grid.
421     * The coordinates are based on the current layout of the grid.
422     */
423    public Point getLayoutOrigin() {
424        Point origin = new Point(0, 0);
425        if (layoutInfo != null) {
426            origin.x = layoutInfo.startx;
427            origin.y = layoutInfo.starty;
428        }
429        return origin;
430    }
431
432    /**
433     * Returns the widths and heights of the grid columns and rows.
434     * The dimensions are based on the current layout of the grid.
435     */
436    public int [][] getLayoutDimensions() {
437        if (layoutInfo == null)
438            return new int[2][0];
439
440        int dim[][] = new int [2][];
441        dim[0] = new int[layoutInfo.width];
442        dim[1] = new int[layoutInfo.height];
443
444        System.arraycopy(layoutInfo.minWidth, 0, dim[0], 0,
445			 layoutInfo.width);
446        System.arraycopy(layoutInfo.minHeight, 0, dim[1], 0,
447			 layoutInfo.height);
448
449        return dim;
450    }
451
452    /**
453     * Returns the minimum widths and heights of the
454     * grid columns and rows.
455     * This is how the grid would be arranged if the parent were
456     * to be reshaped to its minimum size.
457     */
458    public int [][] getMinimumLayoutDimensions(Container parent) {
459        GBLayoutInfo info = GetLayoutInfo(parent, MINSIZE);
460        int dim[][] = new int[2][];
461        dim[0] = new int[info.width];
462        dim[1] = new int[info.height];
463
464        System.arraycopy(info.minWidth, 0, dim[0], 0, info.width);
465        System.arraycopy(info.minHeight, 0, dim[1], 0, info.height);
466
467        return dim;
468    }
469
470    /**
471     * Returns the preferred widths and heights of the
472     * grid columns and rows.
473     * This is how the grid would be arranged if the parent were
474     * to be reshaped to its preferred size.
475     */
476    public int [][] getPreferredLayoutDimensions(Container parent) {
477        GBLayoutInfo info = GetLayoutInfo(parent, PREFERREDSIZE);
478        int dim[][] = new int[2][];
479        dim[0] = new int[info.width];
480        dim[1] = new int[info.height];
481
482        System.arraycopy(info.minWidth, 0, dim[0], 0, info.width);
483        System.arraycopy(info.minHeight, 0, dim[1], 0, info.height);
484
485        return dim;
486    }
487    /* BEGIN JSTYLED */
488    /**
489     * Returns the current set of weights for the grid
490     * columns and rows.
491     * The return value reflects the effective weights for the columns
492     * and rows after taking into account the weight constraints that
493     * are set on the child components.
494     */
495    /* END JSTYLED */
496    public double [][] getLayoutWeights() {
497        if (layoutInfo == null)
498            return new double[2][0];
499
500        double weights[][] = new double [2][];
501        weights[0] = new double[layoutInfo.width];
502        weights[1] = new double[layoutInfo.height];
503
504        System.arraycopy(layoutInfo.weightX, 0, weights[0], 0,
505			 layoutInfo.width);
506        System.arraycopy(layoutInfo.weightY, 0, weights[1], 0,
507			 layoutInfo.height);
508
509        return weights;
510    }
511
512    /**
513     * Returns the coordinates of the grid cell corresponding
514     * to the given
515     * pixel coordinates.
516     */
517    public Point location(int x, int y) {
518        Point loc = new Point(0, 0);
519        int i, d;
520
521        if (layoutInfo == null)
522            return loc;
523
524        d = layoutInfo.startx;
525        for (i = 0; i < layoutInfo.width; i++) {
526            d += layoutInfo.minWidth[i];
527            if (d > x)
528                break;
529        }
530        loc.x = i;
531
532        d = layoutInfo.starty;
533        for (i = 0; i < layoutInfo.height; i++) {
534            d += layoutInfo.minHeight[i];
535            if (d > y)
536                break;
537        }
538        loc.y = i;
539
540        return loc;
541    }
542
543    /**
544     * Sets the anchor for the gridbag.  The anchor determines
545     * the placement
546     * for the child components when the container
547     * has extra space and none
548     * of the children have weights.  The default anchor is CENTER.
549     */
550    public void setAnchor(int anchor) {
551        this.anchor = anchor;
552    }
553
554    /**
555     * Returns the current anchor.
556     */
557    public int getAnchor() {
558        return anchor;
559    }
560
561    /**
562     * Sets the clip anchor.  The clip anchor determines
563     * which edge(s) of
564     * the container get clipped when there is not enough space.  The
565     * default clip anchor is NORTHWEST.  A clip anchor
566     * of NORTHWEST means
567     * that northwest corner is anchored, so the south
568     * and east edges will
569     * be clipped if there is not enough space.
570     */
571    public void setClipAnchor(int clipAnchor) {
572        this.clipAnchor = clipAnchor;
573    }
574
575    /**
576     * Returns the current clip anchor.
577     */
578    public int getClipAnchor() {
579        return clipAnchor;
580    }
581
582    /**
583     * If the parent is a Window, then adjust the insets according to
584     * the window insets.
585     */
586    private Insets getInsets(Container parent) {
587        Insets parentInsets = parent.insets();
588        Insets insets = null;
589        if (parentInsets != null) {
590            insets = (Insets) parentInsets.clone();
591        } else {
592            insets = new Insets(0, 0, 0, 0);
593        }
594        if (parent instanceof Window) {
595            insets.top += windowInsets.top;
596            insets.bottom += windowInsets.bottom;
597            insets.left += windowInsets.left;
598            insets.right += windowInsets.right;
599        }
600        return insets;
601    }
602
603    /**
604     * Adds the specified component with the specified
605     * name to the layout.
606     * The name is converted to a set of GBConstraints.
607     * @param name the constraints string
608     * @param comp the component to be added
609     */
610    public void addLayoutComponent(String name, Component comp) {
611        setConstraints(comp, name);
612    }
613
614    /**
615     * Removes the specified component from the layout. Does not apply.
616     * @param comp the component to be removed
617     */
618    public void removeLayoutComponent(Component comp) {
619    }
620
621    /**
622     * Returns the preferred dimensions for this layout
623     * given the components
624     * in the specified panel.
625     * @param parent the component which needs to be laid out
626     * @see #minimumLayoutSize
627     */
628    public Dimension preferredLayoutSize(Container parent) {
629        GBLayoutInfo info = GetLayoutInfo(parent, PREFERREDSIZE);
630        return GetMinSize(parent, info);
631    }
632
633    /**
634     * Returns the minimum dimensions needed to layout the components
635     * contained in the specified panel.
636     * @param parent the component which needs to be laid out
637     * @see #preferredLayoutSize
638     */
639    public Dimension minimumLayoutSize(Container parent) {
640        GBLayoutInfo info = GetLayoutInfo(parent, MINSIZE);
641        return GetMinSize(parent, info);
642    }
643
644    /**
645     * Returns the smallest allowable size for the specified panel.
646     * This can be smaller than getMinimumSize if there are insets and
647     * pads set on any of the panel's children.
648     * @param parent the component which needs to be laid out
649     * @see #preferredLayoutSize
650     */
651    public Dimension tinyLayoutSize(Container parent) {
652        GBLayoutInfo info = GetLayoutInfo(parent, TINYSIZE);
653        return GetMinSize(parent, info);
654    }
655
656    /**
657     * Lays out the container in the specified panel.
658     * @param parent the specified component being laid out
659     * @see Container
660     */
661    public void layoutContainer(Container parent) {
662        if (!layoutDisabled)
663            ArrangeGrid(parent, true);
664    }
665
666    /**
667     * Does everything that layout normally does, except the components
668     * aren't actually reshaped.  This has the useful side effect of
669     * setting the location and size variables in the constraints
670     * for each component.
671     * @param parent the specified component being laid out
672     * @see Container
673     */
674    public void layoutContainerNoReshape(Container parent) {
675        if (!layoutDisabled)
676            ArrangeGrid(parent, false);
677    }
678
679    /**
680     * Returns the String representation of this GBLayout's values.
681     */
682    public String toString() {
683        return getClass().getName();
684    }
685    /* BEGIN JSTYLED */
686    /**
687     * Print the layout information.  Useful for debugging.
688     */
689
690    /* DEBUG
691     *
692     *  protected void DumpLayoutInfo(GBLayoutInfo s) {
693     *    int x;
694     *
695     *    System.out.println("Col\tWidth\tWeight");
696     *    for (x=0; x<s.width; x++) {
697     *      System.out.println(x + "\t" +
698     *			 s.minWidth[x] + "\t" +
699     *			 s.weightX[x]);
700     *    }
701     *    System.out.println("Row\tHeight\tWeight");
702     *    for (x=0; x<s.height; x++) {
703     *      System.out.println(x + "\t" +
704     *			 s.minHeight[x] + "\t" +
705     *			 s.weightY[x]);
706     *    }
707     *  }
708     */
709
710    /**
711     * Print the layout constraints.  Useful for debugging.
712     */
713
714    /* DEBUG
715     *
716     *  protected void DumpConstraints(GBConstraints constraints) {
717     *    System.out.println(
718     *		       "wt " +
719     *		       constraints.weightx +
720     *		       " " +
721     *		       constraints.weighty +
722     *		       ", " +
723     *
724     *		       "box " +
725     *		       constraints.gridx +
726     *		       " " +
727     *		       constraints.gridy +
728     *		       " " +
729     *		       constraints.gridwidth +
730     *		       " " +
731     *		       constraints.gridheight +
732     *		       ", " +
733     *
734     *		       "min " +
735     *		       constraints.minWidth +
736     *		       " " +
737     *		       constraints.minHeight +
738     *		       ", " +
739     *
740     *		       "pad " +
741     *		       constraints.insets.bottom +
742     *		       " " +
743     *		       constraints.insets.left +
744     *		       " " +
745     *		       constraints.insets.right +
746     *		       " " +
747     *		       constraints.insets.top +
748     *		       " " +
749     *		       constraints.ipadx +
750     *		       " " +
751     *		       constraints.ipady);
752     *  }
753     */
754
755    /**
756     * Fill in an instance of the GBLayoutInfo structure for the
757     * current set of managed children.  This requires four passes
758     * through the child components:
759     *<pre>
760     * 1) Figure out the dimensions of the layout grid.
761     * 2) Determine which cells the components occupy.
762     * 3) Distribute the weights among the rows/columns.
763     * 4) Distribute the minimum sizes among the rows/columns.
764     *</pre>
765     * This also caches the minsizes for all the children when they are
766     * first encountered (so subsequent loops don't need to ask again).
767     */
768
769    /* END JSTYLED */
770    protected GBLayoutInfo GetLayoutInfo(Container parent,
771					 int sizeflag) {
772        Component comp;
773        GBConstraints constraints;
774        Dimension d;
775        Component components[] = parent.getComponents();
776
777        int compindex, width, height, i, j, k, px, py;
778        int limit, pixels_diff, nextSize;
779        int curX, curY, curWidth, curHeight, curRow, curCol;
780        double weight_diff, weight, start, size;
781        int xMax[], yMax[];
782
783	/* BEGIN JSTYLED */
784	/*
785	 * Pass #1
786	 *
787	 * Figure out the dimensions of the layout
788	 * grid (use a value of 1 for
789	 * zero or negative widths and heights).
790	 */
791	/* END JSTYLED */
792
793        width = height = 0;
794        curRow = curCol = -1;
795        xMax = new int[INITGRIDSIZE];
796        yMax = new int[INITGRIDSIZE];
797
798        for (compindex = 0; compindex < components.length; compindex++) {
799            comp = components[compindex];
800            if (!comp.isVisible())
801                continue;
802            constraints = lookupConstraints(comp);
803
804            curX = constraints.gridx;
805            curY = constraints.gridy;
806            curWidth = constraints.gridwidth;
807            if (curWidth <= 0)
808                curWidth = 1;
809            curHeight = constraints.gridheight;
810            if (curHeight <= 0)
811                curHeight = 1;
812
813            /* If x or y is negative, then use relative positioning: */
814            if (curX < 0 && curY < 0) {
815                if (curRow >= 0)
816                    curY = curRow;
817                else if (curCol >= 0)
818                    curX = curCol;
819                else
820                    curY = 0;
821            }
822            if (curX < 0) {
823                px = 0;
824                limit = curY + curHeight;
825                xMax = ensureCapacity(xMax, limit);
826                for (i = curY; i < limit; i++)
827                    px = Math.max(px, xMax[i]);
828
829                curX = px - curX - 1;
830                if (curX < 0)
831                    curX = 0;
832            } else if (curY < 0) {
833                py = 0;
834                limit = curX + curWidth;
835                yMax = ensureCapacity(yMax, limit);
836                for (i = curX; i < limit; i++)
837                    py = Math.max(py, yMax[i]);
838
839                curY = py - curY - 1;
840                if (curY < 0)
841                    curY = 0;
842            }
843
844            /* Adjust the grid width and height */
845            for (px = curX + curWidth; width < px; width++);
846            for (py = curY + curHeight; height < py; height++);
847
848            /* Adjust the xMax and yMax arrays */
849            yMax = ensureCapacity(yMax, px);
850            xMax = ensureCapacity(xMax, py);
851            for (i = curX; i < px; i++) { yMax[i] = py; }
852            for (i = curY; i < py; i++) { xMax[i] = px; }
853
854            /* Cache the current slave's size. */
855            if (sizeflag == TINYSIZE) {
856                if (comp instanceof Container) {
857                    Container cntr = (Container)comp;
858                    if (cntr.getLayout() instanceof GBLayout)
859                        d = ((GBLayout)cntr.getLayout()).tinyLayoutSize(cntr);
860                    else
861                        d = comp.getMinimumSize();
862                }
863                else
864                    d = comp.getMinimumSize();
865
866                constraints.tinyWidth = d.width;
867                constraints.tinyHeight = d.height;
868
869                if (constraints.shrinkx)
870                    constraints.tinyWidth = 0;
871                if (constraints.shrinky)
872                    constraints.tinyHeight = 0;
873
874                if (constraints.minsize == null) {
875                    d = comp.getMinimumSize();
876                    constraints.minsize = new Dimension(d.width,
877							d.height);
878                }
879            } else {
880                if (sizeflag == PREFERREDSIZE) {
881                    d = comp.getPreferredSize();
882                    if (d.width <= 1 && d.height <= 1) {
883                        // If the preferred size is not reasonable
884                        // then try the minumum size
885                        d = comp.getMinimumSize();
886                        if (d.width <= 1 && d.height <= 1) {
887                            // Both preferred and minimun size
888                            // are small so use the actual size
889                            // that was set for the component.
890                            d = comp.getSize();
891                        }
892                    }
893                    constraints.minsize = new Dimension(d.width,
894							d.height);
895                } else {
896                    d = comp.getMinimumSize();
897                    // If the component is less than 1,1 minumum
898                    // size then
899                    // use getPreferredSize instead. This is
900                    // a workaround for
901                    // Beans that do not have getMinimumSize
902                    // implemented.
903                    if (d.width <= 1 && d.height <= 1) {
904                        d = comp.getPreferredSize();
905                        if (d.width <= 1 && d.height <= 1) {
906                            d = comp.getSize();
907                        }
908                    }
909                    constraints.minsize = new Dimension(d.width,
910							d.height);
911                }
912            }
913	    /* BEGIN JSTYLED */
914	    /*
915	     * Zero width and height must mean that this is
916	     * the last item (or
917	     * else something is wrong).
918	     */
919	    if (constraints.gridheight == 0 &&
920		constraints.gridwidth == 0)
921		curRow = curCol = -1;
922
923	    /* Zero width starts a new row */
924	    if (constraints.gridheight == 0 && curRow < 0)
925		curCol = curX + curWidth;
926
927	    /* Zero height starts a new column */
928	    else if (constraints.gridwidth == 0 && curCol < 0)
929		curRow = curY + curHeight;
930	}
931
932	/*
933	 * Apply minimum row/column dimensions
934	 */
935	/* END JSTYLED */
936	if (columnWidths != null && width < columnWidths.length)
937	    width = columnWidths.length;
938	if (rowHeights != null && height < rowHeights.length)
939	    height = rowHeights.length;
940
941	GBLayoutInfo r = new GBLayoutInfo(width, height);
942
943	/*
944	 * Pass #2
945	 *
946	 * Negative values for gridX are filled in with
947	 * the current x value.
948	 * Negative values for gridY are filled in with
949	 * the current y value.
950	 * Negative or zero values for gridWidth and
951	 * gridHeight end the current
952	 * row or column, respectively.
953	 *
954	 * Pass #1 figures out the grid dimensions.
955	 * Pass #2 replaces the
956	 * negative and zero values for gridWidth and gridHeight with
957	 * real values that are based on the grid dimensions determined
958	 * in pass #1.
959	 */
960
961	curRow = curCol = -1;
962	xMax = new int[height];
963	yMax = new int[width];
964
965	for (compindex = 0; compindex < components.length;
966	    compindex++) {
967	    comp = components[compindex];
968	    if (!comp.isVisible())
969		continue;
970	    constraints = lookupConstraints(comp);
971
972	    curX = constraints.gridx;
973	    curY = constraints.gridy;
974	    curWidth = constraints.gridwidth;
975	    curHeight = constraints.gridheight;
976
977	    /* If x or y is negative, then use relative positioning: */
978	    if (curX < 0 && curY < 0) {
979		if (curRow >= 0)
980		    curY = curRow;
981		else if (curCol >= 0)
982		    curX = curCol;
983		else
984		    curY = 0;
985	    }
986
987	    if (curX < 0) {
988		if (curHeight <= 0) {
989		    curHeight += r.height - curY;
990		    if (curHeight < 1)
991			curHeight = 1;
992		}
993
994		px = 0;
995		for (i = curY; i < (curY + curHeight); i++)
996		    px = Math.max(px, xMax[i]);
997
998		curX = px - curX - 1;
999		if (curX < 0)
1000		    curX = 0;
1001	    } else if (curY < 0) {
1002		if (curWidth <= 0) {
1003		    curWidth += r.width - curX;
1004		    if (curWidth < 1)
1005			curWidth = 1;
1006		}
1007
1008		py = 0;
1009		for (i = curX; i < (curX + curWidth); i++)
1010		    py = Math.max(py, yMax[i]);
1011
1012		curY = py - curY - 1;
1013		if (curY < 0)
1014		    curY = 0;
1015	    }
1016
1017	    if (curWidth <= 0) {
1018		curWidth += r.width - curX;
1019		if (curWidth < 1)
1020		    curWidth = 1;
1021	    }
1022
1023	    if (curHeight <= 0) {
1024		curHeight += r.height - curY;
1025		if (curHeight < 1)
1026		    curHeight = 1;
1027	    }
1028
1029	    px = curX + curWidth;
1030	    py = curY + curHeight;
1031
1032	    for (i = curX; i < px; i++) { yMax[i] = py; }
1033	    for (i = curY; i < py; i++) { xMax[i] = px; }
1034
1035	    /* Make negative sizes start a new row/column */
1036	    if (constraints.gridheight == 0 &&
1037                constraints.gridwidth == 0)
1038                curRow = curCol = -1;
1039	    if (constraints.gridheight == 0 && curRow < 0)
1040		curCol = curX + curWidth;
1041	    else if (constraints.gridwidth == 0 && curCol < 0)
1042		curRow = curY + curHeight;
1043
1044	    /* Assign the new values to the gridbag slave */
1045	    constraints.tempX = curX;
1046	    constraints.tempY = curY;
1047	    constraints.tempWidth = curWidth;
1048	    constraints.tempHeight = curHeight;
1049	}
1050
1051	/*
1052	 * Apply row/column weights.
1053	 */
1054
1055	if (columnWeights != null)
1056	    System.arraycopy(columnWeights, 0, r.weightX, 0,
1057			     Math.min(columnWeights.length, r.weightX.length));
1058	if (rowWeights != null)
1059	    System.arraycopy(rowWeights, 0, r.weightY, 0,
1060			     Math.min(rowWeights.length, r.weightY.length));
1061
1062	/*
1063	 * Pass #3
1064	 *
1065	 * Distribute the weights.
1066	 */
1067
1068	nextSize = Integer.MAX_VALUE;
1069
1070	for (i = 1;
1071	    i != Integer.MAX_VALUE;
1072	    i = nextSize, nextSize = Integer.MAX_VALUE) {
1073	    for (compindex = 0; compindex < components.length;
1074		 compindex++) {
1075		comp = components[compindex];
1076		if (!comp.isVisible())
1077		    continue;
1078		constraints = lookupConstraints(comp);
1079
1080		if (constraints.tempWidth == i) {
1081		    px = constraints.tempX + constraints.tempWidth;
1082		    /* right column */
1083
1084		    /*
1085		     * Figure out if we should use this slave\'s
1086		     * weight.  If the weight
1087		     * is less than the total weight spanned
1088		     * by the width of the cell,
1089		     * then discard the weight.  Otherwise
1090		     * split the difference
1091		     * according to the existing weights.
1092		     */
1093
1094		    weight_diff = constraints.weightx;
1095		    for (k = constraints.tempX; k < px; k++)
1096			weight_diff -= r.weightX[k];
1097		    if (weight_diff > 0.0) {
1098			weight = 0.0;
1099			for (k = constraints.tempX; k < px; k++)
1100			    weight += r.weightX[k];
1101			for (k = constraints.tempX; weight > 0.0
1102				 && k < px; k++) {
1103			    double wt = r.weightX[k];
1104			    double dx = (wt * weight_diff) / weight;
1105			    r.weightX[k] += dx;
1106			    weight_diff -= dx;
1107			    weight -= wt;
1108			}
1109				/* BEGIN JSTYLED */
1110                                /* Assign the remainder to the
1111				 * rightmost cell */
1112				/* END JSTYLED */
1113			r.weightX[px-1] += weight_diff;
1114		    }
1115		} else if (constraints.tempWidth > i &&
1116			   constraints.tempWidth < nextSize)
1117                    nextSize = constraints.tempWidth;
1118
1119
1120		if (constraints.tempHeight == i) {
1121		    py = constraints.tempY + constraints.tempHeight;
1122		    /* bottom row */
1123
1124		    /*
1125		     * Figure out if we should use this slave\'s
1126		     * weight.  If the weight
1127		     * is less than the total weight spanned by
1128		     * the height of the cell,
1129		     * then discard the weight.  Otherwise split
1130		     * it the difference
1131		     * according to the existing weights.
1132		     */
1133
1134		    weight_diff = constraints.weighty;
1135		    for (k = constraints.tempY; k < py; k++)
1136			weight_diff -= r.weightY[k];
1137		    if (weight_diff > 0.0) {
1138			weight = 0.0;
1139			for (k = constraints.tempY; k < py; k++)
1140			    weight += r.weightY[k];
1141			for (k = constraints.tempY; weight > 0.0
1142				 && k < py; k++) {
1143			    double wt = r.weightY[k];
1144			    double dy = (wt * weight_diff) / weight;
1145			    r.weightY[k] += dy;
1146			    weight_diff -= dy;
1147			    weight -= wt;
1148			}
1149			/* Assign the remainder to the bottom cell */
1150			r.weightY[py-1] += weight_diff;
1151		    }
1152		} else if (constraints.tempHeight > i &&
1153			   constraints.tempHeight < nextSize)
1154                    nextSize = constraints.tempHeight;
1155	    }
1156	}
1157
1158	/*
1159	 * Apply minimum row/column widths.
1160	 */
1161
1162	if (sizeflag == TINYSIZE) {
1163	    if (columnWidths != null) {
1164		for (i = 0; i < columnWidths.length; i++) {
1165		    if (r.weightX[i] == 0)
1166			r.minWidth[i] = columnWidths[i];
1167		}
1168	    }
1169	    if (rowHeights != null) {
1170		for (i = 0; i < rowHeights.length; i++) {
1171		    if (r.weightY[i] == 0)
1172			r.minHeight[i] = rowHeights[i];
1173		}
1174	    }
1175	} else {
1176	    if (columnWidths != null)
1177		System.arraycopy(columnWidths, 0, r.minWidth, 0,
1178				 columnWidths.length);
1179	    if (rowHeights != null)
1180		System.arraycopy(rowHeights, 0, r.minHeight, 0,
1181				 rowHeights.length);
1182	}
1183
1184	/*
1185	 * Pass #4
1186	 *
1187	 * Distribute the minimum widths.
1188	 */
1189
1190	nextSize = Integer.MAX_VALUE;
1191
1192	for (i = 1;
1193	    i != Integer.MAX_VALUE;
1194	    i = nextSize, nextSize = Integer.MAX_VALUE) {
1195	    for (compindex = 0; compindex < components.length;
1196		 compindex++) {
1197		comp = components[compindex];
1198		if (!comp.isVisible())
1199		    continue;
1200		constraints = lookupConstraints(comp);
1201
1202		if (constraints.tempWidth == i) {
1203		    px = constraints.tempX + constraints.tempWidth;
1204		    /* right column */
1205
1206		    /*
1207		     * Calculate the minWidth array values.
1208		     * First, figure out how wide the current
1209		     * slave needs to be.
1210		     * Then, see if it will fit within the
1211		     * current minWidth values.
1212		     * If it will not fit, add the difference
1213		     * according to the
1214		     * weightX array.
1215		     */
1216
1217		    if (sizeflag == TINYSIZE && hasWeightX(r,
1218							   constraints)) {
1219			pixels_diff = constraints.tinyWidth
1220                            + constraints.hardipadx +
1221                            constraints.hardinsets.left +
1222                            constraints.hardinsets.right;
1223		    } else {
1224			pixels_diff = constraints.minsize.width +
1225                            constraints.ipadx + constraints.hardipadx +
1226                            constraints.insets.left +
1227                            constraints.insets.right +
1228                            constraints.hardinsets.left +
1229                            constraints.hardinsets.right;
1230		    }
1231
1232		    for (k = constraints.tempX; k < px; k++)
1233			pixels_diff -= r.minWidth[k];
1234		    if (pixels_diff > 0) {
1235			weight = 0.0;
1236			for (k = constraints.tempX; k < px; k++)
1237			    weight += r.weightX[k];
1238			for (k = constraints.tempX; weight > 0.0 &&
1239				 k < px; k++) {
1240			    double wt = r.weightX[k];
1241			    int dx = (int)((wt * ((double)
1242						  pixels_diff)) / weight);
1243			    r.minWidth[k] += dx;
1244			    pixels_diff -= dx;
1245			    weight -= wt;
1246			}
1247
1248			/* Any leftovers are evenly distributed */
1249			int dx = pixels_diff/(px-constraints.tempX);
1250			for (k = constraints.tempX; k < (px-1); k++) {
1251			    r.minWidth[k] += dx;
1252			    pixels_diff -= dx;
1253			}
1254			r.minWidth[px-1] += pixels_diff;
1255		    }
1256		} else if (constraints.tempWidth > i &&
1257			   constraints.tempWidth < nextSize)
1258                    nextSize = constraints.tempWidth;
1259
1260
1261		if (constraints.tempHeight == i) {
1262		    py = constraints.tempY + constraints.tempHeight;
1263		    /* bottom row */
1264
1265		    /*
1266		     * Calculate the minHeight array values.
1267		     * First, figure out how tall the current
1268		     * slave needs to be.
1269		     * Then, see if it will fit within the
1270		     * current minHeight values.
1271		     * If it will not fit, add the difference
1272		     * according to the
1273		     * weightY array.
1274		     */
1275
1276		    if (sizeflag == TINYSIZE && hasWeightY(r,
1277							   constraints)) {
1278			pixels_diff = constraints.tinyHeight +
1279                            constraints.hardipady +
1280                            constraints.hardinsets.top +
1281                            constraints.hardinsets.bottom;
1282		    } else {
1283			pixels_diff = constraints.minsize.height +
1284                            constraints.ipady + constraints.hardipady +
1285                            constraints.insets.top +
1286                            constraints.insets.bottom +
1287                            constraints.hardinsets.top +
1288                            constraints.hardinsets.bottom;
1289		    }
1290
1291		    for (k = constraints.tempY; k < py; k++)
1292			pixels_diff -= r.minHeight[k];
1293		    if (pixels_diff > 0) {
1294			weight = 0.0;
1295			for (k = constraints.tempY; k < py; k++)
1296			    weight += r.weightY[k];
1297			for (k = constraints.tempY; weight > 0.0 &&
1298				 k < py; k++) {
1299			    double wt = r.weightY[k];
1300			    int dy = (int)((wt * ((double)pixels_diff))
1301					   / weight);
1302			    r.minHeight[k] += dy;
1303			    pixels_diff -= dy;
1304			    weight -= wt;
1305			}
1306
1307			/* Any leftovers are evenly distributed */
1308			int dy = pixels_diff/(py-constraints.tempY);
1309			for (k = constraints.tempY; k < (py-1); k++) {
1310			    r.minHeight[k] += dy;
1311			    pixels_diff -= dy;
1312			}
1313			r.minHeight[py-1] += pixels_diff;
1314		    }
1315		} else if (constraints.tempHeight > i &&
1316			   constraints.tempHeight < nextSize)
1317                    nextSize = constraints.tempHeight;
1318	    }
1319	}
1320
1321	return r;
1322    }
1323
1324    private int[] ensureCapacity(int arr[], int size) {
1325	if (arr.length < size) {
1326	    int newSize = arr.length * 2;
1327	    if (newSize == 0)
1328		newSize = 1;
1329	    while (newSize < size)
1330		newSize = newSize * 2;
1331
1332	    int newArr[] = new int[newSize];
1333	    System.arraycopy(arr, 0, newArr, 0, arr.length);
1334	    arr = newArr;
1335	}
1336
1337	return arr;
1338    }
1339
1340    private boolean hasWeightX(GBLayoutInfo r, GBConstraints c) {
1341	int gx = c.tempX + c.tempWidth;
1342	for (int i = c.tempX; i < gx; i++) {
1343	    if (r.weightX[i] != 0)
1344		return true;
1345	}
1346	return false;
1347    }
1348
1349    private boolean hasWeightY(GBLayoutInfo r, GBConstraints c) {
1350	int gy = c.tempY + c.tempHeight;
1351	for (int i = c.tempY; i < gy; i++) {
1352	    if (r.weightY[i] != 0)
1353		return true;
1354	}
1355	return false;
1356    }
1357
1358    /**
1359     * Adjusts the x, y, width, and height fields to the correct
1360     * values according to the constraint geometry and pads.
1361     */
1362    protected void AdjustForGravity(GBConstraints c, Rectangle r) {
1363	int diffx, diffy, w, h;
1364	Insets insets = (Insets)c.insets.clone();
1365
1366	w = r.width -
1367            (insets.left + insets.right + c.hardinsets.left +
1368	    c.hardinsets.right);
1369	h = r.height -
1370            (insets.top + insets.bottom + c.hardinsets.top +
1371	    c.hardinsets.bottom);
1372
1373	if (w < c.tinyWidth) {
1374	    if (c.fill == GBConstraints.HORIZONTAL ||
1375                c.fill == GBConstraints.BOTH) {
1376		diffx = c.tinyWidth - w;
1377		insets.left -= diffx/2;
1378		insets.right -= diffx/2;
1379		if (insets.left < 0) {
1380		    insets.right += insets.left;
1381		    insets.left = 0;
1382		}
1383		if (insets.right < 0) {
1384		    insets.left += insets.right;
1385		    insets.right = 0;
1386		}
1387	    } else {
1388		switch (c.anchor) {
1389		case GBConstraints.NORTH:
1390		case GBConstraints.SOUTH:
1391		case GBConstraints.CENTER:
1392		    diffx = c.tinyWidth - w;
1393		    insets.left -= diffx/2;
1394		    insets.right -= diffx/2;
1395		    if (insets.left < 0) {
1396			insets.right += insets.left;
1397			insets.left = 0;
1398		    }
1399		    if (insets.right < 0) {
1400			insets.left += insets.right;
1401			insets.right = 0;
1402		    }
1403		    break;
1404
1405		case GBConstraints.NORTHWEST:
1406		case GBConstraints.SOUTHWEST:
1407		case GBConstraints.WEST:
1408		    diffx = c.tinyWidth - w;
1409		    insets.right -= diffx;
1410		    if (insets.right < 0) {
1411			insets.left += insets.right;
1412			insets.right = 0;
1413		    }
1414		    break;
1415
1416		case GBConstraints.NORTHEAST:
1417		case GBConstraints.SOUTHEAST:
1418		case GBConstraints.EAST:
1419		    diffx = c.tinyWidth - w;
1420		    insets.left -= diffx;
1421		    if (insets.left < 0) {
1422			insets.right += insets.left;
1423			insets.left = 0;
1424		    }
1425		    break;
1426		default:
1427		    /* JSTYLED */
1428		    throw new IllegalArgumentException(Global.getMsg("sunsoft.jws.visual.rt.awt.GBLayout.illegal__anchor__value.4"));
1429		}
1430	    }
1431	}
1432
1433	if (h < c.tinyHeight) {
1434	    if (c.fill == GBConstraints.VERTICAL ||
1435                c.fill == GBConstraints.BOTH) {
1436		diffy = c.tinyHeight - h;
1437		insets.top -= diffy/2;
1438		insets.bottom -= diffy/2;
1439		if (insets.top < 0) {
1440		    insets.bottom += insets.top;
1441		    insets.top = 0;
1442		}
1443		if (insets.bottom < 0) {
1444		    insets.top += insets.bottom;
1445		    insets.bottom = 0;
1446		}
1447	    } else {
1448		switch (c.anchor) {
1449		case GBConstraints.WEST:
1450		case GBConstraints.EAST:
1451		case GBConstraints.CENTER:
1452		    diffy = c.tinyHeight - h;
1453		    insets.top -= diffy/2;
1454		    insets.bottom -= diffy/2;
1455		    if (insets.top < 0) {
1456			insets.bottom += insets.top;
1457			insets.top = 0;
1458		    }
1459		    if (insets.bottom < 0) {
1460			insets.top += insets.bottom;
1461			insets.bottom = 0;
1462		    }
1463		    break;
1464
1465		case GBConstraints.NORTHWEST:
1466		case GBConstraints.NORTHEAST:
1467		case GBConstraints.NORTH:
1468		    diffy = c.tinyHeight - h;
1469		    insets.bottom -= diffy;
1470		    if (insets.bottom < 0) {
1471			insets.top += insets.bottom;
1472			insets.bottom = 0;
1473		    }
1474		    break;
1475
1476		case GBConstraints.SOUTHWEST:
1477		case GBConstraints.SOUTHEAST:
1478		case GBConstraints.SOUTH:
1479		    diffy = c.tinyHeight - h;
1480		    insets.top -= diffy;
1481		    if (insets.top < 0) {
1482			insets.bottom += insets.top;
1483			insets.top = 0;
1484		    }
1485		    break;
1486		default:
1487		    /* JSTYLED */
1488		    throw new IllegalArgumentException(Global.getMsg("sunsoft.jws.visual.rt.awt.GBLayout.illegal__anchor__value.4"));
1489		}
1490	    }
1491	}
1492
1493	r.x += insets.left + c.hardinsets.left;
1494	r.width -= (insets.left + insets.right +
1495		    c.hardinsets.left + c.hardinsets.right);
1496	r.y += insets.top + c.hardinsets.top;
1497	r.height -= (insets.top + insets.bottom +
1498		     c.hardinsets.top + c.hardinsets.bottom);
1499
1500	diffx = 0;
1501	if ((c.fill != GBConstraints.HORIZONTAL &&
1502	    c.fill != GBConstraints.BOTH)
1503            && (r.width > (c.minsize.width + c.ipadx + c.hardipadx))) {
1504	    diffx = r.width - (c.minsize.width + c.ipadx +
1505			       c.hardipadx);
1506	    r.width = c.minsize.width + c.ipadx + c.hardipadx;
1507	}
1508
1509	diffy = 0;
1510	if ((c.fill != GBConstraints.VERTICAL &&
1511	    c.fill != GBConstraints.BOTH)
1512            && (r.height > (c.minsize.height + c.ipady + c.hardipady))) {
1513	    diffy = r.height - (c.minsize.height + c.ipady +
1514				c.hardipady);
1515	    r.height = c.minsize.height + c.ipady + c.hardipady;
1516	}
1517
1518	switch (c.anchor) {
1519	case GBConstraints.CENTER:
1520	    r.x += diffx/2;
1521	    r.y += diffy/2;
1522	    break;
1523	case GBConstraints.NORTH:
1524	    r.x += diffx/2;
1525	    break;
1526	case GBConstraints.NORTHEAST:
1527	    r.x += diffx;
1528	    break;
1529	case GBConstraints.EAST:
1530	    r.x += diffx;
1531	    r.y += diffy/2;
1532	    break;
1533	case GBConstraints.SOUTHEAST:
1534	    r.x += diffx;
1535	    r.y += diffy;
1536	    break;
1537	case GBConstraints.SOUTH:
1538	    r.x += diffx/2;
1539	    r.y += diffy;
1540	    break;
1541	case GBConstraints.SOUTHWEST:
1542	    r.y += diffy;
1543	    break;
1544	case GBConstraints.WEST:
1545	    r.y += diffy/2;
1546	    break;
1547	case GBConstraints.NORTHWEST:
1548	    break;
1549	default:
1550	    /* JSTYLED */
1551	    throw new IllegalArgumentException(Global.getMsg("sunsoft.jws.visual.rt.awt.GBLayout.illegal__anchor__value.5"));
1552	}
1553    }
1554
1555    /**
1556     * Figure out the minimum size of the
1557     * parent based on the information retrieved from GetLayoutInfo.
1558     */
1559    protected Dimension GetMinSize(Container parent,
1560				   GBLayoutInfo info) {
1561	Dimension d = new Dimension();
1562	int i, t;
1563	Insets insets = getInsets(parent);
1564
1565	t = 0;
1566	for (i = 0; i < info.width; i++)
1567	    t += info.minWidth[i];
1568	d.width = t + insets.left + insets.right;
1569
1570	t = 0;
1571	for (i = 0; i < info.height; i++)
1572	    t += info.minHeight[i];
1573	d.height = t + insets.top + insets.bottom;
1574
1575	return d;
1576    }
1577
1578    /**
1579     * Lays out the grid.  Called directly from layoutContainer.
1580     */
1581    protected void ArrangeGrid(Container parent) {
1582	ArrangeGrid(parent, true);
1583    }
1584
1585    /**
1586     * Lays out the grid, conditionally reshaping the children.
1587     * The doReshape flag indicates whether or not
1588     * the children should be reshaped.
1589     *
1590     * @see layoutContainerNoReshape
1591     */
1592    protected void ArrangeGrid(Container parent, boolean doReshape) {
1593	Component comp;
1594	int compindex;
1595	GBConstraints constraints;
1596	Insets insets = getInsets(parent);
1597	Component components[] = parent.getComponents();
1598	Dimension d;
1599	Rectangle r = new Rectangle();
1600	int i, diffw, diffh;
1601	double weight;
1602	GBLayoutInfo info, tinyinfo;
1603
1604	/*
1605	 * If the parent has no slaves anymore, then don't do anything
1606	 * at all:  just leave the parent's size as-is.
1607	 */
1608	if (components.length == 0 &&
1609            (columnWidths == null || columnWidths.length == 0) &&
1610            (rowHeights == null || rowHeights.length == 0)) {
1611	    return;
1612	}
1613
1614	/*
1615	 * Pass #1: scan all the slaves to figure out the total amount
1616	 * of space needed.
1617	 */
1618
1619	info = GetLayoutInfo(parent, PREFERREDSIZE);
1620	d = GetMinSize(parent, info);
1621
1622	Dimension parentSize = parent.getSize();
1623
1624	if (d.width > parentSize.width || d.height >
1625            parentSize.height) {
1626	    info = GetLayoutInfo(parent, MINSIZE);
1627	    d = GetMinSize(parent, info);
1628	}
1629
1630	tinyinfo = GetLayoutInfo(parent, TINYSIZE);
1631
1632	layoutInfo = info;
1633	r.width = d.width;
1634	r.height = d.height;
1635
1636	/* BEGIN JSTYLED */
1637	/*
1638	 * DEBUG
1639	 *
1640	 * DumpLayoutInfo(info);
1641	 * for (compindex = 0 ; compindex < components.length ; compindex++) {
1642	 * comp = components[compindex];
1643	 * if (!comp.isVisible())
1644	 *	continue;
1645	 * constraints = lookupConstraints(comp);
1646	 * DumpConstraints(constraints);
1647	 * }
1648	 * System.out.println("minSize " + r.width + " " + r.height);
1649	 */
1650
1651	/*
1652	 * If the current dimensions of the window don't match the desired
1653	 * dimensions, then adjust the minWidth and minHeight arrays
1654	 * according to the weights.
1655	 */
1656
1657	/* END JSTYLED */
1658
1659	diffw = parentSize.width - r.width;
1660	if (diffw != 0) {
1661	    weight = 0.0;
1662	    for (i = 0; i < info.width; i++)
1663		weight += info.weightX[i];
1664	    if (weight > 0.0) {
1665		for (i = 0; i < info.width; i++) {
1666		    int dx = (int)((((double)diffw) *
1667				    info.weightX[i]) / weight);
1668		    info.minWidth[i] += dx;
1669		    r.width += dx;
1670		    if (info.minWidth[i] < tinyinfo.minWidth[i]) {
1671			r.width += tinyinfo.minWidth[i] -
1672                            info.minWidth[i];
1673			info.minWidth[i] = tinyinfo.minWidth[i];
1674		    }
1675		}
1676	    }
1677	    diffw = parentSize.width - r.width;
1678	} else {
1679	    diffw = 0;
1680	}
1681
1682	diffh = parentSize.height - r.height;
1683	if (diffh != 0) {
1684	    weight = 0.0;
1685	    for (i = 0; i < info.height; i++)
1686		weight += info.weightY[i];
1687	    if (weight > 0.0) {
1688		for (i = 0; i < info.height; i++) {
1689		    int dy = (int)((((double)diffh) *
1690				    info.weightY[i]) / weight);
1691		    info.minHeight[i] += dy;
1692		    r.height += dy;
1693		    if (info.minHeight[i] < tinyinfo.minHeight[i]) {
1694			r.height += tinyinfo.minHeight[i] -
1695                            info.minHeight[i];
1696			info.minHeight[i] = tinyinfo.minHeight[i];
1697		    }
1698		}
1699	    }
1700	    diffh = parentSize.height - r.height;
1701	} else {
1702	    diffh = 0;
1703	}
1704
1705	/*
1706	 * DEBUG
1707	 *
1708	 * System.out.println("Re-adjusted:");
1709	 * DumpLayoutInfo(info);
1710	 */
1711
1712	/*
1713	 * Now do the actual layout of the slaves
1714	 * using the layout information
1715	 * that has been collected.
1716	 */
1717
1718	int anchorx = anchor;
1719	int anchory = anchor;
1720
1721	if (diffw < 0)
1722	    anchorx = clipAnchor;
1723	if (diffh < 0)
1724	    anchory = clipAnchor;
1725
1726	switch (anchorx) {
1727	case GBConstraints.CENTER:
1728	case GBConstraints.NORTH:
1729	case GBConstraints.SOUTH:
1730	    info.startx = diffw/2;
1731	    break;
1732
1733	case GBConstraints.WEST:
1734	case GBConstraints.NORTHWEST:
1735	case GBConstraints.SOUTHWEST:
1736	    info.startx = 0;
1737	    break;
1738
1739	case GBConstraints.EAST:
1740	case GBConstraints.NORTHEAST:
1741	case GBConstraints.SOUTHEAST:
1742	    info.startx = diffw;
1743	    break;
1744
1745	default:
1746	    /* JSTYLED */
1747	    throw new IllegalArgumentException(Global.getMsg("sunsoft.jws.visual.rt.awt.GBLayout.illegal__anchor__value.6"));
1748	}
1749
1750	switch (anchory) {
1751	case GBConstraints.CENTER:
1752	case GBConstraints.WEST:
1753	case GBConstraints.EAST:
1754	    info.starty = diffh/2;
1755	    break;
1756
1757	case GBConstraints.NORTH:
1758	case GBConstraints.NORTHWEST:
1759	case GBConstraints.NORTHEAST:
1760	    info.starty = 0;
1761	    break;
1762
1763	case GBConstraints.SOUTH:
1764	case GBConstraints.SOUTHWEST:
1765	case GBConstraints.SOUTHEAST:
1766	    info.starty = diffh;
1767	    break;
1768
1769	default:
1770	    /* JSTYLED */
1771	    throw new IllegalArgumentException(Global.getMsg("sunsoft.jws.visual.rt.awt.GBLayout.illegal__anchor__value.7"));
1772	}
1773
1774	info.startx += insets.left;
1775	info.starty += insets.top;
1776
1777	for (compindex = 0; compindex < components.length;
1778	    compindex++) {
1779	    comp = components[compindex];
1780	    if (!comp.isVisible())
1781		continue;
1782	    constraints = lookupConstraints(comp);
1783
1784	    r.x = info.startx;
1785	    for (i = 0; i < constraints.tempX; i++)
1786		r.x += info.minWidth[i];
1787
1788	    r.y = info.starty;
1789	    for (i = 0; i < constraints.tempY; i++)
1790		r.y += info.minHeight[i];
1791
1792	    r.width = 0;
1793	    for (i = constraints.tempX;
1794		 i < (constraints.tempX + constraints.tempWidth);
1795		 i++) {
1796		r.width += info.minWidth[i];
1797	    }
1798
1799	    r.height = 0;
1800	    for (i = constraints.tempY;
1801		 i < (constraints.tempY + constraints.tempHeight);
1802		 i++) {
1803		r.height += info.minHeight[i];
1804	    }
1805
1806	    AdjustForGravity(constraints, r);
1807
1808	    /*
1809	     * If the window is too small to be interesting then
1810	     * unmap it.  Otherwise configure it and then make sure
1811	     * it's mapped.
1812	     */
1813
1814	    if ((r.width <= 0) || (r.height <= 0)) {
1815		if (doReshape)
1816		    comp.reshape(-1, -1, 0, 0);
1817		constraints.location = new Point(-1, -1);
1818		constraints.size = new Dimension(0, 0);
1819	    } else {
1820		Point loc = comp.getLocation();
1821		Dimension size = comp.getSize();
1822
1823		if (loc.x != r.x || loc.y != r.y ||
1824                    size.width != r.width || size.height != r.height) {
1825		    if (doReshape)
1826			comp.reshape(r.x, r.y, r.width, r.height);
1827		    constraints.location = new Point(r.x, r.y);
1828		    constraints.size = new Dimension(r.width, r.height);
1829		}
1830	    }
1831	}
1832    }
1833}
1834