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.console;
028:
029: import javax.swing.*;
030: import java.awt.*;
031: import java.awt.event.ComponentAdapter;
032: import java.awt.event.ComponentEvent;
033: import java.awt.event.ComponentListener;
034: import java.beans.PropertyVetoException;
035: import java.util.Enumeration;
036: import java.util.Hashtable;
037:
038: /**
039: * The internal desktop in the console where the Node output windows appear.
040: * Tracks frame locations to help keep them on the screen.
041: **/
042: public class ConsoleDesktop extends JDesktopPane {
043: private static final int M = 20;
044: private static final int frameXOffset = 20, frameYOffset = 20;
045: private int frameCount = 0;
046: Hashtable myFrames = new Hashtable();
047: ComponentListener myComponentListener = new ComponentAdapter() {
048: public void componentMoved(ComponentEvent e) {
049: ConsoleDesktop.this .componentMoved(e.getComponent(), true);
050: }
051:
052: public void componentShown(ComponentEvent e) {
053: ConsoleDesktop.this .componentMoved(e.getComponent(), true);
054: }
055:
056: public void componentResized(ComponentEvent e) {
057: ConsoleDesktop.this .componentResized(e.getComponent());
058: }
059: };
060:
061: public ConsoleDesktop() {
062: this .addComponentListener(myComponentListener);
063: }
064:
065: /**
066: * Add a node output frame to the desktop.
067: * The frame is iconified and not selected.
068: * @param frame the frame to add
069: * @param nodeName the name of the node
070: */
071: public void addNodeFrame(JInternalFrame frame, String nodeName) {
072: //Set the window's location.
073: frameCount++;
074: Insets insets = this .getInsets();
075: int dx = getWidth() - insets.left - insets.right
076: - frame.getWidth();
077: int dy = getHeight() - insets.top - insets.bottom
078: - frame.getHeight();
079: int x = (dx <= 0) ? 0 : ((frameXOffset * frameCount) % dx);
080: int y = (dy <= 0) ? 0 : ((frameYOffset * frameCount) % dy);
081: frame.setLocation(x, y);
082: addFrame(frame, true);
083: myFrames.put(nodeName, frame);
084: }
085:
086: /**
087: * When we're done with a Node Frame, remove it, and remove
088: * our listener. Then dispose of the Frame -- which
089: * will recurse to get rid of the ConsoleTextPane,
090: * ConsoleStyledDocument.
091: **/
092: public void removeNodeFrame(String nodeName) {
093: // System.out.println("Desktop.removeNodeFrame " + nodeName);
094: JInternalFrame frame = (JInternalFrame) myFrames
095: .remove(nodeName);
096: cleanFrame(frame);
097: }
098:
099: public void removeFrame(JInternalFrame frame) {
100: // loop through myFrames to find the one, and remove it
101: Enumeration names = myFrames.keys();
102: while (names.hasMoreElements()) {
103: String title = (String) names.nextElement();
104: JInternalFrame cand = (JInternalFrame) myFrames.get(title);
105: if (cand != null && cand.equals(frame)) {
106: //System.out.println("Found frame to remove: " + title);
107: cleanFrame(cand);
108: myFrames.remove(title);
109: return;
110: }
111: }
112: // If get here it wasnt a node frame. Must remove seperately.
113: cleanFrame(frame);
114: }
115:
116: // FIXME: Add a version to remove a frame by the Frame?
117: public void cleanFrame(JInternalFrame frame) {
118: if (frame != null) {
119: // System.out.println("Desktop.cleanFrame");
120: frame.removeComponentListener(myComponentListener);
121: frame.dispose();
122: }
123: }
124:
125: /**
126: * Get the frame for this node.
127: * @param nodeName the name of the node
128: * @return the frame for the node
129: */
130: public NodeView getNodeFrame(String nodeName) {
131: return (NodeView) myFrames.get(nodeName);
132: }
133:
134: protected void addImpl(Component c, Object constraints, int index) {
135: componentMoved(c, false);
136: super .addImpl(c, constraints, index);
137: c.addComponentListener(myComponentListener);
138: }
139:
140: private void componentMoved(Component c, boolean peek) {
141: if (c == this )
142: return; // Don't care about this
143: Rectangle bb = c.getBounds();
144: Insets insets = this .getInsets();
145: int mx = peek ? M : bb.width;
146: int my = peek ? M : bb.height;
147: int x = Math.max(0, Math.min(bb.x, this .getWidth()
148: - insets.left - insets.right - mx));
149: int y = Math.max(0, Math.min(bb.y, this .getHeight()
150: - insets.top - insets.bottom - my));
151: if (bb.x > x || bb.y > y) {
152: c.setLocation(x, y);
153: }
154: }
155:
156: private void componentResized(Component c) {
157: if (c != this )
158: return; // Don't care about these
159: JInternalFrame[] frames = getAllFrames();
160: for (int i = 0; i < frames.length; i++) {
161: componentMoved(frames[i], true);
162: }
163: }
164:
165: /**
166: * Add an internal frame to the desktop, and optionally iconify it.
167: */
168: public void addFrame(JInternalFrame frame, boolean iconify) {
169: frame.setVisible(true);
170: add(frame, JLayeredPane.DEFAULT_LAYER);
171: if (iconify) {
172: try {
173: frame.setIcon(true);
174: } catch (PropertyVetoException e) {
175: }
176: }
177: }
178:
179: /**
180: * When done with the desktop, clean up. Remove my ComponentListener
181: * and recurse to call dispose on the InternalFrames, which in turn
182: * kills the documents, etc.
183: **/
184: public void dispose() {
185: // System.out.println("Desktop.dispose");
186: if (myComponentListener != null) {
187: removeComponentListener(myComponentListener);
188: // loop through frames and remove the listener from them
189: JInternalFrame[] frames = getAllFrames();
190: for (int i = 0; i < frames.length; i++) {
191: frames[i].removeComponentListener(myComponentListener);
192: frames[i].dispose();
193: }
194: myComponentListener = null;
195: }
196: myFrames.clear();
197: myFrames = null;
198: removeAll();
199: }
200: }
|