Skip to content

Commit e6cf1df

Browse files
author
Jeanette Winzenburg
committed
8267094: TreeCell: cancelEvent must return correct editing location
Reviewed-by: aghaisas
1 parent ca25036 commit e6cf1df

File tree

3 files changed

+175
-25
lines changed

3 files changed

+175
-25
lines changed

modules/javafx.controls/src/main/java/javafx/scene/control/TreeCell.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ public String getName() {
351351
* Public API *
352352
* *
353353
**************************************************************************/
354+
// treeItem at time of startEdit - fix for JDK-8267094
355+
private TreeItem<T> treeItemAtStartEdit;
354356

355357
/** {@inheritDoc} */
356358
@Override public void startEdit() {
@@ -384,6 +386,7 @@ public String getName() {
384386

385387
tree.requestFocus();
386388
}
389+
treeItemAtStartEdit = getTreeItem();
387390
}
388391

389392
/** {@inheritDoc} */
@@ -424,6 +427,7 @@ public String getName() {
424427
// It would be rude of us to request it back again.
425428
ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(tree);
426429
}
430+
treeItemAtStartEdit = null;
427431
}
428432

429433
/** {@inheritDoc} */
@@ -435,6 +439,9 @@ public String getName() {
435439
super.cancelEdit();
436440

437441
if (tree != null) {
442+
TreeItem<T> editingItem = treeItemAtStartEdit;
443+
T value = editingItem != null ? editingItem.getValue() : null;
444+
438445
// reset the editing index on the TreeView
439446
if (updateEditingIndex) tree.edit(null);
440447

@@ -446,10 +453,11 @@ public String getName() {
446453

447454
tree.fireEvent(new TreeView.EditEvent<T>(tree,
448455
TreeView.<T>editCancelEvent(),
449-
getTreeItem(),
450-
getItem(),
456+
editingItem,
457+
value,
451458
null));
452459
}
460+
treeItemAtStartEdit = null;
453461
}
454462

455463
/** {@inheritDoc} */

modules/javafx.controls/src/test/java/test/javafx/scene/control/TreeCellEditingTest.java

-16
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import java.util.List;
3232

3333
import org.junit.Before;
34-
import org.junit.Ignore;
3534
import org.junit.Test;
3635
import org.junit.runner.RunWith;
3736
import org.junit.runners.Parameterized;
@@ -85,21 +84,6 @@ public void testCancelOffEditingIndex() {
8584
assertEquals("sanity: tree editing unchanged", editingItem, tree.getEditingItem());
8685
assertEquals("sanity: editingIndex unchanged", editingIndex, tree.getRow(editingItem));
8786
assertEquals("cell must have fired edit cancel", 1, events.size());
88-
}
89-
90-
/**
91-
* Extracted from testCancelOffEditingIndex to formally ignore
92-
* FIXME: move the assert to the other method, once the issue is solved
93-
*/
94-
@Ignore("JDK-8267094")
95-
@Test
96-
public void testCancelOffEditingIndexEventIndex() {
97-
cell.updateIndex(editingIndex);
98-
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
99-
tree.edit(editingItem);
100-
List<EditEvent<String>> events = new ArrayList<>();
101-
tree.setOnEditCancel(events::add);
102-
cell.updateIndex(cellIndex);
10387
assertEquals("cancel on updateIndex from " + editingIndex + " to " + cellIndex + "\n ",
10488
editingItem, events.get(0).getTreeItem());
10589
}

modules/javafx.controls/src/test/java/test/javafx/scene/control/TreeCellTest.java

+165-7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@
2525

2626
package test.javafx.scene.control;
2727

28+
import java.lang.ref.WeakReference;
29+
import java.util.ArrayList;
30+
import java.util.List;
31+
32+
import org.junit.After;
33+
import org.junit.Before;
34+
import org.junit.Ignore;
35+
import org.junit.Test;
36+
37+
import com.sun.javafx.tk.Toolkit;
38+
39+
import static javafx.scene.control.ControlShim.*;
40+
import static org.junit.Assert.*;
41+
import static test.com.sun.javafx.scene.control.infrastructure.ControlSkinFactory.*;
42+
import static test.com.sun.javafx.scene.control.infrastructure.ControlTestUtils.*;
43+
2844
import javafx.beans.InvalidationListener;
2945
import javafx.collections.ListChangeListener;
3046
import javafx.scene.control.FocusModel;
@@ -34,14 +50,10 @@
3450
import javafx.scene.control.TreeCell;
3551
import javafx.scene.control.TreeItem;
3652
import javafx.scene.control.TreeView;
53+
import javafx.scene.control.TreeView.EditEvent;
3754
import javafx.scene.control.skin.TreeCellSkin;
38-
import org.junit.Before;
39-
import org.junit.Ignore;
40-
import org.junit.Test;
41-
42-
import static javafx.scene.control.ControlShim.*;
43-
import static test.com.sun.javafx.scene.control.infrastructure.ControlTestUtils.*;
44-
import static org.junit.Assert.*;
55+
import test.com.sun.javafx.scene.control.infrastructure.StageLoader;
56+
import test.com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
4557

4658
public class TreeCellTest {
4759
private TreeCell<String> cell;
@@ -56,6 +68,7 @@ public class TreeCellTest {
5668
private TreeItem<String> apples;
5769
private TreeItem<String> oranges;
5870
private TreeItem<String> pears;
71+
private StageLoader stageLoader;
5972

6073
@Before public void setup() {
6174
cell = new TreeCell<String>();
@@ -70,6 +83,11 @@ public class TreeCellTest {
7083
root.setExpanded(true);
7184
}
7285

86+
@After
87+
public void cleanup() {
88+
if (stageLoader != null) stageLoader.dispose();
89+
}
90+
7391
/*********************************************************************
7492
* Tests for the constructors *
7593
********************************************************************/
@@ -686,6 +704,146 @@ public class TreeCellTest {
686704
assertFalse(cell.isEditing());
687705
}
688706

707+
@Test
708+
public void testEditCancelEventAfterCancelOnCell() {
709+
tree.setEditable(true);
710+
cell.updateTreeView(tree);
711+
int editingIndex = 1;
712+
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
713+
cell.updateIndex(editingIndex);
714+
tree.edit(editingItem);
715+
List<EditEvent<String>> events = new ArrayList<>();
716+
tree.setOnEditCancel(events::add);
717+
cell.cancelEdit();
718+
assertEquals(1, events.size());
719+
assertEquals("editing location of cancel event", editingItem, events.get(0).getTreeItem());
720+
}
721+
722+
@Test
723+
public void testEditCancelEventAfterCancelOnTree() {
724+
tree.setEditable(true);
725+
cell.updateTreeView(tree);
726+
int editingIndex = 1;
727+
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
728+
cell.updateIndex(editingIndex);
729+
tree.edit(editingItem);
730+
List<EditEvent<String>> events = new ArrayList<>();
731+
tree.setOnEditCancel(events::add);
732+
tree.edit(null);
733+
assertEquals(1, events.size());
734+
assertEquals("editing location of cancel event", editingItem, events.get(0).getTreeItem());
735+
}
736+
737+
@Test
738+
public void testEditCancelEventAfterCellReuse() {
739+
tree.setEditable(true);
740+
cell.updateTreeView(tree);
741+
int editingIndex = 1;
742+
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
743+
cell.updateIndex(editingIndex);
744+
tree.edit(editingItem);
745+
List<EditEvent<String>> events = new ArrayList<>();
746+
tree.setOnEditCancel(events::add);
747+
cell.updateIndex(0);
748+
assertEquals(1, events.size());
749+
assertEquals("editing location of cancel event", editingItem, events.get(0).getTreeItem());
750+
}
751+
752+
@Test
753+
public void testEditCancelEventAfterCollapse() {
754+
stageLoader = new StageLoader(tree);
755+
tree.setEditable(true);
756+
int editingIndex = 1;
757+
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
758+
tree.edit(editingItem);
759+
List<EditEvent<String>> events = new ArrayList<>();
760+
tree.setOnEditCancel(events::add);
761+
root.setExpanded(false);
762+
Toolkit.getToolkit().firePulse();
763+
assertEquals(1, events.size());
764+
assertEquals("editing location of cancel event", editingItem, events.get(0).getTreeItem());
765+
}
766+
767+
@Test
768+
public void testEditCancelEventAfterModifyItems() {
769+
stageLoader = new StageLoader(tree);
770+
tree.setEditable(true);
771+
int editingIndex = 2;
772+
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
773+
tree.edit(editingItem);
774+
List<EditEvent<String>> events = new ArrayList<>();
775+
tree.setOnEditCancel(events::add);
776+
root.getChildren().add(0, new TreeItem<>("added"));
777+
Toolkit.getToolkit().firePulse();
778+
assertEquals(1, events.size());
779+
assertEquals("editing location of cancel event", editingItem, events.get(0).getTreeItem());
780+
}
781+
782+
/**
783+
* Test that removing the editing item implicitly cancels an ongoing
784+
* edit and fires a correct cancel event.
785+
*/
786+
@Test
787+
public void testEditCancelEventAfterRemoveEditingItem() {
788+
stageLoader = new StageLoader(tree);
789+
tree.setEditable(true);
790+
int editingIndex = 2;
791+
TreeItem<String> editingItem = tree.getTreeItem(editingIndex);
792+
tree.edit(editingItem);
793+
List<EditEvent<String>> events = new ArrayList<>();
794+
tree.setOnEditCancel(events::add);
795+
root.getChildren().remove(editingItem);
796+
Toolkit.getToolkit().firePulse();
797+
assertNull("removing item must cancel edit on tree", tree.getEditingItem());
798+
assertEquals(1, events.size());
799+
assertEquals("editing location of cancel event", editingItem, events.get(0).getTreeItem());
800+
}
801+
802+
/**
803+
* Test that removing the editing item does not cause a memory leak.
804+
*/
805+
@Test
806+
public void testEditCancelMemoryLeakAfterRemoveEditingItem() {
807+
stageLoader = new StageLoader(tree);
808+
tree.setEditable(true);
809+
// the item to test for being gc'ed
810+
TreeItem<String> editingItem = new TreeItem<>("added");
811+
WeakReference<TreeItem<?>> itemRef = new WeakReference<>(editingItem);
812+
root.getChildren().add(0, editingItem);
813+
Toolkit.getToolkit().firePulse();
814+
tree.edit(editingItem);
815+
root.getChildren().remove(editingItem);
816+
Toolkit.getToolkit().firePulse();
817+
assertNull("removing item must cancel edit on tree", tree.getEditingItem());
818+
editingItem = null;
819+
attemptGC(itemRef);
820+
assertEquals("treeItem must be gc'ed", null, itemRef.get());
821+
}
822+
823+
/**
824+
* Test that removing a committed editing item does not cause a memory leak.
825+
*/
826+
@Test
827+
public void testEditCommitMemoryLeakAfterRemoveEditingItem() {
828+
stageLoader = new StageLoader(tree);
829+
tree.setEditable(true);
830+
// the item to test for being gc'ed
831+
TreeItem<String> editingItem = new TreeItem<>("added");
832+
WeakReference<TreeItem<?>> itemRef = new WeakReference<>(editingItem);
833+
root.getChildren().add(0, editingItem);
834+
int editingIndex = tree.getRow(editingItem);
835+
Toolkit.getToolkit().firePulse();
836+
tree.edit(editingItem);
837+
TreeCell<String> editingCell = (TreeCell<String>) VirtualFlowTestUtils.getCell(tree, editingIndex);
838+
editingCell.commitEdit("added changed");
839+
root.getChildren().remove(editingItem);
840+
Toolkit.getToolkit().firePulse();
841+
assertNull("removing item must cancel edit on tree", tree.getEditingItem());
842+
editingItem = null;
843+
attemptGC(itemRef);
844+
assertEquals("treeItem must be gc'ed", null, itemRef.get());
845+
}
846+
689847
// When the tree view item's change and affects a cell that is editing, then what?
690848
// When the tree cell's index is changed while it is editing, then what?
691849

0 commit comments

Comments
 (0)