patternjavaMinor
Simple Java Wizard
Viewed 0 times
wizardsimplejava
Problem
Working on a project, I encountered a need to create a wizard and when I ran into the need for a second, slightly different wizard, I generalized into these classes.
I originally based it off of this tutorial and attempt to adhere to these design considerations:
The purpose is to provide an easy to use way for creating wizards that are very simple (At minimum, the model needs to be able to tell the wizard it's state, give it the pages associated with that state and when it's complete) and not hinder more complex functionality.
I would like to know if there is any obviously expected functionality a Wizard is had that is missing and if the documentation and API make it easy to understand how to understand how to use and what everything does.
Top-level Wizard class. Used to create the wizard, inject the model and start and finish the wizard.
```
package com.thinoza.wizards;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map.Entry;
import java.util.function.Consumer;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.thinoza.wizards.models.WizardModel;
import com.thinoza.wizards.models.events.WizardModelChangeEvent;
/**
* Class for simple JDialog-based wizard.
*
* This class handles the "outside facing" functionality of displaying and
* traversing the pages and passing the final result out of itself.
*
* Custom functionality is provided by passing an implementation of {@link
* WizardModel} to the constructor.
*
* This class provides the following functionality:
I originally based it off of this tutorial and attempt to adhere to these design considerations:
- Allow traversing the pages in a flexible manner as needed.
- Allow the model to specify when to enable and disable buttons.
- Persist the data across the pages.
The purpose is to provide an easy to use way for creating wizards that are very simple (At minimum, the model needs to be able to tell the wizard it's state, give it the pages associated with that state and when it's complete) and not hinder more complex functionality.
I would like to know if there is any obviously expected functionality a Wizard is had that is missing and if the documentation and API make it easy to understand how to understand how to use and what everything does.
Top-level Wizard class. Used to create the wizard, inject the model and start and finish the wizard.
```
package com.thinoza.wizards;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map.Entry;
import java.util.function.Consumer;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.thinoza.wizards.models.WizardModel;
import com.thinoza.wizards.models.events.WizardModelChangeEvent;
/**
* Class for simple JDialog-based wizard.
*
* This class handles the "outside facing" functionality of displaying and
* traversing the pages and passing the final result out of itself.
*
* Custom functionality is provided by passing an implementation of {@link
* WizardModel} to the constructor.
*
* This class provides the following functionality:
Solution
dialog.getContentPane().add(contentPanel, BorderLayout.CENTER);
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
dialog.getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton cancelButton = new JButton("Cancel");
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
cancelButton.addActionListener(this);
}
{
backButton = new JButton("Back");
backButton.setActionCommand("Back");
backButton.setEnabled(false);
buttonPane.add(backButton);
dialog.getRootPane().setDefaultButton(backButton);
backButton.addActionListener(this);
}
{
nextButton = new JButton("Next");
nextButton.setActionCommand("Next");
buttonPane.add(nextButton);
dialog.getRootPane().setDefaultButton(nextButton);
nextButton.addActionListener(this);
}
}What's going on here?
Those braces just ... don't make sense. I had to check to make sure, but basically they're only used for scoping. You don't need that scoping here. You could very well make a function that takes a String, creates a
JButton, sets its actionCommand to that string, and adds this as actionListener to the button. Then you'd have less repeated lines too.Personally I feel that you should use blank lines for signaling separate "parts" of a function, and that quite possibly, each of these parts could be a separate function themselves.
if (model.canGoForward()) {
nextButton.setEnabled(true);
} else {
nextButton.setEnabled(false);
}
if (model.canGoBack()) {
backButton.setEnabled(true);
} else {
backButton.setEnabled(false);
}If true, set true, if false, set false. Replace with set value instead:
nextButton.setEnabled(model.canGoForward());
backButton.setEnabled(model.canGoBack());Oh, and I think
model.completable() should be model.isCompletable() instead, to signal it returns a boolean. Function names should be actionable, if they do something, or a statement, if they test/ask something.Code Snippets
dialog.getContentPane().add(contentPanel, BorderLayout.CENTER);
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
dialog.getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton cancelButton = new JButton("Cancel");
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
cancelButton.addActionListener(this);
}
{
backButton = new JButton("Back");
backButton.setActionCommand("Back");
backButton.setEnabled(false);
buttonPane.add(backButton);
dialog.getRootPane().setDefaultButton(backButton);
backButton.addActionListener(this);
}
{
nextButton = new JButton("Next");
nextButton.setActionCommand("Next");
buttonPane.add(nextButton);
dialog.getRootPane().setDefaultButton(nextButton);
nextButton.addActionListener(this);
}
}if (model.canGoForward()) {
nextButton.setEnabled(true);
} else {
nextButton.setEnabled(false);
}
if (model.canGoBack()) {
backButton.setEnabled(true);
} else {
backButton.setEnabled(false);
}nextButton.setEnabled(model.canGoForward());
backButton.setEnabled(model.canGoBack());Context
StackExchange Code Review Q#84062, answer score: 2
Revisions (0)
No revisions yet.