All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jgoodies.forms.builder.ListViewBuilder Maven / Gradle / Ivy

Go to download

The JGoodies Forms framework helps you lay out and implement elegant Swing panels quickly and consistently. It makes simple things easy and the hard stuff possible, the good design easy and the bad difficult.

There is a newer version: 1.9.0
Show newest version
/*
 * Copyright (c) 2002-2014 JGoodies Software GmbH. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  o Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  o Neither the name of JGoodies Software GmbH nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jgoodies.forms.builder;

import static com.jgoodies.common.base.Preconditions.checkNotNull;

import java.awt.FocusTraversalPolicy;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.border.Border;

import com.jgoodies.common.base.Strings;
import com.jgoodies.forms.FormsSetup;
import com.jgoodies.forms.factories.CC;
import com.jgoodies.forms.factories.ComponentFactory;
import com.jgoodies.forms.factories.Forms;
import com.jgoodies.forms.layout.FormLayout;

/**
 * Builds list/table views from a set of mandatory and optional components:
 * label, filter/search,
 * list (table),
 * list buttons, list extras,
 * details view (or preview).

* * Examples:

 * return new ListViewBuilder()
 *     .label("&Contacts:")
 *     .listView(contactsTable)
 *     .listBar(newButton, editButton, deleteButton)
 *     .build();
 *
 * return new ListViewBuilder()
 *     .border(Borders.DLU14)
 *     .labelView(contactsLabel)
 *     .filterView(contactsSearchField)
 *     .listView(contactsTable)
 *     .listBar(newButton, editButton, deleteButton, null, printButton)
 *     .detailsView(contactDetailsView)
 *     .build();
 * 
* For more examples see the JGoodies Showcase application. * * @author Karsten Lentzsch * @version $Revision: 1.2 $ * * @since 1.6 */ public final class ListViewBuilder { private final ComponentFactory factory; private JComponent labelView; private JComponent filterView; private JComponent listView; private JComponent listBarView; private JComponent listExtrasView; private JComponent detailsView; private Border border; private boolean honorsVisibility = true; private FocusTraversalPolicy focusTraversalPolicy; private String namePrefix = "ListView"; private String filterViewColSpec = "[100dlu, p]"; private String listViewRowSpec = "fill:100dlu:grow"; /** * Holds the panel that has been lazily built in {@code #buildPanel}. */ private JComponent panel; // Instance Creation ****************************************************** /** * Constructs a ListViewBuilder using the AbstractBuilder's * default component factory. The factory is required by * {@link #label(String)} and {@link #headerLabel(String)}. */ public ListViewBuilder() { this(FormsSetup.getComponentFactoryDefault()); } /** * Constructs a ListViewBuilder using the given component factory. * The factory is required by * {@link #label(String)} and {@link #headerLabel(String)}. * * @param factory the component factory used to create labels and headers */ public ListViewBuilder(ComponentFactory factory) { this.factory = factory; } // API ******************************************************************** /** * Sets an optional border that surrounds the list view including * the label and details. * * @param border the border to set */ public ListViewBuilder border(Border border) { this.border = border; invalidatePanel(); return this; } /** * Sets the panel's focus traversal policy and sets the panel * as focus traversal policy provider. Hence, this call is equivalent to: *
     * builder.getPanel().setFocusTraversalPolicy(policy);
     * builder.getPanel().setFocusTraversalPolicyProvider(true);
     * 
* * @param policy the focus traversal policy that will manage * keyboard traversal of the children in this builder's panel * * @see JComponent#setFocusTraversalPolicy(FocusTraversalPolicy) * @see JComponent#setFocusTraversalPolicyProvider(boolean) * * @since 1.7.2 */ public ListViewBuilder focusTraversal(FocusTraversalPolicy policy) { this.focusTraversalPolicy = policy; return this; } /** * Specifies whether invisible components shall be taken into account by * this builder for computing the layout size and setting component bounds. * If set to {@code true} invisible components will be ignored by * the layout. If set to {@code false} components will be taken into * account regardless of their visibility. Visible components are always * used for sizing and positioning.

* * The default value for this setting is {@code true}. * It is useful to set the value to {@code false} (in other words * to ignore the visibility) if you switch the component visibility * dynamically and want the container to retain the size and * component positions. * * @param b {@code true} to honor the visibility, i.e. to exclude * invisible components from the sizing and positioning, * {@code false} to ignore the visibility, in other words to * layout visible and invisible components * * @since 1.7.1 */ public ListViewBuilder honorVisibility(boolean b) { this.honorsVisibility = b; invalidatePanel(); return this; } /** * Sets the prefix that is prepended to component name of components * that have no name set or that are are implicitly created by this builder, * e.g. the (header) label. The default name prefix is "ListView". * @param namePrefix the prefix to be used * * @since 1.7.1 */ public ListViewBuilder namePrefix(String namePrefix) { this.namePrefix = namePrefix; return this; } /** * Sets the mandatory label view. Useful to set a bound label that updates * its text when the list content changes, for example to provide the * number of list elements. * * @param labelView the component that shall label the list view, * often a bound label */ public ListViewBuilder labelView(JComponent labelView) { this.labelView = labelView; setName(labelView, "label"); invalidatePanel(); return this; } /** * Creates a plain label for the given marked text and sets it as label view. * Equivalent to: *

     * labelView(aComponentFactory.createLabel(markedText));
     * 
* * @param markedText the label's text, may contain a mnemonic marker */ public ListViewBuilder label(String markedText) { labelView(factory.createLabel(markedText)); return this; } /** * Creates a header label for the given marked text and sets it as label view. * Equivalent to: *
     * labelView(aComponentFactory.createHeaderLabel(markedText));
     * 
* * @param markedText the label's text, may contain a mnemonic marker */ public ListViewBuilder headerLabel(String markedText) { labelView(factory.createHeaderLabel(markedText)); return this; } /** * Sets an optional view that will be placed in the upper right corner * of the built list view panel. This can be a search field, a panel * with filtering check boxes ("Only valid items"), etc. * * @param filterView the view to be added. */ public ListViewBuilder filterView(JComponent filterView) { this.filterView = filterView; setName(filterView, "filter"); invalidatePanel(); return this; } /** * Changes the FormLayout column specification used to lay out * the filter view. * The default value is {@code "[100dlu, p]"}, which is a column where * the width is determined by the filter view's preferred width, * but a minimum width of 100dlu is ensured. The filter view won't grow * horizontally, if the container gets more space. * * @param colSpec specifies the horizontal layout of the filter view * * @throws NullPointerException if {@code colSpec} is {@code null} */ public ListViewBuilder filterViewColSpec(String colSpec) { checkNotNull(colSpec, "The filter view column specification must not be null."); this.filterViewColSpec = colSpec; invalidatePanel(); return this; } /** * Sets the given component as the the mandatory list view. * If {@code listView} is a JTable, JList, or JTree, it is * automatically wrapped with a JScrollPane, before the scroll pane * is set as list view. * * @param listView the component to be used as scrollable list view * * @throws NullPointerException if {@code listView} is {@code null} */ public ListViewBuilder listView(JComponent listView) { checkNotNull(listView, "The list view must not be null."); if (listView instanceof JTable || listView instanceof JList || listView instanceof JTree) { this.listView = new JScrollPane(listView); } else { this.listView = listView; } setName(listView, "listView"); invalidatePanel(); return this; } /** * Changes the FormLayout row specification used to lay out the list view. * The default value is {@code "fill:[100dlu, pref]:grow"}, which is a row * that is filled by the list view; the height is determined * by the list view's preferred height, but a minimum of 100dlu is ensured. * The list view grows vertically, if the container gets more vertical * space.

* * Examples: *

     * .listViewRowSpec("fill:100dlu");  // fixed height
     * .listViewRowSpec("f:100dlu:g");   // fixed start height, grows
     * .listViewRowSpec("f:p");          // no minimum height
     * 
* * @param rowSpec specifies the vertical layout of the list view * * @throws NullPointerException if {@code rowSpec} is {@code null} */ public ListViewBuilder listViewRowSpec(String rowSpec) { checkNotNull(rowSpec, "The list view row specification must not be null."); this.listViewRowSpec = rowSpec; invalidatePanel(); return this; } /** * Sets an optional list bar - often a button bar - * that will be located in the lower left corner of the list view. * If the list bar view consists only of buttons, * use {@link #listBar(JComponent...)} instead. * * @param listBarView the component to set */ public ListViewBuilder listBarView(JComponent listBarView) { this.listBarView = listBarView; setName(listBarView, "listBarView"); invalidatePanel(); return this; } /** * Builds a button bar using the given buttons and sets it as list bar. * Although JButtons are expected, any JComponent is accepted * to allow custom button component types.

* * Equivalent to {@code listBarView(Forms.buildButtonBar(buttons))}. * * @param buttons the buttons in the list bar * * @throws NullPointerException if {@code buttons} is {@code null} * @throws IllegalArgumentException if no buttons are provided * * @see ButtonBarBuilder#addButton(JComponent...) */ public ListViewBuilder listBar(JComponent... buttons) { listBarView(Forms.buttonBar(buttons)); return this; } /** * Sets an optional view that is located in the lower right corner * of the list view, aligned with the list bar. * * @param listExtrasView the component to set */ public ListViewBuilder listExtrasView(JComponent listExtrasView) { this.listExtrasView = listExtrasView; setName(listExtrasView, "listExtrasView"); invalidatePanel(); return this; } /** * Sets an optional details view that is located under the list view. * Often this is the details view or preview of a master-details view. * * @param detailsView the component to set */ public ListViewBuilder detailsView(JComponent detailsView) { this.detailsView = detailsView; setName(detailsView, "detailsView"); invalidatePanel(); return this; } /** * Lazily builds and returns the list view panel. * * @return the built panel */ public JComponent build() { if (panel == null) { panel = buildPanel(); } return panel; } // Implementation ********************************************************* private void invalidatePanel() { panel = null; } private JComponent buildPanel() { checkNotNull(listView, "The list view must be set before #build is invoked."); FormLayout layout = new FormLayout( "fill:default:grow", "p, " + listViewRowSpec + ", p, p"); layout.setHonorsVisibility(honorsVisibility); PanelBuilder builder = new PanelBuilder(layout); builder.border(border); if (focusTraversalPolicy != null) { builder.focusTraversal(focusTraversalPolicy); } if (labelView != null || filterView != null) { builder.add(buildDecoratedHeaderView(), CC.xy(1, 1)); } builder.add(listView, CC.xy(1, 2)); if (listBarView != null || listExtrasView != null) { builder.add(buildDecoratedListBarAndExtras(), CC.xy(1, 3)); } if (detailsView != null) { builder.add(buildDecoratedDetailsView(), CC.xy(1, 4)); } // Set up the label-for relation - if not already set. if (labelView instanceof JLabel) { JLabel theLabelView = (JLabel) labelView; if (theLabelView.getLabelFor() == null) { theLabelView.setLabelFor(listView); } } return builder.build(); } private JComponent buildDecoratedHeaderView() { String columnSpec = filterView != null ? "default:grow, 9dlu, " + filterViewColSpec : "default:grow, 0, 0"; FormLayout layout = new FormLayout( columnSpec, "[14dlu,p], $lcg"); PanelBuilder builder = new PanelBuilder(layout) .labelForFeatureEnabled(false); if (labelView != null) { builder.add(labelView, CC.xy (1, 1)); } if (filterView != null) { builder.add(filterView, CC.xy (3, 1)); } return builder.build(); } private JComponent buildDecoratedListBarAndExtras() { FormLayout layout = new FormLayout( "left:default, 9dlu:grow, right:pref", "$rgap, p"); layout.setHonorsVisibility(honorsVisibility); PanelBuilder builder = new PanelBuilder(layout); if (listBarView != null) { builder.add(listBarView, CC.xy(1, 2)); } if (listExtrasView != null) { builder.add(listExtrasView, CC.xy(3, 2)); } return builder.build(); } private JComponent buildDecoratedDetailsView() { FormLayout layout = new FormLayout( "fill:default:grow", "14, p"); layout.setHonorsVisibility(honorsVisibility); PanelBuilder builder = new PanelBuilder(layout); builder.add(detailsView, CC.xy(1, 2)); return builder.build(); } // Helper Code ************************************************************ private void setName(JComponent component, String suffix) { if (Strings.isNotBlank(component.getName())) { return; } component.setName(namePrefix + '.' + suffix); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy