jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/MaximizableInternalFrame.java
changeset 25859 3317bb8137f4
parent 14342 8435a30053c1
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.tools.jconsole;
       
    27 
       
    28 import java.awt.*;
       
    29 import java.beans.*;
       
    30 import java.lang.reflect.*;
       
    31 
       
    32 import javax.swing.*;
       
    33 import javax.swing.border.*;
       
    34 import javax.swing.plaf.basic.*;
       
    35 
       
    36 
       
    37 /**
       
    38  * This class is a temporary workaround for bug 4834918:
       
    39  * Win L&F: JInternalFrame should merge with JMenuBar when maximized.
       
    40  * It is not a general solution, but intended for use within the
       
    41  * limited scope of JConsole when running with XP/Vista styles.
       
    42  */
       
    43 @SuppressWarnings("serial")
       
    44 public class MaximizableInternalFrame extends JInternalFrame {
       
    45     private boolean isXP;
       
    46     private JFrame mainFrame;
       
    47     private JMenuBar mainMenuBar;
       
    48     private String mainTitle;
       
    49     private JComponent titlePane;
       
    50     private Border normalBorder;
       
    51     private PropertyChangeListener pcl;
       
    52 
       
    53     public MaximizableInternalFrame(String title, boolean resizable,
       
    54                                     boolean closable, boolean maximizable,
       
    55                                     boolean iconifiable) {
       
    56         super(title, resizable, closable, maximizable, iconifiable);
       
    57 
       
    58         init();
       
    59     }
       
    60 
       
    61     private void init() {
       
    62         normalBorder = getBorder();
       
    63         isXP = normalBorder.getClass().getName().endsWith("XPBorder");
       
    64         if (isXP) {
       
    65             setRootPaneCheckingEnabled(false);
       
    66             titlePane = ((BasicInternalFrameUI)getUI()).getNorthPane();
       
    67 
       
    68             if (pcl == null) {
       
    69                 pcl = new PropertyChangeListener() {
       
    70                     public void propertyChange(PropertyChangeEvent ev) {
       
    71                         String prop = ev.getPropertyName();
       
    72                         if (prop.equals("icon") ||
       
    73                             prop.equals("maximum") ||
       
    74                             prop.equals("closed")) {
       
    75 
       
    76                             updateFrame();
       
    77                         }
       
    78                     }
       
    79                 };
       
    80                 addPropertyChangeListener(pcl);
       
    81             }
       
    82         } else if (pcl != null) {
       
    83             removePropertyChangeListener(pcl);
       
    84             pcl = null;
       
    85         }
       
    86     }
       
    87 
       
    88     private void updateFrame() {
       
    89         JFrame mainFrame;
       
    90         if (!isXP || (mainFrame = getMainFrame()) == null) {
       
    91             return;
       
    92         }
       
    93         JMenuBar menuBar = getMainMenuBar();
       
    94         BasicInternalFrameUI ui = (BasicInternalFrameUI)getUI();
       
    95         if (isMaximum() && !isIcon() && !isClosed()) {
       
    96             if (ui.getNorthPane() != null) {
       
    97                 // Merge title bar into menu bar
       
    98                 mainTitle = mainFrame.getTitle();
       
    99                 mainFrame.setTitle(mainTitle + " - " + getTitle());
       
   100                 if (menuBar != null) {
       
   101                     // Move buttons to menu bar
       
   102                     updateButtonStates();
       
   103                     menuBar.add(Box.createGlue());
       
   104                     for (Component c : titlePane.getComponents()) {
       
   105                         if (c instanceof JButton) {
       
   106                             menuBar.add(c);
       
   107                         } else if (c instanceof JLabel) {
       
   108                             // This is the system menu icon
       
   109                             menuBar.add(Box.createHorizontalStrut(3), 0);
       
   110                             menuBar.add(c, 1);
       
   111                             menuBar.add(Box.createHorizontalStrut(3), 2);
       
   112                         }
       
   113                     }
       
   114                     ui.setNorthPane(null);
       
   115                     setBorder(null);
       
   116                 }
       
   117             }
       
   118         } else {
       
   119             if (ui.getNorthPane() == null) {
       
   120                 // Restore title bar
       
   121                 mainFrame.setTitle(mainTitle);
       
   122                 if (menuBar != null) {
       
   123                     // Move buttons back to title bar
       
   124                     for (Component c : menuBar.getComponents()) {
       
   125                         if (c instanceof JButton || c instanceof JLabel) {
       
   126                             titlePane.add(c);
       
   127                         } else if (c instanceof Box.Filler) {
       
   128                             menuBar.remove(c);
       
   129                         }
       
   130                     }
       
   131                     menuBar.repaint();
       
   132                     updateButtonStates();
       
   133                     ui.setNorthPane(titlePane);
       
   134                     setBorder(normalBorder);
       
   135                 }
       
   136             }
       
   137         }
       
   138     }
       
   139 
       
   140     public void updateUI() {
       
   141         boolean isMax = (isXP && getBorder() == null);
       
   142         if (isMax) {
       
   143             try {
       
   144                 setMaximum(false);
       
   145             } catch (PropertyVetoException ex) { }
       
   146         }
       
   147         super.updateUI();
       
   148         init();
       
   149         if (isMax) {
       
   150             try {
       
   151                 setMaximum(true);
       
   152             } catch (PropertyVetoException ex) { }
       
   153         }
       
   154     }
       
   155 
       
   156     private JFrame getMainFrame() {
       
   157         if (mainFrame == null) {
       
   158             JDesktopPane desktop = getDesktopPane();
       
   159             if (desktop != null) {
       
   160                 mainFrame = (JFrame)SwingUtilities.getWindowAncestor(desktop);
       
   161             }
       
   162         }
       
   163         return mainFrame;
       
   164     }
       
   165 
       
   166     private JMenuBar getMainMenuBar() {
       
   167         if (mainMenuBar == null) {
       
   168             JFrame mainFrame = getMainFrame();
       
   169             if (mainFrame != null) {
       
   170                 mainMenuBar = mainFrame.getJMenuBar();
       
   171                 if (mainMenuBar != null &&
       
   172                     !(mainMenuBar.getLayout() instanceof FixedMenuBarLayout)) {
       
   173 
       
   174                     mainMenuBar.setLayout(new FixedMenuBarLayout(mainMenuBar,
       
   175                                                             BoxLayout.X_AXIS));
       
   176                 }
       
   177             }
       
   178         }
       
   179         return mainMenuBar;
       
   180     }
       
   181 
       
   182     public void setTitle(String title) {
       
   183         if (isXP && isMaximum()) {
       
   184             if (getMainFrame() != null) {
       
   185                 getMainFrame().setTitle(mainTitle + " - " + title);
       
   186             }
       
   187         }
       
   188         super.setTitle(title);
       
   189     }
       
   190 
       
   191 
       
   192     private class FixedMenuBarLayout extends BoxLayout {
       
   193         public FixedMenuBarLayout(Container target, int axis) {
       
   194             super(target, axis);
       
   195         }
       
   196 
       
   197         public void layoutContainer(Container target) {
       
   198             super.layoutContainer(target);
       
   199 
       
   200             for (Component c : target.getComponents()) {
       
   201                 if (c instanceof JButton) {
       
   202                     int y = (target.getHeight() - c.getHeight()) / 2;
       
   203                     c.setLocation(c.getX(), Math.max(2, y));
       
   204                 }
       
   205             }
       
   206         }
       
   207     }
       
   208 
       
   209 
       
   210     // The rest of this class is messy and should not be relied upon. It
       
   211     // uses reflection to access private, undocumented, and unsupported
       
   212     // classes and fields.
       
   213     //
       
   214     // Install icon wrappers to display MDI icons when the buttons
       
   215     // are in the menubar.
       
   216     //
       
   217     // Please note that this will very likely fail in a future version
       
   218     // of Swing, but at least it should fail silently.
       
   219     //
       
   220     private static Object WP_MINBUTTON, WP_RESTOREBUTTON, WP_CLOSEBUTTON,
       
   221                           WP_MDIMINBUTTON, WP_MDIRESTOREBUTTON, WP_MDICLOSEBUTTON;
       
   222     static {
       
   223         if (JConsole.IS_WIN) {
       
   224             try {
       
   225                 Class<?> Part =
       
   226                     Class.forName("com.sun.java.swing.plaf.windows.TMSchema$Part");
       
   227                 if (Part != null) {
       
   228                     WP_MINBUTTON        = Part.getField("WP_MINBUTTON").get(null);
       
   229                     WP_RESTOREBUTTON    = Part.getField("WP_RESTOREBUTTON").get(null);
       
   230                     WP_CLOSEBUTTON      = Part.getField("WP_CLOSEBUTTON").get(null);
       
   231                     WP_MDIMINBUTTON     = Part.getField("WP_MDIMINBUTTON").get(null);
       
   232                     WP_MDIRESTOREBUTTON = Part.getField("WP_MDIRESTOREBUTTON").get(null);
       
   233                     WP_MDICLOSEBUTTON   = Part.getField("WP_MDICLOSEBUTTON").get(null);
       
   234                 }
       
   235 
       
   236                 for (String str : new String[] { "maximize", "minimize",
       
   237                                                  "iconify", "close" }) {
       
   238                     String key = "InternalFrame." + str + "Icon";
       
   239                     UIManager.put(key,
       
   240                                   new MDIButtonIcon(UIManager.getIcon(key)));
       
   241                 }
       
   242             } catch (ClassNotFoundException ex) {
       
   243                 if (JConsole.debug) {
       
   244                     ex.printStackTrace();
       
   245                 }
       
   246             } catch (NoSuchFieldException ex) {
       
   247                 if (JConsole.debug) {
       
   248                     ex.printStackTrace();
       
   249                 }
       
   250             } catch (IllegalAccessException ex) {
       
   251                 if (JConsole.debug) {
       
   252                     ex.printStackTrace();
       
   253                 }
       
   254             }
       
   255         }
       
   256     }
       
   257 
       
   258 
       
   259     // A wrapper class for the title pane button icons.
       
   260     // This code should really go in the WindowsIconsFactory class.
       
   261     private static class MDIButtonIcon implements Icon {
       
   262         Icon windowsIcon;
       
   263         Field part;
       
   264 
       
   265         MDIButtonIcon(Icon icon) {
       
   266             windowsIcon = icon;
       
   267 
       
   268             if (WP_MINBUTTON != null) {
       
   269                 try {
       
   270                     part = windowsIcon.getClass().getDeclaredField("part");
       
   271                     part.setAccessible(true);
       
   272                 } catch (NoSuchFieldException ex) {
       
   273                     if (JConsole.debug) {
       
   274                         ex.printStackTrace();
       
   275                     }
       
   276                 }
       
   277             }
       
   278         }
       
   279 
       
   280         public void paintIcon(Component c, Graphics g, int x, int y) {
       
   281             if (part != null) {
       
   282                 try {
       
   283                     Object v = part.get(windowsIcon);
       
   284 
       
   285                     if (c.getParent() instanceof JMenuBar) {
       
   286                         // Use MDI icons
       
   287                         if (v == WP_MINBUTTON) {
       
   288                             part.set(windowsIcon, WP_MDIMINBUTTON);
       
   289                         } else if (v == WP_RESTOREBUTTON) {
       
   290                             part.set(windowsIcon, WP_MDIRESTOREBUTTON);
       
   291                         } else if (v == WP_CLOSEBUTTON) {
       
   292                             part.set(windowsIcon, WP_MDICLOSEBUTTON);
       
   293                         }
       
   294                     } else {
       
   295                         // Use regular icons
       
   296                         if (v == WP_MDIMINBUTTON) {
       
   297                             part.set(windowsIcon, WP_MINBUTTON);
       
   298                         } else if (v == WP_MDIRESTOREBUTTON) {
       
   299                             part.set(windowsIcon, WP_RESTOREBUTTON);
       
   300                         } else if (v == WP_MDICLOSEBUTTON) {
       
   301                             part.set(windowsIcon, WP_CLOSEBUTTON);
       
   302                         }
       
   303                     }
       
   304                 } catch (IllegalAccessException ex) {
       
   305                     if (JConsole.debug) {
       
   306                         ex.printStackTrace();
       
   307                     }
       
   308                 }
       
   309             }
       
   310             windowsIcon.paintIcon(c, g, x, y);
       
   311         }
       
   312 
       
   313         public int getIconWidth(){
       
   314             return windowsIcon.getIconWidth();
       
   315         }
       
   316 
       
   317         public int getIconHeight() {
       
   318             return windowsIcon.getIconHeight();
       
   319         }
       
   320     }
       
   321 
       
   322 
       
   323     // Use reflection to invoke protected methods in BasicInternalFrameTitlePane
       
   324     private Method setButtonIcons;
       
   325     private Method enableActions;
       
   326 
       
   327     private void updateButtonStates() {
       
   328         try {
       
   329             if (setButtonIcons == null) {
       
   330                 Class<? extends JComponent> cls = titlePane.getClass();
       
   331                 Class<?> superCls = cls.getSuperclass();
       
   332                 setButtonIcons = cls.getDeclaredMethod("setButtonIcons");
       
   333                 enableActions  = superCls.getDeclaredMethod("enableActions");
       
   334                 setButtonIcons.setAccessible(true);
       
   335                 enableActions.setAccessible(true);
       
   336             }
       
   337             setButtonIcons.invoke(titlePane);
       
   338             enableActions.invoke(titlePane);
       
   339         } catch (Exception ex) {
       
   340             if (JConsole.debug) {
       
   341                 ex.printStackTrace();
       
   342             }
       
   343         }
       
   344     }
       
   345 }