All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tentackle.fx.table.DefaultTableColumnConfiguration Maven / Gradle / Ivy

/*
 * Tentackle - https://tentackle.org.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

package org.tentackle.fx.table;

import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.util.Callback;

import org.tentackle.fx.FxComponent;
import org.tentackle.fx.FxRuntimeException;
import org.tentackle.fx.bind.FxTableBinding;
import org.tentackle.misc.FormatHelper;
import org.tentackle.reflect.ReflectionHelper;

import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;

/**
 * Default configuration for a table column.
* * @param type of the objects contained within the table's items list * @param type of the content in all cells in this column * * @author harald */ public class DefaultTableColumnConfiguration implements TableColumnConfiguration { /** * The table config. */ private final DefaultTableConfiguration tableConfiguration; /** * The column name. */ private final String name; /** * The displayed name. */ private String displayedName; /** * The table column. */ private FxTableColumn tableColumn; /** * The tree table column. */ private FxTreeTableColumn treeTableColumn; /** * The binding. */ private FxTableBinding binding; /** * The column class. */ private Class type; /** * The generic type. */ private Type genericType; /** * For formatting. */ private String pattern; /** * The decimal format.
* null if pattern and scale is null. */ private DecimalFormat numberFormat; /** * The date format.
* null if pattern is null. */ private DateFormat dateFormat; /** * Date and time formatter.
* null if pattern is null. */ private DateTimeFormatter dateTimeFormatter; /** * Alignment within cell. */ private Pos alignment; /** * Blank out numeric fields if zero. */ private Boolean blankZero; /** * Unsigned numeric field only. */ private Boolean unsigned; /** * Valid input characters. */ private String validChars; /** * Invalid input characters. */ private String invalidChars; /** * Autoselect cell contents when editing starts. */ private Boolean autoSelect; /** * Max. columns in cell. */ private Integer maxColumns; /** * The numeric scale. */ private Integer scale; /** * Case conversion. */ private Boolean caseConversion; /** * Summable or not. */ private Boolean summable; /** * Editable or not. */ private Boolean editable; /** * Optional editor. */ private FxComponent editor; /** * Create a column config. * * @param tableConfiguration the table config * @param name the column's binding path * @param displayedName the displayed column name */ public DefaultTableColumnConfiguration(DefaultTableConfiguration tableConfiguration, String name, String displayedName) { this.tableConfiguration = tableConfiguration; this.name = name; this.displayedName = displayedName; } @Override public String toString() { return tableConfiguration.getName() + "." + name; } @Override public DefaultTableConfiguration getTableConfiguration() { return tableConfiguration; } @Override public String getName() { return name; } @Override public String getDisplayedName() { return displayedName; } @Override public void setDisplayedName(String displayedName) { this.displayedName = displayedName; if (tableColumn != null) { tableColumn.setText(displayedName); } } @Override public void setType(Class type) { this.type = type; } @Override public void setGenericType(Type genericType) { this.genericType = genericType; } @Override public Type getGenericType() { return genericType; } @Override public Class getType() { return type; } @Override public void setPattern(String pattern) { this.pattern = pattern; numberFormat = null; } @Override public String getPattern() { return pattern; } @Override public DecimalFormat getNumberFormat() { if (numberFormat == null && (pattern != null || scale != null)) { // scale or pattern given if (pattern == null) { pattern = FormatHelper.getIntegerPattern(); } numberFormat = new DecimalFormat(pattern); if (scale == null) { // determine from format scale = 0; String p = getPattern(); int dotNdx = p.lastIndexOf('.'); if (dotNdx >= 0) { // count zeros after dot for (++dotNdx; dotNdx < p.length(); dotNdx++) { if (p.charAt(dotNdx) != '0') { break; } scale++; } } } else { // apply scale for numberFormat overriding the scale from the format FormatHelper.setScale(numberFormat, scale); } } return numberFormat; } @Override public DateFormat getDateFormat() { if (dateFormat == null && pattern != null) { dateFormat = new SimpleDateFormat(pattern); } return dateFormat; } @Override public DateTimeFormatter getDateTimeFormatter() { if (dateTimeFormatter == null && pattern != null) { dateTimeFormatter = DateTimeFormatter.ofPattern(pattern); } return dateTimeFormatter; } @Override public void setAlignment(Pos alignment) { this.alignment = alignment; } @Override public Pos getAlignment() { return alignment; } @Override public void setBlankZero(Boolean blankZero) { this.blankZero = blankZero; } @Override public Boolean isBlankZero() { return blankZero; } @Override public Boolean isUnsigned() { return unsigned; } @Override public void setUnsigned(Boolean unsigned) { this.unsigned = unsigned; } @Override public String getValidChars() { return validChars; } @Override public void setValidChars(String validChars) { this.validChars = validChars; } @Override public String getInvalidChars() { return invalidChars; } @Override public void setInvalidChars(String invalidChars) { this.invalidChars = invalidChars; } @Override public void setAutoSelect(Boolean autoSelect) { this.autoSelect = autoSelect; } @Override public Boolean isAutoSelect() { return autoSelect; } @Override public void setMaxColumns(Integer maxColumns) { this.maxColumns = maxColumns; } @Override public Integer getMaxColumns() { return maxColumns; } @Override public void setScale(Integer scale) { this.scale = scale; numberFormat = null; } @Override public Integer getScale() { return scale; } @Override public void setCaseConversion(Boolean caseConversion) { this.caseConversion = caseConversion; } @Override public Boolean getCaseConversion() { return caseConversion; } @Override public boolean isSummable() { if (summable != null) { return summable; } return type != null && Number.class.isAssignableFrom( type.isPrimitive() ? ReflectionHelper.primitiveToWrapperClass(type) : type); } @Override public void setSummable(Boolean summable) { this.summable = summable; } @Override public Boolean getSummable() { return summable; } @Override public boolean isEditable() { return Boolean.TRUE.equals(editable) || tableConfiguration != null && tableConfiguration.getEditMode() != TableConfiguration.EDITMODE.NO; } @Override public Boolean getEditable() { return editable; } @Override public void setEditable(Boolean editable) { this.editable = editable; } @Override public FxComponent getEditor() { return editor; } @Override public void setEditor(FxComponent editor) { this.editor = editor; } @Override public void setBinding(FxTableBinding binding) { this.binding = binding; } @Override public FxTableBinding getBinding() { return binding; } @Override public FxTableColumn getTableColumn() { if (tableColumn == null) { tableColumn = createTableColumn(); } return tableColumn; } @Override public FxTreeTableColumn getTreeTableColumn() { if (treeTableColumn == null) { treeTableColumn = createTreeTableColumn(); } return treeTableColumn; } // ------------- for TableView ------------------ /** * Creates the cell value for a given row object. * * @param cdf the cell data features * @return the cell value to display */ protected ObservableValue createTableCellValue(TableColumn.CellDataFeatures cdf) { if (binding == null) { throw new FxRuntimeException("missing binding for " + this); } binding.setBoundRootObject(cdf.getValue()); return new ReadOnlyObjectWrapper<>(binding.getModelValue()); } /** * Creates the cell value factory. * * @return the value factory */ protected Callback, ObservableValue> createTableCellValueFactory() { return this::createTableCellValue; } /** * Creates a table cell.
* The method reference can directly be used as a cell factory. * * @param column the table column * @return the table cell */ protected TableCell createTableCell(TableColumn column) { return new FxTableCell<>(this); } /** * Gets the cell factory. * * @return the cell factory */ protected Callback, TableCell> getTableCellFactory() { return this::createTableCell; } /** * Creates the table column. * * @return the table column */ protected FxTableColumn createTableColumn() { FxTableColumn tc = new FxTableColumn<>(this, displayedName); tc.setCellValueFactory(createTableCellValueFactory()); tc.setCellFactory(getTableCellFactory()); return tc; } // ------------- for TreeTableView ------------------ /** * Creates the treetable cell value for a given row object. * * @param cdf the cell data features * @return the cell value to display */ protected ObservableValue createTreeTableCellValue(TreeTableColumn.CellDataFeatures cdf) { if (binding == null) { throw new FxRuntimeException("missing binding for " + this); } TreeItem treeItem = cdf.getValue(); binding.setBoundRootObject(treeItem == null ? null : treeItem.getValue()); return new ReadOnlyObjectWrapper<>(binding.getModelValue()); } /** * Creates the tree table cell value factory. * * @return the value factory */ protected Callback, ObservableValue> createTreeTableCellValueFactory() { return this::createTreeTableCellValue; } /** * Creates a treetable cell.
* The method reference can directly be used as a cell factory. * * @param column the table column * @return the table cell */ protected TreeTableCell createTreeTableCell(TreeTableColumn column) { return new FxTreeTableCell<>(this); } /** * Creates the treetable cell factory. * * @return the cell factory */ protected Callback, TreeTableCell> createTreeTableCellFactory() { return this::createTreeTableCell; } /** * Creates the tree table column. * * @return the tree table column */ protected FxTreeTableColumn createTreeTableColumn() { FxTreeTableColumn tc = new FxTreeTableColumn<>(this, displayedName); tc.setCellValueFactory(createTreeTableCellValueFactory()); tc.setCellFactory(createTreeTableCellFactory()); return tc; } }