blob: 5b034ad1673193cb0a73b11d6acb74f47a4db028 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.reference.ui.tree;
import static javax.swing.SwingUtilities.invokeLater;
import static javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.Autoscroll;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.apache.log4j.Logger;
/**
* A wrapper around JTree that installs the set of models, renderers and
* listeners used by the pre-registration tree control. Implements autoscroll
* and zooms to any new nodes when added. Handles drop of URLs (from e.g.
* FireFox), File structures and plain text by creating corresponding POJOs.
*
* @author Tom Oinn
*/
public class PreRegistrationTree extends JTree implements Autoscroll {
private static final long serialVersionUID = -8357524058131749686L;
private static Logger logger = Logger.getLogger(PreRegistrationTree.class);
private PreRegistrationTreeModel model;
private int margin = 15;
/**
* Get the PreRegistrationTreeModel for this tree. Used to get the contents
* of the tree as a POJO which can then be registered with the
* ReferenceService
*
* @return a POJO containing the contents of the tree.
*/
public PreRegistrationTreeModel getPreRegistrationTreeModel() {
return this.model;
}
/**
* Override this to be informed of status messages from the tree
*/
public void setStatusMessage(String message, boolean isError) {
//
}
/**
* Construct with the depth of the collection to be assembled. This will
* instantiate an appropriate internal model and set all the drag and drop
* handlers, renderers and cell editing components.
*
* @param depth
* the collection depth to use, 0 for single items, 1 for lists
* and so on.
*/
public PreRegistrationTree(int depth) {
this(depth, null);
}
/**
* Construct with the depth of the collection to be assembled. This will
* instantiate an appropriate internal model and set all the drag and drop
* handlers, renderers and cell editing components.
*
* @param depth
* the collection depth to use, 0 for single items, 1 for lists
* and so on.
* @param name Name of the top root of the tree (typically the port name)
*/
public PreRegistrationTree(int depth, String name) {
if (name == null)
model = new PreRegistrationTreeModel(depth);
else
model = new PreRegistrationTreeModel(depth, name);
setModel(model);
setInvokesStopCellEditing(true);
getSelectionModel().setSelectionMode(SINGLE_TREE_SELECTION);
DefaultTreeCellRenderer renderer = new PreRegistrationTreeCellRenderer();
setRowHeight(0);
setCellRenderer(renderer);
new PreRegistrationTreeDnDHandler(this) {
@Override
public void handleNodeMove(MutableTreeNode source,
MutableTreeNode target) {
model.moveNode(source, target);
}
@Override
public void handleFileDrop(MutableTreeNode target,
List<File> fileList) {
for (File f : fileList) {
if (f.isDirectory() == false) {
model.addPojoStructure(target, target, f, 0);
continue;
}
if (model.getDepth() < 1) {
setStatusMessage(
"Can't add directory to single item input",
true);
return;
}
/*
* Try to handle directories as flat lists, don't nest any
* deeper for now.
*/
List<File> children = new ArrayList<>();
for (File child : f.listFiles())
if (child.isFile())
children.add(child);
model.addPojoStructure(target, target, children, 1);
}
}
@Override
public void handleUrlDrop(MutableTreeNode target, URL url) {
if (url.getProtocol().equalsIgnoreCase("http")) {
model.addPojoStructure(target, target, url, 0);
setStatusMessage("Added URL : " + url.toExternalForm(),
false);
} else
setStatusMessage("Only http URLs are supported for now.",
true);
}
@Override
public void handleStringDrop(MutableTreeNode target, String string) {
model.addPojoStructure(target, target, string, 0);
setStatusMessage("Added string from drag and drop", false);
}
};
}
@Override
public void setModel(TreeModel model) {
if (treeModel == model)
return;
if (treeModelListener == null)
treeModelListener = new TreeModelHandler() {
@Override
public void treeNodesInserted(final TreeModelEvent ev) {
invokeLater(new Runnable() {
@Override
public void run() {
TreePath path = ev.getTreePath();
setExpandedState(path, true);
fireTreeExpanded(path);
}
});
}
};
if (model != null)
model.addTreeModelListener(treeModelListener);
TreeModel oldValue = treeModel;
treeModel = model;
firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);
}
@Override
public void autoscroll(Point p) {
int realrow = getRowForLocation(p.x, p.y);
Rectangle outer = getBounds();
realrow = (p.y + outer.y <= margin ? realrow < 1 ? 0 : realrow - 1
: realrow < getRowCount() - 1 ? realrow + 1 : realrow);
scrollRowToVisible(realrow);
}
@Override
public Insets getAutoscrollInsets() {
Rectangle outer = getBounds();
Rectangle inner = getParent().getBounds();
return new Insets(inner.y - outer.y + margin, inner.x - outer.x
+ margin, outer.height - inner.height - inner.y + outer.y
+ margin, outer.width - inner.width - inner.x + outer.x
+ margin);
}
@Override
public int getRowCount() {
int result = super.getRowCount();
logger.info("Row count is " + result);
return result;
}
}