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 */ AccessibleJRootPane()80 protected AccessibleJRootPane() 81 { 82 // Nothing to do here. 83 } 84 85 /** 86 * DOCUMENT ME! 87 * 88 * @return DOCUMENT ME! 89 */ getAccessibleRole()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 */ RootLayout()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 */ addLayoutComponent(Component comp, Object constraints)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 */ addLayoutComponent(String name, Component comp)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 */ getLayoutAlignmentX(Container target)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 */ getLayoutAlignmentY(Container target)172 public float getLayoutAlignmentY(Container target) 173 { 174 return 0.0F; 175 } 176 177 /** 178 * DOCUMENT ME! 179 * 180 * @param target DOCUMENT ME! 181 */ invalidateLayout(Container target)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 */ layoutContainer(Container c)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 */ maximumLayoutSize(Container target)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 */ minimumLayoutSize(Container target)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 */ preferredLayoutSize(Container c)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 */ removeLayoutComponent(Component comp)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 */ setJMenuBar(JMenuBar m)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 */ setMenuBar(JMenuBar m)388 public void setMenuBar(JMenuBar m) 389 { 390 setJMenuBar(m); 391 } 392 393 /** 394 * DOCUMENT ME! 395 * 396 * @return DOCUMENT ME! 397 */ getJMenuBar()398 public JMenuBar getJMenuBar() 399 { 400 return menuBar; 401 } 402 403 /** 404 * @deprecated Replaced by <code>getJMenuBar()</code> 405 */ getMenuBar()406 public JMenuBar getMenuBar() 407 { 408 return getJMenuBar(); 409 } 410 411 /** 412 * DOCUMENT ME! 413 * 414 * @return DOCUMENT ME! 415 */ isValidateRoot()416 public boolean isValidateRoot() 417 { 418 return true; 419 } 420 421 /** 422 * DOCUMENT ME! 423 * 424 * @return DOCUMENT ME! 425 */ getContentPane()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 */ setContentPane(Container p)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 */ addImpl(Component comp, Object constraints, int index)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 */ getGlassPane()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 */ setGlassPane(Component f)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 */ getLayeredPane()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 */ setLayeredPane(JLayeredPane f)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 */ JRootPane()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 */ createRootLayout()545 protected LayoutManager createRootLayout() 546 { 547 return new RootLayout(); 548 } 549 550 /** 551 * DOCUMENT ME! 552 * 553 * @return DOCUMENT ME! 554 */ createContentPane()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 */ createGlassPane()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 */ createLayeredPane()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 */ getUI()594 public RootPaneUI getUI() 595 { 596 return (RootPaneUI) ui; 597 } 598 599 /** 600 * DOCUMENT ME! 601 * 602 * @param ui DOCUMENT ME! 603 */ setUI(RootPaneUI ui)604 public void setUI(RootPaneUI ui) 605 { 606 super.setUI(ui); 607 } 608 609 /** 610 * DOCUMENT ME! 611 */ updateUI()612 public void updateUI() 613 { 614 setUI((RootPaneUI) UIManager.getUI(this)); 615 } 616 617 /** 618 * DOCUMENT ME! 619 * 620 * @return DOCUMENT ME! 621 */ getUIClassID()622 public String getUIClassID() 623 { 624 return "RootPaneUI"; 625 } 626 getDefaultButton()627 public JButton getDefaultButton() 628 { 629 return defaultButton; 630 } 631 setDefaultButton(JButton newButton)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 */ getWindowDecorationStyle()648 public int getWindowDecorationStyle() 649 { 650 return windowDecorationStyle; 651 } 652 653 /** 654 * @since 1.4 655 */ setWindowDecorationStyle(int style)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 */ isOptimizedDrawingEnable()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 */ getAccessibleContext()694 public AccessibleContext getAccessibleContext() 695 { 696 if (accessibleContext == null) 697 accessibleContext = new AccessibleJRootPane(); 698 return accessibleContext; 699 } 700 } 701