alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.core.ui;

import java.util.*;
import java.awt.Component;
import java.beans.*;
import javax.swing.event.*;
import javax.swing.JComponent;

import org.openide.WizardDescriptor;
import org.openide.cookies.InstanceCookie;
import org.openide.loaders.DataFolder;
import org.openide.util.HelpCtx;
import org.openide.util.Task;

/**
 * This class allows you to create the steps of the wizard
 * by providing a folder with .instance files. The wizard
 * will ask dataobjects in the folder for InstanceCookie.
 * If this will be an instance of JPanel or
 * org.openide.WizardDescriptor.Iterator, it will be
 * used as a step of the wizard.
 * @author  dstrupl
 */
public class WizardFolder extends org.openide.loaders.FolderInstance {

    /** See org.openide.WizardDescriptor.PROP_CONTENT_SELECTED_INDEX
     */
    private static final String PROP_CONTENT_SELECTED_INDEX = "WizardPanel_contentSelectedIndex"; // NOI18N
    /** See org.openide.WizardDescriptor.PROP_CONTENT_DATA
     */
    private static final String PROP_CONTENT_DATA = "WizardPanel_contentData"; // NOI18N

    /**
     * Currently active iterator.
     */
    private WizardDescriptor.Iterator iterator;
 
    /** Creates new WizardFolder */
    public WizardFolder(DataFolder theFolder) {
        super(theFolder);
        run();
    }

    /** @return currently active iterator */
    public WizardDescriptor.Iterator getIterator() {
        return iterator;
    }
    
    /**
     * Returns the same cookie if the instance class is
     * java.awt.Component, WizardDescriptor.Iterator or
     * WizardDescriptor.Panel.
     * @param cookie the instance cookie to test
     * @return the cookie to use or null if this cookie should not
     *   be used
     * @exception IOException if an I/O error occurred calling a cookie method
     * @exception ClassNotFoundException if a class is not found in a call to a cookie method
     */
    protected InstanceCookie acceptCookie(InstanceCookie cookie) throws java.io.IOException, ClassNotFoundException {
        if (java.awt.Component.class.isAssignableFrom(cookie.instanceClass())) {
            return cookie;
        }
        if (org.openide.WizardDescriptor.Iterator.class.isAssignableFrom(cookie.instanceClass())) {
            return cookie;
        }
        if (org.openide.WizardDescriptor.Panel.class.isAssignableFrom(cookie.instanceClass())) {
            return cookie;
        }
        return null;
    }
    
    /** Notifies subclasses that the set of cookies for this folder
     * has changed.
     * A new object representing the folder should
     * be created (or the old one updated).
     * Called both upon initialization of the class, and change of its cookies.
     *
     * @param cookies updated array of instance cookies for the folder
     * @return object to represent these cookies
     *
     * @exception IOException an I/O error occured
     * @exception ClassNotFoundException a class has not been found
     */
    protected Object createInstance(InstanceCookie[] cookies) throws java.io.IOException, ClassNotFoundException {
        WizardDescriptor.Iterator []arr = new WizardDescriptor.Iterator[cookies.length];
        for (int i = 0; i < cookies.length; i++) {
            if (org.openide.WizardDescriptor.Iterator.class.isAssignableFrom(cookies[i].instanceClass())) {
                arr[i] = (WizardDescriptor.Iterator) cookies[i].instanceCreate();
                continue;
            }
            if (org.openide.WizardDescriptor.Panel.class.isAssignableFrom(cookies[i].instanceClass())) {
                WizardDescriptor.Panel p = (WizardDescriptor.Panel) cookies[i].instanceCreate();
                arr[i] = new PanelWrapper(p, cookies[i].instanceName());
                continue;
            }
            if (java.awt.Component.class.isAssignableFrom(cookies[i].instanceClass())) {
                java.awt.Component c = (java.awt.Component) cookies[i].instanceCreate();
//                c.setName(cookies[i].instanceName());
                arr[i] = new PanelWrapper(c, cookies[i].instanceName());
                continue;
            }
        }
        if (arr.length > 0) {
            iterator = new CompoundIterator(arr);
        }
        return this; // where is this used anyway? (dstrupl)
    }

    /** Ovverrides task creation policy to run tasks always in AWT thread, as
     * wizards usually work with swing
     */
    protected Task postCreationTask (Runnable run) {
        return new AWTTask(run);
    }
    
    /** A special task designed to run in AWT thread.
     * It will fire itself immediatelly.
     * Copied from openide.awt.AWTTask
     */
    private static class AWTTask extends org.openide.util.Task {
        private boolean executed;

        public AWTTask (Runnable r) {
            super (r);
            org.openide.util.Mutex.EVENT.readAccess (this);
        }

        public void run () {
            if (!executed) {
                super.run ();
                executed = true;
            }
        }

        public void waitFinished () {
            if (javax.swing.SwingUtilities.isEventDispatchThread ()) {
                run ();
            } else {
                super.waitFinished ();
            }
        }
    }

    /** 
     * This iterator delegates to the iterators given in constructor.
     */ 
    protected static class CompoundIterator implements org.openide.WizardDescriptor.Iterator,
                                                     PropertyChangeListener {
        
        /** Iterators we to which we delegate. */
        private WizardDescriptor.Iterator [] array;
        
        /** 
         * Currently active itaratori index. The index is for array variable,
         * so the values are between 0 ... array.length-1
         */
        private int active = 0;
        
        /** Registered change listener. */
        private ChangeListener listener = null;
        
        /** Cached list of steps */
        private HashMap contentMap = new HashMap();
        
        /** Listeners on changes of list of content and selected index. */
        private PropertyChangeSupport propertyChangeSupport;
        
        /** It assumes that all elements of the array are non-null. */
        public CompoundIterator(LinkedList iterators) {
            this((WizardDescriptor.Iterator[])iterators.toArray(
                    new WizardDescriptor.Iterator[iterators.size()]));
        }

        /** It assumes that all elements of the array are non-null. */
        public CompoundIterator(WizardDescriptor.Iterator []arr) {
            array = arr;
            propertyChangeSupport = new PropertyChangeSupport(this);
        }
        
        public void setIterators(LinkedList iterators) {
            if (!iterators.contains(array[active]))
                return;
            active = iterators.indexOf(array[active]);
            array = (WizardDescriptor.Iterator[])iterators.toArray(
                        new WizardDescriptor.Iterator[iterators.size()]);
            
            if (listener != null) {
                listener.stateChanged(new ChangeEvent(this));
            }
        }
        
        /** Add a listener to changes of the current panel.
         * The listener is notified when the possibility to move forward/backward changes.
         * @param l the listener to add
         */
        public void addChangeListener(ChangeListener l) {
            listener = l;
            // add the listener also to the delegated iterators
            for (int i = 0; i < array.length; i++) {
                array[i].addChangeListener(l);
            }
        }
        
        /** Get the current panel.
         * @return the panel
         */
        public WizardDescriptor.Panel current() {
            return array[active].current();
            // [PENDING] ??? wrap the panel to disable finishing 
        }
        
        /** Test whether there is a next panel.
         * @return true if so
         */
        public boolean hasNext() {
            if (active != array.length - 1) {
                // it is not the last one
                return true;
            }
            return array[active].hasNext();
        }
        
        /** Test whether there is a previous panel.
         * @return true if so
         */
        public boolean hasPrevious() {
            if (active != 0) {
                // not the first iterator
                return true;
            }
            return array[active].hasPrevious();
        }
        
        /** Get the name of the current panel.
         * @return the name
         */
        public String name() {
            return array[active].name();
        }
        
        /** Move to the next panel.
         * I.e. increment its index, need not actually change any GUI itself.
         * @exception NoSuchElementException if the panel does not exist
         */
        public void nextPanel() {
            stopListening();
            if (array[active].hasNext()) {
                array[active].nextPanel();
                startListening();
                propertyChangeSupport.firePropertyChange( PROP_CONTENT_SELECTED_INDEX, null, null);
                return;
            }
            if (active < array.length-1) {
                active++;
                startListening();
                propertyChangeSupport.firePropertyChange( PROP_CONTENT_SELECTED_INDEX, null, null);
                return;
            }
            throw new NoSuchElementException();
        }
        
        /** Move to the previous panel.
         * I.e. decrement its index, need not actually change any GUI itself.
         * @exception NoSuchElementException if the panel does not exist
         */
        public void previousPanel() {
            stopListening();
            if (array[active].hasPrevious()) {
                array[active].previousPanel();
                startListening();
                propertyChangeSupport.firePropertyChange( PROP_CONTENT_SELECTED_INDEX, null, null);
                return;
            }
            if (active > 0) {
                active--;
                startListening();
                propertyChangeSupport.firePropertyChange( PROP_CONTENT_SELECTED_INDEX, null, null);
                return;
            }
            throw new NoSuchElementException();
        }
        
        /** Remove a listener to changes of the current panel.
         * @param l the listener to remove
         */
        public void removeChangeListener(ChangeListener l) {
            listener = null;
            // remove the listener also from the delegated iterators
            for (int i = 0; i < array.length; i++) {
                array[i].removeChangeListener(l);
            }
        }
        
        //----------------------- Content creation mehtods ----------------------------
        
        /**
         * @return String[] content taken from i-th iterator or null
         */
        private String[] getContentDataAt(int i) {
            String[] cd = null;
            if (array[i] instanceof CompoundIterator) {
                cd = ((CompoundIterator)array[i]).getContentData();
                if (cd == null)
                    cd = (String[])contentMap.get(array[i]);
                if (cd == null)
                    cd = new String[] {};
            } else {
                Component c = array[i].current().getComponent();
                if (c instanceof JComponent) {
                    Object property = ((JComponent)c).getClientProperty(PROP_CONTENT_DATA);
                    if (property instanceof String[])
                        cd = (String[])property;
                }
                if (cd == null)
                    cd = (String[])contentMap.get(array[i]);
                // use name of panel only when there is nothing else to show
                if (cd == null)
                    //cd = new String[] { c.getName() };
                    cd = new String[0];
            }
            contentMap.put(array[i], cd);
            return cd;
        }

        /** Set subiterator at specified position. When position equals to active subiterator
         * then ignores call and returns null.
         * @param position the position of iterator
         * @param it iterator or null for removing iterator at specified position
         * @return Object null when position equals to active iterator
         */
        public Object setIteratorAt(int position, WizardDescriptor.Iterator it) {
            if (position == active)
                return null;
            if (it == null) {
                contentMap.remove(array[position]);
                WizardDescriptor.Iterator[] buf = new WizardDescriptor.Iterator[array.length -1];
                System.arraycopy(array, 0, buf, 0, array.length - 1);
                array = buf;
                return it;
            }
            array[position] = it;
            contentMap.put(it, getContentDataAt(position));
            return it;
        }
        
        /** Adds iterator to the end of list of subiterators.
         * @param it iterator to add
         */
        public void addIterator(WizardDescriptor.Iterator it) {
            if (it != null) {
                WizardDescriptor.Iterator[] buf = new WizardDescriptor.Iterator[array.length + 1];
                System.arraycopy(array, 0, buf, 0, array.length);
                buf[array.length] = it;
                array = buf;
                contentMap.put(it, getContentDataAt(array.length - 1));
            }
        }
        
        /** Remove specified iterator from iterator tree
         * @param it iterator to remove
         * @return true if iterator was removed
         */
        public boolean removeIterator(WizardDescriptor.Iterator it) {
            if (it == null)
                return false;
            for (int i = 0; i < array.length; i++) {
                if ((it == array[i]) && (active != i)) {
                    WizardDescriptor.Iterator[] buf = new WizardDescriptor.Iterator[array.length - 1];
                    System.arraycopy(array, 0, buf, 0, i);
                    System.arraycopy(array, i + 1, buf, i, buf.length - i);
                    array = buf;
                    contentMap.remove(it);
                    return true;
                }
                if (array[i] instanceof CompoundIterator) {
                    boolean ret = ((CompoundIterator)array[i]).removeIterator(it);
                    if (ret)
                        return true;
                }
            }
            return false;
        }
        
        /** Return number of subiterators.
         * @return size of compound iterator
         */
        public int size() {
            return array.length;
        }
        
        /** Returns content of this compound iterator.
         * @return String[] array of content items
         */
        public String[] getContentData() {
            String[] cData = new String[] {};
            for (int i = 0; i < array.length; i++) {
                String[] cd = getContentDataAt(i);
                String[] buf = new String[cData.length + cd.length];
                System.arraycopy(cData, 0, buf, 0, cData.length);
                System.arraycopy(cd, 0, buf, cData.length, cd.length);
                cData = buf;
            }
            return cData;
        }
        
        /** Returns selected item in content
         * @return int selected index of content
         */
        public int getContentSelectedIndex() {
            int seg = 0;
            for (int i = 0; i < active; i++) {
                seg += getContentDataAt(i).length;
            }
            if (array[active] instanceof CompoundIterator)
                return seg + ((CompoundIterator)array[active]).getContentSelectedIndex();
            Component c = array[active].current().getComponent();
            if (c instanceof JComponent) {
                Object property = ((JComponent)c).getClientProperty(PROP_CONTENT_SELECTED_INDEX);
                if ((property instanceof Integer)) {
                    int off = ((Integer)property).intValue();
                    if ((off >= 0) && (off < getContentDataAt(active).length))
                        return seg + off;
                }
                return -1;
            }
            return seg;
        }
        
        /** Add property change listener.
         */
        public void addPropertyChangeListener(PropertyChangeListener pcl) {
            propertyChangeSupport.addPropertyChangeListener(pcl);
        }
        
        /** Remove property change listener.
         */
        public void removePropertyChangeListener(PropertyChangeListener pcl) {
            propertyChangeSupport.removePropertyChangeListener(pcl);
        }

        /** Start listening on changes in content.
         */
        private void startListening() {
            if (array[active] instanceof CompoundIterator) {
                ((CompoundIterator)array[active]).addPropertyChangeListener(this);
            } else if (array[active].current().getComponent() instanceof JComponent) {
                ((JComponent)array[active].current().getComponent())
                .addPropertyChangeListener(this);
            }
        }

        /** Start listening on changes in content.
         */
        private void stopListening() {
            if (array[active] instanceof CompoundIterator) {
                ((CompoundIterator)array[active]).removePropertyChangeListener(this);
            } else if (array[active].current().getComponent() instanceof JComponent) {
                ((JComponent)array[active].current().getComponent())
                .removePropertyChangeListener(this);
            }
        }
        
        /** Notifies that content has been changed.
         */
        public void propertyChange(PropertyChangeEvent ev) {
            propertyChangeSupport.firePropertyChange(ev.getPropertyName(), null, null);
        }
    }

    /** Simple iterator that iterates over just one panel */
    protected static class PanelWrapper implements org.openide.WizardDescriptor.Iterator {
        
        private WizardDescriptor.Panel panel;
        
        private String name;
        
        public PanelWrapper(WizardDescriptor.Panel p, String name) {
            panel = p;
            this.name = name;
        }
        
        public PanelWrapper(java.awt.Component c, String name) {
            panel = new ComponentPanel(c);
            this.name = name;
        }
        
        /** Add a listener to changes of the current panel.
         * The listener is notified when the possibility to move forward/backward changes.
         * @param l the listener to add
         */
        public void addChangeListener(ChangeListener l) {
//            panel.addChangeListener(l);
        }
        
        /** Get the current panel.
         * @return the panel
         */
        public WizardDescriptor.Panel current() {
            return panel;
        }
        
        /** Test whether there is a next panel.
         * @return true if so
         */
        public boolean hasNext() {
            return false;
        }
        
        /** Test whether there is a previous panel.
         * @return true if so
         */
        public boolean hasPrevious() {
            return false;
        }
        
        /** Get the name of the current panel.
         * @return the name
         */
        public String name() {
            return name;
        }
        
        /** Move to the next panel.
         * I.e. increment its index, need not actually change any GUI itself.
         * @exception NoSuchElementException if the panel does not exist
         */
        public void nextPanel() {
            throw new NoSuchElementException();
        }
        
        /** Move to the previous panel.
         * I.e. decrement its index, need not actually change any GUI itself.
         * @exception NoSuchElementException if the panel does not exist
         */
        public void previousPanel() {
            throw new NoSuchElementException();
        }
        
        /** Remove a listener to changes of the current panel.
         * @param l the listener to remove
         */
        public void removeChangeListener(ChangeListener l) {
//            panel.removeChangeListener(l);
        }
    }

    /**
     * ComponentPanel instance wraps a java.awt.Component to
     * get a WizardDescriptor.Panel
     */
    private static class ComponentPanel implements WizardDescriptor.FinishPanel {
        
        /** Remembered component*/
        private Component component;
        
        /** Just remembers the component.*/
        public ComponentPanel(Component c) {
            component = c;
        }
        
        /**
         * Get the component displayed in this panel.
         * @return the component
         */
        public java.awt.Component getComponent () {
            return component;
        }

        /** Help for this panel.
         * When the panel is active, this is used as the help for the wizard dialog.
         * @return the help or null if no help is supplied
         */
        public HelpCtx getHelp () {
            return null;
        }

        /** Provides the wizard panel with the current data--either
         * the default data or already-modified settings, if the user used the previous and/or next buttons.
         * This method can be called multiple times on one instance of WizardDescriptor.Panel.
         * @param settings the object representing wizard panel state, as originally supplied to {@link WizardDescriptor#WizardDescriptor(WizardDescriptor.Iterator,Object)}
         */
        public void readSettings (Object settings) {
        }

        /** Provides the wizard panel with the opportunity to update the
         * settings with its current customized state.
         * Rather than updating its settings with every change in the GUI, it should collect them,
         * and then only save them when requested to by this method.
         * Also, the original settings passed to {@link #readSettings} should not be modified (mutated);
         * rather, the (copy) passed in here should be mutated according to the collected changes.
         * This method can be called multiple times on one instance of WizardDescriptor.Panel.
         * @param settings the object representing a settings of the wizard
         */
        public void storeSettings (Object settings) {
        }

        /** Test whether the panel is finished and it is safe to proceed to the next one.
         * If the panel is valid, the "Next" (or "Finish") button will be enabled.
         * @return true if the user has entered satisfactory information
         */
        public boolean isValid () {
            return true;
        }

        /** Add a listener to changes of the panel's validity.
         * @param l the listener to add
         * @see #isValid
         */
        public void addChangeListener (ChangeListener l) {
        }

        /** Remove a listener to changes of the panel's validity.
         * @param l the listener to remove
         */
        public void removeChangeListener (ChangeListener l) {
        }

    }


}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.