diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | javax/swing/JLayeredPane.java | 2 | ||||
-rw-r--r-- | javax/swing/JPopupMenu.java | 309 | ||||
-rw-r--r-- | javax/swing/Popup.java | 104 | ||||
-rw-r--r-- | javax/swing/PopupFactory.java | 28 | ||||
-rw-r--r-- | javax/swing/plaf/basic/BasicMenuItemUI.java | 28 | ||||
-rw-r--r-- | javax/swing/plaf/basic/BasicMenuUI.java | 7 |
7 files changed, 214 insertions, 297 deletions
@@ -1,3 +1,36 @@ +2005-10-24 Roman Kennke <kennke@aicas.com> + + * javax/swing/JLayeredPane.java + (addImpl): Removed unnecessary repaint() and revalidate() calls. + * javax/swing/JPopupMenu.java + (remove): Removed unnecessary revalidate() call. + (insert): Removed code that installs GridBagConstraints. JPopupMenu + uses a BoxLayout and this is not needed anymore. + (pack): Send this method call to the event queue to avoid + synchronization problems. Set size to preferredSize of this menu. + (setVisible): Send this method call to the event queue to avoid + synchronization problems. Use PopupFactory for creating a popup. + (setLocation): Use int fields instead of a Point field. + (Popup): Removed inner interface. We use javax.swing.Popup now. + (LightweightPopup): Likewise. + (MediumWeightPopup): Likewise. + (HeavyWeightPopup): Likewise. + * javax/swing/Popup.java + (JWindowPopup.JWindowPopup): Add contents to contentPane of window. + Set focusableWindowState to false. + (JWindowPopup.show): Set size of window here. + (LightweightPopup): New inner class. + * javax/swing/PopupFactory.java + (getPopup): Return heavyweight or lightweight popup depending on + the parameters. + * javax/swing/plaf/basic/BasicMenuItemUI.java + (PropertyChangeHandler): Removed unneeded inner class. + (BasicMenuItemUI): Removed instantiation of PropertyChangeHandler. + (installListeners): Removed handling of the PropertyChangeHandler. + (uninstallListeners): Removed handling of the PropertyChangeHandler. + * javax/swing/plaf/basic/BasicMenuUI.java + (getMaximumSize): Don't treat popup menus different. + 2005-10-25 Audrius Meskauskas <AudriusA@Bioinformatics.org> * gnu/classpath/examples/CORBA/NamingService/Demo.java (main): diff --git a/javax/swing/JLayeredPane.java b/javax/swing/JLayeredPane.java index 33461e773..2617bc408 100644 --- a/javax/swing/JLayeredPane.java +++ b/javax/swing/JLayeredPane.java @@ -644,8 +644,6 @@ public class JLayeredPane extends JComponent implements Accessible incrLayer (layer); super.addImpl(comp, null, newIdx); - revalidate(); - repaint(); } /** diff --git a/javax/swing/JPopupMenu.java b/javax/swing/JPopupMenu.java index 9cf9a4511..cd182fd25 100644 --- a/javax/swing/JPopupMenu.java +++ b/javax/swing/JPopupMenu.java @@ -39,11 +39,8 @@ exception statement from your version. */ package javax.swing; import java.awt.Component; -import java.awt.Container; import java.awt.Dimension; -import java.awt.GridBagConstraints; import java.awt.Insets; -import java.awt.Panel; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -127,8 +124,15 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement /* Popup that is used to display JPopupMenu */ private transient Popup popup; - /* Location of the popup */ - private Point popupLocation; + /** + * Location of the popup, X coordinate. + */ + private int popupLocationX; + + /** + * Location of the popup, Y coordinate. + */ + private int popupLocationY; /* Field indicating if popup menu is visible or not */ private boolean visible = false; @@ -208,19 +212,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement public void remove(int index) { super.remove(index); - - GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.BOTH; - constraints.weightx = 100.0; - constraints.weighty = 100.0; - - Component[] items = getComponents(); - for (int i = index; i < items.length; i++) - { - constraints.gridy = i; - super.add(items[i], constraints, i); - } - this.setSize(this.getPreferredSize()); + revalidate(); } /** @@ -245,27 +237,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement */ public void insert(Component component, int index) { - GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.BOTH; - constraints.weightx = 100.0; - constraints.weighty = 100.0; - - constraints.gridy = index; - super.add(component, constraints, index); - - // need to change constraints for the components that were moved by 1 - // due to the insertion - if (index != -1) - { - Component[] items = getComponents(); - - for (int i = index + 1; i < items.length; i++) - { - constraints.gridy = i; - super.add(items[i], constraints, i); - } - } - this.setSize(this.getPreferredSize()); + super.add(component, index); } /** @@ -515,7 +487,20 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement */ public void pack() { - super.setSize(null); + // Hook up this call so that it gets executed on the event thread in order + // to avoid synchronization problems when calling the layout manager. + if (! SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + show(); + } + }); + } + + setSize(getPreferredSize()); } /** @@ -535,8 +520,21 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement * * @param visible true if popup menu will become visible and false otherwise. */ - public void setVisible(boolean visible) + public void setVisible(final boolean visible) { + // Hook up this call so that it gets executed on the event thread in order + // to avoid synchronization problems when calling the layout manager. + if (! SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + setVisible(visible); + } + }); + } + if (visible == isVisible()) return; @@ -548,63 +546,11 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement if (visible) { firePopupMenuWillBecomeVisible(); - Container rootContainer = (Container) SwingUtilities.getRoot(invoker); - Dimension screenSize = getToolkit().getScreenSize(); - - boolean fit = true; - Dimension size = getSize(); - if (size.width == 0 && size.height == 0) - { - size = getPreferredSize(); - setSize(size); - } - if ((size.width > (rootContainer.getWidth() - popupLocation.x)) - || (size.height > (rootContainer.getHeight() - popupLocation.y))) - fit = false; - if (lightWeightPopupEnabled && fit) - popup = new LightWeightPopup(this); - else - { - if (fit) - popup = new MediumWeightPopup(this); - else - { - popup = new HeavyWeightPopup(this); - setLightWeightPopupEnabled(false); - } - } - if (popup instanceof LightWeightPopup - || popup instanceof MediumWeightPopup) - { - JLayeredPane layeredPane; - layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); - Point p = new Point(popupLocation.x, popupLocation.y); - - if (layeredPane.isShowing()) - SwingUtilities.convertPointFromScreen(p, layeredPane); - - if (size.width + popupLocation.x > screenSize.width) - popupLocation.x -= size.width; - if (size.height + popupLocation.y > screenSize.height) - popupLocation.y -= size.height; - - popup.show(p.x, p.y, size.width, size.height); - } - else - { - // Subtract insets of the top-level container if popup menu's - // top-left corner is inside it. - Insets insets = rootContainer.getInsets(); - - if (size.width + popupLocation.x > screenSize.width) - popupLocation.x -= size.width; - if (size.height + popupLocation.y > screenSize.height) - popupLocation.y -= size.height; - - popup.show(popupLocation.x - insets.left, - popupLocation.y - insets.top, - size.width, size.height); - } + + PopupFactory pf = PopupFactory.getSharedInstance(); + popup = pf.getPopup(invoker, this, popupLocationX, popupLocationY); + pack(); + popup.show(); } else { @@ -622,11 +568,11 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement */ public void setLocation(int x, int y) { - if (popupLocation == null) - popupLocation = new Point(); - - popupLocation.x = x; - popupLocation.y = y; + popupLocationX = x; + popupLocationY = y; + // Handle the case when the popup is already showing. In this case we need + // to fetch a new popup from PopupFactory and use this. See the general + // contract of the PopupFactory. } /** @@ -888,158 +834,6 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement } /** - * This interface is used to display menu items of the JPopupMenu - */ - private interface Popup - { - /** - * Displays container on the screen - * - * @param x x-coordinate of popup menu's location on the screen - * @param y y-coordinate of popup menu's location on the screen - * @param width width of the container that is used to display menu - * item's for popup menu - * @param height height of the container that is used to display menu - * item's for popup menu - */ - void show(int x, int y, int width, int height); - - /** - * Hides container used to display popup menu item's from the screen - */ - void hide(); - } - - /** - * This class represents Popup menu that uses light weight container - * to display its contents. - */ - private class LightWeightPopup extends Container implements Popup - { - private Component c; - - /** - * Creates a new LightWeightPopup menu - * - * @param c Container containing menu items - */ - public LightWeightPopup(Container c) - { - this.c = c; - } - - /** - * Displayes lightweight container with menu items to the screen - * - * @param x x-coordinate of lightweight container on the screen - * @param y y-coordinate of lightweight container on the screen - * @param width width of the lightweight container - * @param height height of the lightweight container - */ - public void show(int x, int y, int width, int height) - { - JLayeredPane layeredPane; - layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); - c.setBounds(x, y, width, height); - layeredPane.add(c, JLayeredPane.POPUP_LAYER, 0); - } - - /** - * Hides lightweight container from the screen - */ - public void hide() - { - // FIXME: Right now the lightweight container is removed from JLayered - // pane. It is probably would be better in order to improve performance - // to make the container invisible instead of removing it everytime. - JLayeredPane layeredPane; - layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); - int index = layeredPane.getIndexOf(c); - layeredPane.remove(index); - } - } - - /** - * MediumWeightPopup is an AWT Panel with JPopupMenu's menu items. - * It is used to display JPopupMenu's menu items on the screen - */ - private class MediumWeightPopup extends Panel implements Popup - { - /** - * Creates a new MediumWeightPopup object. - * - * @param c Container with JPopupMenu's menu items - */ - public MediumWeightPopup(Container c) - { - this.add(c); - } - - /** - * Displays AWT Panel with its components on the screen - * - * @param x x-coordinate of the upper-left corner of the panel's - * @param y y-coordinate of the upper-left corner of the panel's - * @param width width of the panel - * @param height height of the panel - */ - public void show(int x, int y, int width, int height) - { - JLayeredPane layeredPane; - layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); - layeredPane.add(this, JLayeredPane.POPUP_LAYER, 0); - this.setBounds(x, y, width, height); - } - - /** - * Hides This panel from the screen - */ - public void hide() - { - // FIXME: Right now the lightweight container is removed from JLayered - // pane. It is probably would be better in order to improve performance - // to make the container invisible instead of removing it everytime. - JLayeredPane layeredPane; - layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); - int index = layeredPane.getIndexOf(this); - layeredPane.remove(index); - } - } - - /** - * HeavyWeightPopup is JDialog that is used to display JPopupMenu menu item's - * on the screen - */ - private class HeavyWeightPopup extends JDialog implements Popup - { - /** - * Creates a new HeavyWeightPopup object. - * - * @param c Container containing menu items - */ - public HeavyWeightPopup(Container c) - { - this.setContentPane(c); - this.setUndecorated(true); - this.getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG); - } - - /** - * Displays JDialog container JPopupMenu's menu items to the screen - * - * @param x x-coordinate of JDialog containing menu items - * @param y y-coordinate of JDialog containing menu items - * @param width width of the JDialog - * @param height height of the JDialog - */ - public void show(int x, int y, int width, int height) - { - this.setBounds(x, y, width, height); - this.show(); - } - } - - /** * This is the separator that can be used in popup menu. */ public static class Separator extends JSeparator @@ -1076,8 +870,9 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement { public void propertyChange(PropertyChangeEvent evt) { - JPopupMenu.this.revalidate(); - JPopupMenu.this.repaint(); + // We used to have a revalidate() and repaint() call here. However I think + // this is not needed. Instead, a new Popup has to be fetched from the + // PopupFactory and used here. } } } diff --git a/javax/swing/Popup.java b/javax/swing/Popup.java index 3b3a5c6e5..5b2615d2f 100644 --- a/javax/swing/Popup.java +++ b/javax/swing/Popup.java @@ -39,6 +39,7 @@ exception statement from your version. */ package javax.swing; import java.awt.Component; +import java.awt.Point; /** @@ -130,6 +131,7 @@ public class Popup */ JWindow window; + private Component contents; /** * Constructs a new <code>JWindowPopup</code> given its owner, @@ -156,10 +158,11 @@ public class Popup /* Checks whether contents is null. */ super(owner, contents, x, y); + this.contents = contents; window = new JWindow(); - window.getRootPane().add(contents); + window.getContentPane().add(contents); window.setLocation(x, y); - window.pack(); + window.setFocusableWindowState(false); } @@ -169,6 +172,7 @@ public class Popup */ public void show() { + window.setSize(contents.getSize()); window.show(); } @@ -187,4 +191,100 @@ public class Popup window.dispose(); } } + + /** + * A popup that displays itself within the JLayeredPane of a JRootPane of + * the containment hierarchy of the owner component. + * + * @author Roman Kennke (kennke@aicas.com) + */ + static class LightweightPopup extends Popup + { + /** + * The owner component for this popup. + */ + Component owner; + + /** + * The contents that should be shown. + */ + Component contents; + + /** + * The X location in screen coordinates. + */ + int x; + + /** + * The Y location in screen coordinates. + */ + int y; + + /** + * The panel that holds the content. + */ + private JPanel panel; + + /** + * Constructs a new <code>LightweightPopup</code> given its owner, + * contents and the screen position where the popup + * will appear. + * + * @param owner the component that should own the popup window; this + * provides the JRootPane in which we place the popup window + * + * @param contents the contents that will be displayed inside + * the <code>Popup</code>. + * + * @param x the horizontal position where the Popup will appear in screen + * coordinates + * + * @param y the vertical position where the Popup will appear in screen + * coordinates + * + * @throws IllegalArgumentException if <code>contents</code> + * is <code>null</code>. + */ + public LightweightPopup(Component owner, Component contents, int x, int y) + { + super(owner, contents, x, y); + this.owner = owner; + this.contents = contents; + this.x = x; + this.y = y; + } + + /** + * Places the popup within the JLayeredPane of the owner component and + * makes it visible. + */ + public void show() + { + JRootPane rootPane = SwingUtilities.getRootPane(owner); + JLayeredPane layeredPane = rootPane.getLayeredPane(); + // We insert a JPanel between the layered pane and the contents so we + // can fiddle with the setLocation() method without disturbing a + // JPopupMenu (which overrides setLocation in an unusual manner). + if (panel == null) + { + panel = new JPanel(); + panel.setLayout(null); + } + panel.add(contents); + panel.setSize(contents.getSize()); + Point layeredPaneLoc = layeredPane.getLocationOnScreen(); + panel.setLocation(x - layeredPaneLoc.x, y - layeredPaneLoc.y); + layeredPane.add(panel, JLayeredPane.POPUP_LAYER); + } + + /** + * Removes the popup from the JLayeredPane thus making it invisible. + */ + public void hide() + { + JRootPane rootPane = SwingUtilities.getRootPane(owner); + JLayeredPane layeredPane = rootPane.getLayeredPane(); + layeredPane.remove(panel); + } + } } diff --git a/javax/swing/PopupFactory.java b/javax/swing/PopupFactory.java index 1e4ad4af1..7bb2529cd 100644 --- a/javax/swing/PopupFactory.java +++ b/javax/swing/PopupFactory.java @@ -39,6 +39,8 @@ exception statement from your version. */ package javax.swing; import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; /** @@ -135,6 +137,30 @@ public class PopupFactory public Popup getPopup(Component owner, Component contents, int x, int y) { - return new Popup.JWindowPopup(owner, contents, x, y); + Popup popup = null; + // By default we enable lightweight popups since they are more efficient + // than heavyweight popups. + boolean lightweightEnabled = true; + // Special case JPopupMenu here, since it supports a lightweightEnabled + // flag that we must respect. + if (contents instanceof JPopupMenu) + { + JPopupMenu menu = (JPopupMenu) contents; + lightweightEnabled = menu.isLightWeightPopupEnabled(); + } + + // If we have a root pane and the contents fits within the root pane and + // lightweight popups are enabled, than we can use a lightweight popup. + JRootPane root = SwingUtilities.getRootPane(owner); + Point rootLoc = root.getLocationOnScreen(); + Dimension contentsSize = contents.getSize(); + Dimension rootSize = root.getSize(); + if (x >= rootLoc.x && y > rootLoc.y + && (x - rootLoc.x) + contentsSize.width < rootSize.width + && (y - rootLoc.y) + contentsSize.height < rootSize.height) + popup = new Popup.LightweightPopup(owner, contents, x, y); + else + popup = new Popup.JWindowPopup(owner, contents, x, y); + return popup; } } diff --git a/javax/swing/plaf/basic/BasicMenuItemUI.java b/javax/swing/plaf/basic/BasicMenuItemUI.java index 883f4f18e..3606100d6 100644 --- a/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -48,8 +48,6 @@ import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; @@ -161,11 +159,6 @@ public class BasicMenuItemUI extends MenuItemUI private String acceleratorDelimiter; /** - * PropertyChangeListener to listen for property changes in the menu item - */ - private PropertyChangeListener propertyChangeListener; - - /** * ItemListener to listen for item changes in the menu item */ private ItemListener itemListener; @@ -188,7 +181,6 @@ public class BasicMenuItemUI extends MenuItemUI mouseInputListener = createMouseInputListener(menuItem); menuDragMouseListener = createMenuDragMouseListener(menuItem); menuKeyListener = createMenuKeyListener(menuItem); - propertyChangeListener = new PropertyChangeHandler(); itemListener = new ItemHandler(); } @@ -439,7 +431,6 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.addMouseMotionListener(mouseInputListener); menuItem.addMenuDragMouseListener(menuDragMouseListener); menuItem.addMenuKeyListener(menuKeyListener); - menuItem.addPropertyChangeListener(propertyChangeListener); menuItem.addItemListener(itemListener); } @@ -728,7 +719,6 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.removeMouseListener(mouseInputListener); menuItem.removeMenuDragMouseListener(menuDragMouseListener); menuItem.removeMenuKeyListener(menuKeyListener); - menuItem.removePropertyChangeListener(propertyChangeListener); menuItem.removeItemListener(itemListener); } @@ -1057,24 +1047,6 @@ public class BasicMenuItemUI extends MenuItemUI // TODO: What should be done here, if anything? } } - - /** - * Helper class that listens for changes to the properties of the {@link - * JMenuItem}. - */ - private class PropertyChangeHandler implements PropertyChangeListener - { - /** - * This method is called when one of the menu item's properties change. - * - * @param evt A {@link PropertyChangeEvent}. - */ - public void propertyChange(PropertyChangeEvent evt) - { - menuItem.revalidate(); - menuItem.repaint(); - } - } /** * Helper class that listens for item changes to the properties of the {@link diff --git a/javax/swing/plaf/basic/BasicMenuUI.java b/javax/swing/plaf/basic/BasicMenuUI.java index 00db5b92f..827cbb0f5 100644 --- a/javax/swing/plaf/basic/BasicMenuUI.java +++ b/javax/swing/plaf/basic/BasicMenuUI.java @@ -47,7 +47,6 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuBar; -import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.LookAndFeel; import javax.swing.MenuSelectionManager; @@ -182,12 +181,6 @@ public class BasicMenuUI extends BasicMenuItemUI */ public Dimension getMaximumSize(JComponent c) { - // If this menu is in a popup menu, treat it like a regular JMenuItem - if (!((JMenu)c).isTopLevelMenu()) - { - JMenuItem menuItem = new JMenuItem(((JMenu)c).getText(), ((JMenu)c).getIcon()); - return menuItem.getMaximumSize(); - } return c.getPreferredSize(); } |