2525
2626package 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+
2844import javafx .beans .InvalidationListener ;
2945import javafx .collections .ListChangeListener ;
3046import javafx .scene .control .FocusModel ;
3450import javafx .scene .control .TreeCell ;
3551import javafx .scene .control .TreeItem ;
3652import javafx .scene .control .TreeView ;
53+ import javafx .scene .control .TreeView .EditEvent ;
3754import 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
4658public 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