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.Color;
030: import java.awt.Component;
031: import java.awt.Container;
032: import java.awt.Dimension;
033: import java.awt.GridBagConstraints;
034: import java.awt.GridBagLayout;
035: import java.awt.Insets;
036: import java.awt.LayoutManager;
037: import java.awt.Toolkit;
038: import java.awt.event.ActionEvent;
039: import java.awt.event.ActionListener;
040: import java.awt.event.WindowAdapter;
041: import java.awt.event.WindowEvent;
042: import java.awt.event.WindowListener;
043: import java.util.Hashtable;
044:
045: import javax.swing.JButton;
046: import javax.swing.JFrame;
047: import javax.swing.JPanel;
048:
049: import org.cougaar.core.mts.MessageAddress;
050: import org.cougaar.planning.ldm.plan.Plan;
051: import org.cougaar.planning.plugin.legacy.PluginDelegate;
052:
053: /** The sample User Interface Plugin display.
054: This is created and run from the UIPlugin.start method. It's run
055: in a separate thread so that the UIPlugin.start method
056: can return immediately while this new thread creates
057: the user display and awaits user actions.
058:
059: The display contains buttons for displaying the log plan,
060: expandable tasks, allocatable workflows, assets and asset schedules.
061:
062: A new thread is created for each display; it:
063: obtains the requested information;
064: creates a window and displays the requested information;
065: listens for changes in the cluster (for local cluster only);
066: listens for user changes (currently only closing the window).
067:
068: This assumes that there is only one plan ("Reality").
069: In the future, this should allow the user to:
070: select a plan and see the clusters associated with that plan (at
071: the local cluster)
072: */
073:
074: public class UIDisplay implements ActionListener, Runnable {
075: // contains correspondence between display buttons and cluster boxes
076: private Hashtable displayDictionary = new Hashtable();
077: private UIPlugin uiPlugin; // plugin we're a part of
078: private PluginDelegate delegate;
079: private Plan plan = null; // plan we're examining
080: private MessageAddress myClusterId; // local cluster id
081: private String myClusterName;
082: private static int WIDTH = 250; // width and height of initial frame
083: private static int HEIGHT = 550;
084: public static String PLAN_COMMAND = "PLAN";// log plan
085: public static String PLAN_DETAILS_COMMAND = "PLAN_DETAILS";// log plan details
086: public static String TASKS_COMMAND = "TASKS"; // tasks
087: public static String WORKFLOWS_COMMAND = "WORKFLOWS"; // workflows
088: public static String ASSETS_COMMAND = "ASSETS"; // assets assigned to cluster
089: public static String CLUSTER_ASSETS_COMMAND = "CLUSTER_ASSETS";
090: public static String ALL_ASSETS_COMMAND = "ALL_ASSETS";
091: public static String ASSET_SCHEDULE_COMMAND = "ASSET_SCHEDULE"; // assets allocated by cluster
092: public static String SINGLE_ASSET_SCHEDULE_COMMAND = "SINGLE_ASSET_SCHEDULE";
093: public static String OUTPUT_FILE_COMMAND = "OUTPUT_FILE"; // for DLA work
094: public static String PROVIDE_LOG_SUPPORT_COMMAND = "PROVIDE_LOG_SUPPORT";//do log support
095: public static String ASSIGN_ASSETS_COMMAND = "ASSIGN_ASSETS";
096: public static String CREATE_TASK_COMMAND = "CREATE_TASK"; // general purpose user input
097: int gridx = 0; // for grid bag layout
098: int gridy = 0;
099: Insets noInternalPadding;
100: Insets internalPadding;
101: Insets labelInternalPadding;
102: JPanel panel;
103:
104: /** Called from UIPlugin; records the plugin this is part of for use by
105: objects it creates.
106: @param uiPlugin this user interface plugin
107: */
108:
109: public UIDisplay(UIPlugin uiPlugin, PluginDelegate del) {
110: this .uiPlugin = uiPlugin;
111: delegate = del;
112: }
113:
114: /** how many gui frames we've exposed (in this vm) **/
115: private static int framecount = 0;
116: private static Object framecountlock = new Object();
117:
118: private static int getFrameCount() {
119: synchronized (framecountlock) {
120: int i = framecount;
121: framecount++;
122: return i;
123: }
124: }
125:
126: /** Obtain the information requested and display it.
127: Information is obtained in the run method, so that the main user
128: interface thread is not hung waiting to obtain information from
129: (potentially remote) clusters.
130: If the user closes this window (the main display), then the plugin exits.
131: In the future, this should query the user for the plan; for now,
132: it simply gets the first plan (should be "Reality")
133: and exits if it doesn't exist.
134: Although the plan is passed to the createRow method and used
135: to display potentially different lists of cluster ids, the actionperformed
136: method simply gets the plan from the global plan variable; eventually
137: it will get it from the user's input.
138: */
139:
140: public void run() {
141: myClusterId = delegate.getMessageAddress();
142: myClusterName = myClusterId.getAddress();
143: // get the plan
144: plan = uiPlugin.getPlan();
145:
146: // quit when user closes window
147:
148: WindowListener windowListener = new WindowAdapter() {
149: public void windowClosing(WindowEvent e) {
150: System.out
151: .println("UIDisplay().run() calling System.exit through an anonymous WindowAdapter class.");
152: System.exit(0);
153: }
154: };
155:
156: // create a frame to hold the gui controls
157: JFrame frame = new JFrame("*" + myClusterName);
158: frame.setForeground(Color.black);
159: frame.setBackground(Color.lightGray);
160: frame.addWindowListener(windowListener);
161: frame.setSize(WIDTH, HEIGHT);
162: Dimension screenSize = Toolkit.getDefaultToolkit()
163: .getScreenSize();
164: // center the frame on the display
165:
166: int fo = getFrameCount() * 20;
167: int cx = (screenSize.width - WIDTH) / 3 + fo;
168: int cy = (screenSize.height - HEIGHT) / 3 + fo;
169: frame.setLocation(cx, cy);
170:
171: /*
172: frame.setLocation(screenSize.width/2 - WIDTH/2,
173: screenSize.height/2 - HEIGHT/2);
174: */
175:
176: // do layout
177: panel = new JPanel();
178: GridBagLayout gbl = new GridBagLayout();
179: panel.setLayout(gbl);
180: internalPadding = new Insets(10, 2, 10, 2); // top, left, bottom, right
181: noInternalPadding = new Insets(0, 0, 0, 0);
182: labelInternalPadding = new Insets(10, 2, 10, 2);
183: gridx = 0;
184: gridy = 0;
185: createRow("Display LogPlan", PLAN_COMMAND, plan);
186: createRow("Display LogPlanDetails", PLAN_DETAILS_COMMAND, plan);
187: createRow("Display Expandable Tasks", TASKS_COMMAND, plan);
188: createRow("Display Allocatable Workflows", WORKFLOWS_COMMAND,
189: plan);
190: createRow("Display Asset Quantity", ASSETS_COMMAND, plan);
191: createRow("Display Organization Assets",
192: CLUSTER_ASSETS_COMMAND, plan);
193: createRow("Display All Assets", ALL_ASSETS_COMMAND, plan);
194: createRow("Display All Asset Schedules",
195: ASSET_SCHEDULE_COMMAND, plan);
196: createRow("Display Single Asset Schedule",
197: SINGLE_ASSET_SCHEDULE_COMMAND, plan);
198: createRow("Display Output File", OUTPUT_FILE_COMMAND, plan);
199:
200: // add buttons for user input
201: // provide log support
202: // gridx = 0;
203: // JButton button2 = new JButton("Provide Log Support");
204: // button2.setActionCommand(PROVIDE_LOG_SUPPORT_COMMAND);
205: // button2.setEnabled(false);
206: // button2.addActionListener(this);
207: // addComponent(panel, button2, gridx, gridy++,
208: // GridBagConstraints.REMAINDER, 1,
209: // GridBagConstraints.CENTER, GridBagConstraints.NONE,
210: // 0, 0, internalPadding, 0, 0);
211:
212: // create general task
213: gridx = 0;
214: JButton button3 = new JButton("Create Task");
215: button3.setActionCommand(CREATE_TASK_COMMAND);
216: button3.addActionListener(this );
217: addComponent(panel, button3, gridx, gridy++,
218: GridBagConstraints.REMAINDER, 1,
219: GridBagConstraints.CENTER, GridBagConstraints.NONE, 0,
220: 0, internalPadding, 0, 0);
221: frame.getContentPane().add("Center", panel);
222: frame.setVisible(true);
223: }
224:
225: /** Create a row of components in the main display.
226: Each row contains a button for displaying info from the cluster.
227: */
228:
229: private void createRow(String buttonLabel, String buttonCommand,
230: Plan plan) {
231: gridx = 0;
232: JButton button = new JButton(buttonLabel);
233: button.setActionCommand(buttonCommand);
234: button.addActionListener(this );
235: addComponent(panel, button, gridx++, gridy++, 1, 1,
236: GridBagConstraints.WEST, GridBagConstraints.NONE, 0, 0,
237: internalPadding, 1, 0);
238: }
239:
240: /** For adding components using grid bag layout.
241: */
242:
243: private void addComponent(Container container, Component component,
244: int gridx, int gridy, int gridwidth, int gridheight,
245: int anchor, int fill, int ipadx, int ipady, Insets insets,
246: double weightx, double weighty) {
247: LayoutManager gbl = container.getLayout();
248: GridBagConstraints gbc = new GridBagConstraints();
249: gbc.gridx = gridx;
250: gbc.gridy = gridy;
251: gbc.gridwidth = gridwidth;
252: gbc.gridheight = gridheight;
253: gbc.fill = fill;
254: gbc.anchor = anchor;
255: gbc.ipadx = ipadx;
256: gbc.ipady = ipady;
257: gbc.insets = insets;
258: gbc.weightx = weightx;
259: gbc.weighty = weighty;
260: ((GridBagLayout) gbl).setConstraints(component, gbc);
261: container.add(component);
262: }
263:
264: /** Handle user selection.
265: Create a new thread which creates a new window, displays the
266: information requested, and listens for changes (from local cluster only).
267: Each display is handled by a separate thread, so while one
268: display is waiting to collect information from the clusters,
269: the user can request another set of information.
270: This creates a tree display for log plans, tasks and workflows,
271: and a bar graph display for assets and asset schedules.
272: @param e the event generated by the user
273: */
274:
275: public void actionPerformed(ActionEvent e) {
276: Runnable display;
277: String command = e.getActionCommand();
278: // this handles a user input event
279: // if (command.equals(ASSIGN_ASSETS_COMMAND)) {
280: // ((JButton)(e.getSource())).setEnabled(false);
281: // UIInput uiInput = new UIInput(uiPlugin, ASSIGN_ASSETS_COMMAND);
282: // Thread uiThread = new Thread(uiInput);
283: // uiThread.setName("uiThread:ASSIGN_ASSET_COMMAND:" + uiThread.getName());
284: // uiThread.start(); // go assign assets
285: // }
286: // else if (command.equals(PROVIDE_LOG_SUPPORT_COMMAND)) {
287: // else if (command.equals(PROVIDE_LOG_SUPPORT_COMMAND)) {
288: // ((JButton)(e.getSource())).setEnabled(false); // disable button
289: // UIInput uiInput = new UIInput(uiPlugin, PROVIDE_LOG_SUPPORT_COMMAND); // create uiinput
290: // Thread uiThread = new Thread(uiInput);
291: // uiThread.setName("uiThread:PROVIDE_LOG_SUPPORT_COMMAND:" + uiThread.getName());
292: // uiThread.start(); // start uiinput
293: if (command.equals(CREATE_TASK_COMMAND)) {
294: UserInput userInput = new UserInput(uiPlugin, this ,
295: delegate);
296: Thread uiThread = new Thread(userInput);
297: uiThread.setName("uiThread:CREATE_TASK_COMMAND:"
298: + uiThread.getName());
299: uiThread.start();
300: } else {
301: String planName = plan.getPlanName();
302: if (command.equals(PLAN_COMMAND)
303: || command.equals(PLAN_DETAILS_COMMAND)
304: || command.equals(TASKS_COMMAND)
305: || command.equals(WORKFLOWS_COMMAND)
306: || command.equals(CLUSTER_ASSETS_COMMAND)
307: || command.equals(ALL_ASSETS_COMMAND)) {
308: display = new UITreeDisplay(uiPlugin, planName,
309: myClusterId, command);
310: Thread uiThread = new Thread(display);
311: uiThread.setName("uiThread:DISPLAY:"
312: + uiThread.getName());
313: uiThread.start();
314: } else if (command.equals(ASSETS_COMMAND)
315: || command.equals(ASSET_SCHEDULE_COMMAND)
316: || command.equals(SINGLE_ASSET_SCHEDULE_COMMAND)) {
317: display = new UIBarGraphDisplay(uiPlugin, planName,
318: myClusterId, command);
319: Thread uiThread = new Thread(display);
320: uiThread.setName("uiThread:SCHEDULE:"
321: + uiThread.getName());
322: uiThread.start();
323: } else if (command.equals(OUTPUT_FILE_COMMAND)) {
324: display = new UIFile();
325: Thread uiThread = new Thread(display);
326: uiThread.setName("uiThread:OUTPUTFILE:"
327: + uiThread.getName());
328: uiThread.start();
329: } else
330: System.out.println("Received unknown action event: "
331: + command);
332: }
333: }
334: }
|