Source for javax.swing.plaf.basic.BasicInternalFrameUI

   1: /* BasicInternalFrameUI.java --
   2:    Copyright (C) 2004, 2005 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.plaf.basic;
  40: 
  41: import gnu.classpath.NotImplementedException;
  42: 
  43: import java.awt.AWTEvent;
  44: import java.awt.Color;
  45: import java.awt.Component;
  46: import java.awt.Container;
  47: import java.awt.Cursor;
  48: import java.awt.Dimension;
  49: import java.awt.Graphics;
  50: import java.awt.Insets;
  51: import java.awt.LayoutManager;
  52: import java.awt.LayoutManager2;
  53: import java.awt.Point;
  54: import java.awt.Rectangle;
  55: import java.awt.event.ComponentEvent;
  56: import java.awt.event.ComponentListener;
  57: import java.awt.event.MouseEvent;
  58: import java.beans.PropertyChangeEvent;
  59: import java.beans.PropertyChangeListener;
  60: 
  61: import javax.swing.DefaultDesktopManager;
  62: import javax.swing.DesktopManager;
  63: import javax.swing.JComponent;
  64: import javax.swing.JDesktopPane;
  65: import javax.swing.JInternalFrame;
  66: import javax.swing.KeyStroke;
  67: import javax.swing.LookAndFeel;
  68: import javax.swing.SwingConstants;
  69: import javax.swing.SwingUtilities;
  70: import javax.swing.UIManager;
  71: import javax.swing.border.AbstractBorder;
  72: import javax.swing.event.InternalFrameEvent;
  73: import javax.swing.event.InternalFrameListener;
  74: import javax.swing.event.MouseInputAdapter;
  75: import javax.swing.event.MouseInputListener;
  76: import javax.swing.plaf.ComponentUI;
  77: import javax.swing.plaf.InternalFrameUI;
  78: import javax.swing.plaf.UIResource;
  79: 
  80: /**
  81:  * This is the UI delegate for the Basic look and feel for JInternalFrames.
  82:  */
  83: public class BasicInternalFrameUI extends InternalFrameUI
  84: {
  85:   /**
  86:    * This is a helper class that listens to the JInternalFrame for
  87:    * InternalFrameEvents.
  88:    */
  89:   protected class BasicInternalFrameListener implements InternalFrameListener
  90:   {
  91:     /**
  92:      * This method is called when the JInternalFrame is activated.
  93:      *
  94:      * @param e The InternalFrameEvent.
  95:      */
  96:     public void internalFrameActivated(InternalFrameEvent e)
  97:     {
  98:       frame.getGlassPane().setVisible(false);
  99:     }
 100: 
 101:     /**
 102:      * This method is called when the JInternalFrame is closed.
 103:      *
 104:      * @param e The InternalFrameEvent.
 105:      */
 106:     public void internalFrameClosed(InternalFrameEvent e)
 107:     {
 108:       // FIXME: Implement.
 109:     }
 110: 
 111:     /**
 112:      * This method is called when the JInternalFrame is closing.
 113:      *
 114:      * @param e The InternalFrameEvent.
 115:      */
 116:     public void internalFrameClosing(InternalFrameEvent e)
 117:     {
 118:       // FIXME: Implement.
 119:     }
 120: 
 121:     /**
 122:      * This method is called when the JInternalFrame is deactivated.
 123:      *
 124:      * @param e The InternalFrameEvent.
 125:      */
 126:     public void internalFrameDeactivated(InternalFrameEvent e)
 127:     {
 128:       frame.getGlassPane().setVisible(true);
 129:     }
 130: 
 131:     /**
 132:      * This method is called when the JInternalFrame is  deiconified.
 133:      *
 134:      * @param e The InternalFrameEvent.
 135:      */
 136:     public void internalFrameDeiconified(InternalFrameEvent e)
 137:     {
 138:       // FIXME: Implement.
 139:     }
 140: 
 141:     /**
 142:      * This method is called when the JInternalFrame is  iconified.
 143:      *
 144:      * @param e The InternalFrameEvent.
 145:      */
 146:     public void internalFrameIconified(InternalFrameEvent e)
 147:     {
 148:       // FIXME: Implement.
 149:     }
 150: 
 151:     /**
 152:      * This method is called when the JInternalFrame is opened.
 153:      *
 154:      * @param e The InternalFrameEvent.
 155:      */
 156:     public void internalFrameOpened(InternalFrameEvent e)
 157:     {
 158:       // FIXME: Implement.
 159:     }
 160:   }
 161: 
 162:   /**
 163:    * This helper class listens to the edges of the JInternalFrame and the
 164:    * TitlePane for mouse events. It is responsible for dragging  and resizing
 165:    * the JInternalFrame in response to the MouseEvents.
 166:    */
 167:   protected class BorderListener extends MouseInputAdapter
 168:     implements SwingConstants
 169:   {
 170:     /**
 171:      * If true, the cursor is being already shown in the alternative "resize"
 172:      * shape. 
 173:      */
 174:     transient boolean showingResizeCursor;
 175:     
 176:     /** FIXME: Use for something. */
 177:     protected final int RESIZE_NONE = 0;
 178: 
 179:     /** The x offset from the top left corner of the JInternalFrame. */
 180:     private transient int xOffset = 0;
 181: 
 182:     /** The y offset from the top left corner of the JInternalFrame. */
 183:     private transient int yOffset = 0;
 184: 
 185:     /** The direction that the resize is occuring in. */
 186:     private transient int direction = -1;
 187: 
 188:     /** Cache rectangle that can be reused. */
 189:     private transient Rectangle cacheRect = new Rectangle();
 190: 
 191:     /**
 192:      * This method is called when the mouse is clicked.
 193:      *
 194:      * @param e The MouseEvent.
 195:      */
 196:     public void mouseClicked(MouseEvent e)
 197:     {
 198:       // There is nothing to do when the mouse is clicked
 199:       // on the border.
 200:     }
 201: 
 202:     /**
 203:      * This method is called when the mouse is dragged. This method is
 204:      * responsible for resizing or dragging the JInternalFrame.
 205:      *
 206:      * @param e The MouseEvent.
 207:      */
 208:     public void mouseDragged(MouseEvent e)
 209:     {
 210:       // If the frame is maximized, there is nothing that
 211:       // can be dragged around.
 212:       if (frame.isMaximum())
 213:         return;
 214:       DesktopManager dm = getDesktopManager();
 215:       Rectangle b = frame.getBounds();
 216:       Dimension min = frame.getMinimumSize();
 217:       if (min == null)
 218:         min = new Dimension(0, 0);
 219:       Insets insets = frame.getInsets();
 220:       int x = e.getX();
 221:       int y = e.getY();
 222:       if (e.getSource() == frame && frame.isResizable())
 223:         {
 224:           switch (direction)
 225:             {
 226:             case NORTH:
 227:               cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height
 228:                                                          - min.height),
 229:                                   b.width, b.height - y);
 230:               break;
 231:             case NORTH_EAST:
 232:               cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height
 233:                                                          - min.height), x,
 234:                                   b.height - y);
 235:               break;
 236:             case EAST:
 237:               cacheRect.setBounds(b.x, b.y, x, b.height);
 238:               break;
 239:             case SOUTH_EAST:
 240:               cacheRect.setBounds(b.x, b.y, x, y);
 241:               break;
 242:             case SOUTH:
 243:               cacheRect.setBounds(b.x, b.y, b.width, y);
 244:               break;
 245:             case SOUTH_WEST:
 246:               cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
 247:                                   b.y, b.width - x, y);
 248:               break;
 249:             case WEST:
 250:               cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width),
 251:                                   b.y, b.width - x, b.height);
 252:               break;
 253:             case NORTH_WEST:
 254:               cacheRect.setBounds(
 255:                                   Math.min(b.x + x, b.x + b.width - min.width),
 256:                                   Math.min(b.y + y, b.y + b.height - min.height),
 257:                                   b.width - x, b.height - y);
 258:               break;
 259:             }
 260:           dm.resizeFrame(frame, cacheRect.x, cacheRect.y,
 261:                          Math.max(min.width, cacheRect.width),
 262:                          Math.max(min.height, cacheRect.height));
 263:         }
 264:       else if (e.getSource() == titlePane)
 265:         {
 266:           Rectangle fBounds = frame.getBounds();
 267:           frame.putClientProperty("bufferedDragging", Boolean.TRUE);
 268:           dm.dragFrame(frame, e.getX() - xOffset + b.x, e.getY() - yOffset
 269:                                                         + b.y);
 270:         }
 271:     }
 272: 
 273:     /**
 274:      * This method is called when the mouse exits the JInternalFrame.
 275:      * 
 276:      * @param e The MouseEvent.
 277:      */
 278:     public void mouseExited(MouseEvent e)
 279:     {
 280:       // Reset the cursor shape.
 281:       if (showingResizeCursor)
 282:         {
 283:           frame.setCursor(Cursor.getDefaultCursor());
 284:           showingResizeCursor = false;
 285:         }
 286:     }
 287: 
 288:     /**
 289:      * This method is called when the mouse is moved inside the JInternalFrame.
 290:      * 
 291:      * @param e The MouseEvent.
 292:      */
 293:     public void mouseMoved(MouseEvent e)
 294:     {
 295:       // Turn off the resize cursor if we are in the frame header.
 296:       if (showingResizeCursor && e.getSource() != frame)
 297:         {
 298:           frame.setCursor(Cursor.getDefaultCursor());
 299:           showingResizeCursor = false;
 300:         }
 301:       else if (e.getSource()==frame && frame.isResizable())
 302:         {
 303:           int cursor;
 304:           switch (sectionOfClick(e.getX(), e.getY()))
 305:             {
 306:             case NORTH:
 307:               cursor = Cursor.N_RESIZE_CURSOR;
 308:               break;
 309:             case NORTH_EAST:
 310:               cursor = Cursor.NE_RESIZE_CURSOR;
 311:               break;
 312:             case EAST:
 313:               cursor = Cursor.E_RESIZE_CURSOR;
 314:               break;
 315:             case SOUTH_EAST:
 316:               cursor = Cursor.SE_RESIZE_CURSOR;
 317:               break;
 318:             case SOUTH:
 319:               cursor = Cursor.S_RESIZE_CURSOR;
 320:               break;
 321:             case SOUTH_WEST:
 322:               cursor = Cursor.SW_RESIZE_CURSOR;
 323:               break;
 324:             case WEST:
 325:               cursor = Cursor.W_RESIZE_CURSOR;
 326:               break;
 327:             case NORTH_WEST:
 328:               cursor = Cursor.NW_RESIZE_CURSOR;
 329:               break;
 330:             default:
 331:               cursor = Cursor.DEFAULT_CURSOR;
 332:             }
 333: 
 334:           Cursor resize = Cursor.getPredefinedCursor(cursor);
 335:           frame.setCursor(resize);
 336:           showingResizeCursor = true;
 337:         }
 338:     }
 339: 
 340:     /**
 341:      * This method is called when the mouse is pressed.
 342:      *
 343:      * @param e The MouseEvent.
 344:      */
 345:     public void mousePressed(MouseEvent e)
 346:     {
 347:       activateFrame(frame);
 348:       DesktopManager dm = getDesktopManager();
 349:       int x = e.getX();
 350:       int y = e.getY();
 351:       Insets insets = frame.getInsets();
 352: 
 353:       if (e.getSource() == frame && frame.isResizable())
 354:         {
 355:           direction = sectionOfClick(x, y);
 356:           dm.beginResizingFrame(frame, direction);
 357:         }
 358:       else if (e.getSource() == titlePane)
 359:         {
 360:           Rectangle tBounds = titlePane.getBounds();
 361: 
 362:           xOffset = e.getX() - tBounds.x + insets.left;
 363:           yOffset = e.getY() - tBounds.y + insets.top;
 364: 
 365:           dm.beginDraggingFrame(frame);
 366:         }
 367:     }
 368: 
 369:     /**
 370:      * This method is called when the mouse is released.
 371:      *
 372:      * @param e The MouseEvent.
 373:      */
 374:     public void mouseReleased(MouseEvent e)
 375:     {
 376:       DesktopManager dm = getDesktopManager();
 377:       xOffset = 0;
 378:       yOffset = 0;
 379:       if (e.getSource() == frame && frame.isResizable())
 380:         dm.endResizingFrame(frame);
 381:       else if (e.getSource() == titlePane)
 382:         {
 383:           dm.endDraggingFrame(frame);
 384:           frame.putClientProperty("bufferedDragging", null);
 385:         }
 386:     }
 387: 
 388:     /**
 389:      * This method determines the direction of the resize based on the
 390:      * coordinates and the size of the JInternalFrame.
 391:      *
 392:      * @param x The x coordinate of the MouseEvent.
 393:      * @param y The y coordinate of the MouseEvent.
 394:      *
 395:      * @return The direction of the resize (a SwingConstant direction).
 396:      */
 397:     private int sectionOfClick(int x, int y)
 398:     {
 399:       Insets insets = frame.getInsets();
 400:       Rectangle b = frame.getBounds();
 401:       if (x < insets.left && y < insets.top)
 402:         return NORTH_WEST;
 403:       else if (x > b.width - insets.right && y < insets.top)
 404:         return NORTH_EAST;
 405:       else if (x > b.width - insets.right && y > b.height - insets.bottom)
 406:         return SOUTH_EAST;
 407:       else if (x < insets.left && y > b.height - insets.bottom)
 408:         return SOUTH_WEST;
 409:       else if (y < insets.top)
 410:         return NORTH;
 411:       else if (x < insets.left)
 412:         return WEST;
 413:       else if (y > b.height - insets.bottom)
 414:         return SOUTH;
 415:       else if (x > b.width - insets.right)
 416:         return EAST;
 417: 
 418:       return -1;
 419:     }
 420:   }
 421: 
 422:   /**
 423:    * This helper class listens to the JDesktopPane that parents this
 424:    * JInternalFrame and listens for resize events and resizes the
 425:    * JInternalFrame appropriately.
 426:    */
 427:   protected class ComponentHandler implements ComponentListener
 428:   {
 429:     /**
 430:      * This method is called when the JDesktopPane is hidden.
 431:      * 
 432:      * @param e
 433:      *          The ComponentEvent fired.
 434:      */
 435:     public void componentHidden(ComponentEvent e)
 436:     {
 437:       // Do nothing.
 438:     }
 439: 
 440:     /**
 441:      * This method is called when the JDesktopPane is moved.
 442:      * 
 443:      * @param e
 444:      *          The ComponentEvent fired.
 445:      */
 446:     public void componentMoved(ComponentEvent e)
 447:     {
 448:       // Do nothing.
 449:     }
 450: 
 451:     /**
 452:      * This method is called when the JDesktopPane is resized.
 453:      * 
 454:      * @param e
 455:      *          The ComponentEvent fired.
 456:      */
 457:     public void componentResized(ComponentEvent e)
 458:     {
 459:       if (frame.isMaximum())
 460:         {
 461:           JDesktopPane pane = (JDesktopPane) e.getSource();
 462:           Insets insets = pane.getInsets();
 463:           Rectangle bounds = pane.getBounds();
 464: 
 465:           frame.setBounds(bounds.x + insets.left, bounds.y + insets.top,
 466:                           bounds.width - insets.left - insets.right,
 467:                           bounds.height - insets.top - insets.bottom);
 468:           frame.revalidate();
 469:           frame.repaint();
 470:         }
 471: 
 472:       // Sun also resizes the icons. but it doesn't seem to do anything.
 473:     }
 474: 
 475:     /**
 476:      * This method is called when the JDesktopPane is shown.
 477:      * 
 478:      * @param e
 479:      *          The ComponentEvent fired.
 480:      */
 481:     public void componentShown(ComponentEvent e)
 482:     {
 483:       // Do nothing.
 484:     }
 485:   }
 486: 
 487:   /**
 488:    * This helper class acts as the LayoutManager for JInternalFrames.
 489:    */
 490:   public class InternalFrameLayout implements LayoutManager
 491:   {
 492:     /**
 493:      * This method is called when the given Component is added to the
 494:      * JInternalFrame.
 495:      * 
 496:      * @param name
 497:      *          The name of the Component.
 498:      * @param c
 499:      *          The Component added.
 500:      */
 501:     public void addLayoutComponent(String name, Component c)
 502:     {
 503:       // Nothing to do here.
 504:     }
 505: 
 506:     /**
 507:      * This method is used to set the bounds of the children of the
 508:      * JInternalFrame.
 509:      * 
 510:      * @param c
 511:      *          The Container to lay out.
 512:      */
 513:     public void layoutContainer(Container c)
 514:     {
 515:       Dimension dims = frame.getSize();
 516:       Insets insets = frame.getInsets();
 517: 
 518:       dims.width -= insets.left + insets.right;
 519:       dims.height -= insets.top + insets.bottom;
 520: 
 521:       int nh = 0;
 522:       int sh = 0;
 523:       int ew = 0;
 524:       int ww = 0;
 525: 
 526:       if (northPane != null)
 527:         {
 528:           Dimension nDims = northPane.getPreferredSize();
 529:           nh = Math.min(nDims.height, dims.height);
 530: 
 531:           northPane.setBounds(insets.left, insets.top, dims.width, nh);
 532:         }
 533: 
 534:       if (southPane != null)
 535:         {
 536:           Dimension sDims = southPane.getPreferredSize();
 537:           sh = Math.min(sDims.height, dims.height - nh);
 538: 
 539:           southPane.setBounds(insets.left, insets.top + dims.height - sh,
 540:                               dims.width, sh);
 541:         }
 542: 
 543:       int remHeight = dims.height - sh - nh;
 544: 
 545:       if (westPane != null)
 546:         {
 547:           Dimension wDims = westPane.getPreferredSize();
 548:           ww = Math.min(dims.width, wDims.width);
 549: 
 550:           westPane.setBounds(insets.left, insets.top + nh, ww, remHeight);
 551:         }
 552: 
 553:       if (eastPane != null)
 554:         {
 555:           Dimension eDims = eastPane.getPreferredSize();
 556:           ew = Math.min(eDims.width, dims.width - ww);
 557: 
 558:           eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh,
 559:                              ew, remHeight);
 560:         }
 561: 
 562:       int remWidth = dims.width - ww - ew;
 563: 
 564:       frame.getRootPane().setBounds(insets.left + ww, insets.top + nh,
 565:                                     remWidth, remHeight);
 566:     }
 567: 
 568:     /**
 569:      * This method returns the minimum layout size.
 570:      * 
 571:      * @param c
 572:      *          The Container to find a minimum layout size for.
 573:      * @return The minimum dimensions for the JInternalFrame.
 574:      */
 575:     public Dimension minimumLayoutSize(Container c)
 576:     {
 577:       return getSize(c, true);
 578:     }
 579: 
 580:     /**
 581:      * Th8is method returns the preferred layout size.
 582:      * 
 583:      * @param c
 584:      *          The Container to find a preferred layout size for.
 585:      * @return The preferred dimensions for the JInternalFrame.
 586:      */
 587:     public Dimension preferredLayoutSize(Container c)
 588:     {
 589:       return getSize(c, false);
 590:     }
 591: 
 592:     /**
 593:      * DOCUMENT ME!
 594:      * 
 595:      * @param c
 596:      *          DOCUMENT ME!
 597:      * @param min
 598:      *          DOCUMENT ME!
 599:      * @return DOCUMENT ME!
 600:      */
 601:     private Dimension getSize(Container c, boolean min)
 602:     {
 603:       Insets insets = frame.getInsets();
 604: 
 605:       Dimension contentDims = frame.getContentPane().getPreferredSize();
 606:       if (min)
 607:         contentDims.width = contentDims.height = 0;
 608:       int nWidth = 0;
 609:       int nHeight = 0;
 610:       int sWidth = 0;
 611:       int sHeight = 0;
 612:       int eWidth = 0;
 613:       int eHeight = 0;
 614:       int wWidth = 0;
 615:       int wHeight = 0;
 616:       Dimension dims;
 617: 
 618:       if (northPane != null)
 619:         {
 620:           dims = northPane.getPreferredSize();
 621:           if (dims != null)
 622:             {
 623:               nWidth = dims.width;
 624:               nHeight = dims.height;
 625:             }
 626:         }
 627: 
 628:       if (southPane != null)
 629:         {
 630:           dims = southPane.getPreferredSize();
 631:           if (dims != null)
 632:             {
 633:               sWidth = dims.width;
 634:               sHeight = dims.height;
 635:             }
 636:         }
 637: 
 638:       if (eastPane != null)
 639:         {
 640:           dims = eastPane.getPreferredSize();
 641:           if (dims != null)
 642:             {
 643:               sWidth = dims.width;
 644:               sHeight = dims.height;
 645:             }
 646:         }
 647: 
 648:       if (westPane != null)
 649:         {
 650:           dims = westPane.getPreferredSize();
 651:           if (dims != null)
 652:             {
 653:               wWidth = dims.width;
 654:               wHeight = dims.height;
 655:             }
 656:         }
 657: 
 658:       int width = Math.max(sWidth, nWidth);
 659:       width = Math.max(width, contentDims.width + eWidth + wWidth);
 660: 
 661:       int height = Math.max(eHeight, wHeight);
 662:       height = Math.max(height, contentDims.height);
 663:       height += nHeight + sHeight;
 664: 
 665:       width += insets.left + insets.right;
 666:       height += insets.top + insets.bottom;
 667: 
 668:       return new Dimension(width, height);
 669:     }
 670: 
 671:     /**
 672:      * This method is called when a Component is removed from the
 673:      * JInternalFrame.
 674:      *
 675:      * @param c The Component that was removed.
 676:      */
 677:     public void removeLayoutComponent(Component c)
 678:     {
 679:       // Nothing to do here.
 680:     }
 681:   }
 682: 
 683:   /**
 684:    * This helper class is used to listen to the JDesktopPane's glassPane for
 685:    * MouseEvents. The JInternalFrame can then be selected if a click is
 686:    * detected on its children.
 687:    */
 688:   protected class GlassPaneDispatcher implements MouseInputListener
 689:   {
 690:     /** The MouseEvent target. */
 691:     private transient Component mouseEventTarget;
 692: 
 693:     /** The component pressed. */
 694:     private transient Component pressedComponent;
 695: 
 696:     /** The last component entered. */
 697:     private transient Component lastComponentEntered;
 698: 
 699:     /** Used to store/reset lastComponentEntered. */
 700:     private transient Component tempComponent;
 701: 
 702:     /** The number of presses. */
 703:     private transient int pressCount;
 704: 
 705:     /**
 706:      * This method is called when the mouse enters the glass pane.
 707:      * 
 708:      * @param e
 709:      *          The MouseEvent.
 710:      */
 711:     public void mouseEntered(MouseEvent e)
 712:     {
 713:       handleEvent(e);
 714:     }
 715: 
 716:     /**
 717:      * This method is called when the mouse is clicked on the glass pane.
 718:      * 
 719:      * @param e
 720:      *          The MouseEvent.
 721:      */
 722:     public void mouseClicked(MouseEvent e)
 723:     {
 724:       handleEvent(e);
 725:     }
 726: 
 727:     /**
 728:      * This method is called when the mouse is dragged in the glass pane.
 729:      * 
 730:      * @param e
 731:      *          The MouseEvent.
 732:      */
 733:     public void mouseDragged(MouseEvent e)
 734:     {
 735:       handleEvent(e);
 736:     }
 737: 
 738:     /**
 739:      * This method is called when the mouse exits the glass pane.
 740:      * 
 741:      * @param e
 742:      *          The MouseEvent.
 743:      */
 744:     public void mouseExited(MouseEvent e)
 745:     {
 746:       handleEvent(e);
 747:     }
 748: 
 749:     /**
 750:      * This method is called when the mouse is moved in the glass pane.
 751:      * 
 752:      * @param e
 753:      *          The MouseEvent.
 754:      */
 755:     public void mouseMoved(MouseEvent e)
 756:     {
 757:       handleEvent(e);
 758:     }
 759: 
 760:     /**
 761:      * This method is called when the mouse is pressed in the glass pane.
 762:      * 
 763:      * @param e
 764:      *          The MouseEvent.
 765:      */
 766:     public void mousePressed(MouseEvent e)
 767:     {
 768:       activateFrame(frame);
 769:       handleEvent(e);
 770:     }
 771: 
 772:     /**
 773:      * This method is called when the mouse is released in the glass pane.
 774:      * 
 775:      * @param e
 776:      *          The MouseEvent.
 777:      */
 778:     public void mouseReleased(MouseEvent e)
 779:     {
 780:       handleEvent(e);
 781:     }
 782: 
 783:     /**
 784:      * This method acquires a candidate component to dispatch the MouseEvent to.
 785:      * 
 786:      * @param me
 787:      *          The MouseEvent to acquire a component for.
 788:      */
 789:     private void acquireComponentForMouseEvent(MouseEvent me)
 790:     {
 791:       int x = me.getX();
 792:       int y = me.getY();
 793: 
 794:       // Find the candidate which should receive this event.
 795:       Component parent = frame.getLayeredPane();
 796:       if (parent == null)
 797:         return;
 798:       Component candidate = null;
 799:       Point p = me.getPoint();
 800:       while (candidate == null && parent != null)
 801:         {
 802:           candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
 803:           if (candidate == null)
 804:             {
 805:               p = SwingUtilities.convertPoint(parent, p.x, p.y,
 806:                                               parent.getParent());
 807:               parent = parent.getParent();
 808:             }
 809:         }
 810: 
 811:       // If the only candidate we found was the native container itself,
 812:       // don't dispatch any event at all. We only care about the lightweight
 813:       // children here.
 814:       if (candidate == frame.getContentPane())
 815:         candidate = null;
 816: 
 817:       // If our candidate is new, inform the old target we're leaving.
 818:       if (lastComponentEntered != null && lastComponentEntered.isShowing()
 819:           && lastComponentEntered != candidate)
 820:         {
 821:           Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y,
 822:                                                  lastComponentEntered);
 823:           MouseEvent exited = new MouseEvent(lastComponentEntered,
 824:                                              MouseEvent.MOUSE_EXITED,
 825:                                              me.getWhen(), me.getModifiersEx(),
 826:                                              tp.x, tp.y, me.getClickCount(),
 827:                                              me.isPopupTrigger(),
 828:                                              me.getButton());
 829:           tempComponent = lastComponentEntered;
 830:           lastComponentEntered = null;
 831:           tempComponent.dispatchEvent(exited);
 832:         }
 833: 
 834:       // If we have a candidate, maybe enter it.
 835:       if (candidate != null)
 836:         {
 837:           mouseEventTarget = candidate;
 838:           if (candidate.isLightweight() && candidate.isShowing()
 839:               && candidate != frame.getContentPane()
 840:               && candidate != lastComponentEntered)
 841:             {
 842:               lastComponentEntered = mouseEventTarget;
 843:               Point cp = SwingUtilities.convertPoint(frame.getContentPane(), x,
 844:                                                      y, lastComponentEntered);
 845:               MouseEvent entered = new MouseEvent(lastComponentEntered,
 846:                                                   MouseEvent.MOUSE_ENTERED,
 847:                                                   me.getWhen(),
 848:                                                   me.getModifiersEx(), cp.x,
 849:                                                   cp.y, me.getClickCount(),
 850:                                                   me.isPopupTrigger(),
 851:                                                   me.getButton());
 852:               lastComponentEntered.dispatchEvent(entered);
 853:             }
 854:         }
 855: 
 856:       if (me.getID() == MouseEvent.MOUSE_RELEASED
 857:           || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0
 858:           || me.getID() == MouseEvent.MOUSE_DRAGGED)
 859:         // If any of the following events occur while a button is held down,
 860:         // they should be dispatched to the same component to which the
 861:         // original MOUSE_PRESSED event was dispatched:
 862:         // - MOUSE_RELEASED
 863:         // - MOUSE_PRESSED: another button pressed while the first is held down
 864:         // - MOUSE_DRAGGED
 865:         mouseEventTarget = pressedComponent;
 866:       else if (me.getID() == MouseEvent.MOUSE_CLICKED)
 867:         {
 868:           // Don't dispatch CLICKED events whose target is not the same as the
 869:           // target for the original PRESSED event.
 870:           if (candidate != pressedComponent)
 871:             mouseEventTarget = null;
 872:           else if (pressCount == 0)
 873:             pressedComponent = null;
 874:         }
 875:     }
 876: 
 877:     /**
 878:      * This is a helper method that dispatches the GlassPane MouseEvents to the
 879:      * proper component.
 880:      * 
 881:      * @param e
 882:      *          The AWTEvent to be dispatched. Usually an instance of
 883:      *          MouseEvent.
 884:      */
 885:     private void handleEvent(AWTEvent e)
 886:     {
 887:       if (e instanceof MouseEvent)
 888:         {
 889:           MouseEvent me = (MouseEvent) e;
 890:           acquireComponentForMouseEvent(me);
 891: 
 892:           //If there is no target, return
 893:           if (mouseEventTarget == null)
 894:             return;
 895:           
 896:           //Avoid re-dispatching to ourselves and causing an infinite loop
 897:           if (mouseEventTarget.equals(frame.getGlassPane()))
 898:             return;
 899: 
 900:           // Avoid dispatching ENTERED and EXITED events twice.
 901:           if (mouseEventTarget.isShowing()
 902:               && e.getID() != MouseEvent.MOUSE_ENTERED
 903:               && e.getID() != MouseEvent.MOUSE_EXITED)
 904:             {
 905:               MouseEvent newEvt = SwingUtilities.convertMouseEvent(
 906:                                                                    frame.getGlassPane(),
 907:                                                                    me,
 908:                                                                    mouseEventTarget);
 909:               mouseEventTarget.dispatchEvent(newEvt);
 910: 
 911:               switch (e.getID())
 912:                 {
 913:                 case MouseEvent.MOUSE_PRESSED:
 914:                   if (pressCount++ == 0)
 915:                     pressedComponent = mouseEventTarget;
 916:                   break;
 917:                 case MouseEvent.MOUSE_RELEASED:
 918:                   // Clear our memory of the original PRESSED event, only if
 919:                   // we're not expecting a CLICKED event after this. If
 920:                   // there is a CLICKED event after this, it will do clean up.
 921:                   if (--pressCount == 0 && mouseEventTarget != pressedComponent)
 922:                     pressedComponent = null;
 923:                   break;
 924:                 }
 925:             }
 926:         }
 927:     }
 928:   }
 929: 
 930:   /**
 931:    * This helper class listens for PropertyChangeEvents from the
 932:    * JInternalFrame.
 933:    */
 934:   public class InternalFramePropertyChangeListener
 935:     implements PropertyChangeListener
 936:   {
 937: 
 938:     /**
 939:      * This method is called when one of the JInternalFrame's properties change.
 940:      * 
 941:      * @param evt
 942:      *          The PropertyChangeEvent.
 943:      */
 944:     public void propertyChange(PropertyChangeEvent evt)
 945:     {
 946:       if (evt.getPropertyName().equals(JInternalFrame.IS_MAXIMUM_PROPERTY))
 947:         {
 948:           if (frame.isMaximum())
 949:             maximizeFrame(frame);
 950:           else
 951:             minimizeFrame(frame);
 952:         }
 953:       else if (evt.getPropertyName().equals(JInternalFrame.IS_ICON_PROPERTY))
 954:         {
 955:           if (frame.isIcon())
 956:             iconifyFrame(frame);
 957:           else
 958:             deiconifyFrame(frame);
 959:         }
 960:       else if (evt.getPropertyName().equals(JInternalFrame.IS_SELECTED_PROPERTY))
 961:         {
 962:           if (frame.isSelected())
 963:             activateFrame(frame);
 964:           else
 965:             deactivateFrame(frame);
 966:         }
 967:       else if (evt.getPropertyName().equals(JInternalFrame.ROOT_PANE_PROPERTY)
 968:                || evt.getPropertyName().equals(
 969:                                                JInternalFrame.GLASS_PANE_PROPERTY))
 970:         {
 971:           Component old = (Component) evt.getOldValue();
 972:           old.removeMouseListener(glassPaneDispatcher);
 973:           old.removeMouseMotionListener(glassPaneDispatcher);
 974: 
 975:           Component newPane = (Component) evt.getNewValue();
 976:           newPane.addMouseListener(glassPaneDispatcher);
 977:           newPane.addMouseMotionListener(glassPaneDispatcher);
 978: 
 979:           frame.revalidate();
 980:         }
 981:       /*
 982:        * FIXME: need to add ancestor properties to JComponents. else if
 983:        * (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY)) { if
 984:        * (desktopPane != null)
 985:        * desktopPane.removeComponentListener(componentListener); desktopPane =
 986:        * frame.getDesktopPane(); if (desktopPane != null)
 987:        * desktopPane.addComponentListener(componentListener); }
 988:        */
 989:     }
 990:   }
 991: 
 992:   /**
 993:    * This helper class is the border for the JInternalFrame.
 994:    */
 995:   private class InternalFrameBorder extends AbstractBorder implements
 996:       UIResource
 997:   {
 998:     /** The width of the border. */
 999:     private static final int bSize = 5;
1000: 
1001:     /** The size of the corners. */
1002:     private static final int offset = 10;
1003: 
1004:     /**
1005:      * This method returns whether the border is opaque.
1006:      * 
1007:      * @return Whether the border is opaque.
1008:      */
1009:     public boolean isBorderOpaque()
1010:     {
1011:       return true;
1012:     }
1013: 
1014:     /**
1015:      * This method returns the insets of the border.
1016:      * 
1017:      * @param c
1018:      *          The Component to find border insets for.
1019:      * @return The border insets.
1020:      */
1021:     public Insets getBorderInsets(Component c)
1022:     {
1023:       return new Insets(bSize, bSize, bSize, bSize);
1024:     }
1025: 
1026:     /**
1027:      * This method paints the border.
1028:      * 
1029:      * @param c
1030:      *          The Component that owns the border.
1031:      * @param g
1032:      *          The Graphics object to paint with.
1033:      * @param x
1034:      *          The x coordinate to paint at.
1035:      * @param y
1036:      *          The y coordinate to paint at.
1037:      * @param width
1038:      *          The width of the Component.
1039:      * @param height
1040:      *          The height of the Component.
1041:      */
1042:     public void paintBorder(Component c, Graphics g, int x, int y, int width,
1043:                             int height)
1044:     {
1045:       g.translate(x, y);
1046:       Color saved = g.getColor();
1047:       Rectangle b = frame.getBounds();
1048: 
1049:       Color d = c.getBackground();
1050:       g.setColor(d);
1051:       g.fillRect(0, 0, bSize, b.height);
1052:       g.fillRect(0, 0, b.width, bSize);
1053:       g.fillRect(0, b.height - bSize, b.width, bSize);
1054:       g.fillRect(b.width - bSize, 0, bSize, b.height);
1055: 
1056:       int x1 = 0;
1057:       int x2 = bSize;
1058:       int x3 = b.width - bSize;
1059:       int x4 = b.width;
1060: 
1061:       int y1 = 0;
1062:       int y2 = bSize;
1063:       int y3 = b.height - bSize;
1064:       int y4 = b.height;
1065: 
1066:       g.setColor(Color.GRAY);
1067:       g.fillRect(0, 0, bSize, y4);
1068:       g.fillRect(0, 0, x4, bSize);
1069:       g.fillRect(0, y3, b.width, bSize);
1070:       g.fillRect(x3, 0, bSize, b.height);
1071: 
1072:       g.fill3DRect(0, offset, bSize, b.height - 2 * offset, false);
1073:       g.fill3DRect(offset, 0, b.width - 2 * offset, bSize, false);
1074:       g.fill3DRect(offset, b.height - bSize, b.width - 2 * offset, bSize, false);
1075:       g.fill3DRect(b.width - bSize, offset, bSize, b.height - 2 * offset, false);
1076: 
1077:       g.translate(-x, -y);
1078:       g.setColor(saved);
1079:     }
1080:   }
1081: 
1082:   /**
1083:    * The MouseListener that is responsible for dragging and resizing the
1084:    * JInternalFrame in response to MouseEvents.
1085:    */
1086:   protected MouseInputAdapter borderListener;
1087: 
1088:   /**
1089:    * The ComponentListener that is responsible for resizing the JInternalFrame
1090:    * in response to ComponentEvents from the JDesktopPane.
1091:    */
1092:   protected ComponentListener componentListener;
1093: 
1094:   /**
1095:    * The MouseListener that is responsible for activating the JInternalFrame
1096:    * when the mouse press activates one of its descendents.
1097:    */
1098:   protected MouseInputListener glassPaneDispatcher;
1099: 
1100:   /**
1101:    * The PropertyChangeListener that is responsible for listening to
1102:    * PropertyChangeEvents from the JInternalFrame.
1103:    */
1104:   protected PropertyChangeListener propertyChangeListener;
1105: 
1106:   /** The InternalFrameListener that listens to the JInternalFrame. */
1107:   private transient BasicInternalFrameListener internalFrameListener;
1108: 
1109:   /** The JComponent placed at the east region of the JInternalFrame. */
1110:   protected JComponent eastPane;
1111: 
1112:   /** The JComponent placed at the north region of the JInternalFrame. */
1113:   protected JComponent northPane;
1114: 
1115:   /** The JComponent placed at the south region of the JInternalFrame. */
1116:   protected JComponent southPane;
1117: 
1118:   /** The JComponent placed at the west region of the JInternalFrame. */
1119:   protected JComponent westPane;
1120: 
1121:   /**
1122:    * The Keystroke bound to open the menu.
1123:    * @deprecated
1124:    */
1125:   protected KeyStroke openMenuKey;
1126: 
1127:   /** The TitlePane displayed at the top of the JInternalFrame. */
1128:   protected BasicInternalFrameTitlePane titlePane;
1129: 
1130:   /** The JInternalFrame this UI is responsible for. */
1131:   protected JInternalFrame frame;
1132: 
1133:   /** The LayoutManager used in the JInternalFrame. */
1134:   protected LayoutManager internalFrameLayout;
1135: 
1136:   /** The JDesktopPane that is the parent of the JInternalFrame. */
1137:   private transient JDesktopPane desktopPane;
1138: 
1139:   /**
1140:    * Creates a new BasicInternalFrameUI object.
1141:    *
1142:    * @param b The JInternalFrame this UI will represent.
1143:    */
1144:   public BasicInternalFrameUI(JInternalFrame b)
1145:   {
1146:     // Nothing to do here.
1147:   }
1148: 
1149:   /**
1150:    * This method will create a new BasicInternalFrameUI for the given
1151:    * JComponent.
1152:    *
1153:    * @param b The JComponent to create a BasicInternalFrameUI for.
1154:    *
1155:    * @return A new BasicInternalFrameUI.
1156:    */
1157:   public static ComponentUI createUI(JComponent b)
1158:   {
1159:     return new BasicInternalFrameUI((JInternalFrame) b);
1160:   }
1161: 
1162:   /**
1163:    * This method installs a UI for the JInternalFrame.
1164:    *
1165:    * @param c The JComponent to install this UI on.
1166:    */
1167:   public void installUI(JComponent c)
1168:   {
1169:     if (c instanceof JInternalFrame)
1170:       {
1171:         frame = (JInternalFrame) c;
1172: 
1173:         installDefaults();
1174:         installListeners();
1175:         installComponents();
1176:         installKeyboardActions();
1177: 
1178:         if (! frame.isSelected())
1179:           frame.getGlassPane().setVisible(true);
1180:       }
1181:   }
1182: 
1183:   /**
1184:    * This method reverses the work done by installUI.
1185:    *
1186:    * @param c The JComponent to uninstall this UI for.
1187:    */
1188:   public void uninstallUI(JComponent c)
1189:   {
1190:     uninstallKeyboardActions();
1191:     uninstallComponents();
1192:     uninstallListeners();
1193:     uninstallDefaults();
1194: 
1195:     frame.getRootPane().getGlassPane().setVisible(false);
1196:     frame = null;
1197:   }
1198: 
1199:   /**
1200:    * This method installs the defaults specified by the look and feel.
1201:    */
1202:   protected void installDefaults()
1203:     {
1204:       internalFrameLayout = createLayoutManager();
1205:       frame.setLayout(internalFrameLayout);
1206:       LookAndFeel.installBorder(frame, "InternalFrame.border");
1207:       frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon"));
1208: 
1209:       // Let the content pane inherit the background color from its
1210:       // frame by setting the background to null.
1211:       Component contentPane = frame.getContentPane();
1212:       if (contentPane != null
1213:           && contentPane.getBackground() instanceof UIResource)
1214:         {
1215:           contentPane.setBackground(null);
1216:         }
1217:   }
1218: 
1219:   /**
1220:    * This method installs the keyboard actions for the JInternalFrame.
1221:    */
1222:   protected void installKeyboardActions()
1223:     throws NotImplementedException
1224:   {
1225:     // FIXME: Implement.
1226:   }
1227: 
1228:   /**
1229:    * This method installs the Components for the JInternalFrame.
1230:    */
1231:   protected void installComponents()
1232:   {
1233:     setNorthPane(createNorthPane(frame));
1234:     setSouthPane(createSouthPane(frame));
1235:     setEastPane(createEastPane(frame));
1236:     setWestPane(createWestPane(frame));
1237:   }
1238: 
1239:   /**
1240:    * This method installs the listeners for the JInternalFrame.
1241:    */
1242:   protected void installListeners()
1243:   {
1244:     glassPaneDispatcher = createGlassPaneDispatcher();
1245:     createInternalFrameListener();
1246:     borderListener = createBorderListener(frame);
1247:     componentListener = createComponentListener();
1248:     propertyChangeListener = createPropertyChangeListener();
1249: 
1250:     frame.addMouseListener(borderListener);
1251:     frame.addMouseMotionListener(borderListener);
1252:     frame.addInternalFrameListener(internalFrameListener);
1253:     frame.addPropertyChangeListener(propertyChangeListener);
1254:     frame.getRootPane().getGlassPane().addMouseListener(glassPaneDispatcher);
1255:     frame.getRootPane().getGlassPane().addMouseMotionListener(glassPaneDispatcher);
1256:   }
1257: 
1258:   /**
1259:    * This method uninstalls the defaults for the JInternalFrame.
1260:    */
1261:   protected void uninstallDefaults()
1262:   {
1263:     frame.setBorder(null);
1264:     frame.setLayout(null);
1265:     internalFrameLayout = null;
1266:   }
1267: 
1268:   /**
1269:    * This method uninstalls the Components for the JInternalFrame.
1270:    */
1271:   protected void uninstallComponents()
1272:   {
1273:     setNorthPane(null);
1274:     setSouthPane(null);
1275:     setEastPane(null);
1276:     setWestPane(null);
1277:   }
1278: 
1279:   /**
1280:    * This method uninstalls the listeners for the JInternalFrame.
1281:    */
1282:   protected void uninstallListeners()
1283:   {
1284:     if (desktopPane != null)
1285:       desktopPane.removeComponentListener(componentListener);
1286: 
1287:     frame.getRootPane().getGlassPane().removeMouseMotionListener(glassPaneDispatcher);
1288:     frame.getRootPane().getGlassPane().removeMouseListener(glassPaneDispatcher);
1289: 
1290:     frame.removePropertyChangeListener(propertyChangeListener);
1291:     frame.removeInternalFrameListener(internalFrameListener);
1292:     frame.removeMouseMotionListener(borderListener);
1293:     frame.removeMouseListener(borderListener);
1294: 
1295:     propertyChangeListener = null;
1296:     componentListener = null;
1297:     borderListener = null;
1298:     internalFrameListener = null;
1299:     glassPaneDispatcher = null;
1300:   }
1301: 
1302:   /**
1303:    * This method uninstalls the keyboard actions for the JInternalFrame.
1304:    */
1305:   protected void uninstallKeyboardActions()
1306:     throws NotImplementedException
1307:   {
1308:     // FIXME: Implement.
1309:   }
1310: 
1311:   /**
1312:    * This method creates a new LayoutManager for the JInternalFrame.
1313:    *
1314:    * @return A new LayoutManager for the JInternalFrame.
1315:    */
1316:   protected LayoutManager createLayoutManager()
1317:   {
1318:     return new InternalFrameLayout();
1319:   }
1320: 
1321:   /**
1322:    * This method creates a new PropertyChangeListener for the JInternalFrame.
1323:    *
1324:    * @return A new PropertyChangeListener for the JInternalFrame.
1325:    */
1326:   protected PropertyChangeListener createPropertyChangeListener()
1327:   {
1328:     return new InternalFramePropertyChangeListener();
1329:   }
1330: 
1331:   /**
1332:    * This method returns the preferred size of the given JComponent.
1333:    *
1334:    * @param x The JComponent to find a preferred size for.
1335:    *
1336:    * @return The preferred size.
1337:    */
1338:   public Dimension getPreferredSize(JComponent x)
1339:   {
1340:     Dimension pref = null;
1341:     LayoutManager layout = frame.getLayout();
1342:     if (frame == x && layout != null)
1343:       pref = layout.preferredLayoutSize(frame);
1344:     else
1345:       pref = new Dimension(100, 100);
1346:     return pref;
1347:   }
1348: 
1349:   /**
1350:    * This method returns the minimum size of the given JComponent.
1351:    *
1352:    * @param x The JComponent to find a minimum size for.
1353:    *
1354:    * @return The minimum size.
1355:    */
1356:   public Dimension getMinimumSize(JComponent x)
1357:   {
1358:     Dimension min = null;
1359:     LayoutManager layout = frame.getLayout();
1360:     if (frame == x && layout != null)
1361:       min = layout.minimumLayoutSize(frame);
1362:     else
1363:       min = new Dimension(0, 0);
1364:     return min;
1365:   }
1366: 
1367:   /**
1368:    * This method returns the maximum size of the given JComponent.
1369:    *
1370:    * @param x The JComponent to find a maximum size for.
1371:    *
1372:    * @return The maximum size.
1373:    */
1374:   public Dimension getMaximumSize(JComponent x)
1375:   {
1376:     Dimension max = null;
1377:     LayoutManager layout = frame.getLayout();
1378:     if (frame == x && layout != null && layout instanceof LayoutManager2)
1379:       max = ((LayoutManager2) layout).maximumLayoutSize(frame);
1380:     else
1381:       max = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
1382:     return max;
1383:   }
1384: 
1385:   /**
1386:    * This method replaces the currentPane with the newPane. When replacing it
1387:    * also removes the MouseHandlers for the old pane and installs  them on
1388:    * the new pane.
1389:    *
1390:    * @param currentPane The old pane to remove.
1391:    * @param newPane The new pane to install.
1392:    */
1393:   protected void replacePane(JComponent currentPane, JComponent newPane)
1394:   {
1395:     if (currentPane != null)
1396:       {
1397:         deinstallMouseHandlers(currentPane);
1398:         frame.remove(currentPane);
1399:       }
1400: 
1401:     if (newPane != null)
1402:       {
1403:         installMouseHandlers(newPane);
1404:         frame.add(newPane);
1405:       }
1406:   }
1407: 
1408:   /**
1409:    * This method removes the necessary MouseListeners from the given
1410:    * JComponent.
1411:    *
1412:    * @param c The JComponent to remove MouseListeners from.
1413:    */
1414:   protected void deinstallMouseHandlers(JComponent c)
1415:   {
1416:     c.removeMouseListener(borderListener);
1417:     c.removeMouseMotionListener(borderListener);
1418:   }
1419: 
1420:   /**
1421:    * This method installs the necessary MouseListeners from the given
1422:    * JComponent.
1423:    *
1424:    * @param c The JComponent to install MouseListeners on.
1425:    */
1426:   protected void installMouseHandlers(JComponent c)
1427:   {
1428:     c.addMouseListener(borderListener);
1429:     c.addMouseMotionListener(borderListener);
1430:   }
1431: 
1432:   /**
1433:    * This method creates the north pane used in the JInternalFrame.
1434:    *
1435:    * @param w The JInternalFrame to create a north pane for.
1436:    *
1437:    * @return The north pane.
1438:    */
1439:   protected JComponent createNorthPane(JInternalFrame w)
1440:   {
1441:     titlePane = new BasicInternalFrameTitlePane(w);
1442:     return titlePane;
1443:   }
1444: 
1445:   /**
1446:    * This method creates the west pane used in the JInternalFrame.
1447:    *
1448:    * @param w The JInternalFrame to create a west pane for.
1449:    *
1450:    * @return The west pane.
1451:    */
1452:   protected JComponent createWestPane(JInternalFrame w)
1453:   {
1454:     return null;
1455:   }
1456: 
1457:   /**
1458:    * This method creates the south pane used in the JInternalFrame.
1459:    *
1460:    * @param w The JInternalFrame to create a south pane for.
1461:    *
1462:    * @return The south pane.
1463:    */
1464:   protected JComponent createSouthPane(JInternalFrame w)
1465:   {
1466:     return null;
1467:   }
1468: 
1469:   /**
1470:    * This method creates the east pane used in the JInternalFrame.
1471:    *
1472:    * @param w The JInternalFrame to create an east pane for.
1473:    *
1474:    * @return The east pane.
1475:    */
1476:   protected JComponent createEastPane(JInternalFrame w)
1477:   {
1478:     return null;
1479:   }
1480: 
1481:   /**
1482:    * This method returns a new BorderListener for the given JInternalFrame.
1483:    *
1484:    * @param w The JIntenalFrame to create a BorderListener for.
1485:    *
1486:    * @return A new BorderListener.
1487:    */
1488:   protected MouseInputAdapter createBorderListener(JInternalFrame w)
1489:   {
1490:     return new BorderListener();
1491:   }
1492: 
1493:   /**
1494:    * This method creates a new InternalFrameListener for the JInternalFrame.
1495:    */
1496:   protected void createInternalFrameListener()
1497:   {
1498:     internalFrameListener = new BasicInternalFrameListener();
1499:   }
1500: 
1501:   /**
1502:    * DOCUMENT ME!
1503:    *
1504:    * @return DOCUMENT ME!
1505:    */
1506:   protected final boolean isKeyBindingRegistered()
1507:   {
1508:     // FIXME: Implement.
1509:     return false;
1510:   }
1511: 
1512:   /**
1513:    * DOCUMENT ME!
1514:    *
1515:    * @param b DOCUMENT ME!
1516:    */
1517:   protected final void setKeyBindingRegistered(boolean b)
1518:   {
1519:     // FIXME: Implement.
1520:   }
1521: 
1522:   /**
1523:    * DOCUMENT ME!
1524:    *
1525:    * @return DOCUMENT ME!
1526:    */
1527:   public final boolean isKeyBindingActive()
1528:   {
1529:     // FIXME: Implement.
1530:     return false;
1531:   }
1532: 
1533:   /**
1534:    * DOCUMENT ME!
1535:    *
1536:    * @param b DOCUMENT ME!
1537:    */
1538:   protected final void setKeyBindingActive(boolean b)
1539:   {
1540:     // FIXME: Implement.
1541:   }
1542: 
1543:   /**
1544:    * DOCUMENT ME!
1545:    */
1546:   protected void setupMenuOpenKey()
1547:   {
1548:     // FIXME: Implement.
1549:   }
1550: 
1551:   /**
1552:    * DOCUMENT ME!
1553:    */
1554:   protected void setupMenuCloseKey()
1555:   {
1556:     // FIXME: Implement.
1557:   }
1558: 
1559:   /**
1560:    * This method returns the north pane.
1561:    *
1562:    * @return The north pane.
1563:    */
1564:   public JComponent getNorthPane()
1565:   {
1566:     return northPane;
1567:   }
1568: 
1569:   /**
1570:    * This method sets the north pane to be the given JComponent.
1571:    *
1572:    * @param c The new north pane.
1573:    */
1574:   public void setNorthPane(JComponent c)
1575:   {
1576:     replacePane(northPane, c);
1577:     northPane = c;
1578:   }
1579: 
1580:   /**
1581:    * This method returns the south pane.
1582:    *
1583:    * @return The south pane.
1584:    */
1585:   public JComponent getSouthPane()
1586:   {
1587:     return southPane;
1588:   }
1589: 
1590:   /**
1591:    * This method sets the south pane to be the given JComponent.
1592:    *
1593:    * @param c The new south pane.
1594:    */
1595:   public void setSouthPane(JComponent c)
1596:   {
1597:     replacePane(southPane, c);
1598:     southPane = c;
1599:   }
1600: 
1601:   /**
1602:    * This method sets the east pane to be the given JComponent.
1603:    *
1604:    * @param c The new east pane.
1605:    */
1606:   public void setEastPane(JComponent c)
1607:   {
1608:     replacePane(eastPane, c);
1609:     eastPane = c;
1610:   }
1611: 
1612:   /**
1613:    * This method returns the east pane.
1614:    *
1615:    * @return The east pane.
1616:    */
1617:   public JComponent getEastPane()
1618:   {
1619:     return eastPane;
1620:   }
1621: 
1622:   /**
1623:    * This method sets the west pane to be the given JComponent.
1624:    *
1625:    * @param c The new west pane.
1626:    */
1627:   public void setWestPane(JComponent c)
1628:   {
1629:     replacePane(westPane, c);
1630:     westPane = c;
1631:   }
1632: 
1633:   /**
1634:    * This method returns the west pane.
1635:    *
1636:    * @return The west pane.
1637:    */
1638:   public JComponent getWestPane()
1639:   {
1640:     return westPane;
1641:   }
1642: 
1643:   /**
1644:    * This method returns the DesktopManager to use with the JInternalFrame.
1645:    *
1646:    * @return The DesktopManager to use with the JInternalFrame.
1647:    */
1648:   protected DesktopManager getDesktopManager()
1649:   {
1650:     DesktopManager value = null;
1651:     JDesktopPane pane = frame.getDesktopPane();
1652:     if (pane != null)
1653:       value = frame.getDesktopPane().getDesktopManager();
1654:     if (value == null)
1655:       value = createDesktopManager();
1656:     return value;
1657:   }
1658: 
1659:   /**
1660:    * This method returns a default DesktopManager that can be used with this
1661:    * JInternalFrame.
1662:    *
1663:    * @return A default DesktopManager that can be used with this
1664:    *         JInternalFrame.
1665:    */
1666:   protected DesktopManager createDesktopManager()
1667:   {
1668:     return new DefaultDesktopManager();
1669:   }
1670: 
1671:   /**
1672:    * This is a convenience method that closes the JInternalFrame.
1673:    *
1674:    * @param f The JInternalFrame to close.
1675:    */
1676:   protected void closeFrame(JInternalFrame f)
1677:   {
1678:     getDesktopManager().closeFrame(f);
1679:   }
1680: 
1681:   /**
1682:    * This is a convenience method that maximizes the JInternalFrame.
1683:    *
1684:    * @param f The JInternalFrame to maximize.
1685:    */
1686:   protected void maximizeFrame(JInternalFrame f)
1687:   {
1688:     getDesktopManager().maximizeFrame(f);
1689:   }
1690: 
1691:   /**
1692:    * This is a convenience method that minimizes the JInternalFrame.
1693:    *
1694:    * @param f The JInternalFrame to minimize.
1695:    */
1696:   protected void minimizeFrame(JInternalFrame f)
1697:   {
1698:     getDesktopManager().minimizeFrame(f);
1699:   }
1700: 
1701:   /**
1702:    * This is a convenience method that iconifies the JInternalFrame.
1703:    *
1704:    * @param f The JInternalFrame to iconify.
1705:    */
1706:   protected void iconifyFrame(JInternalFrame f)
1707:   {
1708:     getDesktopManager().iconifyFrame(f);
1709:   }
1710: 
1711:   /**
1712:    * This is a convenience method that deiconifies the JInternalFrame.
1713:    *
1714:    * @param f The JInternalFrame to deiconify.
1715:    */
1716:   protected void deiconifyFrame(JInternalFrame f)
1717:   {
1718:     getDesktopManager().deiconifyFrame(f);
1719:   }
1720: 
1721:   /**
1722:    * This is a convenience method that activates the JInternalFrame.
1723:    *
1724:    * @param f The JInternalFrame to activate.
1725:    */
1726:   protected void activateFrame(JInternalFrame f)
1727:   {
1728:     getDesktopManager().activateFrame(f);
1729:   }
1730: 
1731:   /**
1732:    * This is a convenience method that deactivates the JInternalFrame.
1733:    *
1734:    * @param f the JInternalFrame to deactivate
1735:    */
1736:   protected void deactivateFrame(JInternalFrame f)
1737:   {
1738:     getDesktopManager().deactivateFrame(f);
1739:   }
1740: 
1741:   /**
1742:    * This method returns a new ComponentListener for the JDesktopPane.
1743:    *
1744:    * @return A new ComponentListener.
1745:    */
1746:   protected ComponentListener createComponentListener()
1747:   {
1748:     return new ComponentHandler();
1749:   }
1750: 
1751:   /**
1752:    * This method returns a new GlassPaneDispatcher.
1753:    *
1754:    * @return A new GlassPaneDispatcher.
1755:    */
1756:   protected MouseInputListener createGlassPaneDispatcher()
1757:   {
1758:     return new GlassPaneDispatcher();
1759:   }
1760: }