/** * OrbisGIS is a java GIS application dedicated to research in GIScience. * OrbisGIS is developed by the GIS group of the DECIDE team of the * Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>. * * The GIS group of the DECIDE team is located at : * * Laboratoire Lab-STICC – CNRS UMR 6285 * Equipe DECIDE * UNIVERSITÉ DE BRETAGNE-SUD * Institut Universitaire de Technologie de Vannes * 8, Rue Montaigne - BP 561 56017 Vannes Cedex * * OrbisGIS is distributed under GPL 3 license. * * Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488) * Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285) * * This file is part of OrbisGIS. * * OrbisGIS 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. * * OrbisGIS 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 * OrbisGIS. If not, see <http://www.gnu.org/licenses/>. * * For more information, please consult: <http://www.orbisgis.org/> * or contact directly: * info_at_ orbisgis.org */ package org.orbisgis.sif.components.fstree; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.beans.EventHandler; import java.io.File; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTree; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import org.apache.commons.io.FilenameUtils; import org.xnap.commons.i18n.I18n; import org.xnap.commons.i18n.I18nFactory; /** * This JTree Can be linked with the file system thanks to the TreeNodeFolder * @author Nicolas Fortin */ public class FileTree extends JTree implements TreeNodeFileFactoryManager { private static final long serialVersionUID = 1L; private MouseListener treeMouse = EventHandler.create(MouseListener.class,this,"onMouseEvent",""); private AtomicBoolean initialized = new AtomicBoolean(false); private static final I18n I18N = I18nFactory.getI18n(FileTree.class); public FileTree(TreeModel tm) { super(tm); } public FileTree() { } @Override public void addNotify() { super.addNotify(); if(!initialized.getAndSet(true)) { setTransferHandler(new FileTreeTransferHandler()); setDragEnabled(true); setCellRenderer(new CustomTreeCellRenderer(this)); addMouseListener(treeMouse); getSelectionModel().addTreeSelectionListener( EventHandler.create(TreeSelectionListener.class, this,"onSelectionChange")); javax.swing.ToolTipManager.sharedInstance().registerComponent(this); } } /** * Called when the tree selection change. * Update the tree editable state */ public void onSelectionChange() { TreePath[] Selected = getSelectionPaths(); if(Selected!=null) { TreePath firstSelected = Selected[Selected.length-1]; Object comp = firstSelected.getLastPathComponent(); if(comp instanceof AbstractTreeNode) { if(!isEditing()) { setEditable(((AbstractTreeNode)comp).isEditable()); } } } } private boolean contains(TreePath[] selectionPaths, TreePath path) { for (TreePath treePath : selectionPaths) { Object[] objectPath = treePath.getPath(); Object[] testPath = path.getPath(); if (objectPath.length != testPath.length) { return false; } else { for (int i = 0; i < testPath.length; i++) { if (testPath[i] != objectPath[i]) { return false; } } } return true; } return false; } /** * Event on Tree, called by listener * @param evt */ public void onMouseEvent(MouseEvent evt) { if (evt.isPopupTrigger()) { //Update selection TreePath path = getPathForLocation(evt.getX(), evt.getY()); TreePath[] selectionPaths = getSelectionPaths(); if ((selectionPaths != null) && (path != null)) { if (!contains(selectionPaths, path)) { if (evt.isControlDown()) { addSelectionPath(path); } else { setSelectionPath(path); } } } else { setSelectionPath(path); } //Show popup makePopupMenu().show(evt.getComponent(), evt.getX(), evt.getY()); } } /** * The user select the menu rename */ public void onRenameItem() { TreePath[] paths = getSelectionPaths(); if(paths!=null && paths.length==1) { super.startEditingAtPath(paths[0]); } } /** * Fetch all selected items to make a pop-up menu * @return */ private JPopupMenu makePopupMenu() { JPopupMenu menu = new JPopupMenu(); TreePath[] paths = getSelectionPaths(); if(paths!=null) { // Generic action on single TreeNode if(paths.length == 1) { Object component = paths[0].getLastPathComponent(); if(component instanceof AbstractTreeNode) { AbstractTreeNode aTreeNode = (AbstractTreeNode) component; if(aTreeNode.isEditable()) { JMenuItem editMenu = new JMenuItem(I18N.tr("Rename")); editMenu.addActionListener( EventHandler.create(ActionListener.class,this,"onRenameItem")); editMenu.setActionCommand("rename"); menu.add(editMenu); } } } for(TreePath treePath : paths) { Object component = treePath.getLastPathComponent(); // All nodes if(component instanceof MutableTreeNode) { MutableTreeNode node = (MutableTreeNode)component; for(TreeNodeFileFactory fact : getFactories()) { fact.feedTreeNodePopupMenu(node, menu); } } // Specific nodes if(component instanceof PopupTreeNode) { PopupTreeNode treeNode = (PopupTreeNode) component; treeNode.feedPopupMenu(menu); } } } return menu; } // Map of extensions private Map<String,TreeNodeFileFactory> factories = new HashMap<String,TreeNodeFileFactory>(); @Override public void addFactory(String extension, TreeNodeFileFactory factory) { factories.put(extension.toLowerCase(), factory); } @Override public Collection<TreeNodeFileFactory> getFactories() { return factories.values(); } @Override public AbstractTreeNode create(File filePath) { TreeNodeFileFactory factory = factories.get(FilenameUtils.getExtension(filePath.getName()).toLowerCase()); if(factory!=null) { return factory.create(filePath); } else { return null; } } }