001 /****************************************************************************** 002 * Copyright (C) MActor Developers. All rights reserved. * 003 * ---------------------------------------------------------------------------* 004 * This file is part of MActor. * 005 * * 006 * MActor is free software; you can redistribute it and/or modify * 007 * it under the terms of the GNU General Public License as published by * 008 * the Free Software Foundation; either version 2 of the License, or * 009 * (at your option) any later version. * 010 * * 011 * MActor is distributed in the hope that it will be useful, * 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 014 * GNU General Public License for more details. * 015 * * 016 * You should have received a copy of the GNU General Public License * 017 * along with MActor; if not, write to the Free Software * 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * 019 ******************************************************************************/ 020 package org.mactor.ui.gui.project; 021 022 import java.awt.Color; 023 import java.awt.Component; 024 import java.awt.Point; 025 import java.awt.datatransfer.StringSelection; 026 import java.awt.datatransfer.Transferable; 027 import java.awt.dnd.DnDConstants; 028 import java.awt.dnd.DragGestureEvent; 029 import java.awt.dnd.DragGestureListener; 030 import java.awt.dnd.DragSource; 031 import java.awt.dnd.DragSourceAdapter; 032 import java.awt.dnd.DragSourceContext; 033 import java.awt.dnd.DragSourceDragEvent; 034 import java.awt.dnd.DragSourceDropEvent; 035 import java.awt.dnd.DragSourceListener; 036 import java.awt.dnd.DropTarget; 037 import java.awt.dnd.DropTargetAdapter; 038 import java.awt.dnd.DropTargetDragEvent; 039 import java.awt.dnd.DropTargetDropEvent; 040 041 import javax.swing.BorderFactory; 042 import javax.swing.Icon; 043 import javax.swing.JLabel; 044 import javax.swing.JTree; 045 import javax.swing.TransferHandler; 046 import javax.swing.border.Border; 047 import javax.swing.border.LineBorder; 048 import javax.swing.tree.DefaultTreeCellRenderer; 049 import javax.swing.tree.TreePath; 050 051 import org.mactor.framework.MactorException; 052 import org.mactor.ui.gui.GuiUtil; 053 054 public class ProjectTree extends JTree { 055 DragSource dragSource; 056 DragSourceContext dragSourceContext; 057 ProjectTreeNode draggedNode; 058 ProjectTreeNode currentDragOverNode; 059 int currentDragRow = -1; 060 boolean dropUnder; 061 boolean dropInto; 062 Point currentDragLocation; 063 private static Transferable dummy = new StringSelection(""); 064 private DragSourceListener dragSourceListener = new DragSourceAdapter() { 065 public void dragEnter(DragSourceDragEvent event) { 066 dragSourceContext = event.getDragSourceContext(); 067 } 068 @Override 069 public void dragDropEnd(DragSourceDropEvent arg0) { 070 super.dragDropEnd(arg0); 071 clearDragInfo(); 072 } 073 }; 074 private void clearDragInfo() { 075 draggedNode = null; 076 dragSourceContext = null; 077 currentDragRow = -1; 078 currentDragLocation = null; 079 currentDragOverNode = null; 080 dropInto = false; 081 dropUnder = false; 082 repaint(); 083 } 084 DragGestureListener dragGestureListener = new DragGestureListener() { 085 public void dragGestureRecognized(DragGestureEvent event) { 086 TreePath path = getSelectionPath(); 087 if (path != null) { 088 draggedNode = (ProjectTreeNode) path.getLastPathComponent(); 089 dragSource.startDrag(event, DragSource.DefaultMoveDrop, dummy, dragSourceListener); 090 } 091 } 092 }; 093 public ProjectTree(ProjectModel model) { 094 super(model); 095 setDropTarget(new DropTarget(this, new ProjectTreeDropListener())); 096 setCellRenderer(new ProjectTreeCellRenderer()); 097 dragSource = DragSource.getDefaultDragSource(); 098 dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dragGestureListener); 099 } 100 class ProjectTreeCellRenderer extends DefaultTreeCellRenderer { 101 private final Icon INCOMING_ICON = GuiUtil.loadIcon("/incoming_16.PNG"); 102 private final Icon SUBSCR_ICON = GuiUtil.loadIcon("/subscribe_16.PNG"); 103 private final Icon CONDITION_ICON = GuiUtil.loadIcon("/condition_16.PNG"); 104 private final Icon LOOP_ICON = GuiUtil.loadIcon("/loop_16.PNG"); 105 private final Icon ACTION_ICON = GuiUtil.loadIcon("/action_16.PNG"); 106 private final Icon VALUE_EXTRACT_ICON = GuiUtil.loadIcon("/value_extract_16.PNG"); 107 private final Icon OUTGOING_ICON = GuiUtil.loadIcon("/outgoing_16.PNG"); 108 private final Icon OUTGOING_RESP_ICON = GuiUtil.loadIcon("/outgoing_resp_16.PNG"); 109 private Border dropUnderBorder = BorderFactory.createMatteBorder(0, 0, 2, 0, Color.BLUE); 110 private Border dropInsideBorder = new LineBorder(Color.BLUE, 2); 111 private Border noDrop = BorderFactory.createEmptyBorder(0, 0, 2, 0); 112 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean focus) { 113 Component com = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, focus); 114 if (row == currentDragRow) { 115 if ((dropUnder)) { 116 ((JLabel) com).setBorder(dropUnderBorder); 117 } else if (dropInto) { 118 ((JLabel) com).setBorder(dropInsideBorder); 119 } else { 120 ((JLabel) com).setBorder(noDrop); 121 } 122 } else { 123 ((JLabel) com).setBorder(noDrop); 124 } 125 ProjectTreeNode node = (ProjectTreeNode) value; 126 if (node != null) { 127 if (ProjectNodeType.T_MESSAGE_PUBLISH.equals(node.getNodeType())) 128 setIcon(OUTGOING_ICON); 129 else if (ProjectNodeType.T_MESSAGE_RECEIVE.equals(node.getNodeType())) 130 setIcon(INCOMING_ICON); 131 else if (ProjectNodeType.T_MESSAGE_RESPOND.equals(node.getNodeType())) 132 setIcon(OUTGOING_RESP_ICON); 133 else if (ProjectNodeType.T_MESSAGE_SUBSCRIBE.equals(node.getNodeType())) 134 setIcon(SUBSCR_ICON); 135 else if (ProjectNodeType.T_CONDITION.equals(node.getNodeType())) 136 setIcon(CONDITION_ICON); 137 else if (ProjectNodeType.T_LOOP.equals(node.getNodeType())) 138 setIcon(LOOP_ICON); 139 else if (ProjectNodeType.T_ACTION.equals(node.getNodeType())) 140 setIcon(ACTION_ICON); 141 else if (ProjectNodeType.T_VALUE.equals(node.getNodeType())) 142 setIcon(VALUE_EXTRACT_ICON); 143 } 144 return com; 145 } 146 } 147 class ProjectTreeDropListener extends DropTargetAdapter { 148 @Override 149 public void dragOver(DropTargetDragEvent event) { 150 dropInto = false; 151 dropUnder = false; 152 currentDragOverNode = null; 153 DropAcceptRules.DropAcceptInfo dropAcceptInfo = null; 154 boolean move = true; 155 if (dragSourceContext != null) { 156 if (event.getDropAction() == TransferHandler.MOVE) 157 dragSourceContext.setCursor(DragSource.DefaultMoveDrop); 158 else { 159 move = false; 160 dragSourceContext.setCursor(DragSource.DefaultCopyDrop); 161 } 162 } 163 TreePath path = getPathForLocation(event.getLocation().x, event.getLocation().y); 164 if (path != null) { 165 currentDragOverNode = (ProjectTreeNode) path.getLastPathComponent(); 166 currentDragLocation = event.getLocation(); 167 currentDragRow = getRowForLocation(currentDragLocation.x, currentDragLocation.y); 168 dropUnder = getRowForLocation(currentDragLocation.x, currentDragLocation.y + 6) != currentDragRow; 169 dropAcceptInfo = DropAcceptRules.getDropAcceptInfo(currentDragOverNode, draggedNode); 170 if (dropUnder) { 171 if (move) 172 dropUnder = dropAcceptInfo.isMoveAsideAccepted(); 173 else 174 dropUnder = dropAcceptInfo.isCopyAsideAccepted(); 175 } else { 176 if (move) 177 dropInto = dropAcceptInfo.isMoveIntoAccepted(); 178 else 179 dropInto = dropAcceptInfo.isCopyIntoAccepted(); 180 } 181 if (dragSourceContext != null) { 182 if (!dropInto && !dropUnder) 183 dragSourceContext.setCursor(DragSource.DefaultLinkNoDrop); 184 } 185 } else { 186 dropAcceptInfo = null; 187 event.rejectDrag(); 188 } 189 repaint(); 190 } 191 public void drop(DropTargetDropEvent event) { 192 try { 193 if (currentDragOverNode != null && draggedNode != null && dragSourceContext != null) { 194 boolean move = (event.getDropAction() == TransferHandler.MOVE); 195 if (dropUnder) { 196 if (move) { 197 ((ProjectModel) getModel()).moveAfter(currentDragOverNode, draggedNode); 198 } else { 199 ((ProjectModel) getModel()).copyAfter(currentDragOverNode, draggedNode); 200 } 201 } else if (dropInto) { 202 if (move) { 203 ((ProjectModel) getModel()).moveInto(currentDragOverNode, draggedNode); 204 } else { 205 ((ProjectModel) getModel()).copyInto(currentDragOverNode, draggedNode); 206 } 207 } 208 } 209 } catch (MactorException me) { 210 me.printStackTrace(); 211 } 212 } 213 } 214 }