25
25
26
26
package test .javafx .scene .control ;
27
27
28
- import javafx .scene .control .TableRow ;
29
- import javafx .scene .control .TreeTableRow ;
30
- import javafx .scene .control .skin .TableCellSkin ;
31
- import test .com .sun .javafx .scene .control .infrastructure .StageLoader ;
32
- import test .com .sun .javafx .scene .control .infrastructure .VirtualFlowTestUtils ;
33
- import javafx .collections .FXCollections ;
34
- import javafx .collections .ObservableList ;
35
- import javafx .scene .control .TableCell ;
36
- import javafx .scene .control .TableCellShim ;
37
- import javafx .scene .control .TableColumn ;
38
- import javafx .scene .control .TableView ;
28
+ import java .lang .ref .WeakReference ;
29
+ import java .util .ArrayList ;
30
+ import java .util .List ;
39
31
40
32
import org .junit .After ;
41
33
import org .junit .Before ;
42
34
import org .junit .Test ;
43
35
44
- import static test .com .sun .javafx .scene .control .infrastructure .ControlTestUtils .assertStyleClassContains ;
36
+ import com .sun .javafx .tk .Toolkit ;
37
+
45
38
import static org .junit .Assert .*;
46
- import static org .junit .Assert .assertEquals ;
39
+ import static test .com .sun .javafx .scene .control .infrastructure .ControlTestUtils .*;
40
+ import static test .com .sun .javafx .scene .control .infrastructure .ControlSkinFactory .*;
41
+
42
+ import javafx .beans .property .SimpleObjectProperty ;
43
+ import javafx .collections .FXCollections ;
44
+ import javafx .collections .ObservableList ;
45
+ import javafx .scene .control .MenuItem ;
46
+ import javafx .scene .control .TableCell ;
47
+ import javafx .scene .control .TableCellShim ;
48
+ import javafx .scene .control .TableColumn ;
49
+ import javafx .scene .control .TableColumn .CellEditEvent ;
50
+ import javafx .scene .control .TablePosition ;
51
+ import javafx .scene .control .TableRow ;
52
+ import javafx .scene .control .TableView ;
53
+ import javafx .scene .control .skin .TableCellSkin ;
54
+ import test .com .sun .javafx .scene .control .infrastructure .StageLoader ;
55
+ import test .com .sun .javafx .scene .control .infrastructure .VirtualFlowTestUtils ;
47
56
48
57
/**
49
58
*/
50
59
public class TableCellTest {
51
60
private TableCell <String ,String > cell ;
52
61
private TableView <String > table ;
62
+ private TableColumn <String , String > editingColumn ;
53
63
private TableRow <String > row ;
54
64
private ObservableList <String > model ;
65
+ private StageLoader stageLoader ;
55
66
56
67
@ Before public void setup () {
57
68
Thread .currentThread ().setUncaughtExceptionHandler ((thread , throwable ) -> {
@@ -65,12 +76,14 @@ public class TableCellTest {
65
76
cell = new TableCell <String ,String >();
66
77
model = FXCollections .observableArrayList ("Four" , "Five" , "Fear" ); // "Flop", "Food", "Fizz"
67
78
table = new TableView <String >(model );
79
+ editingColumn = new TableColumn <>("TEST" );
68
80
69
81
row = new TableRow <>();
70
82
}
71
83
72
84
@ After
73
85
public void cleanup () {
86
+ if (stageLoader != null ) stageLoader .dispose ();
74
87
Thread .currentThread ().setUncaughtExceptionHandler (null );
75
88
}
76
89
@@ -402,6 +415,120 @@ public void testCellInUneditableColumnIsNotEditable() {
402
415
assertFalse (cell .isEditing ());
403
416
}
404
417
418
+ /**
419
+ * Basic config of table-/cell to allow testing of editEvents:
420
+ * table is editable, has editingColumn and cell is configured with table and column.
421
+ */
422
+ private void setupForEditing () {
423
+ table .setEditable (true );
424
+ table .getColumns ().add (editingColumn );
425
+ // FIXME: default cell (of tableColumn) needs not-null value for firing cancel
426
+ editingColumn .setCellValueFactory (cc -> new SimpleObjectProperty <>("" ));
427
+
428
+ cell .updateTableView (table );
429
+ cell .updateTableColumn (editingColumn );
430
+ }
431
+
432
+ @ Test
433
+ public void testEditCancelEventAfterCancelOnCell () {
434
+ setupForEditing ();
435
+ int editingIndex = 1 ;
436
+ cell .updateIndex (editingIndex );
437
+ table .edit (editingIndex , editingColumn );
438
+ TablePosition <?, ?> editingPosition = table .getEditingCell ();
439
+ List <CellEditEvent <?, ?>> events = new ArrayList <>();
440
+ editingColumn .setOnEditCancel (events ::add );
441
+ cell .cancelEdit ();
442
+ assertEquals ("column must have received editCancel" , 1 , events .size ());
443
+ assertEquals ("editing location of cancel event" , editingPosition , events .get (0 ).getTablePosition ());
444
+ }
445
+
446
+ @ Test
447
+ public void testEditCancelEventAfterCancelOnTable () {
448
+ setupForEditing ();
449
+ int editingIndex = 1 ;
450
+ cell .updateIndex (editingIndex );
451
+ table .edit (editingIndex , editingColumn );
452
+ TablePosition <?, ?> editingPosition = table .getEditingCell ();
453
+ List <CellEditEvent <?, ?>> events = new ArrayList <>();
454
+ editingColumn .setOnEditCancel (events ::add );
455
+ table .edit (-1 , null );
456
+ assertEquals ("column must have received editCancel" , 1 , events .size ());
457
+ assertEquals ("editing location of cancel event" , editingPosition , events .get (0 ).getTablePosition ());
458
+ }
459
+
460
+ @ Test
461
+ public void testEditCancelEventAfterCellReuse () {
462
+ setupForEditing ();
463
+ int editingIndex = 1 ;
464
+ cell .updateIndex (editingIndex );
465
+ table .edit (editingIndex , editingColumn );
466
+ TablePosition <?, ?> editingPosition = table .getEditingCell ();
467
+ List <CellEditEvent <?, ?>> events = new ArrayList <>();
468
+ editingColumn .setOnEditCancel (events ::add );
469
+ cell .updateIndex (0 );
470
+ assertEquals ("column must have received editCancel" , 1 , events .size ());
471
+ assertEquals ("editing location of cancel event" , editingPosition , events .get (0 ).getTablePosition ());
472
+ }
473
+
474
+ @ Test
475
+ public void testEditCancelEventAfterModifyItems () {
476
+ setupForEditing ();
477
+ stageLoader = new StageLoader (table );
478
+ int editingIndex = 1 ;
479
+ table .edit (editingIndex , editingColumn );
480
+ TablePosition <?, ?> editingPosition = table .getEditingCell ();
481
+ List <CellEditEvent <?, ?>> events = new ArrayList <>();
482
+ editingColumn .setOnEditCancel (events ::add );
483
+ table .getItems ().add (0 , "added" );
484
+ Toolkit .getToolkit ().firePulse ();
485
+ assertEquals ("column must have received editCancel" , 1 , events .size ());
486
+ assertEquals ("editing location of cancel event" , editingPosition , events .get (0 ).getTablePosition ());
487
+ }
488
+
489
+ /**
490
+ * Test that removing the editing item implicitly cancels an ongoing
491
+ * edit and fires a correct cancel event.
492
+ */
493
+ @ Test
494
+ public void testEditCancelEventAfterRemoveEditingItem () {
495
+ setupForEditing ();
496
+ stageLoader = new StageLoader (table );
497
+ int editingIndex = 1 ;
498
+ table .edit (editingIndex , editingColumn );
499
+ TablePosition <?, ?> editingPosition = table .getEditingCell ();
500
+ List <CellEditEvent <?, ?>> events = new ArrayList <>();
501
+ editingColumn .setOnEditCancel (events ::add );
502
+ table .getItems ().remove (editingIndex );
503
+ Toolkit .getToolkit ().firePulse ();
504
+ assertNull ("sanity: editing terminated on items modification" , table .getEditingCell ());
505
+ assertEquals ("column must have received editCancel" , 1 , events .size ());
506
+ assertEquals ("editing location of cancel event" , editingPosition , events .get (0 ).getTablePosition ());
507
+ }
508
+
509
+ /**
510
+ * Test that removing the editing item does not cause a memory leak.
511
+ */
512
+ @ Test
513
+ public void testEditCancelMemoryLeakAfterRemoveEditingItem () {
514
+ TableView <MenuItem > table = new TableView <>(FXCollections .observableArrayList (
515
+ new MenuItem ("some" ), new MenuItem ("other" )));
516
+ TableColumn <MenuItem , String > editingColumn = new TableColumn <>("Text" );
517
+ editingColumn .setCellValueFactory (cc -> new SimpleObjectProperty <>("" ));
518
+ table .setEditable (true );
519
+ table .getColumns ().add (editingColumn );
520
+ stageLoader = new StageLoader (table );
521
+ int editingIndex = 1 ;
522
+ MenuItem editingItem = table .getItems ().get (editingIndex );
523
+ WeakReference <MenuItem > itemRef = new WeakReference <>(editingItem );
524
+ table .edit (editingIndex , editingColumn );
525
+ table .getItems ().remove (editingIndex );
526
+ editingItem = null ;
527
+ Toolkit .getToolkit ().firePulse ();
528
+ attemptGC (itemRef );
529
+ assertEquals ("item must be gc'ed" , null , itemRef .get ());
530
+ }
531
+
405
532
/**
406
533
* Test that cell.cancelEdit can switch table editing off
407
534
* even if a subclass violates its contract.
0 commit comments