1 /*
   2  * Copyright (c) 1997, 2015, 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 javax.swing.*;
  29 import javax.swing.plaf.*;
  30 
  31 import java.beans.*;
  32 
  33 import java.awt.event.*;
  34 import java.awt.Dimension;
  35 import java.awt.Insets;
  36 import java.awt.Graphics;
  37 import java.awt.KeyboardFocusManager;
  38 import java.awt.*;
  39 
  40 import sun.swing.DefaultLookup;
  41 import sun.swing.UIAction;
  42 
  43 /**
  44  * Basic L&F for a desktop.
  45  *
  46  * @author Steve Wilson
  47  */
  48 public class BasicDesktopPaneUI extends DesktopPaneUI {
  49     // Old actions forward to an instance of this.
  50     private static final Actions SHARED_ACTION = new Actions();
  51     private Handler handler;
  52     private PropertyChangeListener pcl;
  53 
  54     /**
  55      * The instance of {@code JDesktopPane}.
  56      */
  57     protected JDesktopPane desktop;
  58 
  59     /**
  60      * The instance of {@code DesktopManager}.
  61      */
  62     protected DesktopManager desktopManager;
  63 
  64     /**
  65      * As of Java 2 platform v1.3 this previously undocumented field is no
  66      * longer used.
  67      * Key bindings are now defined by the LookAndFeel, please refer to
  68      * the key bindings specification for further details.
  69      *
  70      * @deprecated As of 1.3.
  71      */
  72     @Deprecated
  73     protected KeyStroke minimizeKey;
  74     /**
  75      * As of Java 2 platform v1.3 this previously undocumented field is no
  76      * longer used.
  77      * Key bindings are now defined by the LookAndFeel, please refer to
  78      * the key bindings specification for further details.
  79      *
  80      * @deprecated As of 1.3.
  81      */
  82     @Deprecated
  83     protected KeyStroke maximizeKey;
  84     /**
  85      * As of Java 2 platform v1.3 this previously undocumented field is no
  86      * longer used.
  87      * Key bindings are now defined by the LookAndFeel, please refer to
  88      * the key bindings specification for further details.
  89      *
  90      * @deprecated As of 1.3.
  91      */
  92     @Deprecated
  93     protected KeyStroke closeKey;
  94     /**
  95      * As of Java 2 platform v1.3 this previously undocumented field is no
  96      * longer used.
  97      * Key bindings are now defined by the LookAndFeel, please refer to
  98      * the key bindings specification for further details.
  99      *
 100      * @deprecated As of 1.3.
 101      */
 102     @Deprecated
 103     protected KeyStroke navigateKey;
 104     /**
 105      * As of Java 2 platform v1.3 this previously undocumented field is no
 106      * longer used.
 107      * Key bindings are now defined by the LookAndFeel, please refer to
 108      * the key bindings specification for further details.
 109      *
 110      * @deprecated As of 1.3.
 111      */
 112     @Deprecated
 113     protected KeyStroke navigateKey2;
 114 
 115     /**
 116      * Constructs a new instance of {@code BasicDesktopPaneUI}.
 117      *
 118      * @param c a component
 119      * @return a new instance of {@code BasicDesktopPaneUI}
 120      */
 121     public static ComponentUI createUI(JComponent c) {
 122         return new BasicDesktopPaneUI();
 123     }
 124 
 125     /**
 126      * Constructs a new instance of {@code BasicDesktopPaneUI}.
 127      */
 128     public BasicDesktopPaneUI() {
 129     }
 130 
 131     public void installUI(JComponent c)   {
 132         desktop = (JDesktopPane)c;
 133         installDefaults();
 134         installDesktopManager();
 135         installListeners();
 136         installKeyboardActions();
 137     }
 138 
 139     public void uninstallUI(JComponent c) {
 140         uninstallKeyboardActions();
 141         uninstallListeners();
 142         uninstallDesktopManager();
 143         uninstallDefaults();
 144         desktop = null;
 145         handler = null;
 146     }
 147 
 148     /**
 149      * Installs default properties.
 150      */
 151     protected void installDefaults() {
 152         if (desktop.getBackground() == null ||
 153             desktop.getBackground() instanceof UIResource) {
 154             desktop.setBackground(UIManager.getColor("Desktop.background"));
 155         }
 156         LookAndFeel.installProperty(desktop, "opaque", Boolean.TRUE);
 157     }
 158 
 159     /**
 160      * Uninstalls default properties.
 161      */
 162     protected void uninstallDefaults() { }
 163 
 164     /**
 165      * Installs the {@code PropertyChangeListener} returned from
 166      * {@code createPropertyChangeListener} on the
 167      * {@code JDesktopPane}.
 168      *
 169      * @since 1.5
 170      * @see #createPropertyChangeListener
 171      */
 172     protected void installListeners() {
 173         pcl = createPropertyChangeListener();
 174         desktop.addPropertyChangeListener(pcl);
 175     }
 176 
 177     /**
 178      * Uninstalls the {@code PropertyChangeListener} returned from
 179      * {@code createPropertyChangeListener} from the
 180      * {@code JDesktopPane}.
 181      *
 182      * @since 1.5
 183      * @see #createPropertyChangeListener
 184      */
 185     protected void uninstallListeners() {
 186         desktop.removePropertyChangeListener(pcl);
 187         pcl = null;
 188     }
 189 
 190     /**
 191      * Installs desktop manager.
 192      */
 193     protected void installDesktopManager() {
 194         desktopManager = desktop.getDesktopManager();
 195         if(desktopManager == null) {
 196             desktopManager = new BasicDesktopManager();
 197             desktop.setDesktopManager(desktopManager);
 198         }
 199     }
 200 
 201     /**
 202      * Uninstalls desktop manager.
 203      */
 204     protected void uninstallDesktopManager() {
 205         if(desktop.getDesktopManager() instanceof UIResource) {
 206             desktop.setDesktopManager(null);
 207         }
 208         desktopManager = null;
 209     }
 210 
 211     /**
 212      * Installs keyboard actions.
 213      */
 214     protected void installKeyboardActions(){
 215         InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
 216         if (inputMap != null) {
 217             SwingUtilities.replaceUIInputMap(desktop,
 218                         JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
 219         }
 220         inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 221         if (inputMap != null) {
 222             SwingUtilities.replaceUIInputMap(desktop,
 223                         JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
 224                         inputMap);
 225         }
 226 
 227         LazyActionMap.installLazyActionMap(desktop, BasicDesktopPaneUI.class,
 228                 "DesktopPane.actionMap");
 229         registerKeyboardActions();
 230     }
 231 
 232     /**
 233      * Registers keyboard actions.
 234      */
 235     protected void registerKeyboardActions(){
 236     }
 237 
 238     /**
 239      * Unregisters keyboard actions.
 240      */
 241     protected void unregisterKeyboardActions(){
 242     }
 243 
 244     InputMap getInputMap(int condition) {
 245         if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
 246             return createInputMap(condition);
 247         }
 248         else if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
 249             return (InputMap)DefaultLookup.get(desktop, this,
 250                     "Desktop.ancestorInputMap");
 251         }
 252         return null;
 253     }
 254 
 255     InputMap createInputMap(int condition) {
 256         if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
 257             Object[] bindings = (Object[])DefaultLookup.get(desktop,
 258                     this, "Desktop.windowBindings");
 259 
 260             if (bindings != null) {
 261                 return LookAndFeel.makeComponentInputMap(desktop, bindings);
 262             }
 263         }
 264         return null;
 265     }
 266 
 267     static void loadActionMap(LazyActionMap map) {
 268         map.put(new Actions(Actions.RESTORE));
 269         map.put(new Actions(Actions.CLOSE));
 270         map.put(new Actions(Actions.MOVE));
 271         map.put(new Actions(Actions.RESIZE));
 272         map.put(new Actions(Actions.LEFT));
 273         map.put(new Actions(Actions.SHRINK_LEFT));
 274         map.put(new Actions(Actions.RIGHT));
 275         map.put(new Actions(Actions.SHRINK_RIGHT));
 276         map.put(new Actions(Actions.UP));
 277         map.put(new Actions(Actions.SHRINK_UP));
 278         map.put(new Actions(Actions.DOWN));
 279         map.put(new Actions(Actions.SHRINK_DOWN));
 280         map.put(new Actions(Actions.ESCAPE));
 281         map.put(new Actions(Actions.MINIMIZE));
 282         map.put(new Actions(Actions.MAXIMIZE));
 283         map.put(new Actions(Actions.NEXT_FRAME));
 284         map.put(new Actions(Actions.PREVIOUS_FRAME));
 285         map.put(new Actions(Actions.NAVIGATE_NEXT));
 286         map.put(new Actions(Actions.NAVIGATE_PREVIOUS));
 287     }
 288 
 289     /**
 290      * Unregisters keyboard actions.
 291      */
 292     protected void uninstallKeyboardActions(){
 293       unregisterKeyboardActions();
 294       SwingUtilities.replaceUIInputMap(desktop, JComponent.
 295                                      WHEN_IN_FOCUSED_WINDOW, null);
 296       SwingUtilities.replaceUIInputMap(desktop, JComponent.
 297                                      WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
 298       SwingUtilities.replaceUIActionMap(desktop, null);
 299     }
 300 
 301     public void paint(Graphics g, JComponent c) {}
 302 
 303     @Override
 304     public Dimension getPreferredSize(JComponent c) {
 305         return null;
 306     }
 307 
 308     @Override
 309     public Dimension getMinimumSize(JComponent c) {
 310         return new Dimension(0, 0);
 311     }
 312 
 313     @Override
 314     public Dimension getMaximumSize(JComponent c) {
 315         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
 316     }
 317 
 318     /**
 319      * Returns the {@code PropertyChangeListener} to install on
 320      * the {@code JDesktopPane}.
 321      *
 322      * @since 1.5
 323      * @return The PropertyChangeListener that will be added to track
 324      * changes in the desktop pane.
 325      */
 326     protected PropertyChangeListener createPropertyChangeListener() {
 327         return getHandler();
 328     }
 329 
 330     private Handler getHandler() {
 331         if (handler == null) {
 332             handler = new Handler();
 333         }
 334         return handler;
 335     }
 336 
 337     private class Handler implements PropertyChangeListener {
 338         public void propertyChange(PropertyChangeEvent evt) {
 339             String propertyName = evt.getPropertyName();
 340             if ("desktopManager" == propertyName) {
 341                 installDesktopManager();
 342             }
 343         }
 344     }
 345 
 346     /**
 347      * The default DesktopManager installed by the UI.
 348      */
 349     @SuppressWarnings("serial") // JDK-implementation class
 350     private class BasicDesktopManager extends DefaultDesktopManager
 351             implements UIResource {
 352     }
 353 
 354     private static class Actions extends UIAction {
 355         private static String CLOSE = "close";
 356         private static String ESCAPE = "escape";
 357         private static String MAXIMIZE = "maximize";
 358         private static String MINIMIZE = "minimize";
 359         private static String MOVE = "move";
 360         private static String RESIZE = "resize";
 361         private static String RESTORE = "restore";
 362         private static String LEFT = "left";
 363         private static String RIGHT = "right";
 364         private static String UP = "up";
 365         private static String DOWN = "down";
 366         private static String SHRINK_LEFT = "shrinkLeft";
 367         private static String SHRINK_RIGHT = "shrinkRight";
 368         private static String SHRINK_UP = "shrinkUp";
 369         private static String SHRINK_DOWN = "shrinkDown";
 370         private static String NEXT_FRAME = "selectNextFrame";
 371         private static String PREVIOUS_FRAME = "selectPreviousFrame";
 372         private static String NAVIGATE_NEXT = "navigateNext";
 373         private static String NAVIGATE_PREVIOUS = "navigatePrevious";
 374         private final int MOVE_RESIZE_INCREMENT = 10;
 375         private static boolean moving = false;
 376         private static boolean resizing = false;
 377         private static JInternalFrame sourceFrame = null;
 378         private static Component focusOwner = null;
 379 
 380         Actions() {
 381             super(null);
 382         }
 383 
 384         Actions(String name) {
 385             super(name);
 386         }
 387 
 388         public void actionPerformed(ActionEvent e) {
 389             JDesktopPane dp = (JDesktopPane)e.getSource();
 390             String key = getName();
 391 
 392             if (CLOSE == key || MAXIMIZE == key || MINIMIZE == key ||
 393                     RESTORE == key) {
 394                 setState(dp, key);
 395             }
 396             else if (ESCAPE == key) {
 397                 if (sourceFrame == dp.getSelectedFrame() &&
 398                         focusOwner != null) {
 399                     focusOwner.requestFocus();
 400                 }
 401                 moving = false;
 402                 resizing = false;
 403                 sourceFrame = null;
 404                 focusOwner = null;
 405             }
 406             else if (MOVE == key || RESIZE == key) {
 407                 sourceFrame = dp.getSelectedFrame();
 408                 if (sourceFrame == null) {
 409                     return;
 410                 }
 411                 moving = (key == MOVE) ? true : false;
 412                 resizing = (key == RESIZE) ? true : false;
 413 
 414                 focusOwner = KeyboardFocusManager.
 415                     getCurrentKeyboardFocusManager().getFocusOwner();
 416                 if (!SwingUtilities.isDescendingFrom(focusOwner, sourceFrame)) {
 417                     focusOwner = null;
 418                 }
 419                 sourceFrame.requestFocus();
 420             }
 421             else if (LEFT == key ||
 422                      RIGHT == key ||
 423                      UP == key ||
 424                      DOWN == key ||
 425                      SHRINK_RIGHT == key ||
 426                      SHRINK_LEFT == key ||
 427                      SHRINK_UP == key ||
 428                      SHRINK_DOWN == key) {
 429                 JInternalFrame c = dp.getSelectedFrame();
 430                 if (sourceFrame == null || c != sourceFrame ||
 431                         KeyboardFocusManager.
 432                             getCurrentKeyboardFocusManager().getFocusOwner() !=
 433                                 sourceFrame) {
 434                     return;
 435                 }
 436                 Insets minOnScreenInsets =
 437                     UIManager.getInsets("Desktop.minOnScreenInsets");
 438                 Dimension size = c.getSize();
 439                 Dimension minSize = c.getMinimumSize();
 440                 int dpWidth = dp.getWidth();
 441                 int dpHeight = dp.getHeight();
 442                 int delta;
 443                 Point loc = c.getLocation();
 444                 if (LEFT == key) {
 445                     if (moving) {
 446                         c.setLocation(
 447                                 loc.x + size.width - MOVE_RESIZE_INCREMENT <
 448                                     minOnScreenInsets.right ?
 449                                         -size.width + minOnScreenInsets.right :
 450                                         loc.x - MOVE_RESIZE_INCREMENT,
 451                                 loc.y);
 452                     } else if (resizing) {
 453                         c.setLocation(loc.x - MOVE_RESIZE_INCREMENT, loc.y);
 454                         c.setSize(size.width + MOVE_RESIZE_INCREMENT,
 455                                 size.height);
 456                     }
 457                 } else if (RIGHT == key) {
 458                     if (moving) {
 459                         c.setLocation(
 460                                 loc.x + MOVE_RESIZE_INCREMENT >
 461                                     dpWidth - minOnScreenInsets.left ?
 462                                         dpWidth - minOnScreenInsets.left :
 463                                         loc.x + MOVE_RESIZE_INCREMENT,
 464                                 loc.y);
 465                     } else if (resizing) {
 466                         c.setSize(size.width + MOVE_RESIZE_INCREMENT,
 467                                 size.height);
 468                     }
 469                 } else if (UP == key) {
 470                     if (moving) {
 471                         c.setLocation(loc.x,
 472                                 loc.y + size.height - MOVE_RESIZE_INCREMENT <
 473                                     minOnScreenInsets.bottom ?
 474                                         -size.height +
 475                                             minOnScreenInsets.bottom :
 476                                         loc.y - MOVE_RESIZE_INCREMENT);
 477                     } else if (resizing) {
 478                         c.setLocation(loc.x, loc.y - MOVE_RESIZE_INCREMENT);
 479                         c.setSize(size.width,
 480                                 size.height + MOVE_RESIZE_INCREMENT);
 481                     }
 482                 } else if (DOWN == key) {
 483                     if (moving) {
 484                         c.setLocation(loc.x,
 485                                 loc.y + MOVE_RESIZE_INCREMENT >
 486                                     dpHeight - minOnScreenInsets.top ?
 487                                         dpHeight - minOnScreenInsets.top :
 488                                         loc.y + MOVE_RESIZE_INCREMENT);
 489                     } else if (resizing) {
 490                         c.setSize(size.width,
 491                                 size.height + MOVE_RESIZE_INCREMENT);
 492                     }
 493                 } else if (SHRINK_LEFT == key && resizing) {
 494                     // Make sure we don't resize less than minimum size.
 495                     if (minSize.width < (size.width - MOVE_RESIZE_INCREMENT)) {
 496                         delta = MOVE_RESIZE_INCREMENT;
 497                     } else {
 498                         delta = size.width - minSize.width;
 499                     }
 500 
 501                     // Ensure that we keep the internal frame on the desktop.
 502                     if (loc.x + size.width - delta < minOnScreenInsets.left) {
 503                         delta = loc.x + size.width - minOnScreenInsets.left;
 504                     }
 505                     c.setSize(size.width - delta, size.height);
 506                 } else if (SHRINK_RIGHT == key && resizing) {
 507                     // Make sure we don't resize less than minimum size.
 508                     if (minSize.width < (size.width - MOVE_RESIZE_INCREMENT)) {
 509                         delta = MOVE_RESIZE_INCREMENT;
 510                     } else {
 511                         delta = size.width - minSize.width;
 512                     }
 513 
 514                     // Ensure that we keep the internal frame on the desktop.
 515                     if (loc.x + delta > dpWidth - minOnScreenInsets.right) {
 516                         delta = (dpWidth - minOnScreenInsets.right) - loc.x;
 517                     }
 518 
 519                     c.setLocation(loc.x + delta, loc.y);
 520                     c.setSize(size.width - delta, size.height);
 521                 } else if (SHRINK_UP == key && resizing) {
 522                     // Make sure we don't resize less than minimum size.
 523                     if (minSize.height <
 524                             (size.height - MOVE_RESIZE_INCREMENT)) {
 525                         delta = MOVE_RESIZE_INCREMENT;
 526                     } else {
 527                         delta = size.height - minSize.height;
 528                     }
 529 
 530                     // Ensure that we keep the internal frame on the desktop.
 531                     if (loc.y + size.height - delta <
 532                             minOnScreenInsets.bottom) {
 533                         delta = loc.y + size.height - minOnScreenInsets.bottom;
 534                     }
 535 
 536                     c.setSize(size.width, size.height - delta);
 537                 } else if (SHRINK_DOWN == key  && resizing) {
 538                     // Make sure we don't resize less than minimum size.
 539                     if (minSize.height <
 540                             (size.height - MOVE_RESIZE_INCREMENT)) {
 541                         delta = MOVE_RESIZE_INCREMENT;
 542                     } else {
 543                         delta = size.height - minSize.height;
 544                     }
 545 
 546                     // Ensure that we keep the internal frame on the desktop.
 547                     if (loc.y + delta > dpHeight - minOnScreenInsets.top) {
 548                         delta = (dpHeight - minOnScreenInsets.top) - loc.y;
 549                     }
 550 
 551                     c.setLocation(loc.x, loc.y + delta);
 552                     c.setSize(size.width, size.height - delta);
 553                 }
 554             }
 555             else if (NEXT_FRAME == key || PREVIOUS_FRAME == key) {
 556                 dp.selectFrame((key == NEXT_FRAME) ? true : false);
 557             }
 558             else if (NAVIGATE_NEXT == key ||
 559                      NAVIGATE_PREVIOUS == key) {
 560                 boolean moveForward = true;
 561                 if (NAVIGATE_PREVIOUS == key) {
 562                     moveForward = false;
 563                 }
 564                 Container cycleRoot = dp.getFocusCycleRootAncestor();
 565 
 566                 if (cycleRoot != null) {
 567                     FocusTraversalPolicy policy =
 568                         cycleRoot.getFocusTraversalPolicy();
 569                     if (policy != null && policy instanceof
 570                             SortingFocusTraversalPolicy) {
 571                         SortingFocusTraversalPolicy sPolicy =
 572                             (SortingFocusTraversalPolicy)policy;
 573                         boolean idc = sPolicy.getImplicitDownCycleTraversal();
 574                         try {
 575                             sPolicy.setImplicitDownCycleTraversal(false);
 576                             if (moveForward) {
 577                                 KeyboardFocusManager.
 578                                     getCurrentKeyboardFocusManager().
 579                                         focusNextComponent(dp);
 580                             } else {
 581                                 KeyboardFocusManager.
 582                                     getCurrentKeyboardFocusManager().
 583                                     focusPreviousComponent(dp);
 584                             }
 585                         } finally {
 586                             sPolicy.setImplicitDownCycleTraversal(idc);
 587                         }
 588                     }
 589                 }
 590             }
 591         }
 592 
 593         private void setState(JDesktopPane dp, String state) {
 594             if (state == CLOSE) {
 595                 JInternalFrame f = dp.getSelectedFrame();
 596                 if (f == null) {
 597                     return;
 598                 }
 599                 f.doDefaultCloseAction();
 600             } else if (state == MAXIMIZE) {
 601                 // maximize the selected frame
 602                 JInternalFrame f = dp.getSelectedFrame();
 603                 if (f == null) {
 604                     return;
 605                 }
 606                 if (!f.isMaximum()) {
 607                     if (f.isIcon()) {
 608                         try {
 609                             f.setIcon(false);
 610                             f.setMaximum(true);
 611                         } catch (PropertyVetoException pve) {}
 612                     } else {
 613                         try {
 614                             f.setMaximum(true);
 615                         } catch (PropertyVetoException pve) {
 616                         }
 617                     }
 618                 }
 619             } else if (state == MINIMIZE) {
 620                 // minimize the selected frame
 621                 JInternalFrame f = dp.getSelectedFrame();
 622                 if (f == null) {
 623                     return;
 624                 }
 625                 if (!f.isIcon()) {
 626                     try {
 627                         f.setIcon(true);
 628                     } catch (PropertyVetoException pve) {
 629                     }
 630                 }
 631             } else if (state == RESTORE) {
 632                 // restore the selected minimized or maximized frame
 633                 JInternalFrame f = dp.getSelectedFrame();
 634                 if (f == null) {
 635                     return;
 636                 }
 637                 try {
 638                     if (f.isIcon()) {
 639                         f.setIcon(false);
 640                     } else if (f.isMaximum()) {
 641                         f.setMaximum(false);
 642                     }
 643                     f.setSelected(true);
 644                 } catch (PropertyVetoException pve) {
 645                 }
 646             }
 647         }
 648 
 649         public boolean isEnabled(Object sender) {
 650             if (sender instanceof JDesktopPane) {
 651                 JDesktopPane dp = (JDesktopPane)sender;
 652                 String action = getName();
 653                 if (action == Actions.NEXT_FRAME ||
 654                     action == Actions.PREVIOUS_FRAME) {
 655                     return true;
 656                 }
 657                 JInternalFrame iFrame = dp.getSelectedFrame();
 658                 if (iFrame == null) {
 659                     return false;
 660                 } else if (action == Actions.CLOSE) {
 661                     return iFrame.isClosable();
 662                 } else if (action == Actions.MINIMIZE) {
 663                     return iFrame.isIconifiable();
 664                 } else if (action == Actions.MAXIMIZE) {
 665                     return iFrame.isMaximizable();
 666                 }
 667                 return true;
 668             }
 669             return false;
 670         }
 671     }
 672 
 673 
 674     /**
 675      * Handles restoring a minimized or maximized internal frame.
 676      * @since 1.3
 677      */
 678     @SuppressWarnings("serial") // Superclass is not serializable across versions
 679     protected class OpenAction extends AbstractAction {
 680         public void actionPerformed(ActionEvent evt) {
 681             JDesktopPane dp = (JDesktopPane)evt.getSource();
 682             SHARED_ACTION.setState(dp, Actions.RESTORE);
 683         }
 684 
 685         public boolean isEnabled() {
 686             return true;
 687         }
 688     }
 689 
 690     /**
 691      * Handles closing an internal frame.
 692      */
 693     @SuppressWarnings("serial") // Superclass is not serializable across versions
 694     protected class CloseAction extends AbstractAction {
 695         public void actionPerformed(ActionEvent evt) {
 696             JDesktopPane dp = (JDesktopPane)evt.getSource();
 697             SHARED_ACTION.setState(dp, Actions.CLOSE);
 698         }
 699 
 700         public boolean isEnabled() {
 701             JInternalFrame iFrame = desktop.getSelectedFrame();
 702             if (iFrame != null) {
 703                 return iFrame.isClosable();
 704             }
 705             return false;
 706         }
 707     }
 708 
 709     /**
 710      * Handles minimizing an internal frame.
 711      */
 712     @SuppressWarnings("serial") // Superclass is not serializable across versions
 713     protected class MinimizeAction extends AbstractAction {
 714         public void actionPerformed(ActionEvent evt) {
 715             JDesktopPane dp = (JDesktopPane)evt.getSource();
 716             SHARED_ACTION.setState(dp, Actions.MINIMIZE);
 717         }
 718 
 719         public boolean isEnabled() {
 720             JInternalFrame iFrame = desktop.getSelectedFrame();
 721             if (iFrame != null) {
 722                 return iFrame.isIconifiable();
 723             }
 724             return false;
 725         }
 726     }
 727 
 728     /**
 729      * Handles maximizing an internal frame.
 730      */
 731     @SuppressWarnings("serial") // Superclass is not serializable across versions
 732     protected class MaximizeAction extends AbstractAction {
 733         public void actionPerformed(ActionEvent evt) {
 734             JDesktopPane dp = (JDesktopPane)evt.getSource();
 735             SHARED_ACTION.setState(dp, Actions.MAXIMIZE);
 736         }
 737 
 738         public boolean isEnabled() {
 739             JInternalFrame iFrame = desktop.getSelectedFrame();
 740             if (iFrame != null) {
 741                 return iFrame.isMaximizable();
 742             }
 743             return false;
 744         }
 745     }
 746 
 747     /**
 748      * Handles navigating to the next internal frame.
 749      */
 750     @SuppressWarnings("serial") // Superclass is not serializable across versions
 751     protected class NavigateAction extends AbstractAction {
 752         public void actionPerformed(ActionEvent evt) {
 753             JDesktopPane dp = (JDesktopPane)evt.getSource();
 754             dp.selectFrame(true);
 755         }
 756 
 757         public boolean isEnabled() {
 758             return true;
 759         }
 760     }
 761 }
--- EOF ---