1 /*
   2  * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.control;
  27 
  28 import javafx.beans.InvalidationListener;
  29 import javafx.beans.Observable;
  30 import javafx.beans.property.BooleanProperty;
  31 import javafx.beans.property.ObjectProperty;
  32 import javafx.beans.property.SimpleBooleanProperty;
  33 import javafx.beans.property.SimpleObjectProperty;
  34 import javafx.collections.ObservableList;
  35 import javafx.scene.Node;
  36 import javafx.scene.layout.GridPane;
  37 import javafx.scene.layout.HBox;
  38 import javafx.scene.shape.Rectangle;
  39 import javafx.css.PseudoClass;
  40 import javafx.beans.property.ReadOnlyBooleanProperty;
  41 import javafx.beans.property.ReadOnlyBooleanWrapper;
  42 import javafx.beans.value.WritableValue;
  43 import javafx.css.StyleableProperty;
  44 
  45 import java.util.Optional;
  46 
  47 /**
  48  * The Cell API is used for virtualized controls such as {@link ListView},
  49  * {@link TreeView}, and {@link TableView}.
  50  * A Cell is a {@link Labeled} {@link Control}, and is used to render a single
  51  * "row" inside  a ListView, TreeView or TableView. Cells are also used for each
  52  * individual 'cell' inside a TableView (i.e. each row/column intersection). See
  53  * the JavaDoc for each control separately for more detail.
  54  * <p>
  55  * Every Cell is associated with a single data item (represented by the
  56  * {@link #itemProperty() item} property). The Cell is responsible for
  57  * rendering that item and, where appropriate, for editing the item. An item
  58  * within a Cell may be represented by text or some other control such as a
  59  * {@link CheckBox}, {@link ChoiceBox} or any other {@link Node} such as a
  60  * {@link HBox}, {@link GridPane}, or even a {@link Rectangle}.
  61  * <p>
  62  * Because TreeView, ListView, TableView and other such controls can potentially
  63  * be used for displaying incredibly large amounts of data, it is not feasible
  64  * to create an actual Cell for every single item in the control.
  65  * We represent extremely large data sets using only very few Cells. Each Cell
  66  * is "recycled", or reused. This is what we mean when we say that these controls
  67  * are virtualized.
  68  * <p>
  69  * Since Cell is a Control, it is essentially a "model". Its Skin is responsible
  70  * for defining the look and layout, while the Behavior is responsible for
  71  * handling all input events and using that information to modify the Control
  72  * state. Also, the Cell is styled from CSS just like any other Control.
  73  * However, it is not necessary to implement a Skin for most uses of a Cell.
  74  * This is because a cell factory can be set - this is detailed more shortly.
  75  * <p>
  76  * Because by far the most common use case for cells is to show text to a user,
  77  * this use case is specially optimized for within Cell. This is done by Cell
  78  * extending from {@link Labeled}. This means that subclasses of Cell need only
  79  * set the {@link #textProperty() text} property, rather than create a separate
  80  * {@link Label} and set that within the Cell. However, for situations where
  81  * something more than just plain text is called for, it is possible to place
  82  * any {@link Node} in the Cell {@link #graphicProperty() graphic} property.
  83  * Despite the term, a graphic can be any Node, and will be fully interactive.
  84  * For example, a ListCell might be configured with a {@link Button} as its
  85  * graphic. The Button text could then be bound to the cells
  86  * {@link #itemProperty() item} property. In this way, whenever the item in the
  87  * Cell changes, the Button text is automatically updated.
  88  * <p>
  89  * Cell sets focusTraversable to false.
  90  * </p>
  91  * <p>
  92  * <b>Cell Factories</b>
  93  * <p>
  94  * The default representation of the Cell <code>item</code> is up to the various
  95  * virtualized container's skins to render. For example, the ListView by default
  96  * will convert the item to a String and call {@link #setText(java.lang.String)}
  97  * with this value. If you want to specialize the Cell used for the
  98  * ListView (for example), then you must provide an implementation of the
  99  * {@link ListView#cellFactoryProperty() cellFactory} callback function defined
 100  * on the ListView. Similar API exists on most controls that use Cells (for example,
 101  * {@link TreeView#cellFactoryProperty() TreeView},
 102  * {@link TableView#rowFactoryProperty() TableView},
 103  * {@link TableColumn#cellFactoryProperty() TableColumn} and
 104  * {@link ListView#cellFactoryProperty() ListView}.
 105  * <p>
 106  * The cell factory is called by the platform whenever it determines that a new
 107  * cell needs to be created. For example, perhaps your ListView has 10 million
 108  * items. Creating all 10 million cells would be prohibitively expensive. So
 109  * instead the ListView skin implementation might only create just enough cells
 110  * to fit the visual space. If the ListView is resized to be larger, the system
 111  * will determine that it needs to create some additional cells. In this case
 112  * it will call the cellFactory callback function (if one is provided) to create
 113  * the Cell implementation that should be used. If no cell factory is provided,
 114  * the built-in default implementation will be used.
 115  * <p>
 116  * The implementation of the cell factory is then responsible not just for
 117  * creating a Cell instance, but also configuring that Cell such that it reacts
 118  * to changes in its state. For example, if I were to create
 119  * a custom Cell which formatted Numbers such that they would appear as currency
 120  * types, I might do so like this:
 121  *
 122  * <pre>
 123  * public class MoneyFormatCell extends ListCell&lt;Number&gt; {
 124  *
 125  *     public MoneyFormatCell() {    }
 126  *
 127  *     @Override protected void updateItem(Number item, boolean empty) {
 128  *         // calling super here is very important - don't skip this!
 129  *         super.updateItem(item, empty);
 130  *
 131  *         // format the number as if it were a monetary value using the
 132  *         // formatting relevant to the current locale. This would format
 133  *         // 43.68 as "$43.68", and -23.67 as "-$23.67"
 134  *         setText(item == null ? "" : NumberFormat.getCurrencyInstance().format(item));
 135  *
 136  *         // change the text fill based on whether it is positive (green)
 137  *         // or negative (red). If the cell is selected, the text will
 138  *         // always be white (so that it can be read against the blue
 139  *         // background), and if the value is zero, we'll make it black.
 140  *         if (item != null) {
 141  *             double value = item.doubleValue();
 142  *             setTextFill(isSelected() ? Color.WHITE :
 143  *                 value == 0 ? Color.BLACK :
 144  *                 value &lt; 0 ? Color.RED : Color.GREEN);
 145  *         }
 146  *     }
 147  * }</pre>
 148  *
 149  * This class could then be used inside a ListView as such:
 150  *
 151  * <pre>
 152  * ObservableList&lt;Number&gt; money = ...;
 153  * final ListView&lt;Number&gt; listView = new ListView&lt;Number&gt;(money);
 154  * listView.setCellFactory(new Callback&lt;ListView&lt;Number&gt;, ListCell&lt;Number&gt;&gt;() {
 155  *     @Override public ListCell&lt;Number&gt; call(ListView&lt;Number&gt; list) {
 156  *         return new MoneyFormatCell();
 157  *     }
 158  * });</pre>
 159  *
 160  * In this example an anonymous inner class is created, that simply returns
 161  * instances of MoneyFormatCell whenever it is called. The MoneyFormatCell class
 162  * extends {@link ListCell}, overriding the
 163  * {@link #updateItem(java.lang.Object, boolean) updateItem} method. This method
 164  * is called whenever the item in the cell changes, for example when the user
 165  * scrolls the ListView or the content of the underlying data model changes
 166  * (and the cell is reused to represent some different item in the ListView).
 167  * Because of this, there is no need to manage bindings - simply react to the
 168  * change in items when this method occurs. In the example above, whenever the
 169  * item changes, we update the cell text property, and also modify the text fill
 170  * to ensure that we get the correct visuals. In addition, if the cell is "empty"
 171  * (meaning it is used to fill out space in the ListView but doesn't have any
 172  * data associated with it), then we just use the empty String.
 173  * <p>
 174  * Note that there are additional
 175  * methods prefixed with 'update' that may be of interest, so be
 176  * sure to read the API documentation for Cell, and subclasses of Cell, closely.
 177  * <p>
 178  * Of course, we can also use the binding API rather than overriding the
 179  * 'update' methods. Shown below is a very trivial example of how this could
 180  * be achieved.
 181  *
 182  *
 183  * <pre>
 184  * public class BoundLabelCell extends ListCell&lt;String&gt; {
 185  *
 186  *     public BoundLabelCell() {
 187  *         textProperty().bind(itemProperty());
 188  *     }
 189  * }
 190  * </pre>
 191  *
 192  * <h3>Key Design Goals</h3>
 193  * <ul>
 194  *   <li>Both time and memory efficient for large data sets</li>
 195  *   <li>Easy to build and use libraries for custom cells</li>
 196  *   <li>Easy to customize cell visuals</li>
 197  *   <li>Easy to customize display formatting (12.34 as $12.34 or 1234% etc)</li>
 198  *   <li>Easy to extend for custom visuals</li>
 199  *   <li>Easy to have "panels" of data for the visuals</li>
 200  *   <li>Easy to animate the cell size or other properties</li>
 201  * </ul>
 202  *
 203  * <h3>Key Use Cases</h3>
 204  * Following are a number of key use cases used to drive the Cell API design,
 205  * along with code examples showing how those use cases are satisfied by this
 206  * API. This is by no means to be considered the definitive list of capabilities
 207  * or features supported, but rather, to provide some guidance as to how to use
 208  * the Cell API. The examples below are focused on the ListView, but the same
 209  * philosophy applies to TreeCells or other kinds of cells.
 210  * <p>
 211  * <b>Changing the Cell's Colors</b>
 212  * <p>
 213  * This should be extraordinarily simple in JavaFX. Each Cell can be styled
 214  * directly from CSS. So for example, if you wanted to change the default
 215  * background of every cell in a ListView to be WHITE you could do the
 216  * following CSS:
 217  *
 218  * <pre>
 219  * .list-cell {
 220  *   -fx-padding: 3 3 3 3;
 221  *   -fx-background-color: white;
 222  * }</pre>
 223  *
 224  * If you wanted to set the color of selected ListView cells to be blue, you
 225  * could add this to your CSS file:
 226  *
 227  * <pre>
 228  * .list-cell:selected {
 229  *   -fx-background-color: blue;
 230  * }</pre>
 231  *
 232  * Most Cell implementations extend from {@link IndexedCell} rather than Cell.
 233  * IndexedCell adds two other pseudoclass states: "odd" and "even". Using this
 234  * you can get alternate row striping by doing something like this in your CSS
 235  * file:
 236  *
 237  * <pre>
 238  * .list-cell:odd {
 239  *   -fx-background-color: grey;
 240  * }</pre>
 241  *
 242  * Each of these examples require no code changes. Simply update your CSS
 243  * file to alter the colors. You can also use the "hover" and other
 244  * pseudoclasses in CSS the same as with other controls.
 245  * <p>
 246  * Another approach to the first example above (formatting a list of numbers) would
 247  * be to use style classes. Suppose you had an {@link ObservableList} of Numbers
 248  * to display in a ListView and wanted to color all of the negative values red
 249  * and all positive or 0 values black.
 250  * One way to achieve this is with a custom cellFactory which changes the
 251  * styleClass of the Cell based on whether the value is negative or positive. This
 252  * is as simple as adding code to test if the number in the cell is negative,
 253  * and adding a "negative" styleClass. If the number is not negative, the "negative"
 254  * string should be removed. This approach allows for the colors to be defined
 255  * from CSS, allowing for simple customization. The CSS file would then include
 256  * something like the following:
 257  *
 258  * <pre>
 259  * .list-cell {
 260  *   -fx-text-fill: black;
 261  * }
 262  *
 263  * .list-cell .negative {
 264  *   -fx-text-fill: red;
 265  * }</pre>
 266  *
 267  * <h3>Editing</h3>
 268  * <p>Most virtualized controls that use the Cell architecture (e.g. {@link ListView},
 269  * {@link TreeView}, {@link TableView} and {@link TreeTableView}) all support
 270  * the notion of editing values directly via the cell. You can learn more about
 271  * the control-specific details by going to the 'editing' section in the class
 272  * documentation for the controls linked above. The remainder of this section
 273  * will cover some of the finer details of editing with cells.</p>
 274  *
 275  * <p>The general flow of editing is as follows (note that in these steps the
 276  * {@link ListView} control is used as an example, but similar API exists for
 277  * all controls mentioned above, and the process is exactly the same in general):</p>
 278  *
 279  * <ol>
 280  *     <li>User requests a cell enter editing mode (via keyboard or mouse commands),
 281  *     or the developer requests that a cell enter editing mode (by calling a
 282  *     method such as the ListView {@link ListView#edit(int) edit} method.
 283  *     <strong>Note:</strong> If the user double-clicks or fires an appropriate
 284  *     keyboard command to initiate editing, then they are effectively calling
 285  *     the appropriate edit method on the control (i.e. the entry method for
 286  *     user-initiated and developer-initiated editing is the same).</li>
 287  *     <li>Each cell in the visible region of the control is notified that the
 288  *     current {@link javafx.scene.control.ListView#editingIndexProperty() editing cell}
 289  *     has changed, and checks to see if it is itself. At this point one of three
 290  *     things can happen:
 291  *         <ol>
 292  *             <li>If the editing index is the same index as the cell,
 293  *             {@link #startEdit()} will be called on this cell. Some pointers:
 294  *                 <ol>
 295  *                     <li>It is recommended that subclasses of Cell override the {@link #startEdit()}
 296  *                     method to update the visuals of the cell when enters the editing state. Note
 297  *                     however that it is very important that subclasses that override the
 298  *                     {@link #startEdit()} method continue to call {@code super.startEdit()} so
 299  *                     that parent classes can update additional state that is necessary for
 300  *                     editing to be successful.</li>
 301  *                     <li>Within the {@link #startEdit()} method is an ideal
 302  *                     time to change the visuals of the cell. For example (and
 303  *                     note that this example is more fleshed out in the UI control
 304  *                     javadocs for {@link ListView}, etc), you may set the
 305  *                     {@link #graphicProperty()} of the cell to a
 306  *                     {@link TextField} and set the {@link #textProperty()}
 307  *                     to null. This would allow end users to then type in input
 308  *                     and make changes to your data model.</li>
 309  *                     <li>When the user has completed editing, they will want
 310  *                     to commit or cancel their change. This is your responsibility
 311  *                     to handle (e.g. by having the Enter key
 312  *                     {@link #commitEdit(Object) commit the edit}
 313  *                     and the ESC key {@link #cancelEdit() cancel the edit}).
 314  *                     You do this by attaching the appropriate event listeners
 315  *                     to the nodes you show whilst in the editing state.</li>
 316  *                 </ol>
 317  *             </li>
 318  *             <li>If the editing index is not the same index as the cell, and
 319  *             if the cell is currently in the {@link #isEditing() editing state},
 320  *             {@link #cancelEdit()} will be called on this cell. As with the
 321  *             {@link #startEdit()} method, you should override this method to
 322  *             clean up the visuals of the cell (and most probably return the
 323  *             {@link #graphicProperty()} back to null and set the
 324  *             {@link #textProperty()} to its (possibly new) value. Again,
 325  *             be sure to always call {@code super.cancelEdit()} to make sure all
 326  *             state is correctly updated.</li>
 327  *             <li>If the editing index is not the same index as the cell, and
 328  *             if the cell is not currently in the {@link #isEditing()} editing state},
 329  *             then nothing will happen on this cell.</li>
 330  *         </ol>
 331  *     </li>
 332  * </ol>
 333  *
 334  *
 335  * @param <T> The type of the item contained within the Cell.
 336  *
 337  * @since JavaFX 2.0
 338  */
 339 public class Cell<T> extends Labeled {
 340 
 341     /***************************************************************************
 342      *                                                                         *
 343      * Constructors                                                            *
 344      *                                                                         *
 345      **************************************************************************/
 346 
 347     /**
 348      * Creates a default Cell with the default style class of 'cell'.
 349      */
 350     public Cell() {
 351         setText(null); // default to null text, to match the null item
 352         // focusTraversable is styleable through css. Calling setFocusTraversable
 353         // makes it look to css like the user set the value and css will not
 354         // override. Initializing focusTraversable by calling set on the
 355         // CssMetaData ensures that css will be able to override the value.
 356         ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE);
 357         getStyleClass().addAll(DEFAULT_STYLE_CLASS);
 358 
 359         /**
 360          * Indicates whether or not this cell has focus. For example, a
 361          * ListView defines zero or one cell as being the "focused" cell. This cell
 362          * would have focused set to true.
 363          */
 364         super.focusedProperty().addListener(o -> {
 365             // The user has shifted focus, so we should cancel the editing on this cell
 366             if (!isFocused() && isEditing()) {
 367                 attemptEditCommit();
 368             }
 369         });
 370 
 371         // initialize default pseudo-class state
 372         pseudoClassStateChanged(PSEUDO_CLASS_EMPTY, true);
 373     }
 374 
 375 
 376 
 377     /***************************************************************************
 378      *                                                                         *
 379      * Properties                                                              *
 380      *                                                                         *
 381      **************************************************************************/
 382 
 383     // --- item
 384     private ObjectProperty<T> item = new SimpleObjectProperty<T>(this, "item");
 385 
 386     /**
 387      * The data value associated with this Cell. This value is set by the
 388      * virtualized Control when the Cell is created or updated. This represents
 389      * the raw data value.
 390     *
 391     * <p>This value should only be set in subclasses of Cell by the virtualised
 392     * user interface controls that know how to properly work with the Cell
 393     * class.
 394      * @return the data value associated with this cell
 395      */
 396     public final ObjectProperty<T> itemProperty() { return item; }
 397 
 398     /**
 399      * Sets the item to the given value - should not be called directly as the
 400      * item is managed by the virtualized control.
 401      * @param value the new data value to set in this cell
 402      */
 403     public final void setItem(T value) { item.set(value); }
 404 
 405     /**
 406      * Returns the data value associated with this Cell.
 407      * @return the data value associated with this cell
 408      */
 409     public final T getItem() { return item.get(); }
 410 
 411 
 412 
 413     // --- empty
 414     private ReadOnlyBooleanWrapper empty = new ReadOnlyBooleanWrapper(true) {
 415         @Override protected void invalidated() {
 416             final boolean active = get();
 417             pseudoClassStateChanged(PSEUDO_CLASS_EMPTY,   active);
 418             pseudoClassStateChanged(PSEUDO_CLASS_FILLED, !active);
 419         }
 420 
 421         @Override
 422         public Object getBean() {
 423             return Cell.this;
 424         }
 425 
 426         @Override
 427         public String getName() {
 428             return "empty";
 429         }
 430     };
 431 
 432     /**
 433      * A property used to represent whether the cell has any contents.
 434      * If true, then the Cell contains no data and is not associated with any
 435      * data item in the virtualized Control.
 436      *
 437      * <p>When a cell is empty, it can be styled differently via the 'empty'
 438      * CSS pseudo class state. For example, it may not receive any
 439      * alternate row highlighting, or it may not receive hover background
 440      * fill when hovered.
 441      * @return the representation of whether this cell has any contents
 442      */
 443     public final ReadOnlyBooleanProperty emptyProperty() { return empty.getReadOnlyProperty(); }
 444 
 445     private void setEmpty(boolean value) { empty.set(value); }
 446 
 447     /**
 448      * Returns a boolean representing whether the cell is considered to be empty
 449      * or not.
 450      * @return true if cell is empty, otherwise false
 451      */
 452     public final boolean isEmpty() { return empty.get(); }
 453 
 454 
 455 
 456     // --- selected
 457     private ReadOnlyBooleanWrapper selected = new ReadOnlyBooleanWrapper() {
 458         @Override protected void invalidated() {
 459             pseudoClassStateChanged(PSEUDO_CLASS_SELECTED, get());
 460         }
 461 
 462         @Override
 463         public Object getBean() {
 464             return Cell.this;
 465         }
 466 
 467         @Override
 468         public String getName() {
 469             return "selected";
 470         }
 471     };
 472 
 473     /**
 474      * Indicates whether or not this cell has been selected. For example, a
 475      * ListView defines zero or more cells as being the "selected" cells.
 476      * @return the representation of whether this cell has been selected
 477      */
 478     public final ReadOnlyBooleanProperty selectedProperty() { return selected.getReadOnlyProperty(); }
 479 
 480     void setSelected(boolean value) { selected.set(value); }
 481 
 482     /**
 483      * Returns whether this cell is currently selected or not.
 484      * @return True if the cell is selected, false otherwise.
 485      */
 486     public final boolean isSelected() { return selected.get(); }
 487 
 488 
 489 
 490     // --- Editing
 491     private ReadOnlyBooleanWrapper editing;
 492 
 493     private void setEditing(boolean value) {
 494         editingPropertyImpl().set(value);
 495     }
 496 
 497     /**
 498      * Represents whether the cell is currently in its editing state or not.
 499      * @return true if this cell is currently in its editing state, otherwise
 500      * false
 501      */
 502     public final boolean isEditing() {
 503         return editing == null ? false : editing.get();
 504     }
 505 
 506     /**
 507      * Property representing whether this cell is currently in its editing state.
 508      * @return the representation of whether this cell is currently in its
 509      * editing state
 510      */
 511     public final ReadOnlyBooleanProperty editingProperty() {
 512         return editingPropertyImpl().getReadOnlyProperty();
 513     }
 514 
 515     private ReadOnlyBooleanWrapper editingPropertyImpl() {
 516         if (editing == null) {
 517             editing = new ReadOnlyBooleanWrapper(this, "editing");
 518         }
 519         return editing;
 520     }
 521 
 522 
 523 
 524     // --- Editable
 525     private BooleanProperty editable;
 526 
 527     /**
 528      * Allows for certain cells to not be able to be edited. This is useful in
 529      * cases where, say, a List has 'header rows' - it does not make sense for
 530      * the header rows to be editable, so they should have editable set to
 531      * false.
 532      *
 533      * @param value A boolean representing whether the cell is editable or not.
 534      *      If true, the cell is editable, and if it is false, the cell can not
 535      *      be edited.
 536      */
 537     public final void setEditable(boolean value) {
 538         editableProperty().set(value);
 539     }
 540 
 541     /**
 542      * Returns whether this cell is allowed to be put into an editing state.
 543      * @return true if this cell is allowed to be put into an editing state,
 544      * otherwise false
 545      */
 546     public final boolean isEditable() {
 547         return editable == null ? true : editable.get();
 548     }
 549 
 550     /**
 551      * A property representing whether this cell is allowed to be put into an
 552      * editing state. By default editable is set to true in Cells (although for
 553      * a subclass of Cell to be allowed to enter its editing state, it may have
 554      * to satisfy additional criteria. For example, ListCell requires that the
 555      * ListView {@link ListView#editableProperty() editable} property is also
 556      * true.
 557      * @return the representation of whether this cell is allowed to be put into
 558      * an editing state
 559      */
 560     public final BooleanProperty editableProperty() {
 561         if (editable == null) {
 562             editable = new SimpleBooleanProperty(this, "editable", true);
 563         }
 564         return editable;
 565     }
 566 
 567 
 568 
 569     /***************************************************************************
 570      *                                                                         *
 571      * Public API                                                              *
 572      *                                                                         *
 573      **************************************************************************/
 574 
 575     /**
 576      * Call this function to transition from a non-editing state into an editing
 577      * state, if the cell is editable. If this cell is already in an editing
 578      * state, it will stay in it.
 579      */
 580     public void startEdit() {
 581         if (isEditable() && !isEditing() && !isEmpty()) {
 582             setEditing(true);
 583         }
 584     }
 585 
 586     /**
 587      * Call this function to transition from an editing state into a non-editing
 588      * state, without saving any user input.
 589      */
 590     public void cancelEdit() {
 591         if (isEditing()) {
 592             setEditing(false);
 593         }
 594     }
 595 
 596     /**
 597      * Call this function when appropriate (based on the user interaction requirements
 598      * of your cell editing user interface) to do two things:
 599      *
 600      * <ol>
 601      *     <li>Fire the appropriate events back to the backing UI control (e.g.
 602      *     {@link ListView}). This will begin the process of pushing this edit
 603      *     back to the relevant data source / property (although it does not
 604      *     guarantee that this will be successful - that is dependent upon the
 605      *     specific edit commit handler being used). Refer to the UI control
 606      *     class javadoc for more detail.</li>
 607      *     <li>Begin the transition from an editing state into a non-editing state.</li>
 608      * </ol>
 609      *
 610      * <p>In general there is no need to override this method in custom cell
 611      * implementations - it should be sufficient to simply call this method
 612      * when appropriate (e.g. when the user pressed the Enter key, you may do something
 613      * like {@code cell.commitEdit(converter.fromString(textField.getText()));}</p>
 614      *
 615      * @param newValue The value as input by the end user, which should be
 616      *      persisted in the relevant way given the data source underpinning the
 617      *      user interface and the install edit commit handler of the UI control.
 618      */
 619     public void commitEdit(T newValue) {
 620         if (isEditing()) {
 621             setEditing(false);
 622         }
 623     }
 624 
 625     /** {@inheritDoc} */
 626     @Override protected void layoutChildren() {
 627         if (itemDirty) {
 628             updateItem(getItem(), isEmpty());
 629             itemDirty = false;
 630         }
 631 
 632         super.layoutChildren();
 633     }
 634 
 635 
 636 
 637     /***************************************************************************
 638      *                                                                         *
 639      * Expert API                                                              *
 640      *                                                                         *
 641      **************************************************************************/
 642 
 643     /**
 644      * The updateItem method should not be called by developers, but it is the
 645      * best method for developers to override to allow for them to customise the
 646      * visuals of the cell. To clarify, developers should never call this method
 647      * in their code (they should leave it up to the UI control, such as the
 648      * {@link javafx.scene.control.ListView} control) to call this method. However,
 649      * the purpose of having the updateItem method is so that developers, when
 650      * specifying custom cell factories (again, like the ListView
 651      * {@link javafx.scene.control.ListView#cellFactoryProperty() cell factory}),
 652      * the updateItem method can be overridden to allow for complete customisation
 653      * of the cell.
 654      *
 655      * <p>It is <strong>very important</strong> that subclasses
 656      * of Cell override the updateItem method properly, as failure to do so will
 657      * lead to issues such as blank cells or cells with unexpected content
 658      * appearing within them. Here is an example of how to properly override the
 659      * updateItem method:
 660      *
 661      * <pre>
 662      * protected void updateItem(T item, boolean empty) {
 663      *     super.updateItem(item, empty);
 664      *
 665      *     if (empty || item == null) {
 666      *         setText(null);
 667      *         setGraphic(null);
 668      *     } else {
 669      *         setText(item.toString());
 670      *     }
 671      * }
 672      * </pre>
 673      *
 674      * <p>Note in this code sample two important points:
 675      * <ol>
 676      *     <li>We call the super.updateItem(T, boolean) method. If this is not
 677      *     done, the item and empty properties are not correctly set, and you are
 678      *     likely to end up with graphical issues.</li>
 679      *     <li>We test for the <code>empty</code> condition, and if true, we
 680      *     set the text and graphic properties to null. If we do not do this,
 681      *     it is almost guaranteed that end users will see graphical artifacts
 682      *     in cells unexpectedly.</li>
 683      * </ol>
 684      *
 685      * @param item The new item for the cell.
 686      * @param empty whether or not this cell represents data from the list. If it
 687      *        is empty, then it does not represent any domain data, but is a cell
 688      *        being used to render an "empty" row.
 689      */
 690     protected void updateItem(T item, boolean empty) {
 691         setItem(item);
 692         setEmpty(empty);
 693         if (empty && isSelected()) {
 694             updateSelected(false);
 695         }
 696     }
 697 
 698     /**
 699      * Updates whether this cell is in a selected state or not.
 700      * @param selected whether or not to select this cell.
 701      */
 702     public void updateSelected(boolean selected) {
 703         if (selected && isEmpty()) return;
 704         boolean wasSelected = isSelected();
 705         setSelected(selected);
 706 
 707         if (wasSelected != selected) {
 708             markCellDirty();
 709         }
 710     }
 711 
 712     /**
 713      * This method is called by Cell subclasses so that certain CPU-intensive
 714      * actions (specifically, calling {@link #updateItem(Object, boolean)}) are
 715      * only performed when necessary (that is, they are only performed
 716      * when the currently set {@link #itemProperty() item} is considered to be
 717      * different than the proposed new item that could be set).
 718      *
 719      * <p>The default implementation of this method tests against equality, but
 720      * developers are able to override this method to perform checks in other ways
 721      * that are specific to their domain.</p>
 722      *
 723      * @param oldItem The currently-set item contained within the cell (i.e. it is
 724      *                the same as what is available via {@link #getItem()}).
 725      * @param newItem The item that will be set in the cell, if this method
 726      *                returns true. If this method returns false, it may not be
 727      *                set.
 728      * @return Returns true if the new item is considered to be different than
 729      *         the old item. By default this method tests against equality, but
 730      *         subclasses may alter the implementation to test appropriate to
 731      *         their needs.
 732      * @since JavaFX 8u40
 733      */
 734     protected boolean isItemChanged(T oldItem, T newItem) {
 735         return oldItem != null ? !oldItem.equals(newItem) : newItem != null;
 736     }
 737 
 738     /**
 739      * Developers of custom cell implementations should override this method when
 740      * the cell provides editing functionality, with this method returning the
 741      * user input after the user has interacted with the editing components.
 742      * The form of the returned data (wrapped in an {@link Optional}) should
 743      * be the same as the form of the underlying data model, hence the
 744      * use of the {@code T} generic type. If no value is available, or if the
 745      * value to be returned is invalid, {@code Optional.empty()} should be returned
 746      * to indicate that the commit should not proceed..
 747      *
 748      * @return The value provided by the user into this cell when it was in its
 749      *      editing state, in the form of the underlying data model. If the value
 750      *      is invalid or unable to be determined, {@code Optional.empty()} should
 751      *      be returned.
 752      * @since 10
 753      */
 754     protected Optional<T> getEditorValue() {
 755         return Optional.empty();
 756     }
 757 
 758 
 759 
 760     /***************************************************************************
 761      *                                                                         *
 762      * Private Implementation                                                  *
 763      *                                                                         *
 764      **************************************************************************/
 765 
 766     // itemDirty and markCellDirty introduced as a solution for JDK-8145588.
 767     // In the fullness of time, a more fully developed solution can be developed
 768     // that offers a public API around this lazy-dirty impl.
 769     private boolean itemDirty = false;
 770     private final void markCellDirty() {
 771         itemDirty = true;
 772         requestLayout();
 773     }
 774 
 775     void attemptEditCommit() {
 776         // The user has shifted focus, so we should cancel the editing on this cell
 777         getEditorValue().ifPresentOrElse(this::commitEdit, this::cancelEdit);
 778     }
 779 
 780 
 781     /***************************************************************************
 782      *                                                                         *
 783      * Stylesheet Handling                                                     *
 784      *                                                                         *
 785      **************************************************************************/
 786 
 787     private static final String DEFAULT_STYLE_CLASS = "cell";
 788     private static final PseudoClass PSEUDO_CLASS_SELECTED =
 789             PseudoClass.getPseudoClass("selected");
 790     private static final PseudoClass PSEUDO_CLASS_EMPTY =
 791             PseudoClass.getPseudoClass("empty");
 792     private static final PseudoClass PSEUDO_CLASS_FILLED =
 793             PseudoClass.getPseudoClass("filled");
 794 
 795     /**
 796      * Returns the initial focus traversable state of this control, for use
 797      * by the JavaFX CSS engine to correctly set its initial value. This method
 798      * is overridden as by default UI controls have focus traversable set to true,
 799      * but that is not appropriate for this control.
 800      *
 801      * @since 9
 802      */
 803     @Override protected Boolean getInitialFocusTraversable() {
 804         return Boolean.FALSE;
 805     }
 806 }