324 // by calling super.startEdit().
325 super.startEdit();
326
327 if (column != null) {
328 CellEditEvent editEvent = new CellEditEvent(
329 table,
330 table.getEditingCell(),
331 TreeTableColumn.<S,T>editStartEvent(),
332 null
333 );
334
335 Event.fireEvent(column, editEvent);
336 }
337 }
338
339 /** {@inheritDoc} */
340 @Override public void commitEdit(T newValue) {
341 if (! isEditing()) return;
342
343 final TreeTableView<S> table = getTreeTableView();
344 if (table != null) {
345 @SuppressWarnings("unchecked")
346 TreeTablePosition<S,T> editingCell = (TreeTablePosition<S,T>) table.getEditingCell();
347
348 // Inform the TableView of the edit being ready to be committed.
349 CellEditEvent<S,T> editEvent = new CellEditEvent<S,T>(
350 table,
351 editingCell,
352 TreeTableColumn.<S,T>editCommitEvent(),
353 newValue
354 );
355
356 Event.fireEvent(getTableColumn(), editEvent);
357 }
358
359 // inform parent classes of the commit, so that they can switch us
360 // out of the editing state.
361 // This MUST come before the updateItem call below, otherwise it will
362 // call cancelEdit(), resulting in both commit and cancel events being
363 // fired (as identified in RT-29650)
364 super.commitEdit(newValue);
365
366 // update the item within this cell, so that it represents the new value
367 updateItem(newValue, false);
368
369 if (table != null) {
370 // reset the editing cell on the TableView
371 table.edit(-1, null);
372
373 // request focus back onto the table, only if the current focus
374 // owner has the table as a parent (otherwise the user might have
375 // clicked out of the table entirely and given focus to something else.
376 // It would be rude of us to request it back again.
377 ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(table);
378 }
379 }
380
381 /** {@inheritDoc} */
382 @Override public void cancelEdit() {
383 if (! isEditing()) return;
384
385 final TreeTableView<S> table = getTreeTableView();
423 // copied from Cell, with the first conditional clause below commented
424 // out, as it is valid for an empty TableCell to be selected, as long
425 // as the parent TableRow is not empty (see RT-15529).
426 /*if (selected && isEmpty()) return;*/
427 if (getTreeTableRow() == null || getTreeTableRow().isEmpty()) return;
428 setSelected(selected);
429 }
430
431
432
433 /* *************************************************************************
434 * *
435 * Private Implementation *
436 * *
437 **************************************************************************/
438
439 /** {@inheritDoc} */
440 @Override void indexChanged(int oldIndex, int newIndex) {
441 super.indexChanged(oldIndex, newIndex);
442
443 if (isEditing() && newIndex == oldIndex) {
444 // no-op
445 // Fix for RT-31165 - if we (needlessly) update the index whilst the
446 // cell is being edited it will no longer be in an editing state.
447 // This means that in certain (common) circumstances that it will
448 // appear that a cell is uneditable as, despite being clicked, it
449 // will not change to the editing state as a layout of VirtualFlow
450 // is immediately invoked, which forces all cells to be updated.
451 } else {
452 // Ideally we would just use the following two lines of code, rather
453 // than the updateItem() call beneath, but if we do this we end up with
454 // RT-22428 where all the columns are collapsed.
455 // itemDirty = true;
456 // requestLayout();
457 updateItem(oldIndex);
458 updateSelection();
459 updateFocus();
460 updateEditing();
461 }
462 }
463
464 private boolean isLastVisibleColumn = false;
465 private int columnIndex = -1;
466
467 private void updateColumnIndex() {
468 final TreeTableView<S> tv = getTreeTableView();
469 TreeTableColumn<S,T> tc = getTableColumn();
470 columnIndex = tv == null || tc == null ? -1 : tv.getVisibleLeafIndex(tc);
471
472 // update the pseudo class state regarding whether this is the last
473 // visible cell (i.e. the right-most).
474 isLastVisibleColumn = getTableColumn() != null &&
475 columnIndex != -1 &&
476 columnIndex == tv.getVisibleLeafColumns().size() - 1;
477 pseudoClassStateChanged(PSEUDO_CLASS_LAST_VISIBLE, isLastVisibleColumn);
478 }
479
480 private void updateSelection() {
481 /*
526
527 TreeTableView.TreeTableViewFocusModel<S> fm = tv.getFocusModel();
528 if (fm == null) {
529 setFocused(false);
530 return;
531 }
532
533 setFocused(fm.isFocused(getIndex(), getTableColumn()));
534 }
535
536 private void updateEditing() {
537 final TreeTableView<S> tv = getTreeTableView();
538 if (getIndex() == -1 || tv == null) return;
539
540 TreeTablePosition<S,?> editCell = tv.getEditingCell();
541 boolean match = match(editCell);
542
543 if (match && ! isEditing()) {
544 startEdit();
545 } else if (! match && isEditing()) {
546 // If my index is not the one being edited then I need to cancel
547 // the edit. The tricky thing here is that as part of this call
548 // I cannot end up calling list.edit(-1) the way that the standard
549 // cancelEdit method would do. Yet, I need to call cancelEdit
550 // so that subclasses which override cancelEdit can execute. So,
551 // I have to use a kind of hacky flag workaround.
552 updateEditingIndex = false;
553 cancelEdit();
554 updateEditingIndex = true;
555 }
556 }
557 private boolean updateEditingIndex = true;
558
559 private boolean match(TreeTablePosition pos) {
560 return pos != null && pos.getRow() == getIndex() && pos.getTableColumn() == getTableColumn();
561 }
562
563 private boolean isInCellSelectionMode() {
564 TreeTableView<S> tv = getTreeTableView();
565 if (tv == null) return false;
566 TreeTableView.TreeTableViewSelectionModel<S> sm = tv.getSelectionModel();
567 return sm != null && sm.isCellSelectionEnabled();
568 }
569
570 /*
571 * This was brought in to fix the issue in RT-22077, namely that the
572 * ObservableValue was being GC'd, meaning that changes to the value were
573 * no longer being delivered. By extracting this value out of the method,
574 * it is now referred to from TableCell and will therefore no longer be
|
324 // by calling super.startEdit().
325 super.startEdit();
326
327 if (column != null) {
328 CellEditEvent editEvent = new CellEditEvent(
329 table,
330 table.getEditingCell(),
331 TreeTableColumn.<S,T>editStartEvent(),
332 null
333 );
334
335 Event.fireEvent(column, editEvent);
336 }
337 }
338
339 /** {@inheritDoc} */
340 @Override public void commitEdit(T newValue) {
341 if (! isEditing()) return;
342
343 final TreeTableView<S> table = getTreeTableView();
344
345 // inform parent classes of the commit, so that they can switch us
346 // out of the editing state.
347 // This MUST come before the updateItem call below, otherwise it will
348 // call cancelEdit(), resulting in both commit and cancel events being
349 // fired (as identified in RT-29650)
350 super.commitEdit(newValue);
351
352 if (table != null) {
353 @SuppressWarnings("unchecked")
354 // Inform the TreeTableView of the edit being ready to be committed.
355 CellEditEvent<S,T> editEvent = new CellEditEvent<S,T>(
356 table,
357 new TreeTablePosition<>(getTreeTableView(), getIndex(), getTableColumn()),
358 TreeTableColumn.<S,T>editCommitEvent(),
359 newValue
360 );
361
362 Event.fireEvent(getTableColumn(), editEvent);
363 }
364
365 // update the item within this cell, so that it represents the new value
366 updateItem(newValue, false);
367
368 if (table != null) {
369 // reset the editing cell on the TableView
370 table.edit(-1, null);
371
372 // request focus back onto the table, only if the current focus
373 // owner has the table as a parent (otherwise the user might have
374 // clicked out of the table entirely and given focus to something else.
375 // It would be rude of us to request it back again.
376 ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(table);
377 }
378 }
379
380 /** {@inheritDoc} */
381 @Override public void cancelEdit() {
382 if (! isEditing()) return;
383
384 final TreeTableView<S> table = getTreeTableView();
422 // copied from Cell, with the first conditional clause below commented
423 // out, as it is valid for an empty TableCell to be selected, as long
424 // as the parent TableRow is not empty (see RT-15529).
425 /*if (selected && isEmpty()) return;*/
426 if (getTreeTableRow() == null || getTreeTableRow().isEmpty()) return;
427 setSelected(selected);
428 }
429
430
431
432 /* *************************************************************************
433 * *
434 * Private Implementation *
435 * *
436 **************************************************************************/
437
438 /** {@inheritDoc} */
439 @Override void indexChanged(int oldIndex, int newIndex) {
440 super.indexChanged(oldIndex, newIndex);
441
442 if (isEditing()) {
443 // no-op
444 // Fix for RT-31165 - if we (needlessly) update the index whilst the
445 // cell is being edited it will no longer be in an editing state.
446 // This means that in certain (common) circumstances that it will
447 // appear that a cell is uneditable as, despite being clicked, it
448 // will not change to the editing state as a layout of VirtualFlow
449 // is immediately invoked, which forces all cells to be updated.
450 } else {
451 // Ideally we would just use the following two lines of code, rather
452 // than the updateItem() call beneath, but if we do this we end up with
453 // RT-22428 where all the columns are collapsed.
454 // itemDirty = true;
455 // requestLayout();
456 updateItem(oldIndex);
457 updateEditing();
458 }
459
460 updateSelection();
461 updateFocus();
462 }
463
464 private boolean isLastVisibleColumn = false;
465 private int columnIndex = -1;
466
467 private void updateColumnIndex() {
468 final TreeTableView<S> tv = getTreeTableView();
469 TreeTableColumn<S,T> tc = getTableColumn();
470 columnIndex = tv == null || tc == null ? -1 : tv.getVisibleLeafIndex(tc);
471
472 // update the pseudo class state regarding whether this is the last
473 // visible cell (i.e. the right-most).
474 isLastVisibleColumn = getTableColumn() != null &&
475 columnIndex != -1 &&
476 columnIndex == tv.getVisibleLeafColumns().size() - 1;
477 pseudoClassStateChanged(PSEUDO_CLASS_LAST_VISIBLE, isLastVisibleColumn);
478 }
479
480 private void updateSelection() {
481 /*
526
527 TreeTableView.TreeTableViewFocusModel<S> fm = tv.getFocusModel();
528 if (fm == null) {
529 setFocused(false);
530 return;
531 }
532
533 setFocused(fm.isFocused(getIndex(), getTableColumn()));
534 }
535
536 private void updateEditing() {
537 final TreeTableView<S> tv = getTreeTableView();
538 if (getIndex() == -1 || tv == null) return;
539
540 TreeTablePosition<S,?> editCell = tv.getEditingCell();
541 boolean match = match(editCell);
542
543 if (match && ! isEditing()) {
544 startEdit();
545 } else if (! match && isEditing()) {
546 attemptEditCommit();
547 }
548 }
549 private boolean updateEditingIndex = true;
550
551 private boolean match(TreeTablePosition pos) {
552 return pos != null && pos.getRow() == getIndex() && pos.getTableColumn() == getTableColumn();
553 }
554
555 private boolean isInCellSelectionMode() {
556 TreeTableView<S> tv = getTreeTableView();
557 if (tv == null) return false;
558 TreeTableView.TreeTableViewSelectionModel<S> sm = tv.getSelectionModel();
559 return sm != null && sm.isCellSelectionEnabled();
560 }
561
562 /*
563 * This was brought in to fix the issue in RT-22077, namely that the
564 * ObservableValue was being GC'd, meaning that changes to the value were
565 * no longer being delivered. By extracting this value out of the method,
566 * it is now referred to from TableCell and will therefore no longer be
|