001: /*
002: * Copyright 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.beans.*;
030: import java.lang.reflect.*;
031:
032: import javax.swing.*;
033: import javax.swing.border.*;
034: import javax.swing.plaf.basic.*;
035:
036: /**
037: * This class is a temporary workaround for bug 4834918:
038: * Win L&F: JInternalFrame should merge with JMenuBar when maximized.
039: * It is not a general solution, but intended for use within the
040: * limited scope of JConsole when running with XP/Vista styles.
041: */
042: @SuppressWarnings("serial")
043: public class MaximizableInternalFrame extends JInternalFrame {
044: private boolean isXP;
045: private JFrame mainFrame;
046: private JMenuBar mainMenuBar;
047: private String mainTitle;
048: private JComponent titlePane;
049: private Border normalBorder;
050: private PropertyChangeListener pcl;
051:
052: public MaximizableInternalFrame(String title, boolean resizable,
053: boolean closable, boolean maximizable, boolean iconifiable) {
054: super (title, resizable, closable, maximizable, iconifiable);
055:
056: init();
057: }
058:
059: private void init() {
060: normalBorder = getBorder();
061: isXP = normalBorder.getClass().getName().endsWith("XPBorder");
062: if (isXP) {
063: setRootPaneCheckingEnabled(false);
064: titlePane = ((BasicInternalFrameUI) getUI()).getNorthPane();
065:
066: if (pcl == null) {
067: pcl = new PropertyChangeListener() {
068: public void propertyChange(PropertyChangeEvent ev) {
069: String prop = ev.getPropertyName();
070: if (prop.equals("icon")
071: || prop.equals("maximum")
072: || prop.equals("closed")) {
073:
074: updateFrame();
075: }
076: }
077: };
078: addPropertyChangeListener(pcl);
079: }
080: } else if (pcl != null) {
081: removePropertyChangeListener(pcl);
082: pcl = null;
083: }
084: }
085:
086: private void updateFrame() {
087: JFrame mainFrame;
088: if (!isXP || (mainFrame = getMainFrame()) == null) {
089: return;
090: }
091: JMenuBar menuBar = getMainMenuBar();
092: BasicInternalFrameUI ui = (BasicInternalFrameUI) getUI();
093: if (isMaximum() && !isIcon() && !isClosed()) {
094: if (ui.getNorthPane() != null) {
095: // Merge title bar into menu bar
096: mainTitle = mainFrame.getTitle();
097: mainFrame.setTitle(mainTitle + " - " + getTitle());
098: if (menuBar != null) {
099: // Move buttons to menu bar
100: updateButtonStates();
101: menuBar.add(Box.createGlue());
102: for (Component c : titlePane.getComponents()) {
103: if (c instanceof JButton) {
104: menuBar.add(c);
105: } else if (c instanceof JLabel) {
106: // This is the system menu icon
107: menuBar
108: .add(Box.createHorizontalStrut(3),
109: 0);
110: menuBar.add(c, 1);
111: menuBar
112: .add(Box.createHorizontalStrut(3),
113: 2);
114: }
115: }
116: ui.setNorthPane(null);
117: setBorder(null);
118: }
119: }
120: } else {
121: if (ui.getNorthPane() == null) {
122: // Restore title bar
123: mainFrame.setTitle(mainTitle);
124: if (menuBar != null) {
125: // Move buttons back to title bar
126: for (Component c : menuBar.getComponents()) {
127: if (c instanceof JButton || c instanceof JLabel) {
128: titlePane.add(c);
129: } else if (c instanceof Box.Filler) {
130: menuBar.remove(c);
131: }
132: }
133: menuBar.repaint();
134: updateButtonStates();
135: ui.setNorthPane(titlePane);
136: setBorder(normalBorder);
137: }
138: }
139: }
140: }
141:
142: public void updateUI() {
143: boolean isMax = (isXP && getBorder() == null);
144: if (isMax) {
145: try {
146: setMaximum(false);
147: } catch (PropertyVetoException ex) {
148: }
149: }
150: super .updateUI();
151: init();
152: if (isMax) {
153: try {
154: setMaximum(true);
155: } catch (PropertyVetoException ex) {
156: }
157: }
158: }
159:
160: private JFrame getMainFrame() {
161: if (mainFrame == null) {
162: JDesktopPane desktop = getDesktopPane();
163: if (desktop != null) {
164: mainFrame = (JFrame) SwingUtilities
165: .getWindowAncestor(desktop);
166: }
167: }
168: return mainFrame;
169: }
170:
171: private JMenuBar getMainMenuBar() {
172: if (mainMenuBar == null) {
173: JFrame mainFrame = getMainFrame();
174: if (mainFrame != null) {
175: mainMenuBar = mainFrame.getJMenuBar();
176: if (mainMenuBar != null
177: && !(mainMenuBar.getLayout() instanceof FixedMenuBarLayout)) {
178:
179: mainMenuBar.setLayout(new FixedMenuBarLayout(
180: mainMenuBar, BoxLayout.X_AXIS));
181: }
182: }
183: }
184: return mainMenuBar;
185: }
186:
187: public void setTitle(String title) {
188: if (isXP && isMaximum()) {
189: if (getMainFrame() != null) {
190: getMainFrame().setTitle(mainTitle + " - " + title);
191: }
192: }
193: super .setTitle(title);
194: }
195:
196: private class FixedMenuBarLayout extends BoxLayout {
197: public FixedMenuBarLayout(Container target, int axis) {
198: super (target, axis);
199: }
200:
201: public void layoutContainer(Container target) {
202: super .layoutContainer(target);
203:
204: for (Component c : target.getComponents()) {
205: if (c instanceof JButton) {
206: int y = (target.getHeight() - c.getHeight()) / 2;
207: c.setLocation(c.getX(), Math.max(2, y));
208: }
209: }
210: }
211: }
212:
213: // The rest of this class is messy and should not be relied upon. It
214: // uses reflection to access private, undocumented, and unsupported
215: // classes and fields.
216: //
217: // Install icon wrappers to display MDI icons when the buttons
218: // are in the menubar.
219: //
220: // Please note that this will very likely fail in a future version
221: // of Swing, but at least it should fail silently.
222: //
223: private static Object WP_MINBUTTON, WP_RESTOREBUTTON,
224: WP_CLOSEBUTTON, WP_MDIMINBUTTON, WP_MDIRESTOREBUTTON,
225: WP_MDICLOSEBUTTON;
226: static {
227: if (JConsole.IS_WIN) {
228: try {
229: Class Part = Class
230: .forName("com.sun.java.swing.plaf.windows.TMSchema$Part");
231: if (Part != null) {
232: WP_MINBUTTON = Part.getField("WP_MINBUTTON").get(
233: null);
234: WP_RESTOREBUTTON = Part
235: .getField("WP_RESTOREBUTTON").get(null);
236: WP_CLOSEBUTTON = Part.getField("WP_CLOSEBUTTON")
237: .get(null);
238: WP_MDIMINBUTTON = Part.getField("WP_MDIMINBUTTON")
239: .get(null);
240: WP_MDIRESTOREBUTTON = Part.getField(
241: "WP_MDIRESTOREBUTTON").get(null);
242: WP_MDICLOSEBUTTON = Part.getField(
243: "WP_MDICLOSEBUTTON").get(null);
244: }
245:
246: for (String str : new String[] { "maximize",
247: "minimize", "iconify", "close" }) {
248: String key = "InternalFrame." + str + "Icon";
249: UIManager.put(key, new MDIButtonIcon(UIManager
250: .getIcon(key)));
251: }
252: } catch (ClassNotFoundException ex) {
253: if (JConsole.debug) {
254: ex.printStackTrace();
255: }
256: } catch (NoSuchFieldException ex) {
257: if (JConsole.debug) {
258: ex.printStackTrace();
259: }
260: } catch (IllegalAccessException ex) {
261: if (JConsole.debug) {
262: ex.printStackTrace();
263: }
264: }
265: }
266: }
267:
268: // A wrapper class for the title pane button icons.
269: // This code should really go in the WindowsIconsFactory class.
270: private static class MDIButtonIcon implements Icon {
271: Icon windowsIcon;
272: Field part;
273:
274: MDIButtonIcon(Icon icon) {
275: windowsIcon = icon;
276:
277: if (WP_MINBUTTON != null) {
278: try {
279: part = windowsIcon.getClass().getDeclaredField(
280: "part");
281: part.setAccessible(true);
282: } catch (NoSuchFieldException ex) {
283: if (JConsole.debug) {
284: ex.printStackTrace();
285: }
286: }
287: }
288: }
289:
290: public void paintIcon(Component c, Graphics g, int x, int y) {
291: if (part != null) {
292: try {
293: Object v = part.get(windowsIcon);
294:
295: if (c.getParent() instanceof JMenuBar) {
296: // Use MDI icons
297: if (v == WP_MINBUTTON) {
298: part.set(windowsIcon, WP_MDIMINBUTTON);
299: } else if (v == WP_RESTOREBUTTON) {
300: part.set(windowsIcon, WP_MDIRESTOREBUTTON);
301: } else if (v == WP_CLOSEBUTTON) {
302: part.set(windowsIcon, WP_MDICLOSEBUTTON);
303: }
304: } else {
305: // Use regular icons
306: if (v == WP_MDIMINBUTTON) {
307: part.set(windowsIcon, WP_MINBUTTON);
308: } else if (v == WP_MDIRESTOREBUTTON) {
309: part.set(windowsIcon, WP_RESTOREBUTTON);
310: } else if (v == WP_MDICLOSEBUTTON) {
311: part.set(windowsIcon, WP_CLOSEBUTTON);
312: }
313: }
314: } catch (IllegalAccessException ex) {
315: if (JConsole.debug) {
316: ex.printStackTrace();
317: }
318: }
319: }
320: windowsIcon.paintIcon(c, g, x, y);
321: }
322:
323: public int getIconWidth() {
324: return windowsIcon.getIconWidth();
325: }
326:
327: public int getIconHeight() {
328: return windowsIcon.getIconHeight();
329: }
330: }
331:
332: // Use reflection to invoke protected methods in BasicInternalFrameTitlePane
333: private Method setButtonIcons;
334: private Method enableActions;
335:
336: private void updateButtonStates() {
337: try {
338: if (setButtonIcons == null) {
339: Class<? extends JComponent> cls = titlePane.getClass();
340: Class<?> super Cls = cls.getSuperclass();
341: setButtonIcons = cls
342: .getDeclaredMethod("setButtonIcons");
343: enableActions = super Cls
344: .getDeclaredMethod("enableActions");
345: setButtonIcons.setAccessible(true);
346: enableActions.setAccessible(true);
347: }
348: setButtonIcons.invoke(titlePane);
349: enableActions.invoke(titlePane);
350: } catch (Exception ex) {
351: if (JConsole.debug) {
352: ex.printStackTrace();
353: }
354: }
355: }
356: }
|