Source for javax.swing.plaf.basic.BasicPopupMenuUI

   1: /* BasicPopupMenuUI.java
   2:    Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package javax.swing.plaf.basic;
  39: 
  40: import java.awt.AWTEvent;
  41: import java.awt.Component;
  42: import java.awt.Container;
  43: import java.awt.Cursor;
  44: import java.awt.Dimension;
  45: import java.awt.Point;
  46: import java.awt.event.ComponentEvent;
  47: import java.awt.event.ComponentListener;
  48: import java.awt.event.MouseEvent;
  49: 
  50: import javax.swing.BoxLayout;
  51: import javax.swing.JComponent;
  52: import javax.swing.JLayeredPane;
  53: import javax.swing.JMenu;
  54: import javax.swing.JMenuItem;
  55: import javax.swing.JPopupMenu;
  56: import javax.swing.LookAndFeel;
  57: import javax.swing.MenuElement;
  58: import javax.swing.MenuSelectionManager;
  59: import javax.swing.RootPaneContainer;
  60: import javax.swing.SwingUtilities;
  61: import javax.swing.event.MouseInputListener;
  62: import javax.swing.event.PopupMenuEvent;
  63: import javax.swing.event.PopupMenuListener;
  64: import javax.swing.plaf.ComponentUI;
  65: import javax.swing.plaf.PopupMenuUI;
  66: 
  67: 
  68: /**
  69:  * UI Delegate for JPopupMenu
  70:  */
  71: public class BasicPopupMenuUI extends PopupMenuUI
  72: {
  73:   /* popupMenu for which this UI delegate is for*/
  74:   protected JPopupMenu popupMenu;
  75: 
  76:   /* MouseInputListener listens to mouse events. Package private for inner classes. */
  77:   static transient MouseInputListener mouseInputListener;
  78: 
  79:   /* PopupMenuListener listens to popup menu events fired by JPopupMenu*/
  80:   private transient PopupMenuListener popupMenuListener;
  81: 
  82:   /* ComponentListener listening to popupMenu's invoker.
  83:    * This is package-private to avoid an accessor method.  */
  84:   TopWindowListener topWindowListener;
  85: 
  86:   /**
  87:    * Creates a new BasicPopupMenuUI object.
  88:    */
  89:   public BasicPopupMenuUI()
  90:   {
  91:     popupMenuListener = new PopupMenuHandler();
  92:     topWindowListener = new TopWindowListener();
  93:   }
  94: 
  95:   /**
  96:    * Factory method to create a BasicPopupMenuUI for the given {@link
  97:    * JComponent}, which should be a {@link JMenuItem}.
  98:    *
  99:    * @param x The {@link JComponent} a UI is being created for.
 100:    *
 101:    * @return A BasicPopupMenuUI for the {@link JComponent}.
 102:    */
 103:   public static ComponentUI createUI(JComponent x)
 104:   {
 105:     return new BasicPopupMenuUI();
 106:   }
 107: 
 108:   /**
 109:    * Installs and initializes all fields for this UI delegate. Any properties
 110:    * of the UI that need to be initialized and/or set to defaults will be
 111:    * done now. It will also install any listeners necessary.
 112:    *
 113:    * @param c The {@link JComponent} that is having this UI installed.
 114:    */
 115:   public void installUI(JComponent c)
 116:   {
 117:     super.installUI(c);
 118:     popupMenu = (JPopupMenu) c;
 119:     popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS));
 120:     popupMenu.setBorderPainted(true);
 121:     JPopupMenu.setDefaultLightWeightPopupEnabled(true);
 122: 
 123:     installDefaults();
 124:     installListeners();
 125:   }
 126: 
 127:   /**
 128:    * This method installs the defaults that are defined in  the Basic look
 129:    * and feel for this {@link JPopupMenu}.
 130:    */
 131:   public void installDefaults()
 132:   {
 133:     LookAndFeel.installColorsAndFont(popupMenu, "PopupMenu.background",
 134:                                      "PopupMenu.foreground", "PopupMenu.font");
 135:     LookAndFeel.installBorder(popupMenu, "PopupMenu.border");
 136:     popupMenu.setOpaque(true);
 137:   }
 138: 
 139:   /**
 140:    * This method installs the listeners for the {@link JMenuItem}.
 141:    */
 142:   protected void installListeners()
 143:   {
 144:     popupMenu.addPopupMenuListener(popupMenuListener);
 145:   }
 146: 
 147:   /**
 148:    * This method installs the keyboard actions for this {@link JPopupMenu}.
 149:    */
 150:   protected void installKeyboardActions()
 151:   {
 152:     // FIXME: Need to implement
 153:   }
 154: 
 155:   /**
 156:    * Performs the opposite of installUI. Any properties or resources that need
 157:    * to be cleaned up will be done now. It will also uninstall any listeners
 158:    * it has. In addition, any properties of this UI will be nulled.
 159:    *
 160:    * @param c The {@link JComponent} that is having this UI uninstalled.
 161:    */
 162:   public void uninstallUI(JComponent c)
 163:   {
 164:     uninstallListeners();
 165:     uninstallDefaults();
 166:     popupMenu = null;
 167:   }
 168: 
 169:   /**
 170:    * This method uninstalls the defaults and sets any objects created during
 171:    * install to null
 172:    */
 173:   protected void uninstallDefaults()
 174:   {
 175:     popupMenu.setBackground(null);
 176:     popupMenu.setBorder(null);
 177:     popupMenu.setFont(null);
 178:     popupMenu.setForeground(null);
 179:   }
 180: 
 181:   /**
 182:    * Unregisters all the listeners that this UI delegate was using.
 183:    */
 184:   protected void uninstallListeners()
 185:   {
 186:     popupMenu.removePopupMenuListener(popupMenuListener);
 187:   }
 188: 
 189:   /**
 190:    * Uninstalls any keyboard actions.
 191:    */
 192:   protected void uninstallKeyboardActions()
 193:   {
 194:     // FIXME: Need to implement
 195:   }
 196: 
 197:   /**
 198:    * This method returns the minimum size of the JPopupMenu.
 199:    *
 200:    * @param c The JComponent to find a size for.
 201:    *
 202:    * @return The minimum size.
 203:    */
 204:   public Dimension getMinimumSize(JComponent c)
 205:   {
 206:     return null;
 207:   }
 208: 
 209:   /**
 210:    * This method returns the preferred size of the JPopupMenu.
 211:    *
 212:    * @param c The JComponent to find a size for.
 213:    *
 214:    * @return The preferred size.
 215:    */
 216:   public Dimension getPreferredSize(JComponent c)
 217:   {
 218:     return null;
 219:   }
 220: 
 221:   /**
 222:    * This method returns the minimum size of the JPopupMenu.
 223:    *
 224:    * @param c The JComponent to find a size for.
 225:    *
 226:    * @return The minimum size.
 227:    */
 228:   public Dimension getMaximumSize(JComponent c)
 229:   {
 230:     return null;
 231:   }
 232: 
 233:   /**
 234:    * Return true if given mouse event is a platform popup trigger, and false
 235:    * otherwise
 236:    *
 237:    * @param e MouseEvent that is to be checked for popup trigger event
 238:    *
 239:    * @return true if given mouse event is a platform popup trigger, and false
 240:    *         otherwise
 241:    */
 242:   public boolean isPopupTrigger(MouseEvent e)
 243:   {
 244:     return false;
 245:   }
 246: 
 247:   /**
 248:    * This listener handles PopupMenuEvents fired by JPopupMenu
 249:    */
 250:   private class PopupMenuHandler implements PopupMenuListener
 251:   {
 252:     /**
 253:      * This method is invoked when JPopupMenu is cancelled.
 254:      *
 255:      * @param event the PopupMenuEvent
 256:      */
 257:     public void popupMenuCanceled(PopupMenuEvent event)
 258:     {
 259:       MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 260:       manager.clearSelectedPath();
 261:     }
 262: 
 263:     /**
 264:      * This method is invoked when JPopupMenu becomes invisible
 265:      *
 266:      * @param event the PopupMenuEvent
 267:      */
 268:     public void popupMenuWillBecomeInvisible(PopupMenuEvent event)
 269:     {
 270:       // remove listener that listens to component events fired 
 271:       // by the top - level window that this popup belongs to.
 272:       Component invoker = popupMenu.getInvoker();
 273: 
 274:       RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities
 275:                                         .getRoot(invoker);
 276:       if (rootContainer != null)
 277:         {
 278:           ((Container) rootContainer).removeComponentListener(topWindowListener);
 279: 
 280:           // If this popup menu is the last popup menu visible on the screen,
 281:           // then
 282:           // stop interrupting mouse events in the glass pane before hiding this
 283:           // last popup menu.
 284:           boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu)
 285:                                  && ((JMenu) popupMenu.getInvoker()).isTopLevelMenu();
 286: 
 287:           if (topLevelMenu || !(popupMenu.getInvoker() instanceof MenuElement))
 288:             {
 289:               // set glass pane not to interrupt mouse events and remove
 290:               // mouseInputListener
 291:               Container glassPane = (Container) rootContainer.getGlassPane();
 292:               glassPane.setVisible(false);
 293:               glassPane.removeMouseListener(mouseInputListener);
 294:               mouseInputListener = null;
 295:             }
 296:         }
 297:     }
 298: 
 299:     /**
 300:      * This method is invoked when JPopupMenu becomes visible
 301:      *
 302:      * @param event the PopupMenuEvent
 303:      */
 304:     public void popupMenuWillBecomeVisible(PopupMenuEvent event)
 305:     {
 306:       // Adds topWindowListener to top-level window to listener to 
 307:       // ComponentEvents fired by it. We need to cancel this popup menu
 308:       // if topWindow to which this popup belongs was resized or moved.
 309:       Component invoker = popupMenu.getInvoker();
 310:       RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities
 311:                                         .getRoot(invoker);
 312:       ((Container) rootContainer).addComponentListener(topWindowListener);
 313: 
 314:       // Set the glass pane to interrupt all mouse events originating in root 
 315:       // container
 316:       if (mouseInputListener == null)
 317:         {
 318:       Container glassPane = (Container) rootContainer.getGlassPane();
 319:       glassPane.setVisible(true);
 320:       mouseInputListener = new MouseInputHandler(rootContainer);
 321:       glassPane.addMouseListener(mouseInputListener);
 322:       glassPane.addMouseMotionListener(mouseInputListener);
 323:         }
 324: 
 325:       // if this popup menu is a free floating popup menu,
 326:       // then by default its first element should be always selected when
 327:       // this popup menu becomes visible. 
 328:       MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 329: 
 330:       if (manager.getSelectedPath().length == 0)
 331:         {
 332:       // Set selected path to point to the first item in the popup menu
 333:       MenuElement[] path = new MenuElement[2];
 334:       path[0] = popupMenu;
 335:       Component[] comps = popupMenu.getComponents();
 336:       if (comps.length != 0 && comps[0] instanceof MenuElement)
 337:         {
 338:           path[1] = (MenuElement) comps[0];
 339:           manager.setSelectedPath(path);
 340:         }
 341:         }
 342:     }
 343:   }
 344: 
 345:   /**
 346:    * ComponentListener that listens to Component Events fired by the top -
 347:    * level window to which popup menu belongs. If top-level window was
 348:    * resized, moved or hidded then popup menu will be hidded and selected
 349:    * path of current menu hierarchy will be set to null.
 350:    */
 351:   private class TopWindowListener implements ComponentListener
 352:   {
 353:     /**
 354:      * This method is invoked when top-level window is resized. This method
 355:      * closes current menu hierarchy.
 356:      *
 357:      * @param e The ComponentEvent
 358:      */
 359:     public void componentResized(ComponentEvent e)
 360:     {
 361:       MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 362:       manager.clearSelectedPath();
 363:     }
 364: 
 365:     /**
 366:      * This method is invoked when top-level window is moved. This method
 367:      * closes current menu hierarchy.
 368:      *
 369:      * @param e The ComponentEvent
 370:      */
 371:     public void componentMoved(ComponentEvent e)
 372:     {
 373:       MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 374:       manager.clearSelectedPath();
 375:     }
 376: 
 377:     /**
 378:      * This method is invoked when top-level window is shown This method
 379:      * does nothing by default.
 380:      *
 381:      * @param e The ComponentEvent
 382:      */
 383:     public void componentShown(ComponentEvent e)
 384:     {
 385:       MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 386:       manager.clearSelectedPath();
 387:     }
 388: 
 389:     /**
 390:      * This method is invoked when top-level window is hidden This method
 391:      * closes current menu hierarchy.
 392:      *
 393:      * @param e The ComponentEvent
 394:      */
 395:     public void componentHidden(ComponentEvent e)
 396:     {
 397:       MenuSelectionManager manager = MenuSelectionManager.defaultManager();
 398:       manager.clearSelectedPath();
 399:     }
 400:   }
 401: 
 402:   /**
 403:    * MouseInputHandler listens to all mouse events originated in the root
 404:    * container. This class is responsible for closing menu hierarchy when the
 405:    * user presses mouse over any component that do not belong to the current 
 406:    * menu hierarchy. This is acomplished by interrupting all mouse event in 
 407:    * the glass pane and checking if other component was pressed while menu 
 408:    * was open, before redestributing events further to intended components
 409:    */
 410:   private class MouseInputHandler implements MouseInputListener
 411:   {
 412:     private JLayeredPane layeredPane;
 413:     private Container glassPane;
 414:     private Cursor nativeCursor;
 415:     private transient Component mouseEventTarget;
 416:     private transient Component pressedComponent;
 417:     private transient Component lastComponentEntered;
 418:     private transient Component tempComponent;
 419:     private transient int pressCount;
 420: 
 421:     /**
 422:      * Creates a new MouseInputHandler object.
 423:      *
 424:      * @param c the top most root container
 425:      */
 426:     public MouseInputHandler(RootPaneContainer c)
 427:     {
 428:       layeredPane = c.getLayeredPane();
 429:       glassPane = (Container) c.getGlassPane();
 430:     }
 431: 
 432:     /**
 433:      * Handles mouse clicked event
 434:      *
 435:      * @param e Mouse event
 436:      */
 437:     public void mouseClicked(MouseEvent e)
 438:     {
 439:       handleEvent(e);
 440:     }
 441: 
 442:     /**
 443:      * Handles mouseDragged event
 444:      *
 445:      * @param e MouseEvent
 446:      */
 447:     public void mouseDragged(MouseEvent e)
 448:     {
 449:       handleEvent(e);
 450:     }
 451: 
 452:     /**
 453:      * Handles mouseEntered event
 454:      *
 455:      * @param e MouseEvent
 456:      */
 457:     public void mouseEntered(MouseEvent e)
 458:     {
 459:       handleEvent(e);
 460:     }
 461: 
 462:     /**
 463:      * Handles mouseExited event
 464:      *
 465:      * @param e MouseEvent
 466:      */
 467:     public void mouseExited(MouseEvent e)
 468:     {
 469:       handleEvent(e);
 470:     }
 471: 
 472:     /**
 473:      * Handles mouse moved event
 474:      *
 475:      * @param e MouseEvent
 476:      */
 477:     public void mouseMoved(MouseEvent e)
 478:     {
 479:       handleEvent(e);
 480:     }
 481: 
 482:     /**
 483:      * Handles mouse pressed event
 484:      *
 485:      * @param e MouseEvent
 486:      */
 487:     public void mousePressed(MouseEvent e)
 488:     {
 489:       handleEvent(e);
 490:     }
 491: 
 492:     /**
 493:      * Handles mouse released event
 494:      *
 495:      * @param e MouseEvent
 496:      */
 497:     public void mouseReleased(MouseEvent e)
 498:     {
 499:       handleEvent(e);
 500:     }
 501: 
 502:     /*
 503:      * This method determines component that was intended to received mouse
 504:      * event, before it was interrupted within the glass pane. This method
 505:      * also redispatches mouse entered and mouse exited events to the
 506:      * appropriate components. This code is slightly modified code from
 507:      * Container.LightweightDispatcher class, which is private inside
 508:      * Container class and cannot be used here.
 509:      */
 510:     public void acquireComponentForMouseEvent(MouseEvent me)
 511:     {
 512:       int x = me.getX();
 513:       int y = me.getY();
 514: 
 515:       // Find the candidate which should receive this event.
 516:       Component parent = layeredPane;
 517:       Component candidate = null;
 518:       Point p = me.getPoint();
 519:       while ((candidate == null) && (parent != null))
 520:         {
 521:       p = SwingUtilities.convertPoint(glassPane, p.x, p.y, parent);
 522:       candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
 523: 
 524:       if (candidate == null)
 525:         {
 526:           p = SwingUtilities.convertPoint(parent, p.x, p.y,
 527:                                           parent.getParent());
 528:           parent = parent.getParent();
 529:         }
 530:         }
 531: 
 532:       // If the only candidate we found was the native container itself,
 533:       // don't dispatch any event at all.  We only care about the lightweight
 534:       // children here.
 535:       if (candidate == layeredPane)
 536:     candidate = null;
 537: 
 538:       // If our candidate is new, inform the old target we're leaving.
 539:       if ((lastComponentEntered != null) && lastComponentEntered.isShowing()
 540:           && (lastComponentEntered != candidate))
 541:         {
 542:       // Old candidate could have been removed from 
 543:       // the layeredPane so we check first.
 544:       if (SwingUtilities.isDescendingFrom(lastComponentEntered, layeredPane))
 545:         {
 546:           Point tp = SwingUtilities.convertPoint(layeredPane, x, y,
 547:                                                  lastComponentEntered);
 548:           MouseEvent exited = new MouseEvent(lastComponentEntered,
 549:                                              MouseEvent.MOUSE_EXITED,
 550:                                              me.getWhen(),
 551:                                              me.getModifiersEx(), tp.x,
 552:                                              tp.y, me.getClickCount(),
 553:                                              me.isPopupTrigger(),
 554:                                              me.getButton());
 555: 
 556:               tempComponent = lastComponentEntered;
 557:               lastComponentEntered = null;
 558:           tempComponent.dispatchEvent(exited);
 559:         }
 560: 
 561:       lastComponentEntered = null;
 562:         }
 563: 
 564:       // If we have a candidate, maybe enter it.
 565:       if (candidate != null)
 566:         {
 567:       mouseEventTarget = candidate;
 568: 
 569:       if (candidate.isLightweight() && candidate.isShowing()
 570:           && (candidate != layeredPane)
 571:           && (candidate != lastComponentEntered))
 572:         {
 573:           lastComponentEntered = mouseEventTarget;
 574: 
 575:           Point cp = SwingUtilities.convertPoint(layeredPane, x, y,
 576:                                                  lastComponentEntered);
 577:           MouseEvent entered = new MouseEvent(lastComponentEntered,
 578:                                               MouseEvent.MOUSE_ENTERED,
 579:                                               me.getWhen(),
 580:                                               me.getModifiersEx(), cp.x,
 581:                                               cp.y, me.getClickCount(),
 582:                                               me.isPopupTrigger(),
 583:                                               me.getButton());
 584:           lastComponentEntered.dispatchEvent(entered);
 585:         }
 586:         }
 587: 
 588:       if ((me.getID() == MouseEvent.MOUSE_RELEASED)
 589:           || ((me.getID() == MouseEvent.MOUSE_PRESSED) && (pressCount > 0))
 590:           || (me.getID() == MouseEvent.MOUSE_DRAGGED))
 591:         {
 592:       // If any of the following events occur while a button is held down,
 593:       // they should be dispatched to the same component to which the
 594:       // original MOUSE_PRESSED event was dispatched:
 595:       //   - MOUSE_RELEASED
 596:       //   - MOUSE_PRESSED: another button pressed while the first is held down
 597:       //   - MOUSE_DRAGGED
 598:       if (SwingUtilities.isDescendingFrom(pressedComponent, layeredPane))
 599:         mouseEventTarget = pressedComponent;
 600:       else if (me.getID() == MouseEvent.MOUSE_CLICKED)
 601:         {
 602:           // Don't dispatch CLICKED events whose target is not the same as the
 603:           // target for the original PRESSED event.
 604:           if (candidate != pressedComponent)
 605:         mouseEventTarget = null;
 606:           else if (pressCount == 0)
 607:         pressedComponent = null;
 608:         }
 609:         }
 610:     }
 611: 
 612:     /*
 613:      * This method handles mouse events interrupted by glassPane. It
 614:      * redispatches the mouse events appropriately to the intended components.
 615:      * The code in this method is also taken from
 616:      * Container.LightweightDispatcher class. The code is slightly modified
 617:      * to handle the case when mouse is released over non-menu component. In
 618:      * this case this method closes current menu hierarchy before 
 619:      * redispatching the event further.
 620:      */
 621:     public void handleEvent(AWTEvent e)
 622:     {
 623:       if (e instanceof MouseEvent)
 624:         {
 625:       MouseEvent me = (MouseEvent) e;
 626: 
 627:       acquireComponentForMouseEvent(me);
 628: 
 629:       // Avoid dispatching ENTERED and EXITED events twice.
 630:       if (mouseEventTarget != null && mouseEventTarget.isShowing()
 631:           && (e.getID() != MouseEvent.MOUSE_ENTERED)
 632:           && (e.getID() != MouseEvent.MOUSE_EXITED))
 633:         {
 634:           MouseEvent newEvt = SwingUtilities.convertMouseEvent(glassPane,
 635:                                                                me,
 636:                                                                mouseEventTarget);
 637: 
 638:           mouseEventTarget.dispatchEvent(newEvt);
 639: 
 640:           // If mouse was clicked over the component that is not part 
 641:           // of menu hierarchy,then must close the menu hierarchy */
 642:           if (e.getID() == MouseEvent.MOUSE_RELEASED)
 643:             {
 644:           boolean partOfMenuHierarchy = false;
 645:           MenuSelectionManager manager = MenuSelectionManager
 646:                                          .defaultManager();
 647: 
 648:           partOfMenuHierarchy = manager.isComponentPartOfCurrentMenu(mouseEventTarget);
 649: 
 650:           if (! partOfMenuHierarchy)
 651:             manager.clearSelectedPath();
 652:             }
 653: 
 654:           switch (e.getID())
 655:             {
 656:         case MouseEvent.MOUSE_PRESSED:
 657:           if (pressCount++ == 0)
 658:             pressedComponent = mouseEventTarget;
 659:           break;
 660:         case MouseEvent.MOUSE_RELEASED:
 661:           // Clear our memory of the original PRESSED event, only if
 662:           // we're not expecting a CLICKED event after this. If
 663:           // there is a CLICKED event after this, it will do clean up.
 664:           if ((--pressCount == 0)
 665:               && (mouseEventTarget != pressedComponent))
 666:             pressedComponent = null;
 667:           break;
 668:             }
 669:         }
 670:         }
 671:     }
 672:   }
 673: }