Showing the changes to java/pkg/sun/tools/jconsole/MaximizableInternalFrame.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,345 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2006, 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 | } | ||