001: /*
002: * <copyright>
003: *
004: * Copyright 1997-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.mlm.debug.ui;
028:
029: import java.awt.FileDialog;
030: import java.awt.event.ActionEvent;
031: import java.awt.event.ActionListener;
032:
033: import javax.swing.JFrame;
034: import javax.swing.JTree;
035: import javax.swing.tree.DefaultTreeModel;
036: import javax.swing.tree.TreeNode;
037: import javax.swing.tree.TreePath;
038:
039: import org.cougaar.core.mts.MessageAddress;
040:
041: /** Displays information in a tree.
042: This supports dynamically expanded nodes (expanded when the
043: user clicks on a tree node to display more information) and dynamically
044: updated nodes (updated when listeners on the underlying information
045: are notified of changes).
046: */
047:
048: public class UITreeDisplay implements Runnable, ActionListener {
049: private UIPlugin uiPlugin;
050: private String planName;
051: private MessageAddress clusterId;
052: private String command;
053: private UITreeNode root;
054: private JFrame uiFrame;
055: private DefaultTreeModel treeModel;
056: private JTree tree;
057:
058: /** Display the specified data in a tree.
059: All the work is done in the run method so
060: that the main user interface thread which creates this,
061: isn't waiting to fetch the information needed for the tree.
062: @param uiPlugin this user interface plugin
063: @param planName the name of the plan for which to display information
064: @param clusterId the cluster for which to display information
065: @param command UIDisplay.PLAN_COMMAND, PLAN_DETAILS_COMMAND, TASKS_COMMAND,
066: WORKFLOWS_COMMAND, CLUSTER_ASSETS_COMMAND, ALL_ASSETS_COMMAND
067: */
068:
069: public UITreeDisplay(UIPlugin uiPlugin, String planName,
070: MessageAddress clusterId, String command) {
071: this .uiPlugin = uiPlugin;
072: this .planName = planName;
073: this .clusterId = clusterId;
074: this .command = command;
075: }
076:
077: /** Create the root node of the tree and the window to display it in.
078: Fill in the tree here so that delays in accessing information
079: from clusters don't affect the main user interface thread.
080: */
081:
082: public void run() {
083: String title = "";
084:
085: try {
086: if (command.equals(UIDisplay.PLAN_COMMAND)) {
087: root = new UIPlanNode(uiPlugin, planName, clusterId);
088: title = "LogPlan in " + clusterId.getAddress();
089: } else if (command.equals(UIDisplay.PLAN_DETAILS_COMMAND)) {
090: root = new UIPlanDetailsNode(uiPlugin, planName,
091: clusterId);
092: title = "LogPlan Details in " + clusterId.getAddress();
093: } else if (command.equals(UIDisplay.TASKS_COMMAND)) {
094: root = new UITaskCollectionNode(uiPlugin, planName,
095: clusterId);
096: title = "Expandable Tasks in " + clusterId.getAddress();
097: } else if (command.equals(UIDisplay.WORKFLOWS_COMMAND)) {
098: root = new UIWorkflowCollectionNode(uiPlugin, planName,
099: clusterId);
100: title = "Allocatable Workflows in "
101: + clusterId.getAddress();
102: } else if (command.equals(UIDisplay.CLUSTER_ASSETS_COMMAND)) {
103: root = new UIClusterAssetsNode(uiPlugin, planName,
104: clusterId);
105: title = "Cluster Assets in " + clusterId.getAddress();
106: } else if (command.equals(UIDisplay.ALL_ASSETS_COMMAND)) {
107: root = new UIAllAssetsNode(uiPlugin, planName,
108: clusterId);
109: title = "All Assets in " + clusterId.getAddress();
110: } else {
111: new UIDisplayError("This request is not supported.");
112: return;
113: }
114: } catch (UINoPlanException e) {
115: new UIDisplayError(e.getMessage());
116: return; // nothing to display
117: }
118: treeModel = new DefaultTreeModel(root);
119: root.setTreeModel(treeModel);
120: tree = new JTree(treeModel);
121:
122: // for doing custom tree cell rendering, such as using color
123: // tree.setCellRenderer(new UITreeCellRenderer());
124: // create frame with update function if not displaying local cluster
125: // and with save (to file) function
126: // don't provide expand button for log plan details, as expansion
127: // is circular due to cluster object class definitions
128: if (command.equals(UIDisplay.PLAN_DETAILS_COMMAND))
129: uiFrame = new UIFrame(title, tree, this , false, true, false);
130: else
131: uiFrame = new UIFrame(title, tree, this , false, true, true);
132: }
133:
134: /** Called when:
135: the user invokes the save function; saves the tree to a file.
136: the user invokes the update function; fetches new data and reloads the tree.
137: the user invokes the expand action; expands the tree
138: @param e the action event for the save menu
139: */
140:
141: public void actionPerformed(ActionEvent e) {
142: String command = e.getActionCommand();
143: synchronized (root) {
144: if (command.equals(UIFrame.SAVE_COMMAND)) {
145: FileDialog fileDialog = new FileDialog(uiFrame, "Save",
146: FileDialog.SAVE);
147: fileDialog.show();
148: String dirname = fileDialog.getDirectory();
149: String filename = fileDialog.getFile();
150: if ((dirname != null) && (filename != null))
151: root.saveTree(dirname + filename);
152: } else if (command.equals(UIFrame.UPDATE_COMMAND)) {
153: root.invalidateChildren(); // children cache is out of date, reload them
154: treeModel.reload(root); // reload this root
155: } else if (command.equals(UIFrame.EXPAND_COMMAND)) {
156: expandTree(root);
157: } else
158: System.out.println("Received unknown action event: "
159: + command);
160: }
161: }
162:
163: private void expandTree(TreeNode node) {
164: if (node.isLeaf())
165: return;
166: int n = node.getChildCount();
167: for (int i = 0; i < n; i++) {
168: TreeNode childNode = node.getChildAt(i);
169: TreePath path = new TreePath(treeModel
170: .getPathToRoot(childNode));
171: tree.expandPath(path);
172: tree.fireTreeExpanded(path);
173: expandTree(childNode);
174: }
175: }
176: }
|