1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing.plaf.basic;
  27 
  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import javax.swing.*;
  31 import javax.swing.plaf.*;
  32 import javax.swing.event.*;
  33 import java.beans.*;
  34 import sun.swing.DefaultLookup;
  35 import sun.swing.UIAction;
  36 
  37 /**
  38  * A basic L&F implementation of JInternalFrame.
  39  *
  40  * @author David Kloba
  41  * @author Rich Schiavi
  42  */
  43 public class BasicInternalFrameUI extends InternalFrameUI
  44 {
  45 
  46     protected JInternalFrame frame;
  47 
  48     private Handler handler;
  49     protected MouseInputAdapter          borderListener;
  50     protected PropertyChangeListener     propertyChangeListener;
  51     protected LayoutManager              internalFrameLayout;
  52     protected ComponentListener          componentListener;
  53     protected MouseInputListener         glassPaneDispatcher;
  54     private InternalFrameListener        internalFrameListener;
  55 
  56     protected JComponent northPane;
  57     protected JComponent southPane;
  58     protected JComponent westPane;
  59     protected JComponent eastPane;
  60 
  61     protected BasicInternalFrameTitlePane titlePane; // access needs this
  62 
  63     private static DesktopManager sharedDesktopManager;
  64     private boolean componentListenerAdded = false;
  65 
  66     private Rectangle parentBounds;
  67 
  68     private boolean dragging = false;
  69     private boolean resizing = false;
  70 
  71     /**
  72      * As of Java 2 platform v1.3 this previously undocumented field is no
  73      * longer used.
  74      * Key bindings are now defined by the LookAndFeel, please refer to
  75      * the key bindings specification for further details.
  76      *
  77      * @deprecated As of Java 2 platform v1.3.
  78      */
  79     @Deprecated
  80     protected KeyStroke openMenuKey;
  81 
  82     private boolean keyBindingRegistered = false;
  83     private boolean keyBindingActive = false;
  84 
  85 /////////////////////////////////////////////////////////////////////////////
  86 // ComponentUI Interface Implementation methods
  87 /////////////////////////////////////////////////////////////////////////////
  88     public static ComponentUI createUI(JComponent b)    {
  89         return new BasicInternalFrameUI((JInternalFrame)b);
  90     }
  91 
  92     public BasicInternalFrameUI(JInternalFrame b)   {
  93         LookAndFeel laf = UIManager.getLookAndFeel();
  94         if (laf instanceof BasicLookAndFeel) {
  95             ((BasicLookAndFeel)laf).installAWTEventListener();
  96         }
  97     }
  98 
  99     public void installUI(JComponent c)   {
 100 
 101         frame = (JInternalFrame)c;
 102 
 103         installDefaults();
 104         installListeners();
 105         installComponents();
 106         installKeyboardActions();
 107 
 108         LookAndFeel.installProperty(frame, "opaque", Boolean.TRUE);
 109     }
 110 
 111     public void uninstallUI(JComponent c) {
 112         if(c != frame)
 113             throw new IllegalComponentStateException(
 114                 this + " was asked to deinstall() "
 115                 + c + " when it only knows about "
 116                 + frame + ".");
 117 
 118         uninstallKeyboardActions();
 119         uninstallComponents();
 120         uninstallListeners();
 121         uninstallDefaults();
 122         updateFrameCursor();
 123         handler = null;
 124         frame = null;
 125     }
 126 
 127     protected void installDefaults(){
 128         Icon frameIcon = frame.getFrameIcon();
 129         if (frameIcon == null || frameIcon instanceof UIResource) {
 130             frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon"));
 131         }
 132 
 133         // Enable the content pane to inherit background color from its
 134         // parent by setting its background color to null.
 135         Container contentPane = frame.getContentPane();
 136         if (contentPane != null) {
 137           Color bg = contentPane.getBackground();
 138           if (bg instanceof UIResource)
 139             contentPane.setBackground(null);
 140         }
 141         frame.setLayout(internalFrameLayout = createLayoutManager());
 142         frame.setBackground(UIManager.getLookAndFeelDefaults().getColor("control"));
 143 
 144         LookAndFeel.installBorder(frame, "InternalFrame.border");
 145 
 146     }
 147     protected void installKeyboardActions(){
 148         createInternalFrameListener();
 149         if (internalFrameListener != null) {
 150             frame.addInternalFrameListener(internalFrameListener);
 151         }
 152 
 153         LazyActionMap.installLazyActionMap(frame, BasicInternalFrameUI.class,
 154             "InternalFrame.actionMap");
 155     }
 156 
 157     static void loadActionMap(LazyActionMap map) {
 158         map.put(new UIAction("showSystemMenu") {
 159             public void actionPerformed(ActionEvent evt) {
 160                 JInternalFrame iFrame = (JInternalFrame)evt.getSource();
 161                 if (iFrame.getUI() instanceof BasicInternalFrameUI) {
 162                     JComponent comp = ((BasicInternalFrameUI)
 163                         iFrame.getUI()).getNorthPane();
 164                     if (comp instanceof BasicInternalFrameTitlePane) {
 165                         ((BasicInternalFrameTitlePane)comp).
 166                             showSystemMenu();
 167                     }
 168                 }
 169             }
 170 
 171             public boolean isEnabled(Object sender){
 172                 if (sender instanceof JInternalFrame) {
 173                     JInternalFrame iFrame = (JInternalFrame)sender;
 174                     if (iFrame.getUI() instanceof BasicInternalFrameUI) {
 175                         return ((BasicInternalFrameUI)iFrame.getUI()).
 176                             isKeyBindingActive();
 177                     }
 178                 }
 179                 return false;
 180             }
 181         });
 182 
 183         // Set the ActionMap's parent to the Auditory Feedback Action Map
 184         BasicLookAndFeel.installAudioActionMap(map);
 185     }
 186 
 187     protected void installComponents(){
 188         setNorthPane(createNorthPane(frame));
 189         setSouthPane(createSouthPane(frame));
 190         setEastPane(createEastPane(frame));
 191         setWestPane(createWestPane(frame));
 192     }
 193 
 194     /**
 195      * @since 1.3
 196      */
 197     protected void installListeners() {
 198         borderListener = createBorderListener(frame);
 199         propertyChangeListener = createPropertyChangeListener();
 200         frame.addPropertyChangeListener(propertyChangeListener);
 201         installMouseHandlers(frame);
 202         glassPaneDispatcher = createGlassPaneDispatcher();
 203         if (glassPaneDispatcher != null) {
 204             frame.getGlassPane().addMouseListener(glassPaneDispatcher);
 205             frame.getGlassPane().addMouseMotionListener(glassPaneDispatcher);
 206         }
 207         componentListener =  createComponentListener();
 208         if (frame.getParent() != null) {
 209           parentBounds = frame.getParent().getBounds();
 210         }
 211         if ((frame.getParent() != null) && !componentListenerAdded) {
 212             frame.getParent().addComponentListener(componentListener);
 213             componentListenerAdded = true;
 214         }
 215     }
 216 
 217     // Provide a FocusListener to listen for a WINDOW_LOST_FOCUS event,
 218     // so that a resize can be cancelled if the focus is lost while resizing
 219     // when an Alt-Tab, modal dialog popup, iconify, dispose, or remove
 220     // of the internal frame occurs.
 221     private WindowFocusListener getWindowFocusListener(){
 222         return getHandler();
 223     }
 224 
 225     // Cancel a resize in progress by calling finishMouseReleased().
 226     private void cancelResize() {
 227         if (resizing) {
 228             if (borderListener instanceof BorderListener) {
 229                 ((BorderListener)borderListener).finishMouseReleased();
 230             }
 231         }
 232     }
 233 
 234     private Handler getHandler() {
 235         if (handler == null) {
 236             handler = new Handler();
 237         }
 238         return handler;
 239     }
 240 
 241     InputMap getInputMap(int condition) {
 242         if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
 243             return createInputMap(condition);
 244         }
 245         return null;
 246     }
 247 
 248     InputMap createInputMap(int condition) {
 249         if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
 250             Object[] bindings = (Object[])DefaultLookup.get(
 251                     frame, this, "InternalFrame.windowBindings");
 252 
 253             if (bindings != null) {
 254                 return LookAndFeel.makeComponentInputMap(frame, bindings);
 255             }
 256         }
 257         return null;
 258     }
 259 
 260     protected void uninstallDefaults() {
 261         Icon frameIcon = frame.getFrameIcon();
 262         if (frameIcon instanceof UIResource) {
 263             frame.setFrameIcon(null);
 264         }
 265         internalFrameLayout = null;
 266         frame.setLayout(null);
 267         LookAndFeel.uninstallBorder(frame);
 268     }
 269 
 270     protected void uninstallComponents(){
 271         setNorthPane(null);
 272         setSouthPane(null);
 273         setEastPane(null);
 274         setWestPane(null);
 275         if(titlePane != null) {
 276             titlePane.uninstallDefaults();
 277         }
 278         titlePane = null;
 279     }
 280 
 281     /**
 282      * @since 1.3
 283      */
 284     protected void uninstallListeners() {
 285         if ((frame.getParent() != null) && componentListenerAdded) {
 286             frame.getParent().removeComponentListener(componentListener);
 287             componentListenerAdded = false;
 288         }
 289         componentListener = null;
 290       if (glassPaneDispatcher != null) {
 291           frame.getGlassPane().removeMouseListener(glassPaneDispatcher);
 292           frame.getGlassPane().removeMouseMotionListener(glassPaneDispatcher);
 293           glassPaneDispatcher = null;
 294       }
 295       deinstallMouseHandlers(frame);
 296       frame.removePropertyChangeListener(propertyChangeListener);
 297       propertyChangeListener = null;
 298       borderListener = null;
 299     }
 300 
 301     protected void uninstallKeyboardActions(){
 302         if (internalFrameListener != null) {
 303             frame.removeInternalFrameListener(internalFrameListener);
 304         }
 305         internalFrameListener = null;
 306 
 307         SwingUtilities.replaceUIInputMap(frame, JComponent.
 308                                          WHEN_IN_FOCUSED_WINDOW, null);
 309         SwingUtilities.replaceUIActionMap(frame, null);
 310 
 311     }
 312 
 313     void updateFrameCursor() {
 314         if (resizing) {
 315             return;
 316         }
 317         Cursor s = frame.getLastCursor();
 318         if (s == null) {
 319             s = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
 320         }
 321         frame.setCursor(s);
 322     }
 323 
 324     protected LayoutManager createLayoutManager(){
 325         return getHandler();
 326     }
 327 
 328     protected PropertyChangeListener createPropertyChangeListener(){
 329         return getHandler();
 330     }
 331 
 332 
 333 
 334     public Dimension getPreferredSize(JComponent x)    {
 335         if(frame == x)
 336             return frame.getLayout().preferredLayoutSize(x);
 337         return new Dimension(100, 100);
 338     }
 339 
 340     public Dimension getMinimumSize(JComponent x)  {
 341         if(frame == x) {
 342             return frame.getLayout().minimumLayoutSize(x);
 343         }
 344         return new Dimension(0, 0);
 345     }
 346 
 347     public Dimension getMaximumSize(JComponent x) {
 348         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
 349     }
 350 
 351 
 352 
 353     /**
 354      * Installs necessary mouse handlers on <code>newPane</code>
 355      * and adds it to the frame.
 356      * Reverse process for the <code>currentPane</code>.
 357      *
 358      * @param currentPane this {@code Jcomponent} is the current pane being
 359      * viewed that has mouse handlers installed
 360      * @param newPane this {@code Jcomponent} is the pane which will be added
 361      * and have mouse handlers installed
 362      */
 363     protected void replacePane(JComponent currentPane, JComponent newPane) {
 364         if(currentPane != null) {
 365             deinstallMouseHandlers(currentPane);
 366             frame.remove(currentPane);
 367         }
 368         if(newPane != null) {
 369            frame.add(newPane);
 370            installMouseHandlers(newPane);
 371         }
 372     }
 373 
 374     protected void deinstallMouseHandlers(JComponent c) {
 375       c.removeMouseListener(borderListener);
 376       c.removeMouseMotionListener(borderListener);
 377     }
 378 
 379     protected void installMouseHandlers(JComponent c) {
 380       c.addMouseListener(borderListener);
 381       c.addMouseMotionListener(borderListener);
 382     }
 383 
 384     protected JComponent createNorthPane(JInternalFrame w) {
 385       titlePane = new BasicInternalFrameTitlePane(w);
 386       return titlePane;
 387     }
 388 
 389 
 390     protected JComponent createSouthPane(JInternalFrame w) {
 391         return null;
 392     }
 393 
 394     protected JComponent createWestPane(JInternalFrame w) {
 395         return null;
 396     }
 397 
 398     protected JComponent createEastPane(JInternalFrame w) {
 399         return null;
 400     }
 401 
 402 
 403     protected MouseInputAdapter createBorderListener(JInternalFrame w) {
 404         return new BorderListener();
 405     }
 406 
 407     protected void createInternalFrameListener(){
 408         internalFrameListener = getHandler();
 409     }
 410 
 411     protected final boolean isKeyBindingRegistered(){
 412       return keyBindingRegistered;
 413     }
 414 
 415     protected final void setKeyBindingRegistered(boolean b){
 416       keyBindingRegistered = b;
 417     }
 418 
 419     public final boolean isKeyBindingActive(){
 420       return keyBindingActive;
 421     }
 422 
 423     protected final void setKeyBindingActive(boolean b){
 424       keyBindingActive = b;
 425     }
 426 
 427 
 428     protected void setupMenuOpenKey(){
 429         // PENDING(hania): Why are these WHEN_IN_FOCUSED_WINDOWs? Shouldn't
 430         // they be WHEN_ANCESTOR_OF_FOCUSED_COMPONENT?
 431         // Also, no longer registering on the desktopicon, the previous
 432         // action did nothing.
 433         InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
 434         SwingUtilities.replaceUIInputMap(frame,
 435                                       JComponent.WHEN_IN_FOCUSED_WINDOW, map);
 436         //ActionMap actionMap = getActionMap();
 437         //SwingUtilities.replaceUIActionMap(frame, actionMap);
 438     }
 439 
 440     protected void setupMenuCloseKey(){
 441     }
 442 
 443     public JComponent getNorthPane() {
 444         return northPane;
 445     }
 446 
 447     public void setNorthPane(JComponent c) {
 448         if (northPane != null &&
 449                 northPane instanceof BasicInternalFrameTitlePane) {
 450             ((BasicInternalFrameTitlePane)northPane).uninstallListeners();
 451         }
 452         replacePane(northPane, c);
 453         northPane = c;
 454         if (c instanceof BasicInternalFrameTitlePane) {
 455           titlePane = (BasicInternalFrameTitlePane)c;
 456         }
 457     }
 458 
 459     public JComponent getSouthPane() {
 460         return southPane;
 461     }
 462 
 463     public void setSouthPane(JComponent c) {
 464         southPane = c;
 465     }
 466 
 467     public JComponent getWestPane() {
 468         return westPane;
 469     }
 470 
 471     public void setWestPane(JComponent c) {
 472         westPane = c;
 473     }
 474 
 475     public JComponent getEastPane() {
 476         return eastPane;
 477     }
 478 
 479     public void setEastPane(JComponent c) {
 480         eastPane = c;
 481     }
 482 
 483     public class InternalFramePropertyChangeListener implements
 484         PropertyChangeListener {
 485         // NOTE: This class exists only for backward compatibility. All
 486         // its functionality has been moved into Handler. If you need to add
 487         // new functionality add it to the Handler, but make sure this
 488         // class calls into the Handler.
 489         /**
 490          * Detects changes in state from the JInternalFrame and handles
 491          * actions.
 492          */
 493         public void propertyChange(PropertyChangeEvent evt) {
 494             getHandler().propertyChange(evt);
 495         }
 496     }
 497 
 498   public class InternalFrameLayout implements LayoutManager {
 499     // NOTE: This class exists only for backward compatibility. All
 500     // its functionality has been moved into Handler. If you need to add
 501     // new functionality add it to the Handler, but make sure this
 502     // class calls into the Handler.
 503     public void addLayoutComponent(String name, Component c) {
 504         getHandler().addLayoutComponent(name, c);
 505     }
 506 
 507     public void removeLayoutComponent(Component c) {
 508         getHandler().removeLayoutComponent(c);
 509     }
 510 
 511     public Dimension preferredLayoutSize(Container c)  {
 512         return getHandler().preferredLayoutSize(c);
 513     }
 514 
 515     public Dimension minimumLayoutSize(Container c) {
 516         return getHandler().minimumLayoutSize(c);
 517     }
 518 
 519     public void layoutContainer(Container c) {
 520         getHandler().layoutContainer(c);
 521     }
 522   }
 523 
 524 /// DesktopManager methods
 525     /**
 526      * Returns the proper DesktopManager. Calls getDesktopPane() to
 527      * find the JDesktop component and returns the desktopManager from
 528      * it. If this fails, it will return a default DesktopManager that
 529      * should work in arbitrary parents.
 530      */
 531     protected DesktopManager getDesktopManager() {
 532         if(frame.getDesktopPane() != null
 533            && frame.getDesktopPane().getDesktopManager() != null)
 534             return frame.getDesktopPane().getDesktopManager();
 535         if(sharedDesktopManager == null)
 536           sharedDesktopManager = createDesktopManager();
 537         return sharedDesktopManager;
 538     }
 539 
 540     protected DesktopManager createDesktopManager(){
 541       return new DefaultDesktopManager();
 542     }
 543 
 544     /**
 545      * This method is called when the user wants to close the frame.
 546      * The <code>playCloseSound</code> Action is fired.
 547      * This action is delegated to the desktopManager.
 548      *
 549      * @param f the {@code JInternalFrame} being viewed
 550      */
 551     protected void closeFrame(JInternalFrame f) {
 552         // Internal Frame Auditory Cue Activation
 553         BasicLookAndFeel.playSound(frame,"InternalFrame.closeSound");
 554         // delegate to desktop manager
 555         getDesktopManager().closeFrame(f);
 556     }
 557 
 558     /**
 559      * This method is called when the user wants to maximize the frame.
 560      * The <code>playMaximizeSound</code> Action is fired.
 561      * This action is delegated to the desktopManager.
 562      *
 563      * @param f the {@code JInternalFrame} being viewed
 564      */
 565     protected void maximizeFrame(JInternalFrame f) {
 566         // Internal Frame Auditory Cue Activation
 567         BasicLookAndFeel.playSound(frame,"InternalFrame.maximizeSound");
 568         // delegate to desktop manager
 569         getDesktopManager().maximizeFrame(f);
 570     }
 571 
 572     /**
 573      * This method is called when the user wants to minimize the frame.
 574      * The <code>playRestoreDownSound</code> Action is fired.
 575      * This action is delegated to the desktopManager.
 576      *
 577      * @param f the {@code JInternalFrame} being viewed
 578      */
 579     protected void minimizeFrame(JInternalFrame f) {
 580         // Internal Frame Auditory Cue Activation
 581         if ( ! f.isIcon() ) {
 582             // This method seems to regularly get called after an
 583             // internal frame is iconified. Don't play this sound then.
 584             BasicLookAndFeel.playSound(frame,"InternalFrame.restoreDownSound");
 585         }
 586         // delegate to desktop manager
 587         getDesktopManager().minimizeFrame(f);
 588     }
 589 
 590     /**
 591      * This method is called when the user wants to iconify the frame.
 592      * The <code>playMinimizeSound</code> Action is fired.
 593      * This action is delegated to the desktopManager.
 594      *
 595      * @param f the {@code JInternalFrame} being viewed
 596      */
 597     protected void iconifyFrame(JInternalFrame f) {
 598         // Internal Frame Auditory Cue Activation
 599         BasicLookAndFeel.playSound(frame, "InternalFrame.minimizeSound");
 600         // delegate to desktop manager
 601         getDesktopManager().iconifyFrame(f);
 602     }
 603 
 604     /**
 605      * This method is called when the user wants to deiconify the frame.
 606      * The <code>playRestoreUpSound</code> Action is fired.
 607      * This action is delegated to the desktopManager.
 608      *
 609      * @param f the {@code JInternalFrame} being viewed
 610      */
 611     protected void deiconifyFrame(JInternalFrame f) {
 612         // Internal Frame Auditory Cue Activation
 613         if ( ! f.isMaximum() ) {
 614             // This method seems to regularly get called after an
 615             // internal frame is maximized. Don't play this sound then.
 616             BasicLookAndFeel.playSound(frame, "InternalFrame.restoreUpSound");
 617         }
 618         // delegate to desktop manager
 619         getDesktopManager().deiconifyFrame(f);
 620     }
 621 
 622     /**
 623       * This method is called when the frame becomes selected.
 624       * This action is delegated to the desktopManager.
 625       *
 626       * @param f the {@code JInternalFrame} being viewed
 627       */
 628     protected void activateFrame(JInternalFrame f) {
 629         getDesktopManager().activateFrame(f);
 630     }
 631     /**
 632      * This method is called when the frame is no longer selected.
 633      * This action is delegated to the desktopManager.
 634      *
 635      * @param f the {@code JInternalFrame} being viewed
 636      */
 637     protected void deactivateFrame(JInternalFrame f) {
 638         getDesktopManager().deactivateFrame(f);
 639     }
 640 
 641     /////////////////////////////////////////////////////////////////////////
 642     /// Border Listener Class
 643     /////////////////////////////////////////////////////////////////////////
 644     /**
 645      * Listens for border adjustments.
 646      */
 647     protected class BorderListener extends MouseInputAdapter implements SwingConstants
 648     {
 649         // _x & _y are the mousePressed location in absolute coordinate system
 650         int _x, _y;
 651         // __x & __y are the mousePressed location in source view's coordinate system
 652         int __x, __y;
 653         Rectangle startingBounds;
 654         int resizeDir;
 655 
 656 
 657         protected final int RESIZE_NONE  = 0;
 658         private boolean discardRelease = false;
 659 
 660         int resizeCornerSize = 16;
 661 
 662         public void mouseClicked(MouseEvent e) {
 663             if(e.getClickCount() > 1 && e.getSource() == getNorthPane()) {
 664                 if(frame.isIconifiable() && frame.isIcon()) {
 665                     try { frame.setIcon(false); } catch (PropertyVetoException e2) { }
 666                 } else if(frame.isMaximizable()) {
 667                     if(!frame.isMaximum())
 668                         try { frame.setMaximum(true); } catch (PropertyVetoException e2) { }
 669                     else
 670                         try { frame.setMaximum(false); } catch (PropertyVetoException e3) { }
 671                 }
 672             }
 673         }
 674 
 675         // Factor out finishMouseReleased() from mouseReleased(), so that
 676         // it can be called by cancelResize() without passing it a null
 677         // MouseEvent.
 678         void finishMouseReleased() {
 679            if (discardRelease) {
 680              discardRelease = false;
 681              return;
 682           }
 683             if (resizeDir == RESIZE_NONE) {
 684                 getDesktopManager().endDraggingFrame(frame);
 685                 dragging = false;
 686             } else {
 687                 // Remove the WindowFocusListener for handling a
 688                 // WINDOW_LOST_FOCUS event with a cancelResize().
 689                 Window windowAncestor =
 690                     SwingUtilities.getWindowAncestor(frame);
 691                 if (windowAncestor != null) {
 692                     windowAncestor.removeWindowFocusListener(
 693                         getWindowFocusListener());
 694                 }
 695                 Container c = frame.getTopLevelAncestor();
 696                 if (c instanceof RootPaneContainer) {
 697                     Component glassPane = ((RootPaneContainer)c).getGlassPane();
 698                     glassPane.setCursor(Cursor.getPredefinedCursor(
 699                         Cursor.DEFAULT_CURSOR));
 700                     glassPane.setVisible(false);
 701                 }
 702                 getDesktopManager().endResizingFrame(frame);
 703                 resizing = false;
 704                 updateFrameCursor();
 705             }
 706             _x = 0;
 707             _y = 0;
 708             __x = 0;
 709             __y = 0;
 710             startingBounds = null;
 711             resizeDir = RESIZE_NONE;
 712             // Set discardRelease to true, so that only a mousePressed()
 713             // which sets it to false, will allow entry to the above code
 714             // for finishing a resize.
 715             discardRelease = true;
 716         }
 717 
 718         public void mouseReleased(MouseEvent e) {
 719             finishMouseReleased();
 720         }
 721 
 722         public void mousePressed(MouseEvent e) {
 723             Point p = SwingUtilities.convertPoint((Component)e.getSource(),
 724                         e.getX(), e.getY(), null);
 725             __x = e.getX();
 726             __y = e.getY();
 727             _x = p.x;
 728             _y = p.y;
 729             startingBounds = frame.getBounds();
 730             resizeDir = RESIZE_NONE;
 731             discardRelease = false;
 732 
 733             try { frame.setSelected(true); }
 734             catch (PropertyVetoException e1) { }
 735 
 736             Insets i = frame.getInsets();
 737 
 738             Point ep = new Point(__x, __y);
 739             if (e.getSource() == getNorthPane()) {
 740                 Point np = getNorthPane().getLocation();
 741                 ep.x += np.x;
 742                 ep.y += np.y;
 743             }
 744 
 745             if (e.getSource() == getNorthPane()) {
 746                 if (ep.x > i.left && ep.y > i.top && ep.x < frame.getWidth() - i.right) {
 747                     getDesktopManager().beginDraggingFrame(frame);
 748                     dragging = true;
 749                     return;
 750                 }
 751             }
 752             if (!frame.isResizable()) {
 753               return;
 754             }
 755 
 756             if (e.getSource() == frame || e.getSource() == getNorthPane()) {
 757                 if (ep.x <= i.left) {
 758                     if (ep.y < resizeCornerSize + i.top) {
 759                         resizeDir = NORTH_WEST;
 760                     } else if (ep.y > frame.getHeight()
 761                               - resizeCornerSize - i.bottom) {
 762                         resizeDir = SOUTH_WEST;
 763                     } else {
 764                         resizeDir = WEST;
 765 }
 766                 } else if (ep.x >= frame.getWidth() - i.right) {
 767                     if (ep.y < resizeCornerSize + i.top) {
 768                         resizeDir = NORTH_EAST;
 769                     } else if (ep.y > frame.getHeight()
 770                               - resizeCornerSize - i.bottom) {
 771                         resizeDir = SOUTH_EAST;
 772                     } else {
 773                         resizeDir = EAST;
 774                     }
 775                 } else if (ep.y <= i.top) {
 776                     if (ep.x < resizeCornerSize + i.left) {
 777                         resizeDir = NORTH_WEST;
 778                     } else if (ep.x > frame.getWidth()
 779                               - resizeCornerSize - i.right) {
 780                         resizeDir = NORTH_EAST;
 781                     } else {
 782                         resizeDir = NORTH;
 783                     }
 784                 } else if (ep.y >= frame.getHeight() - i.bottom) {
 785                     if (ep.x < resizeCornerSize + i.left) {
 786                         resizeDir = SOUTH_WEST;
 787                     } else if (ep.x > frame.getWidth()
 788                               - resizeCornerSize - i.right) {
 789                         resizeDir = SOUTH_EAST;
 790                     } else {
 791                       resizeDir = SOUTH;
 792                     }
 793                 } else {
 794                     /* the mouse press happened inside the frame, not in the
 795                      border */
 796                   discardRelease = true;
 797                   return;
 798                 }
 799                 Cursor s = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
 800                 switch (resizeDir) {
 801                 case SOUTH:
 802                   s = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
 803                   break;
 804                 case NORTH:
 805                   s = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
 806                   break;
 807                 case WEST:
 808                   s = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
 809                   break;
 810                 case EAST:
 811                   s = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
 812                   break;
 813                 case SOUTH_EAST:
 814                   s = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
 815                   break;
 816                 case SOUTH_WEST:
 817                   s = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
 818                   break;
 819                 case NORTH_WEST:
 820                   s = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
 821                   break;
 822                 case NORTH_EAST:
 823                   s = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
 824                   break;
 825                 }
 826                 Container c = frame.getTopLevelAncestor();
 827                 if (c instanceof RootPaneContainer) {
 828                     Component glassPane = ((RootPaneContainer)c).getGlassPane();
 829                     glassPane.setVisible(true);
 830                     glassPane.setCursor(s);
 831                 }
 832                 getDesktopManager().beginResizingFrame(frame, resizeDir);
 833                 resizing = true;
 834                 // Add the WindowFocusListener for handling a
 835                 // WINDOW_LOST_FOCUS event with a cancelResize().
 836                 Window windowAncestor = SwingUtilities.getWindowAncestor(frame);
 837                 if (windowAncestor != null) {
 838                     windowAncestor.addWindowFocusListener(
 839                         getWindowFocusListener());
 840                 }
 841                 return;
 842             }
 843         }
 844 
 845         public void mouseDragged(MouseEvent e) {
 846 
 847             if ( startingBounds == null ) {
 848               // (STEVE) Yucky work around for bug ID 4106552
 849                  return;
 850             }
 851 
 852             Point p = SwingUtilities.convertPoint((Component)e.getSource(),
 853                     e.getX(), e.getY(), null);
 854             int deltaX = _x - p.x;
 855             int deltaY = _y - p.y;
 856             Dimension min = frame.getMinimumSize();
 857             Dimension max = frame.getMaximumSize();
 858             int newX, newY, newW, newH;
 859             Insets i = frame.getInsets();
 860 
 861             // Handle a MOVE
 862             if (dragging) {
 863                 if (frame.isMaximum() || ((e.getModifiers() &
 864                         InputEvent.BUTTON1_MASK) !=
 865                         InputEvent.BUTTON1_MASK)) {
 866                     // don't allow moving of frames if maximixed or left mouse
 867                     // button was not used.
 868                     return;
 869                 }
 870                 int pWidth, pHeight;
 871                 Dimension s = frame.getParent().getSize();
 872                 pWidth = s.width;
 873                 pHeight = s.height;
 874 
 875 
 876                 newX = startingBounds.x - deltaX;
 877                 newY = startingBounds.y - deltaY;
 878 
 879                 // Make sure we stay in-bounds
 880                 if(newX + i.left <= -__x)
 881                     newX = -__x - i.left + 1;
 882                 if(newY + i.top <= -__y)
 883                     newY = -__y - i.top + 1;
 884                 if(newX + __x + i.right >= pWidth)
 885                     newX = pWidth - __x - i.right - 1;
 886                 if(newY + __y + i.bottom >= pHeight)
 887                     newY =  pHeight - __y - i.bottom - 1;
 888 
 889                 getDesktopManager().dragFrame(frame, newX, newY);
 890                 return;
 891             }
 892 
 893             if(!frame.isResizable()) {
 894                 return;
 895             }
 896 
 897             newX = frame.getX();
 898             newY = frame.getY();
 899             newW = frame.getWidth();
 900             newH = frame.getHeight();
 901 
 902             parentBounds = frame.getParent().getBounds();
 903 
 904             switch(resizeDir) {
 905             case RESIZE_NONE:
 906                 return;
 907             case NORTH:
 908                 if(startingBounds.height + deltaY < min.height)
 909                     deltaY = -(startingBounds.height - min.height);
 910                 else if(startingBounds.height + deltaY > max.height)
 911                     deltaY = max.height - startingBounds.height;
 912                 if (startingBounds.y - deltaY < 0) {deltaY = startingBounds.y;}
 913 
 914                 newX = startingBounds.x;
 915                 newY = startingBounds.y - deltaY;
 916                 newW = startingBounds.width;
 917                 newH = startingBounds.height + deltaY;
 918                 break;
 919             case NORTH_EAST:
 920                 if(startingBounds.height + deltaY < min.height)
 921                     deltaY = -(startingBounds.height - min.height);
 922                 else if(startingBounds.height + deltaY > max.height)
 923                     deltaY = max.height - startingBounds.height;
 924                 if (startingBounds.y - deltaY < 0) {deltaY = startingBounds.y;}
 925 
 926                 if(startingBounds.width - deltaX < min.width)
 927                     deltaX = startingBounds.width - min.width;
 928                 else if(startingBounds.width - deltaX > max.width)
 929                     deltaX = -(max.width - startingBounds.width);
 930                 if (startingBounds.x + startingBounds.width - deltaX >
 931                     parentBounds.width) {
 932                   deltaX = startingBounds.x + startingBounds.width -
 933                     parentBounds.width;
 934                 }
 935 
 936                 newX = startingBounds.x;
 937                 newY = startingBounds.y - deltaY;
 938                 newW = startingBounds.width - deltaX;
 939                 newH = startingBounds.height + deltaY;
 940                 break;
 941             case EAST:
 942                 if(startingBounds.width - deltaX < min.width)
 943                     deltaX = startingBounds.width - min.width;
 944                 else if(startingBounds.width - deltaX > max.width)
 945                     deltaX = -(max.width - startingBounds.width);
 946                 if (startingBounds.x + startingBounds.width - deltaX >
 947                     parentBounds.width) {
 948                   deltaX = startingBounds.x + startingBounds.width -
 949                     parentBounds.width;
 950                 }
 951 
 952                 newW = startingBounds.width - deltaX;
 953                 newH = startingBounds.height;
 954                 break;
 955             case SOUTH_EAST:
 956                 if(startingBounds.width - deltaX < min.width)
 957                     deltaX = startingBounds.width - min.width;
 958                 else if(startingBounds.width - deltaX > max.width)
 959                     deltaX = -(max.width - startingBounds.width);
 960                 if (startingBounds.x + startingBounds.width - deltaX >
 961                     parentBounds.width) {
 962                   deltaX = startingBounds.x + startingBounds.width -
 963                     parentBounds.width;
 964                 }
 965 
 966                 if(startingBounds.height - deltaY < min.height)
 967                     deltaY = startingBounds.height - min.height;
 968                 else if(startingBounds.height - deltaY > max.height)
 969                     deltaY = -(max.height - startingBounds.height);
 970                 if (startingBounds.y + startingBounds.height - deltaY >
 971                      parentBounds.height) {
 972                   deltaY = startingBounds.y + startingBounds.height -
 973                     parentBounds.height ;
 974                 }
 975 
 976                 newW = startingBounds.width - deltaX;
 977                 newH = startingBounds.height - deltaY;
 978                 break;
 979             case SOUTH:
 980                 if(startingBounds.height - deltaY < min.height)
 981                     deltaY = startingBounds.height - min.height;
 982                 else if(startingBounds.height - deltaY > max.height)
 983                     deltaY = -(max.height - startingBounds.height);
 984                 if (startingBounds.y + startingBounds.height - deltaY >
 985                      parentBounds.height) {
 986                   deltaY = startingBounds.y + startingBounds.height -
 987                     parentBounds.height ;
 988                 }
 989 
 990                 newW = startingBounds.width;
 991                 newH = startingBounds.height - deltaY;
 992                 break;
 993             case SOUTH_WEST:
 994                 if(startingBounds.height - deltaY < min.height)
 995                     deltaY = startingBounds.height - min.height;
 996                 else if(startingBounds.height - deltaY > max.height)
 997                     deltaY = -(max.height - startingBounds.height);
 998                 if (startingBounds.y + startingBounds.height - deltaY >
 999                      parentBounds.height) {
1000                   deltaY = startingBounds.y + startingBounds.height -
1001                     parentBounds.height ;
1002                 }
1003 
1004                 if(startingBounds.width + deltaX < min.width)
1005                     deltaX = -(startingBounds.width - min.width);
1006                 else if(startingBounds.width + deltaX > max.width)
1007                     deltaX = max.width - startingBounds.width;
1008                 if (startingBounds.x - deltaX < 0) {
1009                   deltaX = startingBounds.x;
1010                 }
1011 
1012                 newX = startingBounds.x - deltaX;
1013                 newY = startingBounds.y;
1014                 newW = startingBounds.width + deltaX;
1015                 newH = startingBounds.height - deltaY;
1016                 break;
1017             case WEST:
1018                 if(startingBounds.width + deltaX < min.width)
1019                     deltaX = -(startingBounds.width - min.width);
1020                 else if(startingBounds.width + deltaX > max.width)
1021                     deltaX = max.width - startingBounds.width;
1022                 if (startingBounds.x - deltaX < 0) {
1023                   deltaX = startingBounds.x;
1024                 }
1025 
1026                 newX = startingBounds.x - deltaX;
1027                 newY = startingBounds.y;
1028                 newW = startingBounds.width + deltaX;
1029                 newH = startingBounds.height;
1030                 break;
1031             case NORTH_WEST:
1032                 if(startingBounds.width + deltaX < min.width)
1033                     deltaX = -(startingBounds.width - min.width);
1034                 else if(startingBounds.width + deltaX > max.width)
1035                     deltaX = max.width - startingBounds.width;
1036                 if (startingBounds.x - deltaX < 0) {
1037                   deltaX = startingBounds.x;
1038                 }
1039 
1040                 if(startingBounds.height + deltaY < min.height)
1041                     deltaY = -(startingBounds.height - min.height);
1042                 else if(startingBounds.height + deltaY > max.height)
1043                     deltaY = max.height - startingBounds.height;
1044                 if (startingBounds.y - deltaY < 0) {deltaY = startingBounds.y;}
1045 
1046                 newX = startingBounds.x - deltaX;
1047                 newY = startingBounds.y - deltaY;
1048                 newW = startingBounds.width + deltaX;
1049                 newH = startingBounds.height + deltaY;
1050                 break;
1051             default:
1052                 return;
1053             }
1054             getDesktopManager().resizeFrame(frame, newX, newY, newW, newH);
1055         }
1056 
1057         public void mouseMoved(MouseEvent e)    {
1058 
1059             if(!frame.isResizable())
1060                 return;
1061 
1062             if (e.getSource() == frame || e.getSource() == getNorthPane()) {
1063                 Insets i = frame.getInsets();
1064                 Point ep = new Point(e.getX(), e.getY());
1065                 if (e.getSource() == getNorthPane()) {
1066                     Point np = getNorthPane().getLocation();
1067                     ep.x += np.x;
1068                     ep.y += np.y;
1069                 }
1070                 if(ep.x <= i.left) {
1071                     if(ep.y < resizeCornerSize + i.top)
1072                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
1073                     else if(ep.y > frame.getHeight() - resizeCornerSize - i.bottom)
1074                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
1075                     else
1076                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
1077                 } else if(ep.x >= frame.getWidth() - i.right) {
1078                     if(e.getY() < resizeCornerSize + i.top)
1079                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
1080                     else if(ep.y > frame.getHeight() - resizeCornerSize - i.bottom)
1081                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
1082                     else
1083                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
1084                 } else if(ep.y <= i.top) {
1085                     if(ep.x < resizeCornerSize + i.left)
1086                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
1087                     else if(ep.x > frame.getWidth() - resizeCornerSize - i.right)
1088                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
1089                     else
1090                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
1091                 } else if(ep.y >= frame.getHeight() - i.bottom) {
1092                     if(ep.x < resizeCornerSize + i.left)
1093                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
1094                     else if(ep.x > frame.getWidth() - resizeCornerSize - i.right)
1095                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
1096                     else
1097                         frame.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
1098                 }
1099                 else
1100                     updateFrameCursor();
1101                 return;
1102             }
1103 
1104             updateFrameCursor();
1105         }
1106 
1107         public void mouseEntered(MouseEvent e)    {
1108             updateFrameCursor();
1109         }
1110 
1111         public void mouseExited(MouseEvent e)    {
1112             updateFrameCursor();
1113         }
1114 
1115     }    /// End BorderListener Class
1116 
1117     protected class ComponentHandler implements ComponentListener {
1118       // NOTE: This class exists only for backward compatibility. All
1119       // its functionality has been moved into Handler. If you need to add
1120       // new functionality add it to the Handler, but make sure this
1121       // class calls into the Handler.
1122       /** Invoked when a JInternalFrame's parent's size changes. */
1123       public void componentResized(ComponentEvent e) {
1124           getHandler().componentResized(e);
1125       }
1126 
1127       public void componentMoved(ComponentEvent e) {
1128           getHandler().componentMoved(e);
1129       }
1130       public void componentShown(ComponentEvent e) {
1131           getHandler().componentShown(e);
1132       }
1133       public void componentHidden(ComponentEvent e) {
1134           getHandler().componentHidden(e);
1135       }
1136     }
1137 
1138     protected ComponentListener createComponentListener() {
1139       return getHandler();
1140     }
1141 
1142 
1143     protected class GlassPaneDispatcher implements MouseInputListener {
1144         // NOTE: This class exists only for backward compatibility. All
1145         // its functionality has been moved into Handler. If you need to add
1146         // new functionality add it to the Handler, but make sure this
1147         // class calls into the Handler.
1148         public void mousePressed(MouseEvent e) {
1149             getHandler().mousePressed(e);
1150         }
1151 
1152         public void mouseEntered(MouseEvent e) {
1153             getHandler().mouseEntered(e);
1154         }
1155 
1156         public void mouseMoved(MouseEvent e) {
1157             getHandler().mouseMoved(e);
1158         }
1159 
1160         public void mouseExited(MouseEvent e) {
1161             getHandler().mouseExited(e);
1162         }
1163 
1164         public void mouseClicked(MouseEvent e) {
1165             getHandler().mouseClicked(e);
1166         }
1167 
1168         public void mouseReleased(MouseEvent e) {
1169             getHandler().mouseReleased(e);
1170         }
1171 
1172         public void mouseDragged(MouseEvent e) {
1173             getHandler().mouseDragged(e);
1174         }
1175     }
1176 
1177     protected MouseInputListener createGlassPaneDispatcher() {
1178         return null;
1179     }
1180 
1181 
1182     protected class BasicInternalFrameListener implements InternalFrameListener
1183     {
1184       // NOTE: This class exists only for backward compatibility. All
1185       // its functionality has been moved into Handler. If you need to add
1186       // new functionality add it to the Handler, but make sure this
1187       // class calls into the Handler.
1188       public void internalFrameClosing(InternalFrameEvent e) {
1189           getHandler().internalFrameClosing(e);
1190       }
1191 
1192       public void internalFrameClosed(InternalFrameEvent e) {
1193           getHandler().internalFrameClosed(e);
1194       }
1195 
1196       public void internalFrameOpened(InternalFrameEvent e) {
1197           getHandler().internalFrameOpened(e);
1198       }
1199 
1200       public void internalFrameIconified(InternalFrameEvent e) {
1201           getHandler().internalFrameIconified(e);
1202       }
1203 
1204       public void internalFrameDeiconified(InternalFrameEvent e) {
1205           getHandler().internalFrameDeiconified(e);
1206       }
1207 
1208       public void internalFrameActivated(InternalFrameEvent e) {
1209           getHandler().internalFrameActivated(e);
1210       }
1211 
1212 
1213       public void internalFrameDeactivated(InternalFrameEvent e) {
1214           getHandler().internalFrameDeactivated(e);
1215       }
1216     }
1217 
1218     private class Handler implements ComponentListener, InternalFrameListener,
1219             LayoutManager, MouseInputListener, PropertyChangeListener,
1220             WindowFocusListener, SwingConstants {
1221 
1222         public void windowGainedFocus(WindowEvent e) {
1223         }
1224 
1225         public void windowLostFocus(WindowEvent e) {
1226             // Cancel a resize which may be in progress, when a
1227             // WINDOW_LOST_FOCUS event occurs, which may be
1228             // caused by an Alt-Tab or a modal dialog popup.
1229             cancelResize();
1230         }
1231 
1232         // ComponentHandler methods
1233         /** Invoked when a JInternalFrame's parent's size changes. */
1234         public void componentResized(ComponentEvent e) {
1235             // Get the JInternalFrame's parent container size
1236             Rectangle parentNewBounds = ((Component) e.getSource()).getBounds();
1237             JInternalFrame.JDesktopIcon icon = null;
1238 
1239             if (frame != null) {
1240                 icon = frame.getDesktopIcon();
1241                 // Resize the internal frame if it is maximized and relocate
1242                 // the associated icon as well.
1243                 if (frame.isMaximum()) {
1244                     frame.setBounds(0, 0, parentNewBounds.width,
1245                         parentNewBounds.height);
1246                 }
1247             }
1248 
1249             // Relocate the icon base on the new parent bounds.
1250             if (icon != null) {
1251                 Rectangle iconBounds = icon.getBounds();
1252                 int y = iconBounds.y +
1253                         (parentNewBounds.height - parentBounds.height);
1254                 icon.setBounds(iconBounds.x, y,
1255                         iconBounds.width, iconBounds.height);
1256             }
1257 
1258             // Update the new parent bounds for next resize.
1259             if (!parentBounds.equals(parentNewBounds)) {
1260                 parentBounds = parentNewBounds;
1261             }
1262 
1263             // Validate the component tree for this container.
1264             if (frame != null) frame.validate();
1265         }
1266 
1267         public void componentMoved(ComponentEvent e) {}
1268         public void componentShown(ComponentEvent e) {}
1269         public void componentHidden(ComponentEvent e) {}
1270 
1271 
1272         // InternalFrameListener
1273         public void internalFrameClosed(InternalFrameEvent e) {
1274             frame.removeInternalFrameListener(getHandler());
1275         }
1276 
1277         public void internalFrameActivated(InternalFrameEvent e) {
1278             if (!isKeyBindingRegistered()){
1279                 setKeyBindingRegistered(true);
1280                 setupMenuOpenKey();
1281                 setupMenuCloseKey();
1282             }
1283             if (isKeyBindingRegistered())
1284                 setKeyBindingActive(true);
1285         }
1286 
1287         public void internalFrameDeactivated(InternalFrameEvent e) {
1288             setKeyBindingActive(false);
1289         }
1290 
1291         public void internalFrameClosing(InternalFrameEvent e) { }
1292         public void internalFrameOpened(InternalFrameEvent e) { }
1293         public void internalFrameIconified(InternalFrameEvent e) { }
1294         public void internalFrameDeiconified(InternalFrameEvent e) { }
1295 
1296 
1297         // LayoutManager
1298         public void addLayoutComponent(String name, Component c) {}
1299         public void removeLayoutComponent(Component c) {}
1300         public Dimension preferredLayoutSize(Container c)  {
1301             Dimension result;
1302             Insets i = frame.getInsets();
1303 
1304             result = new Dimension(frame.getRootPane().getPreferredSize());
1305             result.width += i.left + i.right;
1306             result.height += i.top + i.bottom;
1307 
1308             if(getNorthPane() != null) {
1309                 Dimension d = getNorthPane().getPreferredSize();
1310                 result.width = Math.max(d.width, result.width);
1311                 result.height += d.height;
1312             }
1313 
1314             if(getSouthPane() != null) {
1315                 Dimension d = getSouthPane().getPreferredSize();
1316                 result.width = Math.max(d.width, result.width);
1317                 result.height += d.height;
1318             }
1319 
1320             if(getEastPane() != null) {
1321                 Dimension d = getEastPane().getPreferredSize();
1322                 result.width += d.width;
1323                 result.height = Math.max(d.height, result.height);
1324             }
1325 
1326             if(getWestPane() != null) {
1327                 Dimension d = getWestPane().getPreferredSize();
1328                 result.width += d.width;
1329                 result.height = Math.max(d.height, result.height);
1330             }
1331             return result;
1332         }
1333 
1334         public Dimension minimumLayoutSize(Container c) {
1335             // The minimum size of the internal frame only takes into
1336             // account the title pane since you are allowed to resize
1337             // the frames to the point where just the title pane is visible.
1338             Dimension result = new Dimension();
1339             if (getNorthPane() != null &&
1340                 getNorthPane() instanceof BasicInternalFrameTitlePane) {
1341                   result = new Dimension(getNorthPane().getMinimumSize());
1342             }
1343             Insets i = frame.getInsets();
1344             result.width += i.left + i.right;
1345             result.height += i.top + i.bottom;
1346 
1347             return result;
1348         }
1349 
1350         public void layoutContainer(Container c) {
1351             Insets i = frame.getInsets();
1352             int cx, cy, cw, ch;
1353 
1354             cx = i.left;
1355             cy = i.top;
1356             cw = frame.getWidth() - i.left - i.right;
1357             ch = frame.getHeight() - i.top - i.bottom;
1358 
1359             if(getNorthPane() != null) {
1360                 Dimension size = getNorthPane().getPreferredSize();
1361                 if (DefaultLookup.getBoolean(frame, BasicInternalFrameUI.this,
1362                           "InternalFrame.layoutTitlePaneAtOrigin", false)) {
1363                     cy = 0;
1364                     ch += i.top;
1365                     getNorthPane().setBounds(0, 0, frame.getWidth(),
1366                                              size.height);
1367                 }
1368                 else {
1369                     getNorthPane().setBounds(cx, cy, cw, size.height);
1370                 }
1371                 cy += size.height;
1372                 ch -= size.height;
1373             }
1374 
1375             if(getSouthPane() != null) {
1376                 Dimension size = getSouthPane().getPreferredSize();
1377                 getSouthPane().setBounds(cx, frame.getHeight()
1378                                                     - i.bottom - size.height,
1379                                                     cw, size.height);
1380                 ch -= size.height;
1381             }
1382 
1383             if(getWestPane() != null) {
1384                 Dimension size = getWestPane().getPreferredSize();
1385                 getWestPane().setBounds(cx, cy, size.width, ch);
1386                 cw -= size.width;
1387                 cx += size.width;
1388             }
1389 
1390             if(getEastPane() != null) {
1391                 Dimension size = getEastPane().getPreferredSize();
1392                 getEastPane().setBounds(cw - size.width, cy, size.width, ch);
1393                 cw -= size.width;
1394             }
1395 
1396             if(frame.getRootPane() != null) {
1397                 frame.getRootPane().setBounds(cx, cy, cw, ch);
1398             }
1399         }
1400 
1401 
1402         // MouseInputListener
1403         public void mousePressed(MouseEvent e) { }
1404 
1405         public void mouseEntered(MouseEvent e) { }
1406 
1407         public void mouseMoved(MouseEvent e) { }
1408 
1409         public void mouseExited(MouseEvent e) { }
1410 
1411         public void mouseClicked(MouseEvent e) { }
1412 
1413         public void mouseReleased(MouseEvent e) { }
1414 
1415         public void mouseDragged(MouseEvent e) { }
1416 
1417         // PropertyChangeListener
1418         public void propertyChange(PropertyChangeEvent evt) {
1419             String prop = evt.getPropertyName();
1420             JInternalFrame f = (JInternalFrame)evt.getSource();
1421             Object newValue = evt.getNewValue();
1422             Object oldValue = evt.getOldValue();
1423 
1424             if (JInternalFrame.IS_CLOSED_PROPERTY == prop) {
1425                 if (newValue == Boolean.TRUE) {
1426                     // Cancel a resize in progress if the internal frame
1427                     // gets a setClosed(true) or dispose().
1428                     cancelResize();
1429                     if ((frame.getParent() != null) && componentListenerAdded) {
1430                         frame.getParent().removeComponentListener(componentListener);
1431                     }
1432                     closeFrame(f);
1433                 }
1434             } else if (JInternalFrame.IS_MAXIMUM_PROPERTY == prop) {
1435                 if(newValue == Boolean.TRUE) {
1436                     maximizeFrame(f);
1437                 } else {
1438                     minimizeFrame(f);
1439                 }
1440             } else if(JInternalFrame.IS_ICON_PROPERTY == prop) {
1441                 if (newValue == Boolean.TRUE) {
1442                     iconifyFrame(f);
1443                 } else {
1444                     deiconifyFrame(f);
1445                 }
1446             } else if (JInternalFrame.IS_SELECTED_PROPERTY == prop) {
1447                 if (newValue == Boolean.TRUE && oldValue == Boolean.FALSE) {
1448                     activateFrame(f);
1449                 } else if (newValue == Boolean.FALSE &&
1450                            oldValue == Boolean.TRUE) {
1451                     deactivateFrame(f);
1452                 }
1453             } else if (prop == "ancestor") {
1454                 if (newValue == null) {
1455                     // Cancel a resize in progress, if the internal frame
1456                     // gets a remove(), removeNotify() or setIcon(true).
1457                     cancelResize();
1458                 }
1459                 if (frame.getParent() != null) {
1460                     parentBounds = f.getParent().getBounds();
1461                 } else {
1462                     parentBounds = null;
1463                 }
1464                 if ((frame.getParent() != null) && !componentListenerAdded) {
1465                     f.getParent().addComponentListener(componentListener);
1466                     componentListenerAdded = true;
1467                 }
1468             } else if (JInternalFrame.TITLE_PROPERTY == prop ||
1469                     prop == "closable" || prop == "iconable" ||
1470                     prop == "maximizable") {
1471                 Dimension dim = frame.getMinimumSize();
1472                 Dimension frame_dim = frame.getSize();
1473                 if (dim.width > frame_dim.width) {
1474                     frame.setSize(dim.width, frame_dim.height);
1475                 }
1476             }
1477         }
1478     }
1479 }