Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News

SYS-CON.TV
Cloud Expo & Virtualization 2009 East
PLATINUM SPONSORS:
IBM
Smarter Business Solutions Through Dynamic Infrastructure
IBM
Smarter Insights: How the CIO Becomes a Hero Again
Microsoft
Windows Azure
GOLD SPONSORS:
Appsense
Why VDI?
CA
Maximizing the Business Value of Virtualization in Enterprise and Cloud Computing Environments
ExactTarget
Messaging in the Cloud - Email, SMS and Voice
Freedom OSS
Stairway to the Cloud
Sun
Sun's Incubation Platform: Helping Startups Serve the Enterprise
POWER PANELS:
Cloud Computing & Enterprise IT: Cost & Operational Benefits
How and Why is a Flexible IT Infrastructure the Key To the Future?
Click For 2008 West
Event Webcasts
Java Wizard Class
Java Wizard Class

As it turns out, designing and implementing this wizard framework exposes many of the real-world design and programming issues we face when creating Java applications.

Overview
The first step in designing our wizard class is to come up with an interface. An interface is a prototype for a class in which we describe the class' functionality without getting into implementation details. When designing an interface, think about how someone would use the class and jot down some pseudo-code. Translate these ideas into member functions to create the interface. One thing to remember is that the initial pass at an interface will rarely be the last. You will probably end up modifying and improving the interface several times during the course of development.

Since there are several different ways we could go about designing our wizard interface and corresponding implementation class, we need to decide what features are important to us. For instance, what types of containers do we want our wizard to be capable of displaying? What events do we want our wizard to support? Do we want to support multicasting of events, and, if so, how? Do we want to have random access to our wizard pages or is sequential access sufficient? What do we want our wizard buttons to look like?

There are three main elements to a wizard.

  • First, there are the navigation buttons (next, previous, cancel, etc.).
  • Second, there are the information and controls presented by the wizard, which I refer to as "pages."
  • Finally, there is the dialog, typically modal, that contains the active page and the navigation buttons.

    The Layout
    We now need to think about how the wizard dialog should be laid out. Because the wizard navigation buttons are independent of the content pages, we want to create two distinct areas within the dialog. The first area, which will occupy the upper region of the dialog, will consist of the information that changes between each wizard page. The second area, which will occupy the lower region of the dialog, will contain the wizard navigation buttons. This is where Java's layout manager classes will come in handy.

    Messaging
    The next issue we need to deal with is messaging. We need to provide a mechanism in our wizard class to notify the outside world of events. To do this we will need to create our own event and listener classes so that the appropriate event occurs when one of our navigation buttons is clicked.

    If you are experienced in using the AWT, you are probably familiar with event listeners and event adapters. For instance, Java provides a class called WindowAdapter to accept events that occur on a window. The class is provided mainly for convenience reasons, providing empty methods for all the various window events. To actually do something, you must extend the WindowAdapter class and tell the window about it by calling the AddWindowListener function.

    We are going to use a similar structure in our wizard framework. Our wizard class will allow a user to set a particular WizardAdapter to have the wizard messages sent to. We are going to design our wizard so that there can be only one WizardAdapter active at any given time. Note, however, that this does not prevent us from multicasting the events, if desired, since you can add that functionality to the WizardAdapter class. Why not allow multiple listeners to be registered with the wizard class as they can in Java's Window class? Consider the events that our wizard class is producing. In response to these events (next, previous, finish, etc.) we might validate some of the fields in the current page, then tell the wizard class to display the next page or the previous page, or to close the dialog. Can you see some of the potential problems if these events were to be processed by independent listeners? What if the first listener told the wizard to advance to the next page, while the next listener, not knowing about the first, did the same thing? In this case you would get the unintended result of advancing two pages whenever the next button was clicked.

    By limiting the wizard class to one WizardAdapter, we require a central point of control by the user of the wizard class. This is important because it is the user of the class, not the wizard class itself, that knows how the wizard should be used. If users want events to be multicast, they can implement that multicasting inside their WizardAdapter, simply forwarding on the wizard events to all interested parties. The lesson here is to provide functionality appropriate for the object being modeled. Don't add capabilities just because you think they're cool.

    Example Classes
    To show how you use the wizard class, I created a sample vacation wizard. This wizard is relatively simple, yet illustrates most of the features of the wizard class, as well as some interesting "gotchas."To effectively use the wizard class, several application-specific support classes are created, as shown in Figure 1. An application-specific version of the WizardAdapter class (VacationWizardAdapter) is created to handle messaging, while a class called VacationWizard is used to create the wizard content pages and control the interactions between wizard pages. The VacationWizard class knows about both the wizard class and the VacationWizardAdapter class. The VacationWizardAdapter takes a VacationWizard instance in its constructor so that it knows whom to send messages to. The three classes used together provide a flexible and extensible mechanism for handling wizards.

    The Details
    Let us begin by taking a closer look at the interface definition for the wizard class (see Listing 1). From this interface definition we can see that in addition to the basic wizard navigation support, we also want our wizard to be able to support advanced features such as hidden panels, keyboard navigation, help button and messaging.

    In implementing our wizard class, one of the first issues we must confront is what existing Java class we want to extend. As I mentioned in the overview, a modal dialog is typically used as the container for the various wizard elements. To get some exposure to some of the new JFC classes, we will extend the JFC class Jdialog.

    public class Wizard extends com.sun.java.swing.JDialog implements WizardControllerInterface

    Notice that this declaration says we are going to implement the WizardInterface that we listed earlier. Therefore, our class definition must define all the member functions we defined in our WizardInterface.

    The Layout
    As I alluded earlier, Java's layout classes come in handy when implementing our Wizard class. Using a GridBagLayout, we can lay out the wizard dialog's contents as shown in Figure 2. The uppermost area is itself a Jpanel that uses its own layout manager, CardLayout, to manage the wizard pages. I won't go into the details of laying out controls using the GridBagLayout here, but look at the source code if you are interested.

    Messaging
    How do we go about handling the messaging? First, we need to create a new event type called a WizardEvent by extending Java's EventObject class (see Listing 2). We will then need to create a WizardListener class by extending the Java's EventListener class. Our WizardListener class will handle the events shown in Listing 3.

    Inside our wizard class we need to create ActionListeners for each of our wizard navigation buttons, such as:

    previous_.addActionListener(new PreviousButtonListener());

    Our listener classes simply fire off an appropriate event when one of our navigation buttons is clicked. Listing 4 shows how one of these functions, PreviousButtonListener, is implemented.

    In addition, we need to add KeyListeners for each of our wizard navigation buttons since we want to support keyboard control of our navigation buttons using the Enter Key.

    next_.addKeyListener(new NextEnterKeyListener());

    All we are doing here is checking to see if the Enter Key is pressed while the focus is on one of our navigation buttons. If it is, we fire off the appropriate event. Listing 5 shows how the NextEnterKeyListener is implemented.

    Page Navigation
    How do we accomplish the task of moving between pages in the wizard class? As mentioned earlier, the Java Layout Manager called CardLayout is used to switch between wizard pages. The CardLayout is ideal for use with wizards because it allows easy access to all the pages in the layout either sequentially or randomly via a name. (See the complete listing for details.)

    The wizard class offers the ability to hide certain pages of the wizard if desired. As we will see in our example, many times we might want to create a wizard that shows certain pages conditionally. This is accomplished by using the wizard functions hidePanel and unHidePanel. PanelAttribute class is used inside the wizard class to maintain state about each page of the wizard. If a page is marked as hidden, that page is bypassed by the forward and next logic of the wizard. (See the complete listing for details.)

    Miscellaneous
    Our wizard class also has the ability to display messages. The user of the wizard class might want to display a message stating that all the required fields of the wizard have not been filled in. A user might also want to display a specific field validation message, such as "value must be between 10 and 50." The wizard class handles these situations using a specific function called displayRequiredFieldMessage, as well as provides a generic error message function called displayErrorMessage that takes a title and a message string.

    An Example
    To create an actual wizard of your own, you need to decide on the content and order of the wizard pages. Once you have figured that out, you need to decide what container you will use for the wizard pages. Our wizard class allows you to use any class derived from the AWT's Component class. For the sample wizard I used a variety of components such as the AWT's Panel and ScrollPanel class, as well as the new JFC's Jpanel class.

    Once you have your wizard pages designed, you need to deal with any required interactions between the various controls on the same page as well as the interactions between pages. For instance, in the VacationWizard example, the second page of the wizard is displayed only if Hawaii has been selected as the destination. Therefore, we need to be able to conditionally hide/unhide this wizard page based on the value of the radio buttons on the first wizard page.

    To check the values of various controls at the appropriate time, messages need to be sent when a wizard page is activated and deactivated. This is the job of our VacationWizardAdapter. Since the VacationWizardAdapter is the class that is getting the messages (previous, next, finish, etc.) from the Wizard Class, it is responsible for calling the initializePage and finalizePage functions of the VacationWizard class, passing the current wizard page as a parameter. The finalizePage function can veto moving to the next page by returning false. This is a handy mechanism for validating fields and preventing the wizard from moving forward until all the appropriate fields and values are filled in.The code in the VacationWizard class deals mostly with creating the content pages for the wizard. However, there is one interesting thing to look at. While creating and testing the wizard pages, I discovered some undesired behavior with the AWT's TextArea class. I wanted to use a non-editable TextArea to display some explanatory text at the top of each wizard page (see Figure 3). At first glance everything looked okay. However, when I used the tab key to tab around the dialog, I noticed that once the TextArea received the focus, it did not want to give it back. Although I'm sure the TextArea was happy, the rest of my controls were feeling left out.

    I imagine this behavior stems from the fact that in a standard editable text area, the tab key really means to put in a tab character. Fortunately, you can get around this problem by deriving a new class from TextArea. I called my new class UnfocusedTextArea (see Listing 6). After searching the documentation, I found a handy function in the AWT's Component class, from which TextArea descends, called isFocusTraversable. The key to solving the problem lies in overriding this function in our UnfocusedTextArea class so that it simply returns false. This means that the text area will never actually get the focus -- which is exactly what we want to happen in this case.

    Conclusion
    There are many different ways to design a wizard class and its supporting classes. I have presented one way that provides a flexible and extensible framework for creating real-world wizards. One thing to keep in mind when building applications of your own is that most real-world problems require more than one class to model. In most cases it is best to solve problems with mini-frameworks that use a general-purpose class or classes (like the Wizard class) combined with one or more specializing classes (like the VacationWizard and VacationWizardAdapter classes).

    About Donald Fowler
    Donald Fowler works as a software design
    developer at Rogue Wave Software where he is currently the technical lead for the Software Parts Manager product line. He has 15 years of software design and development experience specializing
    in GUI programming and 7 years' experience in object-oriented design and programming.

  • In order to post a comment you need to be registered and logged in.

    Register | Sign-in

    Reader Feedback: Page 1 of 1

    These Wizard classes are just what I am looking for. I wish that the VacationWizard example classes were included in the source listings.

    Thanks


    Your Feedback
    Milt Demaray wrote: These Wizard classes are just what I am looking for. I wish that the VacationWizard example classes were included in the source listings. Thanks
    Latest Cloud Developer Stories
    Swisscom, the Swiss telecom, is going into the cloud business. Its subsidiary Swisscom IT Services AG has signed up with Red Hat as a Certified Cloud Provider and launched a public cloud Infrastructure-as-a-Service (IaaS) cloud targeting enterprise-class customers primarily in ...
    Apache Deltacloud, the Red Hat-contributed ReSTful API that abstracts differences between clouds so services on any cloud can be managed – provided of course there’s a driver – has graduated from the Apache Foundation’s incubator and is now a full-fledged Top-Level Project (TLP)....
    In a surprise move on Tuesday, January 10, Oracle wheeled out its Big Data Appliance. That’s the one it said in October would be ready sometime in the first half. Only nobody believed it meant early in the first half. Heck, it’s not even clear anybody thought Oracle could make ...
    Rackspace Hosting, the service leader in cloud computing, on Thursday announced its acquisition of SharePoint911, an industry leader in SharePoint consulting, training, and "JumpStart" services within SharePoint. The unification of both companies provides capabilities to deliver ...
    CloudLinux, Inc., on Thursday released CafeFS 3, a virtualized file system for shared hosters that cages each customer within its own virtualized file system. CageFS becomes part of CloudLinux OS at no additional charge. CloudLinux OS, the only commercially-supported Linux OS m...
    Subscribe to the World's Most Powerful Newsletters
    Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
    Click to Add our RSS Feeds to the Service of Your Choice:
    Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
    myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
    Publish Your Article! Please send it to editorial(at)sys-con.com!

    Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

    SYS-CON Featured Whitepapers
    ADS BY GOOGLE

    Breaking Cloud Computing News

    BEACHWOOD, Ohio, Feb. 16, 2012 /PRNewswire/ -- DDR Corp. (NYSE: DDR) today announced operating re...