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.event.ActionEvent;
030: import java.awt.event.ActionListener;
031: import java.util.Enumeration;
032: import java.util.Vector;
033:
034: import javax.swing.JFrame;
035:
036: import org.cougaar.core.blackboard.IncrementalSubscription;
037: import org.cougaar.core.mts.MessageAddress;
038: import org.cougaar.planning.ldm.asset.Asset;
039: import org.cougaar.util.OptionPane;
040: import org.cougaar.util.UnaryPredicate;
041:
042: /** Displays information in a vertical bar graph.
043: */
044:
045: public class UIBarGraphDisplay implements Runnable, ActionListener,
046: UISubscriber {
047: private UIPlugin uiPlugin;
048: private String planName;
049: private MessageAddress clusterId;
050: private String command;
051: private UIBarGraph uiBarGraph;
052: private UIBarGraphSource dataSource;
053: private Vector myAssets = new Vector(10);
054: private boolean graphDisplayed = false;
055: private String title = "";
056: private UIFrame uiFrame;
057:
058: /** Contains the correspondence between display and data source.
059: */
060:
061: /** Display the specified data (either assets or scheduled assets)
062: in a bar graph.
063: All the work is done in the run method so
064: that the main user interface thread which creates this,
065: isn't waiting to fetch the information needed for the bar graph.
066: @param uiPlugin this user interface plugin
067: @param planName the name of the plan for which to display information
068: @param clusterId the cluster for which to display information
069: @param command UIDisplay.ASSET_SCHEDULE_COMMAND or UIDisplay.ASSETS_COMMAND
070: */
071:
072: public UIBarGraphDisplay(UIPlugin uiPlugin, String planName,
073: MessageAddress clusterId, String command) {
074: this .uiPlugin = uiPlugin;
075: this .planName = planName;
076: this .clusterId = clusterId;
077: this .command = command;
078: // uiPlugin.subscribe(this, assetPredicate());
079: }
080:
081: private static UnaryPredicate assetPredicate() {
082: return new UnaryPredicate() {
083: public boolean execute(Object o) {
084: //System.out.println("Predicate called with: " + o.toString());
085: return (o instanceof Asset);
086: }
087: };
088: }
089:
090: public synchronized void subscriptionChanged(
091: IncrementalSubscription container) {
092: Enumeration added = container.getAddedList();
093: while (added.hasMoreElements())
094: myAssets.addElement(added.nextElement());
095: Enumeration removed = container.getRemovedList();
096: while (removed.hasMoreElements())
097: myAssets.removeElement(removed.nextElement());
098: Enumeration changed = container.getChangedList();
099: while (changed.hasMoreElements()) {
100: Object o = changed.nextElement();
101: myAssets.removeElement(o);
102: myAssets.addElement(o);
103: }
104: }
105:
106: /** Create the data source for the bar graph, the bar graph, and its window.
107: Fill in the graph here so that delays in accessing information
108: from clusters don't affect the main user interface thread.
109: Register as a listener for changes in the information in the bar graph.
110: */
111:
112: public void run() {
113: title = "";
114:
115: try {
116: if (command.equals(UIDisplay.ASSET_SCHEDULE_COMMAND)) {
117: // asset name is null for graph all assets
118: dataSource = new UISchedule(uiPlugin, planName,
119: clusterId, null, this );
120: title = "Asset Schedule in " + clusterId.getAddress();
121: } else if (command
122: .equals(UIDisplay.SINGLE_ASSET_SCHEDULE_COMMAND)) {
123: Vector tmp = uiPlugin.getPhysicalAssetNames();
124: String assetNames[] = new String[tmp.size()];
125: tmp.copyInto(assetNames);
126: String assetChosen = (String) OptionPane
127: .showInputDialog(new JFrame(),
128: "Choose an asset:", "Asset",
129: OptionPane.QUESTION_MESSAGE, null,
130: assetNames, null);
131: if (assetChosen == null)
132: return;
133: // create information for bar graph schedule for chosen asset
134: dataSource = new UISchedule(uiPlugin, planName,
135: clusterId, assetChosen, this );
136: title = "Single Asset Schedule in "
137: + clusterId.getAddress();
138: } else if (command.equals(UIDisplay.ASSETS_COMMAND)) {
139: dataSource = new UIAssets(uiPlugin, planName,
140: clusterId, this );
141: title = "Assets in " + clusterId.getAddress();
142: } else {
143: new UIDisplayError("This request is not supported.");
144: return;
145: }
146: } catch (UINoPlanException e) {
147: new UIDisplayError(e.getMessage());
148: return;
149: }
150: uiBarGraph = new UIBarGraph();
151: // create frame with update function (if non-local) and no save function
152: uiFrame = new UIFrame(title, uiBarGraph, this , false, false,
153: false);
154: // dataSource.registerListener(this);
155: dataSource.startSubscription();
156: }
157:
158: /** Redisplay bar graph.
159: This gets called:
160: if the dataSource (a collection) is notified that it was changed or
161: the user requests an update,
162: i.e. this is used for changes stimulated either internally
163: (the data changed) or externally (the user wants an update).
164: The reason for the duality is that we can listen for changes in the
165: LOCAL cluster, but not in REMOTE clusters.
166: If the change was stimulated internally, then the data source got
167: the change, and updated its values, and this simply redisplays;
168: if the change was stimulated externally (by the user), then this
169: first calls the data source to update the values, and then redisplays.
170: @param e the action event (object added, deleted or changed)
171: */
172:
173: public void actionPerformed(ActionEvent e) {
174: Object source = e.getSource();
175: if (source instanceof UIBarGraphSource) {
176: uiBarGraph.setParameters(
177: dataSource.getNumberOfXIntervals(), dataSource
178: .getXLegend(), dataSource.getXLabels(),
179: dataSource.getNumberOfYIntervals(), dataSource
180: .getYLegend(), dataSource.getYLabels(),
181: dataSource.getLegend(), dataSource.getValues());
182: } else if (e.getActionCommand().equals(UIFrame.UPDATE_COMMAND)) {
183: dataSource.update();
184: uiBarGraph.setParameters(
185: dataSource.getNumberOfXIntervals(), dataSource
186: .getXLegend(), dataSource.getXLabels(),
187: dataSource.getNumberOfYIntervals(), dataSource
188: .getYLegend(), dataSource.getYLabels(),
189: dataSource.getLegend(), dataSource.getValues());
190: } else
191: System.out
192: .println("UIBarGraphDisplay: unknown notification.");
193: }
194:
195: }
|