    001    /* ========================================================================
    002     * JCommon : a free general purpose class library for the Java(tm) platform
    003     * ========================================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jcommon/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * -----------------
    028     * WizardDialog.java
    029     * -----------------
    030     * (C) Copyright 2000-2004, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: WizardDialog.java,v 1.6 2007/11/02 17:50:36 taqua Exp $
    036     *
    037     * Changes (from 26-Oct-2001)
    038     * --------------------------
    039     * 26-Oct-2001 : Changed package to com.jrefinery.ui.*;
    040     * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
    041     *
    042     */
    043
    044    package org.jfree.ui;
    045
    046    import java.awt.BorderLayout;
    047    import java.awt.Container;
    048    import java.awt.event.ActionEvent;
    049    import java.awt.event.ActionListener;
    050    import java.util.ArrayList;
    051    import javax.swing.BorderFactory;
    052    import javax.swing.JButton;
    053    import javax.swing.JDialog;
    054    import javax.swing.JFrame;
    055    import javax.swing.JPanel;
    056
    057    /**
    058     * A dialog that presents the user with a sequence of steps for completing a task.  The dialog
    059     * contains "Next" and "Previous" buttons, allowing the user to navigate through the task.
    060     * <P>
    061     * When the user backs up by one or more steps, the dialog keeps the completed steps so that
    062     * they can be reused if the user doesn't change anything - this handles the cases where the user
    063     * backs up a few steps just to review what has been completed.
    064     * <p>
    065     * But if the user changes some options in an earlier step, then the dialog may have to discard
    066     * the later steps and have them repeated.
    067     * <P>
    068     * THIS CLASS IS NOT WORKING CORRECTLY YET.
    069     *
    070     *
    071     * @author David Gilbert
    072     */
    073    public class WizardDialog extends JDialog implements ActionListener {
    074
    075        /** The end result of the wizard sequence. */
    076        private Object result;
    077
    078        /** The current step in the wizard process (starting at step zero). */
    079        private int step;
    080
    081        /** A reference to the current panel. */
    082        private WizardPanel currentPanel;
    083
    084        /** A list of references to the panels the user has already seen - used for navigating through
    085            the steps that have already been completed. */
    086        private java.util.List panels;
    087
    088        /** A handy reference to the "previous" button. */
    089        private JButton previousButton;
    090
    091        /** A handy reference to the "next" button. */
    092        private JButton nextButton;
    093
    094        /** A handy reference to the "finish" button. */
    095        private JButton finishButton;
    096
    097        /** A handy reference to the "help" button. */
    098        private JButton helpButton;
    099
    100        /**
    101         * Standard constructor - builds and returns a new WizardDialog.
    102         *
    103         * @param owner  the owner.
    104         * @param modal  modal?
    105         * @param title  the title.
    106         * @param firstPanel  the first panel.
    107         */
    108        public WizardDialog(final JDialog owner, final boolean modal,
    109                            final String title, final WizardPanel firstPanel) {
    110
    111            super(owner, title + " : step 1", modal);
    112            this.result = null;
    113            this.currentPanel = firstPanel;
    114            this.step = 0;
    115            this.panels = new ArrayList();
    116            this.panels.add(firstPanel);
    117            setContentPane(createContent());
    118
    119        }
    120
    121        /**
    122         * Standard constructor - builds a new WizardDialog owned by the specified JFrame.
    123         *
    124         * @param owner  the owner.
    125         * @param modal  modal?
    126         * @param title  the title.
    127         * @param firstPanel  the first panel.
    128         */
    129        public WizardDialog(final JFrame owner, final boolean modal,
    130                            final String title, final WizardPanel firstPanel) {
    131
    132            super(owner, title + " : step 1", modal);
    133            this.result = null;
    134            this.currentPanel = firstPanel;
    135            this.step = 0;
    136            this.panels = new ArrayList();
    137            this.panels.add(firstPanel);
    138            setContentPane(createContent());
    139        }
    140
    141        /**
    142         * Returns the result of the wizard sequence.
    143         *
    144         * @return the result.
    145         */
    146        public Object getResult() {
    147            return this.result;
    148        }
    149
    150        /**
    151         * Returns the total number of steps in the wizard sequence, if this number is known.  Otherwise
    152         * this method returns zero.  Subclasses should override this method unless the number of steps
    153         * is not known.
    154         *
    155         * @return the number of steps.
    156         */
    157        public int getStepCount() {
    158            return 0;
    159        }
    160
    161        /**
    162         * Returns true if it is possible to back up to the previous panel, and false otherwise.
    163         *
    164         * @return boolean.
    165         */
    166        public boolean canDoPreviousPanel() {
    167            return (this.step > 0);
    168        }
    169
    170        /**
    171         * Returns true if there is a 'next' panel, and false otherwise.
    172         *
    173         * @return boolean.
    174         */
    175        public boolean canDoNextPanel() {
    176            return this.currentPanel.hasNextPanel();
    177        }
    178
    179        /**
    180         * Returns true if it is possible to finish the sequence at this point (possibly with defaults
    181         * for the remaining entries).
    182         *
    183         * @return boolean.
    184         */
    185        public boolean canFinish() {
    186            return this.currentPanel.canFinish();
    187        }
    188
    189        /**
    190         * Returns the panel for the specified step (steps are numbered from zero).
    191         *
    192         * @param step  the current step.
    193         *
    194         * @return the panel.
    195         */
    196        public WizardPanel getWizardPanel(final int step) {
    197            if (step < this.panels.size()) {
    198                return (WizardPanel) this.panels.get(step);
    199            }
    200            else {
    201                return null;
    202            }
    203        }
    204
    205        /**
    206         * Handles events.
    207         *
    208         * @param event  the event.
    209         */
    210        public void actionPerformed(final ActionEvent event) {
    211            final String command = event.getActionCommand();
    212            if (command.equals("nextButton")) {
    213                next();
    214            }
    215            else if (command.equals("previousButton")) {
    216                previous();
    217            }
    218            else if (command.equals("finishButton")) {
    219                finish();
    220            }
    221        }
    222
    223        /**
    224         * Handles a click on the "previous" button, by displaying the previous panel in the sequence.
    225         */
    226        public void previous() {
    227            if (this.step > 0) {
    228                final WizardPanel previousPanel = getWizardPanel(this.step - 1);
    229                // tell the panel that we are returning
    230                previousPanel.returnFromLaterStep();
    231                final Container content = getContentPane();
    232                content.remove(this.currentPanel);
    233                content.add(previousPanel);
    234                this.step = this.step - 1;
    235                this.currentPanel = previousPanel;
    236                setTitle("Step " + (this.step + 1));
    237                enableButtons();
    238                pack();
    239            }
    240        }
    241
    242        /**
    243         * Displays the next step in the wizard sequence.
    244         */
    245        public void next() {
    246
    247            WizardPanel nextPanel = getWizardPanel(this.step + 1);
    248            if (nextPanel != null) {
    249                if (!this.currentPanel.canRedisplayNextPanel()) {
    250                    nextPanel = this.currentPanel.getNextPanel();
    251                }
    252            }
    253            else {
    254                nextPanel = this.currentPanel.getNextPanel();
    255            }
    256
    257            this.step = this.step + 1;
    258            if (this.step < this.panels.size()) {
    259                this.panels.set(this.step, nextPanel);
    260            }
    261            else {
    262                this.panels.add(nextPanel);
    263            }
    264
    265            final Container content = getContentPane();
    266            content.remove(this.currentPanel);
    267            content.add(nextPanel);
    268
    269            this.currentPanel = nextPanel;
    270            setTitle("Step " + (this.step + 1));
    271            enableButtons();
    272            pack();
    273
    274        }
    275
    276        /**
    277         * Finishes the wizard.
    278         */
    279        public void finish() {
    280            this.result = this.currentPanel.getResult();
    281            setVisible(false);
    282        }
    283
    284        /**
    285         * Enables/disables the buttons according to the current step.  A good idea would be to ask the
    286         * panels to return the status...
    287         */
    288        private void enableButtons() {
    289            this.previousButton.setEnabled(this.step > 0);
    290            this.nextButton.setEnabled(canDoNextPanel());
    291            this.finishButton.setEnabled(canFinish());
    292            this.helpButton.setEnabled(false);
    293        }
    294
    295        /**
    296         * Checks, whether the user cancelled the dialog.
    297         *
    298         * @return false.
    299         */
    300        public boolean isCancelled() {
    301            return false;
    302        }
    303
    304        /**
    305         * Creates a panel containing the user interface for the dialog.
    306         *
    307         * @return the panel.
    308         */
    309        public JPanel createContent() {
    310
    311            final JPanel content = new JPanel(new BorderLayout());
    312            content.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
    313            content.add((JPanel) this.panels.get(0));
    314            final L1R3ButtonPanel buttons = new L1R3ButtonPanel("Help", "Previous", "Next", "Finish");
    315
    316            this.helpButton = buttons.getLeftButton();
    317            this.helpButton.setEnabled(false);
    318
    319            this.previousButton = buttons.getRightButton1();
    320            this.previousButton.setActionCommand("previousButton");
    321            this.previousButton.addActionListener(this);
    322            this.previousButton.setEnabled(false);
    323
    324            this.nextButton = buttons.getRightButton2();
    325            this.nextButton.setActionCommand("nextButton");
    326            this.nextButton.addActionListener(this);
    327            this.nextButton.setEnabled(true);
    328
    329            this.finishButton = buttons.getRightButton3();
    330            this.finishButton.setActionCommand("finishButton");
    331            this.finishButton.addActionListener(this);
    332            this.finishButton.setEnabled(false);
    333
    334            buttons.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
    335            content.add(buttons, BorderLayout.SOUTH);
    336
    337            return content;
    338        }
    339
    340    }