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

net.java.truelicense.swing.nexes.Wizard Maven / Gradle / Ivy

Go to download

The TrueLicense Swing module provides a graphical user interface for consuming license keys.

There is a newer version: 2.6.6
Show newest version
/*
 * 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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy