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.5 2005/11/16 15:58:41 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:
052: import javax.swing.BorderFactory;
053: import javax.swing.JButton;
054: import javax.swing.JDialog;
055: import javax.swing.JFrame;
056: import javax.swing.JPanel;
057:
058: /**
059: * A dialog that presents the user with a sequence of steps for completing a task. The dialog
060: * contains "Next" and "Previous" buttons, allowing the user to navigate through the task.
061: * <P>
062: * When the user backs up by one or more steps, the dialog keeps the completed steps so that
063: * they can be reused if the user doesn't change anything - this handles the cases where the user
064: * backs up a few steps just to review what has been completed.
065: * <p>
066: * But if the user changes some options in an earlier step, then the dialog may have to discard
067: * the later steps and have them repeated.
068: * <P>
069: * THIS CLASS IS NOT WORKING CORRECTLY YET.
070: *
071: *
072: * @author David Gilbert
073: */
074: public class WizardDialog extends JDialog implements ActionListener {
075:
076: /** The end result of the wizard sequence. */
077: private Object result;
078:
079: /** The current step in the wizard process (starting at step zero). */
080: private int step;
081:
082: /** A reference to the current panel. */
083: private WizardPanel currentPanel;
084:
085: /** A list of references to the panels the user has already seen - used for navigating through
086: the steps that have already been completed. */
087: private java.util.List panels;
088:
089: /** A handy reference to the "previous" button. */
090: private JButton previousButton;
091:
092: /** A handy reference to the "next" button. */
093: private JButton nextButton;
094:
095: /** A handy reference to the "finish" button. */
096: private JButton finishButton;
097:
098: /** A handy reference to the "help" button. */
099: 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: } 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: } else if (command.equals("previousButton")) {
215: previous();
216: } else if (command.equals("finishButton")) {
217: finish();
218: }
219: }
220:
221: /**
222: * Handles a click on the "previous" button, by displaying the previous panel in the sequence.
223: */
224: public void previous() {
225: if (this .step > 0) {
226: final WizardPanel previousPanel = getWizardPanel(this .step - 1);
227: // tell the panel that we are returning
228: previousPanel.returnFromLaterStep();
229: final Container content = getContentPane();
230: content.remove(this .currentPanel);
231: content.add(previousPanel);
232: this .step = this .step - 1;
233: this .currentPanel = previousPanel;
234: setTitle("Step " + (this .step + 1));
235: enableButtons();
236: pack();
237: }
238: }
239:
240: /**
241: * Displays the next step in the wizard sequence.
242: */
243: public void next() {
244:
245: WizardPanel nextPanel = getWizardPanel(this .step + 1);
246: if (nextPanel != null) {
247: if (!this .currentPanel.canRedisplayNextPanel()) {
248: nextPanel = this .currentPanel.getNextPanel();
249: }
250: } else {
251: nextPanel = this .currentPanel.getNextPanel();
252: }
253:
254: this .step = this .step + 1;
255: if (this .step < this .panels.size()) {
256: this .panels.set(this .step, nextPanel);
257: } else {
258: this .panels.add(nextPanel);
259: }
260:
261: final Container content = getContentPane();
262: content.remove(this .currentPanel);
263: content.add(nextPanel);
264:
265: this .currentPanel = nextPanel;
266: setTitle("Step " + (this .step + 1));
267: enableButtons();
268: pack();
269:
270: }
271:
272: /**
273: * Finishes the wizard.
274: */
275: public void finish() {
276: this .result = this .currentPanel.getResult();
277: setVisible(false);
278: }
279:
280: /**
281: * Enables/disables the buttons according to the current step. A good idea would be to ask the
282: * panels to return the status...
283: */
284: private void enableButtons() {
285: this .previousButton.setEnabled(this .step > 0);
286: this .nextButton.setEnabled(canDoNextPanel());
287: this .finishButton.setEnabled(canFinish());
288: this .helpButton.setEnabled(false);
289: }
290:
291: /**
292: * Checks, whether the user cancelled the dialog.
293: *
294: * @return false.
295: */
296: public boolean isCancelled() {
297: return false;
298: }
299:
300: /**
301: * Creates a panel containing the user interface for the dialog.
302: *
303: * @return the panel.
304: */
305: public JPanel createContent() {
306:
307: final JPanel content = new JPanel(new BorderLayout());
308: content.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
309: content.add((JPanel) this .panels.get(0));
310: final L1R3ButtonPanel buttons = new L1R3ButtonPanel("Help",
311: "Previous", "Next", "Finish");
312:
313: this .helpButton = buttons.getLeftButton();
314: this .helpButton.setEnabled(false);
315:
316: this .previousButton = buttons.getRightButton1();
317: this .previousButton.setActionCommand("previousButton");
318: this .previousButton.addActionListener(this );
319: this .previousButton.setEnabled(false);
320:
321: this .nextButton = buttons.getRightButton2();
322: this .nextButton.setActionCommand("nextButton");
323: this .nextButton.addActionListener(this );
324: this .nextButton.setEnabled(true);
325:
326: this .finishButton = buttons.getRightButton3();
327: this .finishButton.setActionCommand("finishButton");
328: this .finishButton.addActionListener(this );
329: this .finishButton.setEnabled(false);
330:
331: buttons.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
332: content.add(buttons, BorderLayout.SOUTH);
333:
334: return content;
335: }
336:
337: }
|