Sunday Apr 06, 2008

Disabling/Enabling a Wizard Panel's Finish Button

Let's take the wizard panel from a few days ago and disable the "Finish" button until both the new fields are filled in:

  1. Change the visual panel's signature so that it implements DocumentListener. Then, in the constructor, add a DocumentListener to both of your new fields:

    extField.getDocument().addDocumentListener(this);
    impField.getDocument().addDocumentListener(this);

    Next, implement the DocumentListener's methods like this:

    @Override
    public void changedUpdate(DocumentEvent e) {
        panel.fireChangeEvent();
        updateUI(e);
    }
    
    @Override
    public void insertUpdate(DocumentEvent e) {
        panel.fireChangeEvent();
        updateUI(e);
    }
    
    @Override
    public void removeUpdate(DocumentEvent e) {
        panel.fireChangeEvent();
        updateUI(e);
    }
    
    public void updateUI(DocumentEvent e) {
        if (this.extField.getDocument() == e.getDocument()) {
            firePropertyChange(EXTENSION, null, this.extField.getText());
        }
        if (this.impField.getDocument() == e.getDocument()) {
            firePropertyChange(IMPLEMENTATION, null, this.impField.getText());
        }
    }

  2. In the non-visual wizard panel, add the code that receives the change event and enables/disables the "Finish" button:

    private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1);
    
    @Override
    public final void addChangeListener(ChangeListener l) {
        synchronized (listeners) {
            listeners.add(l);
        }
    }
    
    @Override
    public final void removeChangeListener(ChangeListener l) {
        synchronized (listeners) {
            listeners.remove(l);
        }
    }
    
    protected final void fireChangeEvent() {
        Set ls;
        synchronized (listeners) {
            ls = new HashSet(listeners);
        }
        ChangeEvent ev = new ChangeEvent(this);
        for (ChangeListener l : ls) {
            l.stateChanged(ev);
        }
    }
    
    @Override
    public boolean isValid() {
        if (getExtensionFromVisualPanel().length() == 0 || 
                getImplementationFromVisualPanel().length() == 0) {
            return false;
        }
        return true;
    }

  3. Finally, make sure the two classes are correctly hooked up together. In the wizard panel, pass the current class to the visual panel:

    @Override
    public Component getComponent() {
        if (component == null) {
            component = new FancyVisualPanel1(this);
        }
        return component;
    }

    In the visual panel, receive the wizard panel in the constructor:

    private FancyWizardPanel1 panel;
    
    public FancyVisualPanel1(FancyWizardPanel1 panel) {
        initComponents();
        this.panel = panel;
        extField.getDocument().addDocumentListener(this);
        impField.getDocument().addDocumentListener(this);
    }

That's it. Now, if both fields aren't filled in, the "Finish" button is disabled. You can also display some kind of informative message so that the user knows what they should do to enable the "Finish" button. In real life, you probably don't want to force the user to fill in an extension class and an implementation class, because possibly they want to have a signature that doesn't include superclasses and/or interfaces. So you'd probably add a checkbox that enables/disables the two fields, depending on whether the user wants to fill them in or not.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2008 »
SunMonTueWedThuFriSat
  
2
4
5
13
18
19
23
30
   
       
Today