/* $Id: Wizard.java 17816 2010-01-12 18:34:29Z linus $
*****************************************************************************
* Copyright (c) 2009 Contributors - see below
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* tfmorris
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 1996-2007 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
package org.argouml.cognitive.critics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
/**
* "Abstract" base class for non-modal wizards. Each subclass should
* define its own makeNextPanel methods. Because most
* wizards will not be run to completion, the panels are constructed
* only as needed. This implies that Wizards should not initialize
* many instance variables in their constructors.<p>
*
* By convention step 0 is the problem description of the ToDoItem,
* step 1 is the first panel displayed after the user presses
* "Next>", and so on. The problem description panel is not stored in
* this wizard, only the panels that are specific to the wizard are
* stored. If the user presses "Back>" enough times to get back to the
* problem description, backPanel should return null. A null panel
* indicates that the problem description should be shown. <p>
*
* Several of the comments in this class refer to "context". Context
* is the data about this execution of this wizard, for example, values
* that the user enters in step 1 is part of the context of later steps,
* and the ToDoItem with its offenders Set is always context. Most
* context should be stored in instance variables of Wizard subclasses.
*
* @author jrobbins
*/
public abstract class Wizard implements java.io.Serializable {
/** User interface panels displayed so far. */
private List<JPanel> panels = new ArrayList<JPanel>();
/** The current step that the Wizard is on. Zero indicates that the
* wizard has not yet begun. */
private int step = 0;
/** True when the wizard has done everything it can. */
private boolean finished = false;
private boolean started = false;
private WizardItem item = null;
/** Construct a new wizard to help the user repair a design flaw. */
public Wizard() {
}
/**
* @param s the step number of the panel to be removed
*/
protected void removePanel(int s) {
panels.remove(s);
}
/**
* Setter for the todoitem.
*
* @param i the todoitem
*/
public void setToDoItem(WizardItem i) {
item = i;
}
/**
* @return the todoitem
*/
public WizardItem getToDoItem() {
return item;
}
/** An integer between 0 and 100, shows percent done. The current
* ArgoUML user interface shows different PostIt note icons for
* 0, 1-25, 26-50. 51-75, and 76-100.
* @return the percentage done.
*/
public int getProgress() {
return step * 100 / getNumSteps();
}
/** Get the number of steps in this wizard. Subclasses should
* override to return a constant, or compute based on context.
* @return the number of steps in this wizard.
*/
public abstract int getNumSteps();
/** Get the panel that should be displayed now. Usually called
* after the user pressed "Next>" and next() has returned, or after
* the user pressed "<Back" and back() has returned. Also called
* when the user turns away from the wizard to do something else and
* then returns his or her attention to the wizard.
* @return the panel that should be displayed now.
*/
public JPanel getCurrentPanel() {
return getPanel(step);
}
/** Get the exising panel at step s. Step 1 is the first wizard
* panel.
* @param s the step
* @return the panel for step s or null if none.
*/
public JPanel getPanel(int s) {
if (s > 0 && s <= panels.size()) {
return panels.get(s - 1);
}
return null;
}
////////////////////////////////////////////////////////////////
// wizard actions
/** Return true iff the "Next>" button should be enabled.
* Subclasses should override to first check super.nextEnabled()
* and then check for legal context values.
* @return <code>true</code> iff the "Next>" button should be enabled.
*/
public boolean canGoNext() {
return step < getNumSteps();
}
/**
* The next step of the wizard.
*/
public void next() {
doAction(step);
step++;
JPanel p = makePanel(step);
if (p != null) {
panels.add(p);
}
started = true;
if (item != null) {
item.changed();
}
}
/**
* @return true if we can step back
*/
public boolean canGoBack() {
return step > 0;
}
/**
* Step back.
*/
public void back() {
step--;
if (step < 0) step = 0;
undoAction(step);
if (item != null) item.changed();
}
/**
* @return true if we can finish (i.e. the finish button is not downlighted)
*/
public boolean canFinish() {
return true;
}
/**
* @return true if the wizard is started
*/
public boolean isStarted() {
return started;
}
/**
* @return true if the wizard is finished
*/
public boolean isFinished() {
return finished;
}
/**
* Finish the wizard.
*/
public void finish() {
started = true;
int numSteps = getNumSteps();
for (int i = step; i <= numSteps; i++) {
doAction(i);
if (item != null) item.changed();
}
// TODO: do all following steps
// TODO: resolve item from ToDoList
finished = true;
}
/** Create a new panel for the given step. For example, When the
* given step is 1, create the first step of the wizard. <p>
*
* TODO: It might be convient to make a reusable
* subclass of Wizard that shows all textual steps to guide the
* user without any automation. Such a Wizard could be easily
* authored, stored in an XML file, and efficiently presented by
* reusing a single panel with a single JTextArea.
*
* @param newStep the number of the step to make a panel for.
* @return a new panel for the given step
*/
public abstract JPanel makePanel(int newStep);
/** Take action at the completion of a step. For example, when the
* given step is 0, do nothing; and when the given step is 1, do
* the first action. Argo non-modal wizards should take action as
* they do along, as soon as possible, they should not wait until
* the final step. Also, if the user pressed "Finish" doAction may
* be called for steps that never constructored or displayed their
* panels.
*
* @param oldStep the given step
*/
public abstract void doAction(int oldStep);
/**
* Do the action of this wizard.
*/
public void doAction() { doAction(step); }
/** Undo the action done after the given step. For example, when the
* given step is 0, nothing was done, so nothing can be undone; and
* when the given step is 1, undo the first action. Undo allows
* users to work part way through fixing a problem, see the partial
* result, and explore a different alternative.
*
* @param oldStep the given step
*/
public void undoAction(int oldStep) {
}
/**
* Undo the action.
*/
public void undoAction() { undoAction(step); }
/**
* @return Returns the step.
*/
protected int getStep() {
return step;
}
}