/** * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * * Copyright 2012-2015 the original author or authors. */ package org.assertj.swing.test.swing; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; /** * <p> * {@code JTree} that requires a name and supports drag and drop. * </p> * * <p> * Adapted from the tutorial <a href="http://java.sun.com/docs/books/tutorial/uiswing/dnd/intro.html" * target="_blank">Introduction to Drag and Drop and Data Transfer</a>. * </p> * * @author Alex Ruiz */ public final class TestTree extends JTree { public TestTree(String name) { this(name, null); } public TestTree(TreeModel model) { this(null, model); } public TestTree(String name, TreeModel model) { setDragEnabled(true); setModel(model); setName(name); setTransferHandler(new TreeTransferHandler()); } private static class TreeTransferHandler extends StringTransferHandler<JTree> { TreeTransferHandler() { super(JTree.class); } @Override protected String exportString(JTree tree) { rows = tree.getSelectionRows(); StringBuilder b = new StringBuilder(); for (int i = 0; i < rows.length; i++) { TreePath path = tree.getPathForRow(rows[i]); Object val = path.getLastPathComponent(); b.append(val == null ? "" : val.toString()); if (i != rows.length - 1) { b.append("\n"); } } return b.toString(); } @Override protected void importString(JTree target, String s) { DefaultTreeModel model = (DefaultTreeModel) target.getModel(); int index = target.getRowForPath(target.getSelectionPath()); // Prevent the user from dropping data back on itself. if (rows != null && index >= rows[0] - 1 && index <= rows[rows.length - 1]) { rows = null; return; } int max = target.getRowCount(); if (index < 0) { index = max; } else if (index > max) { index = max; } addIndex = index; String[] values = s.split("\n"); addCount = values.length; for (String value : values) { TreePath path = target.getPathForRow(index++); model.insertNodeInto(new DefaultMutableTreeNode(value), (MutableTreeNode) path.getLastPathComponent(), 0); } } // not working perfectly right, but good enough for testing. @Override protected void cleanup(JTree source, boolean remove) { if (remove && rows != null) { DefaultTreeModel model = (DefaultTreeModel) source.getModel(); // If we are moving items around in the same table, we need to adjust the rows accordingly, since those after // the // insertion point have moved. if (addCount > 0) { for (int i = 0; i < rows.length; i++) { if (rows[i] > addIndex) { rows[i] += addCount; } } } for (int i = rows.length - 1; i >= 0; i--) { TreePath path = source.getPathForRow(rows[i]); if (path == null) { continue; } model.removeNodeFromParent((MutableTreeNode) path.getLastPathComponent()); } } } } }