org.openmicroscopy.shoola.agents.treeviewer.util.MoveGroupSelectionDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.agents.treeviewer.util.MoveGroupSelectionDialog.java

Source

/*
 * org.openmicroscopy.shoola.agents.treeviewer.util.MoveGroupSelectionDialog 
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006-2012 University of Dundee & Open Microscopy Environment.
 *  All rights reserved.
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */
package org.openmicroscopy.shoola.agents.treeviewer.util;

//Java imports
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

//Third-party libraries
import info.clearthought.layout.TableLayout;

import org.apache.commons.collections.CollectionUtils;
import org.jdesktop.swingx.JXBusyLabel;

//Application-internal dependencies
import org.openmicroscopy.shoola.agents.treeviewer.IconManager;
import org.openmicroscopy.shoola.agents.util.ViewerSorter;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageDisplay;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeViewerTranslator;
import org.openmicroscopy.shoola.env.data.util.SecurityContext;
import org.openmicroscopy.shoola.util.ui.TitlePanel;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import org.openmicroscopy.shoola.util.ui.filechooser.CreateFolderDialog;

import pojos.DataObject;
import pojos.DatasetData;
import pojos.ImageData;
import pojos.PlateData;
import pojos.ProjectData;
import pojos.ScreenData;

/** 
 * Selects the targets of the move group action.
 *
 * @author Jean-Marie Burel     
 * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
 * @since Beta4.4
 */
public class MoveGroupSelectionDialog extends JDialog
        implements ActionListener, PropertyChangeListener, TreeSelectionListener {

    /** Bound property indicating to transfer the data.*/
    public static final String TRANSFER_PROPERTY = "transfer";

    /** Action id to close and dispose.*/
    public static final int CANCEL = 1;

    /** Action id to move the data.*/
    private static final int MOVE = 2;

    /** 
     * Action id to create a new container e.g. Dataset. The supported types
     * are Project, Dataset or Screen, depending on the objects to move.
     */
    private static final int CREATE = 3;

    /** Text displayed in the header.*/
    private static final String TEXT = "Select where to move the data.";

    /** The default size of the busy image.*/
    private static final Dimension SIZE = new Dimension(32, 32);

    /** The object to handle.*/
    private ChgrpObject object;

    /** The button to close and dispose.*/
    private JButton cancelButton;

    /** The button to move the data.*/
    private JButton moveButton;

    /** The button to create a new container.*/
    private JButton createButton;

    /** The component displayed in center of dialog.*/
    private JComponent body;

    /** The id of the user.*/
    private long userID;

    /** Sort the data.*/
    private ViewerSorter sorter;

    /** Indicate the status of the dialog.*/
    private int status;

    /** Handle the nodes to display.*/
    private JTree treeDisplay;

    /** The type of container to create.*/
    private Class<?> containerType;

    /** The data object to create.*/
    private DataObject toCreate;

    /** Flag indicating that the message indicating that no node displayed.*/
    private boolean noDisplay;

    /**
     * Creates a new container corresponding to {@link #containerType}.
     * 
     * @param name The name of the container.
     */
    private void create(String name) {
        if (containerType == null)
            return;
        if (ProjectData.class.equals(containerType)) {
            toCreate = new ProjectData();
            ((ProjectData) toCreate).setName(name);
        } else if (ScreenData.class.equals(containerType)) {
            toCreate = new ScreenData();
            ((ScreenData) toCreate).setName(name);
        } else if (DatasetData.class.equals(containerType)) {
            toCreate = new DatasetData();
            ((DatasetData) toCreate).setName(name);
        }
        DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
        TreeImageDisplay root = (TreeImageDisplay) dtm.getRoot();
        TreeImageSet node = new TreeImageSet(toCreate);
        node.setDisplayItems(false);
        dtm.insertNodeInto(node, root, root.getChildCount());
        node = (TreeImageSet) root.getChildAt(root.getChildCount() - 1);
        treeDisplay.setSelectionPath(new TreePath(node.getPath()));
        if (noDisplay) {
            noDisplay = false;
            Container c = getContentPane();
            c.remove(body);
            c.remove(1);
            c.add(new JScrollPane(treeDisplay), BorderLayout.CENTER);
            c.add(buildToolBar(), BorderLayout.SOUTH);
            validate();
            repaint();

        }
    }

    /** Brings up a dialog to create a new container.*/
    private void showNewFolder() {
        if (containerType == null)
            return;
        String title = "";
        String defaultName = "";
        if (ProjectData.class.equals(containerType)) {
            title = "New Project";
            defaultName = "untitled project";
        } else if (ScreenData.class.equals(containerType)) {
            title = "New Screen";
            defaultName = "untitled screen";
        } else if (DatasetData.class.equals(containerType)) {
            title = "New Dataset";
            defaultName = "untitled dataset";
        }
        CreateFolderDialog d = new CreateFolderDialog(this, title);
        d.setDefaultName(defaultName);
        d.addPropertyChangeListener(CreateFolderDialog.CREATE_FOLDER_PROPERTY, this);
        d.pack();
        UIUtilities.centerAndShow(this, d);
    }

    /**
      * Adds the nodes to the specified parent.
      * 
      * @param parent The parent node.
      * @param nodes The list of nodes to add.
      * @param tm The  tree model.
      */
    private void buildTreeNode(TreeImageDisplay parent, Collection<TreeImageDisplay> nodes, DefaultTreeModel tm) {
        Iterator<TreeImageDisplay> i = nodes.iterator();
        TreeImageDisplay display;
        List<TreeImageDisplay> children;
        while (i.hasNext()) {
            display = (TreeImageDisplay) i.next();
            display.setDisplayItems(false);
            tm.insertNodeInto(display, parent, parent.getChildCount());
            if (display instanceof TreeImageSet) {
                children = display.getChildrenDisplay();
                if (children.size() > 0) {
                    buildTreeNode(display, prepareSortedList(sorter.sort(children)), tm);
                }
            }
        }
    }

    /** Closes and disposes.*/
    private void cancel() {
        status = CANCEL;
        setVisible(false);
        dispose();
    }

    /** Moves the data.*/
    private void move() {
        DataObject target = null;
        if (toCreate != null) {
            target = toCreate;
        } else {
            TreePath path = treeDisplay.getSelectionPath();

            if (path != null) {
                Object object = path.getLastPathComponent();
                if (object != null && object instanceof TreeImageDisplay) {
                    target = (DataObject) ((TreeImageDisplay) object).getUserObject();
                }
            }
        }
        ChgrpObject newObject = new ChgrpObject(object.getGroupData(), target, object.getTransferable());
        firePropertyChange(TRANSFER_PROPERTY, null, newObject);
        cancel();
    }

    /** Initializes the components.
     * 
     * @param same Pass <code>true</code> if the user moving the data and the 
     *             owner of the data are the same person, <code>false</code>
     */
    private void initComponents(boolean same) {
        containerType = null;
        sorter = new ViewerSorter();
        createButton = new JButton("New...");
        createButton.addActionListener(this);
        createButton.setActionCommand("" + CREATE);
        cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(this);
        cancelButton.setActionCommand("" + CANCEL);
        moveButton = new JButton("Move");
        moveButton.setEnabled(true);
        moveButton.addActionListener(this);
        moveButton.setActionCommand("" + MOVE);
        Entry<SecurityContext, List<DataObject>> entry;
        Iterator<Entry<SecurityContext, List<DataObject>>> i = object.getTransferable().entrySet().iterator();
        List<DataObject> list;
        DataObject data;
        while (i.hasNext()) {
            entry = i.next();
            list = entry.getValue();
            if (list != null && list.size() > 0) {
                data = list.get(0);
                if (data instanceof PlateData) {
                    containerType = ScreenData.class;
                } else if (data instanceof DatasetData) {
                    containerType = ProjectData.class;
                } else if (data instanceof ImageData) {
                    containerType = DatasetData.class;
                }
            }
        }
        createButton.setEnabled(false);
        if (same) {
            createButton.setEnabled(containerType != null);
            createButton.setVisible(containerType != null);
        }
    }

    /** 
     * Builds and lays out the buttons.
     * 
     * @return See above.
     */
    private JPanel buildToolBar() {
        JPanel bar = new JPanel();
        bar.add(moveButton);
        bar.add(Box.createRigidArea(UIUtilities.H_SPACER_SIZE));
        bar.add(cancelButton);
        bar.add(Box.createRigidArea(UIUtilities.H_SPACER_SIZE));
        JPanel barLeft = new JPanel();
        barLeft.add(createButton);

        JPanel row = new JPanel();
        row.setLayout(new BoxLayout(row, BoxLayout.X_AXIS));

        row.add(UIUtilities.buildComponentPanel(barLeft));
        row.add(UIUtilities.buildComponentPanelRight(bar));
        return row;
    }

    /** Builds and lays out the UI.*/
    private void buildGUI() {
        IconManager icons = IconManager.getInstance();
        TitlePanel tp = new TitlePanel(getTitle(), TEXT, icons.getIcon(IconManager.MOVE_48));
        Container c = getContentPane();
        c.add(tp, BorderLayout.NORTH);
        JXBusyLabel label = new JXBusyLabel(SIZE);
        label.setBusy(true);
        body = buildContent(label);
        c.add(body, BorderLayout.CENTER);
        c.add(buildToolBar(), BorderLayout.SOUTH);
        setSize(400, 500);
    }

    /** 
     * Builds the main component of this dialog.
     * 
     * @param group The selected group if any.
     * @param comp The component to add.
     * @return See above.
     */
    private JComponent buildContent(JComponent comp) {
        double[][] tl = { { TableLayout.FILL }, //columns
                { TableLayout.FILL } }; //rows
        JPanel content = new JPanel();
        content.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
        content.setLayout(new TableLayout(tl));
        content.setBackground(UIUtilities.BACKGROUND);
        content.add(comp, "0, 0, CENTER, CENTER");
        return content;
    }

    /**
      * Organizes the sorted list so that the Project/Screen/Tag Set 
      * are displayed first.
      * 
      * @param sorted The collection to organize.
      * @return See above.
      */
    private List<TreeImageDisplay> prepareSortedList(List<TreeImageDisplay> sorted) {
        List<TreeImageDisplay> top = new ArrayList<TreeImageDisplay>();
        List<TreeImageDisplay> bottom = new ArrayList<TreeImageDisplay>();

        List<TreeImageDisplay> top2 = new ArrayList<TreeImageDisplay>();
        List<TreeImageDisplay> bottom2 = new ArrayList<TreeImageDisplay>();

        Iterator<TreeImageDisplay> j = sorted.iterator();
        TreeImageDisplay object;
        Object uo;
        while (j.hasNext()) {
            object = (TreeImageDisplay) j.next();
            uo = object.getUserObject();
            if (ProjectData.class.equals(containerType)) {
                if (uo instanceof ProjectData) {
                    top.add(object);
                    object.removeAllChildrenDisplay();
                }
            } else if (ScreenData.class.equals(containerType)) {
                if (uo instanceof ScreenData) {
                    top.add(object);
                    object.removeAllChildrenDisplay();
                }
            } else if (DatasetData.class.equals(containerType)) {
                if (uo instanceof ProjectData)
                    top.add(object);
                else if (uo instanceof DatasetData)
                    bottom.add(object);
            }
        }
        List<TreeImageDisplay> all = new ArrayList<TreeImageDisplay>();
        if (top.size() > 0)
            all.addAll(top);
        if (bottom.size() > 0)
            all.addAll(bottom);
        if (top2.size() > 0)
            all.addAll(top2);
        if (bottom2.size() > 0)
            all.addAll(bottom2);
        return all;
    }

    /** Builds the components displayed when no node to display.*/
    private void buildNoContentPane() {
        noDisplay = true;
        Container c = getContentPane();
        StringBuffer s = new StringBuffer();
        StringBuffer s1 = new StringBuffer();
        if (ProjectData.class.equals(containerType)) {
            s.append("There is no Project to move the Dataset(s) into.");
            s1.append("Please create a new Project if you wish.");
        } else if (DatasetData.class.equals(containerType)) {
            s.append("There is no Dataset to move the Image(s) into.");
            s1.append("Please create a new Dataset if you wish.");
        } else if (ScreenData.class.equals(containerType)) {
            s.append("There is no Screen to move the Plate into.");
            s1.append("Please create a new Screen if you wish.");
        }
        JPanel p = new JPanel();
        p.setBackground(UIUtilities.BACKGROUND);
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.add(new JLabel(s.toString()));
        p.add(new JLabel(s1.toString()));
        body = buildContent(p);
        c.add(body, BorderLayout.CENTER);
        c.add(buildToolBar(), BorderLayout.SOUTH);
        validate();
        repaint();
    }

    /**
     * Creates a new instance.
     * 
     * @param owner The owner of the dialog.
     * @param userID The identifier of the user.
     * @param object The object to move.
     * @param same Pass <code>true</code> if the user moving the data and the 
     *             owner of the data are the same person, <code>false</code>
     */
    public MoveGroupSelectionDialog(JFrame owner, long userID, ChgrpObject object, boolean same) {
        super(owner);
        if (object == null)
            throw new IllegalArgumentException("No object to move.");
        StringBuffer buf = new StringBuffer();
        buf.append("Move to ");
        buf.append(object.getGroupData().getName());
        setTitle(buf.toString());
        this.object = object;
        this.userID = userID;
        initComponents(same);
        buildGUI();
    }

    /**
     * Returns the status of the dialog.
     * 
     * @return See above.
     */
    public int getStatus() {
        return status;
    }

    /**
     * Sets the values where to import the data.
     * 
     * @param targets The values to display.
     */
    public void setTargets(Collection<DataObject> targets) {
        Container c = getContentPane();
        c.remove(body);
        c.remove(1);
        treeDisplay = new JTree();
        treeDisplay.setVisible(true);
        treeDisplay.setRootVisible(false);
        ToolTipManager.sharedInstance().registerComponent(treeDisplay);
        treeDisplay.setCellRenderer(new TreeCellRenderer(userID));
        treeDisplay.setShowsRootHandles(true);
        TreeImageSet root = new TreeImageSet("");
        treeDisplay.setModel(new DefaultTreeModel(root));
        treeDisplay.addTreeSelectionListener(this);
        if (CollectionUtils.isEmpty(targets)) {
            buildNoContentPane();
            return;
        }
        Set<TreeImageDisplay> nodes = TreeViewerTranslator.transformHierarchy(new ArrayList<Object>(targets));
        List<TreeImageDisplay> transformedNodes = prepareSortedList(sorter.sort(nodes));
        if (transformedNodes.size() == 0) {
            buildNoContentPane();
            return;
        }
        DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
        buildTreeNode(root, transformedNodes, dtm);
        dtm.reload();
        c.add(new JScrollPane(treeDisplay), BorderLayout.CENTER);
        c.add(buildToolBar(), BorderLayout.SOUTH);
        validate();
        repaint();
    }

    /**
     * Closes or moves the data.
     * @see ActionListener#actionPerformed(ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        int index = Integer.parseInt(e.getActionCommand());
        switch (index) {
        case CANCEL:
            cancel();
            break;
        case MOVE:
            move();
            break;
        case CREATE:
            showNewFolder();
        }
    }

    /**
     * Listens to property to create a new container.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        String name = evt.getPropertyName();
        if (CreateFolderDialog.CREATE_FOLDER_PROPERTY.equals(name)) {
            String folderName = (String) evt.getNewValue();
            if (folderName != null && folderName.trim().length() > 0)
                create(folderName);
        }
    }

    /**
     * Listens to node selection in the tree.
     * @see TreeSelectionListener#valueChanged(TreeSelectionEvent)
     */
    public void valueChanged(TreeSelectionEvent e) {
        TreePath[] paths = treeDisplay.getSelectionPaths();
        if (paths == null || paths.length == 0) {
            moveButton.setEnabled(false);
            return;
        }
        Object p = paths[0].getLastPathComponent();
        if (p instanceof TreeImageDisplay) {
            Object ho = ((TreeImageDisplay) p).getUserObject();
            moveButton.setEnabled(ho.getClass().equals(containerType));
        }
    }

}