2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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., 59 Temple Place, Suite 330, Boston, MA
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
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. */
40 import java
.awt
.BorderLayout
;
41 import java
.awt
.Component
;
42 import java
.awt
.Container
;
43 import java
.awt
.Dimension
;
44 import java
.awt
.Frame
;
45 import java
.awt
.Graphics
;
46 import java
.awt
.GridBagConstraints
;
47 import java
.awt
.GridBagLayout
;
48 import java
.awt
.Insets
;
49 import java
.awt
.LayoutManager
;
50 import java
.awt
.Panel
;
51 import java
.awt
.Point
;
52 import java
.awt
.Window
;
53 import java
.awt
.event
.KeyEvent
;
54 import java
.awt
.event
.MouseEvent
;
55 import java
.beans
.PropertyChangeListener
;
56 import java
.io
.IOException
;
57 import java
.io
.ObjectInputStream
;
58 import java
.io
.ObjectOutputStream
;
59 import java
.util
.EventListener
;
60 import java
.util
.Vector
;
61 import javax
.accessibility
.Accessible
;
62 import javax
.accessibility
.AccessibleContext
;
63 import javax
.accessibility
.AccessibleRole
;
64 import javax
.swing
.event
.PopupMenuEvent
;
65 import javax
.swing
.event
.PopupMenuListener
;
66 import javax
.swing
.plaf
.PopupMenuUI
;
73 * @version $Revision: 1.3.8.3 $
75 public class JPopupMenu
extends JComponent
implements Accessible
, MenuElement
77 private static final String uiClassID
= "PopupMenuUI";
78 private static final Object defaultLWPopupEnabledKey
= null;
79 private static boolean defaultLWPopupEnabled
= true;
80 transient Component invoker
;
81 private int locationX
;
82 private int locationY
;
84 private boolean paintBorder
;
85 private Insets margin
;
86 private boolean lightWeightPopupEnabled
;
87 private SingleSelectionModel selectionModel
;
88 private transient Popup popup
;
89 private Point location
;
92 * Creates a new JPopupMenu object.
98 lightWeightPopupEnabled
= defaultLWPopupEnabled
;
99 selectionModel
= new DefaultSingleSelectionModel();
103 * Creates a new JPopupMenu object.
105 * @param label DOCUMENT ME!
107 public JPopupMenu(String label
)
115 * @param stream DOCUMENT ME!
117 * @throws IOException DOCUMENT ME!
118 * @throws ClassNotFoundException DOCUMENT ME!
120 private void readObject(ObjectInputStream stream
)
121 throws IOException
, ClassNotFoundException
128 * @param stream DOCUMENT ME!
130 * @throws IOException DOCUMENT ME!
132 private void writeObject(ObjectOutputStream stream
) throws IOException
139 * @param item DOCUMENT ME!
141 * @return DOCUMENT ME!
143 public JMenuItem
add(JMenuItem item
)
145 this.insert(item
, -1);
152 * @param text DOCUMENT ME!
154 * @return DOCUMENT ME!
156 public JMenuItem
add(String text
)
158 JMenuItem item
= new JMenuItem(text
);
165 * @param action DOCUMENT ME!
167 * @return DOCUMENT ME!
169 public JMenuItem
add(Action action
)
171 JMenuItem item
= new JMenuItem(action
);
178 * @param index DOCUMENT ME!
180 public void remove(int index
)
184 GridBagConstraints constraints
= new GridBagConstraints();
185 constraints
.fill
= GridBagConstraints
.HORIZONTAL
;
186 constraints
.weightx
= 100.0;
187 constraints
.weighty
= 100.0;
189 Component
[] items
= getComponents();
190 for (int i
= index
; i
< items
.length
; i
++)
192 constraints
.gridy
= i
;
193 super.add(items
[i
], constraints
, i
);
200 * @param action DOCUMENT ME!
201 * @param index DOCUMENT ME!
203 public void insert(Action action
, int index
)
205 JMenuItem item
= new JMenuItem(action
);
206 this.insert(item
, index
);
212 * @param component DOCUMENT ME!
213 * @param index DOCUMENT ME!
215 public void insert(Component component
, int index
)
217 GridBagConstraints constraints
= new GridBagConstraints();
218 constraints
.fill
= GridBagConstraints
.HORIZONTAL
;
219 constraints
.weightx
= 100.0;
220 constraints
.weighty
= 100.0;
223 index
= getComponents().length
;
225 constraints
.gridy
= index
;
226 super.add(component
, constraints
, index
);
228 // need to change constraints for the components that were moved by 1
229 // due to the insertion
232 Component
[] items
= getComponents();
234 for (int i
= index
+ 1; i
< items
.length
; i
++)
236 constraints
.gridy
= i
;
237 super.add(items
[i
], constraints
, i
);
245 * @param graphics DOCUMENT ME!
247 protected void paintBorder(Graphics graphics
)
250 getBorder().paintBorder(this, graphics
, 0, 0, getSize(null).width
,
251 getSize(null).height
);
257 * @return DOCUMENT ME!
259 public static boolean getDefaultLightWeightPopupEnabled()
261 return defaultLWPopupEnabled
;
267 * @param enabled DOCUMENT ME!
269 public static void setDefaultLightWeightPopupEnabled(boolean enabled
)
271 defaultLWPopupEnabled
= enabled
;
277 * @return DOCUMENT ME!
279 public PopupMenuUI
getUI()
281 return (PopupMenuUI
) ui
;
287 * @param ui DOCUMENT ME!
289 public void setUI(PopupMenuUI ui
)
297 public void updateUI()
299 setUI((PopupMenuUI
) UIManager
.getUI(this));
306 * @return DOCUMENT ME!
308 public String
getUIClassID()
310 return "PopupMenuUI";
316 * @return DOCUMENT ME!
318 public SingleSelectionModel
getSelectionModel()
320 return selectionModel
;
326 * @param model DOCUMENT ME!
328 public void setSelectionModel(SingleSelectionModel model
)
330 if (selectionModel
!= model
)
332 SingleSelectionModel oldModel
= this.selectionModel
;
339 * @param action DOCUMENT ME!
341 * @return DOCUMENT ME!
343 protected JMenuItem
createActionComponent(Action action
)
351 * @param item DOCUMENT ME!
353 * @return DOCUMENT ME!
355 protected PropertyChangeListener
createActionChangeListener(JMenuItem item
)
363 * @return DOCUMENT ME!
365 public boolean isLightWeightPopupEnabled()
367 return lightWeightPopupEnabled
;
373 * @param enabled DOCUMENT ME!
375 public void setLightWeightPopupEnabled(boolean enabled
)
377 lightWeightPopupEnabled
= enabled
;
383 * @return DOCUMENT ME!
385 public String
getLabel()
393 * @param label DOCUMENT ME!
395 public void setLabel(String label
)
403 public void addSeparator()
410 * @param listener DOCUMENT ME!
412 public void addPopupMenuListener(PopupMenuListener listener
)
414 listenerList
.add(PopupMenuListener
.class, listener
);
420 * @param listener DOCUMENT ME!
422 public void removePopupMenuListener(PopupMenuListener listener
)
424 listenerList
.remove(PopupMenuListener
.class, listener
);
430 protected void firePopupMenuWillBecomeVisible()
432 EventListener
[] ll
= listenerList
.getListeners(PopupMenuListener
.class);
434 for (int i
= 0; i
< ll
.length
; i
++)
435 ((PopupMenuListener
) ll
[i
]).popupMenuWillBecomeVisible(new PopupMenuEvent(this));
441 protected void firePopupMenuWillBecomeInvisible()
443 EventListener
[] ll
= listenerList
.getListeners(PopupMenuListener
.class);
445 for (int i
= 0; i
< ll
.length
; i
++)
446 ((PopupMenuListener
) ll
[i
]).popupMenuWillBecomeInvisible(new PopupMenuEvent(this));
452 protected void firePopupMenuCanceled()
454 EventListener
[] ll
= listenerList
.getListeners(PopupMenuListener
.class);
456 for (int i
= 0; i
< ll
.length
; i
++)
457 ((PopupMenuListener
) ll
[i
]).popupMenuCanceled(new PopupMenuEvent(this));
470 * @return DOCUMENT ME!
472 public boolean isVisible()
474 return super.visible
;
480 * @param visible DOCUMENT ME!
482 public void setVisible(boolean visible
)
484 super.visible
= visible
;
486 firePopupMenuWillBecomeVisible();
490 Container rootContainer
= (Container
) SwingUtilities
.getRoot(invoker
);
495 // Determine the size of the popup menu
496 if (this.getSize().width
== 0 && this.getSize().width
== 0)
497 size
= this.getPreferredSize();
499 size
= this.getSize();
501 if ((size
.width
> (rootContainer
.getWidth() - locationX
))
502 || (size
.height
> (rootContainer
.getHeight() - locationY
)))
505 if (lightWeightPopupEnabled
&& fit
)
506 popup
= new LightWeightPopup(this);
510 popup
= new MediumWeightPopup(this);
512 popup
= new HeavyWeightPopup(this);
515 if (popup
instanceof LightWeightPopup
516 || popup
instanceof MediumWeightPopup
)
518 JLayeredPane layeredPane
;
519 layeredPane
= SwingUtilities
.getRootPane(invoker
).getLayeredPane();
520 Point lp
= layeredPane
.getLocationOnScreen();
521 Point r
= SwingUtilities
.getRoot(invoker
).getLocationOnScreen();
522 int px
= locationX
- (lp
.x
- r
.x
);
523 int py
= locationY
- (lp
.y
- r
.y
);
524 popup
.show(px
, py
, size
.width
, size
.height
);
527 popup
.show(locationX
, locationY
, size
.width
, size
.height
);
531 firePopupMenuWillBecomeInvisible();
539 * @param x DOCUMENT ME!
540 * @param y DOCUMENT ME!
542 public void setLocation(int x
, int y
)
551 * @return DOCUMENT ME!
553 private boolean isPopupMenu()
561 * @return DOCUMENT ME!
563 public Component
getInvoker()
571 * @param component DOCUMENT ME!
573 public void setInvoker(Component component
)
581 * @param component DOCUMENT ME!
582 * @param x DOCUMENT ME!
583 * @param y DOCUMENT ME!
585 public void show(Component component
, int x
, int y
)
587 setInvoker(component
);
590 rootOnScreen
= SwingUtilities
.getRoot(invoker
).getLocationOnScreen();
591 Point invokerOnScreen
= invoker
.getLocationOnScreen();
593 int popupX
= (invokerOnScreen
.x
- rootOnScreen
.x
) + x
;
594 int popupY
= (invokerOnScreen
.y
- rootOnScreen
.y
) + y
;
596 setLocation(popupX
, popupY
);
603 * @return DOCUMENT ME!
605 JPopupMenu
getRootPopupMenu()
613 * @param index DOCUMENT ME!
615 * @return DOCUMENT ME!
617 public Component
getComponentAtIndex(int index
)
619 return getComponent(index
);
625 * @param component DOCUMENT ME!
627 * @return DOCUMENT ME!
629 public int getComponentIndex(Component component
)
631 Component
[] items
= getComponents();
633 for (int i
= 0; i
< items
.length
; i
++)
635 if (items
[i
].equals(component
))
645 * @param size DOCUMENT ME!
647 public void setPopupSize(Dimension size
)
655 * @param x DOCUMENT ME!
656 * @param y DOCUMENT ME!
658 public void setPopupSize(int x
, int y
)
666 * @param selected DOCUMENT ME!
668 public void setSelected(Component selected
)
670 int index
= getComponentIndex(selected
);
671 selectionModel
.setSelectedIndex(index
);
677 * @return DOCUMENT ME!
679 public boolean isBorderPainted()
687 * @param painted DOCUMENT ME!
689 public void setBorderPainted(boolean painted
)
691 paintBorder
= painted
;
697 * @return DOCUMENT ME!
699 public Insets
getMargin()
707 * @return DOCUMENT ME!
709 protected String
paramString()
717 * @param event DOCUMENT ME!
718 * @param path DOCUMENT ME!
719 * @param manager DOCUMENT ME!
721 public void processMouseEvent(MouseEvent event
, MenuElement
[] path
,
722 MenuSelectionManager manager
)
729 * @param event DOCUMENT ME!
730 * @param path DOCUMENT ME!
731 * @param manager DOCUMENT ME!
733 public void processKeyEvent(KeyEvent event
, MenuElement
[] path
,
734 MenuSelectionManager manager
)
741 * @param changed DOCUMENT ME!
743 public void menuSelectionChanged(boolean changed
)
750 * @return DOCUMENT ME!
752 public MenuElement
[] getSubElements()
754 Component
[] items
= getComponents();
755 MenuElement
[] subElements
= new MenuElement
[items
.length
];
757 for (int i
= 0; i
< items
.length
; i
++)
758 subElements
[i
] = (MenuElement
) items
[i
];
766 * @return DOCUMENT ME!
768 public Component
getComponent()
776 * @param event DOCUMENT ME!
778 * @return DOCUMENT ME!
780 public boolean isPopupTrigger(MouseEvent event
)
782 return ((PopupMenuUI
)getUI()).isPopupTrigger(event
);
789 * @return DOCUMENT ME!
791 public AccessibleContext
getAccessibleContext()
793 if (accessibleContext
== null)
794 accessibleContext
= new AccessibleJPopupMenu(this);
796 return accessibleContext
;
803 * @version $Revision: 1.3.8.3 $
805 private interface Popup
810 * @param x DOCUMENT ME!
811 * @param y DOCUMENT ME!
812 * @param width DOCUMENT ME!
813 * @param height DOCUMENT ME!
815 void show(int x
, int y
, int width
, int height
);
827 * @version $Revision: 1.3.8.3 $
829 private class LightWeightPopup
extends JPanel
implements Popup
832 * Creates a new LightWeightPopup object.
834 * @param c DOCUMENT ME!
836 public LightWeightPopup(Container c
)
844 * @param x DOCUMENT ME!
845 * @param y DOCUMENT ME!
846 * @param width DOCUMENT ME!
847 * @param height DOCUMENT ME!
849 public void show(int x
, int y
, int width
, int height
)
851 JLayeredPane layeredPane
;
852 layeredPane
= SwingUtilities
.getRootPane(invoker
).getLayeredPane();
853 this.setBounds(x
, y
, width
, height
);
854 layeredPane
.add(this, JLayeredPane
.POPUP_LAYER
, 0);
862 JLayeredPane layeredPane
;
863 layeredPane
= SwingUtilities
.getRootPane(invoker
).getLayeredPane();
864 int index
= layeredPane
.getIndexOf(this);
865 layeredPane
.remove(index
);
873 * @version $Revision: 1.3.8.3 $
875 private class MediumWeightPopup
extends Panel
implements Popup
879 * Creates a new MediumWeightPopup object.
881 * @param c DOCUMENT ME!
883 public MediumWeightPopup(Container c
)
891 * @param x DOCUMENT ME!
892 * @param y DOCUMENT ME!
893 * @param width DOCUMENT ME!
894 * @param heigth DOCUMENT ME!
896 public void show(int x
, int y
, int width
, int heigth
)
898 JLayeredPane layeredPane
;
899 layeredPane
= SwingUtilities
.getRootPane(invoker
).getLayeredPane();
900 layeredPane
.add(this, JLayeredPane
.POPUP_LAYER
, 0);
901 this.setBounds(x
, y
, width
, height
);
909 JLayeredPane layeredPane
;
910 layeredPane
= SwingUtilities
.getRootPane(invoker
).getLayeredPane();
911 int index
= layeredPane
.getIndexOf(this);
912 layeredPane
.remove(index
);
920 * @version $Revision: 1.3.8.3 $
922 private class HeavyWeightPopup
extends JWindow
implements Popup
925 * Creates a new HeavyWeightPopup object.
927 * @param c DOCUMENT ME!
929 public HeavyWeightPopup(Container c
)
931 this.setContentPane(c
);
937 * @param x DOCUMENT ME!
938 * @param y DOCUMENT ME!
939 * @param width DOCUMENT ME!
940 * @param height DOCUMENT ME!
942 public void show(int x
, int y
, int width
, int height
)
944 this.setBounds(x
, y
, width
, height
);
961 * @version $Revision: 1.3.8.3 $
963 public static class Separator
extends JSeparator
966 * Creates a new Separator object.
975 * @return DOCUMENT ME!
977 public String
getUIClassID()
987 * @version $Revision: 1.3.8.3 $
989 protected class AccessibleJPopupMenu
extends AccessibleJComponent
992 * Creates a new AccessibleJPopupMenu object.
994 * @param component DOCUMENT ME!
996 protected AccessibleJPopupMenu(JPopupMenu component
)
1004 * @return DOCUMENT ME!
1006 public AccessibleRole
getAccessibleRole()
1008 return AccessibleRole
.POPUP_MENU
;