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