001/*
002 * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003 *
004 * Redistribution and use in source and binary forms, with or without
005 * modification, are permitted provided that the following conditions are met:
006 *
007 *  o Redistributions of source code must retain the above copyright notice,
008 *    this list of conditions and the following disclaimer.
009 *
010 *  o Redistributions in binary form must reproduce the above copyright notice,
011 *    this list of conditions and the following disclaimer in the documentation
012 *    and/or other materials provided with the distribution.
013 *
014 *  o Neither the name of JGoodies Karsten Lentzsch nor the names of
015 *    its contributors may be used to endorse or promote products derived
016 *    from this software without specific prior written permission.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030
031package com.jgoodies.forms.debug;
032
033import java.awt.Component;
034import java.awt.Container;
035
036import javax.swing.JLabel;
037
038import com.jgoodies.forms.layout.CellConstraints;
039import com.jgoodies.forms.layout.ColumnSpec;
040import com.jgoodies.forms.layout.FormLayout;
041import com.jgoodies.forms.layout.RowSpec;
042
043/**
044 * Provides static methods that help you understand and fix layout problems
045 * when using the {@link FormLayout}. Dumps information about the layout grid,
046 * layout groups and cell constraints to the console.<p>
047 *
048 * Implicit values are mapped to concrete. For example, implicit alignments
049 * in column and row specifications will be visible. And cell constraint
050 * alignments that use or override the column and row defaults are visible too.
051 * <pre>
052 * ColumnSpec("p")   -&gt; ColumnSpec("fill:pref:0");
053 * ColumnSpec("p:1") -&gt; ColumnSpec("fill:pref:1");
054 *
055 * RowSpec("p")      -&gt; RowSpec("center:pref:0");
056 * RowSpec("p:1")    -&gt; RowSpec("center:pref:1");
057 * </pre>
058 *
059 * @author        Karsten Lentzsch
060 * @version $Revision$
061 *
062 * @see FormDebugPanel
063 */
064public final class FormDebugUtils {
065
066    private FormDebugUtils() {
067        // Overrides default constructor; prevents instantiation.
068    }
069
070    // Console Dump *********************************************************
071
072    /**
073     * Dumps all layout state to the console: column and row specifications,
074     * column and row groups, grid bounds and cell constraints.
075     *
076     * @param container  the layout container
077     */
078    public static void dumpAll(Container container) {
079        if (!(container.getLayout() instanceof FormLayout)) {
080            System.out.println("The container's layout is not a FormLayout.");
081            return;
082        }
083        FormLayout layout = (FormLayout) container.getLayout();
084        dumpColumnSpecs(layout);
085        dumpRowSpecs(layout);
086        System.out.println();
087        dumpColumnGroups(layout);
088        dumpRowGroups(layout);
089        System.out.println();
090        dumpConstraints(container);
091        dumpGridBounds(container);
092    }
093
094    /**
095     * Dumps the layout's column specifications to the console.
096     *
097     * @param layout   the <code>FormLayout</code> to inspect
098     */
099    public static void dumpColumnSpecs(FormLayout layout) {
100        System.out.print("COLUMN SPECS:");
101        for (int col = 1; col <= layout.getColumnCount(); col++) {
102            ColumnSpec colSpec = layout.getColumnSpec(col);
103            System.out.print(colSpec.toShortString());
104            if (col < layout.getColumnCount()) {
105                System.out.print(", ");
106            }
107        }
108        System.out.println();
109    }
110
111    /**
112     * Dumps the layout's row specifications to the console.
113     *
114     * @param layout   the <code>FormLayout</code> to inspect
115     */
116    public static void dumpRowSpecs(FormLayout layout) {
117        System.out.print("ROW SPECS:   ");
118        for (int row = 1; row <= layout.getRowCount(); row++) {
119            RowSpec rowSpec = layout.getRowSpec(row);
120            System.out.print(rowSpec.toShortString());
121            if (row < layout.getRowCount()) {
122                System.out.print(", ");
123            }
124        }
125        System.out.println();
126    }
127
128    /**
129     * Dumps the layout's column groups to the console.
130     *
131     * @param layout   the <code>FormLayout</code> to inspect
132     */
133    public static void dumpColumnGroups(FormLayout layout) {
134        dumpGroups("COLUMN GROUPS: ", layout.getColumnGroups());
135    }
136
137    /**
138     * Dumps the layout's row groups to the console.
139     *
140     * @param layout   the <code>FormLayout</code> to inspect
141     */
142    public static void dumpRowGroups(FormLayout layout) {
143        dumpGroups("ROW GROUPS:    ", layout.getRowGroups());
144    }
145
146    /**
147     * Dumps the container's grid info to the console if and only
148     * if the container's layout is a <code>FormLayout</code>.
149     *
150     * @param container   the container to inspect
151     * @exception IllegalArgumentException   if the layout is not FormLayout
152     */
153    public static void dumpGridBounds(Container container) {
154        System.out.println("GRID BOUNDS");
155        dumpGridBounds(getLayoutInfo(container));
156    }
157
158    /**
159     * Dumps the grid layout info to the console.
160     *
161     * @param layoutInfo   provides the column and row origins
162     */
163    public static void dumpGridBounds(FormLayout.LayoutInfo layoutInfo) {
164        System.out.print("COLUMN ORIGINS: ");
165        for (int columnOrigin : layoutInfo.columnOrigins) {
166            System.out.print(columnOrigin + " ");
167        }
168        System.out.println();
169
170        System.out.print("ROW ORIGINS:    ");
171        for (int rowOrigin : layoutInfo.rowOrigins) {
172            System.out.print(rowOrigin + " ");
173        }
174        System.out.println();
175    }
176
177    /**
178     * Dumps the component constraints to the console.
179     *
180     * @param container   the layout container to inspect
181     */
182    public static void dumpConstraints(Container container) {
183        System.out.println("COMPONENT CONSTRAINTS");
184        if (!(container.getLayout() instanceof FormLayout)) {
185            System.out.println("The container's layout is not a FormLayout.");
186            return;
187        }
188        FormLayout layout = (FormLayout) container.getLayout();
189        int childCount = container.getComponentCount();
190        for (int i = 0; i < childCount; i++) {
191            Component child = container.getComponent(i);
192            CellConstraints cc = layout.getConstraints(child);
193            String ccString = cc == null ? "no constraints"
194                    : cc.toShortString(layout);
195            System.out.print(ccString);
196            System.out.print("; ");
197            String childType = child.getClass().getName();
198            System.out.print(childType);
199            if (child instanceof JLabel) {
200                JLabel label = (JLabel) child;
201                System.out.print("      \"" + label.getText() + "\"");
202            }
203            if (child.getName() != null) {
204                System.out.print("; name=");
205                System.out.print(child.getName());
206            }
207            System.out.println();
208        }
209        System.out.println();
210    }
211
212    // Helper Code **********************************************************
213
214    /**
215     * Dumps the given groups to the console.
216     *
217     * @param title       a string title for the dump
218     * @param allGroups   a two-dimensional array with all groups
219     */
220    private static void dumpGroups(String title, int[][] allGroups) {
221        System.out.print(title + " {");
222        for (int group = 0; group < allGroups.length; group++) {
223            int[] groupIndices = allGroups[group];
224            System.out.print(" {");
225            for (int i = 0; i < groupIndices.length; i++) {
226                System.out.print(groupIndices[i]);
227                if (i < groupIndices.length - 1) {
228                    System.out.print(", ");
229                }
230            }
231            System.out.print("} ");
232            if (group < allGroups.length - 1) {
233                System.out.print(", ");
234            }
235        }
236        System.out.println("}");
237    }
238
239    /**
240     * Computes and returns the layout's grid origins.
241     *
242     * @param container   the layout container to inspect
243     * @return an object that comprises the cell origins and extents
244     * @exception IllegalArgumentException   if the layout is not FormLayout
245     */
246    public static FormLayout.LayoutInfo getLayoutInfo(Container container) {
247        if (!(container.getLayout() instanceof FormLayout)) {
248            throw new IllegalArgumentException(
249                    "The container must use an instance of FormLayout.");
250        }
251        FormLayout layout = (FormLayout) container.getLayout();
252        return layout.getLayoutInfo(container);
253    }
254
255}