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 }