/*
* GNU General Public License
*
* Copyright (C) 2006 Matej Zachar <mzachar@users.sourceforge.net>
*
* This program 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 2 of the License, or (at your option) any later
* version.
*
* This program 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
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: DynamicTree.java 55 2006-04-23 20:43:49 +0000 (Ne, 23 apr 2006) mzachar $
*/
package sk.netmap.gui.componets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.util.Set;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.apache.log4j.Logger;
import sk.netmap.bo.Group;
import sk.netmap.bo.Server;
import sk.netmap.bo.SharedFolder;
import sk.netmap.gui.MainFrame;
import sk.netmap.gui.controller.DataController;
import sk.netmap.util.Global;
/**
* Dynamic Tree
*
* @author Matej Zachar, $Date: 2006-04-23 20:43:49 +0000 (Ne, 23 apr 2006) $
*/
public class DynamicTree implements ActionListener, PopupMenuListener, MouseListener, IPropertyChangeListener {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(DynamicTree.class);
public static final int GROUPS_NODE = 1;
public static final int GROUP_NODE = 2;
public static final int SERVER_NODE = 3;
public static final int SHARED_FOLDER_NODE = 4;
protected DataController data = DataController.getInstance();
protected DefaultMutableTreeNode rootNode;
protected DefaultTreeModel treeModel;
protected JTree tree;
protected JPopupMenu treePopupMenu;
private Toolkit toolkit = Toolkit.getDefaultToolkit();
private TreePath currentSelection;
public DynamicTree() {
rootNode = new DefaultMutableTreeNode(resString("GroupsNode"));
treeModel = new DefaultTreeModel(rootNode);
treePopupMenu = new JPopupMenu();
treePopupMenu.addPopupMenuListener(this);
tree = new JTree(treeModel);
fillTree();
tree.setCellRenderer(new TreeCellRenderer());
tree.setComponentPopupMenu(treePopupMenu);
tree.addMouseListener(this);
tree.addTreeSelectionListener(MainFrame.getInstance());
tree.setEditable(false);
tree.setExpandsSelectedPaths(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.expandRow(0);
tree.setDragEnabled(true);
DataController.getInstance().addPropertyChangeListener(this);
}
public void expandAll(JTree tree) {
int row = 0;
while (row < tree.getRowCount()) {
tree.expandRow(row);
row++;
}
}
public void rebuildPopup() {
buildPopup();
}
private void buildPopup() {
treePopupMenu.removeAll();
JMenuItem add = new JMenuItem();
add.setEnabled(true);
add.setActionCommand("Add");
add.addActionListener(this);
treePopupMenu.add(add);
JMenuItem del = new JMenuItem();
del.setEnabled(true);
del.setActionCommand("Delete");
del.addActionListener(this);
del.setIcon(Global.iconTrash);
treePopupMenu.add(del);
if (currentSelection != null) {
if (isRootNodeSelectedPath()) {
add.setText(resString("AddGroup"));
add.setIcon(Global.iconGroup);
treePopupMenu.remove(del);
} else if (isGroupNodeSelectedPath()) {
add.setText(resString("AddServer"));
add.setIcon(Global.iconServerOff);
del.setText(resString("DeleteGroup"));
} else if (isServerNodeSelectedPath()) {
Server server = (Server)getCurrentNode().getUserObject();
if (DataController.getInstance().getFreeLettersInGroup(server.getGroup()).size() > 0){
add.setEnabled(true);
} else {
add.setEnabled(false);
}
add.setText(resString("AddSharedFolder"));
add.setIcon(Global.iconFolder);
del.setText(resString("DeleteServer"));
} else if (isSharedFolderNodeSelectedPath()){
treePopupMenu.remove(add);
del.setText(resString("DeleteSharedFoder"));
}
} else {
treePopupMenu.removeAll();
logger.debug("Selection null - buildPopup()");
}
}
/**
* Remove all nodes from tree.
*/
public void clear() {
rootNode.removeAllChildren();
treeModel.reload();
}
/**
* Returns tree that we are working with
*
* @return jtree
*/
public JTree getTree() {
return tree;
}
/**
* Returns tree model that we are working with
*
* @return treemodel
*/
public DefaultTreeModel getTreeModel() {
return treeModel;
}
public void setCurrentSelectionPath(TreePath path){
this.currentSelection = path;
}
/**
* Return currently selected node (or root node if no node selected)
*
* @return node: user-added object is enveloped in node
*/
public DefaultMutableTreeNode getCurrentNode() {
DefaultMutableTreeNode currentNode = null;
if (currentSelection == null) {
currentNode = rootNode;
} else {
currentNode = (DefaultMutableTreeNode) currentSelection.getLastPathComponent();
}
return currentNode;
}
/**
* Removes currently selected node.
*/
public void removeCurrentNode() {
DefaultMutableTreeNode currentNode = getCurrentNode();
MutableTreeNode parent = (MutableTreeNode) currentNode.getParent();
if (parent != null) {
treeModel.removeNodeFromParent(currentNode);
return;
}
// Either there was no selection, or the root was selected.
toolkit.beep();
}
// Add child to the currently selected node.
public DefaultMutableTreeNode addObject(Object child) {
DefaultMutableTreeNode parentNode = null;
if (currentSelection == null) { // Add Group Node
parentNode = rootNode;
} else if (isGroupNodeSelectedPath()) { //Add Server Node
parentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent());
} else if (isServerNodeSelectedPath()) { //Add SharedFolder Node
parentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent());
}
return addObject(parentNode, child, true);
}
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
Object child) {
return addObject(parent, child, false);
}
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
Object child, boolean shouldBeVisible) {
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);
if (parent == null) {
parent = rootNode;
}
treeModel.insertNodeInto(childNode, parent, parent.getChildCount());
// Make sure the user can see the lovely new node.
if (shouldBeVisible) {
tree.scrollPathToVisible(new TreePath(childNode.getPath()));
}
return childNode;
}
public void fillTree() {
clear();
for (Group g : data.getAllGroups()) {
DefaultMutableTreeNode parentGroupNode = addObject(rootNode, g);
for (Server s : g.getServers()) {
DefaultMutableTreeNode parentServerNode = addObject(
parentGroupNode, s);
for (SharedFolder f : s.getSharedFolders()) {
addObject(parentServerNode, f);
}
}
}
}
public boolean isRootNodeSelectedPath() {
if (currentSelection.getPathCount() != GROUPS_NODE) {
return false;
}
return true;
}
public boolean isGroupNodeSelectedPath() {
if (currentSelection.getPathCount() != GROUP_NODE) {
return false;
}
return true;
}
public boolean isServerNodeSelectedPath() {
if (currentSelection.getPathCount() != SERVER_NODE) {
return false;
}
return true;
}
public boolean isSharedFolderNodeSelectedPath() {
if (currentSelection.getPathCount() != SHARED_FOLDER_NODE) {
return false;
}
return true;
}
public void propertyChange(PropertyChangeEvent event) {
String property = event.getPropertyName();
if (logger.isDebugEnabled()){
logger.debug("DynamicTree: "+property);
}
if (property.equals(DataController.PROPERTY_GROUP_CHANGE)
|| property.equals(DataController.PROPERTY_SERVER_CHANGE)
|| property.equals(DataController.PROPERTY_SHARED_FOLDER_CHANGE)) propertyValueChange(event.getOldValue(), event.getNewValue());
}
private void propertyValueChange(Object oldValue, Object newValue) {
if (oldValue != null){
if (newValue != null){
//update
treeModel.reload(getCurrentNode());
} else {
//delete
removeCurrentNode();
}
} else {
//add
addObject(newValue);
}
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command == "Delete") remove();
if (command == "Add") add();
}
private void remove() {
if (isGroupNodeSelectedPath()){
data.removeGroup((Group)getCurrentNode().getUserObject());
} else if (isServerNodeSelectedPath()) {
data.removeServer((Server)getCurrentNode().getUserObject());
} else if (isSharedFolderNodeSelectedPath()){
data.removeSharedFolder((SharedFolder)getCurrentNode().getUserObject());
}
}
private void add() {
if (isRootNodeSelectedPath()) { // add group
Group newGroup = new Group();
newGroup.setName("Group"+tree.getRowCount());
data.addGroup(newGroup);
} else if (isGroupNodeSelectedPath()) { // add server
Server newServer = new Server();
newServer.setName("Server"+tree.getRowCount());
data.addServer((Group)getCurrentNode().getUserObject(), newServer);
} else if (isServerNodeSelectedPath()){ // add shared folder
Server server = (Server)getCurrentNode().getUserObject();
SharedFolder newSharedFoder = new SharedFolder();
Set<String> letters = DataController.getInstance().getFreeLettersInGroup(server.getGroup());
newSharedFoder.setLetter(letters.iterator().next());
newSharedFoder.setRelativePath("share"+tree.getRowCount());
data.addSharedFolder(server, newSharedFoder);
}
}
public String resString(String key){
return MainFrame.resString(key);
}
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
rebuildPopup();
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
//no code
}
public void popupMenuCanceled(PopupMenuEvent e) {
//no code
}
public void mousePressed(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
TreePath tp = tree.getPathForLocation(e.getX(), e.getY());
if (tp != null) {
tree.setSelectionPath(tp);
}
}
}
public void mouseClicked(MouseEvent e) {
// no code
}
public void mouseReleased(MouseEvent e) {
// no code
}
public void mouseEntered(MouseEvent e) {
// no code
}
public void mouseExited(MouseEvent e) {
// no code
}
}