1 /* 2 * Copyright (c) 2012, 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.cell; 27 28 import javafx.beans.property.ObjectProperty; 29 import javafx.beans.property.SimpleObjectProperty; 30 import javafx.scene.control.*; 31 import javafx.util.Callback; 32 import javafx.util.StringConverter; 33 import javafx.util.converter.DefaultStringConverter; 34 35 /** 36 * A class containing a {@link TableCell} implementation that draws a 37 * {@link TextField} node inside the cell. 38 * 39 * <p>By default, the TextFieldTableCell is rendered as a {@link Label} when not 40 * being edited, and as a TextField when in editing mode. The TextField will, by 41 * default, stretch to fill the entire table cell. 42 * 43 * @param <S> The type of the TableView generic type 44 * @param <T> The type of the elements contained within the TableColumn. 45 * @since JavaFX 2.2 46 */ 47 public class TextFieldTableCell<S,T> extends TableCell<S,T> { 48 49 /*************************************************************************** 50 * * 51 * Static cell factories * 52 * * 53 **************************************************************************/ 54 55 /** 56 * Provides a {@link TextField} that allows editing of the cell content when 57 * the cell is double-clicked, or when 58 * {@link TableView#edit(int, javafx.scene.control.TableColumn)} is called. 59 * This method will only work on {@link TableColumn} instances which are of 60 * type String. 61 * 62 * @param <S> The type of the TableView generic type 63 * @return A {@link Callback} that can be inserted into the 64 * {@link TableColumn#cellFactoryProperty() cell factory property} of a 65 * TableColumn, that enables textual editing of the content. 66 */ 67 public static <S> Callback<TableColumn<S,String>, TableCell<S,String>> forTableColumn() { 68 return forTableColumn(new DefaultStringConverter()); 69 } 70 71 /** 72 * Provides a {@link TextField} that allows editing of the cell content when 73 * the cell is double-clicked, or when 74 * {@link TableView#edit(int, javafx.scene.control.TableColumn) } is called. 75 * This method will work on any {@link TableColumn} instance, regardless of 76 * its generic type. However, to enable this, a {@link StringConverter} must 77 * be provided that will convert the given String (from what the user typed 78 * in) into an instance of type T. This item will then be passed along to the 79 * {@link TableColumn#onEditCommitProperty()} callback. 80 * 81 * @param <S> The type of the TableView generic type 82 * @param <T> The type of the elements contained within the TableColumn 83 * @param converter A {@link StringConverter} that can convert the given String 84 * (from what the user typed in) into an instance of type T. 85 * @return A {@link Callback} that can be inserted into the 86 * {@link TableColumn#cellFactoryProperty() cell factory property} of a 87 * TableColumn, that enables textual editing of the content. 88 */ 89 public static <S,T> Callback<TableColumn<S,T>, TableCell<S,T>> forTableColumn( 90 final StringConverter<T> converter) { 91 return list -> new TextFieldTableCell<S,T>(converter); 92 } 93 94 95 /*************************************************************************** 96 * * 97 * Fields * 98 * * 99 **************************************************************************/ 100 101 private TextField textField; 102 103 104 105 /*************************************************************************** 106 * * 107 * Constructors * 108 * * 109 **************************************************************************/ 110 111 /** 112 * Creates a default TextFieldTableCell with a null converter. Without a 113 * {@link StringConverter} specified, this cell will not be able to accept 114 * input from the TextField (as it will not know how to convert this back 115 * to the domain object). It is therefore strongly encouraged to not use 116 * this constructor unless you intend to set the converter separately. 117 */ 118 public TextFieldTableCell() { 119 this(null); 120 } 121 122 /** 123 * Creates a TextFieldTableCell that provides a {@link TextField} when put 124 * into editing mode that allows editing of the cell content. This method 125 * will work on any TableColumn instance, regardless of its generic type. 126 * However, to enable this, a {@link StringConverter} must be provided that 127 * will convert the given String (from what the user typed in) into an 128 * instance of type T. This item will then be passed along to the 129 * {@link TableColumn#onEditCommitProperty()} callback. 130 * 131 * @param converter A {@link StringConverter converter} that can convert 132 * the given String (from what the user typed in) into an instance of 133 * type T. 134 */ 135 public TextFieldTableCell(StringConverter<T> converter) { 136 this.getStyleClass().add("text-field-table-cell"); 137 setConverter(converter); 138 } 139 140 141 142 /*************************************************************************** 143 * * 144 * Properties * 145 * * 146 **************************************************************************/ 147 148 // --- converter 149 private ObjectProperty<StringConverter<T>> converter = 150 new SimpleObjectProperty<StringConverter<T>>(this, "converter"); 151 152 /** 153 * The {@link StringConverter} property. 154 * @return the {@link StringConverter} property 155 */ 156 public final ObjectProperty<StringConverter<T>> converterProperty() { 157 return converter; 158 } 159 160 /** 161 * Sets the {@link StringConverter} to be used in this cell. 162 * @param value the {@link StringConverter} to be used in this cell 163 */ 164 public final void setConverter(StringConverter<T> value) { 165 converterProperty().set(value); 166 } 167 168 /** 169 * Returns the {@link StringConverter} used in this cell. 170 * @return the {@link StringConverter} used in this cell 171 */ 172 public final StringConverter<T> getConverter() { 173 return converterProperty().get(); 174 } 175 176 177 178 /*************************************************************************** 179 * * 180 * Public API * 181 * * 182 **************************************************************************/ 183 184 /** {@inheritDoc} */ 185 @Override public void startEdit() { 186 if (! isEditable() 187 || ! getTableView().isEditable() 188 || ! getTableColumn().isEditable()) { 189 return; 190 } 191 super.startEdit(); 192 193 if (isEditing()) { 194 if (textField == null) { 195 textField = CellUtils.createTextField(this, getConverter()); 196 } 197 198 CellUtils.startEdit(this, getConverter(), null, null, textField); 199 } 200 } 201 202 /** {@inheritDoc} */ 203 @Override public void cancelEdit() { 204 super.cancelEdit(); 205 CellUtils.cancelEdit(this, getConverter(), null); 206 } 207 208 /** {@inheritDoc} */ 209 @Override public void updateItem(T item, boolean empty) { 210 super.updateItem(item, empty); 211 CellUtils.updateItem(this, getConverter(), null, null, textField); 212 } 213 }