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