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();
+    }
   }
 
   /**

Reply via email to