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; } }