diff --git a/client/src/org/compiere/apps/AMenu.java b/client/src/org/compiere/apps/AMenu.java index 373bf5c6f7..282797c203 100644 --- a/client/src/org/compiere/apps/AMenu.java +++ b/client/src/org/compiere/apps/AMenu.java @@ -317,7 +317,6 @@ public final class AMenu extends CFrame mainLayout.setVgap(2); // treePanel.addPropertyChangeListener(VTreePanel.NODE_SELECTION, this); - treePanel.addPropertyChangeListener(VTreePanel.NODE_SELECTION_RIGHT, this); // infoPanel.setLayout(infoLayout); infoLayout.setColumns(2); @@ -575,11 +574,6 @@ public final class AMenu extends CFrame */ public void propertyChange(PropertyChangeEvent e) { - if(e.getPropertyName().equals(VTreePanel.NODE_SELECTION_RIGHT)){ - MTreeNode nd = (MTreeNode)e.getNewValue(); - progressBar.setString(nd.toString()); - return; - } MTreeNode nd = (MTreeNode)e.getNewValue(); log.info(nd.getNode_ID() + " - " + nd.toString()); diff --git a/client/src/org/compiere/grid/tree/AdempiereTreeModel.java b/client/src/org/compiere/grid/tree/AdempiereTreeModel.java new file mode 100644 index 0000000000..012262d39d --- /dev/null +++ b/client/src/org/compiere/grid/tree/AdempiereTreeModel.java @@ -0,0 +1,102 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.grid.tree; + +import java.util.logging.Level; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; + +import org.compiere.model.MTree; +import org.compiere.model.MTreeNode; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Trx; + +/** + * AdempiereTreeModel provides a persistable tree model based on an MTree. + * + * @author phib 2008/07/30 + * FR [ 2032092 ] Java 6 improvements to tree drag and drop + */ +public class AdempiereTreeModel extends DefaultTreeModel { + + /** Logger */ + private static CLogger log = CLogger.getCLogger(AdempiereTreeModel.class); + + private MTree m_MTree; + public AdempiereTreeModel(TreeNode root) { + super(root); + } + + public AdempiereTreeModel(MTreeNode root, boolean b) { + super(root, b); + } + + public void setMTree(MTree tree) { + + m_MTree = tree; + + } + + public void saveChangedNodes(MTreeNode from, MTreeNode to) { + int AD_Tree_ID = m_MTree.getAD_Tree_ID(); + Trx trx = Trx.get (Trx.createTrxName("AdempiereTreeModel"), true); + try + { + int no = 0; + for (int i = 0; i < from.getChildCount(); i++) + { + MTreeNode nd = (MTreeNode)from.getChildAt(i); + StringBuffer sql = new StringBuffer("UPDATE "); + sql.append(m_MTree.getNodeTableName()) + .append(" SET Parent_ID=").append(from.getNode_ID()) + .append(", SeqNo=").append(i) + .append(", Updated=SysDate") + .append(" WHERE AD_Tree_ID=").append(AD_Tree_ID) + .append(" AND Node_ID=").append(nd.getNode_ID()); + no = DB.executeUpdate(sql.toString(),trx.getTrxName()); + } + if (from != to) + for (int i = 0; i < to.getChildCount(); i++) + { + MTreeNode nd = (MTreeNode)to.getChildAt(i); + StringBuffer sql = new StringBuffer("UPDATE "); + sql.append(m_MTree.getNodeTableName()) + .append(" SET Parent_ID=").append(to.getNode_ID()) + .append(", SeqNo=").append(i) + .append(", Updated=SysDate") + .append(" WHERE AD_Tree_ID=").append(AD_Tree_ID) + .append(" AND Node_ID=").append(nd.getNode_ID()); + log.fine(sql.toString()); + no = DB.executeUpdate(sql.toString(),trx.getTrxName()); + } + trx.commit(true); + } + catch (Exception e) + { + trx.rollback(); + log.log(Level.SEVERE, "move", e); + } + trx.close(); + trx = null; + log.config("complete"); + + } + + +} diff --git a/client/src/org/compiere/grid/tree/TransferableTreeNode.java b/client/src/org/compiere/grid/tree/TransferableTreeNode.java new file mode 100644 index 0000000000..5606709f8a --- /dev/null +++ b/client/src/org/compiere/grid/tree/TransferableTreeNode.java @@ -0,0 +1,65 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.grid.tree; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +import org.compiere.model.MTreeNode; + +/** + * TransferableTreeNode wraps an MTreeNode into a Transferable for + * use by drag and drop type actions. + * + * + * @author phib 2008/07/30 + * FR [ 2032092 ] Java 6 improvements to tree drag and drop + */ +class TransferableTreeNode implements Transferable { + + public static DataFlavor TREE_NODE_FLAVOR = new DataFlavor(MTreeNode.class, + "Tree Path"); + + DataFlavor flavors[] = { TREE_NODE_FLAVOR }; + + MTreeNode node; + + public TransferableTreeNode(MTreeNode node) { + this.node = node; + } + + public synchronized DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return (flavor.getRepresentationClass() == MTreeNode.class); + } + + public synchronized Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + if (isDataFlavorSupported(flavor)) { + return (Object) node; + } else { + throw new UnsupportedFlavorException(flavor); + } + } + } + + diff --git a/client/src/org/compiere/grid/tree/VTreePanel.java b/client/src/org/compiere/grid/tree/VTreePanel.java index aa225a6c5f..093b12fdd4 100644 --- a/client/src/org/compiere/grid/tree/VTreePanel.java +++ b/client/src/org/compiere/grid/tree/VTreePanel.java @@ -1,5 +1,5 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * + /****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * @@ -23,23 +23,7 @@ import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; -import java.awt.Point; import java.awt.Rectangle; -import java.awt.datatransfer.StringSelection; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragGestureEvent; -import java.awt.dnd.DragGestureListener; -import java.awt.dnd.DragGestureRecognizer; -import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceDragEvent; -import java.awt.dnd.DragSourceDropEvent; -import java.awt.dnd.DragSourceEvent; -import java.awt.dnd.DragSourceListener; -import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetDragEvent; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DropTargetEvent; -import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -54,7 +38,10 @@ import java.util.HashMap; import java.util.Map; import java.util.logging.Level; +import javax.swing.Action; +import javax.swing.ActionMap; import javax.swing.BorderFactory; +import javax.swing.DropMode; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; @@ -66,11 +53,12 @@ import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JToolBar; import javax.swing.JTree; +import javax.swing.KeyStroke; import javax.swing.SwingUtilities; +import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.plaf.SplitPaneUI; import javax.swing.plaf.basic.BasicSplitPaneUI; -import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreePath; @@ -118,12 +106,15 @@ import de.schaeffer.compiere.tools.DocumentSearch; * @author Teo Sarca *
  • BF [ 2866493 ] VTreePanel is not saving who did the node move * https://sourceforge.net/tracker/?func=detail&atid=879332&aid=2866493&group_id=176962 + * + * @author Paul Bowden + *
  • FR [ 2032092 ] Java 6 improvements to tree drag and drop + * https://sourceforge.net/tracker/index.php?func=detail&aid=2032092&group_id=176962&atid=879335 */ public final class VTreePanel extends CPanel - implements ActionListener, DragGestureListener, DragSourceListener, DropTargetListener + implements ActionListener { - - /****************************************************************************** +/****************************************************************************** * Mouse Clicked */ class VTreePanel_mouseAdapter extends java.awt.event.MouseAdapter @@ -188,6 +179,8 @@ public final class VTreePanel extends CPanel protected boolean m_lookAndFeelChanged = false; + private VTreeTransferHandler handler = new VTreeTransferHandler(); + /** * Tree Panel for browsing and editing of a tree. * Need to call initTree @@ -225,12 +218,16 @@ public final class VTreePanel extends CPanel if ("lookAndFeel".equals(evt.getPropertyName())) m_lookAndFeelChanged = true; } - + }); } // base settings - if (editable) - tree.setDropTarget(dropTarget); + if (editable) { + tree.setDragEnabled(true); + tree.setTransferHandler(handler); + tree.setDropMode(DropMode.INSERT); + setMappings(tree); + } else { popMenuTree.remove(mFrom); @@ -258,7 +255,8 @@ public final class VTreePanel extends CPanel log.config("root=" + m_root); m_nodeTableName = vTree.getNodeTableName(); - treeModel = new DefaultTreeModel(m_root, true); + treeModel = new AdempiereTreeModel(m_root, true); + treeModel.setMTree(vTree); tree.setModel(treeModel); // Shortcut Bar @@ -268,7 +266,7 @@ public final class VTreePanel extends CPanel jt.removeAll(); toolbarMap = new HashMap(); Enumeration enTop = m_root.children(); - JToolBar jt = null; + JToolBar jt = null; Map titleMap = new HashMap(); while (enTop.hasMoreElements()) { @@ -299,7 +297,7 @@ public final class VTreePanel extends CPanel jt2.setFloatable(false); jt2.setRollover(true); jt2.setBorder(BorderFactory.createEmptyBorder()); - + JXTaskPane barPart = new JXTaskPane(); //Begin - [FR 1953769] barPart.setUI(new AdempiereTaskPaneUI()); @@ -309,7 +307,7 @@ public final class VTreePanel extends CPanel barPart.setLayout(new BorderLayout()); barPart.add(jt2, BorderLayout.NORTH); barPart.setTitle(titleMap.get(jt2)); - + bar.add(barPart); //Begin - [FR 1953769] bar.setBackground(AdempierePLAF.getFormBackground()); @@ -324,7 +322,7 @@ public final class VTreePanel extends CPanel private BorderLayout mainLayout = new BorderLayout(); private JTree tree = new JTree(); - private DefaultTreeModel treeModel; + private AdempiereTreeModel treeModel; private DefaultTreeSelectionModel treeSelect = new DefaultTreeSelectionModel(); private CPanel southPanel = new CPanel(); private CCheckBox treeExpand = new CCheckBox(); @@ -337,6 +335,7 @@ public final class VTreePanel extends CPanel private JXTaskPaneContainer bar = new JXTaskPaneContainer(); private java.util.List toolbar; private HashMap toolbarMap; + private int toolBarCols=3; private CMenuItem mBarAdd = new CMenuItem(); private CMenuItem mBarRemove = new CMenuItem(); private BorderLayout southLayout = new BorderLayout(); @@ -359,7 +358,6 @@ public final class VTreePanel extends CPanel private MTreeNode m_root = null; - private MTreeNode m_moveNode; // the node to move private String m_search = ""; private Enumeration m_nodeEn; private MTreeNode m_selectedNode; // the selected model node @@ -369,8 +367,6 @@ public final class VTreePanel extends CPanel /** Property Listener NodeSelected by Left Click */ public static final String NODE_SELECTION = "NodeSelected"; - /** Property Listener NodeSelected by Right Click */ - public static final String NODE_SELECTION_RIGHT = "NodeSelectedRight"; /** * Static Component initialization. @@ -398,12 +394,12 @@ public final class VTreePanel extends CPanel treePane.getViewport().add(tree, null); treePane.setBorder(new ShadowBorder()); tree.setBorder(BorderFactory.createEmptyBorder()); - + CPanel treePart = new CPanel(); treePart.setLayout(new BorderLayout()); treePart.add(treePane, BorderLayout.CENTER); treePart.setBorder(BorderFactory.createEmptyBorder()); - + // treeExpand.setText(Msg.getMsg(Env.getCtx(), "ExpandTree")); treeExpand.setActionCommand("Expand"); @@ -431,16 +427,22 @@ public final class VTreePanel extends CPanel removeSplitPaneBorder(); this.add(centerSplitPane, BorderLayout.CENTER); - + // mFrom.setText(Msg.getMsg(Env.getCtx(), "ItemMove")); - mFrom.setActionCommand("From"); + mFrom.setActionCommand((String)TransferHandler.getCutAction(). + getValue(Action.NAME)); mFrom.addActionListener(this); - mTo.setEnabled(false); + mFrom.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK)); mTo.setText(Msg.getMsg(Env.getCtx(), "ItemInsert")); - mTo.setActionCommand("To"); + mTo.setActionCommand((String)TransferHandler.getPasteAction(). + getValue(Action.NAME)); + mTo.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK)); + mTo.setMnemonic(KeyEvent.VK_V); mTo.addActionListener(this); - + mBarAdd.setText(Msg.getMsg(Env.getCtx(), "BarAdd")); mBarAdd.setActionCommand("BarAdd"); mBarAdd.addActionListener(this); @@ -452,7 +454,7 @@ public final class VTreePanel extends CPanel popMenuTree.add(mBarAdd); popMenuTree.add(mFrom); if(!m_hasBar){ - popMenuTree.addSeparator(); + popMenuTree.addSeparator(); } popMenuTree.add(mTo); popMenuBar.setLightWeightPopupEnabled(false); @@ -469,7 +471,7 @@ public final class VTreePanel extends CPanel } } } - + /** * Set Divider Location * @param location location (80 default) @@ -478,7 +480,7 @@ public final class VTreePanel extends CPanel { centerSplitPane.setDividerLocation(location); } // setDividerLocation - + /** * Get Divider Location * @return divider location @@ -487,223 +489,7 @@ public final class VTreePanel extends CPanel { return centerSplitPane.getDividerLocation(); } // getDividerLocation - - - /************************************************************************* - * Drag & Drop - */ - protected DragSource dragSource - = DragSource.getDefaultDragSource(); - protected DropTarget dropTarget - = new DropTarget(tree, DnDConstants.ACTION_MOVE, this, true, null); - protected DragGestureRecognizer recognizer - = dragSource.createDefaultDragGestureRecognizer(tree, DnDConstants.ACTION_MOVE, this); - - - /** - * Drag Gesture Interface ** Start ** - * @param e event - */ - public void dragGestureRecognized(DragGestureEvent e) - { - if (!m_editable) - return; - // - try - { - m_moveNode = (MTreeNode)tree.getSelectionPath().getLastPathComponent(); - } - catch (Exception ex) // nothing selected - { - return; - } - // start moving - StringSelection content = new StringSelection(m_moveNode.toString()); - e.startDrag(DragSource.DefaultMoveDrop, // cursor - content, // Transferable - this); - log.fine( "Drag: " + m_moveNode.toString()); - } // dragGestureRecognized - - - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dragDropEnd(DragSourceDropEvent e) {} - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dragEnter(DragSourceDragEvent e) {} - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dragExit(DragSourceEvent e) {} - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dragOver(DragSourceDragEvent e) {} - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dropActionChanged(DragSourceDragEvent e) {} - - /** - * DropTargetListener interface - * @param e event - */ - public void dragEnter(DropTargetDragEvent e) - { - e.acceptDrag(DnDConstants.ACTION_MOVE); - } - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dropActionChanged(DropTargetDragEvent e) {} - /** - * DragSourceListener interface - noop - * @param e event - */ - public void dragExit(DropTargetEvent e) {} - - - /** - * Drag over ** Between ** - * @param e event - */ - public void dragOver(DropTargetDragEvent e) - { - Point mouseLoc = e.getLocation(); // where are we? - TreePath path = tree.getClosestPathForLocation(mouseLoc.x, mouseLoc.y); - tree.setSelectionPath(path); // show it by selecting - MTreeNode toNode = (MTreeNode)path.getLastPathComponent(); - // - // log.fine( "Move: " + toNode); - if (m_moveNode == null // nothing to move - || toNode == null) // nothing to drop on - e.rejectDrag(); - else - e.acceptDrag(DnDConstants.ACTION_MOVE); - } // dragOver - - - /** - * Drop ** End ** - * @param e event - */ - public void drop(DropTargetDropEvent e) - { - Point mouseLoc = e.getLocation(); // where are we? - TreePath path = tree.getClosestPathForLocation(mouseLoc.x, mouseLoc.y); - tree.setSelectionPath(path); // show it by selecting - MTreeNode toNode = (MTreeNode)path.getLastPathComponent(); - // - log.fine( "Drop: " + toNode); - if (m_moveNode == null // nothing to move - || toNode == null) // nothing to drop on - { - e.rejectDrop(); - return; - } - // - e.acceptDrop(DnDConstants.ACTION_MOVE); - moveNode(m_moveNode, toNode); - - e.dropComplete(true); - m_moveNode = null; - } // drop - - - /** - * Move TreeNode - * @param movingNode The node to be moved - * @param toNode The target node - */ - private void moveNode(MTreeNode movingNode, MTreeNode toNode) - { - log.info(movingNode.toString() + " to " + toNode.toString()); - - if (movingNode == toNode) - return; - - // remove - final MTreeNode oldParent = (MTreeNode)movingNode.getParent(); - movingNode.removeFromParent(); - treeModel.nodeStructureChanged(oldParent); - - // insert - final MTreeNode newParent; - int index; - if (!toNode.isSummary()) // drop on a child node - { - newParent = (MTreeNode)toNode.getParent(); - index = newParent.getIndex(toNode) + 1; // the next node - } - else // drop on a summary node - { - newParent = toNode; - index = 0; // the first node - } - newParent.insert(movingNode, index); - treeModel.nodeStructureChanged(newParent); - - // *** Save changes to disk - try - { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - Trx.run(new TrxRunnable() { - public void run(String trxName) { - for (int i = 0; i < oldParent.getChildCount(); i++) - { - MTreeNode nd = (MTreeNode)oldParent.getChildAt(i); - updateTreeNode(nd.getNode_ID(), oldParent.getNode_ID(), i, trxName); - } - if (oldParent != newParent) - { - for (int i = 0; i < newParent.getChildCount(); i++) - { - MTreeNode nd = (MTreeNode)newParent.getChildAt(i); - updateTreeNode(nd.getNode_ID(), newParent.getNode_ID(), i, trxName); - } - } - } - }); - } - catch (Exception e) - { - log.log(Level.SEVERE, "move", e); - ADialog.error(m_WindowNo, this, "TreeUpdateError", e.getLocalizedMessage()); - } - finally - { - setCursor(Cursor.getDefaultCursor()); - } - log.config("complete"); - } // moveNode - private int updateTreeNode(int Node_ID, int Parent_ID, int SeqNo, String trxName) - { - // We do not use parametrized statements because we need to log these migration scripts - StringBuffer sql = new StringBuffer("UPDATE "); - sql.append(m_nodeTableName) - .append(" SET Parent_ID=").append(Parent_ID) - .append(", SeqNo=").append(SeqNo) - .append(", Updated=SysDate") - .append(", UpdatedBy=").append(Env.getAD_User_ID(Env.getCtx())) - .append(" WHERE AD_Tree_ID=").append(m_AD_Tree_ID) - .append(" AND Node_ID=").append(Node_ID); - log.fine(sql.toString()); - int no = DB.executeUpdateEx(sql.toString(), trxName); - return no; - } - - - /*************************************************************************/ /** * Enter Key @@ -803,24 +589,22 @@ public final class VTreePanel extends CPanel // Right Click for PopUp else if ((m_editable || m_hasBar) - && SwingUtilities.isRightMouseButton(e) - && tree.getSelectionPath() != null) // need select first + && SwingUtilities.isRightMouseButton(e) ) { int selRow = tree.getRowForLocation(e.getX(), e.getY()); - TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); - if(selRow != -1){ - tree.setSelectionPath(selPath); - + if(selRow != -1) + { + tree.setSelectionRow(selRow); + } + if (tree.getSelectionPath() != null) // need select first + { + MTreeNode nd = (MTreeNode)tree.getSelectionPath().getLastPathComponent(); + if (nd.isLeaf()) // only add leaves to bar + mBarAdd.setEnabled(true); + else + mBarAdd.setEnabled(false); Rectangle r = tree.getPathBounds(tree.getSelectionPath()); - if(r!=null){ - popMenuTree.show(tree, (int)r.getMaxX(), (int)r.getY()); - }else{ - popMenuTree.show(tree, e.getX(), e.getY()); - } - if(m_hasBar){ - MTreeNode nd = (MTreeNode)tree.getSelectionPath().getLastPathComponent(); - firePropertyChange(NODE_SELECTION_RIGHT, null, nd); - } + popMenuTree.show(tree, (int)r.getMaxX(), (int)r.getY()); } } } // JTree @@ -879,14 +663,14 @@ public final class VTreePanel extends CPanel { if (m_root == null) return false; - log.config("NodeID=" + nodeID + log.config("NodeID=" + nodeID + ", Show=" + show + ", root=" + m_root); // try to find the node MTreeNode node = m_root.findNode (nodeID); if (node != null) { TreePath treePath = new TreePath(node.getPath()); - log.config("Node=" + node + log.config("Node=" + node + ", Path=" + treePath.toString()); tree.setSelectionPath(treePath); if (show) @@ -913,7 +697,7 @@ public final class VTreePanel extends CPanel firePropertyChange(NODE_SELECTION, null, nd); } // setSelectedNode - + /************************************************************************** * Node Changed - synchronize Node * @@ -928,13 +712,13 @@ public final class VTreePanel extends CPanel String name, String description, boolean isSummary, String imageIndicator) { log.config("Save=" + save + ", KeyID=" + keyID - + ", Name=" + name + ", Description=" + description + + ", Name=" + name + ", Description=" + description + ", IsSummary=" + isSummary + ", ImageInd=" + imageIndicator + ", root=" + m_root); // if ID==0=root - don't update it if (keyID == 0) - return; - + return; + // try to find the node MTreeNode node = m_root.findNode(keyID); @@ -1000,13 +784,16 @@ public final class VTreePanel extends CPanel // popup menu commands else if (e.getSource() instanceof JMenuItem) { - if (e.getActionCommand().equals("From")) - moveFrom(); - else if (e.getActionCommand().equals("To")) - moveTo(); - else if (e.getActionCommand().equals("BarAdd")) + String action = (String)e.getActionCommand(); + Action a = tree.getActionMap().get(action); + if (a != null) { + a.actionPerformed(new ActionEvent(tree, + ActionEvent.ACTION_PERFORMED, + null)); + } + else if (action.equals("BarAdd")) barAdd(); - else if (e.getActionCommand().equals("BarRemove")) + else if (action.equals("BarRemove")) barRemove(); } @@ -1017,35 +804,6 @@ public final class VTreePanel extends CPanel } } // actionPerformed - - /*************************************************************************/ - - /** - * Copy Node into buffer - */ - private void moveFrom() - { - m_moveNode = (MTreeNode)tree.getSelectionPath().getLastPathComponent(); - if (m_moveNode != null) - mTo.setEnabled(true); // enable menu - } // mFrom_actionPerformed - - /** - * Move Node - */ - private void moveTo() - { - mFrom.setEnabled(true); - mTo.setEnabled(false); - if (m_moveNode == null) - return; - - MTreeNode toNode = (MTreeNode)tree.getSelectionPath().getLastPathComponent(); - moveNode(m_moveNode, toNode); - // cleanup - m_moveNode = null; - } // mTo_actionPerformed - /** * Add selected TreeNode to Bar */ @@ -1057,9 +815,9 @@ public final class VTreePanel extends CPanel else if (CLogger.retrieveException().getMessage().indexOf("ORA-00001")!=-1) ADialog.error(0, this, "BookmarkExist", null); } // barAdd - + /** - * Returns the top level parent JToolBar for the given MTreenode. If the parent is not on + * Returns the top level parent JToolBar for the given MTreenode. If the parent is not on * the CPanel yet a new one is created and added. * @param nd * @return top level parent JToolBar for the given MTreenode @@ -1168,7 +926,7 @@ public final class VTreePanel extends CPanel bar.remove(parentPanel); //remove from toolBarMap.. toolbarMap.values().remove(parentBar); - + } bar.validate(); bar.repaint(); @@ -1231,8 +989,16 @@ public final class VTreePanel extends CPanel } super.paint(g); } - - //CHANGED - SET BUSY ADDED + + private void setMappings(JTree tree) { + ActionMap map = tree.getActionMap(); + map.put(TransferHandler.getCutAction().getValue(Action.NAME), + TransferHandler.getCutAction()); + map.put(TransferHandler.getPasteAction().getValue(Action.NAME), + TransferHandler.getPasteAction()); + } + + //CHANGED - SET BUSY ADDED /** * Indicate Busy * @param busy busy @@ -1256,8 +1022,9 @@ public final class VTreePanel extends CPanel treeSearch.setCursor(Cursor.getDefaultCursor()); } } // set Busy - - + } // VTreePanel + + diff --git a/client/src/org/compiere/grid/tree/VTreeTransferHandler.java b/client/src/org/compiere/grid/tree/VTreeTransferHandler.java new file mode 100644 index 0000000000..9de5485a94 --- /dev/null +++ b/client/src/org/compiere/grid/tree/VTreeTransferHandler.java @@ -0,0 +1,123 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.grid.tree; + +import java.awt.datatransfer.Transferable; + +import javax.swing.JComponent; +import javax.swing.JTree; +import javax.swing.TransferHandler; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import org.compiere.model.MTreeNode; + +/** + * VTreeTransferHandler provides the TransferHandler for dragging and dropping + * within a tree. See VTreePanel. + * + * + * @author phib 2008/07/30 + * FR [ 2032092 ] Java 6 improvements to tree drag and drop + */ +public class VTreeTransferHandler extends TransferHandler { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public int getSourceActions(JComponent c) { + return TransferHandler.MOVE; + } + + protected Transferable createTransferable(JComponent c) { + JTree tree = (JTree) c; + MTreeNode node = (MTreeNode) tree.getSelectionPath().getLastPathComponent(); + return new TransferableTreeNode(node); + } + + protected void exportDone(JComponent c, Transferable t, int action) { + if (action == MOVE) { + JTree tree = (JTree) c; + MTreeNode node = null; + try { + node = (MTreeNode) t.getTransferData(TransferableTreeNode.TREE_NODE_FLAVOR); + } catch (Exception e) { + // ignore + } + + if ( node != null ) + ((DefaultTreeModel) tree.getModel()).removeNodeFromParent(node); + } + } + + public boolean canImport(TransferSupport info) { + // Check for flavor + if (!info.isDataFlavorSupported(TransferableTreeNode.TREE_NODE_FLAVOR)) { + return false; + } + return true; + } + + public boolean importData(TransferHandler.TransferSupport info) { + if (!canImport(info)) + return false; + + JTree tree = (JTree) info.getComponent(); + AdempiereTreeModel model = (AdempiereTreeModel) tree.getModel(); + Transferable t = info.getTransferable(); + MTreeNode to = null; + MTreeNode from = null; + int index; + try { + from = (MTreeNode)t.getTransferData(TransferableTreeNode.TREE_NODE_FLAVOR); + } + catch (Exception e) { return false; } + + if (info.isDrop()) { + JTree.DropLocation dl = (JTree.DropLocation)info.getDropLocation(); + to = (MTreeNode) dl.getPath().getLastPathComponent(); + + if (from == to) + return false; + + index = dl.getChildIndex(); + if ( index == -1 ) + index = 0; // insert as first child + + } + else { // it's a paste + MTreeNode selected = (MTreeNode) tree.getSelectionPath().getLastPathComponent(); + if ( selected.isLeaf() ) { + to = (MTreeNode) selected.getParent(); + index = to.getIndex(selected) + 1; // insert after selected + } + else { + to = selected; + index = 0; + } + } + + model.insertNodeInto(from, to, index); + tree.scrollPathToVisible(new TreePath(from.getPath())); // display from's new location + model.saveChangedNodes(from, to); + + return true; + } + +}