Source for org.jfree.ui.WizardDialog

   1: /* ========================================================================
   2:  * JCommon : a free general purpose class library for the Java(tm) platform
   3:  * ========================================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  * 
   7:  * Project Info:  http://www.jfree.org/jcommon/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  * 
  27:  * -----------------
  28:  * WizardDialog.java
  29:  * -----------------
  30:  * (C) Copyright 2000-2004, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: WizardDialog.java,v 1.5 2005/11/16 15:58:41 taqua Exp $
  36:  *
  37:  * Changes (from 26-Oct-2001)
  38:  * --------------------------
  39:  * 26-Oct-2001 : Changed package to com.jrefinery.ui.*;
  40:  * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  41:  *
  42:  */
  43: 
  44: package org.jfree.ui;
  45: 
  46: import java.awt.BorderLayout;
  47: import java.awt.Container;
  48: import java.awt.event.ActionEvent;
  49: import java.awt.event.ActionListener;
  50: import java.util.ArrayList;
  51: 
  52: import javax.swing.BorderFactory;
  53: import javax.swing.JButton;
  54: import javax.swing.JDialog;
  55: import javax.swing.JFrame;
  56: import javax.swing.JPanel;
  57: 
  58: /**
  59:  * A dialog that presents the user with a sequence of steps for completing a task.  The dialog
  60:  * contains "Next" and "Previous" buttons, allowing the user to navigate through the task.
  61:  * <P>
  62:  * When the user backs up by one or more steps, the dialog keeps the completed steps so that
  63:  * they can be reused if the user doesn't change anything - this handles the cases where the user
  64:  * backs up a few steps just to review what has been completed.
  65:  * <p>
  66:  * But if the user changes some options in an earlier step, then the dialog may have to discard
  67:  * the later steps and have them repeated.
  68:  * <P>
  69:  * THIS CLASS IS NOT WORKING CORRECTLY YET.
  70:  *
  71:  *
  72:  * @author David Gilbert
  73:  */
  74: public class WizardDialog extends JDialog implements ActionListener {
  75: 
  76:     /** The end result of the wizard sequence. */
  77:     private Object result;
  78: 
  79:     /** The current step in the wizard process (starting at step zero). */
  80:     private int step;
  81: 
  82:     /** A reference to the current panel. */
  83:     private WizardPanel currentPanel;
  84: 
  85:     /** A list of references to the panels the user has already seen - used for navigating through
  86:         the steps that have already been completed. */
  87:     private java.util.List panels;
  88: 
  89:     /** A handy reference to the "previous" button. */
  90:     private JButton previousButton;
  91: 
  92:     /** A handy reference to the "next" button. */
  93:     private JButton nextButton;
  94: 
  95:     /** A handy reference to the "finish" button. */
  96:     private JButton finishButton;
  97: 
  98:     /** A handy reference to the "help" button. */
  99:     private JButton helpButton;
 100: 
 101:     /**
 102:      * Standard constructor - builds and returns a new WizardDialog.
 103:      *
 104:      * @param owner  the owner.
 105:      * @param modal  modal?
 106:      * @param title  the title.
 107:      * @param firstPanel  the first panel.
 108:      */
 109:     public WizardDialog(final JDialog owner, final boolean modal,
 110:                         final String title, final WizardPanel firstPanel) {
 111: 
 112:         super(owner, title + " : step 1", modal);
 113:         this.result = null;
 114:         this.currentPanel = firstPanel;
 115:         this.step = 0;
 116:         this.panels = new ArrayList();
 117:         this.panels.add(firstPanel);
 118:         setContentPane(createContent());
 119: 
 120:     }
 121: 
 122:     /**
 123:      * Standard constructor - builds a new WizardDialog owned by the specified JFrame.
 124:      *
 125:      * @param owner  the owner.
 126:      * @param modal  modal?
 127:      * @param title  the title.
 128:      * @param firstPanel  the first panel.
 129:      */
 130:     public WizardDialog(final JFrame owner, final boolean modal,
 131:                         final String title, final WizardPanel firstPanel) {
 132: 
 133:         super(owner, title + " : step 1", modal);
 134:         this.result = null;
 135:         this.currentPanel = firstPanel;
 136:         this.step = 0;
 137:         this.panels = new ArrayList();
 138:         this.panels.add(firstPanel);
 139:         setContentPane(createContent());
 140:     }
 141: 
 142:     /**
 143:      * Returns the result of the wizard sequence.
 144:      *
 145:      * @return the result.
 146:      */
 147:     public Object getResult() {
 148:         return this.result;
 149:     }
 150: 
 151:     /**
 152:      * Returns the total number of steps in the wizard sequence, if this number is known.  Otherwise
 153:      * this method returns zero.  Subclasses should override this method unless the number of steps
 154:      * is not known.
 155:      *
 156:      * @return the number of steps.
 157:      */
 158:     public int getStepCount() {
 159:         return 0;
 160:     }
 161: 
 162:     /**
 163:      * Returns true if it is possible to back up to the previous panel, and false otherwise.
 164:      *
 165:      * @return boolean.
 166:      */
 167:     public boolean canDoPreviousPanel() {
 168:         return (this.step > 0);
 169:     }
 170: 
 171:     /**
 172:      * Returns true if there is a 'next' panel, and false otherwise.
 173:      *
 174:      * @return boolean.
 175:      */
 176:     public boolean canDoNextPanel() {
 177:         return this.currentPanel.hasNextPanel();
 178:     }
 179: 
 180:     /**
 181:      * Returns true if it is possible to finish the sequence at this point (possibly with defaults
 182:      * for the remaining entries).
 183:      *
 184:      * @return boolean.
 185:      */
 186:     public boolean canFinish() {
 187:         return this.currentPanel.canFinish();
 188:     }
 189: 
 190:     /**
 191:      * Returns the panel for the specified step (steps are numbered from zero).
 192:      *
 193:      * @param step  the current step.
 194:      *
 195:      * @return the panel.
 196:      */
 197:     public WizardPanel getWizardPanel(final int step) {
 198:         if (step < this.panels.size()) {
 199:             return (WizardPanel) this.panels.get(step);
 200:         }
 201:         else {
 202:             return null;
 203:         }
 204:     }
 205: 
 206:     /**
 207:      * Handles events.
 208:      *
 209:      * @param event  the event.
 210:      */
 211:     public void actionPerformed(final ActionEvent event) {
 212:         final String command = event.getActionCommand();
 213:         if (command.equals("nextButton")) {
 214:             next();
 215:         }
 216:         else if (command.equals("previousButton")) {
 217:             previous();
 218:         }
 219:         else if (command.equals("finishButton")) {
 220:             finish();
 221:         }
 222:     }
 223: 
 224:     /**
 225:      * Handles a click on the "previous" button, by displaying the previous panel in the sequence.
 226:      */
 227:     public void previous() {
 228:         if (this.step > 0) {
 229:             final WizardPanel previousPanel = getWizardPanel(this.step - 1);
 230:             // tell the panel that we are returning
 231:             previousPanel.returnFromLaterStep();
 232:             final Container content = getContentPane();
 233:             content.remove(this.currentPanel);
 234:             content.add(previousPanel);
 235:             this.step = this.step - 1;
 236:             this.currentPanel = previousPanel;
 237:             setTitle("Step " + (this.step + 1));
 238:             enableButtons();
 239:             pack();
 240:         }
 241:     }
 242: 
 243:     /**
 244:      * Displays the next step in the wizard sequence.
 245:      */
 246:     public void next() {
 247: 
 248:         WizardPanel nextPanel = getWizardPanel(this.step + 1);
 249:         if (nextPanel != null) {
 250:             if (!this.currentPanel.canRedisplayNextPanel()) {
 251:                 nextPanel = this.currentPanel.getNextPanel();
 252:             }
 253:         }
 254:         else {
 255:             nextPanel = this.currentPanel.getNextPanel();
 256:         }
 257: 
 258:         this.step = this.step + 1;
 259:         if (this.step < this.panels.size()) {
 260:             this.panels.set(this.step, nextPanel);
 261:         }
 262:         else {
 263:             this.panels.add(nextPanel);
 264:         }
 265: 
 266:         final Container content = getContentPane();
 267:         content.remove(this.currentPanel);
 268:         content.add(nextPanel);
 269: 
 270:         this.currentPanel = nextPanel;
 271:         setTitle("Step " + (this.step + 1));
 272:         enableButtons();
 273:         pack();
 274: 
 275:     }
 276: 
 277:     /**
 278:      * Finishes the wizard.
 279:      */
 280:     public void finish() {
 281:         this.result = this.currentPanel.getResult();
 282:         setVisible(false);
 283:     }
 284: 
 285:     /**
 286:      * Enables/disables the buttons according to the current step.  A good idea would be to ask the
 287:      * panels to return the status...
 288:      */
 289:     private void enableButtons() {
 290:         this.previousButton.setEnabled(this.step > 0);
 291:         this.nextButton.setEnabled(canDoNextPanel());
 292:         this.finishButton.setEnabled(canFinish());
 293:         this.helpButton.setEnabled(false);
 294:     }
 295: 
 296:     /**
 297:      * Checks, whether the user cancelled the dialog.
 298:      *
 299:      * @return false.
 300:      */
 301:     public boolean isCancelled() {
 302:         return false;
 303:     }
 304: 
 305:     /**
 306:      * Creates a panel containing the user interface for the dialog.
 307:      *
 308:      * @return the panel.
 309:      */
 310:     public JPanel createContent() {
 311: 
 312:         final JPanel content = new JPanel(new BorderLayout());
 313:         content.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
 314:         content.add((JPanel) this.panels.get(0));
 315:         final L1R3ButtonPanel buttons = new L1R3ButtonPanel("Help", "Previous", "Next", "Finish");
 316: 
 317:         this.helpButton = buttons.getLeftButton();
 318:         this.helpButton.setEnabled(false);
 319: 
 320:         this.previousButton = buttons.getRightButton1();
 321:         this.previousButton.setActionCommand("previousButton");
 322:         this.previousButton.addActionListener(this);
 323:         this.previousButton.setEnabled(false);
 324: 
 325:         this.nextButton = buttons.getRightButton2();
 326:         this.nextButton.setActionCommand("nextButton");
 327:         this.nextButton.addActionListener(this);
 328:         this.nextButton.setEnabled(true);
 329: 
 330:         this.finishButton = buttons.getRightButton3();
 331:         this.finishButton.setActionCommand("finishButton");
 332:         this.finishButton.addActionListener(this);
 333:         this.finishButton.setEnabled(false);
 334: 
 335:         buttons.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
 336:         content.add(buttons, BorderLayout.SOUTH);
 337: 
 338:         return content;
 339:     }
 340: 
 341: }