/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.designer.ui.wizard;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import ro.nextreports.designer.ui.EdgeBorder;
import ro.nextreports.designer.ui.EqualsLayout;
import ro.nextreports.designer.ui.MagicButton;
import ro.nextreports.designer.ui.wizard.util.GuiUtil;
import ro.nextreports.designer.util.I18NSupport;
import ro.nextreports.designer.util.ImageUtil;
import ro.nextreports.designer.util.UIActivator;
import ro.nextreports.designer.wizrep.WizardConstants;
/**
* This class controls a wizard.
* <p/>
* Add it to a frame or any other container then call start with your initial
* wizard panel.
* <p/>
* Listeners can also be added to trap when the wizard finishes and when the
* wizard is cancelled.
*
* @author Decebal Suiu
*/
public class Wizard extends JPanel {
private JButton backButton;
private JButton nextButton;
private JButton finishButton;
private JButton cancelButton;
private JButton helpButton;
private Stack<WizardPanelWithBanner> previous;
private WizardPanelWithBanner current;
private WizardContext context;
private List<WizardListener> listeners;
public Wizard(WizardPanel startPanel) {
listeners = new ArrayList<WizardListener>();
initComponents();
start(startPanel);
}
/**
* Add a listener to this wizard.
*
* @param listener a WizardListener object
*/
public void addWizardListener(WizardListener listener) {
listeners.add(listener);
}
/**
* Remove a listener from this wizard.
*
* @param listener a WizardListener object
*/
public void removeWizardListener(WizardListener listener) {
listeners.remove(listener);
}
public void onBack() {
WizardPanel panel = previous.pop().getPanel();
setPanel(panel);
updateButtons();
}
public void onNext() {
final String waitingMessage = current.getPanel().getWaitingMessage();
if (waitingMessage == null) {
next();
} else {
Thread executorThread = new Thread(new Runnable() {
public void run() {
JDialog dialog = (JDialog)context.getAttribute(WizardConstants.MAIN_FRAME);
UIActivator activator = new UIActivator(dialog, waitingMessage);
activator.start();
try {
next();
} finally {
if (activator != null) {
activator.stop();
}
}
}
}, "NEXT : " + getClass().getSimpleName());
executorThread.start();
}
}
// executes on EDT or not
private void next() {
final List<String> messages = new ArrayList<String>();
if (current.getPanel().validateNext(messages)) {
previous.push(current);
final WizardPanel panel = current.getPanel().getNextPanel();
if (panel != null) {
panel.setContext(context);
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setPanel(panel);
updateButtons();
}
});
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GuiUtil.showMessages(Wizard.this, messages);
}
});
}
}
public void onFinish() {
List<String> messages = new ArrayList<String>();
if (current.getPanel().validateFinish(messages)) {
current.getPanel().onFinish();
for (WizardListener listener : listeners) {
listener.wizardFinished(this);
}
} else {
GuiUtil.showMessages(this, messages);
}
}
public void onCancel() {
for (WizardListener listener : listeners) {
listener.wizardCancelled(this);
}
}
public void onHelp() {
current.getPanel().onHelp();
}
public WizardContext getContext() {
return context;
}
private void initComponents() {
createButtons();
disableButtons();
setLayout(new BorderLayout(0, 0));
JPanel navigationButtons = new JPanel();
navigationButtons.setLayout(new EqualsLayout(5));
navigationButtons.add(backButton);
navigationButtons.add(nextButton);
navigationButtons.add(finishButton);
navigationButtons.add(cancelButton);
JPanel helpButtons = new JPanel();
helpButtons.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
helpButtons.add(helpButton);
JPanel buttonsPanel = new JPanel();
buttonsPanel.setLayout(new BorderLayout(0, 0));
buttonsPanel.add(navigationButtons, BorderLayout.EAST);
buttonsPanel.add(helpButtons, BorderLayout.WEST);
CompoundBorder innerBorder = new CompoundBorder(new EdgeBorder(
SwingConstants.NORTH), new EmptyBorder(10, 0, 0, 0));
buttonsPanel.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10),
innerBorder));
add(buttonsPanel, BorderLayout.SOUTH);
}
private void createButtons() {
backButton = new JButton(new AbstractAction() {
public void actionPerformed(ActionEvent event) {
onBack();
}
});
backButton.setText(I18NSupport.getString("wizard.panel.back"));
nextButton = new JButton(new AbstractAction() {
public void actionPerformed(ActionEvent event) {
onNext();
}
});
nextButton.setText(I18NSupport.getString("wizard.panel.next"));
finishButton = new JButton(new AbstractAction() {
public void actionPerformed(ActionEvent event) {
onFinish();
}
});
finishButton.setText(I18NSupport.getString("wizard.panel.finish"));
cancelButton = new JButton(new AbstractAction() {
public void actionPerformed(ActionEvent event) {
onCancel();
}
});
cancelButton.setText(I18NSupport.getString("wizard.panel.cancel"));
helpButton = new MagicButton(new AbstractAction() {
public void actionPerformed(ActionEvent event) {
onHelp();
}
});
helpButton.setText("");
helpButton.setIcon(ImageUtil.getImageIcon("wizard_help"));
}
private void disableButtons() {
nextButton.setEnabled(false);
backButton.setEnabled(false);
finishButton.setEnabled(false);
cancelButton.setEnabled(false);
helpButton.setEnabled(false);
}
/**
* Start this wizard with this panel.
*/
private void start(WizardPanel wizardPanel) {
previous = new Stack<WizardPanelWithBanner>();
context = new WizardContext();
wizardPanel.setContext(context);
setPanel(wizardPanel);
updateButtons();
}
private void setPanel(WizardPanel wizardPanel) {
if (current != null) {
remove(current);
}
wizardPanel.setBorder(new EmptyBorder(10, 10, 0, 10));
current = new WizardPanelWithBanner(wizardPanel);
if (current == null) {
current = new WizardPanelWithBanner(new WizardPanelAdapter());
}
add(current, BorderLayout.CENTER);
for (WizardListener listener : listeners) {
listener.wizardPanelChanged(this);
}
setVisible(true);
revalidate();
updateUI();
current.getPanel().onDisplay();
}
private void updateButtons() {
cancelButton.setEnabled(true);
// helpButton.setEnabled(current.getPanel().hasHelp());
helpButton.setVisible(current.getPanel().hasHelp());
backButton.setEnabled(previous.size() > 0);
nextButton.setEnabled(current.getPanel().hasNext());
finishButton.setEnabled(current.getPanel().canFinish());
}
private class WizardPanelWithBanner extends JPanel {
private WizardPanel panel;
public WizardPanelWithBanner(WizardPanel panel) {
super();
this.panel = panel;
initComponents();
}
public WizardPanel getPanel() {
return panel;
}
private void initComponents() {
setLayout(new BorderLayout());
if (panel.getBanner().isVisible()) {
add(panel.getBanner(), BorderLayout.NORTH);
}
add(panel, BorderLayout.CENTER);
}
}
}