jdk/src/share/classes/sun/tools/jconsole/MaximizableInternalFrame.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/tools/jconsole/MaximizableInternalFrame.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.tools.jconsole;
+
+import java.awt.*;
+import java.beans.*;
+import java.lang.reflect.*;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.plaf.basic.*;
+
+
+/**
+ * This class is a temporary workaround for bug 4834918:
+ * Win L&F: JInternalFrame should merge with JMenuBar when maximized.
+ * It is not a general solution, but intended for use within the
+ * limited scope of JConsole when running with XP/Vista styles.
+ */
+@SuppressWarnings("serial")
+public class MaximizableInternalFrame extends JInternalFrame {
+    private boolean isXP;
+    private JFrame mainFrame;
+    private JMenuBar mainMenuBar;
+    private String mainTitle;
+    private JComponent titlePane;
+    private Border normalBorder;
+    private PropertyChangeListener pcl;
+
+    public MaximizableInternalFrame(String title, boolean resizable,
+                                    boolean closable, boolean maximizable,
+                                    boolean iconifiable) {
+        super(title, resizable, closable, maximizable, iconifiable);
+
+        init();
+    }
+
+    private void init() {
+        normalBorder = getBorder();
+        isXP = normalBorder.getClass().getName().endsWith("XPBorder");
+        if (isXP) {
+            setRootPaneCheckingEnabled(false);
+            titlePane = ((BasicInternalFrameUI)getUI()).getNorthPane();
+
+            if (pcl == null) {
+                pcl = new PropertyChangeListener() {
+                    public void propertyChange(PropertyChangeEvent ev) {
+                        String prop = ev.getPropertyName();
+                        if (prop.equals("icon") ||
+                            prop.equals("maximum") ||
+                            prop.equals("closed")) {
+
+                            updateFrame();
+                        }
+                    }
+                };
+                addPropertyChangeListener(pcl);
+            }
+        } else if (pcl != null) {
+            removePropertyChangeListener(pcl);
+            pcl = null;
+        }
+    }
+
+    private void updateFrame() {
+        JFrame mainFrame;
+        if (!isXP || (mainFrame = getMainFrame()) == null) {
+            return;
+        }
+        JMenuBar menuBar = getMainMenuBar();
+        BasicInternalFrameUI ui = (BasicInternalFrameUI)getUI();
+        if (isMaximum() && !isIcon() && !isClosed()) {
+            if (ui.getNorthPane() != null) {
+                // Merge title bar into menu bar
+                mainTitle = mainFrame.getTitle();
+                mainFrame.setTitle(mainTitle + " - " + getTitle());
+                if (menuBar != null) {
+                    // Move buttons to menu bar
+                    updateButtonStates();
+                    menuBar.add(Box.createGlue());
+                    for (Component c : titlePane.getComponents()) {
+                        if (c instanceof JButton) {
+                            menuBar.add(c);
+                        } else if (c instanceof JLabel) {
+                            // This is the system menu icon
+                            menuBar.add(Box.createHorizontalStrut(3), 0);
+                            menuBar.add(c, 1);
+                            menuBar.add(Box.createHorizontalStrut(3), 2);
+                        }
+                    }
+                    ui.setNorthPane(null);
+                    setBorder(null);
+                }
+            }
+        } else {
+            if (ui.getNorthPane() == null) {
+                // Restore title bar
+                mainFrame.setTitle(mainTitle);
+                if (menuBar != null) {
+                    // Move buttons back to title bar
+                    for (Component c : menuBar.getComponents()) {
+                        if (c instanceof JButton || c instanceof JLabel) {
+                            titlePane.add(c);
+                        } else if (c instanceof Box.Filler) {
+                            menuBar.remove(c);
+                        }
+                    }
+                    menuBar.repaint();
+                    updateButtonStates();
+                    ui.setNorthPane(titlePane);
+                    setBorder(normalBorder);
+                }
+            }
+        }
+    }
+
+    public void updateUI() {
+        boolean isMax = (isXP && getBorder() == null);
+        if (isMax) {
+            try {
+                setMaximum(false);
+            } catch (PropertyVetoException ex) { }
+        }
+        super.updateUI();
+        init();
+        if (isMax) {
+            try {
+                setMaximum(true);
+            } catch (PropertyVetoException ex) { }
+        }
+    }
+
+    private JFrame getMainFrame() {
+        if (mainFrame == null) {
+            JDesktopPane desktop = getDesktopPane();
+            if (desktop != null) {
+                mainFrame = (JFrame)SwingUtilities.getWindowAncestor(desktop);
+            }
+        }
+        return mainFrame;
+    }
+
+    private JMenuBar getMainMenuBar() {
+        if (mainMenuBar == null) {
+            JFrame mainFrame = getMainFrame();
+            if (mainFrame != null) {
+                mainMenuBar = mainFrame.getJMenuBar();
+                if (mainMenuBar != null &&
+                    !(mainMenuBar.getLayout() instanceof FixedMenuBarLayout)) {
+
+                    mainMenuBar.setLayout(new FixedMenuBarLayout(mainMenuBar,
+                                                            BoxLayout.X_AXIS));
+                }
+            }
+        }
+        return mainMenuBar;
+    }
+
+    public void setTitle(String title) {
+        if (isXP && isMaximum()) {
+            if (getMainFrame() != null) {
+                getMainFrame().setTitle(mainTitle + " - " + title);
+            }
+        }
+        super.setTitle(title);
+    }
+
+
+    private class FixedMenuBarLayout extends BoxLayout {
+        public FixedMenuBarLayout(Container target, int axis) {
+            super(target, axis);
+        }
+
+        public void layoutContainer(Container target) {
+            super.layoutContainer(target);
+
+            for (Component c : target.getComponents()) {
+                if (c instanceof JButton) {
+                    int y = (target.getHeight() - c.getHeight()) / 2;
+                    c.setLocation(c.getX(), Math.max(2, y));
+                }
+            }
+        }
+    }
+
+
+    // The rest of this class is messy and should not be relied upon. It
+    // uses reflection to access private, undocumented, and unsupported
+    // classes and fields.
+    //
+    // Install icon wrappers to display MDI icons when the buttons
+    // are in the menubar.
+    //
+    // Please note that this will very likely fail in a future version
+    // of Swing, but at least it should fail silently.
+    //
+    private static Object WP_MINBUTTON, WP_RESTOREBUTTON, WP_CLOSEBUTTON,
+                          WP_MDIMINBUTTON, WP_MDIRESTOREBUTTON, WP_MDICLOSEBUTTON;
+    static {
+        if (JConsole.IS_WIN) {
+            try {
+                Class Part =
+                    Class.forName("com.sun.java.swing.plaf.windows.TMSchema$Part");
+                if (Part != null) {
+                    WP_MINBUTTON        = Part.getField("WP_MINBUTTON").get(null);
+                    WP_RESTOREBUTTON    = Part.getField("WP_RESTOREBUTTON").get(null);
+                    WP_CLOSEBUTTON      = Part.getField("WP_CLOSEBUTTON").get(null);
+                    WP_MDIMINBUTTON     = Part.getField("WP_MDIMINBUTTON").get(null);
+                    WP_MDIRESTOREBUTTON = Part.getField("WP_MDIRESTOREBUTTON").get(null);
+                    WP_MDICLOSEBUTTON   = Part.getField("WP_MDICLOSEBUTTON").get(null);
+                }
+
+                for (String str : new String[] { "maximize", "minimize",
+                                                 "iconify", "close" }) {
+                    String key = "InternalFrame." + str + "Icon";
+                    UIManager.put(key,
+                                  new MDIButtonIcon(UIManager.getIcon(key)));
+                }
+            } catch (ClassNotFoundException ex) {
+                if (JConsole.debug) {
+                    ex.printStackTrace();
+                }
+            } catch (NoSuchFieldException ex) {
+                if (JConsole.debug) {
+                    ex.printStackTrace();
+                }
+            } catch (IllegalAccessException ex) {
+                if (JConsole.debug) {
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+
+
+    // A wrapper class for the title pane button icons.
+    // This code should really go in the WindowsIconsFactory class.
+    private static class MDIButtonIcon implements Icon {
+        Icon windowsIcon;
+        Field part;
+
+        MDIButtonIcon(Icon icon) {
+            windowsIcon = icon;
+
+            if (WP_MINBUTTON != null) {
+                try {
+                    part = windowsIcon.getClass().getDeclaredField("part");
+                    part.setAccessible(true);
+                } catch (NoSuchFieldException ex) {
+                    if (JConsole.debug) {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+        }
+
+        public void paintIcon(Component c, Graphics g, int x, int y) {
+            if (part != null) {
+                try {
+                    Object v = part.get(windowsIcon);
+
+                    if (c.getParent() instanceof JMenuBar) {
+                        // Use MDI icons
+                        if (v == WP_MINBUTTON) {
+                            part.set(windowsIcon, WP_MDIMINBUTTON);
+                        } else if (v == WP_RESTOREBUTTON) {
+                            part.set(windowsIcon, WP_MDIRESTOREBUTTON);
+                        } else if (v == WP_CLOSEBUTTON) {
+                            part.set(windowsIcon, WP_MDICLOSEBUTTON);
+                        }
+                    } else {
+                        // Use regular icons
+                        if (v == WP_MDIMINBUTTON) {
+                            part.set(windowsIcon, WP_MINBUTTON);
+                        } else if (v == WP_MDIRESTOREBUTTON) {
+                            part.set(windowsIcon, WP_RESTOREBUTTON);
+                        } else if (v == WP_MDICLOSEBUTTON) {
+                            part.set(windowsIcon, WP_CLOSEBUTTON);
+                        }
+                    }
+                } catch (IllegalAccessException ex) {
+                    if (JConsole.debug) {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+            windowsIcon.paintIcon(c, g, x, y);
+        }
+
+        public int getIconWidth(){
+            return windowsIcon.getIconWidth();
+        }
+
+        public int getIconHeight() {
+            return windowsIcon.getIconHeight();
+        }
+    }
+
+
+    // Use reflection to invoke protected methods in BasicInternalFrameTitlePane
+    private Method setButtonIcons;
+    private Method enableActions;
+
+    private void updateButtonStates() {
+        try {
+            if (setButtonIcons == null) {
+                Class<? extends JComponent> cls = titlePane.getClass();
+                Class<?> superCls = cls.getSuperclass();
+                setButtonIcons = cls.getDeclaredMethod("setButtonIcons");
+                enableActions  = superCls.getDeclaredMethod("enableActions");
+                setButtonIcons.setAccessible(true);
+                enableActions.setAccessible(true);
+            }
+            setButtonIcons.invoke(titlePane);
+            enableActions.invoke(titlePane);
+        } catch (Exception ex) {
+            if (JConsole.debug) {
+                ex.printStackTrace();
+            }
+        }
+    }
+}