62,614
社区成员
发帖
与我相关
我的任务
分享
/**
*
*/
package com.gordon.ui.wizard;
import javax.swing.JPanel;
import com.gordon.ui.wizard.Wizard.CardHead;
/**
* @author Administrator
*
*/
public abstract class Card {
/**
* 面板的步骤标识符,其目地是为了实现对整个向导流中按钮的显示控制,子类不需要关心面板需要显示哪几个按钮
*/
public static enum StepID {
FirstCard, SecondCard, ThirdCard, FourCard, FiveCard, SixCard, SevenCard, EightCard, NineCard, TenCard;
}
public Card() {
cardView = new JPanel();
}
public Card(JPanel cardView) {
this.cardView = cardView;
}
/**
* 设置当前面板显示内容
*
* @param mainPane
*/
public final void setCardView(JPanel mainPane) {
this.cardView = mainPane;
}
/**
* 获取当前面板显示内容
*
* @return mainPane
*/
final JPanel getCardView() {
return this.cardView;
}
/**
* 子类实现,提供当前步骤流总计有多少步,可能根据不同的流程,总的步骤不一样,由子类提供
*
* @return int 返回当前向导流总的步骤数
*/
protected abstract int getTotalSteps();
/**
* 子类实现,指明当前处于向导流中的第几步?
*
* @return int 返回当前所处的步骤
*/
protected abstract int getCurrentStep();
/**
* 子类实现,返回当前步骤在向导页面顶部上的步骤说明信息:包括当前步骤的标题,详细描述以及图标
*
* @return
*/
protected abstract CardHead getCardHead();
/**
* 设置当前步骤ID
* @param stepID
*/
void setCurrentStepID(StepID stepID) {
currentStepID = stepID;
}
/**
* 获取当前步骤ID
*
* @return
*/
StepID getCurrentStepID() {
return currentStepID;
}
/**
* 获取下一步面板的标志符, 可以根据该标识符,找到上一步面板实例对象
*/
protected abstract StepID getNextCardStepID();
/**
* 获取上一步面板的标志符, 可以根据该标识符,找到上一步面板实例对象
*/
protected abstract StepID getPreviousStepID();
/**
* 子类覆盖实现:离开当前面板到下一面板时回调此方法,做一些离开此面板前的工作。 如数据收集工作,下发命令工作
*
* @return true: 能够正常进入下一页面, false:不能进入下一页面
*/
protected boolean onNextCommand() {
return true;
}
/**
* 子类覆盖实现:离开当前面板时到上一步时回调此方法,做一些离开此面板前的工作。 如密码的清理工作 如数据收集工作
*
* @return true: 能够正常回到上一页面, false:不能回到上一页面
*/
protected boolean onPreviousCommand() {
return true;
}
/**
* 响应完成按钮命令。Card子类覆盖实现,以提供完成前的处理工作:如提醒用户做什么操作,或想系统发送一条后台命令等
*
* @return
*/
protected boolean onCancelCommand() {
return true;
}
/**
* 响应完成按钮命令。Card子类覆盖实现,以提供取消前的处理工作:如警告用户任务未完成。
*/
protected boolean onFinishCommand() {
return true;
}
/**
* 子类实现:进入下一页面前做一些初始化工作
*
* @return
*/
protected boolean doInitTask() {
return true;
}
/**
* 子类实现:进入页面后,可能才开始更新数据,或者启动一些后台任务。如升级处的进入页面后有一些后台任务
*/
protected void showing() {
}
/**
* 获取向导对话框标题上的当前步骤与总步骤的显示
*
* @return
*/
String getWizardStep() {
int totalSteps = getTotalSteps();
int currentStep = getCurrentStep();
return "Step" + currentStep + "/" + totalSteps;
}
/**
* 设置当前的向导对话框
*
* @param wizard
*/
void setWizard(Wizard wizard) {
this.wizard = wizard;
}
/**
* @return 获取当前的向导对话框
*/
protected Wizard getWizard() {
return this.wizard;
}
private Wizard wizard;
private JPanel cardView;
private StepID currentStepID;
}
/**
*
*/
package com.gordon.ui.wizard;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;
import com.gordon.ui.wizard.Card.StepID;
/**
* @author Administrator
*
*/
public final class Wizard extends JDialog implements PropertyChangeListener {
private static final long serialVersionUID = 847520613043597065L;
private JPanel cardContentPane; // 每一步的内容面板
private CardLayout cardLayout;
private CardHeadPane cardHeadPane; // 每一步的描述给信息
private NavigationBar buttonPane;
private WizardHandler wizardHandler;
private WizardModel wizardModel;
private String wizardTitle;
public Wizard(Window parent, String title) {
super(parent);
wizardTitle = title;
wizardHandler = new WizardHandler(this);
wizardModel = new WizardModel();
wizardModel.addPropertyChangeListener(this);
// TODO:增加将对话框放置在主屏幕中间
// TODO:取消ESC键的响应
// 初始化主框架
doLayoutUI();
}
private void doLayoutUI() {
cardContentPane = new JPanel();
cardLayout = new CardLayout();
cardContentPane.setLayout(cardLayout);
cardHeadPane = new CardHeadPane();
buttonPane = new NavigationBar(wizardHandler);
this.setLayout(new BorderLayout());
this.add(cardHeadPane, BorderLayout.NORTH);
this.add(cardContentPane, BorderLayout.CENTER);
this.add(buttonPane, BorderLayout.SOUTH);
}
public void showWizard() {
Card card = wizardModel.getCardBy(StepID.FirstCard);
if (null == card || !card.doInitTask()) {
return;
}
this.setCurrentCard(StepID.FirstCard);
this.setModal(true);
this.pack();
this.setVisible(true);
}
public WizardModel getModel() {
return this.wizardModel;
}
public void setButtonEnable(EWizardButton buttonE, boolean enable) {
JButton button = buttonPane.getButtonBy(buttonE);
if (null != button) {
button.setEnabled(enable);
}
}
public void addCard(StepID stepID, Card card) {
card.setCurrentStepID(stepID);
cardContentPane.add(card.getCardView(), stepID.name());
card.setWizard(this);
wizardModel.addCard(stepID, card);
}
void setCurrentCard(StepID stepID) {
if (null == stepID) {
return;
}
wizardModel.setCurrentCard(stepID);
cardLayout.show(cardContentPane, stepID.name());
wizardModel.getCurrentCard().showing();
}
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(
WizardModel.CURRENT_CARD_IDENTIFIER_PROPERTY)) {
Card card = wizardModel.getCurrentCard();
cardHeadPane.update(card.getCardHead());
String title = wizardTitle + " " + card.getWizardStep();
this.setTitle(title);
if (wizardModel.arrivedFirstCard()) {
buttonPane.update(EWizardButton.Next, EWizardButton.Cancel,
EWizardButton.Help);
} else if (wizardModel.arraivedFinishCard()) {
buttonPane.update(EWizardButton.Previous, EWizardButton.Finish,
EWizardButton.Help);
} else {
buttonPane.update(EWizardButton.Previous, EWizardButton.Next,
EWizardButton.Cancel, EWizardButton.Help);
}
}
}
/**
* 按钮枚举
*
* @author Administrator
*/
enum EWizardButton {
Previous("PREVIOUS_COMMAND", KeyEvent.VK_P), Next("NEXT_COMMAND",
KeyEvent.VK_N), Cancel("CANCEL_COMMAND", KeyEvent.VK_C), Finish(
"FINISH_COMMAND", KeyEvent.VK_F), Help("HELP_COMMAND",
KeyEvent.VK_H);
private String command;
private int memonic;
private EWizardButton(String command, int memonic) {
this.command = command;
this.memonic = memonic;
}
public String getCommand() {
return command;
}
public int getMemonic() {
return memonic;
}
public String getText() {
return this.name();
}
/**
* 根据按钮的命令码获取对应的枚举
*
* @param command
* 按钮的命令码
* @return
*/
public static EWizardButton getEWizardButtonBy(String command) {
for (EWizardButton buttonE : EWizardButton.values()) {
if (buttonE.getCommand().equals(command)) {
return buttonE;
}
}
return null;
}
}
/**
* 向导对话框的顶部描述面板的信息封装,包括描述,图标,当前步骤的子标题
*
* 由Card的实现子类返回当前步骤的信息描述
*/
public static class CardHead {
public CardHead(String title, String details) {
this.stepTitle = title;
this.details = details;
}
public CardHead(String title, String details, Icon icon) {
this(title, details);
this.icon = icon;
}
public String getDetails() {
return details;
}
public Icon getIcon() {
return icon;
}
public String getTitle() {
return stepTitle;
}
private String stepTitle;
private Icon icon;
private String details;
}
/**
* 向导对话框的顶部描述面板,信息显示由实现的Card子类返回
*/
private class CardHeadPane extends JPanel {
private static final long serialVersionUID = -7173107387328821161L;
public CardHeadPane() {
doLayoutUI();
}
private void doLayoutUI() {
titleLabel = new JLabel();
detailsArea = new JTextArea();
iconLable = new JLabel();
JPanel detailAreaPane = new JPanel(new BorderLayout());
detailAreaPane.add(titleLabel, BorderLayout.NORTH);
detailAreaPane.add(detailsArea, BorderLayout.CENTER);
this.setLayout(new BorderLayout());
this.add(iconLable, BorderLayout.WEST);
this.add(detailAreaPane, BorderLayout.CENTER);
this.add(new JSeparator(), BorderLayout.SOUTH);
}
public void update(CardHead cardHead) {
titleLabel.setText(cardHead.getTitle());
iconLable.setIcon(cardHead.getIcon());
detailsArea.setText(cardHead.getDetails());
this.revalidate();
this.repaint();
}
private JLabel titleLabel;
private JTextArea detailsArea;
private JLabel iconLable;
}
/**
* 向导底部按钮导航区的面板布局,显示的按钮由当前步骤而决定
*
* 有三种风格: 第一步面板中只有下一步、取消、帮助 最后一步面板只有上一步、完成、帮助、 中间每一步面板包括上一步、下一步、取消、帮助
*
* @author Administrator
*/
class NavigationBar extends JPanel {
public NavigationBar(WizardHandler handler) {
doLayoutUI(handler);
}
private void doLayoutUI(WizardHandler handler) {
for (EWizardButton wizardButtonE : EWizardButton.values()) {
JButton button = new JButton(wizardButtonE.getText());
button.setActionCommand(wizardButtonE.getCommand());
button.setMnemonic(wizardButtonE.getMemonic());
button.addActionListener(handler);
stepBtnPane.put(wizardButtonE, button);
}
buttonPane = Box.createHorizontalBox();
Box buttonBox = Box.createHorizontalBox();
buttonBox.add(Box.createHorizontalGlue());
buttonBox.add(buttonPane);
buttonBox.setBorder(new EmptyBorder(8, 10, 8, 10));
this.setLayout(new BorderLayout());
this.add(new JSeparator(), BorderLayout.NORTH);
this.add(buttonBox, BorderLayout.CENTER);
}
public void update(final EWizardButton... buttons) {
EWizardButton[] stepButtons = buttons;
if (null == stepButtons || 0 == stepButtons.length) {
stepButtons = new EWizardButton[] { EWizardButton.Previous,
EWizardButton.Next, EWizardButton.Cancel,
EWizardButton.Help };
}
buttonPane.removeAll();
int index = 0;
for (EWizardButton buttonE : stepButtons) {
index++;
buttonPane.add(stepBtnPane.get(buttonE));
if (index != stepButtons.length) {
buttonPane.add(Box.createHorizontalStrut(4));
}
}
this.revalidate();
this.repaint();
}
/**
* 根据按钮的枚举返回对应按钮实例
*
* @param buttonE
* 按钮枚举
* @return JButton 按钮实例
*/
public JButton getButtonBy(EWizardButton buttonE) {
return stepBtnPane.get(buttonE);
}
private static final long serialVersionUID = -6353833271412606367L;
private Map<EWizardButton, JButton> stepBtnPane = new EnumMap<EWizardButton, JButton>(
EWizardButton.class);
private Box buttonPane;
}
}