001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.jconsole;
027:
028: import java.awt.*;
029: import java.awt.event.*;
030: import java.beans.*;
031:
032: import javax.swing.*;
033: import javax.swing.border.*;
034: import javax.swing.text.*;
035:
036: import static javax.swing.JOptionPane.*;
037:
038: @SuppressWarnings("serial")
039: public final class SheetDialog {
040: // Reusable objects
041: private static Rectangle iconR = new Rectangle();
042: private static Rectangle textR = new Rectangle();
043: private static Rectangle viewR = new Rectangle();
044: private static Insets viewInsets = new Insets(0, 0, 0, 0);
045:
046: /** Don't let anyone instantiate this class */
047: private SheetDialog() {
048: }
049:
050: static JOptionPane showOptionDialog(final VMPanel vmPanel,
051: Object message, int optionType, int messageType, Icon icon,
052: Object[] options, Object initialValue) {
053:
054: JRootPane rootPane = SwingUtilities.getRootPane(vmPanel);
055: JPanel glassPane = (JPanel) rootPane.getGlassPane();
056:
057: if (!(glassPane instanceof SlideAndFadeGlassPane)) {
058: glassPane = new SlideAndFadeGlassPane();
059: glassPane.setName(rootPane.getName() + ".glassPane");
060: rootPane.setGlassPane(glassPane);
061: rootPane.revalidate();
062: }
063:
064: final SlideAndFadeGlassPane safGlassPane = (SlideAndFadeGlassPane) glassPane;
065:
066: // Workaround for the fact that JOptionPane does not handle
067: // limiting the width when using multi-line html messages.
068: // See Swing bug 5074006 and JConsole bug 6426317
069: message = fixWrapping(message, rootPane.getWidth() - 75); // Leave room for icon
070:
071: final SheetOptionPane optionPane = new SheetOptionPane(message,
072: messageType, optionType, icon, options, initialValue);
073:
074: optionPane.setComponentOrientation(vmPanel
075: .getComponentOrientation());
076: optionPane
077: .addPropertyChangeListener(new PropertyChangeListener() {
078: public void propertyChange(PropertyChangeEvent event) {
079: if (event.getPropertyName().equals(
080: VALUE_PROPERTY)
081: && event.getNewValue() != null
082: && event.getNewValue() != UNINITIALIZED_VALUE) {
083: ((SlideAndFadeGlassPane) optionPane
084: .getParent()).hide(optionPane);
085: }
086: }
087: });
088:
089: // Delay this (even though we're already on the EDT)
090: EventQueue.invokeLater(new Runnable() {
091: public void run() {
092: safGlassPane.show(optionPane);
093: }
094: });
095:
096: return optionPane;
097: }
098:
099: private static Object fixWrapping(Object message, final int maxWidth) {
100: if (message instanceof Object[]) {
101: Object[] arr = (Object[]) message;
102: for (int i = 0; i < arr.length; i++) {
103: arr[i] = fixWrapping(arr[i], maxWidth);
104: }
105: } else if (message instanceof String
106: && ((String) message).startsWith("<html>")) {
107: message = new JLabel((String) message) {
108: public Dimension getPreferredSize() {
109: String text = getText();
110: Insets insets = getInsets(viewInsets);
111: FontMetrics fm = getFontMetrics(getFont());
112: Dimension pref = super .getPreferredSize();
113: Dimension min = getMinimumSize();
114:
115: iconR.x = iconR.y = iconR.width = iconR.height = 0;
116: textR.x = textR.y = textR.width = textR.height = 0;
117: int dx = insets.left + insets.right;
118: int dy = insets.top + insets.bottom;
119: viewR.x = dx;
120: viewR.y = dy;
121: viewR.width = viewR.height = Short.MAX_VALUE;
122:
123: View v = (View) getClientProperty("html");
124: if (v != null) {
125: // Use pref width if less than 300, otherwise
126: // min width up to size of window.
127: int w = Math.min(maxWidth, Math.min(pref.width,
128: Math.max(min.width, 300)));
129: v.setSize((float) w, 0F);
130:
131: SwingUtilities.layoutCompoundLabel(this , fm,
132: text, null, getVerticalAlignment(),
133: getHorizontalAlignment(),
134: getVerticalTextPosition(),
135: getHorizontalTextPosition(), viewR,
136: iconR, textR, getIconTextGap());
137: return new Dimension(textR.width + dx,
138: textR.height + dy);
139: } else {
140: return pref; // Should not happen
141: }
142: }
143: };
144: }
145: return message;
146: }
147:
148: private static class SlideAndFadeGlassPane extends JPanel {
149: SheetOptionPane optionPane;
150:
151: int fade = 20;
152: boolean slideIn = true;
153:
154: SlideAndFadeGlassPane() {
155: super (null);
156: setVisible(false);
157: setOpaque(false);
158:
159: // Grab mouse input, making the dialog modal
160: addMouseListener(new MouseAdapter() {
161: });
162: }
163:
164: public void show(SheetOptionPane optionPane) {
165: this .optionPane = optionPane;
166: removeAll();
167: add(optionPane);
168: setVisible(true);
169: slideIn = true;
170: revalidate();
171: repaint();
172: doSlide();
173: }
174:
175: public void hide(SheetOptionPane optionPane) {
176: if (optionPane != this .optionPane) {
177: return;
178: }
179:
180: slideIn = false;
181: revalidate();
182: repaint();
183: doSlide();
184: }
185:
186: private void doSlide() {
187: if (optionPane.getParent() == null) {
188: return;
189: }
190:
191: if (optionPane.getWidth() == 0) {
192: optionPane.setSize(optionPane.getPreferredSize());
193: }
194:
195: int glassPaneWidth = getWidth();
196: if (glassPaneWidth == 0 && getParent() != null) {
197: glassPaneWidth = getParent().getWidth();
198: }
199:
200: int x = (glassPaneWidth - optionPane.getWidth()) / 2;
201:
202: if (!slideIn) {
203: remove(optionPane);
204: setVisible(false);
205: return;
206: } else {
207: optionPane.setLocation(x, 0);
208: setGrayLevel(fade);
209: return;
210: }
211: }
212:
213: public void setGrayLevel(int gray) {
214: gray = gray * 255 / 100;
215: setBackground(new Color(0, 0, 0, gray));
216: }
217:
218: public void paint(Graphics g) {
219: g.setColor(getBackground());
220: g.fillRect(0, 0, getWidth(), getHeight());
221: super .paint(g);
222: }
223: }
224:
225: static class SheetOptionPane extends JOptionPane {
226: SheetOptionPane(Object message, int messageType,
227: int optionType, Icon icon, Object[] options,
228: Object initialValue) {
229: super (message, messageType, optionType, icon, options,
230: initialValue);
231:
232: setBorder(new CompoundBorder(new LineBorder(new Color(204,
233: 204, 204), 1), new EmptyBorder(4, 4, 4, 4)));
234: }
235:
236: private static Composite comp = AlphaComposite.getInstance(
237: AlphaComposite.SRC_OVER, 0.8F);
238:
239: private static Color bgColor = new Color(241, 239, 239);
240:
241: public void setVisible(boolean visible) {
242: SlideAndFadeGlassPane glassPane = (SlideAndFadeGlassPane) getParent();
243: if (glassPane != null) {
244: if (visible) {
245: glassPane.show(this );
246: } else {
247: glassPane.hide(this );
248: }
249: }
250: }
251:
252: public void paint(Graphics g) {
253: Graphics2D g2d = (Graphics2D) g;
254: Composite oldComp = g2d.getComposite();
255: g2d.setComposite(comp);
256: Color oldColor = g2d.getColor();
257: g2d.setColor(bgColor);
258: g2d.fillRect(0, 0, getWidth(), getHeight());
259: g2d.setColor(oldColor);
260: g2d.setComposite(oldComp);
261: super.paint(g);
262: }
263: }
264:
265: }
|