/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.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();
}
}
}
}