
import javafx.application.Platform;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.stage.StageStyle;

import java.util.Objects;
import java.util.concurrent.CountDownLatch;


public class MyTest extends Application {

    @Override
    public void start(Stage stage) {
        
        try {
        
            //Build the table view.
            TableView<MyBean> table = new TableView<>(FXCollections.observableArrayList(
                                                                          new MyBean(1, true),
                                                                          new MyBean(2, false),
                                                                          new MyBean(3, true),
                                                                          new MyBean(4, true),
                                                                          new MyBean(5, false),
                                                                          new MyBean(6, false),
                                                                          new MyBean(7, true),
                                                                          new MyBean(8, true)
                                                                          ));
            
            //Build an integer column
            TableColumn<MyBean, Integer> idColumn = new TableColumn<MyBean, Integer>("ID");
            idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
            idColumn.setEditable(false);
            
            //Build a CheckBox column for the SimpleProperty.
            TableColumn<MyBean, Boolean> deathColumn = new TableColumn<MyBean, Boolean>("Is Death");
            deathColumn.setCellValueFactory(new PropertyValueFactory<>("death"));
            deathColumn.setCellFactory(CheckBoxTableCell.forTableColumn(deathColumn));
            deathColumn.setEditable(true);
            
            //Build a checkbox column for the readonly property bound to death.not()
            TableColumn<MyBean, Boolean> canUseColumn = new TableColumn<MyBean, Boolean>("Can Use");
            canUseColumn.setCellValueFactory(new PropertyValueFactory<>("canUse"));
            canUseColumn.setCellFactory(CheckBoxTableCell.forTableColumn(canUseColumn));
            canUseColumn.setEditable(false);
            
            //Build a text column to see the value at canUseColumn
            TableColumn<MyBean, Boolean> canUsetext = new TableColumn<MyBean, Boolean>("Can Use?");
            canUsetext.setCellValueFactory(new PropertyValueFactory<>("canUse"));
            canUsetext.setEditable(false);
            
            //Add columns
            table.getColumns().addAll(idColumn, deathColumn, canUseColumn, canUsetext);
            table.setEditable(true);
            
            //Create the scene
            Scene scene = new Scene(table);
            
            //Create the window and show
            stage.setScene(scene);
            stage.show();
            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
             !Looking at the window, canUseText shows the text for the boolean value !
             !read from the canUse property. And you can see that it doesn't match with !
             !the state of check boxes at the checkBox column. !
             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
             */
        }catch(Exception e){
            
        }
    }
    
    
    /**
     * An hypotetical bean class.
     */
    @SuppressWarnings({"WeakerAccess", "unused"})
    public static class MyBean {
        /**
         * Autogenerated numeric ID.
         */
        private final IntegerProperty id = new SimpleIntegerProperty();
        /**
         * If this object is death.
         */
        private final BooleanProperty death = new SimpleBooleanProperty();
        /**
         * Flag to know if you can use this object. Of course, it's the opossite of death.
         */
        private final ReadOnlyBooleanWrapper canUse = new ReadOnlyBooleanWrapper();
        
        /**
         * Constructs a new bean object.
         *
         * @param id autogenerated id.
         * @param death value of death property.
         */
        public MyBean(int id, boolean death) {
            canUse.bind(this.death.not());
            setId(id);
            setDeath(death);
        }
        
        public final IntegerProperty idProperty() {
            return id;
        }
        
        public final int getId() {
            return id.get();
        }
        
        public final void setId(int value) {
            id.set(value);
        }
        
        public final BooleanProperty deathProperty() {
            return death;
        }
        
        public final boolean isDeath() {
            return death.get();
        }
        
        public final void setDeath(boolean value) {
            death.set(value);
        }
        
        public final ReadOnlyBooleanProperty canUseProperty() {
            return canUse.getReadOnlyProperty();
        }
        
        // This is the workaround
        /*public ReadOnlyBooleanWrapper canUseProperty(){
            return canUse;
        }*/
        
        public final boolean getCanUse() {
            return canUse.get();
        }
        
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            MyBean myBean = (MyBean) o;
            return Objects.equals(getId(), myBean.getId());
        }
        
        @Override
        public int hashCode() {
            return Objects.hash(getId());
        }
    }
}
