/*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2015 University of Dundee. 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.browser;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.DnDConstants;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
//Third-party libraries
import org.apache.commons.collections.CollectionUtils;
//Application-internal dependencies
import org.openmicroscopy.shoola.agents.treeviewer.TreeViewerAgent;
import org.openmicroscopy.shoola.agents.treeviewer.actions.BrowserManageAction;
import org.openmicroscopy.shoola.agents.treeviewer.cmd.ViewCmd;
import org.openmicroscopy.shoola.agents.treeviewer.util.TreeCellRenderer;
import org.openmicroscopy.shoola.agents.treeviewer.view.TreeViewer;
import org.openmicroscopy.shoola.agents.util.ViewerSorter;
import org.openmicroscopy.shoola.agents.util.browser.PartialNameVisitor;
import org.openmicroscopy.shoola.agents.util.browser.SmartFolder;
import org.openmicroscopy.shoola.agents.util.browser.TreeFileSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageDisplay;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageDisplayVisitor;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageNode;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeImageTimeSet;
import org.openmicroscopy.shoola.agents.util.browser.TreeViewerTranslator;
import org.openmicroscopy.shoola.agents.util.dnd.DnDTree;
import org.openmicroscopy.shoola.agents.util.dnd.ObjectToTransfer;
import org.openmicroscopy.shoola.env.LookupNames;
import org.openmicroscopy.shoola.env.config.Registry;
import org.openmicroscopy.shoola.env.data.FSFileSystemView;
import org.openmicroscopy.shoola.util.CommonsLangUtils;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import omero.gateway.model.DataObject;
import omero.gateway.model.DatasetData;
import omero.gateway.model.ExperimenterData;
import omero.gateway.model.FileAnnotationData;
import omero.gateway.model.FileData;
import omero.gateway.model.GroupData;
import omero.gateway.model.ImageData;
import omero.gateway.model.PlateData;
import omero.gateway.model.PlateAcquisitionData;
import omero.gateway.model.ProjectData;
import omero.gateway.model.ScreenData;
import omero.gateway.model.TagAnnotationData;
/**
* The Browser's View.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @version 2.2
* @since OME2.2
*/
class BrowserUI
extends JPanel
implements PropertyChangeListener
{
/** The <code>Attachments</code> smart folder. */
private static final int[] VALUES = {TreeFileSet.MOVIE, TreeFileSet.OTHER};
/** The tree hosting the display. */
private DnDTree treeDisplay;
/** The tool bar hosting the controls. */
private JToolBar rightMenuBar;
/** The tool bar hosting the controls. */
private JToolBar leftMenuBar;
/** The Controller. */
private BrowserControl controller;
/** The model. */
private BrowserModel model;
/**
* A {@link ViewerSorter sorter} to order nodes in ascending
* alphabetical order.
*/
private ViewerSorter sorter;
/** Reference to the listener. */
private TreeExpansionListener listener;
/** Reference to the selection listener. */
private TreeSelectionListener selectionListener;
/** Collections of nodes whose <code>enabled</code> flag has to be reset. */
private Set<TreeImageDisplay> nodesToReset;
/** Button indicating if the partial name is displayed or not. */
private JToggleButton partialButton;
/** Indicates if the <code>control</code> key is down. */
private boolean ctrl;
/** Flag indicating if the left mouse button is pressed. */
private boolean leftMouseButton;
/** The component displayed at the bottom of the UI. */
private JComponent bottomComponent;
/* The tree selection event. */
private TreeSelectionEvent event;
/* The time when the latest tree selection event was handled. */
private long eventHandledTime = Long.MIN_VALUE;
/* The time when the latest mouse press event occurred. */
private long mousePressedTime;
/* If a mouse event delayed handling tree selection, because
* a corresponding tree selection event had not yet been seen. */
private boolean delayedHandlingTreeSelection = false;
/** Flag indicating if it is a right-click.*/
private boolean rightClickButton;
/** Flag indicating if it is a right-click.*/
private boolean rightClickPad;
/** Identifies the key event.*/
private int keyEvent;
/**
* Builds the tool bar.
*
* @return See above.
*/
private JPanel buildToolBar()
{
JPanel bar = new JPanel();
bar.setLayout(new BoxLayout(bar, BoxLayout.X_AXIS));
bar.setBorder(null);
JPanel p = new JPanel();
p.setLayout(new FlowLayout(FlowLayout.LEFT));
p.setBorder(null);
p.add(leftMenuBar);
p.setPreferredSize(leftMenuBar.getPreferredSize());
bar.add(p);
p = new JPanel();
p.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
p.setBorder(null);
p.add(rightMenuBar);
p.setPreferredSize(rightMenuBar.getPreferredSize());
bar.add(p);
return bar;
}
/** Builds and lays out the UI. */
private void buildGUI()
{
setLayout(new BorderLayout(0, 0));
add(buildToolBar(), BorderLayout.NORTH);
add(new JScrollPane(treeDisplay), BorderLayout.CENTER);
}
/** Helper method to create the menu bar. */
private void createMenuBars()
{
rightMenuBar = new JToolBar();
rightMenuBar.setBorder(null);
rightMenuBar.setRollover(true);
rightMenuBar.setFloatable(false);
JButton button;
leftMenuBar = new JToolBar();
leftMenuBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));
leftMenuBar.setRollover(true);
leftMenuBar.setFloatable(false);
BrowserManageAction a;
int type = model.getBrowserType();
switch (type) {
case Browser.PROJECTS_EXPLORER:
case Browser.SCREENS_EXPLORER:
a = (BrowserManageAction)
controller.getAction(BrowserControl.NEW_CONTAINER);
button = new JButton(a);
button.setName("new container button");
button.setBorderPainted(false);
button.addMouseListener(a);
rightMenuBar.add(button);
break;
case Browser.ADMIN_EXPLORER:
a = (BrowserManageAction)
controller.getAction(BrowserControl.NEW_ADMIN);
button = new JButton(a);
button.setName("new group or user button");
button.setBorderPainted(false);
button.addMouseListener(a);
rightMenuBar.add(button);
break;
case Browser.TAGS_EXPLORER:
a = (BrowserManageAction)
controller.getAction(BrowserControl.NEW_TAG);
button = new JButton(a);
button.setName("new tag button");
button.setBorderPainted(false);
button.addMouseListener(a);
rightMenuBar.add(button);
}
button = new JButton(controller.getAction(BrowserControl.CUT));
button.setName("cut button");
button.setBorderPainted(false);
rightMenuBar.add(button);
button = new JButton(controller.getAction(BrowserControl.COPY));
button.setName("copy button");
button.setBorderPainted(false);
rightMenuBar.add(button);
button = new JButton(controller.getAction(BrowserControl.PASTE));
button.setName("paste button");
button.setBorderPainted(false);
rightMenuBar.add(button);
button = new JButton(controller.getAction(BrowserControl.DELETE));
button.setName("delete button");
button.setBorderPainted(false);
rightMenuBar.add(button);
button = new JButton(controller.getAction(BrowserControl.REFRESH));
button.setName("refresh button");
button.setBorderPainted(false);
rightMenuBar.add(button);
if (type == Browser.ADMIN_EXPLORER) {
button = new JButton(controller.getAction(
BrowserControl.RESET_PASSWORD));
button.setBorderPainted(false);
rightMenuBar.add(button);
} else {
button = new JButton(controller.getAction(BrowserControl.IMPORT));
button.setBorderPainted(false);
//rightMenuBar.add(button);
}
rightMenuBar.add(Box.createHorizontalStrut(6));
rightMenuBar.add(new JSeparator());
rightMenuBar.add(Box.createHorizontalStrut(6));
ButtonGroup group = new ButtonGroup();
JToggleButton b = new JToggleButton();
group.add(b);
b.setBorderPainted(true);
b.setSelected(true);
b.setAction(controller.getAction(BrowserControl.SORT));
rightMenuBar.add(b);
b = new JToggleButton(controller.getAction(BrowserControl.SORT_DATE));
b.setBorderPainted(true);
group.add(b);
rightMenuBar.add(b);
partialButton = new JToggleButton(
controller.getAction(BrowserControl.PARTIAL_NAME));
partialButton.setBorderPainted(true);
rightMenuBar.add(partialButton);
rightMenuBar.add(new JSeparator(JSeparator.VERTICAL));
button = new JButton(controller.getAction(BrowserControl.COLLAPSE));
button.setBorderPainted(false);
rightMenuBar.add(button);
}
/**
* Reacts to node expansion event.
*
* @param node The node to handle.
* @param expanded Pass <code>true</code> is the node is expanded,
* <code>false</code> otherwise.
*/
private void onNodeNavigation(TreeImageDisplay node, boolean expanded)
{
node.setExpanded(expanded);
controller.onNodeNavigation(node, expanded);
treeDisplay.clearSelection();
try {
treeDisplay.setSelectionPath(new TreePath(node.getPath()));
} catch (Exception e) {}
treeDisplay.repaint();
}
/**
* Reacts to mouse pressed and mouse release event.
*
* @param me The event to handle.
* @param released Pass <code>true</code> if the method is invoked when
* the mouse is released, <code>false</code> otherwise.
*/
private void onClick(MouseEvent me, boolean released)
{
Point p = me.getPoint();
int row = treeDisplay.getRowForLocation(p.x, p.y);
if (row != -1) {
if (me.getClickCount() == 1) {
model.setClickPoint(p);
if (mousePressedTime > eventHandledTime)
/* have not yet seen the tree selection event */
delayedHandlingTreeSelection = true;
else
handleTreeSelection();
//if (released) {
if ((me.isPopupTrigger() && !released) ||
(me.isPopupTrigger() && released &&
!UIUtilities.isMacOS()) ||
(UIUtilities.isMacOS() &&
SwingUtilities.isLeftMouseButton(me)
&& me.isControlDown())) {
if (rightClickButton && !model.isMultiSelection()) { //(!(me.isShiftDown() || ctrl))
TreePath path = treeDisplay.getPathForLocation(p.x,
p.y);
//treeDisplay.removeTreeSelectionListener(
// selectionListener);
if (path != null)
treeDisplay.setSelectionPath(path);
//treeDisplay.addTreeSelectionListener(selectionListener);
if (path != null &&
path.getLastPathComponent()
instanceof TreeImageDisplay)
controller.onRightClick((TreeImageDisplay)
path.getLastPathComponent());
}
if (model.getBrowserType() == Browser.ADMIN_EXPLORER)
controller.showPopupMenu(TreeViewer.ADMIN_MENU);
else
controller.showPopupMenu(TreeViewer.FULL_POP_UP_MENU);
}
} else if (me.getClickCount() == 2 && !(me.isMetaDown()
|| me.isControlDown() || me.isShiftDown())) {
//controller.cancel();
//model.viewDataObject();
TreeImageDisplay d = model.getLastSelectedDisplay();
if (d == null) return;
Object o = d.getUserObject();
if (o instanceof ImageData) {
model.browse(d);
} else if (o instanceof PlateData) {
if (!d.hasChildrenDisplay() ||
d.getChildrenDisplay().size() == 1)
model.browse(d);
} else if (o instanceof PlateAcquisitionData) {
model.browse(d);
}
}
}
}
/**
* Handles the mouse moved event. Displays the properties of the
* the nodes the mouse is over.
*
* @param e The mouse event to handle.
*/
private void rollOver(MouseEvent e)
{
if (!model.getParentModel().isRollOver()) return;
JTree tree = treeDisplay;
TreePath path = treeDisplay.getClosestPathForLocation(
e.getX(), e.getY());
Rectangle bounds = tree.getPathBounds(path);
if (!bounds.contains(e.getPoint())) return;
TreeImageDisplay node = (TreeImageDisplay) path.getLastPathComponent();
Object uo = node.getUserObject();
if (!(uo instanceof DataObject)) return;
}
/**
* Creates an experimenter node hosting the passed experimenter.
*
* @param exp The experimenter to add.
* @param groupNode The node to attach the experimenter to.
* @return See above.
*/
private TreeImageSet createExperimenterNode(ExperimenterData exp,
TreeImageDisplay groupNode)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
TreeImageSet node = new TreeImageSet(exp);
switch (model.getBrowserType()) {
case Browser.IMAGES_EXPLORER:
createTimeElements(node);
break;
case Browser.FILES_EXPLORER:
createFileElements(node);
break;
case Browser.TAGS_EXPLORER:
createTagsElements(node);
break;
default:
buildEmptyNode(node);
}
//TreeImageDisplay root = getTreeRoot();
//root.addChildDisplay(node);
//tm.insertNodeInto(node, root, root.getChildCount());
groupNode.addChildDisplay(node);
tm.insertNodeInto(node, groupNode, groupNode.getChildCount());
return node;
}
/**
* Creates the elements to attach the specified group node.
*
* @param node The node to attach the elements to.
* @return See above.
*/
private TreeImageSet createGroupNode(TreeImageSet node)
{
switch (model.getBrowserType()) {
case Browser.IMAGES_EXPLORER:
createTimeElements(node);
break;
case Browser.FILES_EXPLORER:
createFileElements(node);
break;
default:
buildEmptyNode(node);
}
return node;
}
/**
* Creates the smart folders added to the passed node.
*
* @param parent The parent of the smart folder.
*/
private void createTimeElements(TreeImageSet parent)
{
createTimeNode(TreeImageTimeSet.TODAY, parent, true);
createTimeNode(TreeImageTimeSet.WEEK, parent, true);
createTimeNode(TreeImageTimeSet.TWO_WEEK, parent, true);
TreeImageSet n = createTimeNode(TreeImageTimeSet.YEAR, parent, false);
int month = TreeImageTimeSet.getCurrentMonth()+1;
for (int i = 0; i < month; i++)
createTimeNode(TreeImageTimeSet.YEAR, i, n);
n.setNumberItems(-1);
n = createTimeNode(TreeImageTimeSet.YEAR_BEFORE, parent, false);
for (int i = 0; i < 12; i++)
createTimeNode(TreeImageTimeSet.YEAR_BEFORE, i, n);
n.setNumberItems(-1);
createTimeNode(TreeImageTimeSet.OTHER, parent, true);
//parent.setChildrenLoaded(true);
}
/**
* Creates folders hosting <code>FileAnnotation</code>s.
*
* @param parent The parent of the elements.
*/
private void createFileElements(TreeImageSet parent)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
TreeFileSet node;
for (int i = 0; i < VALUES.length; i++) {
node = new TreeFileSet(VALUES[i]);
buildEmptyNode(node);
node.setNumberItems(-1);
parent.addChildDisplay(node);
tm.insertNodeInto(node, parent, parent.getChildCount());
}
}
/**
* Creates the smart folders added to the passed node.
*
* @param parent The parent of the smart folder.
*/
private void createTagsElements(TreeImageDisplay parent)
{
if (model.getDisplayMode() == TreeViewer.GROUP_DISPLAY) return;
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
TreeFileSet node = new TreeFileSet(TreeFileSet.TAG);
buildEmptyNode(node);
node.setNumberItems(-1);
parent.addChildDisplay(node);
tm.insertNodeInto(node, parent, parent.getChildCount());
}
/**
* Creates and returns a {@link TreeImageTimeSet}.
*
* @param index One of the following constants:
* {@link TreeImageTimeSet#YEAR} or
* {@link TreeImageTimeSet#WEEK}
* @param parent The parent of the new node.
* @param empty Pass <code>true</code> to add an empty node,
* <code>false</code> otherwise.
* @return See above.
*/
private TreeImageTimeSet createTimeNode(int index, TreeImageSet parent,
boolean empty)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
TreeImageTimeSet date = new TreeImageTimeSet(index);
if (empty) buildEmptyNode(date);
parent.addChildDisplay(date);
tm.insertNodeInto(date, parent, parent.getChildCount());
return date;
}
/**
* Creates and returns a {@link TreeImageTimeSet}.
*
* @param index One of the following constants:
* {@link TreeImageTimeSet#YEAR} or
* {@link TreeImageTimeSet#YEAR_BEFORE}.
* @param month The index of the month.
* @param parent The parent of the new node.
* @return See above.
*/
private TreeImageTimeSet createTimeNode(int index, int month,
TreeImageSet parent)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
TreeImageTimeSet date = new TreeImageTimeSet(index, month);
buildEmptyNode(date);
parent.addChildDisplay(date);
tm.insertNodeInto(date, parent, parent.getChildCount());
parent.setChildrenLoaded(true);
return date;
}
/**
* Transforms the file contained in the passed directory.
* Returns the collection of <code>TreeImageNode</code> to check.
*
* @param dirSet The directory to transform.
* @return See above.
*/
private List<TreeImageNode> transformDirectory(TreeImageSet dirSet)
{
List<TreeImageNode> leaves = new ArrayList<TreeImageNode>();
FileData dir = (FileData) dirSet.getUserObject();
TreeImageDisplay expNode = BrowserFactory.getDataOwner(dirSet);
if (expNode == null) return leaves;
Object ho = expNode.getUserObject();
if (!(ho instanceof ExperimenterData)) return leaves;
long expID = ((ExperimenterData) ho).getId();
DataObject[] files = model.getFilesData(expID, dir);
if (files != null && files.length > 0) {
DataObject object;
FileData file;
TreeImageDisplay display;
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
for (int i = 0; i < files.length; i++) {
object = files[i];
display = null;
if (object instanceof FileData) {
file = (FileData) object;
if (file.isDirectory()) {
if (!file.isHidden()) {
display = new TreeImageSet(file);
buildEmptyNode(display);
}
} else {
if (!file.isHidden())
display = new TreeImageNode(file);
}
} else if (object instanceof ImageData) {
display = TreeViewerTranslator.transformImage(
(ImageData) object);
}
if (display != null) dirSet.addChildDisplay(display);
}
}
return leaves;
}
/**
* Creates the file system view.
*
* @param id The id of the user the directory is for.
* @return See above.
*/
private Set<TreeImageDisplay> createFileSystemExplorer(
TreeImageDisplay expNode)
{
Set<TreeImageDisplay> results = new HashSet<TreeImageDisplay>();
ExperimenterData exp = (ExperimenterData) expNode.getUserObject();
FSFileSystemView fs = model.getRepositories(exp.getId());
if (fs == null) return results;
FileData file;
TreeImageSet display;
FileData[] files = fs.getRoots();
for (int j = 0; j < files.length; j++) {
file = files[j];
if (file.isDirectory() && !file.isHidden()) {
display = new TreeImageSet(file);
//display.setChildrenLoaded(true);
expNode.addChildDisplay(display);
buildEmptyNode(display);
//transformDirectory(display);
results.add(display);
}
}
return results;
}
/** Handles the selection of the nodes in the tree.*/
private void handleTreeSelection()
{
delayedHandlingTreeSelection = false;
TreeImageDisplay[] nodes = model.getSelectedDisplays();
if (((rightClickButton && !ctrl) || rightClickPad)
&& model.isMultiSelection()) {
setFoundNode(nodes);
return;
}
if (ctrl && leftMouseButton) {
TreePath[] paths = treeDisplay.getSelectionPaths();
List<TreePath> added = new ArrayList<TreePath>();
TreePath[] all = null;
if (paths != null) {
all = new TreePath[paths.length];
for (int i = 0; i < paths.length; i++) {
all[i] = new TreePath(paths[i].getPath());
}
}
//treeDisplay.removeTreeSelectionListener(selectionListener);
if (all != null) treeDisplay.setSelectionPaths(all);
//treeDisplay.addTreeSelectionListener(selectionListener);
if (all != null) {
for (int i = 0; i < all.length; i++)
added.add(all[i]);
}
controller.onClick(added);
return;
}
if (event == null) return;
TreePath[] paths = event.getPaths();
List<TreePath> added = new ArrayList<TreePath>();
for (int i = 0; i < paths.length; i++) {
if (rightClickPad) {
if (!event.isAddedPath(paths[i])) {
added.add(paths[i]);
}
} else {
if (event.isAddedPath(paths[i])) {
added.add(paths[i]);
}
}
}
//if (!ctrl)
controller.onClick(added);
}
/**
* Handles multi-selection using <code>Ctrl-A</code> or <code>Meta-A</code>.
*/
private void handleMultiSelection()
{
TreeImageDisplay[] nodes = model.getSelectedDisplays();
if (nodes == null || nodes.length == 0) return;
TreeImageDisplay n = nodes[0];
Object o = n.getUserObject();
TreeImageDisplay p;
if (o instanceof ImageData) {
p = n.getParentDisplay();
controller.selectNodes(p.getChildrenDisplay(), ImageData.class);
} else if (o instanceof DatasetData) {
if (n.isExpanded()) {
controller.selectNodes(n.getChildrenDisplay(), ImageData.class);
} else {
p = n.getParentDisplay();
controller.selectNodes(p.getChildrenDisplay(),
DatasetData.class);
}
} else if (o instanceof ProjectData) {
if (n.isExpanded()) {
controller.selectNodes(n.getChildrenDisplay(),
DatasetData.class);
} else {
p = n.getParentDisplay();
controller.selectNodes(p.getChildrenDisplay(),
ProjectData.class);
}
} else if (o instanceof ScreenData) {
if (n.isExpanded()) {
controller.selectNodes(
n.getChildrenDisplay(),
PlateData.class);
} else {
p = n.getParentDisplay();
controller.selectNodes(p.getChildrenDisplay(),
ScreenData.class);
}
} else if (o instanceof PlateData) {
if (n.isExpanded()) {
controller.selectNodes(
n.getChildrenDisplay(),
PlateAcquisitionData.class);
} else {
p = n.getParentDisplay();
controller.selectNodes(p.getChildrenDisplay(),
PlateData.class);
}
} else if (o instanceof TagAnnotationData) {
TagAnnotationData tag = (TagAnnotationData) o;
String ns = tag.getNameSpace();
if (TagAnnotationData.INSIGHT_TAGSET_NS.equals(ns)) {
//dealing with a tag set.
if (n.isExpanded()) {
controller.selectNodes(n.getChildrenDisplay(),
TagAnnotationData.class);
} else {
p = n.getParentDisplay();
List l = p.getChildrenDisplay();
Iterator i = l.iterator();
List values = new ArrayList();
TreeImageDisplay node;
Object data;
while (i.hasNext()) {
node = (TreeImageDisplay) i.next();
data = node.getUserObject();
if (data instanceof TagAnnotationData) {
tag = (TagAnnotationData) data;
ns = tag.getNameSpace();
if (TagAnnotationData.INSIGHT_TAGSET_NS.equals(ns))
values.add(node);
}
}
controller.selectNodes(values, TagAnnotationData.class);
}
} else { //tag
if (n.isExpanded()) {
controller.selectNodes(n.getChildrenDisplay(),
ImageData.class);
} else {
p = n.getParentDisplay();
List l = p.getChildrenDisplay();
Iterator i = l.iterator();
List values = new ArrayList();
TreeImageDisplay node;
Object data;
while (i.hasNext()) {
node = (TreeImageDisplay) i.next();
data = node.getUserObject();
if (data instanceof TagAnnotationData) {
tag = (TagAnnotationData) data;
ns = tag.getNameSpace();
if (!TagAnnotationData.INSIGHT_TAGSET_NS.equals(ns))
values.add(node);
}
}
controller.selectNodes(values, TagAnnotationData.class);
}
}
} else if (o instanceof FileAnnotationData) {
p = n.getParentDisplay();
controller.selectNodes(p.getChildrenDisplay(),
FileAnnotationData.class);
} else if (n instanceof TreeImageTimeSet) {
TreeImageTimeSet time = (TreeImageTimeSet) n;
if (time.containsImages()) {
controller.selectNodes(n.getChildrenDisplay(),
ImageData.class);
}
} else if (n instanceof TreeFileSet) {
controller.selectNodes(n.getChildrenDisplay(),
FileAnnotationData.class);
}
}
/**
* Builds the top nodes of the tree.
*
* @param exp The experimenter to attach.
* @return See above.
*/
private TreeImageDisplay buildTreeNodes(ExperimenterData exp)
{
TreeImageDisplay root = getTreeRoot();
TreeImageDisplay node = null;
switch (model.getDisplayMode()) {
case TreeViewer.GROUP_DISPLAY:
if (TreeViewerAgent.isMultiGroups()) {
GroupData group = model.getSelectedGroup();
List<TreeImageSet> nodes = createGroups(group);
Iterator<TreeImageSet> i = nodes.iterator();
TreeImageSet n;
GroupData g;
while (i.hasNext()) {
n = i.next();
g = (GroupData) n.getUserObject();
n = createGroupNode((TreeImageSet) n);
if (g.getId() == group.getId())
node = n;
}
} else {
node = createGroup(model.getSelectedGroup());
node = createGroupNode((TreeImageSet) node);
}
break;
case TreeViewer.EXPERIMENTER_DISPLAY:
default:
if (model.isSingleGroup()) {
node = root;
node = createExperimenterNode(exp, node);
} else {
if (TreeViewerAgent.isMultiGroups()) {
GroupData group = model.getSelectedGroup();
List<TreeImageSet> nodes = createGroups(group);
Iterator<TreeImageSet> i = nodes.iterator();
TreeImageSet n;
GroupData g;
while (i.hasNext()) {
n = i.next();
g = (GroupData) n.getUserObject();
n = createExperimenterNode(exp, n);
if (g.getId() == group.getId())
node = n;
}
} else {
node = createGroup(model.getSelectedGroup());
node = createExperimenterNode(exp, node);
}
}
break;
}
return node;
}
/**
* Creates the group nodes.
*
* @param defaultGroup The default group
* @return See above.
*/
private List<TreeImageSet> createGroups(GroupData defaultGroup)
{
TreeImageDisplay root = getTreeRoot();
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
//root.addChildDisplay(node);
//tm.insertNodeInto(node, root, root.getChildCount());
List<TreeImageSet> l = new ArrayList<TreeImageSet>();
List groups = sorter.sort(TreeViewerAgent.getAvailableUserGroups());
//sort the group first.
Iterator i = groups.iterator();
GroupData group;
TreeImageSet n = new TreeImageSet(defaultGroup);
TreeViewerTranslator.formatToolTipFor(n);
l.add(n);
root.addChildDisplay(n);
tm.insertNodeInto(n, root, root.getChildCount());
while (i.hasNext()) {
group = (GroupData) i.next();
if (group.getId() != defaultGroup.getId()) {
n = new TreeImageSet(group);
TreeViewerTranslator.formatToolTipFor(n);
l.add(n);
root.addChildDisplay(n);
tm.insertNodeInto(n, root, root.getChildCount());
}
}
return l;
}
/**
* Creates the group node.
*
* @param group The group to add.
* @return See above.
*/
private TreeImageSet createGroup(GroupData group)
{
TreeImageDisplay root = getTreeRoot();
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
//root.addChildDisplay(node);
//tm.insertNodeInto(node, root, root.getChildCount());
TreeImageSet n = new TreeImageSet(group);
TreeViewerTranslator.formatToolTipFor(n);
root.addChildDisplay(n);
tm.insertNodeInto(n, root, root.getChildCount());
return n;
}
/**
* Helper method to create the trees hosting the display.
*
* @param exp The logged in experimenter.
*/
private void createTrees(ExperimenterData exp)
{
treeDisplay = new DnDTree(model.getUserID(),
TreeViewerAgent.isAdministrator());
treeDisplay.addPropertyChangeListener(this);
String key = "meta pressed A";
if (UIUtilities.isWindowsOS()) key = "ctrl pressed A";
KeyStroke ks = KeyStroke.getKeyStroke(key);
treeDisplay.getInputMap().put(ks, "none");
treeDisplay.setVisible(true);
treeDisplay.setRootVisible(false);
ToolTipManager.sharedInstance().registerComponent(treeDisplay);
treeDisplay.setCellRenderer(new TreeCellRenderer(model.getUserID()));
treeDisplay.setShowsRootHandles(true);
TreeImageSet root = new TreeImageSet("");
treeDisplay.setModel(new DefaultTreeModel(root));
if (model.getBrowserType() != Browser.ADMIN_EXPLORER) {
TreeImageDisplay node = buildTreeNodes(exp);
if (node != null)
treeDisplay.collapsePath(new TreePath(node.getPath()));
}
//Add Listeners
//treeDisplay.requestFocus();
treeDisplay.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e)
{
mousePressedTime = e.getWhen();
rightClickPad = UIUtilities.isMacOS() &&
SwingUtilities.isLeftMouseButton(e) && e.isControlDown();
rightClickButton = SwingUtilities.isRightMouseButton(e);
ctrl = e.isControlDown();
if (UIUtilities.isMacOS()) ctrl = e.isMetaDown();
leftMouseButton = SwingUtilities.isLeftMouseButton(e);
if (UIUtilities.isMacOS() || UIUtilities.isLinuxOS())
onClick(e, false);
}
public void mouseReleased(MouseEvent e)
{
leftMouseButton = SwingUtilities.isLeftMouseButton(e);
if (UIUtilities.isWindowsOS()) onClick(e, true);
}
// public void mouseMoved(MouseEvent e) { rollOver(e); }
});
treeDisplay.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) { rollOver(e); }
});
treeDisplay.addTreeExpansionListener(listener);
selectionListener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e)
{
event = e;
eventHandledTime = System.currentTimeMillis();
if (delayedHandlingTreeSelection)
/* mouse click delayed handling until this event occurred */
handleTreeSelection();
switch (keyEvent) {
case KeyEvent.VK_DOWN:
case KeyEvent.VK_UP:
TreePath[] paths = treeDisplay.getSelectionPaths();
if (paths != null)
controller.onClick(Arrays.asList(paths));
else controller.onClick(new ArrayList<TreePath>());
break;
}
}
};
treeDisplay.addTreeSelectionListener(selectionListener);
//remove standard behaviour
treeDisplay.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e)
{
ctrl = false;
switch (e.getKeyCode()) {
case KeyEvent.VK_ENTER:
ViewCmd cmd = new ViewCmd(model.getParentModel(), true);
cmd.execute();
break;
case KeyEvent.VK_DELETE:
switch (model.getState()) {
case Browser.LOADING_DATA:
case Browser.LOADING_LEAVES:
//case Browser.COUNTING_ITEMS:
break;
default:
model.delete();
}
break;
case KeyEvent.VK_CONTROL:
if (!UIUtilities.isMacOS()) ctrl = true;
break;
case KeyEvent.VK_META:
if (UIUtilities.isMacOS()) ctrl = true;
break;
case KeyEvent.VK_A:
if (UIUtilities.isWindowsOS() && e.isControlDown() ||
!UIUtilities.isWindowsOS() && e.isMetaDown()) {
handleMultiSelection();
}
break;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_UP:
case KeyEvent.VK_RIGHT:
keyEvent = e.getKeyCode();
break;
case KeyEvent.VK_LEFT:
TreePath[] paths = treeDisplay.getSelectionPaths();
TreeImageDisplay node;
Object o;
for (int i = 0; i < paths.length; i++) {
o = paths[i].getLastPathComponent();
if (o instanceof TreeImageDisplay) {
node = (TreeImageDisplay) o;
if (node.isExpanded())
node.setExpanded(false);
}
}
}
}
public void keyReleased(KeyEvent e)
{
ctrl = false;
keyEvent = -1;
}
});
}
/**
* 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 nodes, DefaultTreeModel tm)
{
if (nodes.size() == 0) {
tm.insertNodeInto(new DefaultMutableTreeNode(Browser.EMPTY_MSG),
parent, parent.getChildCount());
return;
}
Iterator i = nodes.iterator();
TreeImageDisplay display;
List children;
parent.removeAllChildren();
int browserType = model.getBrowserType();
Object uo;
while (i.hasNext()) {
display = (TreeImageDisplay) i.next();
tm.insertNodeInto(display, parent, parent.getChildCount());
if (display instanceof TreeImageSet) {
children = display.getChildrenDisplay();
if (children.size() > 0) {
if (display.containsImages()) {
display.setExpanded(true);
setExpandedParent(display, false);
nodesToReset.add(display);
buildTreeNode(display,
prepareSortedList(sorter.sort(children)), tm);
expandNode(display);
tm.reload(display);
} else {
if (browserType == Browser.TAGS_EXPLORER) {
if (display.isExpanded()) {
setExpandedParent(display, false);
nodesToReset.add(display);
}
buildTreeNode(display,
prepareSortedList(sorter.sort(children)),
tm);
if (display.isExpanded()) {
expandNode(display);
tm.reload(display);
}
} else {
if (display.isExpanded()) {
setExpandedParent(display, true);
nodesToReset.add(display);
}
buildTreeNode(display,
prepareSortedList(sorter.sort(children)), tm);
}
}
} else {
uo = display.getUserObject();
if (uo instanceof DatasetData) {
tm.insertNodeInto(new DefaultMutableTreeNode(Browser.EMPTY_MSG),
display, display.getChildCount());
} else if (uo instanceof TagAnnotationData) {
TagAnnotationData tag = (TagAnnotationData) uo;
if (!(TagAnnotationData.INSIGHT_TAGSET_NS.equals(
tag.getNameSpace()))) {
tm.insertNodeInto(
new DefaultMutableTreeNode(Browser.EMPTY_MSG),
display, display.getChildCount());
}
} else if (uo instanceof GroupData) {
tm.insertNodeInto(new DefaultMutableTreeNode(Browser.EMPTY_MSG),
display, display.getChildCount());
} else if (uo instanceof FileAnnotationData) {
if (browserType == Browser.SCREENS_EXPLORER) {
TreeImageSet n = new TreeImageSet(uo);
tm.insertNodeInto(
new DefaultMutableTreeNode(Browser.EMPTY_MSG),
n, n.getChildCount());
}
}
}
}
}
if (parent.isExpanded()) {
expandNode(parent);
tm.reload(parent);
}
}
/**
* Sets the value of the <code>expanded</code> flag for the parent of
* the specified node.
*
* @param n The node to handle.
* @param b The value to set.
*/
private void setExpandedParent(TreeImageDisplay n, boolean b)
{
TreeImageDisplay p = n.getParentDisplay();
if (p != null) {
p.setExpanded(b);
setExpandedParent(p, b);
}
}
/**
* Adds a dummy node to the specified node.
*
* @param node The parent node.
*/
private void buildEmptyNode(DefaultMutableTreeNode node)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
tm.insertNodeInto(new DefaultMutableTreeNode(Browser.EMPTY_MSG), node,
node.getChildCount());
}
/**
* Creates the smart folders added to the passed node.
*
* @param parent The parent of the smart folder.
*/
private void buildOrphanImagesNode(TreeImageDisplay parent)
{
Registry reg = TreeViewerAgent.getRegistry();
//First check if we had the orphaned images node
Boolean value = Boolean.parseBoolean((String) reg.lookup(
LookupNames.ORPHANED_IMAGE_ENABLED));
if (value != null && !value.booleanValue()) {
boolean enabled = false;
if (TreeViewerAgent.isAdministrator()) {
enabled = true;
} else {
//check group owner.
long expID = TreeViewerAgent.getUserDetails().getId();
if (expID == parent.getUserObjectId()) {
enabled = true;
} else {
TreeImageDisplay node = parent.getParentDisplay();
long id = -1;
if (node != null) {
id = node.getUserObjectId();
if (id == -1) { //only in one group
id = TreeViewerAgent.getUserDetails().getGroupId();
}
}
Set leaders = TreeViewerAgent.getGroupsLeaderOf();
if (CollectionUtils.isNotEmpty(leaders)) {
Iterator i = leaders.iterator();
while (i.hasNext()) {
GroupData type = (GroupData) i.next();
if (id == type.getId()) {
enabled = true;
}
}
}
}
}
if (!enabled) {
return;
}
}
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
TreeFileSet node = new TreeFileSet(TreeFileSet.ORPHANED_IMAGES);
String v = (String) reg.lookup(LookupNames.ORPHANED_IMAGE_NAME);
if (CommonsLangUtils.isNotBlank(v)) {
node.setUserObject(v);
}
v = (String) reg.lookup(LookupNames.ORPHANED_IMAGE_DESCRIPTION);
if (CommonsLangUtils.isNotBlank(v)) {
node.setToolTip(v);
}
buildEmptyNode(node);
node.setNumberItems(-1);
parent.addChildDisplay(node);
tm.insertNodeInto(node, parent, parent.getChildCount());
}
/**
* Sorts the children of the passed node.
*
* @param node The node to handle.
*/
private void sortNode(TreeImageSet node)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
List children = node.getChildrenDisplay();
Iterator j;
if (node.containsImages()) {
node.removeAllChildren();
dtm.reload(node);
if (children.size() != 0) {
buildTreeNode(node, sorter.sort(children), dtm);
} else buildEmptyNode(node);
j = nodesToReset.iterator();
while (j.hasNext()) {
setExpandedParent((TreeImageDisplay) j.next(), true);
}
} else {
if (children.size() != 0) {
j = children.iterator();
while (j.hasNext())
sortNode((TreeImageSet) j.next());
} else buildEmptyNode(node);
}
}
/**
* Refreshes the passed folder node.
*
* @param node The node to refresh.
* @param elements The elements to add.
*/
private void refreshFolderNode(TreeImageSet node, Set elements)
{
node.removeAllChildren();
node.removeAllChildrenDisplay();
Iterator k = elements.iterator();
TreeImageDisplay child;
while (k.hasNext()) {
child = (TreeImageDisplay) k.next();
node.addChildDisplay(child);
}
buildTreeNode(node, sorter.sort(elements),
(DefaultTreeModel) treeDisplay.getModel());
node.setExpanded(true);
expandNode(node);
}
/**
* 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 prepareSortedList(List 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 j = sorted.iterator();
TreeImageDisplay object;
Object uo;
while (j.hasNext()) {
object = (TreeImageDisplay) j.next();
uo = object.getUserObject();
if (uo instanceof ProjectData) top.add(object);
else if (uo instanceof GroupData) top.add(object);
else if (uo instanceof ScreenData) top2.add(object);
else if (uo instanceof DatasetData) bottom.add(object);
else if (uo instanceof PlateData) bottom2.add(object);
else if (uo instanceof PlateAcquisitionData) bottom2.add(object);
else if (uo instanceof TagAnnotationData) {
if (TagAnnotationData.INSIGHT_TAGSET_NS.equals(
((TagAnnotationData) uo).getNameSpace()))
top.add(object);
else bottom.add(object);
} else if (uo instanceof File) {
File f = (File) uo;
if (f.isDirectory()) {
if (((TreeImageSet) object).isSystem())
top.add(object);
else bottom.add(object);
} else top.add(object);
} else if (uo instanceof FileData) {
FileData f = (FileData) uo;
if (f.isDirectory()) top.add(object);
else bottom.add(object);
} else if (uo instanceof ImageData)
bottom.add(object);
else if (uo instanceof ExperimenterData)
bottom.add(object);
else if (object instanceof SmartFolder ||
object instanceof TreeFileSet)
bottom2.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;
}
/**
* Refreshes the folder hosting the file.
*
* @param expNode The experimenter node to refresh.
* @param r The data to display.
*/
private void refreshFileFolder(TreeImageDisplay expNode,
Map<Integer, Set> r)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
expNode.setChildrenLoaded(Boolean.valueOf(true));
expNode.setExpanded(Boolean.valueOf(true));
if (r == null || r.size() == 0) return;
Iterator i = r.keySet().iterator();
int index;
int n = expNode.getChildCount();
TreeFileSet node;
dtm.reload();
while (i.hasNext()) {
index = (Integer) i.next();
for (int j = 0; j < n; j++) {
node = (TreeFileSet) expNode.getChildAt(j);
if (node.getType() == index)
refreshFolderNode(node, r.get(index));
}
}
setExpandedParent(expNode, true);
}
/**
* Refreshes the folder hosting the time.
*
* @param expNode The experimenter node to refresh.
* @param r The data to display.
*/
private void refreshTimeFolder(TreeImageDisplay expNode,
Map<Integer, Set> r)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
expNode.setChildrenLoaded(Boolean.TRUE);
expNode.setExpanded(true);
if (r == null || r.size() == 0) return;
Iterator i = r.keySet().iterator();
int index;
int n = expNode.getChildCount();
TreeImageTimeSet node, child;
dtm.reload();
int nodeType;
List children;
Iterator s;
while (i.hasNext()) {
index = (Integer) i.next();
for (int j = 0; j < n; j++) {
node = (TreeImageTimeSet) expNode.getChildAt(j);
nodeType = node.getType();
switch (nodeType) {
case TreeImageTimeSet.YEAR:
case TreeImageTimeSet.YEAR_BEFORE:
children = node.getChildrenDisplay();
s = children.iterator();
while (s.hasNext()) {
child = (TreeImageTimeSet) s.next();
if (child.getIndex() == index)
refreshFolderNode(child, r.get(index));
}
default:
if (node.getIndex() == index)
refreshFolderNode(node, r.get(index));
break;
}
}
}
setExpandedParent(expNode, true);
}
/**
* Creates a new instance.
* The {@link #initialize(BrowserControl, BrowserModel) initialize} method
* should be called straight after to link this View to the Controller.
*/
BrowserUI()
{
sorter = new ViewerSorter();
nodesToReset = new HashSet<TreeImageDisplay>();
listener = new TreeExpansionListener() {
public void treeCollapsed(TreeExpansionEvent e) {
onNodeNavigation((TreeImageDisplay)
e.getPath().getLastPathComponent(), false);
}
public void treeExpanded(TreeExpansionEvent e) {
onNodeNavigation((TreeImageDisplay)
e.getPath().getLastPathComponent(), true);
}
};
}
/**
* Links this View to its Controller and its Model.
*
* @param controller The Controller.
* @param model The Model.
* @param exp The experimenter the tree view is for.
*/
void initialize(BrowserControl controller, BrowserModel model,
ExperimenterData exp)
{
if (controller == null)
throw new IllegalArgumentException("Controller cannot be null");
if (model == null)
throw new IllegalArgumentException("Model cannot be null");
this.controller = controller;
this.model = model;
createMenuBars();
createTrees(exp);
buildGUI();
}
/**
* Creates a dummy loading node whose parent is the specified node.
*
* @param parent The parent node.
*/
void loadAction(TreeImageDisplay parent)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
parent.removeAllChildren();
tm.insertNodeInto(new DefaultMutableTreeNode(Browser.LOADING_MSG), parent,
parent.getChildCount());
tm.reload(parent);
}
/**
* Returns <code>true</code> if the first child of the passed node
* is one of the added element.
*
* @param parent The node to handle.
* @return See above.
*/
boolean isFirstChildMessage(TreeImageDisplay parent)
{
int n = parent.getChildCount();
if (n == 0) return true;
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) parent.getChildAt(0);
Object uo = node.getUserObject();
if (Browser.LOADING_MSG.equals(uo) || Browser.EMPTY_MSG.equals(uo))
return true;
return false;
}
/**
* Returns the tree hosting the display.
*
* @return See above.
*/
JTree getTreeDisplay() { return treeDisplay; }
/**
* Returns the root node of the tree.
*
* @return See above.
*/
TreeImageDisplay getTreeRoot()
{
if (treeDisplay == null) return null;
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
if (dtm == null) return null;
return (TreeImageDisplay) dtm.getRoot();
}
/**
* Returns the title of the Browser according to the type.
*
* @return See above.
*/
String getBrowserTitle()
{
switch (model.getBrowserType()) {
case Browser.PROJECTS_EXPLORER:
return Browser.HIERARCHY_TITLE;
case Browser.IMAGES_EXPLORER:
return Browser.IMAGES_TITLE;
case Browser.TAGS_EXPLORER:
return Browser.TAGS_TITLE;
case Browser.SCREENS_EXPLORER:
return Browser.SCREENS_TITLE;
case Browser.FILES_EXPLORER:
return Browser.FILES_TITLE;
case Browser.FILE_SYSTEM_EXPLORER:
return Browser.FILE_SYSTEM_TITLE;
case Browser.ADMIN_EXPLORER:
return Browser.ADMIN_TITLE;
}
return "";
}
/**
* Selects the specified node.
*
* @param node The node to select.
*/
void selectFoundNode(TreeImageDisplay node)
{
TreePath path = new TreePath(node.getPath());
treeDisplay.setSelectionPath(path);
TreeCellRenderer renderer = (TreeCellRenderer)
treeDisplay.getCellRenderer();
//treeDisplay.requestFocus();
renderer.getTreeCellRendererComponent(treeDisplay, node,
treeDisplay.isPathSelected(path),
false, true, 0, false);
}
/**
* Collapses the specified node. To avoid loop, we first need to
* remove the <code>TreeExpansionListener</code>.
*
* @param node The node to collapse.
*/
void collapsePath(DefaultMutableTreeNode node)
{
//First remove listener otherwise an event is fired.
treeDisplay.removeTreeExpansionListener(listener);
treeDisplay.collapsePath(new TreePath(node.getPath()));
treeDisplay.addTreeExpansionListener(listener);
}
/**
* Collapses the node when an on-going data loading is cancelled.
*
* @param node The node to collapse.
*/
void cancel(DefaultMutableTreeNode node)
{
if (node == null) return;
if (node.getChildCount() <= 1) {
if (node.getUserObject() instanceof String) {
node.removeAllChildren();
buildEmptyNode(node);
}
}
//in this order otherwise the node is not collapsed.
((DefaultTreeModel) treeDisplay.getModel()).reload(node);
collapsePath(node);
}
/**
* Update the specified set of nodes.
*
* @param nodes The collection of nodes to update.
* @param object The <code>DataObject</code> to update.
*/
void updateNodes(List nodes, DataObject object)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
Iterator i = nodes.iterator();
TreeImageDisplay node;
while (i.hasNext()) {
node = (TreeImageDisplay) i.next();
node.setUserObject(object);
dtm.nodeChanged(node);
}
}
/**
* Removes the specified set of nodes from the tree.
*
* @param nodes The collection of nodes to remove.
* @param parentDisplay The selected parent.
*/
void removeNodes(List nodes, TreeImageDisplay parentDisplay)
{
if (parentDisplay == null) parentDisplay = getTreeRoot();
Iterator i = nodes.iterator();
TreeImageDisplay node;
TreeImageDisplay parent;
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
while (i.hasNext()) {
node = (TreeImageDisplay) i.next();
parent = node.getParentDisplay();
if (parent.isChildrenLoaded()) {
parent.removeChildDisplay(node);
parent.remove(node);
dtm.reload(parent);
if (parent.equals(parentDisplay))
treeDisplay.setSelectionPath(
new TreePath(parent.getPath()));
}
}
}
/**
* Adds the newly created node to the tree.
*
* @param nodes The collection of the parent nodes.
* @param newNode The node to add to the parent.
* @param parentDisplay The selected parent.
*/
void createNodes(List nodes, TreeImageDisplay newNode,
TreeImageDisplay parentDisplay)
{
if (parentDisplay == null) parentDisplay = getTreeRoot();
Iterator i = nodes.iterator();
TreeImageDisplay parent;
List list;
Iterator j;
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
//buildEmptyNode(newNode);
boolean toLoad = false;
TreeImageDisplay n;
while (i.hasNext()) {
parent = (TreeImageDisplay) i.next();
//problem will come when we have images
if (parent.isChildrenLoaded()) {
parent.addChildDisplay(newNode);
list = prepareSortedList(
sorter.sort(parent.getChildrenDisplay()));
parent.removeAllChildren();
j = list.iterator();
while (j.hasNext()) {
n = (TreeImageDisplay) j.next();
if (!n.isChildrenLoaded()) {
n.removeAllChildren();
buildEmptyNode(n);
}
dtm.insertNodeInto(n, parent, parent.getChildCount());
}
dtm.reload(parent);
expandNode(parent);
if (parent.equals(parentDisplay))
treeDisplay.setSelectionPath(
new TreePath(newNode.getPath()));
} else { //Only the currently selected one will be loaded.
if (parent.equals(parentDisplay)) toLoad = true;
}
}
//should be leaves. Need to review that code.
if (toLoad) { //TO BE MODIFIED
//if (parentDisplay.getParentDisplay() == null) //root
// controller.loadData();
//else controller.loadLeaves();
}
}
/**
* Sorts the nodes in the tree view according to the specified index.
*
* @param type One out of the following constants:
* {@link Browser#SORT_NODES_BY_DATE} or
* {@link Browser#SORT_NODES_BY_NAME}.
*/
void sortNodes(int type)
{
boolean b = type == Browser.SORT_NODES_BY_DATE;
sorter.setByDate(b);
sorter.setAscending(!b);
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
TreeImageDisplay root = (TreeImageDisplay) dtm.getRoot();
int n = root.getChildCount();
TreeImageDisplay node;
List children;
Iterator j;
List all;
switch (model.getBrowserType()) {
case Browser.IMAGES_EXPLORER:
case Browser.FILES_EXPLORER:
for (int i = 0; i < n; i++) {
node = (TreeImageDisplay) root.getChildAt(i);
children = node.getChildrenDisplay();
j = children.iterator();
TreeImageDisplay child;
while (j.hasNext()) {
child = (TreeImageDisplay) j.next();
if (child instanceof TreeImageTimeSet ||
child instanceof TreeFileSet)
sortNode((TreeImageSet) child);
}
}
break;
case Browser.ADMIN_EXPLORER:
for (int i = 0; i < n; i++) {
node = (TreeImageDisplay) root.getChildAt(i);
children = node.getChildrenDisplay();
node.removeAllChildren();
dtm.reload(node);
if (!children.isEmpty()) {
if (node.getUserObject() instanceof GroupData) {
all = prepareSortedList(sorter.sort(children));
buildTreeNode(node, all, dtm);
} else {
buildTreeNode(node, sorter.sort(children), dtm);
}
} else buildEmptyNode(node);
j = nodesToReset.iterator();
while (j.hasNext()) {
setExpandedParent((TreeImageDisplay) j.next(), true);
}
}
break;
default:
for (int i = 0; i < n; i++) {
node = (TreeImageDisplay) root.getChildAt(i);
children = node.getChildrenDisplay();
node.removeAllChildren();
dtm.reload(node);
if (!children.isEmpty()) {
if (node.getUserObject() instanceof ExperimenterData) {
List<Object> sets = new ArrayList<Object>();
List<Object> toSort = new ArrayList<Object>();
Iterator k = children.iterator();
while (k.hasNext()) {
Object object = (Object) k.next();
if (object instanceof TreeFileSet) {
sets.add((TreeFileSet) object);
} else toSort.add(object);
}
sets.addAll(sorter.sort(toSort));
Collections.reverse(sets);
all = prepareSortedList(sets);
buildTreeNode(node, all, dtm);
} else {
buildTreeNode(node, sorter.sort(children), dtm);
}
} else buildEmptyNode(node);
j = nodesToReset.iterator();
while (j.hasNext()) {
setExpandedParent((TreeImageDisplay) j.next(), true);
}
}
}
}
/**
* Reacts to state change.
*
* @param b Pass <code>true</code> to enable the trees, <code>false</code>
* otherwise.
*/
void onStateChanged(boolean b)
{
model.getParentModel().onComponentStateChange(b);
}
/**
* Enables the components composing the display depending on the specified
* parameter.
*
* @param b Pass <code>true</code> to enable the component,
* <code>false</code> otherwise.
*/
void onComponentStateChange(boolean b)
{
treeDisplay.setEnabled(b);
}
/** Resets the UI so that we have no node selected in trees. */
void setNullSelectedNode()
{
if (getTreeRoot() != null) {
treeDisplay.setSelectionRow(-1);
}
}
/**
* Returns <code>true</code> if the partial name is displayed,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean isPartialName() { return !partialButton.isSelected(); }
/**
* Removes the collection of <code>TreePath</code>s from the main tree.
* We first need to remove the <code>TreeSelectionListener</code> to avoid
* loop.
*
* @param paths Collection of paths to be removed.
*/
void removeTreePaths(List paths)
{
//treeDisplay.removeTreeSelectionListener(selectionListener);
Iterator j = paths.iterator();
while (j.hasNext())
treeDisplay.removeSelectionPath((TreePath) j.next());
//treeDisplay.addTreeSelectionListener(selectionListener);
}
/**
* Adds the experimenter's data to the passed node.
*
* @param nodes The data to add.
* @param expNode The selected experimenter node.
*/
void setExperimenterData(Set nodes, TreeImageDisplay expNode)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
expNode.removeAllChildren();
expNode.removeAllChildrenDisplay();
expNode.setChildrenLoaded(Boolean.valueOf(true));
dtm.reload(expNode);
Iterator i;
if (nodes.size() > 0) {
boolean createFolder = true;
i = nodes.iterator();
TreeImageDisplay node;
TreeFileSet n = null;
Set<TreeImageDisplay> toKeep = new HashSet<TreeImageDisplay>();
int type;
while (i.hasNext()) {
node = (TreeImageDisplay) i.next();
if (node instanceof TreeFileSet) {
type = ((TreeFileSet) node).getType();
if (type == TreeFileSet.TAG ||
type == TreeFileSet.ORPHANED_IMAGES) {
List l = node.getChildrenDisplay();
if (l.size() > 0) {
createFolder = false;
n = (TreeFileSet) node.copy();
n.setChildrenLoaded(Boolean.valueOf(true));
expNode.addChildDisplay(n);
expandNode(n);
}
} else {
toKeep.add(node);
expNode.addChildDisplay(node);
}
} else {
toKeep.add(node);
expNode.addChildDisplay(node);
}
}
List sorted = prepareSortedList(sorter.sort(toKeep));
if (n != null) sorted.add(n);
buildTreeNode(expNode, sorted,
(DefaultTreeModel) treeDisplay.getModel());
if (createFolder) {
switch (model.getBrowserType()) {
case Browser.TAGS_EXPLORER:
if (n == null)
createTagsElements(expNode);
break;
case Browser.PROJECTS_EXPLORER:
buildOrphanImagesNode(expNode);
}
}
} else {
switch (model.getBrowserType()) {
case Browser.TAGS_EXPLORER:
createTagsElements(expNode);
break;
case Browser.PROJECTS_EXPLORER:
buildOrphanImagesNode(expNode);
break;
default:
expNode.setExpanded(false);
buildEmptyNode(expNode);
}
}
//
i = nodesToReset.iterator();
while (i.hasNext())
setExpandedParent((TreeImageDisplay) i.next(), true);
TreeImageDisplay root = getTreeRoot();
TreeImageDisplay element, child;
Object ho;
List children;
for (int j = 0; j < root.getChildCount(); j++) {
element = (TreeImageDisplay) root.getChildAt(j);
ho = element.getUserObject();
if (ho instanceof GroupData && element.isExpanded()) {
expandNode(element);
children = element.getChildrenDisplay();
if (children != null) {
i = children.iterator();
while (i.hasNext()) {
child = (TreeImageDisplay) i.next();
if (child.isExpanded())
expandNode(child);
}
}
}
}
}
/**
* Sets the nodes hosting the groups to manage.
*
* @param nodes The nodes to display
* @param expanded The list of nodes previously expanded.
*/
void setGroups(Set nodes, List expanded)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
TreeImageDisplay root = getTreeRoot();
root.removeAllChildren();
root.removeAllChildrenDisplay();
root.setChildrenLoaded(Boolean.valueOf(true));
root.setExpanded(true);
dtm.reload();
if (nodes.size() != 0) {
Iterator i = nodes.iterator();
while (i.hasNext()) {
root.addChildDisplay((TreeImageDisplay) i.next());
}
buildTreeNode(root, prepareSortedList(sorter.sort(nodes)), dtm);
i = nodes.iterator();
while (i.hasNext()) {
((TreeImageDisplay) i.next()).setExpanded(false);
}
if (expanded != null && expanded.size() > 0) {
i = nodes.iterator();
TreeImageDisplay display;
GroupData group;
Object ho;
Set l;
GroupData g;
while (i.hasNext()) {
display = (TreeImageDisplay) i.next();
ho = display.getUserObject();
if (ho instanceof GroupData) {
g = (GroupData) ho;
if (expanded.contains(g.getId())) {
expandNode(display);
}
}
}
}
}
if (TreeViewerAgent.isAdministrator()) {
SmartFolder folder = new SmartFolder(GroupData.class,
"Experimenters w/o groups");
buildEmptyNode(folder);
//root.addChildDisplay(folder);
//dtm.insertNodeInto(folder, root, root.getChildCount());
}
}
/**
* Sets the number of items imported during a period of time.
*
* @param expNode The node hosting the experimenter.
* @param index The index of the time node.
* @param value The value to set.
*/
void setCountValues(TreeImageDisplay expNode, int index, Object value)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
if (model.getBrowserType() != Browser.TAGS_EXPLORER)
expNode.setChildrenLoaded(Boolean.valueOf(true));
int n = expNode.getChildCount();
TreeImageSet node;
List l;
Iterator i, k;
TreeImageTimeSet child;
//Test
List<TreeImageSet> toRemove = new ArrayList<TreeImageSet>();
List<TreeImageSet> toKeep = new ArrayList<TreeImageSet>();
int number;
int total;
DefaultMutableTreeNode childNode;
List<DefaultMutableTreeNode> remove =
new ArrayList<DefaultMutableTreeNode>();
for (int j = 0; j < n; j++) {
childNode = (DefaultMutableTreeNode) expNode.getChildAt(j);
Object o = childNode.getUserObject();
if (o instanceof String) {
String s = (String) o;
if (Browser.EMPTY_MSG.equals(s)) {
remove.add(childNode);
}
}
if (childNode instanceof TreeImageTimeSet) {
node = (TreeImageTimeSet) childNode;
if (((TreeImageTimeSet) node).getType() == index) {
if (value instanceof Integer) {
//Check if the number is 0
int vv = ((Integer) value).intValue();
long v = node.getNumberItems();
node.setNumberItems(vv);
if (v == 0 && vv > 0) {
buildEmptyNode(node);
node.setChildrenLoaded(Boolean.valueOf(false));
}
} else if (value instanceof List) {
l = (List) value;
total = 0;
i = node.getChildrenDisplay().iterator();
while (i.hasNext()) {
child = (TreeImageTimeSet) i.next();
number = child.countTime(l);
total += number;
if (number > 0) {
child.setNumberItems(number);
toKeep.add(child);
} else {
toRemove.add(child);
}
}
node.removeAllChildren();
node.removeChildrenDisplay(toRemove);
node.setNumberItems(total);
k = toKeep.iterator();
while (k.hasNext()) {
dtm.insertNodeInto((TreeImageTimeSet) k.next(), node,
node.getChildCount());
}
}
dtm.reload(node);
}
} else if (childNode instanceof TreeFileSet) {
node = (TreeFileSet) childNode;
if (((TreeFileSet) node).getType() == index) {
if (value instanceof Long)
node.setNumberItems((Long) value);
}
}
}
if (remove.size() > 0) {
Iterator<DefaultMutableTreeNode> j = remove.iterator();
while (j.hasNext()) {
expNode.remove(j.next());
dtm.reload(expNode);
}
}
}
/**
* Refreshes the folder hosting the files and the times.
*
* @param expNode The experimenter node to refresh.
* @param r The data to display.
*/
void refreshFolder(TreeImageDisplay expNode, Map<Integer, Set> r)
{
int browseType = model.getBrowserType();
if (browseType == Browser.IMAGES_EXPLORER)
refreshTimeFolder(expNode, r);
else if (browseType == Browser.FILES_EXPLORER)
refreshFileFolder(expNode, r);
}
/**
* Adds the specifies nodes to the currently selected
* {@link TreeImageDisplay}.
*
* @param nodes The collection of nodes to add.
* @param parent The parent of the nodes.
*/
void setLeavesViews(Collection nodes, TreeImageSet parent)
{
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
parent.removeAllChildren();
parent.removeAllChildrenDisplay();
parent.setChildrenLoaded(Boolean.TRUE);
if (nodes.size() != 0) {
Iterator i = nodes.iterator();
while (i.hasNext())
parent.addChildDisplay((TreeImageDisplay) i.next()) ;
buildTreeNode(parent, sorter.sort(nodes), dtm);
} else buildEmptyNode(parent);
dtm.reload(parent);
if (!isPartialName()) {
model.component.accept(new PartialNameVisitor(isPartialName()),
TreeImageDisplayVisitor.TREEIMAGE_NODE_ONLY);
}
}
/**
* Adds a new experimenter to the tree.
*
* @param experimenter The experimenter to add.
* @param groupNode The node to add the experimenter to.
*/
void addExperimenter(ExperimenterData experimenter,
TreeImageDisplay groupNode)
{
TreeImageSet node = createExperimenterNode(experimenter, groupNode);
}
/**
* Removes the specified experimenter from the tree.
*
* @param exp The experimenter data to remove.
* @param refNode The node to remove the experimenter from.
*/
void removeExperimenter(ExperimenterData exp, TreeImageDisplay refNode)
{
if (model.getBrowserType() == Browser.ADMIN_EXPLORER) return;
if (refNode == null) refNode = getTreeRoot();
List<TreeImageDisplay> nodesToKeep;
List l = refNode.getChildrenDisplay();
if (l == null || l.size() == 0) return;
Iterator j = l.iterator();
TreeImageDisplay element, node;
Object ho;
ExperimenterData expElement;
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
Iterator k;
node = null;
nodesToKeep = new ArrayList<TreeImageDisplay>();
List<TreeImageDisplay> toExpand = new ArrayList<TreeImageDisplay>();
while (j.hasNext()) {
element = (TreeImageDisplay) j.next();
ho = element.getUserObject();
if (ho instanceof ExperimenterData) {
expElement = (ExperimenterData) ho;
if (expElement.getId() == exp.getId())
node = element;
else {
nodesToKeep.add(element);
if (element.isExpanded())
toExpand.add(element);
}
}
}
if (node != null) refNode.removeChildDisplay(node);
k = nodesToKeep.iterator();
refNode.removeAllChildren();
while (k.hasNext()) {
tm.insertNodeInto((TreeImageSet) k.next(), refNode,
refNode.getChildCount());
}
tm.reload(refNode);
k = toExpand.iterator();
while (k.hasNext()) {
expandNode((TreeImageSet) k.next(), false);
}
}
/**
* Removes the specified group from the tree.
*
* @param group The data to remove.
*/
void removeGroup(GroupData group)
{
if (model.getBrowserType() == Browser.ADMIN_EXPLORER) return;
TreeImageDisplay root = getTreeRoot();
List<TreeImageDisplay> nodesToKeep;
List l = root.getChildrenDisplay();
if (l == null || l.size() == 0) return;
Iterator j = l.iterator();
TreeImageDisplay element, n, node;
Object ho;
ExperimenterData expElement;
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
Iterator k;
GroupData g;
nodesToKeep = new ArrayList<TreeImageDisplay>();
node = null;
while (j.hasNext()) {
element = (TreeImageDisplay) j.next();
if (element.getUserObject() instanceof GroupData) {
g = (GroupData) element.getUserObject();
if (g.getId() == group.getId()) node = element;
else nodesToKeep.add(element);
}
}
if (node != null) root.removeChildDisplay(node);
k = nodesToKeep.iterator();
root.removeAllChildren();
while (k.hasNext()) {
tm.insertNodeInto((TreeImageSet) k.next(), root,
root.getChildCount());
}
tm.reload();
}
/** Reactivates the tree. */
void reActivate()
{
clear();
treeDisplay.reset(model.getUserID(),
TreeViewerAgent.isAdministrator());
TreeCellRenderer renderer = (TreeCellRenderer)
treeDisplay.getCellRenderer();
renderer.reset(model.getUserID());
if (model.getBrowserType() != Browser.ADMIN_EXPLORER) {
ExperimenterData exp = model.getUserDetails();
TreeImageDisplay node = buildTreeNodes(exp);
if (model.isSelected() && node != null) {
expandNode(node, true);
}
}
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
tm.reload();
}
/** Clear the tree.*/
void clear()
{
TreeImageDisplay root = getTreeRoot();
root.removeAllChildren();
root.removeAllChildrenDisplay();
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
tm.reload();
}
/**
* Sets the nodes selecting via other views.
*
* @param newSelection The collection of nodes to select.
*/
void setFoundNode(TreeImageDisplay[] newSelection)
{
if (newSelection == null) {
model.setSelectedDisplay(null, true);
treeDisplay.clearSelection();
controller.getAction(BrowserControl.DELETE).setEnabled(false);
} else {
TreePath[] paths = new TreePath[newSelection.length];
for (int i = 0; i < newSelection.length; i++) {
paths[i] = new TreePath(newSelection[i].getPath());
}
treeDisplay.setSelectionPaths(paths);
}
treeDisplay.repaint();
}
/**
* Loads the files contained in the passed folder.
*
* @param display The directory.
*/
void loadFile(TreeImageDisplay display)
{
//if ((uo instanceof File) && (display instanceof TreeImageSet)) {
display.removeAllChildren();
display.removeAllChildrenDisplay();
display.setChildrenLoaded(Boolean.TRUE);
display.setExpanded(true);
transformDirectory((TreeImageSet) display);
buildTreeNode(display, prepareSortedList(sorter.sort(
display.getChildrenDisplay())),
(DefaultTreeModel) treeDisplay.getModel());
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
tm.reload(display);
//model.fireFilesCheck(leaves);
}
/**
* Loads the file system.
*
* @param refresh Pass <code>true</code> to rebuild the file system view.
* <code>false</code> otherwise.
*/
void loadFileSystem(TreeImageDisplay expNode)
{
if (model.getBrowserType() != Browser.FILE_SYSTEM_EXPLORER)
return;
setExperimenterData(createFileSystemExplorer(expNode), expNode);
}
/**
* Reloads the specified node.
*
* @param node The node to reload.
*/
void reloadContainer(TreeImageDisplay node)
{
if (node == null) return;
node.removeAllChildren();
node.removeAllChildrenDisplay();
node.setChildrenLoaded(Boolean.FALSE);
buildEmptyNode(node);
treeDisplay.collapsePath(new TreePath(node.getPath()));
treeDisplay.expandPath(new TreePath(node.getPath()));
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
tm.reload(node);
}
/**
* Reloads the specified node.
*
* @param node The node to reload.
*/
void reloadNode(TreeImageDisplay node)
{
DefaultTreeModel tm = (DefaultTreeModel) treeDisplay.getModel();
if (node == null) tm.reload();
else tm.reload(node);
}
/**
* Expands the specified node. To avoid loop, we first need to
* remove the <code>TreeExpansionListener</code>.
*
* @param node The node to expand.
*/
void expandNode(TreeImageDisplay node, boolean withListener)
{
//First remove listener otherwise an event is fired.
if (node == null) return;
node.setExpanded(true);
if (withListener) {
treeDisplay.expandPath(new TreePath(node.getPath()));
} else {
treeDisplay.removeTreeExpansionListener(listener);
treeDisplay.expandPath(new TreePath(node.getPath()));
treeDisplay.addTreeExpansionListener(listener);
}
}
/**
* Expands the specified node. To avoid loop, we first need to
* remove the <code>TreeExpansionListener</code>.
*
* @param node The node to expand.
*/
void expandNode(TreeImageDisplay node)
{
expandNode(node, false);
}
/**
* Adds the component under the tree.
*
* @param component The component to add.
*/
void addComponent(JComponent component)
{
if (bottomComponent != null) remove(bottomComponent);
bottomComponent = component;
if (component != null) add(bottomComponent, BorderLayout.SOUTH);
revalidate();
repaint();
}
/**
* Adds the specified groups to the tree.
*
* @param group The group to add.
*/
void setUserGroup(List<GroupData> groups)
{
if (groups == null || groups.size() == 0) return;
ExperimenterData exp = model.getUserDetails();
TreeImageSet node;
Iterator<GroupData> i = groups.iterator();
while (i.hasNext()) {
node = createGroup(i.next());
node = createExperimenterNode(exp, node);
}
DefaultTreeModel dtm = (DefaultTreeModel) treeDisplay.getModel();
dtm.reload();
}
/**
* Reacts to the D&D properties.
* @see PropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt)
{
String name = evt.getPropertyName();
if (DnDTree.DRAGGED_PROPERTY.equals(name)) {
ObjectToTransfer transfer = (ObjectToTransfer) evt.getNewValue();
int action = TreeViewer.CUT_AND_PASTE;
if (transfer.getDropAction() == DnDConstants.ACTION_COPY)
action = TreeViewer.COPY_AND_PASTE;
//check the node
model.transfer(transfer.getTarget(), transfer.getNodes(),
action);
}
}
}