org.orbisgis.sif.components.fstree.FileTree.java Source code

Java tutorial

Introduction

Here is the source code for org.orbisgis.sif.components.fstree.FileTree.java

Source

/**
 * 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-2016 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;
        }
    }
}