< prev index next >

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

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

@@ -40,10 +40,12 @@
 import javafx.beans.property.ReadOnlyBooleanProperty;
 import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.beans.value.WritableValue;
 import javafx.css.StyleableProperty;
 
+import java.util.Optional;
+
 /**
  * The Cell API is used for virtualized controls such as {@link ListView},
  * {@link TreeView}, and {@link TableView}.
  * A Cell is a {@link Labeled} {@link Control}, and is used to render a single
  * "row" inside  a ListView, TreeView or TableView. Cells are also used for each

@@ -357,18 +359,14 @@
         /**
          * Indicates whether or not this cell has focus. For example, a
          * ListView defines zero or one cell as being the "focused" cell. This cell
          * would have focused set to true.
          */
-        super.focusedProperty().addListener(new InvalidationListener() {
-            @Override public void invalidated(Observable property) {
-                pseudoClassStateChanged(PSEUDO_CLASS_FOCUSED, isFocused()); // TODO is this necessary??
-
+        super.focusedProperty().addListener(o -> {
                 // The user has shifted focus, so we should cancel the editing on this cell
                 if (!isFocused() && isEditing()) {
-                    cancelEdit();
-                }
+                attemptEditCommit();
             }
         });
 
         // initialize default pseudo-class state
         pseudoClassStateChanged(PSEUDO_CLASS_EMPTY, true);

@@ -628,10 +626,11 @@
     @Override protected void layoutChildren() {
         if (itemDirty) {
             updateItem(getItem(), isEmpty());
             itemDirty = false;
         }
+
         super.layoutChildren();
     }
 
 
 

@@ -734,10 +733,30 @@
      */
     protected boolean isItemChanged(T oldItem, T newItem) {
         return oldItem != null ? !oldItem.equals(newItem) : newItem != null;
     }
 
+    /**
+     * Developers of custom cell implementations should override this method when
+     * the cell provides editing functionality, with this method returning the
+     * user input after the user has interacted with the editing components.
+     * The form of the returned data (wrapped in an {@link Optional}) should
+     * be the same as the form of the underlying data model, hence the
+     * use of the {@code T} generic type. If no value is available, or if the
+     * value to be returned is invalid, {@code Optional.empty()} should be returned
+     * to indicate that the commit should not proceed..
+     *
+     * @return The value provided by the user into this cell when it was in its
+     *      editing state, in the form of the underlying data model. If the value
+     *      is invalid or unable to be determined, {@code Optional.empty()} should
+     *      be returned.
+     * @since 10
+     */
+    protected Optional<T> getEditorValue() {
+        return Optional.empty();
+    }
+
 
 
     /***************************************************************************
      *                                                                         *
      * Private Implementation                                                  *

@@ -751,22 +770,25 @@
     private final void markCellDirty() {
         itemDirty = true;
         requestLayout();
     }
 
+    void attemptEditCommit() {
+        // The user has shifted focus, so we should cancel the editing on this cell
+        getEditorValue().ifPresentOrElse(this::commitEdit, this::cancelEdit);
+    }
+
 
     /***************************************************************************
      *                                                                         *
      * Stylesheet Handling                                                     *
      *                                                                         *
      **************************************************************************/
 
     private static final String DEFAULT_STYLE_CLASS = "cell";
     private static final PseudoClass PSEUDO_CLASS_SELECTED =
             PseudoClass.getPseudoClass("selected");
-    private static final PseudoClass PSEUDO_CLASS_FOCUSED =
-            PseudoClass.getPseudoClass("focused");
     private static final PseudoClass PSEUDO_CLASS_EMPTY =
             PseudoClass.getPseudoClass("empty");
     private static final PseudoClass PSEUDO_CLASS_FILLED =
             PseudoClass.getPseudoClass("filled");
 
< prev index next >