blob: a18424179bc951ac92fd9912122212792832db02 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.gui.wizard;
import org.apache.tools.ant.gui.core.ResourceManager;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.util.*;
/**
* Top level container and controller for wizard-type GUI.
*
* @version $Revision$
* @author Simeon Fitch
*/
public class Wizard extends JComponent {
/** The data model to pass on to each step. */
private WizardData _data = null;
/** Container for the step editors. */
private JPanel _stepContainer = null;
/** Layout manager for all the step panels. */
private CardLayout _layout = null;
/** Set initialized steps. */
private Map _steps = new HashMap();
/** Steps saved in a list to preserve ordering. */
private List _stepOrdering = new ArrayList();
/** Description text. XXX should probably change to some other widget. */
private JTextArea _description = null;
/** Progress meter. */
private JProgressBar _progress = null;
/** Widget for navigating through steps. */
private WizardNavigator _nav = null;
/** The current Wizard step. */
private WizardStep _curr = null;
/** The set of wizard listeners. */
private List _listeners = new ArrayList(1);
/**
* Standard ctor.
*
* @param data Data for the wizard.
*/
public Wizard(WizardData data) {
setLayout(new BorderLayout());
_data = data;
_progress = new JProgressBar();
_progress.setBorder(BorderFactory.createTitledBorder(
_data.getResources().getString("progress")));
_progress.setStringPainted(true);
add(_progress, BorderLayout.NORTH);
_description = new JTextArea();
_description.setMargin(new Insets(5, 5, 5, 5));
_description.setPreferredSize(new Dimension(100, 100));
_description.setOpaque(true);
_description.setFont(new Font("Serif", Font.PLAIN, 12));
_description.setEditable(false);
_description.setLineWrap(true);
_description.setWrapStyleWord(true);
JScrollPane scroller = new JScrollPane(
_description,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroller.setBorder(BorderFactory.createTitledBorder(
_data.getResources().getString("help")));
add(scroller, BorderLayout.WEST);
_stepContainer = new JPanel(_layout = new CardLayout());
_stepContainer.setBorder(BorderFactory.createEtchedBorder());
_stepContainer.setPreferredSize(new Dimension(400, 400));
add(_stepContainer, BorderLayout.CENTER);
_nav = new ButtonNavigator(_data.getResources());
_nav.addNavigatorListener(new NavHandler());
((ButtonNavigator)_nav).setBorder(BorderFactory.createEtchedBorder());
add((ButtonNavigator)_nav, BorderLayout.SOUTH);
String[] steps = _data.getResources().getStringArray("steps");
_progress.setMaximum(steps.length - 1);
try {
for(int i = 0; i < steps.length; i++) {
Class type = _data.getResources().getClass(steps[i] + ".editor");
WizardStep step = (WizardStep) type.newInstance();
step.setResources(_data.getResources());
step.setID(steps[i]);
step.setTitle(
_data.getResources().getString(steps[i]+ ".title"));
step.setDescription(
_data.getResources().getString(steps[i]+ ".description"));
_steps.put(steps[i], step);
_stepOrdering.add(step);
_stepContainer.add(step.getEditorComponent(), steps[i]);
}
// Initialize the first screen with the data model.
if(steps.length > 0) {
WizardStep first = (WizardStep)_steps.get(steps[0]);
first.setDataModel(_data);
_curr = first;
showStep(first);
}
}
catch(Exception ex) {
// If we get here then the wizard didn't initialize properly.
// XXX log me.
ex.printStackTrace();
}
}
/**
* Add a wizard listener.
*
* @param l Listener to add.
*/
public void addWizardListener(WizardListener l) {
_listeners.add(l);
}
/**
* Remove a wizard listener.
*
* @param l Listener to remove.
*/
public void removeWizardListener(WizardListener l) {
_listeners.remove(l);
}
/**
* Go to the given step.
*
* @param step Step to go to.
*/
private void showStep(WizardStep step) {
if(step == null) return;
step.setDataModel(_curr.getDataModel());
// Update the title and description.
_stepContainer.setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(step.getTitle()),
BorderFactory.createEmptyBorder(5, 15, 5, 15)));
_description.setText(step.getDescription());
_nav.setBackEnabled(step.getPrevious() != null);
_nav.setNextEnabled(step.getNext() != null);
_nav.setFinishEnabled(step.getNext() == null);
_progress.setValue(_stepOrdering.indexOf(step));
// Tell the step to refresh its display based on the data model.
step.updateDisplay();
// Display the step.
_layout.show(_stepContainer, step.getID());
_curr = step;
}
/** Handler for actions invoked by wizard. */
private class NavHandler implements NavigatorListener {
public void nextStep() {
// Called to give data model chance to make changes to what is next.
_curr.updateDataModel();
String nextID = _curr.getNext();
if(nextID != null) {
showStep((WizardStep)_steps.get(nextID));
}
}
public void backStep() {
// Called to give data model chance to make changes to what is
// before.
_curr.updateDataModel();
String prevID = _curr.getPrevious();
if(prevID != null) {
showStep((WizardStep)_steps.get(prevID));
}
}
public void gotoStep(String stepID){
_curr.updateDataModel();
showStep((WizardStep) _steps.get(stepID));
}
public void cancel() {
_curr.updateDataModel();
Iterator it = _listeners.iterator();
while(it.hasNext()) {
WizardListener l = (WizardListener) it.next();
l.canceled();
}
}
public void finish() {
_curr.updateDataModel();
Iterator it = _listeners.iterator();
while(it.hasNext()) {
WizardListener l = (WizardListener) it.next();
l.finished(_curr.getDataModel());
}
}
}
}