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