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.builder;
032
033import javax.swing.JButton;
034import javax.swing.JComponent;
035import javax.swing.JPanel;
036
037import com.jgoodies.forms.factories.FormFactory;
038import com.jgoodies.forms.layout.ColumnSpec;
039import com.jgoodies.forms.layout.ConstantSize;
040import com.jgoodies.forms.layout.FormLayout;
041import com.jgoodies.forms.layout.FormSpec;
042import com.jgoodies.forms.layout.RowSpec;
043
044/**
045 * A non-visual builder that assists you in building consistent button stacks
046 * using the {@link FormLayout}.<p>
047 *
048 * This builder sets a hint for narrow  margin for the gridded buttons.
049 * This can reduce the button stack's width if some buttons have long texts.
050 * For example, a stack with 'OK', 'Cancel', 'Configure...' will likely
051 * exceed the minimum button width. The narrow margins help getting narrow
052 * stacks.
053 * Note that some look&amp;feels do not support the narrow margin feature,
054 * and conversely, others have only narrow margins. The JGoodies look&amp;feels
055 * honor the setting, the Mac Aqua l&amp;f uses narrow margins all the time.<p>
056 *
057 * <strong>Example:</strong><br>
058 * The following example builds a button stack with <i>Close, Up</i> and
059 * <i>Down</i>, where Up and Down are related, and Close is not related
060 * to the other buttons, which makes a wide gap for the unrelated and
061 * a smaller gap for the related buttons.
062 * <pre>
063 * private JPanel createCloseUpDownButtonStack(
064 *         JButton close, JButton up, JButton down) {
065 *     ButtonStackBuilder builder = new ButtonStackBuilder();
066 *     builder.addGridded(close);
067 *     builder.addUnrelatedGap();
068 *     builder.addGridded(up);
069 *     builder.addRelatedGap();
070 *     builder.addGridded(down);
071 *     return builder.getPanel();
072 * }
073 * </pre>
074 *
075 * @author        Karsten Lentzsch
076 * @version $Revision$
077 *
078 * @see ButtonBarBuilder
079 * @see com.jgoodies.forms.factories.ButtonBarFactory
080 * @see com.jgoodies.forms.util.LayoutStyle
081 */
082public final class ButtonStackBuilder extends PanelBuilder {
083
084    /**
085     * Specifies the FormLayout's the single button stack column.
086     */
087    private static final ColumnSpec[] COL_SPECS = new ColumnSpec[] {
088            FormFactory.BUTTON_COLSPEC };
089
090    /**
091     * Specifies the rows of the initial FormLayout used in constructors.
092     */
093    private static final RowSpec[] ROW_SPECS = new RowSpec[] {};
094
095    /**
096     * The client property key used to indicate that a button shall
097     * get narrow margins on the left and right hand side.<p>
098     *
099     * This optional setting will be honored by all JGoodies Look&amp;Feel
100     * implementations. The Mac Aqua l&amp;f uses narrow margins only.
101     * Other look&amp;feel implementations will likely ignore this key
102     * and so may render a wider button margin.
103     */
104    private static final String NARROW_KEY = "jgoodies.isNarrow";
105
106    // Instance Creation ****************************************************
107
108    /**
109     * Constructs an instance of <code>ButtonStackBuilder</code> on a default
110     * <code>JPanel</code> using a preconfigured FormLayout as layout manager.
111     */
112    public ButtonStackBuilder() {
113        this(new JPanel(null));
114    }
115
116    /**
117     * Constructs an instance of <code>ButtonStackBuilder</code> on the given
118     * panel using a preconfigured FormLayout as layout manager.
119     *
120     * @param panel   the layout container
121     */
122    public ButtonStackBuilder(JPanel panel) {
123        super(new FormLayout(COL_SPECS, ROW_SPECS), panel);
124    }
125
126    // Adding Components ****************************************************
127
128    /**
129     * Adds a sequence of related buttons separated by a default gap.
130     *
131     * @param buttons  an array of buttons to add
132     */
133    public void addButtons(JButton[] buttons) {
134        for (int i = 0; i < buttons.length; i++) {
135            addGridded(buttons[i]);
136            if (i < buttons.length - 1) {
137                addRelatedGap();
138            }
139        }
140    }
141
142    /**
143     * Adds a fixed size component.
144     *
145     * @param component  the component to add
146     */
147    public void addFixed(JComponent component) {
148        getLayout().appendRow(FormFactory.PREF_ROWSPEC);
149        add(component);
150        nextRow();
151    }
152
153    /**
154     * Adds a gridded component.
155     *
156     * @param component  the component to add
157     */
158    public void addGridded(JComponent component) {
159        getLayout().appendRow(FormFactory.PREF_ROWSPEC);
160        getLayout().addGroupedRow(getRow());
161        component.putClientProperty(NARROW_KEY, Boolean.TRUE);
162        add(component);
163        nextRow();
164    }
165
166    /**
167     * Adds a glue that will be given the extra space,
168     * if this box is larger than its preferred size.
169     */
170    public void addGlue() {
171        appendGlueRow();
172        nextRow();
173    }
174
175    /**
176     * Adds the standard gap for related components.
177     */
178    public void addRelatedGap() {
179        appendRelatedComponentsGapRow();
180        nextRow();
181    }
182
183    /**
184     * Adds the standard gap for unrelated components.
185     */
186    public void addUnrelatedGap() {
187        appendUnrelatedComponentsGapRow();
188        nextRow();
189    }
190
191    /**
192     * Adds a strut of a specified size.
193     *
194     * @param size  a constant that describes the gap
195     */
196    public void addStrut(ConstantSize size) {
197        getLayout().appendRow(new RowSpec(RowSpec.TOP, size, FormSpec.NO_GROW));
198        nextRow();
199    }
200
201}