package org.openswing.swing.tree.client;
import java.util.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.tree.*;
import org.openswing.swing.message.receive.java.*;
import org.openswing.swing.tree.java.*;
import org.openswing.swing.util.client.*;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeModelEvent;
/**
* <p>Title: OpenSwing Framework</p>
* <p>Description: Panel that contains an expandable tree.
* Nodes may be dragged inside the tree if enabledDrag method is invoked.</p>
* <p>Copyright: Copyright (C) 2006 Mauro Carniel</p>
*
* <p> This file is part of OpenSwing Framework.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the (LGPL) Lesser General Public
* License as published by the Free Software Foundation;
*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
*
* 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author may be contacted at:
* maurocarniel@tin.it</p>
*
* @author Mauro Carniel
* @version 1.0
*/
public class TreePanel extends JPanel implements DragSourceListener, DropTargetListener, SearchControl {
static {
UIManager.getDefaults().put("Tree.selectionBackground",new javax.swing.plaf.ColorUIResource(ClientSettings.TREE_SELECTION_BACKGROUND));
UIManager.getDefaults().put("Tree.selectionForeground",new javax.swing.plaf.ColorUIResource(ClientSettings.TREE_SELECTION_FOREGROUND));
}
/** current checked nodes (i.e. nodes having selected the associated check-box) */
private HashSet checkedNodes = new HashSet();
/** tree selection background color */
private Color selectionBackground = ClientSettings.TREE_SELECTION_BACKGROUND;
/** tree selection foreground color */
private Color selectionForeground = ClientSettings.TREE_SELECTION_FOREGROUND;
/** expandable tree */
private JTree tree = new JTree(new OpenSwingTreeNode()){
public TreePath getNextMatch(String prefix, int startingRow,
Position.Bias bias) {
try {
return super.getNextMatch(prefix, startingRow, bias);
}
catch (Exception ex) {
return null;
}
}
public void setModel(TreeModel model) {
super.setModel(model);
try {
if (checkedNodes != null) {
checkedNodes.clear();
}
}
catch (Exception ex) {
}
}
};
/** tree container */
private JTable table = new JTable();
/** tree model */
private DefaultTreeModel treeModel = new DefaultTreeModel(new OpenSwingTreeNode());
/** tree container */
private JScrollPane treePane = new JScrollPane();
/** data source used to fill in the tree */
private TreeDataLocator treeDataLocator;
/** tree controller: it manages tree events */
private TreeController treeController;
/** pop-up menu related to right mouse click on a tree node (optional) */
private JPopupMenu popup = new JPopupMenu();
/** collection of pairs: menu item description (not yet translated), menu item object; used to change the menu item abilitation */
private Hashtable menuItems = new Hashtable();
/** flag used inside addNotify method */
private boolean firstTime = true;
/** image icon used for leaves; default value: as for folders */
private String leavesImageName = ClientSettings.getInstance().PERC_TREE_FOLDER;
/** define if tree will be filled on viewing this panel; default value: true */
private boolean loadWhenVisibile = true;
/** define if all tree nodes must be expanded after loading */
private boolean expandAllNodes = false;
/** folder node image name */
private String folderIconName = ClientSettings.PERC_TREE_FOLDER;
/** drag source */
private DragSource dragSource = null;
/** drop gestures */
private DropTarget dropTarget = null;
/** drag 'n' drop listener */
private TreeDragNDropListener dndListener = null;
/** tree identifier, used for DnD */
private String treeId = null;
/** attribute name that contains the icon image name; default value: null; if defined, this attribute overrides "folderIcon"/"leafIcon" values */
private String iconAttributeName;
/** attribute name that contains the tool tip text for the node; default value: null */
private String tooltipAttributeName;
/** search manager */
private SearchWindowManager searchWindowManager;
/** Determines whether or not the root node from the <code>TreeModel</code> is visible; default value: <code>true</code> */
private boolean rootVisible = true;
/** tree selection mode; allowed values: <code>TreeSelectionModel.SINGLE_TREE_SELECTION</code>,<code>TreeSelectionModel.CONTIGUOUS_TREE_SELECTION</code> or <code>TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION</code>. Default value: <code>TreeSelectionModel.SINGLE_TREE_SELECTION </code> */
private int selectionMode = TreeSelectionModel.SINGLE_TREE_SELECTION;
/** tree row height */
private int rowHeight = tree.getRowHeight();
/** specifies whether the node handles should be displayed; default value: <code>true</code> */
private boolean showsRootHandles = true;
/** list of KeyListener objects added to the tree */
private ArrayList keyListeners = new ArrayList();
/** list of MouseListener objects added to the tree */
private ArrayList mouseListeners = new ArrayList();
/** cursor to show on dragging */
private Cursor dragCursor = null;
/** define if a check-box must be showed for each node; default value: <code>false</code> */
private boolean showCheckBoxes = false;
/** define if a check-box must be showed for leaves nodes too; default value: <code>true</code> */
private boolean showCheckBoxesOnLeaves = true;
/** list of ItemListener objects added to the check-box tree */
private ArrayList itemListeners = new ArrayList();
/** define if root node must be automatically expanded when "expandAllNodes" property is set to <code>false</code>; default value: <code>true</code> */
private boolean expandRoot = true;
/** flag used to mark the state "tree content changed" */
private boolean treeChanged = false;
/**
* Constructor.
*/
public TreePanel() {
try {
tree.setRootVisible(rootVisible);
tree.setShowsRootHandles(showsRootHandles);
jbInit();
dragCursor = Toolkit.getDefaultToolkit().createCustomCursor(
ClientUtils.getImage("drag.gif"),
new Point(15, 10),
ClientSettings.getInstance().getResources().getResource("drag")
);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public void addNotify() {
super.addNotify();
if (firstTime) {
if (loadWhenVisibile) {
firstTime = false;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createTree();
}
});
}
else
recreateTree();
}
}
/**
* Force tree reloading.
*/
public final void reloadTree() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (!loadWhenVisibile && firstTime) {
firstTime = false;
createTree();
if (expandAllNodes)
expandAllNodes();
else if (expandRoot && rootVisible)
tree.expandRow(0);
}
else {
ClientUtils.fireBusyEvent(true);
try {
ClientUtils.getParentWindow(TreePanel.this).setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR));
ClientUtils.getParentWindow(TreePanel.this).getToolkit().sync();
}
catch (Exception ex) {
}
Response response = null;
try {
response = treeDataLocator.getTreeModel(tree);
}
finally {
try {
ClientUtils.getParentWindow(TreePanel.this).setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
ClientUtils.getParentWindow(TreePanel.this).getToolkit().sync();
}
catch (Exception ex1) {
}
ClientUtils.fireBusyEvent(false);
}
if (response.isError())
treeModel = new DefaultTreeModel(new OpenSwingTreeNode());
else
treeModel = (DefaultTreeModel) ( (VOResponse) response).getVo();
tree.setModel(treeModel);
treeDataLocator.loadDataCompleted(response.isError());
tree.revalidate();
if (expandAllNodes)
expandAllNodes();
else if (expandRoot && rootVisible)
tree.expandRow(0);
}
}
});
}
/**
* Expand a tree node.
* @param index index of node to expand
*/
public final void expandNode(int index) {
tree.expandRow(index);
}
/**
* Collapse a tree node.
* @param index index of node to collapse
*/
public final void collapseNode(int index) {
tree.collapseRow(index);
}
/**
* Expand all tree nodes.
*/
public final void expandAllNodes() {
int i = 0;
try {
while (i < tree.getRowCount()) {
tree.expandRow(i++);
}
}
catch (Exception ex) {
}
}
/**
* Collapse all tree nodes.
*/
public final void collapseAllNodes() {
int i = tree.getRowCount()-1;
while (i >0)
tree.collapseRow(i--);
}
void jbInit() throws Exception {
this.setLayout(new java.awt.BorderLayout());
treePane.getViewport().add(tree, null);
this.add(treePane, BorderLayout.CENTER);
}
/**
* Redraw the tree. Used when the tree model has been modified.
*/
public final void repaintTree() {
TreePath selPath = tree.getSelectionPath();
treePane.getViewport().remove(tree);
MouseMotionListener[] mml = null;
MouseWheelListener[] mwl = null;
TreeSelectionListener[] tsl = null;
TreeWillExpandListener[] twl = null;
TreeExpansionListener[] tel = null;
if (tree!=null) {
mml = tree.getMouseMotionListeners();
mwl = tree.getMouseWheelListeners();
tsl = tree.getTreeSelectionListeners();
twl = tree.getTreeWillExpandListeners();
tel = tree.getTreeExpansionListeners();
}
tree = new JTree(treeModel) {
public TreePath getNextMatch(String prefix, int startingRow,
Position.Bias bias) {
try {
return super.getNextMatch(prefix, startingRow, bias);
}
catch (Exception ex) {
return null;
}
}
public void setModel(TreeModel model) {
super.setModel(model);
try {
if (checkedNodes != null) {
checkedNodes.clear();
}
}
catch (Exception ex) {
}
}
};
searchWindowManager = new SearchWindowManager(this);
for(int i=0;i<keyListeners.size();i++)
tree.addKeyListener((KeyListener)keyListeners.get(i));
for(int i=0;i<mouseListeners.size();i++)
tree.addMouseListener((MouseListener)mouseListeners.get(i));
if (mml!=null)
for(int i=0;i<mml.length;i++)
tree.addMouseMotionListener(mml[i]);
if (mwl!=null)
for(int i=0;i<mwl.length;i++)
tree.addMouseWheelListener(mwl[i]);
if (tsl!=null)
for(int i=0;i<tsl.length;i++)
tree.addTreeSelectionListener(tsl[i]);
if (twl!=null)
for(int i=0;i<twl.length;i++)
tree.addTreeWillExpandListener(twl[i]);
if (tel!=null)
for(int i=0;i<tel.length;i++)
tree.addTreeExpansionListener(tel[i]);
if (treeId != null && dndListener != null)
enableDrag(treeId, dndListener);
recreateTree();
tree.repaint();
try {
tree.setSelectionPath(selPath.getParentPath());
}
catch (Exception ex) {
}
try {
tree.setSelectionPath(selPath);
}
catch (Exception ex) {
}
}
/**
* Remove all nodes (expept the root node) from the tree.
*/
public final void clearTree() {
treeModel = new DefaultTreeModel(new OpenSwingTreeNode());
repaintTree();
}
/**
* Fill in the tree.
*/
private void createTree() {
ClientUtils.fireBusyEvent(true);
try {
ClientUtils.getParentWindow(TreePanel.this).setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR));
ClientUtils.getParentWindow(TreePanel.this).getToolkit().sync();
}
catch (Exception ex) {
}
Response response = null;
try {
response = treeDataLocator.getTreeModel(tree);
}
finally {
try {
ClientUtils.getParentWindow(TreePanel.this).setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
ClientUtils.getParentWindow(TreePanel.this).getToolkit().sync();
}
catch (Exception ex1) {
}
ClientUtils.fireBusyEvent(false);
}
if (response.isError())
treeModel = new DefaultTreeModel(new OpenSwingTreeNode());
else
treeModel = (DefaultTreeModel) ( (VOResponse) response).getVo();
recreateTree();
treeDataLocator.loadDataCompleted(response.isError());
if (expandAllNodes)
expandAllNodes();
else if (expandRoot && rootVisible)
tree.expandRow(0);
}
private void recreateTree() {
try {
TreeNodeRenderer renderer = new TreeNodeRenderer(
this,
folderIconName,
leavesImageName,
iconAttributeName,
tooltipAttributeName
);
tree.setCellRenderer(renderer);
}
catch (Exception ex) {
ex.printStackTrace();
}
tree.setRootVisible(rootVisible);
tree.setToolTipText("");
tree.setModel(treeModel);
tree.revalidate();
if (searchWindowManager == null)
searchWindowManager = new SearchWindowManager(this);
tree.getSelectionModel().setSelectionMode(selectionMode);
tree.setRowHeight(rowHeight);
tree.setShowsRootHandles(showsRootHandles);
tree.setSize(new Dimension( (int)this.getPreferredSize().getWidth() / 2,
(int)this.getPreferredSize().getHeight()));
treePane.getViewport().add(tree);
treePane.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedBevelBorder(),
BorderFactory.createLoweredBevelBorder()
));
treePane.setAutoscrolls(true);
tree.setMinimumSize(new Dimension(0, 200));
dropTarget = new DropTarget(tree, this);
MouseListener ml = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1 && SwingUtilities.isLeftMouseButton(e))
treeLeftClick(e, tree);
else if (e.getClickCount() == 1 && SwingUtilities.isRightMouseButton(e))
treeRightClick(e, tree);
if (e.getClickCount() == 2)
treeDoubleClick(e, tree);
}
};
tree.addMouseListener(ml);
treeChanged = false;
treeModel.addTreeModelListener(new TreeModelListener() {
public void treeNodesChanged(TreeModelEvent e) {
treeChanged = true;
}
public void treeNodesInserted(TreeModelEvent e) {
treeChanged = true;
}
public void treeNodesRemoved(TreeModelEvent e) {
treeChanged = true;
}
public void treeStructureChanged(TreeModelEvent e) {
treeChanged = true;
}
});
}
/**
* @return selected node or null if no node is selected
*/
public final DefaultMutableTreeNode getSelectedNode() {
try {
javax.swing.tree.TreePath selPath = tree.getSelectionPath();
if (selPath != null)
return (DefaultMutableTreeNode) (selPath.getPathComponent(selPath.
getPathCount() - 1));
else
return null;
}
catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* Select a node in the tree.
* @param node tree node to select
*/
public final void setSelectedNode(DefaultMutableTreeNode node) {
try {
tree.setSelectionPath(new TreePath(node.getPath()));
}
catch (Exception ex) {
}
}
/**
* Method called when user has double clicked.
* @param e double click event
* @param tree tree
*/
public final void treeDoubleClick(MouseEvent e, JTree tree) {
try {
int selRow = tree.getRowForLocation(e.getX(), e.getY());
javax.swing.tree.TreePath selPath = tree.getPathForLocation(e.getX(),
e.getY());
if (selPath != null) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) (selPath.
getPathComponent(selPath.getPathCount() - 1));
treeController.doubleClick(node);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Method called when user has clicked on the left mouse button.
* @param e left mouse button click event
* @param tree tree
*/
public final void treeLeftClick(MouseEvent e, JTree tree) {
try {
int selRow = tree.getRowForLocation(e.getX(), e.getY());
javax.swing.tree.TreePath selPath = tree.getPathForLocation(e.getX(),
e.getY());
if (selPath != null) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) (selPath.
getPathComponent(selPath.getPathCount() - 1));
treeController.leftClick(node);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
treePane.setEnabled(enabled);
}
/**
* Method called when user has clicked on the right mouse button.
* @param e right mouse button click event
* @param tree tree
*/
public final void treeRightClick(MouseEvent e, JTree tree) {
try {
if (this.selectionMode!=TreeSelectionModel.SINGLE_TREE_SELECTION &&
tree.getSelectionRows().length>1) {
int selRow = tree.getRowForLocation(e.getX(), e.getY());
// javax.swing.tree.TreePath selPath = tree.getPathForLocation(e.getX(),e.getY());
// tree.setSelectionPath(selPath);
if (selRow!=-1 && popup.getComponentCount() > 0 && treePane.isEnabled()) {
TreePath[] selPaths = tree.getSelectionPaths();
DefaultMutableTreeNode node = null;
boolean ok = true;
for(int i=0;i<selPaths.length;i++) {
node = (DefaultMutableTreeNode) (selPaths[i].getPathComponent(selPaths[i].getPathCount() - 1));
ok = treeController.rightClick(node);
if (!ok)
break;
}
if (ok) {
// visualizzazione del menu' a pop-up associato al nodo dell'albero,
// SOLO se il metodo rightClick ha ritornato valore "true" e c'e almeno un elemento nel menu' a pop-up
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
else {
int selRow = tree.getRowForLocation(e.getX(), e.getY());
javax.swing.tree.TreePath selPath = tree.getPathForLocation(e.getX(),e.getY());
tree.setSelectionPath(selPath);
if (selPath != null) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) (selPath.getPathComponent(selPath.getPathCount() - 1));
if (treeController.rightClick(node) && popup.getComponentCount() > 0 &&
treePane.isEnabled()) {
// visualizzazione del menu' a pop-up associato al nodo dell'albero,
// SOLO se il metodo rightClick ha ritornato valore "true" e c'e almeno un elemento nel menu' a pop-up
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Add a pop-up menu item.
* @param menuName menu item description (not yet translated)
* @param mnemonic mnemonic value
* @param enabled flag used to set menu item abilitation
* @param menuListener listener used to capture menu item selection
*/
public final void addPopupMenuItem(String menuName, char mnemonic,
boolean enabled,
ActionListener menuListener) {
JMenuItem cbMenuItem = new JMenuItem(ClientSettings.getInstance().
getResources().getResource(menuName));
cbMenuItem.setMnemonic(mnemonic);
cbMenuItem.setEnabled(enabled);
cbMenuItem.addActionListener(menuListener);
popup.add(cbMenuItem);
menuItems.put(menuName, cbMenuItem);
}
/**
* Add a pop-up menu item to a parent menu item.
* @param menuName menu item description (not yet translated)
* @param parentMenuName
* @param mnemonic mnemonic value
* @param enabled flag used to set menu item abilitation
* @param menuListener listener used to capture menu item selection
*/
public final void addPopupMenuItem(String menuName, String parentMenuName,char mnemonic,
boolean enabled,
ActionListener menuListener) {
JMenuItem cbMenuItem = new JMenuItem(ClientSettings.getInstance().
getResources().getResource(menuName));
cbMenuItem.setMnemonic(mnemonic);
cbMenuItem.setEnabled(enabled);
cbMenuItem.addActionListener(menuListener);
JMenuItem parentItem = (JMenuItem)menuItems.get(parentMenuName);
if (parentItem!=null) {
parentItem.add(cbMenuItem);
menuItems.put(menuName, cbMenuItem);
}
}
/**
* Add a separator to the pop-up menu.
*/
public final void addPopupSeparator() {
popup.add(new JSeparator());
}
/**
* Set menu item abilitation.
* @param menuName menu item description (not yet translated)
* @param enabled flag used to enable the menu item
*/
public final void setMenuItemEnabled(String menuName, boolean enabled) {
JMenuItem menu = (JMenuItem) menuItems.get(menuName);
if (menu != null)
menu.setEnabled(enabled);
}
/**
* Set menu item visibility.
* @param menuName menu item description (not yet translated)
* @param visible flag used to hide/show the menu item
*/
public final void setMenuItemVisible(String menuName, boolean visible) {
JMenuItem menu = (JMenuItem) menuItems.get(menuName);
if (menu != null)
menu.setVisible(visible);
}
/**
* @return tree controller: it manages tree events
*/
public final TreeController getTreeController() {
return treeController;
}
/**
* @return data source used to fill in the tree
*/
public final TreeDataLocator getTreeDataLocator() {
return treeDataLocator;
}
/**
* Set the data source used to fill in the tree
* @param treeDataLocator data source used to fill in the tree
*/
public final void setTreeDataLocator(TreeDataLocator treeDataLocator) {
this.treeDataLocator = treeDataLocator;
}
/**
* Set the tree controller: it manages tree events.
* @param treeController tree controller: it manages tree events.
*/
public final void setTreeController(TreeController treeController) {
this.treeController = treeController;
}
/**
* @return image icon used for leaves
*/
public final String getLeavesImageName() {
return leavesImageName;
}
/**
* Set image icon used for leaves.
* @param leavesImageName image icon used for leaves
*/
public final void setLeavesImageName(String leavesImageName) {
this.leavesImageName = leavesImageName;
}
/**
* @return define if tree will be filled on viewing this panel
*/
public final boolean isLoadWhenVisibile() {
return loadWhenVisibile;
}
/**
* Define if tree will be filled on viewing this panel.
* @param loadWhenVisibile define if tree will be filled on viewing this panel
*/
public final void setLoadWhenVisibile(boolean loadWhenVisibile) {
this.loadWhenVisibile = loadWhenVisibile;
}
/**
* @return boolean define if all tree nodes must be expanded after loading
*/
public final boolean isExpandAllNodes() {
return expandAllNodes;
}
/**
* Define if all tree nodes must be expanded after loading.
* @param expandAllNodes boolean define if all tree nodes must be expanded after loading
*/
public final void setExpandAllNodes(boolean expandAllNodes) {
this.expandAllNodes = expandAllNodes;
}
/**
* @return folder icon name
*/
public final String getFolderIconName() {
return folderIconName;
}
/**
* Set the folder icon name.
* @param treeFolderName folder icon name
*/
public final void setFolderIconName(String folderIconName) {
this.folderIconName = folderIconName;
}
/**
* @return tree
*/
public final JTree getTree() {
return tree;
}
/********************************************************************
*
* DRAG 'N DROP MANAGEMENTS METHODS
*
********************************************************************/
/************************************************************
* DRAG MANAGEMENT
************************************************************/
/**
* Enable drag onto the grid.
* @param gridId grid identifier
*/
public final void enableDrag(String treeId, TreeDragNDropListener dndListener) {
try {
dragSource = new DragSource();
dragSource.createDefaultDragGestureRecognizer(
tree,
DnDConstants.ACTION_MOVE,
new DragGestureAdapter(this)
);
}
catch (Exception ex) {
ex.printStackTrace();
}
this.treeId = treeId;
this.dndListener = dndListener;
}
class DragGestureAdapter
implements DragGestureListener {
private DragSourceListener dragListener = null;
public DragGestureAdapter(DragSourceListener dragListener) {
this.dragListener = dragListener;
}
/**
* A drag gesture has been initiated.
*/
public final void dragGestureRecognized(DragGestureEvent event) {
if (dndListener.dragEnabled()) {
tree.setCursor(dragCursor);
dragSource.startDrag(event, DragSource.DefaultMoveDrop,
new StringSelection(treeId), dragListener);
}
else
// drag interrupted...
event.getSourceAsDragGestureRecognizer().resetRecognizer();
}
}
/**
* This message goes to DragSourceListener, informing it that the dragging has entered the DropSite
*/
public final void dragEnter(DragSourceDragEvent event) {
tree.setCursor(Cursor.getDefaultCursor());
dndListener.dragEnter();
}
/**
* This message goes to DragSourceListener, informing it that the dragging has exited the DropSite.
*/
public final void dragExit(DragSourceEvent event) {
tree.setCursor(Cursor.getDefaultCursor());
dndListener.dragExit();
}
/**
* This message goes to DragSourceListener, informing it that the dragging is currently ocurring over the DropSite.
*/
public final void dragOver(DragSourceDragEvent e) {
tree.setCursor(dragCursor);
Point loc = tree.getLocationOnScreen();
int row = (e.getY()-loc.y)/tree.getRowHeight();
int firstVisibleRow = tree.getVisibleRect().y/tree.getRowHeight();
int lastVisibleRow = (tree.getVisibleRect().y+tree.getVisibleRect().height)/tree.getRowHeight();
if (row<=firstVisibleRow+1)
tree.scrollRowToVisible(row-1);
else if (row>=lastVisibleRow-1)
tree.scrollRowToVisible(row+1);
dndListener.dragOver();
}
/**
* This method is invoked when the user changes the dropAction.
*/
public final void dropActionChanged(DragSourceDragEvent event) {}
/**
* This message goes to DragSourceListener, informing it that the dragging has ended.
*/
public final void dragDropEnd(DragSourceDropEvent event) {
dndListener.dragDropEnd();
}
/************************************************************
* DROP MANAGEMENT
************************************************************/
/**
* This method is invoked when you are dragging over the DropSite.
*/
public final void dragEnter(DropTargetDragEvent event) {
event.acceptDrag(DnDConstants.ACTION_MOVE);
dndListener.dropEnter();
}
/**
* This method is invoked when you are exit the DropSite without dropping.
*/
public final void dragExit(DropTargetEvent event) {
try {
dndListener.dropExit();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* This method is invoked when a drag operation is going on.
*/
public final void dragOver(DropTargetDragEvent event) {
dndListener.dropOver();
}
/**
* This method is invoked when a drop event has occurred.
*/
public final void drop(DropTargetDropEvent event) {
try {
tree.setCursor(Cursor.getDefaultCursor());
Transferable transferable = event.getTransferable();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.
getClosestPathForLocation(event.getLocation().x,
event.getLocation().y).getLastPathComponent();
if (node != null &&
transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
if (dndListener.dropEnabled(node,
(String) transferable.getTransferData(DataFlavor.
stringFlavor))) {
event.acceptDrop(DnDConstants.ACTION_MOVE);
event.getDropTargetContext().dropComplete(true);
}
else
event.rejectDrop();
}
else {
event.rejectDrop();
}
}
catch (Exception ex) {
ex.printStackTrace();
event.rejectDrop();
}
finally {
}
}
/**
* This method is invoked if the use modifies the current drop gesture.
*/
public final void dropActionChanged(DropTargetDragEvent event) {
dndListener.dropActionChanged();
}
/************************************************************
* END DROP MANAGEMENT
************************************************************/
/**
* Set the attribute name that contains the icon name; default value: null; if defined, this attribute overrides "folderIcon"/"leafIcon" values.
* @param iconAttributeName attribute name that contains the icon name
*/
public final void setIconAttributeName(String iconAttributeName) {
this.iconAttributeName = iconAttributeName;
}
/**
* @return attribute name that contains the icon name (optional)
*/
public final String getIconAttributeName() {
return iconAttributeName;
}
/**
* @return attribute name that contains the tool tip text for the node
*/
public final String getTooltipAttributeName() {
return tooltipAttributeName;
}
/**
* Set the attribute name that contains the tool tip text for the node; default value: null.
* @param tooltipAttributeName attribute name that contains the tool tip text for the node
*/
public final void setTooltipAttributeName(String tooltipAttributeName) {
this.tooltipAttributeName = tooltipAttributeName;
}
/**
* @return the selected index in the input control
*/
public final int getSelectedIndex() {
if (tree.getSelectionRows() == null)
return -1;
if (tree.getSelectionRows().length > 0)
return tree.getSelectionRows()[0];
else
return -1;
}
/**
* Set the selected index.
*/
public final void setSelectedIndex(int index) {
tree.setSelectionRow(index);
try {
tree.scrollRowToVisible(index);
}
catch (Exception ex) {
}
}
/**
* @return total rows count in the input control
*/
public final int getRowCount() {
return tree.getRowCount();
}
/**
* @return the element at the specified index, converted in String format
*/
public final String getValueAt(int index) {
try {
JPanel p = (JPanel)tree.getCellRenderer().getTreeCellRendererComponent(
tree,
tree.getPathForRow(index).getLastPathComponent(),
false,
false,
tree.getModel().isLeaf(tree.getPathForRow(index).getLastPathComponent()),
index,
false
);
JLabel l = null;
if (p.getComponent(0) instanceof JLabel)
l = (JLabel)p.getComponent(0);
else if (p.getComponent(1) instanceof JLabel)
l = (JLabel)p.getComponent(1);
if (l!=null)
return l.getText();
else
return "";
}
catch (Exception ex) {
Object obj = tree.getPathForRow(index).getLastPathComponent();
return obj == null ? "" : obj.toString();
}
}
/**
* @return combo control
*/
public final JComponent getComponent() {
return tree;
}
/**1
* @return <code>true</code> if the input control is in read only mode (so search is enabled), <code>false</code> otherwise
*/
public final boolean isReadOnly() {
return true;
}
/**
* @return <code>true</code> to disable key listening on input control (for instance, in case of nested grids), <code>false</code> to listen for key events
*/
public final boolean disableListener() {
return false;
}
/**
* Returns true if the root node of the tree is displayed.
*
* @return true if the root node of the tree is displayed
* @see #rootVisible
*/
public final boolean isRootVisible() {
return rootVisible;
}
/**
* Determines whether or not the root node from
* the <code>TreeModel</code> is visible.
*
* @param rootVisible true if the root node of the tree is to be displayed
* @see #rootVisible
* @beaninfo
* bound: true
* description: Whether or not the root node
* from the TreeModel is visible.
*/
public final void setRootVisible(boolean rootVisible) {
this.rootVisible = rootVisible;
tree.setRootVisible(rootVisible);
}
/**
* Sets the selection model, which must be one of TreeSelectionModel.SINGLE_TREE_SELECTION,
* TreeSelectionModel.CONTIGUOUS_TREE_SELECTION or TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION.
* <p>
* This may change the selection if the current selection is not valid
* for the new mode. For example, if three TreePaths are
* selected when the mode is changed to <code>TreeSelectionModel.SINGLE_TREE_SELECTION</code>,
* only one TreePath will remain selected. It is up to the particular
* implementation to decide what TreePath remains selected.
*/
public final void setSelectionMode(int selectionMode) {
this.selectionMode = selectionMode;
tree.getSelectionModel().setSelectionMode(selectionMode);
tree.setRowHeight(0);
}
/**
* Returns the current selection mode, one of
* <code>TreeSelectionModel.SINGLE_TREE_SELECTION</code>,
* <code>TreeSelectionModel.CONTIGUOUS_TREE_SELECTION</code> or
* <code>TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION</code>.
*/
public final int getSelectionMode() {
return selectionMode;
}
/**
* Sets the height of each cell, in pixels. If the specified value
* is less than or equal to zero the current cell renderer is
* queried for each row's height.
*
* @param rowHeight the height of each cell, in pixels
* @beaninfo
* bound: true
* description: The height of each cell.
*/
public final void setRowHeight(int rowHeight) {
this.rowHeight = rowHeight;
tree.setRowHeight(rowHeight);
}
/**
* Returns the height of each row. If the returned value is less than
* or equal to 0 the height for each row is determined by the
* renderer.
*
*/
public final int getRowHeight() {
return rowHeight;
}
/**
* Sets the value of the <code>showsRootHandles</code> property,
* which specifies whether the node handles should be displayed.
* The default value of this property depends on the constructor
* used to create the <code>JTree</code>.
* Some look and feels might not support handles;
* they will ignore this property.
* @param newValue <code>true</code> if root handles should be displayed;
* otherwise, <code>false</code>
* @see #showsRootHandles
* @see #getShowsRootHandles
* @beaninfo bound: true
* description: Whether the node handles are to be displayed.
*/
public final void setShowsRootHandles(boolean showsRootHandles) {
this.showsRootHandles = showsRootHandles;
tree.setShowsRootHandles(showsRootHandles);
}
/**
* Returns the value of the <code>showsRootHandles</code> property.
* @return the value of the <code>showsRootHandles</code> property
* @see #showsRootHandles
*/
public final boolean getShowsRootHandles() {
return showsRootHandles;
}
/**
* Scrolls the item identified by row until it is displayed. The minimum
* of amount of scrolling necessary to bring the row into view
* is performed. Only works when this <code>JTree</code> is contained in a
* <code>JScrollPane</code>.
*
* @param row an integer specifying the row to scroll, where 0 is the
* first row in the display
*/
public final void scrollRowToVisible(int row) {
tree.scrollRowToVisible(row);
}
/**
* Selects the node at the specified row in the display.
*
* @param row the row to select, where 0 is the first row in
* the display
*/
public final void setSelectionRow(int row) {
tree.setSelectionRow(row);
}
/**
* Selects the nodes corresponding to each of the specified rows
* in the display. If a particular element of <code>rows</code> is
* < 0 or >= <code>getRowCount</code>, it will be ignored.
* If none of the elements
* in <code>rows</code> are valid rows, the selection will
* be cleared. That is it will be as if <code>clearSelection</code>
* was invoked.
*
* @param rows an array of ints specifying the rows to select,
* where 0 indicates the first row in the display
*/
public final void setSelectionRows(int[] rows) {
tree.setSelectionRows(rows);
}
/**
* Selects the node identified by the specified path. If any
* component of the path is hidden (under a collapsed node), and
* <code>getExpandsSelectedPaths</code> is true it is
* exposed (made viewable).
*
* @param path the <code>TreePath</code> specifying the node to select
*/
public final void setSelectionPath(TreePath path) {
tree.setSelectionPath(path);
}
/**
* Selects the nodes identified by the specified array of paths.
* If any component in any of the paths is hidden (under a collapsed
* node), and <code>getExpandsSelectedPaths</code> is true
* it is exposed (made viewable).
*
* @param paths an array of <code>TreePath</code> objects that specifies
* the nodes to select
*/
public final void setSelectionPaths(TreePath[] paths) {
tree.setSelectionPaths(paths);
}
/**
* Makes sure all the path components in path are expanded (except
* for the last path component) and scrolls so that the
* node identified by the path is displayed. Only works when this
* <code>JTree</code> is contained in a <code>JScrollPane</code>.
*
* @param path the <code>TreePath</code> identifying the node to
* bring into view
*/
public final void scrollPathToVisible(TreePath path) {
tree.scrollPathToVisible(path);
}
/**
* Returns the path to the first selected node.
*
* @return the <code>TreePath</code> for the first selected node,
* or <code>null</code> if nothing is currently selected
*/
public final TreePath getSelectionPath() {
return tree.getSelectionPath();
}
/**
* Returns the paths of all selected values.
*
* @return an array of <code>TreePath</code> objects indicating the selected
* nodes, or <code>null</code> if nothing is currently selected
*/
public final TreePath[] getSelectionPaths() {
return tree.getSelectionPaths();
}
/**
* Returns all of the currently selected rows. This method is simply
* forwarded to the <code>TreeSelectionModel</code>.
* If nothing is selected <code>null</code> or an empty array will
* be returned, based on the <code>TreeSelectionModel</code>
* implementation.
*
* @return an array of integers that identifies all currently selected rows
* where 0 is the first row in the display
*/
public final int[] getSelectionRows() {
return tree.getSelectionRows();
}
/**
* Set tree selection background color
* @param selectionBackground tree selection background color
*/
public final void setSelectionBackground(Color selectionBackground) {
this.selectionBackground = selectionBackground;
UIManager.getDefaults().put("Tree.selectionBackground",new javax.swing.plaf.ColorUIResource(selectionBackground));
tree.revalidate();
}
/**
* Set tree selection foreground color
* @param selectionForeground tree selection foreground color
*/
public final void setSelectionForeground(Color selectionForeground) {
this.selectionForeground = selectionForeground;
UIManager.getDefaults().put("Tree.selectionForeground",new javax.swing.plaf.ColorUIResource(selectionForeground));
tree.revalidate();
}
/**
* @return tree selection background color
*/
public final Color getSelectionBackground() {
return selectionBackground;
}
/**
* @return tree selection foreground color
*/
public final Color getSelectionForeground() {
return selectionForeground;
}
/**
* Revalidate tree content.
*/
public final void revalidateTree() {
TreePath[] paths = tree.getSelectionPaths();
boolean asksAllowsChildren = treeModel.asksAllowsChildren();
treeModel = new DefaultTreeModel((DefaultMutableTreeNode)tree.getModel().getRoot(),asksAllowsChildren);
tree.setModel(treeModel);
if (paths!=null)
tree.setSelectionPaths(paths);
}
/**
* Add a key listener to the tree.
* @param listener KeyListener to add
*/
public final void addKeyListener(KeyListener listener) {
keyListeners.add(listener);
}
/**
* Remove a key listener from the tree.
* @param listener KeyListener to remove
*/
public final void removeKeyListener(KeyListener listener) {
keyListeners.remove(listener);
}
/**
* Add a mouse listener to the tree.
* @param listener MouseListener to add
*/
public final void addMouseListener(MouseListener listener) {
mouseListeners.add(listener);
}
/**
* Remove a mouse listener from the tree.
* @param listener MouseListener to remove
*/
public final void removeMouseListener(MouseListener listener) {
mouseListeners.remove(listener);
}
/**
* Add an Item Listener to the tree, that listen for check-box selections.
* @param listener ItemListener to add
*/
public final void addItemListener(ItemListener listener) {
itemListeners.add(listener);
}
/**
* Remove an ItemListener from the tree.
* @param listener ItemListener to remove
*/
public final void removeItemListener(ItemListener listener) {
itemListeners.remove(listener);
}
/**
* @return ItemListener objects added to this check-box tree
*/
public final ItemListener[] getItemListeners() {
return (ItemListener[])itemListeners.toArray(new ItemListener[itemListeners.size()]);
}
/**
* @return define if a check-box must be showed for each node
*/
public final boolean isShowCheckBoxes() {
return showCheckBoxes;
}
/**
* Define if a check-box must be showed for each node.
* @param showCheckBoxes define if a check-box must be showed for each node
*/
public final void setShowCheckBoxes(boolean showCheckBoxes) {
this.showCheckBoxes = showCheckBoxes;
}
/**
* @return current checked nodes (i.e. nodes having selected the associated check-box)
*/
public final HashSet getCheckedNodes() {
return checkedNodes;
}
/**
* Set current checked nodes (i.e. nodes having selected the associated check-box).
* @param checkedNodes current checked nodes (i.e. nodes having selected the associated check-box)
*/
public void setCheckedNodes(HashSet checkedNodes) {
this.checkedNodes = checkedNodes;
}
/**
* @return define if a check-box must be showed for leaves nodes too
*/
public final boolean isShowCheckBoxesOnLeaves() {
return showCheckBoxesOnLeaves;
}
/**
* Define if a check-box must be showed for leaves nodes too.
* @param showCheckBoxesOnLeaves define if a check-box must be showed for leaves nodes too
*/
public final void setShowCheckBoxesOnLeaves(boolean showCheckBoxesOnLeaves) {
this.showCheckBoxesOnLeaves = showCheckBoxesOnLeaves;
}
/**
* @return retrieve current leaves having their check-boxes selected
*/
public final HashSet getCheckedLeaves() {
HashSet set = new HashSet();
if (showCheckBoxesOnLeaves) {
Iterator it = checkedNodes.iterator();
TreeNode node = null;
while(it.hasNext()) {
node = (TreeNode)it.next();
if (checkedNodes.contains(node) && node.isLeaf())
set.add(node);
}
}
else {
Iterator it = checkedNodes.iterator();
TreeNode node = null;
while(it.hasNext()) {
node = (TreeNode)it.next();
if (checkedNodes.contains(node)) {
for(int i=0;i<node.getChildCount();i++)
if (node.getChildAt(i).isLeaf())
set.add(node.getChildAt(i));
}
}
}
return set;
}
/**
* @return define if root node must be automatically expanded when "expandAllNodes" property is set to <code>false</code>
*/
public final boolean isExpandRoot() {
return expandRoot;
}
/**
* Define if root node must be automatically expanded when "expandAllNodes" property is set to <code>false</code>; default value: <code>true</code>.
* @param expandRoot define if root node must be automatically expanded when "expandAllNodes" property is set to <code>false</code>
*/
public final void setExpandRoot(boolean expandRoot) {
this.expandRoot = expandRoot;
}
/**
* @return mark the state "tree content changed"
*/
public final boolean isChanged() {
return treeChanged;
}
/**
* Method invoked by SearchWindowManager when the specified "textToSeach" pattern has not matchings in the current content
* of binded control.
* This callback can be used to retrieve additional data into control and to search inside new data.
* @param textToSeach patten of text to search
* @return -1 if no additional data is available, otherwise the row index of data just added that satify the pattern
*/
public final int search(String textToSeach) {
return -1;
}
/**
* @return cursor to show on dragging
*/
public final Cursor getDragCursor() {
return dragCursor;
}
/**
* Set the cursor to show on dragging.
* @param dragCursor cursor to show on dragging
*/
public final void setDragCursor(Cursor dragCursor) {
this.dragCursor = dragCursor;
}
}