1   /*
2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    *
7    * 1. Redistributions of source code must retain the above copyright notice,
8    *    this list of conditions and the following disclaimer.
9    * 2. Redistributions in binary form must reproduce the above copyright notice,
10   *    this list of conditions and the following disclaimer in the documentation
11   *    and/or other materials provided with the distribution.
12   * 3. The end-user documentation included with the redistribution, if any, must
13   *    include the following acknowledgment:
14   *
15   *       "This product includes software developed by Gargoyle Software Inc.
16   *        (http://www.GargoyleSoftware.com/)."
17   *
18   *    Alternately, this acknowledgment may appear in the software itself, if
19   *    and wherever such third-party acknowledgments normally appear.
20   * 4. The name "Gargoyle Software" must not be used to endorse or promote
21   *    products derived from this software without prior written permission.
22   *    For written permission, please contact info@GargoyleSoftware.com.
23   * 5. Products derived from this software may not be called "GSBase", nor may
24   *    "GSBase" appear in their name, without prior written permission of
25   *    Gargoyle Software Inc.
26   *
27   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30   * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   */
38  package com.gargoylesoftware.base.gui;
39  
40  import java.awt.Dimension;
41  import java.awt.Point;
42  
43  import javax.swing.BorderFactory;
44  import javax.swing.JLabel;
45  import javax.swing.JPanel;
46  
47  import junit.framework.TestCase;
48  
49  import com.gargoylesoftware.base.util.DetailedNullPointerException;
50  
51  /***
52   * Tests for TableLayout
53   *
54   * @version  $Revision: 1.8 $
55   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
56   */
57  public class TableLayoutTest extends TestCase {
58  
59      /***
60       * Create a new test case.
61       * @param name The name of the test.
62       */
63      public TableLayoutTest( final String name ) {
64          super(name);
65      }
66  
67      /***
68       * Make sure that everything works ok if there aren't any children
69       */
70      public void testNoComponents() {
71  
72          final TableLayout layout = new TableLayout();
73          final Dimension zeroSize = new Dimension(0,0);
74          final Dimension maxSize = new Dimension(Integer.MAX_VALUE,Integer.MAX_VALUE);
75  
76          final JPanel panel = new JPanel();
77          panel.setLayout(layout);
78  
79          assertEquals( "minimumSize", zeroSize,
80                        panel.getMinimumSize());
81          assertEquals( "preferredSize", zeroSize,
82                        panel.getPreferredSize());
83          assertEquals( "maximumSize", maxSize,
84                        panel.getMaximumSize());
85  
86          panel.setSize(800,600);
87          panel.validate();
88      }
89  
90      /***
91       * Test with no children but with insets specified
92       */
93      public void testNoComponents_WithInsets() {
94  
95          final TableLayout layout = new TableLayout();
96          final JPanel panel = new JPanel();
97          panel.setLayout(layout);
98          panel.setBorder( BorderFactory.createEmptyBorder(2,2,2,2) );
99  
100         assertEquals( "minimumSize", new Dimension(4,4),
101                       panel.getMinimumSize());
102         assertEquals( "preferredSize", new Dimension(4,4),
103                       panel.getPreferredSize());
104 
105         panel.setSize(800,600);
106         panel.validate();
107     }
108 
109     /***
110      * The layout should always be called by the same container.
111      * Make sure it throws an exception if it is called by more
112      * than one container.
113      */
114     public void testDifferentContainers() {
115 
116         final TableLayout layout = new TableLayout();
117         final JPanel panel1 = new JPanel();
118         final JPanel panel2 = new JPanel();
119 
120         layout.minimumLayoutSize(panel1);
121         try {
122             layout.minimumLayoutSize(panel2);
123             fail("Expected IllegalArgumentException when using different containers");
124         }
125         catch( final IllegalArgumentException e ) {
126             // Expected path
127         }
128     }
129 
130     /***
131      * Ensure that an exception is thrown if null is passed in as
132      * the container.
133      */
134     public void testNullContainers() {
135 
136         final TableLayout layout = new TableLayout();
137 
138         try {
139             layout.minimumLayoutSize(null);
140             fail("Expected exception when using null container");
141         }
142         catch( final DetailedNullPointerException e ) {
143             assertEquals("newParent", e.getArgumentName());
144         }
145     }
146 
147     /***
148      * Make sure you can't add the same component twice.
149      */
150     public void testAddComponentTwice() {
151 
152         final TableLayout layout = new TableLayout();
153         final JPanel panel = new JPanel();
154         layout.addLayoutComponent( panel, new TableLayoutConstraints(3,4) );
155 
156         try {
157             layout.addLayoutComponent(panel, new TableLayoutConstraints(1,2));
158             fail("Should not be able to add the same component twice");
159         }
160         catch( final IllegalArgumentException e ) {
161             // Expected path
162         }
163     }
164 
165     /***
166      * Make sure you can't pass in a null component.
167      */
168     public void testAddNullComponent() {
169 
170         final TableLayout layout = new TableLayout();
171         try {
172             layout.addLayoutComponent(null, new TableLayoutConstraints(1,2));
173         }
174         catch( final DetailedNullPointerException e ) {
175             assertEquals("comp", e.getArgumentName());
176         }
177     }
178 
179     /***
180      * Make sure that the layout doesn't accept constraints that
181      * aren't TableLayoutConstraints or String objects.
182      */
183     public void testAddStringConstraint() {
184 
185         final TableLayout layout = new TableLayout();
186         try {
187             layout.addLayoutComponent(new JPanel(), new Integer(5));
188         }
189         catch( final IllegalArgumentException e ) {
190             // Expected path
191         }
192     }
193 
194     /***
195      * Make sure you can't remove the same object twice.
196      */
197     public void testRemoveComponentTwice() {
198 
199         final TableLayout layout = new TableLayout();
200         final JPanel panel = new JPanel();
201         layout.addLayoutComponent( panel, new TableLayoutConstraints(1,2) );
202         layout.removeLayoutComponent( panel );
203         try {
204             layout.removeLayoutComponent( panel );
205             fail("Should be not able to remove the same component twice");
206         }
207         catch( final IllegalArgumentException e ) {
208             // Expected path
209         }
210     }
211 
212     /***
213      * Make sure you can't remove a null component.
214      */
215     public void testRemoveNullComponent() {
216 
217         final TableLayout layout = new TableLayout();
218         try {
219             layout.removeLayoutComponent(null);
220             fail("Expected exception");
221         }
222         catch( final DetailedNullPointerException e ) {
223             assertEquals("comp", e.getArgumentName());
224         }
225     }
226 
227     /***
228      * Test with only one child to ensure that all dimensions
229      * are calculated correctly.
230      */
231     public void testOneChild() {
232 
233         final JPanel parent = new JPanel();
234         final TableLayout layout = new TableLayout();
235         JPanel child;
236 
237         parent.setLayout( layout );
238         parent.setMaximumSize( new Dimension(600,700) );
239 
240         child = new JPanel();
241         child.setMinimumSize  ( new Dimension(20,30) );
242         child.setPreferredSize( new Dimension(40,50) );
243         child.setMaximumSize  ( new Dimension(60,70) );
244         parent.add( child, new TableLayoutConstraints(1,1) );
245 
246         parent.setSize(800,600);
247         layout.layoutContainer(parent);
248 
249         assertEquals( "parent.minimumSize",
250                       new Dimension(20,30),
251                       parent.getMinimumSize() );
252         assertEquals( "parent.preferredSize",
253                       new Dimension(40,50),
254                       parent.getPreferredSize() );
255         assertEquals( "parent.maximumSize",
256                       new Dimension(600,700),
257                       parent.getMaximumSize() );
258 
259         assertEquals( "child.size",
260                       new Dimension(40,50),
261                       child.getSize() );
262     }
263 
264     /***
265      * Test with one child and some insets to make sure all
266      * dimensions are calculated correctly.
267      */
268     public void testOneChildWithInsetsOnParent() {
269 
270         final JPanel parent = new JPanel();
271         final TableLayout layout = new TableLayout();
272         JPanel child;
273 
274         parent.setLayout( layout );
275         parent.setMaximumSize( new Dimension(600,700) );
276         parent.setBorder( BorderFactory.createEmptyBorder(2,2,2,2) );
277 
278         child = new JPanel();
279         child.setMinimumSize  ( new Dimension(20,30) );
280         child.setPreferredSize( new Dimension(40,50) );
281         child.setMaximumSize  ( new Dimension(60,70) );
282 
283         parent.add(child, new TableLayoutConstraints(1,1) );
284 
285         parent.setSize(800,600);
286         layout.layoutContainer(parent);
287 
288         assertEquals( "parent.minimumSize",
289                       new Dimension(24,34),
290                       parent.getMinimumSize() );
291         assertEquals( "parent.preferredSize",
292                       new Dimension(44,54),
293                       parent.getPreferredSize() );
294         assertEquals( "parent.maximumSize",
295                       new Dimension(600,700),
296                       parent.getMaximumSize() );
297 
298         assertEquals( "child.size",
299                       new Dimension(40,50),
300                       child.getSize() );
301 
302         final Dimension childMinimumSize = child.getMinimumSize();
303         parent.setSize( new Dimension( childMinimumSize.width+20, childMinimumSize.height+20) );
304         layout.layoutContainer(parent);
305         assertEquals( "child.location",
306                       new Point(2,2),
307                       child.getLocation() );
308     }
309 
310     /***
311      * Test the alignment with one child and insets.
312      */
313     public void testParentAlignmentWithOneChildAndInsets() {
314 
315         final JPanel parent = new JPanel();
316         final TableLayout layout = new TableLayout();
317         JPanel child;
318 
319         parent.setLayout( layout );
320         parent.setMaximumSize( new Dimension(600,700) );
321         final int top = 2;
322         final int bottom = 2;
323         final int left = 2;
324         final int right = 2;
325         parent.setBorder( BorderFactory.createEmptyBorder(top,left,bottom,right) );
326 
327         final int childWidth  = 20;
328         final int childHeight = 30;
329 
330         child = new JPanel();
331         child.setMinimumSize  ( new Dimension(20,30) );
332         child.setPreferredSize( new Dimension(childWidth, childHeight) );
333         child.setMaximumSize  ( new Dimension(60,70) );
334         parent.add(child, new TableLayoutConstraints(1,1) );
335 
336         final int parentWidth  = 800;
337         final int parentHeight = 600;
338         parent.setSize( parentWidth, parentHeight );
339 
340         layout.setHorizontalAlignment( TableLayout.LEFT );
341         layout.setVerticalAlignment( TableLayout.TOP );
342         layout.layoutContainer(parent);
343         assertEquals( "child.location for LEFT,TOP",
344                       new Point(2,2),
345                       child.getLocation() );
346 
347         layout.setHorizontalAlignment( TableLayout.CENTER );
348         layout.setVerticalAlignment( TableLayout.CENTER );
349         layout.layoutContainer(parent);
350         assertEquals( "child.location for CENTER, CENTER",
351                       new Point( (parentWidth-childWidth-left-right)/2 + left,
352                                  (parentHeight-childHeight-top-bottom)/2 + top),
353                       child.getLocation() );
354 
355         layout.setHorizontalAlignment( TableLayout.RIGHT );
356         layout.setVerticalAlignment( TableLayout.BOTTOM );
357         layout.layoutContainer(parent);
358         assertEquals( "child.location for BOTTOM, RIGHT",
359                       new Point( parentWidth-childWidth-left,
360                                  parentHeight-childHeight-top ),
361                       child.getLocation() );
362     }
363 
364 
365     /***
366      * Test removing a component.
367      */
368     public void testRemove() {
369         final JPanel parent = new JPanel();
370         final TableLayout layout = new TableLayout();
371 
372         parent.setLayout( layout );
373 
374         final JPanel child = new JPanel();
375         child.setPreferredSize( new Dimension(100,100) );
376         parent.add(child, new TableLayoutConstraints(1,1) );
377 
378         assertEquals( "parent.preferredSize",
379                       new Dimension(100,100),
380                       parent.getPreferredSize() );
381 
382         parent.remove(child);
383         assertEquals( "parent.preferredSize",
384                       new Dimension(0,0),
385                       parent.getPreferredSize() );
386     }
387 
388 
389     /***
390      * Test the case where removing a component changes the
391      * sizes but doesn't change the number of rows or columns.
392      *
393      *  ***** *****
394      *  * 1 * * 2 *
395      *  ***** *****
396      *
397      *  ***** *******
398      *  * 3 * *     *
399      *  ***** *  4  *
400      *        *     *
401      *        *******
402      */
403     public void testRemoveWhereColumnAndRowCountsDontChange() {
404         final JPanel parent = new JPanel();
405         final TableLayout layout = new TableLayout();
406 
407         parent.setLayout( layout );
408 
409         final int small = 10;
410         final int large = 50;
411         final Dimension smallSize = new Dimension(small, small);
412         final Dimension largeSize = new Dimension(large, large);
413 
414         final JPanel child1 = new JPanel();
415         final JPanel child2 = new JPanel();
416         final JPanel child3 = new JPanel();
417         final JPanel child4 = new JPanel();
418 
419         child1.setMinimumSize(smallSize);
420         child2.setMinimumSize(smallSize);
421         child3.setMinimumSize(smallSize);
422         child4.setMinimumSize(largeSize);
423 
424         parent.add( child1, new TableLayoutConstraints(0,0) );
425         parent.add( child2, new TableLayoutConstraints(0,1) );
426         parent.add( child3, new TableLayoutConstraints(1,0) );
427         parent.add( child4, new TableLayoutConstraints(1,1) );
428 
429         assertEquals( "parent.minimumSize",
430                       new Dimension(small+large, small+large),
431                       parent.getMinimumSize() );
432 
433         parent.remove(child4);
434 
435         assertEquals( "parent.minimumSize",
436                       new Dimension(small+small, small+small),
437                       parent.getMinimumSize() );
438     }
439 
440 
441     /***
442      * Regression test: Exception was being thrown when a component was added
443      * after it had been removed once.
444      */
445     public void testRemoveAndAddAgain() {
446         final JPanel parent = new JPanel();
447         final TableLayout layout = new TableLayout();
448 
449         parent.setLayout( layout );
450 
451         final JPanel child = new JPanel();
452         parent.add(child, new TableLayoutConstraints(1,1) );
453 
454         parent.setSize( 800,600 );
455 
456         // The original bug would throw an exception on execution of the
457         // following line.
458         layout.setMinimumRowHeight(9,10);
459 
460         parent.remove(child);
461         parent.add(child, new TableLayoutConstraints(1,1) );
462         layout.layoutContainer(parent);
463     }
464 
465 
466     /***
467      * Test the ability to expand rows.
468      */
469     public void testOneChildExpandedRow() {
470 
471         final JPanel parent = new JPanel();
472         final TableLayout layout = new TableLayout();
473         JPanel child;
474 
475         parent.setLayout( layout );
476 
477         child = new JPanel();
478         child.setMinimumSize  ( new Dimension(20,30) );
479         child.setPreferredSize( new Dimension(40,50) );
480 
481         final TableLayoutConstraints constraints = new TableLayoutConstraints(0,0);
482         constraints.setVerticalStretch(true);
483         constraints.setHorizontalStretch(true);
484         parent.add( child, constraints );
485 
486         layout.setRowExpandable( 0, true );
487 
488         assertEquals( "parent.minimumSize",
489                       new Dimension(20,30),
490                       parent.getMinimumSize() );
491         assertEquals( "parent.preferredSize",
492                       new Dimension(40,50),
493                       parent.getPreferredSize() );
494 
495         parent.setSize(800,600);
496         layout.layoutContainer(parent);
497 
498         assertEquals( "child.size",
499                       new Dimension(40,600),
500                       child.getSize() );
501         assertEquals( "child.location",
502                       new Point((800-40)/2, 0),
503                       child.getLocation() );
504     }
505 
506 
507     /***
508      * Test the ability to expand columns.
509      */
510     public void testOneChildExpandedColumn() {
511 
512         final JPanel parent = new JPanel();
513         final TableLayout layout = new TableLayout();
514         JPanel child;
515 
516         parent.setLayout( layout );
517 
518         child = new JPanel();
519         child.setMinimumSize  ( new Dimension(20,30) );
520         child.setPreferredSize( new Dimension(40,50) );
521 
522         final TableLayoutConstraints constraints = new TableLayoutConstraints(0,0);
523         constraints.setVerticalStretch(true);
524         constraints.setHorizontalStretch(true);
525         parent.add( child, constraints );
526 
527         layout.setColumnExpandable( 0, true );
528 
529         assertEquals( "parent.minimumSize",
530                       new Dimension(20,30),
531                       parent.getMinimumSize() );
532         assertEquals( "parent.preferredSize",
533                       new Dimension(40,50),
534                       parent.getPreferredSize() );
535 
536         parent.setSize(800,600);
537         layout.layoutContainer(parent);
538 
539         assertEquals( "child.size",
540                       new Dimension(800,50),
541                       child.getSize() );
542         assertEquals( "child.location",
543                       new Point(0,(600-50)/2),
544                       child.getLocation() );
545     }
546 
547 
548     /***
549      * Make sure that the child doesn't get stretched beyond its
550      * maximum size.
551      */
552     public void testOneChildExpandedWithMaxSize() {
553 
554         final JPanel parent = new JPanel();
555         final TableLayout layout = new TableLayout();
556 
557         parent.setLayout( layout );
558 
559         final JPanel child = new JPanel();
560         child.setMinimumSize  ( new Dimension(20,30) );
561         child.setPreferredSize( new Dimension(40,50) );
562         child.setMaximumSize( new Dimension(100,100));
563 
564         final TableLayoutConstraints constraints = new TableLayoutConstraints(0,0);
565         constraints.setHorizontalAlignment( TableLayout.LEFT );
566         constraints.setVerticalAlignment( TableLayout.TOP );
567         constraints.setVerticalStretch(true);
568         constraints.setHorizontalStretch(true);
569         constraints.setObeyMaximumSize(true);
570         parent.add( child, constraints );
571 
572         layout.setRowExpandable   ( 0, true );
573         layout.setColumnExpandable( 0, true );
574 
575         assertEquals( "parent.minimumSize",
576                       new Dimension(20,30),
577                       parent.getMinimumSize() );
578         assertEquals( "parent.preferredSize",
579                       new Dimension(40,50),
580                       parent.getPreferredSize() );
581 
582         parent.setSize(800,600);
583         layout.layoutContainer(parent);
584 
585         assertEquals( "child.size",
586                       new Dimension(100,100),
587                       child.getSize() );
588         assertEquals( "child.location",
589                       new Point(0,0),
590                       child.getLocation() );
591 
592 
593     }
594 
595 
596     /***
597      * <pre>
598      * ################################
599      * #     parent                   #
600      * #                              #
601      * #    #######################   #
602      * #    # child1 # child2     #   #
603      * #    # (0,0)  # (0,1)      #   #
604      * #    #        #            #   #
605      * #    #        ##############   #
606      * #    #        # child3     #   #
607      * #    #        # (1,1)      #   #
608      * #    #        #            #   #
609      * #    #######################   #
610      * #    # child4              #   #
611      * #    # (2,0)               #   #
612      * #    #                     #   #
613      * #    #######################   #
614      * #                              #
615      * #                              #
616      * ################################
617      * </pre>
618      */
619     public void testFourChildrenWithComponentStretching() {
620         final JPanel parent = new JPanel();
621         final JLabel child1 = new JLabel("child1");
622         final JLabel child2 = new JLabel("child2");
623         final JLabel child3 = new JLabel("child3");
624         final JLabel child4 = new JLabel("child4");
625 
626         // By default, labels set their maximum size to be the same
627         // as their preferred size which means that they won't stretch.
628         // Since we're testing stretching, we force the maximum size
629         // to be huge.
630         final Dimension maximumSize = new Dimension(1000,1000);
631         child1.setMaximumSize( maximumSize );
632         child2.setMaximumSize( maximumSize );
633         child3.setMaximumSize( maximumSize );
634         child4.setMaximumSize( maximumSize );
635 
636         final TableLayout layout = new TableLayout();
637         TableLayoutConstraints constraints;
638         constraints = new TableLayoutConstraints(0,0);
639         constraints.setVerticalStretch(true);
640         constraints.setHorizontalStretch(true);
641 
642         parent.setLayout( layout );
643 
644         constraints = new TableLayoutConstraints(0,0);
645         constraints.setVerticalStretch(true);
646         constraints.setHorizontalStretch(true);
647         constraints.setRowSpan(2);
648         parent.add( child1, constraints );
649 
650         constraints = new TableLayoutConstraints(0,1);
651         constraints.setVerticalStretch(true);
652         constraints.setHorizontalStretch(true);
653         parent.add( child2, constraints );
654 
655         constraints = new TableLayoutConstraints(1,1);
656         constraints.setVerticalStretch(true);
657         constraints.setHorizontalStretch(true);
658         parent.add( child3, constraints );
659 
660         constraints = new TableLayoutConstraints(2,0);
661         constraints.setVerticalStretch(true);
662         constraints.setHorizontalStretch(true);
663         constraints.setColumnSpan(2);
664         parent.add( child4, constraints );
665 
666         parent.setSize(2000,2000);
667         layout.layoutContainer(parent);
668 
669         final Dimension child1Size = child1.getSize();
670         final Dimension child2Size = child2.getSize();
671         final Dimension child3Size = child3.getSize();
672         final Dimension child4Size = child4.getSize();
673 
674         assertEquals( "Children 2 and 3 should have the same width",
675                       child2Size.width, child3Size.width );
676         assertEquals( "child1.height == child2.height+child3.height",
677                       child1Size.height,
678                       child2Size.height + child3Size.height );
679         assertEquals( "child4.width == child1.width+child2.width",
680                       child4Size.width,
681                       child1Size.width + child2Size.width );
682 
683         assertEquals( "child4.width should be no wider than the sum of the preferred sizes",
684                       child4Size.width,
685                       child1.getPreferredSize().width
686                         + Math.max( child2.getPreferredSize().width,
687                       child3.getPreferredSize().width ) );
688     }
689 
690 
691     /***
692      * <pre>
693      * ################################
694      * #     parent                   #
695      * #                              #
696      * #    #######################   #
697      * #    # child1 # child2     #   #
698      * #    # (0,0)  # (0,1)      #   #
699      * #    #        #            #   #
700      * #    #        ##############   #
701      * #    #        # child3     #   #
702      * #    #        # (1,1)      #   #
703      * #    #        #            #   #
704      * #    #######################   #
705      * #    # child4              #   #
706      * #    # (2,0)               #   #
707      * #    #                     #   #
708      * #    #######################   #
709      * #                              #
710      * #                              #
711      * ################################
712      * </pre>
713      */
714     public void testNoExpansionBeyondMaximumSize() {
715         final JPanel parent = new JPanel();
716         final JLabel child1 = new JLabel("child1");
717         final JLabel child2 = new JLabel("child2");
718         final JLabel child3 = new JLabel("child3");
719         final JLabel child4 = new JLabel("child4");
720 
721         final TableLayout layout = new TableLayout();
722         TableLayoutConstraints constraints;
723 
724         parent.setLayout( layout );
725 
726         constraints = new TableLayoutConstraints(0,0);
727         constraints.setVerticalStretch(true);
728         constraints.setHorizontalStretch(true);
729         constraints.setRowSpan(2);
730         constraints.setObeyMaximumSize(true);
731         parent.add( child1, constraints );
732 
733         constraints = new TableLayoutConstraints(0,1 );
734         constraints.setVerticalStretch(true);
735         constraints.setHorizontalStretch(true);
736         constraints.setObeyMaximumSize(true);
737         parent.add( child2, constraints );
738 
739         constraints = new TableLayoutConstraints(1,1);
740         constraints.setVerticalStretch(true);
741         constraints.setHorizontalStretch(true);
742         constraints.setObeyMaximumSize(true);
743         parent.add( child3, constraints );
744 
745         constraints = new TableLayoutConstraints(2,0);
746         constraints.setVerticalStretch(true);
747         constraints.setHorizontalStretch(true);
748         constraints.setColumnSpan(2);
749         constraints.setObeyMaximumSize(true);
750         parent.add( child4, constraints );
751 
752         parent.setSize(2000,2000);
753         layout.layoutContainer(parent);
754 
755         assertEquals( "child1", child1.getSize(), child1.getMaximumSize() );
756         assertEquals( "child2", child1.getSize(), child2.getMaximumSize() );
757         assertEquals( "child3", child1.getSize(), child3.getMaximumSize() );
758         assertEquals( "child4", child1.getSize(), child4.getMaximumSize() );
759     }
760 
761 
762     /***
763      * Test the minimum sizes.
764      */
765     public void testMinimumSizesOnColumnsAndRows() {
766 
767         final JPanel parent = new JPanel();
768         final TableLayout layout = new TableLayout();
769         JPanel child;
770 
771         parent.setLayout( layout );
772 
773         child = new JPanel();
774         child.setMinimumSize  ( new Dimension(20,30) );
775         child.setPreferredSize( new Dimension(40,50) );
776         child.setMaximumSize  ( new Dimension(10000,10000) );
777         final TableLayoutConstraints constraints = new TableLayoutConstraints(1,1);
778         constraints.setVerticalStretch(true);
779         constraints.setHorizontalStretch(true);
780         parent.add( child, constraints );
781 
782         layout.setRowExpandable(1, true );
783         layout.setColumnExpandable(1, true );
784 
785         layout.setMinimumRowHeight  (0,11);
786         layout.setMinimumColumnWidth(0,12);
787         layout.setMinimumRowHeight  (2,13);
788         layout.setMinimumColumnWidth(2,14);
789 
790         assertEquals( "parent.preferredSize",
791                       new Dimension(40+12+14,50+11+13),
792                       parent.getPreferredSize() );
793         assertEquals( "parent.minimumSize",
794                       new Dimension(20+12+14,30+11+13),
795                       parent.getMinimumSize() );
796 
797         parent.setSize(800,600);
798         layout.layoutContainer(parent);
799 
800         assertEquals( "child.size",
801                       new Dimension(800-12-14, 600-11-13),
802                       child.getSize() );
803         assertEquals( "child.location",
804                       new Point(12,11),
805                       child.getLocation() );
806 
807     }
808 
809 
810     /***
811      * Test expandable rows with insets
812      */
813     public void testExpandableRowWithInsets() {
814         final JPanel parent = new JPanel();
815         final TableLayout layout = new TableLayout();
816         TableLayoutConstraints constraints;
817 
818         parent.setLayout( layout );
819 
820         final JPanel child1 = new JPanel();
821         child1.setPreferredSize( new Dimension(10,20) );
822         parent.add( child1, new TableLayoutConstraints(1,1) );
823 
824         final JPanel child2 = new JPanel();
825         child2.setPreferredSize( new Dimension(10,20) );
826         child2.setMaximumSize( new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE) );
827         constraints = new TableLayoutConstraints(3,1);
828         constraints.setVerticalStretch(true);
829         parent.add( child2, constraints );
830 
831         final JPanel child3 = new JPanel();
832         child3.setPreferredSize( new Dimension(10,20) );
833         parent.add( child3, new TableLayoutConstraints(5,1) );
834 
835         final int borderLeft   = 2;
836         final int borderRight  = 2;
837         final int borderTop    = 2;
838         final int borderBottom = 2;
839         layout.setRowExpandable(3, true );
840         parent.setBorder( BorderFactory.createEmptyBorder(borderTop, borderLeft, borderBottom, borderRight ) );
841 
842         final int parentWidth = 800;
843         final int parentHeight = 600;
844         parent.setSize( parentWidth, parentHeight );
845         //layout.setHorizontalAlignment( TableLayout.LEFT );
846         layout.layoutContainer(parent);
847 
848         // Child 1
849         assertEquals( "child1.size",
850                       new Dimension(10, 20),
851                       child1.getSize() );
852         assertEquals( "child1.location",
853                       borderTop,
854                       child1.getLocation().y );
855 
856         // Child 2
857         assertEquals( "child2.location",
858                       borderTop + child1.getSize().height,
859                       child2.getLocation().y );
860 
861         // Child 3
862         assertEquals( "child3.size",
863                       new Dimension(10, 20),
864                       child3.getSize() );
865         assertEquals( "child3.location",
866                       parentHeight - borderBottom - child3.getSize().height,
867                       child3.getLocation().y );
868 
869     }
870 
871     /***
872      * If the actual size is less than the preferred size of the layout then
873      * some components were being sized to larger than their preferred size.
874      * Make sure this is fixed.
875      */
876     public void testShrinkToFit() {
877         final JPanel parent = new JPanel();
878         final TableLayout layout = new TableLayout();
879         TableLayoutConstraints constraints;
880 
881         parent.setLayout( layout );
882 
883         JPanel child1 = new JPanel();
884         child1.setMinimumSize( new Dimension(10,10) );
885         child1.setPreferredSize( new Dimension(200,200) );
886         constraints = new TableLayoutConstraints(1,1);
887         parent.add( child1, constraints );
888 
889         JPanel child2 = new JPanel();
890         child2.setMinimumSize( new Dimension(10,10) );
891         child2.setPreferredSize( new Dimension(20,20) );
892         constraints = new TableLayoutConstraints(1,3);
893         parent.add( child2, constraints );
894 
895         JPanel child3 = new JPanel();
896         child3.setMinimumSize( new Dimension(10,10) );
897         child3.setPreferredSize( new Dimension(200,200) );
898         constraints = new TableLayoutConstraints(1,5);
899         parent.add( child3, constraints );
900 
901         assertEquals("parent.minimumSize",
902                      new Dimension(30,10),
903                      parent.getMinimumSize() );
904         assertEquals("parent.preferredSize",
905                      new Dimension(420,200),
906                      parent.getPreferredSize() );
907 
908         // We set the parent size to be smaller than the children's preferred
909         parent.setSize( new Dimension(390,420) );
910         layout.layoutContainer(parent);
911 
912         assertEquals("child1.size",
913                      new Dimension(185,200),
914                      child1.getSize() );
915         assertEquals("child2.size",
916                      new Dimension(20,20),
917                      child2.getSize() );
918         assertEquals("child3.size",
919                      new Dimension(185,200),
920                      child3.getSize() );
921     }
922 
923     /***
924      * Regression test for a bug.
925      */
926     public void testEmptyColumnsExpanding() {
927         final TableLayout layout = new TableLayout();
928         final JPanel parent = new JPanel(layout);
929 
930         TableLayoutConstraints constraints;
931 
932         final JPanel child1 = new JPanel();
933         final JPanel child2 = new JPanel();
934         final JPanel child3 = new JPanel();
935         final JPanel child4 = new JPanel();
936 
937         final Dimension smallSize = new Dimension(10,10);
938         final Dimension largeSize = new Dimension(100,10);
939 
940         child1.setMinimumSize  ( smallSize );
941         child1.setPreferredSize( smallSize );
942         child2.setMinimumSize  ( smallSize );
943         child2.setPreferredSize( smallSize );
944         child3.setMinimumSize  ( smallSize );
945         child3.setPreferredSize( smallSize );
946         child4.setMinimumSize  ( smallSize );
947         child4.setPreferredSize( largeSize );
948 
949         layout.setColumnExpandable(1,true);
950 
951         constraints = new TableLayoutConstraints(1,1);
952         constraints.setHorizontalStretch(true);
953         parent.add( child1, constraints );
954 
955         constraints = new TableLayoutConstraints(1,3);
956         constraints.setHorizontalStretch(true);
957         parent.add( child2, constraints );
958 
959         constraints = new TableLayoutConstraints(3,1);
960         constraints.setHorizontalStretch(true);
961         parent.add( child3, constraints );
962 
963         constraints = new TableLayoutConstraints(5,1);
964         constraints.setColumnSpan(3);
965         constraints.setHorizontalStretch(true);
966         parent.add( child4, constraints );
967 
968         assertEquals("parent.preferredSize",
969                      new Dimension(100,30),
970                      parent.getPreferredSize() );
971 
972         parent.setSize( parent.getPreferredSize() );
973         layout.layoutContainer(parent);
974 
975         assertEquals("child1.size",
976                      new Dimension(90,10),
977                      child1.getSize() );
978         assertEquals("child1.location",
979                      new Point(0,0),
980                      child1.getLocation() );
981 
982         assertEquals("child2.size",
983                      new Dimension(10,10),
984                      child2.getSize() );
985         assertEquals("child2.location",
986                      new Point(90,0),
987                      child2.getLocation() );
988 
989         assertEquals("child3.size",
990                      new Dimension(90,10),
991                      child3.getSize() );
992         assertEquals("child3.location",
993                      new Point(0,10),
994                      child3.getLocation() );
995 
996         assertEquals("child4.size",
997                      new Dimension(100,10),
998                      child4.getSize() );
999         assertEquals("child4.location",
1000                      new Point(0,20),
1001                      child4.getLocation() );
1002 
1003     }
1004 
1005     /***
1006      *  *******
1007      *  *  A  *
1008      *  *     *
1009      *  *******
1010      *
1011      *  ******************
1012      *  *      B         *
1013      *  *                *
1014      *  ******************
1015      *
1016      * Regression testing a bug where having an odd number for the width of A (or B for that
1017      * matter) caused column 0 to expand.  Column 0 should end up with a width of zero as there
1018      * are no components in it and it is not marked as expandable.
1019      */
1020     public void testOddSizeWidth() {
1021         final TableLayout layout = new TableLayout();
1022         final JPanel panel = new TableLayoutDebuggingPanel(layout);
1023 
1024         TableLayoutConstraints constraints;
1025 
1026         layout.setColumnExpandable(1,true);
1027         layout.setColumnExpandable(2,true);
1028 
1029         final JPanel compA = new JPanel();
1030         compA.setName("A");
1031         compA.setPreferredSize( new Dimension(102, 30) );
1032         constraints = new TableLayoutConstraints(1,1);
1033 
1034         panel.add( compA, constraints );
1035 
1036         final JPanel compB = new JPanel();
1037         compB.setName("B");
1038         compB.setPreferredSize( new Dimension(300,30) );
1039         constraints = new TableLayoutConstraints(2,1);
1040         constraints.setColumnSpan(2);
1041         constraints.setHorizontalStretch(true);
1042         panel.add( compB, constraints );
1043 
1044         panel.setSize( panel.getPreferredSize() );
1045         layout.layoutContainer(panel);
1046 
1047         assertEquals( "compA.position even width", new Point(0,0), compA.getLocation() );
1048 
1049         // So far everything should have worked since we're using even widths.  Now we
1050         // set the width to an odd number and watch things blow up.
1051 
1052         layout.invalidateLayout(panel);
1053         compA.setPreferredSize( new Dimension(103, 30) );
1054         panel.setSize( panel.getPreferredSize() );
1055         layout.layoutContainer(panel);
1056 
1057         assertEquals( "compA.position odd width", new Point(0,0), compA.getLocation() );
1058     }
1059 
1060     /***
1061      * Regression test for bug where an exception would be thrown if the size of the panel
1062      * was so small that there wasn't room to display the insets.
1063      */
1064     public void testSmallerSizeThanAllowedByInsets() {
1065         final TableLayout layout = new TableLayout();
1066         final JPanel panel = new TableLayoutDebuggingPanel(layout);
1067 
1068         panel.add( new JLabel("foo"), "1,1" );
1069         panel.setBorder( BorderFactory.createEmptyBorder(5,5,5,5) );
1070 
1071         panel.setSize( new Dimension(0,0) );
1072         layout.layoutContainer(panel);
1073     }
1074 
1075     /***
1076      * Regression test for a bug where adding and then removing a component followed
1077      * by adding a new one will cause an ArrayOutOfBoundsException to be thrown.
1078      */
1079     public void testAddAddRemoveAdd() {
1080         final TableLayout layout = new TableLayout();
1081         final JPanel panel = new JPanel(layout);
1082 
1083         final JPanel child1 = new JPanel();
1084         final JPanel child2 = new JPanel();
1085         final JPanel child3 = new JPanel();
1086 
1087         panel.add( "1,1", child1 );
1088 
1089         layout.addLayoutComponent( child2, "1,3" );
1090         layout.removeLayoutComponent(child2);
1091         layout.addLayoutComponent( child3, "1,3" );
1092         layout.layoutContainer(panel);
1093     }
1094 }
1095 
1096