United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4548788 JTree should toggle for all even-numbered clicks
JDK-4548788 : JTree should toggle for all even-numbered clicks

Details
Type:
Enhancement
Submit Date:
2001-12-05
Status:
Resolved
Updated Date:
2005-01-15
Project Name:
JDK
Resolved Date:
2005-01-15
Component:
client-libs
OS:
generic
Sub-Component:
javax.swing
CPU:
generic
Priority:
P5
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:

Related Reports
Backport:
Backport:

Sub Tasks

Description

Name: gm110360			Date: 12/05/2001


java version "1.4.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b88)
Java HotSpot(TM) Client VM (build 1.4.0-rc-b88, mixed mode)

In Windows, users can setup the minimal interval between consecutive mouse
clickes for those two clicks to be recognized as double click. Also in
Windows, it's permissible to move mouse position slightly to some amount
between two clicks constituting a double click.

As far as I know, there's no clear indication in Java API documentation about
how a programmer benefits from the platform specific double click detection.
There should be a clear definition or a facility to capture this platform
(maybe) platform specific events.

I'm using mouse pressed / released instead of mouse clicked to detect double
clicks since the current AWT implementation seems to convert Windows double
click messages to mouse pressed / released events with click count of 2.
(Review ID: 136785) 
======================================================================

Name: gm110360			Date: 12/05/2001


java version "1.4.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b88)
Java HotSpot(TM) Client VM (build 1.4.0-rc-b88, mixed mode)

Launch SwingSet2 and choose tree tab.
When we double click on a node with children, it toggles between expanded and
collapse states. In Windows, if we click more than twice without moving the
mouse points, then the node keeps toggled. But in Swing, the toggling happens
only once.

This is caused by the difference in the recognization of double clicks in AWT
and Windows. Windows detects double clicks done with slight mouse movement
between two subsequent clicks, but Swing don't.

Even though I report this as a bug specific to JTree, this discrepancy in
double click detection is sometimes very annoying in most cases. So I usually
utilizes a undocumented behavior that may be specific to the current AWT
implementation, that is, I'm detecting double clicks by capturing mouse
released or pressed events instead of mouse clicked, since the current AWT
implementation takes Windows double click messages and transforms them to
mouse released and pressed events with click count of 2.
(Review ID: 136782)
======================================================================

                                    

Comments
SUGGESTED FIX

------- BasicTreeUI.java -------
*** /tmp/sccs.3eaOUs    Fri Dec  7 16:33:06 2001
--- BasicTreeUI.java    Fri Dec  7 16:33:02 2001
***************
*** 2141,2147 ****
        if(clickCount <= 0) {
            return false;
        }
!       return (event.getClickCount() == clickCount);
      }
  
      /**
--- 2141,2147 ----
        if(clickCount <= 0) {
            return false;
        }
!       return (event.getClickCount() % clickCount == 0);
      }
  
      /**
                                     
2004-09-24
WORK AROUND



Name: gm110360			Date: 12/05/2001


Use mouse pressed / released instead of mouse clicked to detect double clicks.
This works at least on Windows.
======================================================================

You can also install your own TreeUI that responds to all even-numbered clicks.
###@###.### 2001-12-07

A simpler approach is set the toggle click count to a negative number, say -1, and install a MouseListener that handles the actual toggling.  Here's a rough cut at it:

        tree.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    if (e.getModifiers() == InputEvent.BUTTON1_MASK &&
                              e.getClickCount() > 0 &&
                              e.getClickCount() % 2 == 0) {
                        int row = tree.getRowForLocation(e.getX(), e.getY());
                        if (row != -1) {
                            if (tree.isExpanded(row)) {
                                tree.collapseRow(row);
                            }
                            else {
                                tree.expandRow(row);
                            }
                        }
                    }
                }

            });

###@###.### 2005-1-03 18:39:19 GMT
                                     
2005-01-03
EVALUATION

The getClickCount() method in MouseEvent is more flexible than a double-click event would be, because it allows detection of double, triple, or any tuple click.

As the code below demonstrates, it is possible to get the behavior you expect using mouseClicked() by checking that the click count is divisible by 2:

// Test that checking for an event number of clicks in click count will
// correctly toggle a Component

import java.awt.*;
import java.awt.event.*;

public class BClickCountTest extends Frame implements MouseListener {
    public BClickCountTest () {
        addMouseListener(this);
        setSize(400, 400);
    }

    public static void main(String[] args) {
        BClickCountTest t = new BClickCountTest();
        t.show();
    }

    public void toggle() {
        if (getBackground() == Color.red) {
            setBackground(Color.green);
        } else {
            setBackground(Color.red);
        }
    }

    public void mouseClicked (MouseEvent e){
        System.out.print("clickcount = " + e.getClickCount());
        if (e.getClickCount() % 2 == 0) {
            System.out.println(", TOGGLE");
            toggle();
        } else {
            System.out.println("");
        }
    }
    public void mousePressed(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
}

When the mouse is double-(or quadruple-, or sextuple-, or octuple-, etc)clicked, the Frame's background color is toggled between red and green.  This behaves in a similar fashion to the windows Explorer, in that each even-numbered click causes a toggle.  You don't need to use mousePressed()/mouseReleased() for this.

The reason that JTree doesn't behave this way is that BasicTreeUI checks if the number of clicks in the MouseEvent is equal to the desired number of clicks, not modulo:

    protected boolean isToggleEvent(MouseEvent event) {
	if(!SwingUtilities.isLeftMouseButton(event)) {
	    return false;
	}
	int           clickCount = tree.getToggleClickCount();

	if(clickCount <= 0) {
	    return false;
	}
-->	return (event.getClickCount() == clickCount);
    }

You should be able to install your own TreeUI that uses your own isToggleEvent() which responds to every even-numbered click.  However, the Windows Look & Feel should also behave this way.  I'm going to pass this to Swing to fix that aspect.
###@###.### 2001-12-07

Interestingly Windows explorer does not exhibit the behavior that a click count % 2 is equivalent to a toggle, where as the tree in regedit does.
I've provided a workaround that will provide windows behavior.
###@###.### 2005-1-03 18:39:19 GMT

Windows doesn't appear to offer up a click count, only single and double click events.  What Java generates as a quarduple click is equivalent to two double clicks on windows.  So, tree should be using % here (at least for windows).
The change will offer a new ui property, "Tree.useEqualsForToggle", that if flase will use %.  The default is true, so that == is used.
###@###.### 2005-1-06 17:37:42 GMT

After talking with Shannon we decided to make the change for all look and feels and remove the property.
###@###.### 2005-1-06 19:22:10 GMT
                                     
2005-01-06



Hardware and Software, Engineered to Work Together