diff --git a/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/Wizard.java b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/Wizard.java
new file mode 100644
index 000000000..560216bd2
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/Wizard.java
@@ -0,0 +1,556 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.customcontrols.wizard;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.Insets;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+import javax.swing.border.EmptyBorder;
+
+import com.ibm.media.bean.multiplayer.ImageLabel;
+
+import net.java.sip.communicator.impl.gui.i18n.Messages;
+import net.java.sip.communicator.impl.gui.utils.ImageLoader;
+import net.java.sip.communicator.service.gui.WizardContainer;
+import net.java.sip.communicator.service.gui.WizardPage;
+
+/**
+ * This class implements a basic wizard dialog, where the programmer can
+ * insert one or more Components to act as panels. These panels can be navigated
+ * through arbitrarily using the 'Next' or 'Back' buttons, or the dialog itself
+ * can be closed using the 'Cancel' button. Note that even though the dialog
+ * uses a CardLayout manager, the order of the panels is not linear. Each panel
+ * determines at runtime what its next and previous panel will be.
+ */
+public class Wizard extends WindowAdapter
+ implements WizardContainer, PropertyChangeListener {
+
+ /**
+ * The identifier of the summary wizard page.
+ */
+ String SUMMARY_PAGE_IDENTIFIER = "SUMMARY";
+
+ /**
+ * The identifier of the default wizard page.
+ */
+ String DEFAULT_PAGE_IDENTIFIER = "DEFAULT";
+
+
+ /**
+ * Indicates that the 'Finish' button was pressed to close the dialog.
+ */
+ public static final int FINISH_RETURN_CODE = 0;
+ /**
+ * Indicates that the 'Cancel' button was pressed to close the dialog, or
+ * the user pressed the close box in the corner of the window.
+ */
+ public static final int CANCEL_RETURN_CODE = 1;
+ /**
+ * Indicates that the dialog closed due to an internal error.
+ */
+ public static final int ERROR_RETURN_CODE = 2;
+
+ /**
+ * The String-based action command for the 'Next' button.
+ */
+ public static final String NEXT_BUTTON_ACTION_COMMAND
+ = "NextButtonActionCommand";
+ /**
+ * The String-based action command for the 'Back' button.
+ */
+ public static final String BACK_BUTTON_ACTION_COMMAND
+ = "BackButtonActionCommand";
+ /**
+ * The String-based action command for the 'Cancel' button.
+ */
+ public static final String CANCEL_BUTTON_ACTION_COMMAND
+ = "CancelButtonActionCommand";
+
+ private BufferedImage wizardIcon;
+
+ private JLabel wizardIconLabel = new JLabel();
+
+ private JPanel wizardIconPanel
+ = new JPanel(new FlowLayout(FlowLayout.CENTER));
+
+ /**
+ * The i18n text used for the buttons. Loaded from a property resource
+ * file.
+ */
+ static String BACK_TEXT;
+ static String NEXT_TEXT;
+ static String FINISH_TEXT;
+ static String CANCEL_TEXT;
+
+ /**
+ * The image icons used for the buttons. Filenames are loaded from a
+ * property resource file.
+ */
+ static Icon BACK_ICON;
+ static Icon NEXT_ICON;
+ static Icon FINISH_ICON;
+ static Icon CANCEL_ICON;
+
+
+ private WizardModel wizardModel;
+ private WizardController wizardController;
+ private JDialog wizardDialog;
+
+ private JPanel cardPanel;
+ private CardLayout cardLayout;
+ private JButton backButton;
+ private JButton nextButton;
+ private JButton cancelButton;
+
+ private int returnCode;
+
+
+
+ /**
+ * Default constructor. This method creates a new WizardModel object and
+ * passes it into the overloaded constructor.
+ */
+ public Wizard() {
+ this((Frame)null);
+ }
+
+ /**
+ * This method accepts a java.awt.Dialog object as the javax.swing.JDialog's
+ * parent.
+ * @param owner The java.awt.Dialog object that is the owner of this dialog.
+ */
+ public Wizard(Dialog owner) {
+ wizardModel = new WizardModel();
+ wizardDialog = new JDialog(owner);
+ initComponents();
+ }
+
+ /**
+ * This method accepts a java.awt.Frame object as the javax.swing.JDialog's
+ * parent.
+ * @param owner The java.awt.Frame object that is the owner of the
+ * javax.swing.JDialog.
+ */
+ public Wizard(Frame owner) {
+ wizardModel = new WizardModel();
+ wizardDialog = new JDialog(owner);
+ initComponents();
+ }
+
+ /**
+ * Returns an instance of the JDialog that this class created.This is useful
+ * in the event that you want to change any of the JDialog parameters
+ * manually.
+ * @return The JDialog instance that this class created.
+ */
+ public JDialog getDialog() {
+ return wizardDialog;
+ }
+
+ /**
+ * Returns the owner of the generated javax.swing.JDialog.
+ * @return The owner (java.awt.Frame or java.awt.Dialog) of the
+ * javax.swing.JDialog generated
+ * by this class.
+ */
+ public Component getOwner() {
+ return wizardDialog.getOwner();
+ }
+
+ /**
+ * Sets the title of the generated javax.swing.JDialog.
+ * @param s The title of the dialog.
+ */
+ public void setTitle(String s) {
+ wizardDialog.setTitle(s);
+ }
+
+ /**
+ * Returns the current title of the generated dialog.
+ * @return The String-based title of the generated dialog.
+ */
+ public String getTitle() {
+ return wizardDialog.getTitle();
+ }
+
+ /**
+ * Sets the modality of the generated javax.swing.JDialog.
+ * @param b the modality of the dialog
+ */
+ public void setModal(boolean b) {
+ wizardDialog.setModal(b);
+ }
+
+ /**
+ * Returns the modality of the dialog.
+ * @return A boolean indicating whether or not the generated
+ * javax.swing.JDialog is modal.
+ */
+ public boolean isModal() {
+ return wizardDialog.isModal();
+ }
+
+ /**
+ * Convienence method that displays a modal wizard dialog and blocks until
+ * the dialog has completed.
+ * @return Indicates how the dialog was closed. Compare this value against
+ * the RETURN_CODE constants at the beginning of the class.
+ */
+ public int showModalDialog() {
+
+ wizardDialog.setModal(true);
+ wizardDialog.pack();
+ wizardDialog.setVisible(true);
+
+ return returnCode;
+ }
+
+ /**
+ * Returns the current model of the wizard dialog.
+ * @return A WizardModel instance, which serves as the model for the
+ * wizard dialog.
+ */
+ public WizardModel getModel() {
+ return wizardModel;
+ }
+
+ /**
+ * Add a Component as a panel for the wizard dialog by registering its
+ * WizardPanelDescriptor object. Each panel is identified by a unique
+ * Object-based identifier (often a String), which can be used by the
+ * setCurrentPanel() method to display the panel at runtime.
+ * @param id An Object-based identifier used to identify the
+ * WizardPanelDescriptor object.
+ * @param panel The WizardPanelDescriptor object which contains helpful
+ * information about the panel.
+ */
+ public void registerWizardPage(Object id, WizardPage page) {
+
+ // Add the incoming panel to our JPanel display that is managed by
+ // the CardLayout layout manager.
+
+ Object wizardForm = page.getWizardForm();
+
+ if(wizardForm instanceof Component)
+ cardPanel.add((Component)wizardForm, id);
+
+ // Place a reference to it in the model.
+ wizardModel.registerPage(id, page);
+ }
+
+ /**
+ * Removes from the wizard the WizardPage corresponding to the
+ * given identifier.
+ *
+ * @param id The identifer of the wizard page.
+ */
+ public void unregisterWizardPage(Object id) {
+
+ cardPanel.remove(
+ (Component)wizardModel.getWizardPage(id).getWizardForm());
+
+ wizardModel.unregisterPage(id);
+ }
+
+ /**
+ * Removes from the wizard all WizardPages except the default one.
+ */
+ public void unregisterAll() {
+
+ Iterator i = wizardModel.getAllPages();
+
+ while(i.hasNext()) {
+ Map.Entry entry = (Map.Entry)i.next();
+
+ Object id = entry.getKey();
+
+ if (!id.equals(DEFAULT_PAGE_IDENTIFIER)
+ && !id.equals(SUMMARY_PAGE_IDENTIFIER)) {
+ cardPanel.remove(
+ (Component)((WizardPage)entry.getValue()).getWizardForm());
+
+ wizardModel.unregisterPage(id);
+ }
+ }
+ }
+
+ /**
+ * Displays the panel identified by the object passed in. This is the same
+ * Object-based identified used when registering the panel.
+ * @param id The Object-based identifier of the panel to be displayed.
+ */
+ public void setCurrentPage(Object id) {
+
+ // Get the hashtable reference to the panel that should
+ // be displayed. If the identifier passed in is null, then close
+ // the dialog.
+
+ if (id == null)
+ close(ERROR_RETURN_CODE);
+
+ WizardPage oldPanelDescriptor
+ = wizardModel.getCurrentWizardPage();
+ if (oldPanelDescriptor != null)
+ oldPanelDescriptor.pageHiding();
+
+ wizardModel.setCurrentPanel(id);
+ wizardModel.getCurrentWizardPage().pageShowing();
+
+ // Show the panel in the dialog.
+
+ cardLayout.show(cardPanel, id.toString());
+ wizardModel.getCurrentWizardPage().pageShown();
+
+
+ }
+
+ /**
+ * Method used to listen for property change events from the model and
+ * update the dialog's graphical components as necessary.
+ * @param evt PropertyChangeEvent passed from the model to signal that one
+ * of its properties has changed value.
+ */
+ public void propertyChange(PropertyChangeEvent evt) {
+
+ if (evt.getPropertyName().equals(
+ WizardModel.CURRENT_PAGE_PROPERTY)) {
+ wizardController.resetButtonsToPanelRules();
+ } else if (evt.getPropertyName().equals(
+ WizardModel.NEXT_FINISH_BUTTON_TEXT_PROPERTY)) {
+ nextButton.setText(evt.getNewValue().toString());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.BACK_BUTTON_TEXT_PROPERTY)) {
+ backButton.setText(evt.getNewValue().toString());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.CANCEL_BUTTON_TEXT_PROPERTY)) {
+ cancelButton.setText(evt.getNewValue().toString());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.NEXT_FINISH_BUTTON_ENABLED_PROPERTY)) {
+ nextButton.setEnabled(((Boolean)evt.getNewValue()).booleanValue());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.BACK_BUTTON_ENABLED_PROPERTY)) {
+ backButton.setEnabled(((Boolean)evt.getNewValue()).booleanValue());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.CANCEL_BUTTON_ENABLED_PROPERTY)) {
+ cancelButton.setEnabled(((Boolean)evt.getNewValue()).booleanValue());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.NEXT_FINISH_BUTTON_ICON_PROPERTY)) {
+ nextButton.setIcon((Icon)evt.getNewValue());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.BACK_BUTTON_ICON_PROPERTY)) {
+ backButton.setIcon((Icon)evt.getNewValue());
+ } else if (evt.getPropertyName().equals(
+ WizardModel.CANCEL_BUTTON_ICON_PROPERTY)) {
+ cancelButton.setIcon((Icon)evt.getNewValue());
+ }
+
+ }
+
+ /**
+ * Retrieves the last return code set by the dialog.
+ * @return An integer that identifies how the dialog was closed. See the
+ * RETURN_CODE constants of this class for possible values.
+ */
+ public int getReturnCode() {
+ return returnCode;
+ }
+
+ /**
+ * Mirrors the WizardModel method of the same name.
+ * @return A boolean indicating if the button is enabled.
+ */
+ public boolean isBackButtonEnabled() {
+ return wizardModel.getBackButtonEnabled().booleanValue();
+ }
+
+ /**
+ * Mirrors the WizardModel method of the same name.
+ * @param newValue The new enabled status of the button.
+ */
+ public void setBackButtonEnabled(boolean newValue) {
+ wizardModel.setBackButtonEnabled(new Boolean(newValue));
+ }
+
+ /**
+ * Mirrors the WizardModel method of the same name.
+ * @return A boolean indicating if the button is enabled.
+ */
+ public boolean isNextFinishButtonEnabled() {
+ return wizardModel.getNextFinishButtonEnabled().booleanValue();
+ }
+
+ /**
+ * Mirrors the WizardModel method of the same name.
+ * @param newValue The new enabled status of the button.
+ */
+ public void setNextFinishButtonEnabled(boolean newValue) {
+ wizardModel.setNextFinishButtonEnabled(new Boolean(newValue));
+ }
+
+ /**
+ * Mirrors the WizardModel method of the same name.
+ * @return A boolean indicating if the button is enabled.
+ */
+ public boolean isCancelButtonEnabled() {
+ return wizardModel.getCancelButtonEnabled().booleanValue();
+ }
+
+ /**
+ * Mirrors the WizardModel method of the same name.
+ * @param newValue The new enabled status of the button.
+ */
+ public void setCancelButtonEnabled(boolean newValue) {
+ wizardModel.setCancelButtonEnabled(new Boolean(newValue));
+ }
+
+ /**
+ * Closes the dialog and sets the return code to the integer parameter.
+ * @param code The return code.
+ */
+ void close(int code) {
+ WizardPage oldPanelDescriptor
+ = wizardModel.getCurrentWizardPage();
+ if (oldPanelDescriptor != null)
+ oldPanelDescriptor.pageHiding();
+
+ returnCode = code;
+ wizardDialog.dispose();
+ }
+
+ /**
+ * This method initializes the components for the wizard dialog: it creates
+ * a JDialog as a CardLayout panel surrounded by a small amount of space on
+ * each side, as well as three buttons at the bottom.
+ */
+
+ private void initComponents() {
+
+ wizardModel.addPropertyChangeListener(this);
+ wizardController = new WizardController(this);
+
+ wizardDialog.getContentPane().setLayout(new BorderLayout());
+ wizardDialog.addWindowListener(this);
+
+ /*
+ * Create the outer wizard panel, which is responsible for three
+ * buttons: Next, Back, and Cancel. It is also responsible a JPanel
+ * above them that uses a CardLayout layout manager to display multiple
+ * panels in the same spot.
+ */
+
+ JPanel buttonPanel = new JPanel();
+ JSeparator separator = new JSeparator();
+ Box buttonBox = new Box(BoxLayout.X_AXIS);
+
+ cardPanel = new JPanel();
+ cardPanel.setBorder(new EmptyBorder(new Insets(5, 10, 5, 10)));
+
+ cardLayout = new CardLayout();
+ cardPanel.setLayout(cardLayout);
+
+ backButton = new JButton();
+ nextButton = new JButton();
+ cancelButton = new JButton();
+
+ backButton.setActionCommand(BACK_BUTTON_ACTION_COMMAND);
+ nextButton.setActionCommand(NEXT_BUTTON_ACTION_COMMAND);
+ cancelButton.setActionCommand(CANCEL_BUTTON_ACTION_COMMAND);
+
+ backButton.addActionListener(wizardController);
+ nextButton.addActionListener(wizardController);
+ cancelButton.addActionListener(wizardController);
+
+ // Create the buttons with a separator above them, then place them
+ // on the east side of the panel with a small amount of space between
+ // the back and the next button, and a larger amount of space between
+ // the next button and the cancel button.
+
+ buttonPanel.setLayout(new BorderLayout());
+ buttonPanel.add(separator, BorderLayout.NORTH);
+
+ buttonBox.setBorder(new EmptyBorder(new Insets(5, 10, 5, 10)));
+ buttonBox.add(backButton);
+ buttonBox.add(Box.createHorizontalStrut(10));
+ buttonBox.add(nextButton);
+ buttonBox.add(Box.createHorizontalStrut(30));
+ buttonBox.add(cancelButton);
+
+ buttonPanel.add(buttonBox, java.awt.BorderLayout.EAST);
+
+ wizardIconPanel.add(wizardIconLabel);
+
+ wizardDialog.getContentPane().add(
+ buttonPanel, java.awt.BorderLayout.SOUTH);
+ wizardDialog.getContentPane().add(
+ cardPanel, java.awt.BorderLayout.CENTER);
+ wizardDialog.getContentPane().add(
+ wizardIconPanel,
+ java.awt.BorderLayout.WEST);
+ }
+
+ /**
+ * If the user presses the close box on the dialog's window, treat it
+ * as a cancel.
+ * @param e The event passed in from AWT.
+ */
+
+ public void windowClosing(WindowEvent e) {
+ returnCode = CANCEL_RETURN_CODE;
+ }
+
+
+ static {
+ BACK_TEXT = Messages.getString("back");
+ NEXT_TEXT = Messages.getString("next");
+ CANCEL_TEXT = Messages.getString("cancel");
+ FINISH_TEXT = Messages.getString("finish");
+ }
+
+
+ public void setLocation(int x, int y) {
+ this.wizardDialog.setLocation(x, y);
+ }
+
+ public BufferedImage getWizzardIcon() {
+ return wizardIcon;
+ }
+
+ public void setWizzardIcon(BufferedImage wizardIcon) {
+ wizardIconLabel.setBorder(BorderFactory
+ .createCompoundBorder(
+ BorderFactory.createEmptyBorder(20, 20, 20, 20),
+ BorderFactory.createTitledBorder("")));
+
+ this.wizardIconLabel.setIcon(new ImageIcon(wizardIcon));
+ }
+
+ public void setReturnCode(int returnCode) {
+ this.returnCode = returnCode;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardController.java b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardController.java
new file mode 100644
index 000000000..951ffd2a9
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardController.java
@@ -0,0 +1,139 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package net.java.sip.communicator.impl.gui.customcontrols.wizard;
+
+import java.awt.event.ActionListener;
+
+import net.java.sip.communicator.service.gui.WizardPage;
+
+/**
+ * This class is responsible for reacting to events generated by pushing any
+ * of the three buttons, 'Next', 'Previous', and 'Cancel.' Based on what
+ * button is pressed, the controller will update the model to show a new panel
+ * and reset the state of the buttons as necessary.
+ */
+public class WizardController implements ActionListener {
+
+ private Wizard wizard;
+
+ /**
+ * This constructor accepts a reference to the Wizard component that created
+ * it, which it uses to update the button components and access the
+ * WizardModel.
+ * @param w A callback to the Wizard component that created this controller.
+ */
+ public WizardController(Wizard w) {
+ wizard = w;
+ }
+
+ /**
+ * Calling method for the action listener interface. This class listens for
+ * actions performed by the buttons in the Wizard class, and calls methods
+ * below to determine the correct course of action.
+ * @param evt The ActionEvent that occurred.
+ */
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+
+ if (evt.getActionCommand().equals(
+ Wizard.CANCEL_BUTTON_ACTION_COMMAND))
+ cancelButtonPressed();
+ else if (evt.getActionCommand().equals(
+ Wizard.BACK_BUTTON_ACTION_COMMAND))
+ backButtonPressed();
+ else if (evt.getActionCommand().equals(
+ Wizard.NEXT_BUTTON_ACTION_COMMAND))
+ nextButtonPressed();
+
+ }
+
+ /**
+ * Closes the wizard by specifying the appropriate return code, when user
+ * has pressed the "Cancel" button.
+ */
+ private void cancelButtonPressed() {
+ wizard.close(Wizard.CANCEL_RETURN_CODE);
+ }
+
+ /**
+ * If it is a finishable panel, closes the dialog. Otherwise, gets the
+ * ID that the current panel identifies as the next panel, and displays
+ * the panel that it's identifying.
+ */
+ private void nextButtonPressed() {
+
+ WizardModel model = wizard.getModel();
+ WizardPage page = model.getCurrentWizardPage();
+
+ page.pageNext();
+
+ Object nextPageIdentifier = page.getNextPageIdentifier();
+
+ if (nextPageIdentifier
+ .equals(WizardPage.FINISH_PAGE_IDENTIFIER)) {
+ wizard.close(Wizard.FINISH_RETURN_CODE);
+ }
+ else {
+ wizard.setCurrentPage(nextPageIdentifier);
+ }
+ }
+
+ /**
+ * Gets the descriptor that the current panel identifies as the previous
+ * panel, and displays the panel that it's identifying.
+ */
+ private void backButtonPressed() {
+
+ WizardModel model = wizard.getModel();
+ WizardPage page = model.getCurrentWizardPage();
+
+ page.pageBack();
+
+ Object backPageIdentifier = page.getBackPageIdentifier();
+
+ wizard.setCurrentPage(backPageIdentifier);
+ }
+
+ /**
+ * Resets the buttons to support the original panel rules, including
+ * whether the next or back buttons are enabled or disabled, or if
+ * the panel is finishable. If the panel in question has another panel
+ * behind it, enables the back button. Otherwise, disables it. If the
+ * panel in question has one or more panels in front of it, enables the
+ * next button. Otherwise, disables it.
+ */
+ void resetButtonsToPanelRules() {
+
+ WizardModel model = wizard.getModel();
+ WizardPage page = model.getCurrentWizardPage();
+
+ model.setCancelButtonText(Wizard.CANCEL_TEXT);
+
+ model.setBackButtonText(Wizard.BACK_TEXT);
+
+ if (page.getBackPageIdentifier() != null)
+ model.setBackButtonEnabled(Boolean.TRUE);
+ else
+ model.setBackButtonEnabled(Boolean.FALSE);
+
+ if (page.getNextPageIdentifier() != null)
+ model.setNextFinishButtonEnabled(Boolean.TRUE);
+ else
+ model.setNextFinishButtonEnabled(Boolean.FALSE);
+
+ if (page.getNextPageIdentifier()
+ .equals(WizardPage.FINISH_PAGE_IDENTIFIER)) {
+
+ model.setNextFinishButtonText(Wizard.FINISH_TEXT);
+ } else {
+ model.setNextFinishButtonText(Wizard.NEXT_TEXT);
+ }
+
+ }
+
+
+}
diff --git a/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardModel.java b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardModel.java
new file mode 100644
index 000000000..0fc89f5f5
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardModel.java
@@ -0,0 +1,407 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package net.java.sip.communicator.impl.gui.customcontrols.wizard;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.Icon;
+
+import net.java.sip.communicator.service.gui.WizardPage;
+
+/**
+ * The model for the Wizard component, which tracks the text, icons, and
+ * enabled state of each of the buttons, as well as the current panel that
+ * is displayed. Note that the model, in its current form, is not intended
+ * to be subclassed.
+ *
+ * @author Yana Stamcheva
+ */
+
+
+public class WizardModel {
+
+ /**
+ * Identification string for the current panel.
+ */
+ public static final String CURRENT_PAGE_PROPERTY
+ = "currentPageProperty";
+
+ /**
+ * Property identification String for the Back button's text
+ */
+ public static final String BACK_BUTTON_TEXT_PROPERTY
+ = "backButtonTextProperty";
+ /**
+ * Property identification String for the Back button's icon
+ */
+ public static final String BACK_BUTTON_ICON_PROPERTY
+ = "backButtonIconProperty";
+ /**
+ * Property identification String for the Back button's enabled state
+ */
+ public static final String BACK_BUTTON_ENABLED_PROPERTY
+ = "backButtonEnabledProperty";
+
+ /**
+ * Property identification String for the Next button's text
+ */
+ public static final String NEXT_FINISH_BUTTON_TEXT_PROPERTY
+ = "nextButtonTextProperty";
+ /**
+ * Property identification String for the Next button's icon
+ */
+ public static final String NEXT_FINISH_BUTTON_ICON_PROPERTY
+ = "nextButtonIconProperty";
+ /**
+ * Property identification String for the Next button's enabled state
+ */
+ public static final String NEXT_FINISH_BUTTON_ENABLED_PROPERTY
+ = "nextButtonEnabledProperty";
+
+ /**
+ * Property identification String for the Cancel button's text
+ */
+ public static final String CANCEL_BUTTON_TEXT_PROPERTY
+ = "cancelButtonTextProperty";
+ /**
+ * Property identification String for the Cancel button's icon
+ */
+ public static final String CANCEL_BUTTON_ICON_PROPERTY
+ = "cancelButtonIconProperty";
+ /**
+ * Property identification String for the Cancel button's enabled state
+ */
+ public static final String CANCEL_BUTTON_ENABLED_PROPERTY
+ = "cancelButtonEnabledProperty";
+
+ private WizardPage currentPanel;
+
+ private HashMap panelHashmap;
+
+ private HashMap buttonTextHashmap;
+ private HashMap buttonIconHashmap;
+ private HashMap buttonEnabledHashmap;
+
+ private PropertyChangeSupport propertyChangeSupport;
+
+
+ /**
+ * Default constructor.
+ */
+ public WizardModel() {
+
+ panelHashmap = new HashMap();
+
+ buttonTextHashmap = new HashMap();
+ buttonIconHashmap = new HashMap();
+ buttonEnabledHashmap = new HashMap();
+
+ propertyChangeSupport = new PropertyChangeSupport(this);
+
+ }
+
+ /**
+ * Returns the currently displayed WizardPage.
+ * @return The currently displayed WizardPage
+ */
+ WizardPage getCurrentWizardPage() {
+ return currentPanel;
+ }
+
+ /**
+ * Registers the WizardPage in the model using the
+ * Object-identifier specified.
+ * @param id Object-based identifier
+ * @param page WizardPage that describes the panel
+ */
+ void registerPage(Object id, WizardPage page) {
+ panelHashmap.put(id, page);
+ }
+
+ /**
+ * Unregisters the WizardPage corresponding to the given id.
+ *
+ * @param id The id of the WizardPage.
+ */
+ void unregisterPage(Object id) {
+ panelHashmap.remove(id);
+ }
+
+ /**
+ * Returns the WizardPage corresponding to the given identifier.
+ * @param id The identifier of the page.
+ * @return the WizardPage corresponding to the given identifier.
+ */
+ WizardPage getWizardPage(Object id) {
+ return (WizardPage)panelHashmap.get(id);
+ }
+
+ Iterator getAllPages() {
+ return panelHashmap.entrySet().iterator();
+ }
+
+ /**
+ * Sets the current panel to that identified by the Object passed in.
+ * @param id Object-based panel identifier
+ * @return boolean indicating success or failure
+ */
+ boolean setCurrentPanel(Object id) {
+ // First, get the hashtable reference to the panel that should
+ // be displayed.
+
+ WizardPage nextPanel =
+ (WizardPage)panelHashmap.get(id);
+
+
+ // If we couldn't find the panel that should be displayed, return
+ // false.
+
+ if (nextPanel == null)
+ throw new WizardPanelNotFoundException();
+
+ WizardPage oldPanel = currentPanel;
+ currentPanel = nextPanel;
+
+ if (oldPanel != currentPanel) {
+ firePropertyChange(CURRENT_PAGE_PROPERTY,
+ oldPanel, currentPanel);
+ }
+ return true;
+ }
+
+ /**
+ * Returns the text for the Back button.
+ * @return the text for the Back button.
+ */
+ Object getBackButtonText() {
+ return buttonTextHashmap.get(BACK_BUTTON_TEXT_PROPERTY);
+ }
+
+ /**
+ * Sets the text for the back button.
+ * @param newText The text to set.
+ */
+ void setBackButtonText(Object newText) {
+
+ Object oldText = getBackButtonText();
+ if (!newText.equals(oldText)) {
+ buttonTextHashmap.put(BACK_BUTTON_TEXT_PROPERTY, newText);
+ firePropertyChange(BACK_BUTTON_TEXT_PROPERTY, oldText, newText);
+ }
+ }
+
+ /**
+ * Returns the text for the Next/Finish button.
+ * @return the text for the Next/Finish button.
+ */
+ Object getNextFinishButtonText() {
+ return buttonTextHashmap.get(NEXT_FINISH_BUTTON_TEXT_PROPERTY);
+ }
+
+ void setNextFinishButtonText(Object newText) {
+
+ Object oldText = getNextFinishButtonText();
+ if (!newText.equals(oldText)) {
+ buttonTextHashmap.put(NEXT_FINISH_BUTTON_TEXT_PROPERTY, newText);
+ firePropertyChange(NEXT_FINISH_BUTTON_TEXT_PROPERTY,
+ oldText, newText);
+ }
+ }
+
+ /**
+ * Returns the text for the Cancel button.
+ * @return the text for the Cancel button.
+ */
+ Object getCancelButtonText() {
+ return buttonTextHashmap.get(CANCEL_BUTTON_TEXT_PROPERTY);
+ }
+
+ /**
+ * Sets the text for the Cancel button.
+ * @param newText The text to set.
+ */
+ void setCancelButtonText(Object newText) {
+
+ Object oldText = getCancelButtonText();
+ if (!newText.equals(oldText)) {
+ buttonTextHashmap.put(CANCEL_BUTTON_TEXT_PROPERTY, newText);
+ firePropertyChange(CANCEL_BUTTON_TEXT_PROPERTY, oldText, newText);
+ }
+ }
+
+ /**
+ * Returns the icon for the Back button.
+ * @return the icon for the Back button.
+ */
+ Icon getBackButtonIcon() {
+ return (Icon)buttonIconHashmap.get(BACK_BUTTON_ICON_PROPERTY);
+ }
+
+ /**
+ * Sets the icon for the Back button.
+ * @param newIcon The new icon to set.
+ */
+ void setBackButtonIcon(Icon newIcon) {
+
+ Object oldIcon = getBackButtonIcon();
+ if (!newIcon.equals(oldIcon)) {
+ buttonIconHashmap.put(BACK_BUTTON_ICON_PROPERTY, newIcon);
+ firePropertyChange(BACK_BUTTON_ICON_PROPERTY, oldIcon, newIcon);
+ }
+ }
+
+ /**
+ * Returns the icon for the Next/Finish button.
+ * @return the icon for the Next/Finish button.
+ */
+ Icon getNextFinishButtonIcon() {
+ return (Icon)buttonIconHashmap.get(NEXT_FINISH_BUTTON_ICON_PROPERTY);
+ }
+
+ /**
+ * Sets the icon for the Next/Finish button.
+ * @param newIcon The new icon to set.
+ */
+ public void setNextFinishButtonIcon(Icon newIcon) {
+
+ Object oldIcon = getNextFinishButtonIcon();
+ if (!newIcon.equals(oldIcon)) {
+ buttonIconHashmap.put(NEXT_FINISH_BUTTON_ICON_PROPERTY, newIcon);
+ firePropertyChange(NEXT_FINISH_BUTTON_ICON_PROPERTY,
+ oldIcon, newIcon);
+ }
+ }
+
+ /**
+ * Returns the icon for the Cancel button.
+ * @return the icon for the Cancel button.
+ */
+ Icon getCancelButtonIcon() {
+ return (Icon)buttonIconHashmap.get(CANCEL_BUTTON_ICON_PROPERTY);
+ }
+
+ /**
+ * Sets the icon for the Cancel button.
+ * @param newIcon The new icon to set.
+ */
+ void setCancelButtonIcon(Icon newIcon) {
+ Icon oldIcon = getCancelButtonIcon();
+ if (!newIcon.equals(oldIcon)) {
+ buttonIconHashmap.put(CANCEL_BUTTON_ICON_PROPERTY, newIcon);
+ firePropertyChange(CANCEL_BUTTON_ICON_PROPERTY, oldIcon, newIcon);
+ }
+ }
+
+ /**
+ * Checks if the Back button is enabled.
+ * @return true if the Back button is enabled,
+ * false otherwise.
+ */
+ Boolean getBackButtonEnabled() {
+ return (Boolean)buttonEnabledHashmap.get(
+ BACK_BUTTON_ENABLED_PROPERTY);
+ }
+
+ /**
+ * Enables or disables the Back button.
+ * @param newValue true to enable the Back button,
+ * false to disable it.
+ */
+ void setBackButtonEnabled(Boolean newValue) {
+
+ Boolean oldValue = getBackButtonEnabled();
+ if (newValue != oldValue) {
+ buttonEnabledHashmap.put(BACK_BUTTON_ENABLED_PROPERTY, newValue);
+ firePropertyChange(BACK_BUTTON_ENABLED_PROPERTY,
+ oldValue, newValue);
+ }
+ }
+
+ /**
+ * Checks if the Next/Finish button is enabled.
+ * @return true if the Next/Finish button is enabled,
+ * false otherwise.
+ */
+ Boolean getNextFinishButtonEnabled() {
+ return (Boolean)buttonEnabledHashmap.get(
+ NEXT_FINISH_BUTTON_ENABLED_PROPERTY);
+ }
+
+ /**
+ * Enables or disables the Next/Finish button.
+ * @param newValue true to enable the Next/Finish button,
+ * false to disable it.
+ */
+ void setNextFinishButtonEnabled(Boolean newValue) {
+
+ Boolean oldValue = getNextFinishButtonEnabled();
+ if (newValue != oldValue) {
+ buttonEnabledHashmap.put(
+ NEXT_FINISH_BUTTON_ENABLED_PROPERTY, newValue);
+ firePropertyChange(NEXT_FINISH_BUTTON_ENABLED_PROPERTY,
+ oldValue, newValue);
+ }
+ }
+
+ /**
+ * Checks if the Cancel button is enabled.
+ * @return true if the Cancel button is enabled,
+ * false otherwise.
+ */
+ Boolean getCancelButtonEnabled() {
+ return (Boolean)buttonEnabledHashmap.get(
+ CANCEL_BUTTON_ENABLED_PROPERTY);
+ }
+
+ /**
+ * Enables or disables the Cancel button.
+ * @param newValue true to enable the Cancel button,
+ * false to disable it.
+ */
+ void setCancelButtonEnabled(Boolean newValue) {
+
+ Boolean oldValue = getCancelButtonEnabled();
+ if (newValue != oldValue) {
+ buttonEnabledHashmap.put(CANCEL_BUTTON_ENABLED_PROPERTY, newValue);
+ firePropertyChange(CANCEL_BUTTON_ENABLED_PROPERTY,
+ oldValue, newValue);
+ }
+ }
+
+ /**
+ * Adds a PropertyChangeListener
+ * @param p The PropertyChangeListener to add.
+ */
+ public void addPropertyChangeListener(PropertyChangeListener p) {
+ propertyChangeSupport.addPropertyChangeListener(p);
+ }
+
+ /**
+ * Removes a PropertyChangeListener
+ * @param p The PropertyChangeListener to remove.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener p) {
+ propertyChangeSupport.removePropertyChangeListener(p);
+ }
+
+ /**
+ * Informs allPropertyChangeListeners that the a given property
+ * has changed.
+ * @param propertyName The name of the property.
+ * @param oldValue The old property value.
+ * @param newValue The new property value.
+ */
+ protected void firePropertyChange(String propertyName,
+ Object oldValue, Object newValue) {
+ propertyChangeSupport.firePropertyChange(propertyName,
+ oldValue, newValue);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardPanelNotFoundException.java b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardPanelNotFoundException.java
new file mode 100644
index 000000000..217f61a76
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/customcontrols/wizard/WizardPanelNotFoundException.java
@@ -0,0 +1,21 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package net.java.sip.communicator.impl.gui.customcontrols.wizard;
+
+/**
+ * A RuntimeException, which is thrown if the wizard doesn't find
+ * the panel corresponding to a given WizardPanelDescriptor.
+ *
+ * @author Yana Stamcheva
+ */
+public class WizardPanelNotFoundException extends RuntimeException {
+
+ public WizardPanelNotFoundException() {
+ super();
+ }
+}
\ No newline at end of file