Example Plugin

This appendix shows how to build a plugin.

package ncsa.Im2Learn.ext.test;

import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;

import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import ncsa.Im2Learn.core.datatype.ImageObject;
import ncsa.Im2Learn.core.display.*;

// ------------------------------------------------------------
public class ExamplePlugin extends Im2LearnFrame
                           implements Im2LearnMenu {
    /**
     * Reference to the imagepanel this menu is associated
     * with.
     */
    private ImagePanel imagepanel;

    /**
     * Preview of the swap operation.
     */
    private ImagePanel ipPreview;

    /**
     * Logger used for debug and warning messages.
     */
    static private Log logger = LogFactory.
                                 getLog(ExamplePlugin.class);

    /**
     * Create the UI for this menu. Show a preview panel in the
     * middle of the frame and buttons below to do the swap,
     * apply changes to imagepanel and close the window.
     *
     */
    public ExamplePlugin() {
        super("COLOR SWAP");

        imagepanel = null;
        createUI();
    }

    /**
     * Called when the user hides the window.
     */
    public void hiding() {
        ipPreview.setImageObject(null);
    }

    /**
     * Called when the user shows the window.
     */
    public void showing() {
        reset();
    }

    /**
     * Create the UI. The UI consists of a preview imagepanel
     * which will show the swapped image, and three buttons to
     * swap the image, apply changes to the imagepanel and close
     * the window.
     */
    private void createUI() {
        ipPreview = new ImagePanel();
        ipPreview.setAutozoom(true);
        getContentPane().add(ipPreview, BorderLayout.CENTER);

        JPanel pnlButtons = new JPanel(new FlowLayout());
        pnlButtons.add(new JButton(new AbstractAction("Swap") {
            public void actionPerformed(ActionEvent e) {
                swap();
            }
        }));
        pnlButtons.add(new JButton(new AbstractAction("Apply") {
            public void actionPerformed(ActionEvent e) {
                if (ipPreview.getImageObject() == null) {
                    swap();
                }
                ImageObject imgobj = ipPreview.getImageObject();
                imagepanel.setImageObject(imgobj);
            }
        }));
        pnlButtons.add(new JButton(new AbstractAction("Close") {
            public void actionPerformed(ActionEvent e) {
                ExamplePlugin.this.setVisible(false);
            }
        }));
        getContentPane().add(pnlButtons, BorderLayout.SOUTH);

        pack();
    }

    /**
     * Set the image shown in the preview to null.
     */
    private void reset() {
        ipPreview.setImageObject(null);
    }

    /**
     * Change the colors of the imageobject. This will take
     * the current maximum color and subtract the color of
     * the pixel.
     */
    private void swap() {
        ImageObject imgobj = imagepanel.getImageObject();
        if ((imgobj == null) || !imgobj.isDataValid()) {
            return;
        }

        // create a copy that we work with
        ImageObject clone = null;
        try {
            clone = (ImageObject) imgobj.clone();
        } catch (CloneNotSupportedException exc) {
            logger.warn("Could not clone image.", exc);
            return;
        }
        double max = clone.getMax();

        // change all pixels, see Appendix B for more
        // efficient methods
        for (int i = 0; i  clone.getSize(); i++) {
            clone.setDouble(i, max - clone.getDouble(i));
        }

        // set the preview pane
        ipPreview.setImageObject(clone);
    }

    // ------------------------------------------------------------
    // Im2LearnMenu implementation
    // ------------------------------------------------------------
    /**
     * Store the reference to the imagepanel for later use.
     * The imagepanel passed in as argument is the
     * imagepanel to which this tools is associated.
     */
    public void setImagePanel(ImagePanel imagepanel) {
        this.imagepanel = imagepanel;
    }

    /**
     * For this tool there is no operation that works on the
     * imagepanel directly and thus we return null
     * indicating that no menu entries need to be created on
     * the panel.
     */
    public JMenuItem[] getPanelMenuItems() {
        return null;
    }

    /**
     * Create a menu entry called Tools, and attach a
     * submenu entry to this for this class, called swap. If
     * the user selects this class
     */
    public JMenuItem[] getMainMenuItems() {
        JMenu menu = new JMenu("Tools");

        JMenuItem item = new JMenuItem(new AbstractAction("Swap") {
            public void actionPerformed(ActionEvent e) {
                if (!isVisible()) {
                    Window win = SwingUtilities.
                                  getWindowAncestor(imagepanel);
                    setLocationRelativeTo(win);
                    setVisible(true);
                }
                toFront();
            }
        });
        menu.add(item);

        return new JMenuItem[] { menu };
    }

    /**
     * When a new image is loaded make sure that the current
     * swapped image is removed, i.e. perform a reset. Only
     * need to reset the image if this frame is visible.
     */
    public void imageUpdated(ImageUpdateEvent event) {
        if (!isVisible()) {
            return;
        }
        if (event.getId() == ImageUpdateEvent.NEW_IMAGE) {
            reset();
        }
    }

    /**
     * Return the right documentation depending on what node
     * is selected, in this case only the Swap node should
     * exist.
     */
    public URL getHelp(String menu) {
        if (menu.equals("Swap")) {
            return getClass().getResource("help/swap.html");
        } else {
            return null;
        }
    }
}