Source for javax.swing.plaf.basic.BasicInternalFrameUI

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