assertj / assertj/assertj-swing

Select + drag may fail in JTree in JScrollPane if the row is only partially visible

Ouverte
#33 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

bug Critical import from fest-swing
Langage dominant
Java
Étoiles
121
Forks
52
Métriques de merge des PR
Aucune PR mergée en 30 j

Description

Issue by Per Rovegård from Thu, 20 Jan 2011 02:34:16 -0600
Originally opened as http://jira.codehaus.org/browse/FEST-422


Description

I have created a small test program where a JTree is put in a JScrollPane. The tree has a root and a child with a really, really long name. The scroll pane is placed in a JSplitPane with the divider location set so that the row with the really long name is only partially visible. The other split pane component is a label.

The tree supports drag and drop with printouts to the console, and the label prints a message on the console if a mouse button is pressed.

When the test program runs, notice that selectRow fails, as does drag. When these calls are made, the mouse click occurs on the label instead, as can be seen on the console.

Test program

import static org.fest.swing.timing.Pause.pause;

import java.awt.Component;
import java.awt.datatransfer.;
import java.awt.event.
;

import javax.swing.;
import javax.swing.tree.
;

import org.fest.swing.core.*;
import org.fest.swing.finder.WindowFinder;
import org.fest.swing.fixture.FrameFixture;

public class SelectAndDnDTest
{
public static void main(String[] args)
{
Robot robot = BasicRobot.robotWithNewAwtHierarchy();

    SwingUtilities.invokeLater(<span class="code-keyword">new</span> <span class="code-object">Runnable</span>()
    {
        @Override
        <span class="code-keyword">public</span> void run()
        {
            JSplitPane pane = <span class="code-keyword">new</span> JSplitPane();
            pane.setDividerLocation(150);

            JLabel label = <span class="code-keyword">new</span> JLabel(<span class="code-quote">"Test"</span>);
            label.addMouseListener(<span class="code-keyword">new</span> MouseAdapter()
            {
                @Override
                <span class="code-keyword">public</span> void mousePressed(MouseEvent e)
                {
                    <span class="code-object">System</span>.out.println(<span class="code-quote">"Mouse press on label"</span>);
                }
            });

            pane.setLeftComponent(<span class="code-keyword">new</span> JScrollPane(createTree()));
            pane.setRightComponent(label);

            JFrame frame = <span class="code-keyword">new</span> JFrame(<span class="code-quote">"Test"</span>);
            frame.setSize(640, 480);
            frame.getContentPane().add(pane);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.setVisible(<span class="code-keyword">true</span>);
        }
    });

    FrameFixture window = WindowFinder.findFrame(JFrame.class).using(robot);

    pause(1000);
    window.tree().selectRow(1);
    pause(1000);
    window.tree().drag(1);
    pause(1000);
    window.tree().drop(0);

    robot.cleanUp();
}

<span class="code-keyword">protected</span> <span class="code-keyword">static</span> Component createTree()
{
    <span class="code-keyword">final</span> JTree tree = <span class="code-keyword">new</span> JTree();
    tree.setDragEnabled(<span class="code-keyword">true</span>);
    tree.setDropMode(DropMode.ON);
    tree.setTransferHandler(<span class="code-keyword">new</span> TransferHandler()
    {
        @Override
        <span class="code-keyword">public</span> <span class="code-object">int</span> getSourceActions(JComponent c)
        {
            <span class="code-keyword">return</span> COPY;
        }

        @Override
        <span class="code-keyword">public</span> <span class="code-object">boolean</span> importData(TransferSupport support)
        {
            Transferable t = support.getTransferable();
            <span class="code-keyword">try</span>
            {
                <span class="code-object">String</span> s = (<span class="code-object">String</span>) t.getTransferData(DataFlavor.stringFlavor);
                DropLocation loc = support.getDropLocation();
                TreePath dropPath = tree.getPathForLocation(loc.getDropPoint().x, loc.getDropPoint().y);

                <span class="code-object">System</span>.out.println(<span class="code-quote">"Dragged "</span> + s + <span class="code-quote">" and dropped on "</span> + dropPath);
            }
            <span class="code-keyword">catch</span> (Exception ex)
            {
                ex.printStackTrace(<span class="code-object">System</span>.err);
                <span class="code-keyword">return</span> <span class="code-keyword">false</span>;
            }
            <span class="code-keyword">return</span> <span class="code-keyword">true</span>;
        }

        @Override
        <span class="code-keyword">public</span> <span class="code-object">boolean</span> canImport(TransferSupport support)
        {
            <span class="code-keyword">return</span> <span class="code-keyword">true</span>;
        }

        @Override
        <span class="code-keyword">protected</span> Transferable createTransferable(JComponent c)
        {
            TreePath path = tree.getSelectionPath();
            <span class="code-keyword">return</span> <span class="code-keyword">new</span> StringSelection(path.toString());
        }
    });

    DefaultMutableTreeNode root = <span class="code-keyword">new</span> DefaultMutableTreeNode(<span class="code-quote">"Root"</span>, <span class="code-keyword">true</span>);
    TreeModel model = <span class="code-keyword">new</span> DefaultTreeModel(root);

    root.add(<span class="code-keyword">new</span> DefaultMutableTreeNode(
            <span class="code-quote">"Child with a really, really <span class="code-object">long</span> name that makes the center point move to the right very much."</span>));

    tree.setModel(model);

    <span class="code-keyword">return</span> tree;
}

}

Actual printout

Mouse press on label
Mouse press on label
Mouse press on label

Expected printout

Dragged [Root, Child with a really, really long name that makes the center point move to the right very much.] and dropped on [Root]

Fix

The problem seems to be in JTreeLocation.rowBoundsAndCoordinates. Although the JavaDoc comment says "Returns the bounds and visible coordinates of the given row", the method fails to take into account the visible rectangle of the tree. Suggested fix:

  @RunsInCurrentThread
  public Pair<Rectangle, Point> rowBoundsAndCoordinates(JTree tree, int row) {
    Rectangle rowBounds = tree.getRowBounds(validIndex(tree, row));
    // BEGIN FIX
    Rectangle visibleRect = tree.getVisibleRect();
    rowBounds = rowBounds.intersection(visibleRect);
    // END FIX
    if (rowBounds != null) return new Pair<Rectangle, Point>(rowBounds, pointAt(rowBounds));
    throw new LocationUnavailableException(concat("The tree row ", row, " is not visible"));
  }

votes (original issue): 0
watches (original issue): 0

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par JTreeLocation.rowBoundsAndCoordinates et exécutez le programme SelectAndDnDTest fourni avec la ligne d’arbre partiellement visible. Vérifiez le calcul de la position par rapport à la zone visible de l’arbre ; c’est terminé lorsque la sélection et le glisser-déposer ciblent le JTree et que la sortie attendue du glisser-déposer est produite au lieu de pressions de souris sur l’étiquette.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
java
Domaine
desktop, testing-qa
Type d'issue
Bug
Difficulté
2/5
Temps estimé
1-3 heures
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
43/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.