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