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

de.factoryfx.javafx.widget.table.TableControlWidget Maven / Gradle / Ivy

package de.factoryfx.javafx.widget.table;

import java.text.DecimalFormat;

import de.factoryfx.data.Data;
import de.factoryfx.javafx.util.UniformDesign;
import de.factoryfx.javafx.widget.Widget;
import javafx.animation.FadeTransition;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.util.Duration;

public class TableControlWidget implements Widget {
    private final HBox target = new HBox();
    private final TableView tableView;
    TextField filterField;
    private final UniformDesign uniformDesign;
    private final TableMenu tableMenu;

    public TableControlWidget(TableView tableView, TableMenu tableMenu,  UniformDesign uniformDesign) {
        this.tableMenu=tableMenu;
        this.tableView = tableView;
        this.uniformDesign = uniformDesign;

        setupTableControls();
        tableMenu.addMenu(tableView);
    }

    public TableControlWidget(TableView tableView, UniformDesign uniformDesign) {
        this(tableView,new TableMenu<>(uniformDesign),uniformDesign);
    }


    public void clearFilter() {
        filterField.clear();
    }

    @Override
    public Node createContent() {
        return target;
    }

    public TableControlWidget hide() {
        target.visibleProperty().set(false);
        return this;
    }

    public void setFilterText(String filter) {
        filterField.setText(filter);
    }

    private void setupTableControls() {
        filterField = new TextField();//(CustomTextField) TextFields.createClearableTextField();

//        filterField.leftProperty().set(uniformDesign.createIcon(FontAwesome.Glyph.FILTER));
        filterField.disableProperty().bind(tableView.disabledProperty().or(tableView.itemsProperty().isNull()));
        filterField.setMinWidth(50);

        HBox.setHgrow(filterField, Priority.ALWAYS);
        final Label count = new Label("");
        FilterTextFieldListener filterTextFieldListener = new FilterTextFieldListener<>();
        filterField.textProperty().addListener(filterTextFieldListener);

        InvalidationListener listener = (observableItems) -> {
            @SuppressWarnings("unchecked") ObservableList list = ((SimpleObjectProperty>) observableItems).get();
            if (!(list instanceof SortedList) && list != null) {
                FilteredList filteredData = new FilteredList<>(list, p -> true);
                SortedList sortedData = new SortedList<>(filteredData);
                tableView.setItems(sortedData);
                sortedData.comparatorProperty().bind(tableView.comparatorProperty());

                filterTextFieldListener.setFilteredData(filteredData);

                count.setText("" + filteredData.size());
                tableView.getItems().addListener((ListChangeListener) c -> {
                    if (c != null) {
                        StringBuilder format = new StringBuilder();
                        for (int i = 0; i < String.valueOf(filteredData.getSource().size()).length(); i++) {
                            format.append("0");
                        }
                        DecimalFormat decimalFormat = new DecimalFormat(format.toString());
                        count.setText(decimalFormat.format(filteredData.size()));
                    }
                });
            }
            if (list == null) {
                count.setText("0");
            }
        };
        tableView.itemsProperty().addListener(listener);
        listener.invalidated(tableView.itemsProperty());

        target.getChildren().add(filterField);
        target.getChildren().add(new Separator(Orientation.VERTICAL));
        target.getChildren().add(count);

        target.setSpacing(3);
        target.setAlignment(Pos.CENTER_LEFT);
        target.setPadding(new Insets(2));

        target.setOpacity(0.35);

        int fadeTransitionDuration = 350;
        double minFadeValue = 0.20;
        ChangeListener focusChangeListener = (observable, oldValue, newValue) -> {
            target.getStyleClass().remove("selectedTableViewControl");
            if (newValue) {
                if (!filterField.focusedProperty().get()) {
                    target.getStyleClass().add("selectedTableViewControl");
                }
                if (target.getOpacity() < 0.999999) {
                    FadeTransition ft = new FadeTransition(Duration.millis(fadeTransitionDuration), target);
                    ft.setFromValue(minFadeValue);
                    ft.setToValue(1.0);
                    ft.play();
                }
            } else {
                if (!filterField.focusedProperty().get() && !tableView.focusedProperty().get()) {
                    target.getStyleClass().remove("selectedTableViewControl");
                    FadeTransition ft = new FadeTransition(Duration.millis(fadeTransitionDuration), target);
                    ft.setFromValue(1.0);
                    ft.setToValue(minFadeValue);
                    ft.play();
                }
            }
        };
        tableView.focusedProperty().addListener(focusChangeListener);
        filterField.focusedProperty().addListener(focusChangeListener);

        //workaround for bug http://stackoverflow.com/questions/37423748/javafx-tablecolumns-headers-not-aligned-with-cells-due-to-vertical-scrollbar
        Platform.runLater(tableView::refresh);

    }

    private static class FilterTextFieldListener implements ChangeListener {
        FilteredList filteredData;

        public FilterTextFieldListener() {
        }

        @Override
        public void changed(ObservableValue observable, String oldValue, String newValue) {
            filteredData.setPredicate(data -> {
                // If filter text is empty, display all.
                if (newValue==null || newValue.isEmpty()) {
                    return true;
                }
                if (data instanceof Data){
                    return ((Data)data).internal().matchSearchText(newValue);
                }
                if (data instanceof String){
                    return ((String) data).toLowerCase().contains(newValue.toLowerCase());
                }

                return true;
            });
        }

        public FilteredList getFilteredData() {
            return filteredData;
        }

        public void setFilteredData(FilteredList filteredData) {
            this.filteredData = filteredData;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy