After talking to rkennke, here is an alternate implementation to fix the
same bug, which does not involve removing and re-adding listeners, nor
consuming the mouseclick event (since this breaks other functionality).
Regards,
Francis
2006-06-13 Francis Kung <[EMAIL PROTECTED]>
* javax/swing/plaf/basic/BasicComboPopup.java:
(setVisible): new method
* javax/swing/plaf/basic/BasicLookAndFeel.java:
(PopupHelper.mousePressed): do not consume event; instead,
check a client property to determine whether to close the popup
On Mon, 2006-06-12 at 14:09 -0400, Francis Kung wrote:
> Hi,
>
> Please find attached a patch to fix mouseclick actions in the JComboBox.
>
> Previously, if you clicked on the combo box button while the popup menu
> was already open, it would close and immediately re-open the popup; this
> was caused by two listeners both catching the mouseclick and both
> toggling the menu (ie toggled off, then immediately toggled back on).
> This patch disables one of the listeners while the popup menu is
> visible.
>
> Unfortunately, the fix isn't evident at the moment due to a new bug in
> JComponent introduced by the VolatileImage patch, but has been tested
> against pre-VolatileImage code. Not sure how to write a mauve test,
> since it must simulate a mouseclick on a specific component's
> location...
>
> Regards,
> Francis
>
> 2006-06-12 Francis Kung <[EMAIL PROTECTED]>
>
> * javax/swing/plaf/basic/BasicComboPopup.java:
> (setVisible): new method
>
Index: javax/swing/plaf/basic/BasicComboPopup.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicComboPopup.java,v
retrieving revision 1.19
diff -u -r1.19 BasicComboPopup.java
--- BasicComboPopup.java 13 Jun 2006 09:28:57 -0000 1.19
+++ BasicComboPopup.java 13 Jun 2006 18:00:52 -0000
@@ -223,6 +223,43 @@
comboBox.repaint();
}
+ /**
+ * Sets visibility property of this popup menu. If the property is set to
+ * true then popup menu will be dispayed and popup menu will hide itself if
+ * visible property is set to false.
+ *
+ * @param visible true if popup menu will become visible and false
+ * otherwise.
+ */
+ public void setVisible(final boolean visible)
+ {
+ System.out.println("setting visible to " + visible);
+ super.setVisible(visible);
+
+ // Set or update a client property so that the menu manager
+ // (called from BasicLookAndFeel) doesn't also try to close the popup menu
+ //
+ // Properties must be updated in both the combobox itself and the button
+ // due to the basic look and feel implementation (only the button is used
+ // in the metal look and feel)
+ if (visible)
+ {
+ comboBox.putClientProperty("keepPopupMenu", new Boolean(true));
+ ((BasicComboBoxUI) comboBox.getUI()).arrowButton.putClientProperty(
+ "keepPopupMenu",
+ new Boolean(
+ true));
+ }
+ else
+ {
+ comboBox.putClientProperty("keepPopupMenu", new Boolean(false));
+ ((BasicComboBoxUI) comboBox.getUI()).arrowButton.putClientProperty(
+ "keepPopupMenu",
+ new Boolean(
+ false));
+ }
+ }
+
/**
* Return list cointaining JComboBox's items
*
Index: javax/swing/plaf/basic/BasicLookAndFeel.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java,v
retrieving revision 1.94
diff -u -r1.94 BasicLookAndFeel.java
--- BasicLookAndFeel.java 13 Jun 2006 12:37:53 -0000 1.94
+++ BasicLookAndFeel.java 13 Jun 2006 18:00:53 -0000
@@ -64,6 +64,7 @@
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
+import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.MenuSelectionManager;
@@ -128,14 +129,18 @@
Component target = ev.getComponent();
if (target instanceof Container)
target = ((Container) target).findComponentAt(ev.getPoint());
- if (m.getSelectedPath().length > 0
- && ! m.isComponentPartOfCurrentMenu(target))
- {
- m.clearSelectedPath();
- ev.consume();
- }
- }
+
+ // Special check for components that will close their own menus
+ // (ie, combo box popup menus when you click on the combo box button)
+ boolean ownButton = false;
+ if (target instanceof JComponent
+ && ((JComponent)target).getClientProperty("keepPopupMenu") != null
+ && ((JComponent)target).getClientProperty("keepPopupMenu").equals(new Boolean(true)))
+ ownButton = true;
+ if (! m.isComponentPartOfCurrentMenu(target) && (! ownButton))
+ m.clearSelectedPath();
+ }
}
/**