/* * JAME 6.2.1 * http://jame.sourceforge.net * * Copyright 2001, 2016 Andrea Medeghini * * This file is part of JAME. * * JAME is an application for creating fractals and other graphics artifacts. * * JAME 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 3 of the License, or * (at your option) any later version. * * JAME 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 JAME. If not, see <http://www.gnu.org/licenses/>. * */ package net.sf.jame.core.swing; import java.awt.Cursor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.io.IOException; import java.util.logging.Logger; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import net.sf.jame.core.swing.util.GUIFactory; import net.sf.jame.core.swing.util.GUIUtil; import net.sf.jame.core.swing.util.MutableTreeNodeAdapter; import net.sf.jame.core.tree.Node; import net.sf.jame.core.tree.NodeEditor; import net.sf.jame.core.tree.NodeEvent; import net.sf.jame.core.tree.NodeListener; import net.sf.jame.core.tree.NodePath; import net.sf.jame.core.tree.RootNode; import net.sf.jame.core.tree.TransferableNodeValue; /** * @author Andrea Medeghini */ public class NavigatorTree extends JTree implements NodeListener, DropTargetListener, DragGestureListener, DragSourceListener { private static final Logger logger = Logger.getLogger(NavigatorTree.class.getName()); private static final long serialVersionUID = 1L; /** * Constructs a new adapter. * * @param RootNode the root node. */ public NavigatorTree(final RootNode rootNode) { setCellRenderer(new SimpleTreeCellRenderer()); final MutableTreeNodeAdapter root = new MutableTreeNodeAdapter(rootNode); final DefaultTreeModel model = new DefaultTreeModel(root); setModel(model); if (DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this) != null) { setDropTarget(new DropTarget(this, this)); } rootNode.addNodeListener(this); setFont(GUIFactory.NORMAL_FONT); } /** * @param path * @return the path. */ public TreePath creareTreePath(final NodePath path) { final Integer[] elements = path.getPathElements(); final Object[] nodePath = new Object[elements.length + 1]; nodePath[0] = getModel().getRoot(); Object node = getModel().getRoot(); for (int i = 0; i < elements.length; i++) { nodePath[i + 1] = getModel().getChild(node, elements[i]); node = nodePath[i + 1]; } if (nodePath.length > 0) { return new TreePath(nodePath); } else { return new TreePath(getModel().getRoot()); } } private void expandNode(final DefaultMutableTreeNode node) { if (node.getParent() != null) { expandPath(new TreePath(((DefaultMutableTreeNode) node.getParent()).getPath())); } if (node.getChildCount() > 0) { for (int i = 0; i < node.getChildCount(); i++) { expandNode((DefaultMutableTreeNode) node.getChildAt(i)); } } } /** * @see net.sf.jame.core.tree.NodeListener#nodeChanged(net.sf.jame.core.tree.NodeEvent) */ public void nodeChanged(final NodeEvent e) { GUIUtil.executeTask(new Runnable() { public void run() { final TreePath path = creareTreePath(e.getPath()); getModel().valueForPathChanged(path, e.getNode()); } }, true); } /** * @see net.sf.jame.core.tree.NodeListener#nodeAdded(net.sf.jame.core.tree.NodeEvent) */ public void nodeAdded(final NodeEvent e) { GUIUtil.executeTask(new Runnable() { public void run() { final Integer[] nodePath = e.getPath().getPathElements(); final Integer[] parentPath = new Integer[nodePath.length - 1]; System.arraycopy(nodePath, 0, parentPath, 0, parentPath.length); final TreePath path = creareTreePath(new NodePath(parentPath)); ((DefaultTreeModel) getModel()).insertNodeInto(new MutableTreeNodeAdapter(e.getNode()), (DefaultMutableTreeNode) path.getLastPathComponent(), nodePath[nodePath.length - 1]); expandPath(new TreePath(((DefaultMutableTreeNode) path.getLastPathComponent()).getPath())); // expandNode((DefaultMutableTreeNode) path.getLastPathComponent()); } }, true); } /** * @see net.sf.jame.core.tree.NodeListener#nodeRemoved(net.sf.jame.core.tree.NodeEvent) */ public void nodeRemoved(final NodeEvent e) { GUIUtil.executeTask(new Runnable() { public void run() { final TreePath path = creareTreePath(e.getPath()); ((DefaultTreeModel) getModel()).removeNodeFromParent((DefaultMutableTreeNode) path.getLastPathComponent()); } }, true); } /** * @see net.sf.jame.core.tree.NodeListener#nodeAccepted(net.sf.jame.core.tree.NodeEvent) */ public void nodeAccepted(final NodeEvent e) { } /** * @see net.sf.jame.core.tree.NodeListener#nodeCancelled(net.sf.jame.core.tree.NodeEvent) */ public void nodeCancelled(final NodeEvent e) { } /** * @see java.awt.dnd.DropTargetListener#dragEnter(java.awt.dnd.DropTargetDragEvent) */ public void dragEnter(final DropTargetDragEvent dtde) { } /** * @see java.awt.dnd.DropTargetListener#dragExit(java.awt.dnd.DropTargetEvent) */ public void dragExit(final DropTargetEvent dte) { } /** * @see java.awt.dnd.DropTargetListener#dragOver(java.awt.dnd.DropTargetDragEvent) */ public void dragOver(final DropTargetDragEvent dtde) { } /** * @see java.awt.dnd.DropTargetListener#drop(java.awt.dnd.DropTargetDropEvent) */ public void drop(final DropTargetDropEvent dtde) { if (dtde.getDropAction() == DnDConstants.ACTION_MOVE) { if (dtde.isDataFlavorSupported(TransferableNodeValueAdapter.NODE_VALUE_FLAVOR)) { final Transferable transferable = dtde.getTransferable(); try { final TransferableNodeValue nodeValue = (TransferableNodeValue) transferable.getTransferData(TransferableNodeValueAdapter.NODE_VALUE_FLAVOR); final TreePath path = getPathForLocation(dtde.getLocation().x, dtde.getLocation().y); if (path != null) { final NodeEditor nodeEditor = ((Node) ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject()).getNodeEditor(); if (nodeEditor != null) { if (nodeValue.getType().isAssignableFrom(nodeEditor.getNodeValueType())) { NavigatorTree.logger.fine("Drop on node = " + nodeEditor.getNodeId()); dtde.acceptDrop(DnDConstants.ACTION_MOVE); if (nodeEditor.isNodeEditable()) { nodeEditor.setNodeValue(nodeValue.getValue()); } dtde.dropComplete(true); } else { dtde.rejectDrop(); } } else { dtde.rejectDrop(); } } } catch (final UnsupportedFlavorException e) { dtde.rejectDrop(); } catch (final IOException e) { NavigatorTree.logger.fine("Drop failed: " + e.getLocalizedMessage()); dtde.dropComplete(false); } } } else if (dtde.getDropAction() == DnDConstants.ACTION_COPY) { if (dtde.isDataFlavorSupported(TransferableNodeValueAdapter.NODE_VALUE_FLAVOR)) { final Transferable transferable = dtde.getTransferable(); try { final TransferableNodeValue nodeValue = (TransferableNodeValue) transferable.getTransferData(TransferableNodeValueAdapter.NODE_VALUE_FLAVOR); final TreePath path = getPathForLocation(dtde.getLocation().x, dtde.getLocation().y); if (path != null) { final NodeEditor nodeEditor = ((Node) ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject()).getNodeEditor(); if (nodeEditor != null) { if (nodeValue.getType().isAssignableFrom(nodeEditor.getNodeValueType())) { NavigatorTree.logger.fine("Drop on node = " + nodeEditor.getNodeId()); dtde.acceptDrop(DnDConstants.ACTION_COPY); if (nodeEditor.isNodeEditable()) { nodeEditor.setNodeValue(nodeValue.getValue()); } dtde.dropComplete(true); } else { dtde.rejectDrop(); } } else { dtde.rejectDrop(); } } } catch (final UnsupportedFlavorException e) { dtde.rejectDrop(); } catch (final IOException e) { NavigatorTree.logger.fine("Drop failed: " + e.getLocalizedMessage()); dtde.dropComplete(false); } } } else { dtde.rejectDrop(); } } /** * @see java.awt.dnd.DropTargetListener#dropActionChanged(java.awt.dnd.DropTargetDragEvent) */ public void dropActionChanged(final DropTargetDragEvent dtde) { } /** * @see java.awt.dnd.DragGestureListener#dragGestureRecognized(java.awt.dnd.DragGestureEvent) */ public void dragGestureRecognized(final DragGestureEvent dge) { if (getSelectionPath() != null) { final NodeEditor nodeEditor = ((Node) ((DefaultMutableTreeNode) getSelectionPath().getLastPathComponent()).getUserObject()).getNodeEditor(); if (nodeEditor != null) { NavigatorTree.logger.fine("Drag node = " + nodeEditor.getNodeId()); dge.startDrag(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR), new TransferableNodeValueAdapter(nodeEditor.getNodeValueAsTransferable()), this); } } } /** * @see java.awt.dnd.DragSourceListener#dragDropEnd(java.awt.dnd.DragSourceDropEvent) */ public void dragDropEnd(final DragSourceDropEvent dsde) { } /** * @see java.awt.dnd.DragSourceListener#dragEnter(java.awt.dnd.DragSourceDragEvent) */ public void dragEnter(final DragSourceDragEvent dsde) { } /** * @see java.awt.dnd.DragSourceListener#dragExit(java.awt.dnd.DragSourceEvent) */ public void dragExit(final DragSourceEvent dse) { } /** * @see java.awt.dnd.DragSourceListener#dragOver(java.awt.dnd.DragSourceDragEvent) */ public void dragOver(final DragSourceDragEvent dsde) { } /** * @see java.awt.dnd.DragSourceListener#dropActionChanged(java.awt.dnd.DragSourceDragEvent) */ public void dropActionChanged(final DragSourceDragEvent dsde) { } /** * */ public void expandAll() { GUIUtil.executeTask(new Runnable() { public void run() { expandNode((DefaultMutableTreeNode) getModel().getRoot()); } }, true); } }