Source for javax.swing.JRootPane

   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: }