1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.commons.gui.wizard;
21
22 import java.awt.BorderLayout;
23 import java.awt.CardLayout;
24 import java.awt.Color;
25 import java.awt.Component;
26 import java.awt.Dialog;
27 import java.awt.Dimension;
28 import java.awt.Font;
29 import java.awt.Frame;
30 import java.awt.event.ActionEvent;
31 import java.util.ArrayList;
32 import java.util.LinkedList;
33 import java.util.List;
34 import javax.swing.AbstractButton;
35 import javax.swing.Action;
36 import javax.swing.BorderFactory;
37 import javax.swing.JLabel;
38 import javax.swing.JPanel;
39 import javax.swing.SwingConstants;
40 import javax.swing.border.EmptyBorder;
41 import org.xnap.commons.gui.Builder;
42 import org.xnap.commons.gui.DefaultDialog;
43 import org.xnap.commons.gui.action.AbstractXNapAction;
44 import org.xnap.commons.i18n.I18n;
45 import org.xnap.commons.i18n.I18nFactory;
46
47
48 /***
49 *
50 * @author Steffen Pingel
51 */
52 public class WizardDialog extends DefaultDialog
53 {
54
55 private static final I18n i18n = I18nFactory.getI18n(WizardDialog.class);
56
57 private JLabel titleLabel;
58 private JLabel iconLabel;
59 private JLabel descriptionLabel;
60
61 private JPanel pagePanel;
62 private CardLayout pageCardLayout;
63
64 private List<WizardPage> pages = new LinkedList<WizardPage>();
65 private int selectedIndex = -1;
66
67 private AbstractButton nextButton;
68 private AbstractButton finishButton;
69
70 private PreviousAction previousAction = new PreviousAction();
71 private NextAction nextAction = new NextAction();
72 private FinishAction finishAction = new FinishAction();
73
74 private List<WizardDialogListener> listeners
75 = new ArrayList<WizardDialogListener>();
76
77 public WizardDialog(int buttons)
78 {
79 super(buttons);
80
81 initialize();
82 }
83
84 public WizardDialog(Dialog owner, int buttons)
85 {
86 super(owner, buttons);
87
88 initialize();
89 }
90
91 public WizardDialog(Frame owner, int buttons)
92 {
93 super(owner, buttons);
94
95 initialize();
96 }
97
98 public WizardDialog()
99 {
100 super(BUTTON_CANCEL);
101
102 initialize();
103 }
104
105 public WizardDialog(Dialog owner)
106 {
107 super(owner, BUTTON_CANCEL);
108
109 initialize();
110 }
111
112 public WizardDialog(Frame owner)
113 {
114 super(owner, BUTTON_CANCEL);
115
116 initialize();
117 }
118
119 private void initialize()
120 {
121 JPanel jpTop = new JPanel(new BorderLayout());
122 jpTop.setBackground(Color.white);
123 jpTop.setBorder(BorderFactory.createEtchedBorder());
124 getContentPane().add(jpTop, BorderLayout.NORTH);
125
126 JPanel jpTitle = new JPanel(new BorderLayout());
127 jpTitle.setBackground(Color.white);
128 jpTop.add(jpTitle, BorderLayout.CENTER);
129
130 titleLabel = new JLabel(" ");
131 titleLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
132 titleLabel.setFont(new Font("Dialog", Font.BOLD, 16));
133 titleLabel.setForeground(Color.black);
134 jpTitle.add(titleLabel, BorderLayout.NORTH);
135
136 descriptionLabel = new JLabel(" ");
137 descriptionLabel.setBackground(Color.white);
138 descriptionLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
139 descriptionLabel.setForeground(Color.black);
140 jpTitle.add(descriptionLabel, BorderLayout.CENTER);
141
142 iconLabel = new JLabel();
143 iconLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
144 jpTop.add(iconLabel, BorderLayout.EAST);
145
146
147 pageCardLayout = new CardLayout();
148 pagePanel = new JPanel();
149 pagePanel.setBorder(new EmptyBorder(5, 5, 5, 5));
150 pagePanel.setLayout(pageCardLayout);
151
152
153 JPanel jpButtons = getButtonPanel();
154
155 jpButtons.add(Builder.createButton(previousAction), 0);
156
157 nextButton = Builder.createButton(nextAction);
158 nextButton.setHorizontalTextPosition(SwingConstants.LEFT);
159 jpButtons.add(nextButton, 1);
160
161 finishButton = Builder.createButton(finishAction);
162 jpButtons.add(finishButton, 2);
163
164
165 setMainComponent(pagePanel);
166 setSize(640, 480);
167 }
168
169 public void addPage(WizardPage page, String identifier)
170 {
171
172 pages.add(page);
173 pagePanel.add(page.getPanel(), identifier);
174 if (selectedIndex == -1) {
175 selectedIndex = 0;
176 }
177 updateHeader();
178 }
179
180 public void addPage(int index, WizardPage page, String identifier)
181 {
182
183 pages.add(index, page);
184 pagePanel.add(page.getPanel(), identifier);
185 if (selectedIndex == -1) {
186 selectedIndex = 0;
187 }
188 else if (index <= selectedIndex) {
189 selectedIndex++;
190 }
191 updateHeader();
192 }
193
194 public void addWizardDialogListener(WizardDialogListener listener)
195 {
196 listeners.add(listener);
197 }
198
199 public void finish()
200 {
201 boolean canClose = true;
202 for (WizardPage page : pages) {
203 canClose &= page.apply();
204 }
205
206 if (canClose) {
207 isOkay = true;
208 close();
209 }
210 }
211
212 public Action getFinishAction()
213 {
214 return finishAction;
215 }
216
217 public Action getNextAction()
218 {
219 return nextAction;
220 }
221
222 public int getSelectedIndex()
223 {
224 return selectedIndex;
225 }
226
227 public WizardPage getSelectedPage()
228 {
229 return (WizardPage)pages.get(getSelectedIndex());
230 }
231
232
233 protected void firePageChaned(WizardPage oldPage, WizardPage newPage)
234 {
235 WizardDialogListener[] array
236 = listeners.toArray(new WizardDialogListener[0]);
237 for (int i = array.length - 1; i >= 0; i--) {
238 array[i].pageChanged(oldPage, newPage);
239 }
240 }
241
242 /***
243 * Removes <code>page</code> from the dialog. Does nothing if page has not
244 * been previously added to the dialog.
245 * @param page the page to remove
246 */
247 public void removePage(WizardPage page)
248 {
249 int index = pages.indexOf(page);
250 if (index == -1) {
251 return;
252 }
253 pagePanel.remove(page.getPanel());
254 pages.remove(index);
255 if (index <= selectedIndex) {
256 selectedIndex--;
257 }
258 if (selectedIndex == -1) {
259 clearHeader();
260 } else {
261 updateHeader();
262 }
263 }
264
265 public void removeWizardDialogListener(WizardDialogListener listener)
266 {
267 listeners.remove(listener);
268 }
269
270 private void updateActions()
271 {
272 previousAction.setEnabled(selectedIndex > 0);
273 nextAction.setEnabled(selectedIndex < pages.size() - 1);
274 if (nextAction.isEnabled()) {
275 nextButton.requestFocus();
276 }
277 else {
278 finishButton.requestFocus();
279 }
280 }
281
282 public void showNextPage()
283 {
284 if (selectedIndex == pages.size() - 1) {
285 throw new IllegalStateException("no more pages");
286 }
287
288 WizardPage oldPage = getSelectedPage();
289
290 pageCardLayout.next(pagePanel);
291 selectedIndex++;
292 updateHeader();
293
294 firePageChaned(oldPage, getSelectedPage());
295 }
296
297 public void showPreviousPage()
298 {
299 if (selectedIndex <= 0) {
300 throw new IllegalStateException("no more pages");
301 }
302
303 WizardPage oldPage = getSelectedPage();
304
305 pageCardLayout.previous(pagePanel);
306 selectedIndex--;
307 updateHeader();
308
309 firePageChaned(oldPage, getSelectedPage());
310 }
311
312 private void updateHeader()
313 {
314 WizardPage panel = getSelectedPage();
315 titleLabel.setText(panel.getTitle());
316 iconLabel.setIcon(panel.getIcon());
317 descriptionLabel.setText(panel.getDescription());
318
319 updateActions();
320 }
321
322 private void clearHeader()
323 {
324 titleLabel.setText(" ");
325 iconLabel.setIcon(null);
326 descriptionLabel.setText(" ");
327 }
328
329 public class PreviousAction extends AbstractXNapAction {
330
331 public PreviousAction()
332 {
333 putValue(Action.NAME, i18n.tr("Previous"));
334 putValue(ICON_FILENAME, "1leftarrow.png");
335 }
336
337 public void actionPerformed(ActionEvent event)
338 {
339 showPreviousPage();
340 }
341
342 }
343
344 public class NextAction extends AbstractXNapAction {
345
346 public NextAction()
347 {
348 putValue(Action.NAME, i18n.tr("Next"));
349 putValue(ICON_FILENAME, "1rightarrow.png");
350 }
351
352 public void actionPerformed(ActionEvent event)
353 {
354 showNextPage();
355 }
356
357 }
358
359 public class FinishAction extends AbstractXNapAction {
360
361 public FinishAction()
362 {
363 putValue(Action.NAME, i18n.tr("Finish"));
364 }
365
366 public void actionPerformed(ActionEvent event)
367 {
368 finish();
369 }
370
371 }
372
373 protected class PContainer extends JPanel
374 {
375 Dimension maxDim = new Dimension(0, 0);
376
377 public void add(Component comp, Object constraints)
378 {
379 Dimension d = comp.getPreferredSize();
380 if (d.height > maxDim.height) {
381 maxDim.height = d.height;
382 }
383 if (d.width > maxDim.width) {
384 maxDim.width = d.width;
385 }
386
387 super.add(comp, constraints);
388 }
389
390 public Dimension getPreferredSize()
391 {
392
393 return new Dimension(maxDim.width + 10, maxDim.height + 30);
394 }
395 }
396
397 }