/** * Copyright (c) 2003, Spellcast development team * http://spellcast.dev.java.net/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * [1] Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * [2] 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. * [3] Neither the name "Spellcast development team" 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 net.java.dev.spellcast.utilities; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.LayoutManager; import java.awt.event.ActionListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SpringLayout; import javax.swing.SwingConstants; import org.jdesktop.swingx.JXCollapsiblePane; import com.sun.java.forums.SpringUtilities; public abstract class ActionVerifyPanel extends ActionPanel { protected VerifiableElement[] elements; protected JPanel container; protected JPanel mainContainer; protected JPanel eastContainer; private String confirmedText, cancelledText1, cancelledText2; private ActionListener confirmListener, cancelListener; private VerifyButtonPanel buttonPanel; private final boolean isCenterPanel; private final Dimension left, right; private static final Dimension DEFAULT_LEFT = new Dimension( 100, 20 ); private static final Dimension DEFAULT_RIGHT = new Dimension( 165, 20 ); public ActionVerifyPanel() { this( null, null, ActionVerifyPanel.DEFAULT_LEFT, ActionVerifyPanel.DEFAULT_RIGHT, false ); } public ActionVerifyPanel( final String confirmedText ) { this( confirmedText, null, null, ActionVerifyPanel.DEFAULT_LEFT, ActionVerifyPanel.DEFAULT_RIGHT, false ); } public ActionVerifyPanel( final String confirmedText, final boolean isCenterPanel ) { this( confirmedText, null, null, ActionVerifyPanel.DEFAULT_LEFT, ActionVerifyPanel.DEFAULT_RIGHT, isCenterPanel ); } public ActionVerifyPanel( final Dimension left, final Dimension right ) { this( null, null, left, right, false ); } public ActionVerifyPanel( final Dimension left, final Dimension right, final boolean isCenterPanel ) { this( null, null, left, right, isCenterPanel ); } public ActionVerifyPanel( final String confirmedText, final Dimension left, final Dimension right, final boolean isCenterPanel ) { this( confirmedText, null, null, left, right, isCenterPanel ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText ) { this( confirmedText, cancelledText, ActionVerifyPanel.DEFAULT_LEFT, ActionVerifyPanel.DEFAULT_RIGHT, false ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText, final boolean isCenterPanel ) { this( confirmedText, cancelledText, ActionVerifyPanel.DEFAULT_LEFT, ActionVerifyPanel.DEFAULT_RIGHT, isCenterPanel ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText1, final String cancelledText2 ) { this( confirmedText, cancelledText1, cancelledText2, ActionVerifyPanel.DEFAULT_LEFT, ActionVerifyPanel.DEFAULT_RIGHT, false ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText, final Dimension left, final Dimension right ) { this( confirmedText, cancelledText, left, right, false ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText1, final String cancelledText2, final Dimension left, final Dimension right ) { this( confirmedText, cancelledText1, cancelledText2, left, right, false ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText, final Dimension left, final Dimension right, final boolean isCenterPanel ) { this( confirmedText, cancelledText, cancelledText, left, right, isCenterPanel ); } public ActionVerifyPanel( final String confirmedText, final String cancelledText1, final String cancelledText2, final Dimension left, final Dimension right, final boolean isCenterPanel ) { this.contentSet = false; this.left = left; this.right = right; this.isCenterPanel = isCenterPanel; this.confirmedText = confirmedText; this.cancelledText1 = cancelledText1; this.cancelledText2 = cancelledText2; } protected void setListeners( ActionListener confirmListener, ActionListener cancelListener ) { this.confirmListener = confirmListener; this.cancelListener = cancelListener; if ( this.confirmedText != null && !this.confirmedText.equals( "" ) ) { this.buttonPanel = new VerifyButtonPanel( this.confirmedText, this.cancelledText1, this.cancelledText2, this.confirmListener, this.cancelListener ); } } protected void setContent( final VerifiableElement[] elements ) { this.setContent( elements, false ); } protected void setContent( final VerifiableElement[] elements, final boolean bothDisabledOnClick ) { if ( this.contentSet ) { return; } this.elements = elements; this.container = new JPanel(); this.container.setLayout( new BorderLayout( 10, 10 ) ); this.container.add( Box.createVerticalStrut( 2 ), BorderLayout.NORTH ); // add the main container this.container.add( this.constructMainContainer( elements ), BorderLayout.CENTER ); // construct the east container, which usually consists of only the // button panel, if an east panel is not specified; if one happens // to be specified, then it appears above the button panel this.eastContainer = new JPanel(); this.eastContainer.setLayout( new BorderLayout( 10, 10 ) ); if ( this.buttonPanel != null ) { this.eastContainer.add( this.buttonPanel, BorderLayout.NORTH ); } this.container.add( this.eastContainer, BorderLayout.EAST ); JPanel cardContainer = new JPanel(); cardContainer.setLayout( new CardLayout( 10, 10 ) ); cardContainer.add( this.container, "" ); this.setLayout( new BorderLayout() ); this.add( cardContainer, this.isCenterPanel ? BorderLayout.CENTER : BorderLayout.NORTH ); this.contentSet = true; if ( this.buttonPanel != null ) { this.buttonPanel.setBothDisabledOnClick( bothDisabledOnClick ); } } private JPanel constructMainContainer( final VerifiableElement[] elements ) { JPanel mainContainer = new JPanel(); mainContainer.setLayout( new BoxLayout( mainContainer, BoxLayout.Y_AXIS ) ); if ( elements == null || elements.length == 0 ) { return mainContainer; } // Layout the elements using springs // instead of standard panel elements. int springCount = 0; JPanel currentContainer = null; for ( int i = 0; i < elements.length; ++i ) { VerifiableElement element = elements[ i ]; boolean hideable = element instanceof HideableVerifiableElement; boolean isInputPreceding = element.isInputPreceding(); JLabel label = element.getLabel(); JComponent inputField = element.getInputField(); boolean shouldResize = element.shouldResize(); if ( isInputPreceding && ( inputField instanceof JCheckBox || inputField instanceof JRadioButton ) ) { if ( springCount > 0 ) { SpringUtilities.makeCompactGrid( currentContainer, springCount, 2, 5, 5, 5, 5 ); springCount = 0; mainContainer.add( currentContainer ); currentContainer = null; } if ( currentContainer == null ) { currentContainer = new JPanel(); currentContainer.setLayout( new BoxLayout( currentContainer, BoxLayout.Y_AXIS ) ); currentContainer.setAlignmentX( Component.LEFT_ALIGNMENT ); } if ( inputField instanceof JCheckBox ) { ( (JCheckBox) inputField ).setText( label.getText() ); } else if ( inputField instanceof JRadioButton ) { ( (JRadioButton) inputField ).setText( label.getText() ); } currentContainer.add( inputField ); currentContainer.add( Box.createVerticalStrut( 5 ) ); } else if ( inputField instanceof JLabel && label.getText().equals( "" ) ) { if ( currentContainer == null ) { GridLayout layout = new GridLayout( 0, 1, 5, 5 ); currentContainer = new JPanel( layout ); currentContainer.setAlignmentX( Component.LEFT_ALIGNMENT ); } if ( springCount == 0 ) { currentContainer.add( inputField ); } else { JComponentUtilities.setComponentSize( label, isInputPreceding ? this.right : this.left ); JComponentUtilities.setComponentSize( inputField, isInputPreceding ? this.left : this.right ); currentContainer.add( isInputPreceding ? inputField : label ); currentContainer.add( isInputPreceding ? label : inputField ); ++springCount; } } else { if ( shouldResize ) { JComponentUtilities.setComponentSize( label, isInputPreceding ? this.right : this.left ); JComponentUtilities.setComponentSize( inputField, isInputPreceding ? this.left : this.right ); } if ( hideable ) { if ( springCount > 0 ) { SpringUtilities.makeCompactGrid( currentContainer, springCount, 2, 5, 5, 5, 5 ); springCount = 0; } if ( currentContainer != null ) { mainContainer.add( currentContainer ); currentContainer = null; } HideablePanel container = new HideablePanel( new SpringLayout() ); container.setAlignmentX( Component.LEFT_ALIGNMENT ); container.add( isInputPreceding ? inputField : label ); container.add( isInputPreceding ? label : inputField ); SpringUtilities.makeCompactGrid( container.getContentPane(), 1, 2, 5, 5, 5, 5 ); mainContainer.add( container ); } else { if ( currentContainer == null ) { currentContainer = new JPanel( new SpringLayout() ); currentContainer.setAlignmentX( Component.LEFT_ALIGNMENT ); } else if ( springCount == 0 ) { mainContainer.add( currentContainer ); currentContainer = new JPanel( new SpringLayout() ); currentContainer.setAlignmentX( Component.LEFT_ALIGNMENT ); } ++springCount; currentContainer.add( isInputPreceding ? inputField : label ); currentContainer.add( isInputPreceding ? label : inputField ); } } } if ( springCount > 0 ) { SpringUtilities.makeCompactGrid( currentContainer, springCount, 2, 5, 5, 5, 5 ); } if ( currentContainer != null ) { mainContainer.add( currentContainer ); } this.mainContainer = mainContainer; JPanel holder = new JPanel( new BorderLayout() ); holder.add( mainContainer, BorderLayout.NORTH ); return holder; } public void hideOrShowElements() { if ( this.elements == null ) { return; } Component[] components = this.mainContainer.getComponents(); int componentIndex = 0; for ( VerifiableElement element : this.elements ) { if ( element instanceof HideableVerifiableElement ) { HideableVerifiableElement hideableElement = (HideableVerifiableElement) element; boolean shouldBeHidden = hideableElement.isHidden(); while ( componentIndex < components.length ) { Component component = components[ componentIndex++ ]; if ( component instanceof HideablePanel ) { HideablePanel hideablePanel = (HideablePanel) component; boolean isHidden = hideablePanel.isCollapsed(); if ( shouldBeHidden != isHidden ) { hideablePanel.setCollapsed( shouldBeHidden ); } } } } } } @Override public void setEnabled( final boolean isEnabled ) { if ( this.buttonPanel != null ) { this.buttonPanel.setEnabled( isEnabled ); } } @Override public abstract void actionConfirmed(); @Override public abstract void actionCancelled(); @Override public void dispose() { if ( this.buttonPanel != null ) { this.buttonPanel.dispose(); } if ( this.elements != null ) { for ( int i = 0; i < this.elements.length; ++i ) { this.elements[ i ].removeListeners( this.elements[ i ].getInputField() ); this.elements[ i ] = null; } } } protected class HideablePanel extends JXCollapsiblePane { public HideablePanel() { super(); this.initialize(); } public HideablePanel( LayoutManager layout) { super(); this.setLayout( layout ); this.initialize(); } private void initialize() { this.setMinimumSize( new Dimension( 0, 0 ) ); // collapse all the way when hidden this.setAnimated( false ); } } protected class VerifiableElement implements Comparable { private final JLabel label; private final boolean shouldResize; private final JComponent inputField; private final boolean isInputPreceding; public VerifiableElement() { this( "", SwingConstants.RIGHT, new JLabel( " " ), false ); } public VerifiableElement( final JTextArea text ) { this( "", SwingConstants.RIGHT, text, false ); } public VerifiableElement( final JComponent inputField ) { this( "", SwingConstants.RIGHT, inputField, !( inputField instanceof JScrollPane || inputField instanceof JCheckBox ) ); } public VerifiableElement( final String label, final JComponent inputField ) { this( label, SwingConstants.RIGHT, inputField, !( inputField instanceof JScrollPane || inputField instanceof JCheckBox ) ); } public VerifiableElement( final String label, final JComponent inputField, final boolean shouldResize ) { this( label, SwingConstants.RIGHT, inputField, shouldResize ); } public VerifiableElement( final String label, final int direction, final JComponent inputField ) { this( label, direction, inputField, !( inputField instanceof JScrollPane || inputField instanceof JCheckBox ) ); } public VerifiableElement( final String label, final int direction, final JComponent inputField, final boolean shouldResize ) { this.label = new JLabel( label, direction ); this.inputField = inputField; this.shouldResize = shouldResize; this.isInputPreceding = direction == SwingConstants.LEFT; this.label.setLabelFor( inputField ); this.label.setVerticalAlignment( SwingConstants.TOP ); if ( ActionVerifyPanel.this.buttonPanel == null ) { this.addListeners( inputField ); } } public boolean isInputPreceding() { return this.isInputPreceding; } public void removeListeners( final JComponent c ) { if ( c == null || c instanceof JLabel || c instanceof JButton ) { return; } if ( c instanceof JRadioButton ) { ( (JRadioButton) c ).removeActionListener( ActionVerifyPanel.this.confirmListener ); return; } if ( c instanceof JCheckBox ) { ( (JCheckBox) c ).removeActionListener( ActionVerifyPanel.this.confirmListener ); return; } if ( c instanceof JComboBox ) { ( (JComboBox) c ).removeActionListener( ActionVerifyPanel.this.confirmListener ); return; } for ( int i = 0; i < c.getComponentCount(); ++i ) { if ( !( c instanceof JLabel || c instanceof JButton ) ) { this.removeListeners( (JComponent) c.getComponent( i ) ); } } } private void addListeners( final JComponent c ) { if ( c == null || c instanceof JLabel || c instanceof JButton ) { return; } if ( c instanceof JRadioButton ) { ( (JRadioButton) c ).addActionListener( ActionVerifyPanel.this.confirmListener ); return; } if ( c instanceof JCheckBox ) { ( (JCheckBox) c ).addActionListener( ActionVerifyPanel.this.confirmListener ); return; } if ( c instanceof JComboBox ) { ( (JComboBox) c ).addActionListener( ActionVerifyPanel.this.confirmListener ); return; } for ( int i = 0; i < c.getComponentCount(); ++i ) { if ( !( c instanceof JLabel || c instanceof JButton ) ) { this.addListeners( (JComponent) c.getComponent( i ) ); } } } public JLabel getLabel() { return this.label; } public JComponent getInputField() { return this.inputField; } public boolean shouldResize() { return this.shouldResize; } public int compareTo( final Object o ) { return o == null || !( o instanceof VerifiableElement ) ? -1 : this.label.getText().compareTo( ( (VerifiableElement) o ).label.getText() ); } } public abstract class HideableVerifiableElement extends VerifiableElement { public HideableVerifiableElement( final String label, final JComponent inputField ) { super( label, inputField ); } public abstract boolean isHidden(); } }