1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67:
68:
69:
72: public class BasicPopupMenuUI extends PopupMenuUI
73: {
74:
75: protected JPopupMenu popupMenu;
76:
77:
78: static transient MouseInputListener mouseInputListener;
79:
80:
81: private transient PopupMenuListener popupMenuListener;
82:
83:
85: TopWindowListener topWindowListener;
86:
87:
90: public BasicPopupMenuUI()
91: {
92: popupMenuListener = new PopupMenuHandler();
93: topWindowListener = new TopWindowListener();
94: }
95:
96:
104: public static ComponentUI createUI(JComponent x)
105: {
106: return new BasicPopupMenuUI();
107: }
108:
109:
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:
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:
146: protected void installListeners()
147: {
148: popupMenu.addPopupMenuListener(popupMenuListener);
149: }
150:
151:
154: protected void installKeyboardActions()
155: {
156:
157: }
158:
159:
166: public void uninstallUI(JComponent c)
167: {
168: uninstallListeners();
169: uninstallDefaults();
170: popupMenu = null;
171: }
172:
173:
177: protected void uninstallDefaults()
178: {
179: popupMenu.setBackground(null);
180: popupMenu.setBorder(null);
181: popupMenu.setFont(null);
182: popupMenu.setForeground(null);
183: }
184:
185:
188: protected void uninstallListeners()
189: {
190: popupMenu.removePopupMenuListener(popupMenuListener);
191: }
192:
193:
196: protected void uninstallKeyboardActions()
197: {
198:
199: }
200:
201:
208: public Dimension getMinimumSize(JComponent c)
209: {
210: return null;
211: }
212:
213:
220: public Dimension getPreferredSize(JComponent c)
221: {
222: return null;
223: }
224:
225:
232: public Dimension getMaximumSize(JComponent c)
233: {
234: return null;
235: }
236:
237:
246: public boolean isPopupTrigger(MouseEvent e)
247: {
248: return false;
249: }
250:
251:
254: private class PopupMenuHandler implements PopupMenuListener
255: {
256:
261: public void popupMenuCanceled(PopupMenuEvent event)
262: {
263: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
264: manager.clearSelectedPath();
265: }
266:
267:
272: public void popupMenuWillBecomeInvisible(PopupMenuEvent event)
273: {
274:
275:
276: Component invoker = popupMenu.getInvoker();
277:
278: RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities
279: .getRoot(invoker);
280: ((Container) rootContainer).removeComponentListener(topWindowListener);
281:
282:
283:
284:
285: boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu)
286: && ((JMenu) popupMenu.getInvoker())
287: .isTopLevelMenu();
288:
289: if (topLevelMenu || ! (popupMenu.getInvoker() instanceof MenuElement))
290: {
291:
292:
293: Container glassPane = (Container) rootContainer.getGlassPane();
294: glassPane.setVisible(false);
295: glassPane.removeMouseListener(mouseInputListener);
296: mouseInputListener = null;
297: }
298: }
299:
300:
305: public void popupMenuWillBecomeVisible(PopupMenuEvent event)
306: {
307:
308:
309:
310: Component invoker = popupMenu.getInvoker();
311: RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities
312: .getRoot(invoker);
313: ((Container) rootContainer).addComponentListener(topWindowListener);
314:
315:
316:
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:
327:
328:
329: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
330:
331: if (manager.getSelectedPath().length == 0)
332: {
333:
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:
352: private class TopWindowListener implements ComponentListener
353: {
354:
360: public void componentResized(ComponentEvent e)
361: {
362: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
363: manager.clearSelectedPath();
364: }
365:
366:
372: public void componentMoved(ComponentEvent e)
373: {
374: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
375: manager.clearSelectedPath();
376: }
377:
378:
384: public void componentShown(ComponentEvent e)
385: {
386: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
387: manager.clearSelectedPath();
388: }
389:
390:
396: public void componentHidden(ComponentEvent e)
397: {
398: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
399: manager.clearSelectedPath();
400: }
401: }
402:
403:
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:
427: public MouseInputHandler(RootPaneContainer c)
428: {
429: layeredPane = c.getLayeredPane();
430: glassPane = (Container) c.getGlassPane();
431: }
432:
433:
438: public void mouseClicked(MouseEvent e)
439: {
440: handleEvent(e);
441: }
442:
443:
448: public void mouseDragged(MouseEvent e)
449: {
450: handleEvent(e);
451: }
452:
453:
458: public void mouseEntered(MouseEvent e)
459: {
460: handleEvent(e);
461: }
462:
463:
468: public void mouseExited(MouseEvent e)
469: {
470: handleEvent(e);
471: }
472:
473:
478: public void mouseMoved(MouseEvent e)
479: {
480: handleEvent(e);
481: }
482:
483:
488: public void mousePressed(MouseEvent e)
489: {
490: handleEvent(e);
491: }
492:
493:
498: public void mouseReleased(MouseEvent e)
499: {
500: handleEvent(e);
501: }
502:
503:
511: public void acquireComponentForMouseEvent(MouseEvent me)
512: {
513: int x = me.getX();
514: int y = me.getY();
515:
516:
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:
534:
535:
536: if (candidate == layeredPane)
537: candidate = null;
538:
539:
540: if ((lastComponentEntered != null) && lastComponentEntered.isShowing()
541: && (lastComponentEntered != candidate))
542: {
543:
544:
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:
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:
594:
595:
596:
597:
598:
599: if (SwingUtilities.isDescendingFrom(pressedComponent, layeredPane))
600: mouseEventTarget = pressedComponent;
601: else if (me.getID() == MouseEvent.MOUSE_CLICKED)
602: {
603:
604:
605: if (candidate != pressedComponent)
606: mouseEventTarget = null;
607: else if (pressCount == 0)
608: pressedComponent = null;
609: }
610: }
611: }
612:
613:
622: public void handleEvent(AWTEvent e)
623: {
624: if (e instanceof MouseEvent)
625: {
626: MouseEvent me = (MouseEvent) e;
627:
628: acquireComponentForMouseEvent(me);
629:
630:
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:
642:
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:
663:
664:
665: if ((--pressCount == 0)
666: && (mouseEventTarget != pressedComponent))
667: pressedComponent = null;
668: break;
669: }
670: }
671: }
672: }
673: }
674: }