001: /*
002: * <copyright>
003: *
004: * Copyright 2000-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.tools.csmart.ui.tree;
028:
029: import org.cougaar.tools.csmart.experiment.HostComponent;
030: import org.cougaar.tools.csmart.experiment.NodeComponent;
031: import org.cougaar.tools.csmart.society.AgentComponent;
032: import org.cougaar.tools.csmart.ui.viewer.CSMART;
033: import org.cougaar.util.log.Logger;
034:
035: import javax.swing.tree.DefaultMutableTreeNode;
036: import javax.swing.tree.DefaultTreeModel;
037: import javax.swing.tree.TreePath;
038: import java.awt.datatransfer.DataFlavor;
039: import java.awt.datatransfer.Transferable;
040: import java.awt.dnd.DnDConstants;
041: import java.io.IOException;
042: import java.io.ObjectInputStream;
043:
044: /**
045: * Provides method definitions for abstract methods in DNDTree.
046: * Encapsulates all information specific to the drag-and-drop
047: * trees in the Console tool, leaving DNDTree as the generic
048: * drag-and-drop tree class.
049: */
050:
051: public class ConsoleDNDTree extends DNDTree {
052:
053: private transient Logger log;
054:
055: public static CSMARTDataFlavor agentFlavor = new CSMARTDataFlavor(
056: DefaultMutableTreeNode.class, AgentComponent.class,
057: ConsoleDNDTree.class, "CSMART Agent");
058: public static CSMARTDataFlavor nodeFlavor = new CSMARTDataFlavor(
059: DefaultMutableTreeNode.class, NodeComponent.class,
060: ConsoleDNDTree.class, "CSMART Node");
061: public static CSMARTDataFlavor hostFlavor = new CSMARTDataFlavor(
062: DefaultMutableTreeNode.class, HostComponent.class,
063: ConsoleDNDTree.class, "CSMART Host");
064: public static CSMARTDataFlavor agentArrayFlavor = new CSMARTDataFlavor(
065: DMTNArray.class, AgentComponent.class,
066: ConsoleDNDTree.class, "CSMART Agent");
067: public static CSMARTDataFlavor nodeArrayFlavor = new CSMARTDataFlavor(
068: DMTNArray.class, NodeComponent.class, ConsoleDNDTree.class,
069: "CSMART Node");
070:
071: public ConsoleDNDTree(DefaultTreeModel model) {
072: super (model);
073: createLogger();
074: }
075:
076: private void createLogger() {
077: log = CSMART.createLogger(this .getClass().getName());
078: }
079:
080: protected boolean supportsMultiDrag() {
081: return true;
082: }
083:
084: /**
085: * Return true if object can be dragged and false otherwise.
086: */
087:
088: public boolean isDraggable(Object selected) {
089: DefaultMutableTreeNode node = (DefaultMutableTreeNode) selected;
090: Object userObject = node.getUserObject();
091: ConsoleTreeObject cto = (ConsoleTreeObject) userObject;
092: if (cto.isHost())
093: return true;
094: if (node.getParent() == null)
095: return false; // don't ever drag root
096: return true;
097: }
098:
099: /**
100: * Make a draggable object from a DefaultMutableTreeNode.
101: */
102:
103: public Transferable makeDraggableObject(Object o) {
104: if (o instanceof DefaultMutableTreeNode) {
105: return new ConsoleTreeObjectTransferable(
106: (DefaultMutableTreeNode) o);
107: } else if (o instanceof DMTNArray) {
108: return new CTOArrayTransferable((DMTNArray) o);
109: }
110: throw new IllegalArgumentException(
111: "Not a DefaultMutableTreeNode or DMTNArray");
112: }
113:
114: /**
115: * The node being dropped contains either a NodeComponent or AgentComponent.
116: * Uses ConsoleTreeObject class to enforce these rules:
117: * no component type can be dropped on itself
118: * nodes can't be dropped on the "Unassigned Agents" tree root
119: * nodes can't be dropped on agents
120: * agents can't be dropped on hosts (they have to be dropped on nodes)
121: * agents can't be dropped on the "Unassigned Nodes" tree root.
122: */
123:
124: protected int isDroppable(DataFlavor[] flavors,
125: DefaultMutableTreeNode target) {
126: Object userObject = target.getUserObject();
127: ConsoleTreeObject cto;
128: if (userObject instanceof ConsoleTreeObject) {
129: cto = (ConsoleTreeObject) userObject;
130: for (int i = 0; i < flavors.length; i++) {
131: if (cto.allowsDataFlavor(flavors[i])) {
132: // if(log.isDebugEnabled()) {
133: // log.debug(cto + " allows " + flavors[i]);
134: // }
135: return DnDConstants.ACTION_MOVE;
136: }
137: // if(log.isDebugEnabled()) {
138: // log.debug(cto + " disallows " + flavors[i]);
139: // }
140: }
141: // if(log.isDebugEnabled()) {
142: // log.debug(cto + " accepts none of the flavors");
143: // }
144: } else {
145: // if(log.isDebugEnabled()) {
146: // log.debug(target + " has type " + userObject.getClass());
147: // }
148: }
149: return DnDConstants.ACTION_NONE;
150: }
151:
152: /**
153: * Adds dropped object to this tree; called by drop method.
154: * Object is either a ConsoleTreeObject or a DefaultMutableTreeNode
155: * depending on whether the user is dragging a leaf or a node.
156: * Returns true if successful.
157: * This handles the tree and the CSMARTConsole class handles
158: * notifying the configurable components.
159: */
160:
161: public int addElement(Transferable transferable,
162: DefaultMutableTreeNode target, DefaultMutableTreeNode before) {
163: Object data = null;
164: try {
165: data = transferable.getTransferData(transferable
166: .getTransferDataFlavors()[0]);
167: } catch (Exception e) {
168: if (log.isErrorEnabled()) {
169: log.error("Exception", e);
170: }
171: return DnDConstants.ACTION_NONE;
172: }
173: if (data instanceof DMTNArray) {
174: DMTNArray nodes = (DMTNArray) data;
175: for (int i = 0; i < nodes.nodes.length; i++) {
176: addElement(nodes.nodes[i], target, before);
177: }
178: } else {
179: addElement((DefaultMutableTreeNode) data, target, before);
180: }
181: return DnDConstants.ACTION_MOVE;
182: }
183:
184: private void addElement(DefaultMutableTreeNode source,
185: DefaultMutableTreeNode target, DefaultMutableTreeNode before) {
186: ConsoleTreeObject cto = (ConsoleTreeObject) source
187: .getUserObject();
188: DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
189: cto, !cto.isAgent());
190: int ix = target.getChildCount(); // Drop at end by default
191: DefaultTreeModel model = (DefaultTreeModel) getModel();
192: if (before != null) { // If before specified, put it there.
193: ix = model.getIndexOfChild(target, before);
194: }
195: model.insertNodeInto(newNode, target, ix);
196: int n = source.getChildCount();
197: DefaultMutableTreeNode[] children = new DefaultMutableTreeNode[n];
198: for (int i = 0; i < n; i++) {
199: children[i] = (DefaultMutableTreeNode) source.getChildAt(i);
200: }
201: for (int i = 0; i < n; i++) {
202: model.insertNodeInto(children[i], newNode, i);
203: }
204: scrollPathToVisible(new TreePath(newNode.getPath()));
205: }
206:
207: private void readObject(ObjectInputStream ois) throws IOException,
208: ClassNotFoundException {
209: ois.defaultReadObject();
210: createLogger();
211: }
212:
213: }
|