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:
67:
68:
71: public class BasicPopupMenuUI extends PopupMenuUI
72: {
73:
74: protected JPopupMenu popupMenu;
75:
76:
77: static transient MouseInputListener mouseInputListener;
78:
79:
80: private transient PopupMenuListener popupMenuListener;
81:
82:
84: TopWindowListener topWindowListener;
85:
86:
89: public BasicPopupMenuUI()
90: {
91: popupMenuListener = new PopupMenuHandler();
92: topWindowListener = new TopWindowListener();
93: }
94:
95:
103: public static ComponentUI createUI(JComponent x)
104: {
105: return new BasicPopupMenuUI();
106: }
107:
108:
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:
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:
142: protected void installListeners()
143: {
144: popupMenu.addPopupMenuListener(popupMenuListener);
145: }
146:
147:
150: protected void installKeyboardActions()
151: {
152:
153: }
154:
155:
162: public void uninstallUI(JComponent c)
163: {
164: uninstallListeners();
165: uninstallDefaults();
166: popupMenu = null;
167: }
168:
169:
173: protected void uninstallDefaults()
174: {
175: popupMenu.setBackground(null);
176: popupMenu.setBorder(null);
177: popupMenu.setFont(null);
178: popupMenu.setForeground(null);
179: }
180:
181:
184: protected void uninstallListeners()
185: {
186: popupMenu.removePopupMenuListener(popupMenuListener);
187: }
188:
189:
192: protected void uninstallKeyboardActions()
193: {
194:
195: }
196:
197:
204: public Dimension getMinimumSize(JComponent c)
205: {
206: return null;
207: }
208:
209:
216: public Dimension getPreferredSize(JComponent c)
217: {
218: return null;
219: }
220:
221:
228: public Dimension getMaximumSize(JComponent c)
229: {
230: return null;
231: }
232:
233:
242: public boolean isPopupTrigger(MouseEvent e)
243: {
244: return false;
245: }
246:
247:
250: private class PopupMenuHandler implements PopupMenuListener
251: {
252:
257: public void popupMenuCanceled(PopupMenuEvent event)
258: {
259: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
260: manager.clearSelectedPath();
261: }
262:
263:
268: public void popupMenuWillBecomeInvisible(PopupMenuEvent event)
269: {
270:
271:
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:
281:
282:
283:
284: boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu)
285: && ((JMenu) popupMenu.getInvoker()).isTopLevelMenu();
286:
287: if (topLevelMenu || !(popupMenu.getInvoker() instanceof MenuElement))
288: {
289:
290:
291: Container glassPane = (Container) rootContainer.getGlassPane();
292: glassPane.setVisible(false);
293: glassPane.removeMouseListener(mouseInputListener);
294: mouseInputListener = null;
295: }
296: }
297: }
298:
299:
304: public void popupMenuWillBecomeVisible(PopupMenuEvent event)
305: {
306:
307:
308:
309: Component invoker = popupMenu.getInvoker();
310: RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities
311: .getRoot(invoker);
312: ((Container) rootContainer).addComponentListener(topWindowListener);
313:
314:
315:
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:
326:
327:
328: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
329:
330: if (manager.getSelectedPath().length == 0)
331: {
332:
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:
351: private class TopWindowListener implements ComponentListener
352: {
353:
359: public void componentResized(ComponentEvent e)
360: {
361: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
362: manager.clearSelectedPath();
363: }
364:
365:
371: public void componentMoved(ComponentEvent e)
372: {
373: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
374: manager.clearSelectedPath();
375: }
376:
377:
383: public void componentShown(ComponentEvent e)
384: {
385: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
386: manager.clearSelectedPath();
387: }
388:
389:
395: public void componentHidden(ComponentEvent e)
396: {
397: MenuSelectionManager manager = MenuSelectionManager.defaultManager();
398: manager.clearSelectedPath();
399: }
400: }
401:
402:
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:
426: public MouseInputHandler(RootPaneContainer c)
427: {
428: layeredPane = c.getLayeredPane();
429: glassPane = (Container) c.getGlassPane();
430: }
431:
432:
437: public void mouseClicked(MouseEvent e)
438: {
439: handleEvent(e);
440: }
441:
442:
447: public void mouseDragged(MouseEvent e)
448: {
449: handleEvent(e);
450: }
451:
452:
457: public void mouseEntered(MouseEvent e)
458: {
459: handleEvent(e);
460: }
461:
462:
467: public void mouseExited(MouseEvent e)
468: {
469: handleEvent(e);
470: }
471:
472:
477: public void mouseMoved(MouseEvent e)
478: {
479: handleEvent(e);
480: }
481:
482:
487: public void mousePressed(MouseEvent e)
488: {
489: handleEvent(e);
490: }
491:
492:
497: public void mouseReleased(MouseEvent e)
498: {
499: handleEvent(e);
500: }
501:
502:
510: public void acquireComponentForMouseEvent(MouseEvent me)
511: {
512: int x = me.getX();
513: int y = me.getY();
514:
515:
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:
533:
534:
535: if (candidate == layeredPane)
536: candidate = null;
537:
538:
539: if ((lastComponentEntered != null) && lastComponentEntered.isShowing()
540: && (lastComponentEntered != candidate))
541: {
542:
543:
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:
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:
593:
594:
595:
596:
597:
598: if (SwingUtilities.isDescendingFrom(pressedComponent, layeredPane))
599: mouseEventTarget = pressedComponent;
600: else if (me.getID() == MouseEvent.MOUSE_CLICKED)
601: {
602:
603:
604: if (candidate != pressedComponent)
605: mouseEventTarget = null;
606: else if (pressCount == 0)
607: pressedComponent = null;
608: }
609: }
610: }
611:
612:
621: public void handleEvent(AWTEvent e)
622: {
623: if (e instanceof MouseEvent)
624: {
625: MouseEvent me = (MouseEvent) e;
626:
627: acquireComponentForMouseEvent(me);
628:
629:
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:
641:
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:
662:
663:
664: if ((--pressCount == 0)
665: && (mouseEventTarget != pressedComponent))
666: pressedComponent = null;
667: break;
668: }
669: }
670: }
671: }
672: }
673: }