net.java.truelicense.swing.nexes.Wizard Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of truelicense-swing Show documentation
Show all versions of truelicense-swing Show documentation
The TrueLicense Swing module provides a graphical user interface for
consuming license keys.
/*
* Copyright (C) 2005-2013 Schlichtherle IT Services.
* All rights reserved. Use is subject to license terms.
*/
package net.java.truelicense.swing.nexes;
import java.awt.*;
import java.beans.*;
import javax.annotation.CheckForNull;
import javax.swing.*;
import javax.swing.border.*;
import net.java.truelicense.core.util.Objects;
import static net.java.truelicense.swing.nexes.Messages.*;
import static net.java.truelicense.swing.nexes.WizardModel.*;
import net.java.truelicense.swing.util.EnhancedButton;
import net.java.truelicense.swing.util.EnhancedDialog;
/**
* Implements a basic wizard dialog, where the developer can insert one or more
* Components to act as panels. These panels can be navigated through
* arbitrarily using the 'Next' or 'Back' buttons, or the dialog itself can be
* closed using the 'Cancel' button. Note that even though the dialog uses a
* CardLayout manager, the order of the panels is not necessarily linear. Each
* panel determines at runtime what its next and previous panel should be.
*
* @author Robert Eckstein (original code)
* @author Christian Schlichtherle (revision)
*/
public class Wizard implements PropertyChangeListener {
/**
* Indicates that the 'Finish' button was pressed to close the dialog.
*/
public static final int FINISH_RETURN_CODE = 0;
/**
* Indicates that the 'Cancel' button was pressed to close the dialog.
*/
public static final int CANCEL_RETURN_CODE = 1;
/**
* Indicates that the dialog closed due to an internal error.
*/
public static final int ERROR_RETURN_CODE = 2;
/**
* The String-based action command for the 'Next' button.
*/
public static final String NEXT_BUTTON_ACTION_COMMAND
= "NextButtonActionCommand"; // NOI18N
/**
* The String-based action command for the 'Back' button.
*/
public static final String BACK_BUTTON_ACTION_COMMAND
= "BackButtonActionCommand"; // NOI18N
/**
* The String-based action command for the 'Cancel' button.
*/
public static final String CANCEL_BUTTON_ACTION_COMMAND
= "CancelButtonActionCommand"; // NOI18N
/**
* The default text used for the 'Back' button. Good candidate for i18n.
*/
public static final String DEFAULT_BACK_BUTTON_TEXT
= message("backButton").toString();
/**
* The default text used for the 'Next' button. Good candidate for i18n.
*/
public static final String DEFAULT_NEXT_BUTTON_TEXT
= message("nextButton").toString();
/**
* The default text used for the 'Finish' button. Good candidate for i18n.
*/
public static final String DEFAULT_FINISH_BUTTON_TEXT
= message("finishButton").toString();
/**
* The default text used for the 'Cancel' button. Good candidate for i18n.
*/
public static final String DEFAULT_CANCEL_BUTTON_TEXT
= message("cancelButton").toString();
private final WizardModel model;
private WizardController controller;
private final EnhancedDialog dialog;
private int returnCode;
private JPanel cardPanel;
private CardLayout cardLayout;
private EnhancedButton backButton;
private EnhancedButton nextButton;
private EnhancedButton cancelButton;
/**
* Default constructor. This method creates a new WizardModel object and
* passes it into the overloaded constructor.
*/
public Wizard() { this(new WizardModel(), (Frame) null); }
/**
* This method creates a new WizardModel object and passes it into the
* overloaded constructor. It accepts a java.awt.Dialog object as the
* javax.swing.JDialog's parent.
*
* @param owner The java.awt.Dialog object that is the owner of this dialog.
*/
public Wizard(@CheckForNull Dialog owner) { this(new WizardModel(), owner); }
/**
* This method creates a new WizardModel object and passes it into the
* overloaded constructor. It accepts a java.awt.Dialog object as the
* javax.swing.JDialog's parent.
*
* @param owner The java.awt.Frame object that is the owner of the
* javax.swing.JDialog.
*/
public Wizard(@CheckForNull Frame owner) { this(new WizardModel(), owner); }
/**
* This constructor accepts a WizardModel object and a java.awt.Dialog
* object as the wizard's JDialog's parent.
*
* @param model The WizardModel object that serves as the model for the
* wizard dialog.
* @param owner The java.awt.Dialog that is the owner of the generated
* javax.swing.JDialog.
*/
public Wizard(final WizardModel model, final @CheckForNull Dialog owner) {
dialog = new EnhancedDialog(owner);
this.model = model;
initComponents();
}
/**
* This constructor accepts a WizardModel object and a java.awt.Frame object
* as the wizard's javax.swing.JDialog's parent.
*
* @param model The WizardModel object that serves as the model for this
* component.
* @param owner The java.awt.Frame object that serves as the parent of the
* generated javax.swing.JDialog.
*/
public Wizard(final WizardModel model, final @CheckForNull Frame owner) {
dialog = new EnhancedDialog(owner);
this.model = model;
initComponents();
}
/**
* Returns the dialog generated by this wizard.
*/
public JDialog getDialog() { return dialog; }
/**
* Returns the owner of the generated dialog.
* The returned component should be an instance of {@link Frame} or
* {@link Dialog}.
*/
public @CheckForNull Window getDialogOwner() { return getDialog().getOwner(); }
/**
* Returns the title of the generated dialog.
*/
public String getDialogTitle() { return getDialog().getTitle(); }
/**
* Sets the title of the generated dialog.
*/
public void setDialogTitle(String s) { getDialog().setTitle(s); }
/**
* Returns the modality of the dialog.
*
* @return A boolean indicating whether or not the generated
* javax.swing.JDialog is modal.
*/
public boolean isDialogModal() { return getDialog().isModal(); }
/**
* Sets the modality of the generated dialog.
*/
public void setDialogModal(boolean modal) { getDialog().setModal(modal); }
/**
* Convenience method that packs and displays the modal wizard dialog.
*
* @return An integer that identifies how the dialog was closed.
* See RETURN_CODE constants at the beginning of this class.
* @throws NullPointerException If the panel to be displayed initially has
* not been set.
* @see #setCurrentPanelDescriptor(WizardPanelDescriptor)
*/
public int showModalDialog() {
final JDialog dialog = getDialog();
//dialog.pack();
dialog.setLocationRelativeTo(dialog.getOwner());
dialog.setModal(true);
dialog.setVisible(true);
return returnCode;
}
/**
* Returns the current model of the wizard dialog.
*
* @return A WizardModel instance, which serves as the model for the wizard
* dialog.
*/
public WizardModel getModel() { return model; }
/** Adds the given wizard panel getPanelDescriptor to this wizard dialog. */
public void addPanelDescriptor(final WizardPanelDescriptor wpd) {
cardPanel.add(wpd.getPanel(), wpd.getIdentifier());
wpd.setWizard(this);
model.addPanelDescriptor(wpd);
getDialog().pack();
}
/** Returns the current wizard panel getPanelDescriptor. */
public @CheckForNull WizardPanelDescriptor getCurrentPanelDescriptor() {
return model.getCurrentPanelDescriptor();
}
/** Sets the current wizard panel getPanelDescriptor. */
public void setCurrentPanelDescriptor(final @CheckForNull WizardPanelDescriptor nwpd) {
final WizardPanelDescriptor owpd = model.getCurrentPanelDescriptor();
if (Objects.equals(owpd, nwpd)) return;
if (null != owpd) owpd.aboutToHidePanel();
model.setCurrentPanelDescriptor(nwpd);
if (null != nwpd) {
nwpd.aboutToDisplayPanel();
cardLayout.show(cardPanel, nwpd.getIdentifier());
nwpd.displayingPanel();
}
}
public void setCurrentPanelIdentifier(@CheckForNull String id) {
setCurrentPanelDescriptor(getModel().getPanelDescriptor(id));
}
/**
* Method used to listen for property change events from the model and
* update the dialog's components as necessary.
*
* @param evt PropertyChangeEvent passed from the model to signal that one
* of its properties has changed value.
*/
@Override
public void propertyChange(final PropertyChangeEvent evt) {
final String name = evt.getPropertyName();
if (CURRENT_PANEL_DESCRIPTOR_PROPERTY.equals(name))
controller.resetButtonsToPanelRules();
else if (BACK_BUTTON_TEXT_PROPERTY.equals(name))
backButton.setText(evt.getNewValue().toString());
else if (NEXT_BUTTON_TEXT_PROPERTY.equals(name))
nextButton.setText(evt.getNewValue().toString());
else if (CANCEL_BUTTON_TEXT_PROPERTY.equals(name))
cancelButton.setText(evt.getNewValue().toString());
else if (BACK_BUTTON_ENABLED_PROPERTY.equals(name))
backButton.setEnabled(((Boolean) evt.getNewValue()).booleanValue());
else if (NEXT_BUTTON_ENABLED_PROPERTY.equals(name))
nextButton.setEnabled(((Boolean) evt.getNewValue()).booleanValue());
else if (CANCEL_BUTTON_ENABLED_PROPERTY.equals(name))
cancelButton.setEnabled(((Boolean) evt.getNewValue()).booleanValue());
else if (BACK_BUTTON_ICON_PROPERTY.equals(name))
backButton.setIcon((Icon) evt.getNewValue());
else if (NEXT_BUTTON_ICON_PROPERTY.equals(name))
nextButton.setIcon((Icon) evt.getNewValue());
else if (CANCEL_BUTTON_ICON_PROPERTY.equals(name))
cancelButton.setIcon((Icon) evt.getNewValue());
}
/**
* Retrieves the last return code set by the dialog.
*
* @return An integer that identifies how the dialog was closed.
* See RETURN_CODE constants at the beginning of this class.
*/
public int getReturnCode() {
return returnCode;
}
/**
* Closes the dialog and sets the return code to the integer parameter.
*
* @param code The return code.
*/
void close(int code) {
returnCode = code;
dialog.setVisible(false);
}
/**
* This method initializes the components for the wizard dialog: it creates
* a JDialog with a CardLayout panel with a small empty border, as well as
* three buttons at the bottom.
*/
private void initComponents() {
model.addPropertyChangeListener(this);
controller = new WizardController(this);
backButton = new EnhancedButton();
backButton.setName("back");
backButton.setActionCommand(BACK_BUTTON_ACTION_COMMAND);
backButton.addActionListener(controller);
nextButton = new EnhancedButton();
nextButton.setName("next");
nextButton.setActionCommand(NEXT_BUTTON_ACTION_COMMAND);
nextButton.addActionListener(controller);
cancelButton = new EnhancedButton();
cancelButton.setName("cancel");
cancelButton.setActionCommand(CANCEL_BUTTON_ACTION_COMMAND);
cancelButton.addActionListener(controller);
final Border border = new EmptyBorder(new Insets(10, 10, 10, 10));
final Box buttonBox = new Box(BoxLayout.LINE_AXIS);
buttonBox.setBorder(border);
buttonBox.add(backButton);
buttonBox.add(Box.createHorizontalStrut(10));
buttonBox.add(nextButton);
buttonBox.add(Box.createHorizontalStrut(30));
buttonBox.add(cancelButton);
// Create the buttons with a separator above them, then place them
// on the east side of the panel with a small amount of space between
// the back and the next button, and a larger amount of space between
// the next button and the cancel button.
final JPanel buttonPanel = new JPanel(new BorderLayout());
buttonPanel.add(new JSeparator(), BorderLayout.NORTH);
buttonPanel.add(buttonBox, BorderLayout.EAST);
cardLayout = new CardLayout();
cardPanel = new JPanel(cardLayout);
cardPanel.setBorder(border);
dialog.setName("wizardDialog");
dialog.setLayout(new BorderLayout());
dialog.add(cardPanel, BorderLayout.CENTER);
dialog.add(buttonPanel, BorderLayout.SOUTH);
dialog.setDefaultButton(nextButton);
if (null == model.getBackButtonText())
model.setBackButtonText(Wizard.DEFAULT_BACK_BUTTON_TEXT);
if (null == model.getNextButtonText())
model.setNextButtonText(Wizard.DEFAULT_NEXT_BUTTON_TEXT);
if (null == model.getCancelButtonText())
model.setCancelButtonText(Wizard.DEFAULT_CANCEL_BUTTON_TEXT);
}
}