< prev index next >

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

Print this page
rev 10463 : 8089514: [TableView, TreeView, ListView, TreeTableView] Clicking outside of the edited cell, node, or entry should commit the value


 374         // by calling super.startEdit().
 375         super.startEdit();
 376 
 377          // Inform the TreeView of the edit starting.
 378         if (tree != null) {
 379             tree.fireEvent(new TreeView.EditEvent<T>(tree,
 380                     TreeView.<T>editStartEvent(),
 381                     getTreeItem(),
 382                     getItem(),
 383                     null));
 384 
 385             tree.requestFocus();
 386         }
 387     }
 388 
 389      /** {@inheritDoc} */
 390     @Override public void commitEdit(T newValue) {
 391         if (! isEditing()) return;
 392         final TreeItem<T> treeItem = getTreeItem();
 393         final TreeView<T> tree = getTreeView();








 394         if (tree != null) {
 395             // Inform the TreeView of the edit being ready to be committed.
 396             tree.fireEvent(new TreeView.EditEvent<T>(tree,
 397                     TreeView.<T>editCommitEvent(),
 398                     treeItem,
 399                     getItem(),
 400                     newValue));
 401         }
 402 
 403         // inform parent classes of the commit, so that they can switch us
 404         // out of the editing state.
 405         // This MUST come before the updateItem call below, otherwise it will
 406         // call cancelEdit(), resulting in both commit and cancel events being
 407         // fired (as identified in RT-29650)
 408         super.commitEdit(newValue);
 409 
 410         // update the item within this cell, so that it represents the new value
 411         if (treeItem != null) {
 412             treeItem.setValue(newValue);
 413             updateTreeItem(treeItem);
 414             updateItem(newValue, false);
 415         }
 416 
 417         if (tree != null) {
 418             // reset the editing item in the TreetView
 419             tree.edit(null);
 420 
 421             // request focus back onto the tree, only if the current focus
 422             // owner has the tree as a parent (otherwise the user might have
 423             // clicked out of the tree entirely and given focus to something else.
 424             // It would be rude of us to request it back again.
 425             ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(tree);
 426         }
 427     }
 428 
 429     /** {@inheritDoc} */
 430     @Override public void cancelEdit() {
 431         if (! isEditing()) return;
 432 
 433         TreeView<T> tree = getTreeView();
 434 
 435         super.cancelEdit();
 436 
 437         if (tree != null) {
 438             // reset the editing index on the TreeView
 439             if (updateEditingIndex) tree.edit(null);
 440 
 441             // request focus back onto the tree, only if the current focus
 442             // owner has the tree as a parent (otherwise the user might have
 443             // clicked out of the tree entirely and given focus to something else.
 444             // It would be rude of us to request it back again.
 445             ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(tree);
 446 
 447             tree.fireEvent(new TreeView.EditEvent<T>(tree,
 448                     TreeView.<T>editCancelEvent(),
 449                     getTreeItem(),
 450                     getItem(),
 451                     null));
 452         }
 453     }
 454 
 455     /** {@inheritDoc} */
 456     @Override protected Skin<?> createDefaultSkin() {
 457         return new TreeCellSkin<T>(this);
 458     }
 459 
 460     /***************************************************************************
 461      *                                                                         *
 462      * Private Implementation                                                  *
 463      *                                                                         *
 464      **************************************************************************/
 465 
 466     /** {@inheritDoc} */
 467     @Override void indexChanged(int oldIndex, int newIndex) {
 468         super.indexChanged(oldIndex, newIndex);
 469 
 470         // when the cell index changes, this may result in the cell
 471         // changing state to be selected and/or focused.
 472         if (isEditing() && newIndex == oldIndex) {
 473             // no-op
 474             // Fix for RT-31165 - if we (needlessly) update the index whilst the
 475             // cell is being edited it will no longer be in an editing state.
 476             // This means that in certain (common) circumstances that it will
 477             // appear that a cell is uneditable as, despite being clicked, it
 478             // will not change to the editing state as a layout of VirtualFlow
 479             // is immediately invoked, which forces all cells to be updated.
 480         } else {
 481             updateItem(oldIndex);


 482             updateSelection();
 483             updateFocus();
 484         }
 485     }
 486 
 487     private boolean isFirstRun = true;
 488     private void updateItem(int oldIndex) {
 489         TreeView<T> tv = getTreeView();
 490         if (tv == null) return;
 491 
 492         // Compute whether the index for this cell is for a real item
 493         int index = getIndex();
 494         boolean valid = index >=0 && index < tv.getExpandedItemCount();
 495         final boolean isEmpty = isEmpty();
 496         final TreeItem<T> oldTreeItem = getTreeItem();
 497 
 498         // Cause the cell to update itself
 499         outer: if (valid) {
 500             // update the TreeCell state.
 501             // get the new treeItem that is about to go in to the TreeCell
 502             TreeItem<T> newTreeItem = tv.getTreeItem(index);
 503             T newValue = newTreeItem == null ? null : newTreeItem.getValue();
 504             T oldValue = oldTreeItem == null ? null : oldTreeItem.getValue();
 505 


 547         }
 548 
 549         boolean isSelected = sm.isSelected(getIndex());
 550         if (isSelected() == isSelected) return;
 551 
 552         updateSelected(isSelected);
 553     }
 554 
 555     private void updateFocus() {
 556         if (getIndex() == -1 || getTreeView() == null) return;
 557 
 558         FocusModel<TreeItem<T>> fm = getTreeView().getFocusModel();
 559         if (fm == null) {
 560             setFocused(false);
 561             return;
 562         }
 563 
 564         setFocused(fm.isFocused(getIndex()));
 565     }
 566 
 567     private boolean updateEditingIndex = true;
 568     private void updateEditing() {
 569         final int index = getIndex();
 570         final TreeView<T> tree = getTreeView();
 571         final TreeItem<T> treeItem = getTreeItem();
 572         final TreeItem<T> editItem = tree == null ? null : tree.getEditingItem();
 573         final boolean editing = isEditing();
 574 
 575         if (index == -1 || tree == null || treeItem == null) return;
 576 
 577         final boolean match = treeItem.equals(editItem);
 578 
 579         // If my tree item is the item being edited and I'm not currently in
 580         // the edit mode, then I need to enter the edit mode
 581         if (match && !editing) {
 582             startEdit();
 583         } else if (! match && editing) {
 584             // If my tree item is not the one being edited then I need to cancel
 585             // the edit. The tricky thing here is that as part of this call
 586             // I cannot end up calling tree.edit(null) the way that the standard
 587             // cancelEdit method would do. Yet, I need to call cancelEdit
 588             // so that subclasses which override cancelEdit can execute. So,
 589             // I have to use a kind of hacky flag workaround.
 590             updateEditingIndex = false;
 591             cancelEdit();
 592             updateEditingIndex = true;
 593         }
 594     }
 595 
 596 
 597 
 598     /***************************************************************************
 599      *                                                                         *
 600      * Expert API                                                              *
 601      *                                                                         *
 602      **************************************************************************/
 603 
 604 
 605 
 606     /**
 607      * Updates the TreeView associated with this TreeCell.
 608      *
 609      * @param tree The new TreeView that should be associated with this TreeCell.
 610      * Note: This function is intended to be used by experts, primarily
 611      *       by those implementing new Skins. It is not common
 612      *       for developers or designers to access this function directly.




 374         // by calling super.startEdit().
 375         super.startEdit();
 376 
 377          // Inform the TreeView of the edit starting.
 378         if (tree != null) {
 379             tree.fireEvent(new TreeView.EditEvent<T>(tree,
 380                     TreeView.<T>editStartEvent(),
 381                     getTreeItem(),
 382                     getItem(),
 383                     null));
 384 
 385             tree.requestFocus();
 386         }
 387     }
 388 
 389      /** {@inheritDoc} */
 390     @Override public void commitEdit(T newValue) {
 391         if (! isEditing()) return;
 392         final TreeItem<T> treeItem = getTreeItem();
 393         final TreeView<T> tree = getTreeView();
 394 
 395         // inform parent classes of the commit, so that they can switch us
 396         // out of the editing state.
 397         // This MUST come before the updateItem call below, otherwise it will
 398         // call cancelEdit(), resulting in both commit and cancel events being
 399         // fired (as identified in RT-29650)
 400         super.commitEdit(newValue);
 401 
 402         if (tree != null) {
 403             // Inform the TreeView of the edit being ready to be committed.
 404             tree.fireEvent(new TreeView.EditEvent<T>(tree,
 405                     TreeView.<T>editCommitEvent(),
 406                     treeItem,
 407                     getItem(),
 408                     newValue));
 409         }
 410 







 411         // update the item within this cell, so that it represents the new value
 412         if (treeItem != null) {
 413             treeItem.setValue(newValue);
 414             updateTreeItem(treeItem);
 415             updateItem(newValue, false);
 416         }
 417 
 418         if (tree != null) {
 419             // reset the editing item in the TreetView
 420             tree.edit(null);
 421 
 422             // request focus back onto the tree, only if the current focus
 423             // owner has the tree as a parent (otherwise the user might have
 424             // clicked out of the tree entirely and given focus to something else.
 425             // It would be rude of us to request it back again.
 426             ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(tree);
 427         }
 428     }
 429 
 430     /** {@inheritDoc} */
 431     @Override public void cancelEdit() {
 432         if (! isEditing()) return;
 433 
 434         TreeView<T> tree = getTreeView();
 435 
 436         super.cancelEdit();
 437 
 438         if (tree != null) {
 439             // reset the editing index on the TreeView
 440             tree.edit(null);
 441 
 442             // request focus back onto the tree, only if the current focus
 443             // owner has the tree as a parent (otherwise the user might have
 444             // clicked out of the tree entirely and given focus to something else.
 445             // It would be rude of us to request it back again.
 446             ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(tree);
 447 
 448             tree.fireEvent(new TreeView.EditEvent<T>(tree,
 449                     TreeView.<T>editCancelEvent(),
 450                     getTreeItem(),
 451                     getItem(),
 452                     null));
 453         }
 454     }
 455 
 456     /** {@inheritDoc} */
 457     @Override protected Skin<?> createDefaultSkin() {
 458         return new TreeCellSkin<T>(this);
 459     }
 460 
 461     /***************************************************************************
 462      *                                                                         *
 463      * Private Implementation                                                  *
 464      *                                                                         *
 465      **************************************************************************/
 466 
 467     /** {@inheritDoc} */
 468     @Override void indexChanged(int oldIndex, int newIndex) {
 469         super.indexChanged(oldIndex, newIndex);
 470 
 471         // when the cell index changes, this may result in the cell
 472         // changing state to be selected and/or focused.
 473         if (isEditing()) {
 474             // no-op
 475             // Fix for RT-31165 - if we (needlessly) update the index whilst the
 476             // cell is being edited it will no longer be in an editing state.
 477             // This means that in certain (common) circumstances that it will
 478             // appear that a cell is uneditable as, despite being clicked, it
 479             // will not change to the editing state as a layout of VirtualFlow
 480             // is immediately invoked, which forces all cells to be updated.
 481         } else {
 482             updateItem(oldIndex);
 483         }
 484 
 485         updateSelection();
 486         updateFocus();
 487     }

 488 
 489     private boolean isFirstRun = true;
 490     private void updateItem(int oldIndex) {
 491         TreeView<T> tv = getTreeView();
 492         if (tv == null) return;
 493 
 494         // Compute whether the index for this cell is for a real item
 495         int index = getIndex();
 496         boolean valid = index >=0 && index < tv.getExpandedItemCount();
 497         final boolean isEmpty = isEmpty();
 498         final TreeItem<T> oldTreeItem = getTreeItem();
 499 
 500         // Cause the cell to update itself
 501         outer: if (valid) {
 502             // update the TreeCell state.
 503             // get the new treeItem that is about to go in to the TreeCell
 504             TreeItem<T> newTreeItem = tv.getTreeItem(index);
 505             T newValue = newTreeItem == null ? null : newTreeItem.getValue();
 506             T oldValue = oldTreeItem == null ? null : oldTreeItem.getValue();
 507 


 549         }
 550 
 551         boolean isSelected = sm.isSelected(getIndex());
 552         if (isSelected() == isSelected) return;
 553 
 554         updateSelected(isSelected);
 555     }
 556 
 557     private void updateFocus() {
 558         if (getIndex() == -1 || getTreeView() == null) return;
 559 
 560         FocusModel<TreeItem<T>> fm = getTreeView().getFocusModel();
 561         if (fm == null) {
 562             setFocused(false);
 563             return;
 564         }
 565 
 566         setFocused(fm.isFocused(getIndex()));
 567     }
 568 

 569     private void updateEditing() {
 570         final int index = getIndex();
 571         final TreeView<T> tree = getTreeView();
 572         final TreeItem<T> treeItem = getTreeItem();
 573         final TreeItem<T> editItem = tree == null ? null : tree.getEditingItem();
 574         final boolean editing = isEditing();
 575 
 576         if (index == -1 || tree == null || treeItem == null) return;
 577 
 578         final boolean match = treeItem.equals(editItem);
 579 
 580         // If my tree item is the item being edited and I'm not currently in
 581         // the edit mode, then I need to enter the edit mode
 582         if (match && !editing) {
 583             startEdit();
 584         } else if (! match && editing) {
 585             attemptEditCommit();








 586         }
 587     }
 588 
 589 
 590 
 591     /***************************************************************************
 592      *                                                                         *
 593      * Expert API                                                              *
 594      *                                                                         *
 595      **************************************************************************/
 596 
 597 
 598 
 599     /**
 600      * Updates the TreeView associated with this TreeCell.
 601      *
 602      * @param tree The new TreeView that should be associated with this TreeCell.
 603      * Note: This function is intended to be used by experts, primarily
 604      *       by those implementing new Skins. It is not common
 605      *       for developers or designers to access this function directly.


< prev index next >