Path: blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/MaximizableInternalFrame.java
40948 views
/*1* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.jconsole;2627import java.awt.*;28import java.beans.*;29import java.lang.reflect.*;3031import javax.swing.*;32import javax.swing.border.*;33import javax.swing.plaf.basic.*;343536/**37* This class is a temporary workaround for bug 4834918:38* Win L&F: JInternalFrame should merge with JMenuBar when maximized.39* It is not a general solution, but intended for use within the40* limited scope of JConsole when running with XP/Vista styles.41*/42@SuppressWarnings("serial")43public class MaximizableInternalFrame extends JInternalFrame {44private boolean isXP;45private JFrame mainFrame;46private JMenuBar mainMenuBar;47private String mainTitle;48private JComponent titlePane;49private Border normalBorder;50private PropertyChangeListener pcl;5152public MaximizableInternalFrame(String title, boolean resizable,53boolean closable, boolean maximizable,54boolean iconifiable) {55super(title, resizable, closable, maximizable, iconifiable);5657init();58}5960private void init() {61normalBorder = getBorder();62isXP = normalBorder.getClass().getName().endsWith("XPBorder");63if (isXP) {64setRootPaneCheckingEnabled(false);65titlePane = ((BasicInternalFrameUI)getUI()).getNorthPane();6667if (pcl == null) {68pcl = new PropertyChangeListener() {69public void propertyChange(PropertyChangeEvent ev) {70String prop = ev.getPropertyName();71if (prop.equals("icon") ||72prop.equals("maximum") ||73prop.equals("closed")) {7475updateFrame();76}77}78};79addPropertyChangeListener(pcl);80}81} else if (pcl != null) {82removePropertyChangeListener(pcl);83pcl = null;84}85}8687private void updateFrame() {88JFrame mainFrame;89if (!isXP || (mainFrame = getMainFrame()) == null) {90return;91}92JMenuBar menuBar = getMainMenuBar();93BasicInternalFrameUI ui = (BasicInternalFrameUI)getUI();94if (isMaximum() && !isIcon() && !isClosed()) {95if (ui.getNorthPane() != null) {96// Merge title bar into menu bar97mainTitle = mainFrame.getTitle();98mainFrame.setTitle(mainTitle + " - " + getTitle());99if (menuBar != null) {100// Move buttons to menu bar101updateButtonStates();102menuBar.add(Box.createGlue());103for (Component c : titlePane.getComponents()) {104if (c instanceof JButton) {105menuBar.add(c);106} else if (c instanceof JLabel) {107// This is the system menu icon108menuBar.add(Box.createHorizontalStrut(3), 0);109menuBar.add(c, 1);110menuBar.add(Box.createHorizontalStrut(3), 2);111}112}113ui.setNorthPane(null);114setBorder(null);115}116}117} else {118if (ui.getNorthPane() == null) {119// Restore title bar120mainFrame.setTitle(mainTitle);121if (menuBar != null) {122// Move buttons back to title bar123for (Component c : menuBar.getComponents()) {124if (c instanceof JButton || c instanceof JLabel) {125titlePane.add(c);126} else if (c instanceof Box.Filler) {127menuBar.remove(c);128}129}130menuBar.repaint();131updateButtonStates();132ui.setNorthPane(titlePane);133setBorder(normalBorder);134}135}136}137}138139public void updateUI() {140boolean isMax = (isXP && getBorder() == null);141if (isMax) {142try {143setMaximum(false);144} catch (PropertyVetoException ex) { }145}146super.updateUI();147init();148if (isMax) {149try {150setMaximum(true);151} catch (PropertyVetoException ex) { }152}153}154155private JFrame getMainFrame() {156if (mainFrame == null) {157JDesktopPane desktop = getDesktopPane();158if (desktop != null) {159mainFrame = (JFrame)SwingUtilities.getWindowAncestor(desktop);160}161}162return mainFrame;163}164165private JMenuBar getMainMenuBar() {166if (mainMenuBar == null) {167JFrame mainFrame = getMainFrame();168if (mainFrame != null) {169mainMenuBar = mainFrame.getJMenuBar();170if (mainMenuBar != null &&171!(mainMenuBar.getLayout() instanceof FixedMenuBarLayout)) {172173mainMenuBar.setLayout(new FixedMenuBarLayout(mainMenuBar,174BoxLayout.X_AXIS));175}176}177}178return mainMenuBar;179}180181public void setTitle(String title) {182if (isXP && isMaximum()) {183if (getMainFrame() != null) {184getMainFrame().setTitle(mainTitle + " - " + title);185}186}187super.setTitle(title);188}189190191private class FixedMenuBarLayout extends BoxLayout {192public FixedMenuBarLayout(Container target, int axis) {193super(target, axis);194}195196public void layoutContainer(Container target) {197super.layoutContainer(target);198199for (Component c : target.getComponents()) {200if (c instanceof JButton) {201int y = (target.getHeight() - c.getHeight()) / 2;202c.setLocation(c.getX(), Math.max(2, y));203}204}205}206}207208209// The rest of this class is messy and should not be relied upon. It210// uses reflection to access private, undocumented, and unsupported211// classes and fields.212//213// Install icon wrappers to display MDI icons when the buttons214// are in the menubar.215//216// Please note that this will very likely fail in a future version217// of Swing, but at least it should fail silently.218//219private static Object WP_MINBUTTON, WP_RESTOREBUTTON, WP_CLOSEBUTTON,220WP_MDIMINBUTTON, WP_MDIRESTOREBUTTON, WP_MDICLOSEBUTTON;221static {222if (JConsole.IS_WIN) {223try {224Class<?> Part =225Class.forName("com.sun.java.swing.plaf.windows.TMSchema$Part");226if (Part != null) {227WP_MINBUTTON = Part.getField("WP_MINBUTTON").get(null);228WP_RESTOREBUTTON = Part.getField("WP_RESTOREBUTTON").get(null);229WP_CLOSEBUTTON = Part.getField("WP_CLOSEBUTTON").get(null);230WP_MDIMINBUTTON = Part.getField("WP_MDIMINBUTTON").get(null);231WP_MDIRESTOREBUTTON = Part.getField("WP_MDIRESTOREBUTTON").get(null);232WP_MDICLOSEBUTTON = Part.getField("WP_MDICLOSEBUTTON").get(null);233}234235for (String str : new String[] { "maximize", "minimize",236"iconify", "close" }) {237String key = "InternalFrame." + str + "Icon";238UIManager.put(key,239new MDIButtonIcon(UIManager.getIcon(key)));240}241} catch (ClassNotFoundException ex) {242if (JConsole.debug) {243ex.printStackTrace();244}245} catch (NoSuchFieldException ex) {246if (JConsole.debug) {247ex.printStackTrace();248}249} catch (IllegalAccessException ex) {250if (JConsole.debug) {251ex.printStackTrace();252}253}254}255}256257258// A wrapper class for the title pane button icons.259// This code should really go in the WindowsIconsFactory class.260private static class MDIButtonIcon implements Icon {261Icon windowsIcon;262Field part;263264MDIButtonIcon(Icon icon) {265windowsIcon = icon;266267if (WP_MINBUTTON != null) {268try {269part = windowsIcon.getClass().getDeclaredField("part");270part.setAccessible(true);271} catch (NoSuchFieldException ex) {272if (JConsole.debug) {273ex.printStackTrace();274}275}276}277}278279public void paintIcon(Component c, Graphics g, int x, int y) {280if (part != null) {281try {282Object v = part.get(windowsIcon);283284if (c.getParent() instanceof JMenuBar) {285// Use MDI icons286if (v == WP_MINBUTTON) {287part.set(windowsIcon, WP_MDIMINBUTTON);288} else if (v == WP_RESTOREBUTTON) {289part.set(windowsIcon, WP_MDIRESTOREBUTTON);290} else if (v == WP_CLOSEBUTTON) {291part.set(windowsIcon, WP_MDICLOSEBUTTON);292}293} else {294// Use regular icons295if (v == WP_MDIMINBUTTON) {296part.set(windowsIcon, WP_MINBUTTON);297} else if (v == WP_MDIRESTOREBUTTON) {298part.set(windowsIcon, WP_RESTOREBUTTON);299} else if (v == WP_MDICLOSEBUTTON) {300part.set(windowsIcon, WP_CLOSEBUTTON);301}302}303} catch (IllegalAccessException ex) {304if (JConsole.debug) {305ex.printStackTrace();306}307}308}309windowsIcon.paintIcon(c, g, x, y);310}311312public int getIconWidth(){313return windowsIcon.getIconWidth();314}315316public int getIconHeight() {317return windowsIcon.getIconHeight();318}319}320321322// Use reflection to invoke protected methods in BasicInternalFrameTitlePane323private Method setButtonIcons;324private Method enableActions;325326private void updateButtonStates() {327try {328if (setButtonIcons == null) {329Class<? extends JComponent> cls = titlePane.getClass();330Class<?> superCls = cls.getSuperclass();331setButtonIcons = cls.getDeclaredMethod("setButtonIcons");332enableActions = superCls.getDeclaredMethod("enableActions");333setButtonIcons.setAccessible(true);334enableActions.setAccessible(true);335}336setButtonIcons.invoke(titlePane);337enableActions.invoke(titlePane);338} catch (Exception ex) {339if (JConsole.debug) {340ex.printStackTrace();341}342}343}344}345346347