
io.datafx.control.TableViewFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ui Show documentation
Show all versions of ui Show documentation
Visualizing Enterprise Data in JavaFX
The newest version!
/**
* Copyright (c) 2011, 2013, Jonathan Giles, Johan Vos, Hendrik Ebbers
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of DataFX, the website javafxdata.org, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.datafx.control;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.ChoiceBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
/**
* A convenience class intended to make creating a TableView easier. In
* particular, this class can create a TableView, as well as default TableColumn
* instances which are preconfigured with {@link javafx.scene.control.TableColumn#cellValueFactoryProperty() cell
* value factories} that are able to extract the relevant data from a given
* Class type.
*
* In addition to this, the TableViewFactory is able to refine the
* automatically generated TableColumns by reducing the columns added to the
* TableView, as well as renaming and reordering.
*
*
An example of using this API to create a TableView is shown below:
*
*
*
* TODO: Example removed
*
*
*
* @author Jonathan Giles
*/
public class TableViewFactory {
private TableViewFactory() {
}
public static TableView create(Class extends S> dataType) {
List> columns = createColumns(dataType);
TableView table = new TableView();
table.getColumns().setAll(columns);
return table;
}
public static TableViewFactory create(List extends S> items) {
return create(FXCollections.observableArrayList(items));
}
public static TableViewFactory create(Class extends S> dataType, List items) {
return create(dataType, FXCollections.observableArrayList(items));
}
public static TableViewFactory create(ObservableList extends S> items) {
return create(null, FXCollections.observableArrayList(items));
}
public static TableViewFactory create(Class extends S> dataType, final ObservableList items) {
if (items == null) {
throw new NullPointerException("items can not be null");
}
final TableView table = new TableView();
table.setItems(items);
table.setEditable(true);
if (dataType == null && table.getItems().isEmpty()) {
// we'll have to create the columns the first time the items list
// changes, so let's hook in a listener
InvalidationListener listener = new InvalidationListener() {
@Override
public void invalidated(Observable o) {
if (!table.getItems().isEmpty()) {
createColumns(table);
// remove listener
items.removeListener(this);
}
}
};
table.getItems().addListener(listener);
} else {
createColumns(table);
}
return TableViewFactory.configure(table);
}
private static void createColumns(TableView table) {
@SuppressWarnings("unchecked")
Class extends S> actualDataType = (Class extends S>)table.getItems().get(0).getClass();
if (actualDataType != null) {
List> columns = createColumns(actualDataType);
table.getColumns().setAll(columns);
}
}
private static List> createColumns(Class extends S> dataType) {
List> columns = new ArrayList>();
try {
// TODO inspect the class, create columns for all public properties
BeanInfo beanInfo = Introspector.getBeanInfo(dataType);
PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
for (int i = 0; i < properties.length; i++) {
PropertyDescriptor pd = properties[i];
if ("class".equals(pd.getName())) {
continue;
}
if (pd.getReadMethod() == null) {
continue;
}
Class> propertyDataType = pd.getPropertyType();
// System.out.println("Name: " + pd.getName() + ", class: " + propertyDataType);
String displayName = makePrettyDisplayName(pd.getDisplayName());
TableColumn column = new TableColumn();
column.setText(displayName);
column.setCellValueFactory(new PropertyValueFactory(pd.getName()));
columns.add(column);
// TODO set property name in the TableColumn properties map
// install custom cell factory
if (propertyDataType.isEnum()) {
Object[] enumConstants = propertyDataType.getEnumConstants();
column.setCellFactory(ChoiceBoxTableCell.forTableColumn(enumConstants));
} else if (propertyDataType == boolean.class) {
column.setCellFactory(CheckBoxTableCell.forTableColumn(column));
} else if (propertyDataType == String.class) {
column.setCellFactory(TextFieldTableCell.forTableColumn());
}
}
} catch (IntrospectionException ex) {
ex.printStackTrace();
}
return columns;
}
private static String makePrettyDisplayName(String name) {
// split at each capital letter
if (name == null || name.length() == 0) {
return name;
}
if (name.length() > 1 && Character.isUpperCase(name.charAt(1))
&& Character.isUpperCase(name.charAt(0))) {
return name;
}
char chars[] = name.toCharArray();
List charList = new ArrayList(chars.length);
for (int i = 0; i < chars.length; i++) {
char c0 = chars[i];
char c1 = i > 0 ? chars[i - 1] : ' ';
if (i == 0) {
charList.add(Character.toUpperCase(c0));
continue;
}
if (Character.isUpperCase(c0) && !Character.isUpperCase(c1)) {
// insert space
charList.add(' ');
}
charList.add(c0);
}
chars = new char[charList.size()];
for (int i = 0; i < charList.size(); i++) {
chars[i] = charList.get(i);
}
return new String(chars);
}
private TableView table;
private ObservableList> columns;
private boolean columnSelectPerformed = false;
private ObservableList> finalColumns;
public static TableViewFactory configure(TableView table) {
return new TableViewFactory(table);
}
public static void print(TableView table) {
print(table.getColumns());
}
public static void print(ObservableList> columns) {
System.out.println("Columns:");
for (int i = 0; i < columns.size(); i++) {
TableColumn tc = columns.get(i);
System.out.println(" Text: " + tc.getText());
}
}
private TableViewFactory(TableView table/*, ObservableList columns*/) {
this.table = table;
this.columns = table.getColumns(); //columns == null ? table.getColumns() : columns;
this.finalColumns = FXCollections.observableArrayList();
if (this.columns == null) {
throw new NullPointerException("Columns can not be null");
}
}
public TableViewFactory selectColumns(String... names) {
if (names == null || names.length == 0) {
return this;
}
TableColumn tc;
for (int i = 0; i < names.length; i++) {
String name = names[i];
for (int j = 0; j < columns.size(); j++) {
tc = columns.get(j);
if (name == null) continue;
if (name.equals(tc.getText())) {
finalColumns.add(tc);
columnSelectPerformed = true;
}
}
}
return this;
}
public TableViewFactory renameColumn(String oldName, String newName) {
if (oldName == null || oldName.isEmpty() || newName == null || newName.isEmpty()) {
return this;
}
for (int i = 0; i < columns.size(); i++) {
TableColumn tc = columns.get(i);
if (oldName.equals(tc.getText())) {
tc.setText(newName);
break;
}
}
return this;
}
public ObservableList> buildColumns() {
return finalColumns;
}
public TableView buildTableView() {
if (table == null) {
table = new TableView();
}
if (columnSelectPerformed) {
table.getColumns().setAll(finalColumns);
} else if (!table.getColumns().equals(columns)) {
table.getColumns().setAll(columns);
}
return table;
}
// public ObservableList> buildAndSetInTableView() {
// if (table == null) {
// throw new IllegalStateException("Can not set columns in TableView, as TableView instance is null");
// }
// table.getColumns().setAll(finalColumns);
// return finalColumns;
// }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy