package org.openslx.dozmod.gui.wizard;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import org.openslx.dozmod.gui.MainWindow;
import org.openslx.dozmod.gui.helper.GridPos;
@SuppressWarnings("serial")
public abstract class Wizard extends JDialog {
private final JLabel titleLabel;
private final JLabel messageLabel;
private final List<WizardPage> pages = new ArrayList<>();
private final JPanel contentPanel;
private int currentPage = -1;
private boolean needsLayout = true;
private final JButton btnPrev;
private final JButton btnNext;
private final JButton btnCancel;
private final JButton btnFinish;
public Wizard(Window parent) {
super(parent, ModalityType.APPLICATION_MODAL);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
setLayout(new BorderLayout());
JPanel header = new JPanel();
header.setMinimumSize(new Dimension(0, 100));
header.setOpaque(true);
header.setBackground(Color.WHITE);
header.setLayout(new BoxLayout(header, BoxLayout.PAGE_AXIS));
header.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// Labels in header
titleLabel = new JLabel("<title>");
messageLabel = new JLabel("<message>");
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD));
titleLabel.setForeground(Color.BLACK);
messageLabel.setForeground(Color.BLACK);
messageLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
header.add(titleLabel);
header.add(messageLabel);
// Add header
JPanel headerWrapper = new JPanel();
headerWrapper.setLayout(new GridBagLayout());
headerWrapper.add(header, GridPos.get(0, 0, true, false));
headerWrapper.add(new JSeparator(), GridPos.get(0, 1, true, false));
getContentPane().add(headerWrapper, BorderLayout.PAGE_START);
// Buttons in footer
JPanel footer = new JPanel();
footer.setLayout(new BoxLayout(footer, BoxLayout.LINE_AXIS));
footer.add(Box.createHorizontalGlue());
btnPrev = new JButton("< Zurück");
btnNext = new JButton("Weiter >");
btnCancel = new JButton("Abbrechen");
btnFinish = new JButton("Fertigstellen");
footer.add(btnPrev);
footer.add(btnNext);
footer.add(Box.createRigidArea(new Dimension(10, 10)));
footer.add(btnCancel);
footer.add(Box.createRigidArea(new Dimension(5, 5)));
footer.add(btnFinish);
add(footer, BorderLayout.PAGE_END);
// Add content panel
contentPanel = new JPanel();
contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS));
contentPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
add(contentPanel, BorderLayout.CENTER);
//
setPreferredSize(new Dimension(550, 420));
setResizable(false);
// Window events
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
doCancel();
}
});
// Äkschns
btnNext.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doNext();
}
});
btnPrev.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doPrevious();
}
});
btnCancel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doCancel();
}
});
btnFinish.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doFinish();
}
});
}
@SuppressWarnings("deprecation")
@Override
public void show() {
if (needsLayout) {
needsLayout = false;
pack();
if (!pages.isEmpty()) {
showPage(0);
}
MainWindow.centerShell(this);
}
super.show();
}
private void showPage(int index) {
if (currentPage != -1) {
WizardPage old = pages.get(currentPage);
old.onPageLeave();
old.setVisible(false);
}
WizardPage page = pages.get(index);
page.onPageEnter();
page.setVisible(true);
currentPage = index;
updateHeader(page);
updateButtons(page);
validate();
}
void updateHeader(WizardPage page) {
if (currentPage == -1 || pages.get(currentPage) != page)
return;
String pageTitle = page.getTitle();
String pageDesc = page.getMessage();
if (pageTitle == null)
pageTitle = "Step " + currentPage;
if (pageDesc == null)
pageDesc = "";
titleLabel.setText(pageTitle);
messageLabel.setText(pageDesc);
messageLabel.setIcon(page.getMessageIcon());
messageLabel.validate();
setTitle(getWindowTitle() + " - " + pageTitle);
}
public abstract String getWindowTitle();
protected final void addPage(WizardPage page) {
contentPanel.add(page);
if (!pages.isEmpty()) {
page.setVisible(false);
}
pages.add(page);
}
void updateButtons(WizardPage page) {
// State of finish button
boolean canFinish = true;
for (WizardPage p : pages) {
if (!p.isComplete()) {
canFinish = false;
break;
}
}
btnFinish.setEnabled(canFinish);
// State of next button
if (currentPage != -1 && pages.get(currentPage) == page) {
btnNext.setEnabled(currentPage + 1 < pages.size() && page.isComplete());
btnPrev.setEnabled(currentPage > 0 && pages.get(currentPage - 1).canComeBack);
}
}
protected final void doNext() {
if (!btnNext.isEnabled())
return;
if (currentPage + 1 < pages.size()) {
if (!pages.get(currentPage).wantNextOrFinish())
return; // Page canceled the operation
showPage(currentPage + 1);
}
}
protected final void doPrevious() {
if (!btnPrev.isEnabled())
return;
if (currentPage > 0) {
showPage(currentPage - 1);
}
}
protected final void doCancel() {
if (onCancelRequest())
dispose();
}
protected final void doFinish() {
if (!btnFinish.isEnabled())
return;
if (currentPage != -1) {
if (!pages.get(currentPage).wantNextOrFinish())
return;
}
if (wantFinish()) {
if (currentPage != -1) {
pages.get(currentPage).onPageLeave();
}
performFinish();
dispose();
}
}
/*
* Callback to wizard implementation
*/
/**
* User clicked cancel or (X) - when returning false,
* wizard will stay open
*
* @return
*/
protected boolean onCancelRequest() {
return true;
}
/**
* Called when user clicks finish. Override to do final checks and take
* appropriate actions.
*
* @return <code>true</code> if finish is allowed, <code>false</code>
* otherwise
*/
protected boolean wantFinish() {
return true;
}
/**
* Called so the wizard can perform finishing steps. This is called after
* wantFinish() returned true and onPageLeave was called on the currently
* visible wizard step.
*/
protected void performFinish() {
// void
}
}