Announcement Announcement Module
Collapse
No announcement yet.
How to create a wizard? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to create a wizard?

    Hello.

    Could You give me some hints what is the easiest way to create a startup wizard for my application?

    In my app I am using several XML files for which I need to set up paths properly. So, I have created class ApplicationFilesPaths which holds static String fields with paths.

    Now, I have also created a dialog which helps to set them:

    Code:
    public class EditPathsDialog extends TitledApplicationDialog implements
    		ActionListener
    I would like to embed this dialog into some kind of wizard which I will execute during startup. The thing is really would like to use EditPathsDialog since it has been already created and tested.

    How can I do that?

    I've figured already that I can extend SetupWizard class and then call execute() method from within my lifecycle advisor, but I have no idea how can I embed my dialog inside that wizard.

    P.S. My EditPathsDialog has a contentPane field of type JPanel with all the GUI components inside and user actions are handled by ActionListener API.

    Thanks in advance.

  • #2
    Wizards work through the use of pages.

    You'll need to convert your JDialog to a wizard page ( ... extends AbstractWizardPage) and create a wizard and add that page (Wizard#addPage(...)).

    If you want to show your wizard in a dialog, you can use WizardDialog.

    Greetz,

    Lieven

    Comment


    • #3
      Originally posted by LievenDoclo View Post
      Wizards work through the use of pages.
      You'll need to convert your JDialog to a wizard page ( ... extends AbstractWizardPage) and create a wizard and add that page (Wizard#addPage(...)).
      ...
      Alright, so I did as follows:
      1. Created a class for my wizard (extending SetupWizard)
      2. Modified my Dialog (extracted content pane to separate Class file)
      3. Created a page class (extending AbstractWizardPage) and using content pane from my dialog
      4. Used both in following matter:
      Code:
      public class Wizard extends SetupWizard {
      	public Wizard() {
      		setLicenseTextLocation(new FileSystemResource(
      				"absolute_path"));
      		addPages();
      		addPage(new WizardEditPaths("editPathsWizard"));
      		
      	}
      }
      Works fine, but I have some other questions :-)

      1. How can I force my wizard to disable "next" button after reaching the last page? Cause right now I can roll over three pages (welcome, license, edit paths) till infinity and this is not what I was looking for ;-)
      2. How can I force my wizard to enable "Finish" button AFTER setting my paths properly and NOT after accepting the license?

      Thanks for help. It occured to me that I was going in the right direction from the beginning, but Your help was priceless!

      Best regards.

      Comment


      • #4
        Well, WizardPage has a canFlipToNextPage method, when it's false, the next button is disabled.

        As for the finish button, Wizard has a canFinish method, you'll need to work something out so that method only returns true when the paths are set properly.

        By the way, are you using WizardDialog to show your wizard? This class handles a lot of the above behaviour. If you're showing the wizard inside your own dialog, you'll need to handle that behaviour.

        Hope this helps.

        Best regards,

        Lieven

        Comment


        • #5
          By the way, you can always provide an exit page, which is the only page where finish is allowed (a sort of 'Thank you, please enjoy' page).

          I included a small example, there are still bugs in it, but you'll get the picture:

          Code:
          import org.springframework.binding.validation.ValidationListener;
          import org.springframework.binding.validation.ValidationResults;
          import org.springframework.binding.validation.support.RulesValidator;
          import org.springframework.core.io.AbstractResource;
          import org.springframework.richclient.application.setup.SetupWizard;
          import org.springframework.richclient.command.ActionCommandExecutor;
          import org.springframework.richclient.form.AbstractForm;
          import org.springframework.richclient.form.FormModelHelper;
          import org.springframework.richclient.form.builder.TableFormBuilder;
          import org.springframework.richclient.wizard.AbstractWizardPage;
          import org.springframework.richclient.wizard.FormBackedWizardPage;
          import org.springframework.richclient.wizard.WizardDialog;
          import org.springframework.richclient.dialog.DialogPage;
          import org.springframework.rules.Rules;
          import org.springframework.rules.factory.Constraints;
          import org.springframework.rules.support.DefaultRulesSource;
          
          import javax.swing.*;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.StringBufferInputStream;
          import java.beans.PropertyChangeEvent;
          
          public class MySetupWizard extends SetupWizard implements ActionCommandExecutor
          {
          
              private ExtraPage extraPage;
              private LastPage lastPage;
          
              private WizardDialog dialog;
          
              public MySetupWizard()
              {
                  extraPage = new ExtraPage(this);
                  lastPage = new LastPage();
                  addPages();
                  setLicenseTextLocation(new LicenseResource());
                  addPage(extraPage);
                  addPage(lastPage);
              }
          
              public boolean canFinish()
              {
                  return dialog.getCurrentPage().getId().equals("lastPage");
              }
          
              public void execute()
              {
                  if (dialog == null)
                  {
                      dialog = new WizardDialog(this);
                  }
                  dialog.showDialog();
              }
          
              public WizardDialog getDialog()
              {
                  return dialog;
              }
          
              class LicenseResource extends AbstractResource
              {
          
                  public String getDescription()
                  {
                      return "license";
                  }
          
                  public InputStream getInputStream() throws IOException
                  {
                      return new StringBufferInputStream("some license text");
                  }
              }
          
              class ExtraPage extends FormBackedWizardPage
              {
                  private boolean ready;
          
                  public ExtraPage(final MySetupWizard wizard)
                  {
                      super(new ExtraForm());
                      getBackingForm().addValidationListener(new ValidationListener()
                      {
                          public void validationResultsChanged(ValidationResults results)
                          {
                              boolean oldReady = ready;
                              ready = !results.getHasErrors();
                              try {
                                  wizard.getDialog().propertyChange(new PropertyChangeEvent(this, DialogPage.PAGE_COMPLETE_PROPERTY, oldReady, ready));
                              } catch(NullPointerException ex)
                              {
                                  // could happen, ignore
                              }
                          }
                      });
                  }
          
                  public void setReady(boolean ready)
                  {
                      this.ready = ready;
                  }
          
                  public boolean isPageComplete()
                  {
                      return ready;
                  }
              }
          
              class LastPage extends AbstractWizardPage
              {
                  protected LastPage()
                  {
                      super("lastPage");
                  }
          
                  protected JComponent createControl()
                  {
                      return new JLabel("Congratulations, enjoy the product!");
                  }
          
                  public boolean canFlipToNextPage()
                  {
                      return false;
                  }
              }
          
              class ExtraForm extends AbstractForm
              {
          
                  public ExtraForm()
                  {
                      super(FormModelHelper.createFormModel(new ExtraObject(), "extraForm"));
                      DefaultRulesSource source = new DefaultRulesSource();
                      Rules rules = new Rules(ExtraObject.class);
                      Constraints c = new Constraints();
                      rules.add("configOne", c.required());
                      rules.add("configTwo", c.required());
                      source.addRules(rules);
                      getFormModel().setValidator(new RulesValidator(getFormModel(), source));
                  }
          
                  protected JComponent createFormControl()
                  {
                      TableFormBuilder builder = new TableFormBuilder(getBindingFactory());
                      builder.add("configOne");
                      builder.add("configTwo");
                      return builder.getForm();
                  }
              }
          
              class ExtraObject
              {
                  private String configOne;
                  private String configTwo;
          
                  public String getConfigOne()
                  {
                      return configOne;
                  }
          
                  public void setConfigOne(String configOne)
                  {
                      this.configOne = configOne;
                  }
          
                  public String getConfigTwo()
                  {
                      return configTwo;
                  }
          
                  public void setConfigTwo(String configTwo)
                  {
                      this.configTwo = configTwo;
                  }
              }
          }
          Just do

          Code:
          new MySetupDialog().execute();
          to show the dialog.

          Greetingz,

          Lieven

          Comment


          • #6
            Arghgghhhh, so mad at myself. Forgot about overriding methods while searching for sulution. Gues I have to study the foundamentals of Java once more.

            So I have figured out (actually - You did ;-) the way how to disable the buttons, but now I have some more problems. After setting my paths properly I need to force Wizard to reevaluate wheter if it is possible to finish (and thus - enabling button) or not. How can I do that? I cannot find any methods which could do the trick.
            If I click "Back" then I can see "Finish" button enabled but I would like to do that exactly the same as it is done with License Agreement - when user chooses proper paths the Finish button is enabled.

            Is there official JavaDoc documentation for SRCP?

            Thanks for Your time. I appreciate it.


            LievenDoclo: Simple and briliant ;-) I gues I will do that even if I find solution to my previous problem, but I would like to solve it anyhow, cause this way I can learn something.

            Comment


            • #7
              Well, actually, if you look at my example, it does just that. The form with the extra data is invalid, and through a validationlistener I enabled/disable the next button to end up in the 'finish' page.

              Comment


              • #8
                You are right - this example satisfies my needs in terms of wizard capabilities. Cheers for that! I can strongly recommend it for anyone who is newbie (as me ) in SRCP.

                One more question regarding creating "extraForm". I can understand how it works, but my goal was to allow user to input choose proper files via JFileChooser. So, how can I add few buttons and handle events fired by those? I was looking for methods creating buttons in TableFormBuilder but couldn't find any, and when I try adding them via builder.add(String, JComponent) I get runtime errors cause I didn't specify any getter for field which name is being held in "String" parameter. I don't know how to make this work.

                Thanks for help and for Your patiance ;-)

                Comment


                • #9
                  Ok, forms 101 .

                  You'll need to create an object which represents the data. In your case that'll probably be an object with some String or File fields.

                  What you can do then is create some sort of a filechooser binding. The binding is bound to a String/File (you'll have to choose) field and consists of a JTextField and a button which calls a JFileChooser to set the value of the JTextField.

                  That way you can reuse the binding any time you need to choose a file to set a property.

                  Comment


                  • #10
                    Could You provide me with some sample code, cause I cannot handle doing this myself?

                    -----------------

                    Found this post:
                    http://forum.springframework.org/sho...t=JFileChooser
                    I'll try to work on it more.
                    Last edited by bat; May 29th, 2008, 04:44 PM.

                    Comment


                    • #11
                      What do you mean, writing that binder? I'll see if I can whip up something, don't know when I'll be able to post it tho, quite hectic these days...

                      What do you want, a general tutorial on writing binders or a specific sample on how to write that filechooserbinder?

                      Comment


                      • #12
                        Well, to be honest with You I am not very familiar with binding in general, so a tutorial would be perfect. I can understand thath binding helps me to bind some class' property with a GUI component, but I do not know anything more than that. I guess lack of docs is the main problem in my case :/

                        Comment


                        • #13
                          Originally posted by bat View Post
                          Well, to be honest with You I am not very familiar with binding in general, so a tutorial would be perfect. I can understand thath binding helps me to bind some class' property with a GUI component, but I do not know anything more than that. I guess lack of docs is the main problem in my case :/
                          Ok, if I find some time this weekend, I'll try to make a little tutorial on how to create binders and bindings. Then we'll see to get it added to the documentation . But as the lead already stated: documentation is given on a need-to-have basis for RCP, so since you need it, we'll provide it

                          Greetings,

                          Lieven

                          Comment


                          • #14
                            Woooow, that's great! I would really apreciate it. For me (and for many other, I believe) reading some specs before analyzing sample code is much more efficient. Thanks in advance!

                            Cheers.

                            Comment


                            • #15
                              Haven't found the time this weekend, but just finished it this morning, I'll probably post it on my website. I'll post here when it's done.

                              Comment

                              Working...
                              X