/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Markus Kraetzig

 This library 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 library 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 library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA
 */

package com.jstatcom.project;

import java.awt.Cursor;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

import org.apache.log4j.Logger;

import com.jstatcom.component.StdMessages;
import com.jstatcom.component.TopFrameReference;

/**
 * A JTree for project and module management. The state of the
 * tree is saved in a settings file that is loaded at program startup of the
 * TopFrame.
 * 
 * @author Markus Kraetzig 
 */
public final class ProjectTree extends JTree {
    private static final Logger log = Logger.getLogger(ProjectTree.class);

    private final static List projectList = new ArrayList();

    /**
     * Singleton instance.
     */
    private static final ProjectTree INSTANCE = new ProjectTree();

    private final DefaultMutableTreeNode ROOT = new DefaultMutableTreeNode(
            "ROOT");

    // tree model
    private final DefaultTreeModel projectTreeModel = new DefaultTreeModel(ROOT);

    /**
     * Not to be invoked.
     * 
     */
    private ProjectTree() {
        // not to be invoked
        setBorder(new EmptyBorder(3, 3, 0, 0));
        setModel(projectTreeModel);
        setRowHeight(18);
        setRootVisible(false);
        setCellRenderer(new ProjectTreeCellRenderer());
        addKeyListener(new KeyAdapter() {

            public void keyPressed(KeyEvent keyEvent) {

                if (keyEvent.getKeyChar() == KeyEvent.VK_DELETE) {
                    deleteSelectedProjects();
                    return;
                }

                if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER) {

                    TreePath treePath = getSelectionPath();
                    if (treePath == null)
                        return;
                    Object o = treePath.getLastPathComponent();
                    if (o instanceof ProjectTreeNode) {
                        ProjectTreeNode node = (ProjectTreeNode) o;
                        loadProjectForNode(node);
                        return;
                    }
                    if (o instanceof ModuleTreeNode) {
                        ModuleTreeNode node = (ModuleTreeNode) o;
                        node.doAction();
                        return;
                    }

                }

            }
        });

        addMouseListener(new MouseAdapter() {

            public void mouseClicked(MouseEvent e) {
                TreePath treePath = getPathForLocation(e.getX(), e.getY());
                if (treePath == null)
                    return;
                Object o = treePath.getLastPathComponent();

                if (o instanceof ProjectTreeNode) {
                    if (SwingUtilities.isRightMouseButton(e)) {
                        setSelectionPath(treePath);

                        ProjectTreeNode node = (ProjectTreeNode) o;

                        ProjectNodePopup popup = ProjectNodePopup.getInstance();
                        popup.pack();
                        popup.show(ProjectTree.this, e.getX(), e.getY());
                        popup.setCurrentNode(node);

                    } else if (e.getClickCount() == 2) {
                        ProjectTreeNode node = (ProjectTreeNode) o;
                        loadProjectForNode(node);
                    }

                    return;
                }

                if (o instanceof ModuleTreeNode) {
                    ModuleTreeNode node = (ModuleTreeNode) o;
                    node.doAction();
                    return;
                }
            }
        });

    }

    /**
     * Deletes all selected project nodes from the tree. It shows a dialog
     * before which asks whether the project files should be deleted as well or
     * whether the action should be cancelled.
     */
    public void deleteSelectedProjects() {
        if (getSelectionCount() == 0)
            return;
        TreePath[] treePath = getSelectionPaths();
        boolean hasProjectNodes = false;

        if (treePath.length > 0)
            // check for project nodes
            for (int i = 0; i < treePath.length; i++) {
                Object o = treePath[i].getLastPathComponent();
                if ((o instanceof ProjectTreeNode)) {
                    hasProjectNodes = true;
                    break;
                }
            }
        if (!hasProjectNodes)
            return;
        String msg = "Removing selected projects.\nAlso delete project files?\n\n";
        msg = msg
                + "YES - delete project and file\nNO - only remove project from list\nCANCEL - do nothing";
        int status = JOptionPane.showConfirmDialog(TopFrameReference
                .getTopFrameRef(), msg, "Remove Selected Projects",
                JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);

        if (status == JOptionPane.CANCEL_OPTION)
            return;

        for (int i = 0; i < treePath.length; i++) {
            Object o = treePath[i].getLastPathComponent();
            if ((o instanceof ProjectTreeNode)) {
                ProjectTreeNode node = (ProjectTreeNode) o;
                projectTreeModel.removeNodeFromParent(node);
                projectList.remove(node);
                if (status == JOptionPane.YES_OPTION)
                    node.getProjectFile().delete();
            }
        }
    }

    /**
     * Loads a project from a project tree node. Invoked on double mouse click
     * over project nodes.
     * 
     * @param node
     *            the selected node
     */
    public void loadProjectForNode(ProjectTreeNode node) {
        // if (node.isCurrentProject())
        // return;
        try {
            ProjectTree.this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
            ProjectManager.getInstance().deSerializeProject(
                    node.getProjectFile());
            selectNode(node);
            repaint();
        } catch (Throwable ex) {
            String msg = "There was an error loading a project from file:\n\""
                    + node.getProjectFile().getAbsolutePath() + "\".";
            log.error(msg, ex);
            StdMessages.error(msg + "\nThe error message was:\n\""
                    + ex.getMessage()
                    + "\"\nPlease see the log for more details.",
                    "Project Load Error");
        } finally {
            ProjectTree.this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
    }

    /**
     * Gets singleton instance of this tree.
     * 
     * @return instance
     */
    public static ProjectTree getInstance() {
        return INSTANCE;
    }

    protected void selectNode(ProjectTreeNode node) {
        for (int i = 0; i < projectList.size(); i++)
            projectList.get(i).setCurrentProject(false);
        if (node != null)
            node.setCurrentProject(true);

    }

    /**
     * Gets an iterator over all project nodes.
     * 
     * @return iterator
     */
    Iterator getProjectNodesIterator() {
        return projectList.iterator();
    }

    /**
     * Removes a tree node from the tree. Nothing is done if node
     * is not a child anymore or if it is null.
     * 
     * @param node
     *            reference to the node to be removed
     */
    public void removeTreeNode(MutableTreeNode node) {
        if (node == null)
            return;
        projectTreeModel.removeNodeFromParent(node);
        projectList.remove(node);

    }

    /**
     * Adds a node to this tree that represents a module.
     * 
     * @param node
     *            a module node
     * @throws IllegalArgumentException
     *             if (node == null)
     */
    public void addModuleNode(ModuleTreeNode node) {
        if (node == null)
            throw new IllegalArgumentException("Argument was null.");
        boolean inserted = false;
        for (int i = 0; i < ROOT.getChildCount(); i++) {
            Object item = ROOT.getChildAt(i);
            if (item instanceof ModuleTreeNode) {
                ModuleTreeNode mNode = (ModuleTreeNode) item;
                if (mNode.getName().compareTo(node.getName()) >= 0) {
                    ROOT.insert(node, i);
                    inserted = true;
                    break;
                }
            } else {
                ROOT.insert(node, i);
                inserted = true;
                break;
            }
        }
        if (!inserted)
            ROOT.add(node);

        projectTreeModel.reload();
    }

    /**
     * Adds a project node to this tree.
     * 
     * @param node
     *            the element to add to the tree
     * @throws IllegalArgumentException
     *             if (node == null)
     */
    public void addProjectNode(ProjectTreeNode node) {
        if (node == null)
            throw new IllegalArgumentException("Argument was null.");

        // if already there, set to current project
        if (projectList.contains(node)) {
            int i = projectList.indexOf(node);
            ProjectTreeNode containedNode = projectList.get(i);
            containedNode.setNode(node);
            if (node.isCurrentProject())
                selectNode(containedNode);
            repaint();
            return;
        }

        if (node.isCurrentProject())
            selectNode(node);

        // add sorted according to name
        boolean inserted = false;
        for (int i = 0; i < ROOT.getChildCount(); i++) {
            Object item = ROOT.getChildAt(i);
            if (item instanceof ProjectTreeNode) {
                ProjectTreeNode pNode = (ProjectTreeNode) item;
                if (pNode.getName().compareToIgnoreCase(node.getName()) >= 0
                        && !pNode.isLastState()) {
                    ROOT.insert(node, i);
                    inserted = true;
                    break;
                }
            }
        }

        // node was not yet added
        if (!inserted)
            ROOT.add(node);

        projectList.add(node);
        projectTreeModel.reload();
    }

}
 

Ads help maintain this website.