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-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.examples.modules.minicomposer.registryutils.backcompatible;

import org.netbeans.api.nodes2looks.Nodes;
import org.netbeans.api.registry.*;
import org.netbeans.spi.looks.LookSelector;
import org.openide.cookies.InstanceCookie;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.explorer.propertysheet.ExPropertyEditor;
import org.openide.explorer.propertysheet.PropertyEnv;
import org.openide.explorer.propertysheet.PropertySheetView;
import org.openide.explorer.view.BeanTreeView;
import org.openide.explorer.view.TreeView;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;

import javax.swing.*;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyEditorSupport;
import java.beans.PropertyVetoException;
import java.util.Iterator;
import java.util.LinkedHashMap;

/**
 * Potentially reusable editor for objects in a context.
 * Does not attempt to handle subcontexts, only direct bindings.
 * Only objects assignable to some type are accepted.
 * They are displayed in a pulldown according to the default Look.
 * Currently displaying this pulldown will require all objects in
 * the context to be instantiated - pending an API for retrieving
 * display name from just a binding name. However this is unlikely
 * to be a realistic performance problem as only one context is
 * loaded (compared to ObjectEditor which loads a lot).
 * @author Jesse Glick
 */
public class ContextPropertyEditor extends PropertyEditorSupport implements ContextListener, ExPropertyEditor {

    private final Class type;
    private final String title;
    private final Context c;
    private LinkedHashMap/**/ instances;
    private LinkedHashMap/**/ labels;
    private PropertyEnv env;

    private LookSelector selector;


    /**
     * Create the property editor.
     * @param title a message to use e.g. in the custom editor dialog
     * @param c a context in which the objects are stored
     * @param type the interface class
     */
    public ContextPropertyEditor(String title, Context c, Class type, LookSelector selector) {
        this.type = type;
        this.title = title;
        this.c = c;
        this.selector = selector;
        scan();
        c.addContextListener((ContextListener) WeakListeners.create(ContextListener.class, this, c));
    }

    private void scan() {
        instances = new LinkedHashMap();
        labels = new LinkedHashMap();
        Iterator it = c.getOrderedNames().iterator();
        while (it.hasNext()) {
            String name = (String) it.next();
            if (name.endsWith("/")) {
                continue;
            }
            Object o = c.getObject(name, null);
            if (o == null || !type.isInstance(o)) {
                continue;
            }
            ObjectRef ref = new ObjectRef(c, name);
            String label = ref.getBindingName();
            instances.put(label, ref);
            labels.put(ref, label);
        }
    }

    public void setValue(Object o) {
        if (o == null) {
            super.setValue(null);
            return;
        }
        if (!(o instanceof ObjectRef)) {
            throw new ClassCastException(o.getClass().toString());
        }
        ObjectRef ref = (ObjectRef) o;
        if (!ref.isValid()) {
            throw new IllegalStateException("ObjectRef parameter is not valid: " + ref);
        }
        if (!type.isInstance(ref.getObject())) {
            throw new ClassCastException(o.getClass().toString());
        }
        super.setValue(ref);
    }

    public Object getValue() {
        Object o = super.getValue();
        if (o == null) {
            return null;
        }
        if (!(o instanceof ObjectRef)) {
            throw new ClassCastException(o.getClass().toString());
        }
        ObjectRef ref = (ObjectRef) o;
        if (!ref.isValid()) {
            throw new IllegalStateException("ObjectRef parameter is not valid: " + ref);
        }
        if (!type.isInstance(ref.getObject())) {
            throw new ClassCastException(o.getClass().toString());
        }
        return ref;
    }

    public String[] getTags() {
        return (String[]) labels.values().toArray(new String[labels.size()]);
    }

    public String getAsText() {
        String label = (String) labels.get(getValue());
        if (label != null) {
            return label;
        } else {
            return "";
        }
    }

    public void setAsText(String t) throws IllegalArgumentException {
        Object instance = instances.get(t);
        if (instance != null) {
            setValue(instance);
        } else {
            throw new IllegalArgumentException(t);
        }
    }

    public boolean supportsCustomEditor() {
        return true;
    }

    public Component getCustomEditor() {
        return new CustomEditor();
    }

    public void attributeChanged(AttributeEvent evt) {
    }

    public void bindingChanged(BindingEvent evt) {
        scan();
    }

    public void subcontextChanged(SubcontextEvent evt) {
    }

    public void attachEnv(PropertyEnv env) {
        this.env = env;
    }

    private final class CustomEditor extends JPanel implements ExplorerManager.Provider, Lookup.Provider, PropertyChangeListener {

        private final ExplorerManager manager;

        public CustomEditor() {
            Node r = Nodes.node(c, null, selector/*InternalSelector.getSelector(selector, title, type)*/);
            manager = new ExplorerManager();
            manager.setRootContext(r);
            TreeView tree = new BeanTreeView();
            // XXX split does not work well; resizing the left pane especially makes the nodes
            // invisible and there is no way to get them back without restoring the dialog size
            add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tree, new PropertySheetView()));
            ActionMap map = getActionMap();
            map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager));
            map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager));
            map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager));
            map.put("delete", ExplorerUtils.actionDelete(manager, true));
            Object key = "org.openide.actions.PopupAction";
            KeyStroke ks = KeyStroke.getKeyStroke("shift F10");
            tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, key);                                                
            // XXX buttons to clone and delete items, then tree.setRootVisible(false)
            initializeSelection();
            manager.addPropertyChangeListener(this);
        }

        public ExplorerManager getExplorerManager() {
            return manager;
        }

        public Lookup getLookup() {
            // Provide the node selection & our action map. Cf. #36315.
            Node[] ns = manager.getSelectedNodes();
            Object[] stuff = new Object[ns.length + 1];
            stuff[0] = getActionMap();
            System.arraycopy(ns, 0, stuff, 1, ns.length);
            return Lookups.fixed(stuff);
        }

        public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
                readSelection();
            }
        }

        // I guess that this is a trick that Node provides InstanceCookie
        // and InstanceCookie will actually return the represented object
        private void initializeSelection() {
            Node r = manager.getRootContext();
            Object o = getValue();
            try {
                if (o != null) {
                    Node[] ns = r.getChildren().getNodes(true);
                    for (int i = 0; i < ns.length; i++) {
                        InstanceCookie c = (InstanceCookie) ns[i].getCookie(InstanceCookie.class);
                        assert c != null : ns[i];
                        Object o2;
                        try {
                            o2 = c.instanceCreate();
                        } catch (Exception e) {
                            throw (AssertionError) new AssertionError(e).initCause(e);
                        }
                        assert o2 instanceof ObjectRef;
                        if (o == o2) {
                            manager.setSelectedNodes(new Node[]{ns[i]});
                            env.setState(PropertyEnv.STATE_VALID);
                            return;
                        }
                    }
                }
                manager.setSelectedNodes(new Node[]{r});
                env.setState(PropertyEnv.STATE_INVALID);
            } catch (PropertyVetoException e) {
                throw (AssertionError) new AssertionError(e).initCause(e);
            }
        }

        private void readSelection() {
            Node[] ns = manager.getSelectedNodes();
            if (ns.length == 1) {
                InstanceCookie.Of i = (InstanceCookie.Of) ns[0].getCookie(InstanceCookie.Of.class);
                if (i != null && i.instanceOf(ObjectRef.class)) {
                    Object o;
                    try {
                        o = i.instanceCreate();
                    } catch (Exception e) {
                        throw (AssertionError) new AssertionError(e).initCause(e);
                    }
                    assert o instanceof ObjectRef : o;
                    setValue(o);
                    env.setState(PropertyEnv.STATE_VALID);
                    return;
                } else {
                    assert ns[0].getParentNode() == null : ns[0];
                }
            }
            env.setState(PropertyEnv.STATE_INVALID);
        }

    }
}

... 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.