1: /* JRootPane.java -- 2: Copyright (C) 2002, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing; 40: 41: import java.awt.BorderLayout; 42: import java.awt.Component; 43: import java.awt.Container; 44: import java.awt.Dimension; 45: import java.awt.IllegalComponentStateException; 46: import java.awt.Insets; 47: import java.awt.LayoutManager; 48: import java.awt.LayoutManager2; 49: import java.awt.Rectangle; 50: import java.io.Serializable; 51: 52: import javax.accessibility.Accessible; 53: import javax.accessibility.AccessibleContext; 54: import javax.accessibility.AccessibleRole; 55: import javax.swing.plaf.RootPaneUI; 56: 57: /** 58: * This class is where JComponents are added to. Unlike awt where you could 59: * just say frame.add(), with swing you need to say frame.getRootPane() 60: * (which delivers an instance of this class) and add your components to 61: * that. It is implemented by several 'layers' (pane() should be read as 62: * plane()) each on top of the others where you can add components to. 63: * (getContentPane(), getGlassPane(), getLayeredPane()) 64: * 65: * @author Ronald Veldema (rveldema@cs.vu.nl) 66: */ 67: public class JRootPane extends JComponent implements Accessible 68: { 69: // The class used to obtain the accessible role for this object. 70: protected class AccessibleJRootPane extends AccessibleJComponent 71: { 72: /** 73: * For compatability with Sun's JDK 74: */ 75: private static final long serialVersionUID = 1082432482784468088L; 76: 77: /** 78: * Creates a new <code>AccessibleJRootPane</code> object. 79: */ 80: protected AccessibleJRootPane() 81: { 82: // Nothing to do here. 83: } 84: 85: /** 86: * DOCUMENT ME! 87: * 88: * @return DOCUMENT ME! 89: */ 90: public AccessibleRole getAccessibleRole() 91: { 92: return AccessibleRole.ROOT_PANE; 93: } 94: } 95: 96: // Custom Layout Manager for JRootPane. It positions contentPane and 97: // menuBar withing its layeredPane. 98: protected class RootLayout implements LayoutManager2, Serializable 99: { 100: /** DOCUMENT ME! */ 101: private static final long serialVersionUID = -4100116998559815027L; 102: 103: /** 104: * The cached layout info for the glass pane. 105: */ 106: private Rectangle glassPaneBounds; 107: 108: /** 109: * The cached layout info for the layered pane. 110: */ 111: private Rectangle layeredPaneBounds; 112: 113: /** 114: * The cached layout info for the content pane. 115: */ 116: private Rectangle contentPaneBounds; 117: 118: /** 119: * The cached layout info for the menu bar. 120: */ 121: private Rectangle menuBarBounds; 122: 123: /** 124: * Creates a new <code>RootLayout</code> object. 125: */ 126: protected RootLayout() 127: { 128: // Nothing to do here. 129: } 130: 131: /** 132: * DOCUMENT ME! 133: * 134: * @param comp DOCUMENT ME! 135: * @param constraints DOCUMENT ME! 136: */ 137: public void addLayoutComponent(Component comp, Object constraints) 138: { 139: // Nothing to do here. 140: } 141: 142: /** 143: * DOCUMENT ME! 144: * 145: * @param name DOCUMENT ME! 146: * @param comp DOCUMENT ME! 147: */ 148: public void addLayoutComponent(String name, Component comp) 149: { 150: // Nothing to do here. 151: } 152: 153: /** 154: * DOCUMENT ME! 155: * 156: * @param target DOCUMENT ME! 157: * 158: * @return DOCUMENT ME! 159: */ 160: public float getLayoutAlignmentX(Container target) 161: { 162: return 0.0F; 163: } 164: 165: /** 166: * DOCUMENT ME! 167: * 168: * @param target DOCUMENT ME! 169: * 170: * @return DOCUMENT ME! 171: */ 172: public float getLayoutAlignmentY(Container target) 173: { 174: return 0.0F; 175: } 176: 177: /** 178: * DOCUMENT ME! 179: * 180: * @param target DOCUMENT ME! 181: */ 182: public void invalidateLayout(Container target) 183: { 184: synchronized (this) 185: { 186: glassPaneBounds = null; 187: layeredPaneBounds = null; 188: contentPaneBounds = null; 189: menuBarBounds = null; 190: } 191: } 192: 193: /** 194: * DOCUMENT ME! 195: * 196: * @param c DOCUMENT ME! 197: */ 198: public void layoutContainer(Container c) 199: { 200: if (glassPaneBounds == null || layeredPaneBounds == null 201: || contentPaneBounds == null || menuBarBounds == null) 202: { 203: Insets i = getInsets(); 204: int containerWidth = c.getBounds().width - i.left - i.right; 205: int containerHeight = c.getBounds().height - i.top - i.bottom; 206: 207: // 1. the glassPane fills entire viewable region (bounds - insets). 208: // 2. the layeredPane filles entire viewable region. 209: // 3. the menuBar is positioned at the upper edge of layeredPane. 210: // 4. the contentPane fills viewable region minus menuBar, if present. 211: 212: 213: // +-------------------------------+ 214: // | JLayeredPane | 215: // | +--------------------------+ | 216: // | | menuBar | | 217: // | +--------------------------+ | 218: // | +--------------------------+ | 219: // | |contentPane | | 220: // | | | | 221: // | | | | 222: // | | | | 223: // | +--------------------------+ | 224: // +-------------------------------+ 225: 226: if (menuBar != null) 227: { 228: Dimension menuBarSize = menuBar.getPreferredSize(); 229: if (menuBarSize.height > containerHeight) 230: menuBarSize.height = containerHeight; 231: menuBarBounds = new Rectangle(0, 0, containerWidth, 232: menuBarSize.height); 233: contentPaneBounds = new Rectangle(0, menuBarSize.height, 234: containerWidth, 235: containerHeight - menuBarSize.height); 236: } 237: else 238: contentPaneBounds = new Rectangle(0, 0, containerWidth, 239: containerHeight); 240: 241: glassPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight); 242: layeredPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight); 243: } 244: 245: glassPane.setBounds(glassPaneBounds); 246: layeredPane.setBounds(layeredPaneBounds); 247: if (menuBar != null) 248: menuBar.setBounds(menuBarBounds); 249: getContentPane().setBounds(contentPaneBounds); 250: } 251: 252: /** 253: * DOCUMENT ME! 254: * 255: * @param target DOCUMENT ME! 256: * 257: * @return DOCUMENT ME! 258: */ 259: public Dimension maximumLayoutSize(Container target) 260: { 261: return preferredLayoutSize(target); 262: } 263: 264: /** 265: * DOCUMENT ME! 266: * 267: * @param target DOCUMENT ME! 268: * 269: * @return DOCUMENT ME! 270: */ 271: public Dimension minimumLayoutSize(Container target) 272: { 273: return preferredLayoutSize(target); 274: } 275: 276: /** 277: * DOCUMENT ME! 278: * 279: * @param c DOCUMENT ME! 280: * 281: * @return DOCUMENT ME! 282: */ 283: public Dimension preferredLayoutSize(Container c) 284: { 285: Dimension prefSize = new Dimension(); 286: Insets i = getInsets(); 287: prefSize = new Dimension(i.left + i.right, i.top + i.bottom); 288: Dimension contentPrefSize = getContentPane().getPreferredSize(); 289: prefSize.width += contentPrefSize.width; 290: prefSize.height += contentPrefSize.height; 291: if (menuBar != null) 292: { 293: Dimension menuBarSize = menuBar.getPreferredSize(); 294: if (menuBarSize.width > contentPrefSize.width) 295: prefSize.width += menuBarSize.width - contentPrefSize.width; 296: prefSize.height += menuBarSize.height; 297: } 298: return prefSize; 299: } 300: 301: /** 302: * DOCUMENT ME! 303: * 304: * @param comp DOCUMENT ME! 305: */ 306: public void removeLayoutComponent(Component comp) 307: { 308: // Nothing to do here. 309: } 310: } 311: 312: /** DOCUMENT ME! */ 313: private static final long serialVersionUID = 8690748000348575668L; 314: 315: public static final int NONE = 0; 316: public static final int FRAME = 1; 317: public static final int PLAIN_DIALOG = 2; 318: public static final int INFORMATION_DIALOG = 3; 319: public static final int ERROR_DIALOG = 4; 320: public static final int COLOR_CHOOSER_DIALOG = 5; 321: public static final int FILE_CHOOSER_DIALOG = 6; 322: public static final int QUESTION_DIALOG = 7; 323: public static final int WARNING_DIALOG = 8; 324: 325: /** DOCUMENT ME! */ 326: protected Component glassPane; 327: 328: /** DOCUMENT ME! */ 329: protected JLayeredPane layeredPane; 330: 331: /** DOCUMENT ME! */ 332: protected JMenuBar menuBar; 333: 334: /** DOCUMENT ME! */ 335: protected Container contentPane; 336: 337: protected JButton defaultButton; 338: 339: /** 340: * This field is unused since JDK1.3. To override the default action you 341: * should modify the JRootPane's ActionMap. 342: * 343: * @deprecated since JDK1.3 344: * 345: * @specnote the specs indicate that the type of this field is 346: * a package private inner class 347: * javax.swing.JRootPane.DefaultAction. I assume that the closest 348: * public superclass is javax.swing.Action. 349: */ 350: protected Action defaultPressAction; 351: 352: /** 353: * This field is unused since JDK1.3. To override the default action you 354: * should modify the JRootPane's ActionMap. 355: * 356: * @deprecated since JDK1.3 357: * 358: * @specnote the specs indicate that the type of this field is 359: * a package private inner class 360: * javax.swing.JRootPane.DefaultAction. I assume that the closest 361: * public superclass is javax.swing.Action. 362: */ 363: protected Action defaultReleaseAction; 364: 365: /** 366: * @since 1.4 367: */ 368: private int windowDecorationStyle = NONE; 369: 370: /** 371: * DOCUMENT ME! 372: * 373: * @param m DOCUMENT ME! 374: */ 375: public void setJMenuBar(JMenuBar m) 376: { 377: JLayeredPane jlPane = getLayeredPane(); 378: if (menuBar != null) 379: jlPane.remove(menuBar); 380: menuBar = m; 381: if (menuBar != null) 382: jlPane.add(menuBar, JLayeredPane.FRAME_CONTENT_LAYER); 383: } 384: 385: /** 386: * @deprecated Replaced by <code>setJMenuBar()</code> 387: */ 388: public void setMenuBar(JMenuBar m) 389: { 390: setJMenuBar(m); 391: } 392: 393: /** 394: * DOCUMENT ME! 395: * 396: * @return DOCUMENT ME! 397: */ 398: public JMenuBar getJMenuBar() 399: { 400: return menuBar; 401: } 402: 403: /** 404: * @deprecated Replaced by <code>getJMenuBar()</code> 405: */ 406: public JMenuBar getMenuBar() 407: { 408: return getJMenuBar(); 409: } 410: 411: /** 412: * DOCUMENT ME! 413: * 414: * @return DOCUMENT ME! 415: */ 416: public boolean isValidateRoot() 417: { 418: return true; 419: } 420: 421: /** 422: * DOCUMENT ME! 423: * 424: * @return DOCUMENT ME! 425: */ 426: public Container getContentPane() 427: { 428: if (contentPane == null) 429: setContentPane(createContentPane()); 430: return contentPane; 431: } 432: 433: /** 434: * Sets the JRootPane's content pane. The content pane should typically be 435: * opaque for painting to work properly. This method also 436: * removes the old content pane from the layered pane. 437: * 438: * @param p the Container that will be the content pane 439: * @throws IllegalComponentStateException if p is null 440: */ 441: public void setContentPane(Container p) 442: { 443: if (p == null) 444: throw new IllegalComponentStateException ("cannot " + 445: "have a null content pane"); 446: else 447: { 448: if (contentPane != null && contentPane.getParent() == layeredPane) 449: layeredPane.remove(contentPane); 450: contentPane = p; 451: getLayeredPane().add(contentPane, JLayeredPane.FRAME_CONTENT_LAYER); 452: } 453: } 454: 455: /** 456: * DOCUMENT ME! 457: * 458: * @param comp DOCUMENT ME! 459: * @param constraints DOCUMENT ME! 460: * @param index DOCUMENT ME! 461: */ 462: protected void addImpl(Component comp, Object constraints, int index) 463: { 464: super.addImpl(comp, constraints, index); 465: } 466: 467: /** 468: * DOCUMENT ME! 469: * 470: * @return DOCUMENT ME! 471: */ 472: public Component getGlassPane() 473: { 474: if (glassPane == null) 475: setGlassPane(createGlassPane()); 476: return glassPane; 477: } 478: 479: /** 480: * DOCUMENT ME! 481: * 482: * @param f DOCUMENT ME! 483: */ 484: public void setGlassPane(Component f) 485: { 486: if (glassPane != null) 487: remove(glassPane); 488: 489: glassPane = f; 490: 491: glassPane.setVisible(false); 492: add(glassPane, 0); 493: } 494: 495: /** 496: * DOCUMENT ME! 497: * 498: * @return DOCUMENT ME! 499: */ 500: public JLayeredPane getLayeredPane() 501: { 502: if (layeredPane == null) 503: setLayeredPane(createLayeredPane()); 504: return layeredPane; 505: } 506: 507: /** 508: * Set the layered pane for the root pane. 509: * 510: * @param f The JLayeredPane to be used. 511: * 512: * @throws IllegalComponentStateException if JLayeredPane 513: * parameter is null. 514: */ 515: public void setLayeredPane(JLayeredPane f) 516: { 517: if (f == null) 518: throw new IllegalComponentStateException(); 519: 520: if (layeredPane != null) 521: remove(layeredPane); 522: 523: layeredPane = f; 524: add(f, -1); 525: } 526: 527: /** 528: * Creates a new <code>JRootPane</code> object. 529: */ 530: public JRootPane() 531: { 532: setLayout(createRootLayout()); 533: getGlassPane(); 534: getLayeredPane(); 535: getContentPane(); 536: setOpaque(true); 537: updateUI(); 538: } 539: 540: /** 541: * DOCUMENT ME! 542: * 543: * @return DOCUMENT ME! 544: */ 545: protected LayoutManager createRootLayout() 546: { 547: return new RootLayout(); 548: } 549: 550: /** 551: * DOCUMENT ME! 552: * 553: * @return DOCUMENT ME! 554: */ 555: protected Container createContentPane() 556: { 557: JPanel p = new JPanel(); 558: p.setName(this.getName() + ".contentPane"); 559: p.setLayout(new BorderLayout()); 560: return p; 561: } 562: 563: /** 564: * DOCUMENT ME! 565: * 566: * @return DOCUMENT ME! 567: */ 568: protected Component createGlassPane() 569: { 570: JPanel p = new JPanel(); 571: p.setName(this.getName() + ".glassPane"); 572: p.setVisible(false); 573: p.setOpaque(false); 574: return p; 575: } 576: 577: /** 578: * DOCUMENT ME! 579: * 580: * @return DOCUMENT ME! 581: */ 582: protected JLayeredPane createLayeredPane() 583: { 584: JLayeredPane l = new JLayeredPane(); 585: l.setLayout(null); 586: return l; 587: } 588: 589: /** 590: * DOCUMENT ME! 591: * 592: * @return DOCUMENT ME! 593: */ 594: public RootPaneUI getUI() 595: { 596: return (RootPaneUI) ui; 597: } 598: 599: /** 600: * DOCUMENT ME! 601: * 602: * @param ui DOCUMENT ME! 603: */ 604: public void setUI(RootPaneUI ui) 605: { 606: super.setUI(ui); 607: } 608: 609: /** 610: * DOCUMENT ME! 611: */ 612: public void updateUI() 613: { 614: setUI((RootPaneUI) UIManager.getUI(this)); 615: } 616: 617: /** 618: * DOCUMENT ME! 619: * 620: * @return DOCUMENT ME! 621: */ 622: public String getUIClassID() 623: { 624: return "RootPaneUI"; 625: } 626: 627: public JButton getDefaultButton() 628: { 629: return defaultButton; 630: } 631: 632: public void setDefaultButton(JButton newButton) 633: { 634: // We only change the default button if the new button is defaultCapable 635: // or null and the old and new button are different objects. 636: if (defaultButton != newButton 637: && (newButton == null || newButton.isDefaultCapable())) 638: { 639: JButton oldButton = defaultButton; 640: defaultButton = newButton; 641: firePropertyChange("defaultButton", oldButton, newButton); 642: } 643: } 644: 645: /** 646: * @since 1.4 647: */ 648: public int getWindowDecorationStyle() 649: { 650: return windowDecorationStyle; 651: } 652: 653: /** 654: * @since 1.4 655: */ 656: public void setWindowDecorationStyle(int style) 657: { 658: if (style != NONE 659: && style != FRAME 660: && style != INFORMATION_DIALOG 661: && style != ERROR_DIALOG 662: && style != COLOR_CHOOSER_DIALOG 663: && style != FILE_CHOOSER_DIALOG 664: && style != QUESTION_DIALOG 665: && style != WARNING_DIALOG 666: && style != PLAIN_DIALOG) 667: throw new IllegalArgumentException("invalid style"); 668: 669: int oldStyle = windowDecorationStyle; 670: windowDecorationStyle = style; 671: firePropertyChange("windowDecorationStyle", oldStyle, style); 672: } 673: 674: /** 675: * This returns <code>true</code> if the <code>glassPane</code> is not 676: * visible because then the root pane can guarantee to tile its children 677: * (the only other direct child is a JLayeredPane which must figure its 678: * <code>optimizeDrawingEnabled</code> state on its own). 679: * 680: * @return <code>true</code> if the <code>glassPane</code> is not 681: * visible 682: */ 683: public boolean isOptimizedDrawingEnable() 684: { 685: return ! glassPane.isVisible(); 686: } 687: 688: /** 689: * Returns the accessible context for this JRootPane. This will be 690: * an instance of {@link AccessibleJRootPane}. 691: * 692: * @return the accessible context for this JRootPane 693: */ 694: public AccessibleContext getAccessibleContext() 695: { 696: if (accessibleContext == null) 697: accessibleContext = new AccessibleJRootPane(); 698: return accessibleContext; 699: } 700: }