package samples; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.ChoiceBox; import javafx.scene.control.Label; import javafx.scene.control.SelectionMode; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TableColumn; import javafx.scene.control.TablePosition; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import net.jonathangiles.hacking.tableview.cellSpan.CellSpan; import net.jonathangiles.hacking.tableview.cellSpan.CellSpanTableView; import net.jonathangiles.hacking.tableview.cellSpan.SpanModel; import samples.misc.Person; /** * * @author Jonathan Giles */ public class CellSpanTableViewSample extends Application { /** * @param args * the command line arguments */ public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("CellSpanTableView!"); // we need a TabPane to see the samples TabPane tabPane = new TabPane(); tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE); Tab standardTableViewTab = new Tab("Standard"); buildStandardTableViewTab(standardTableViewTab); tabPane.getTabs().add(standardTableViewTab); Tab rowSpanTableViewTab = new Tab("Row Span"); buildRowSpanTableViewTab(rowSpanTableViewTab); tabPane.getTabs().add(rowSpanTableViewTab); Tab columnSpanTableViewTab = new Tab("Column Span"); buildColumnSpanTableViewTab(columnSpanTableViewTab); tabPane.getTabs().add(columnSpanTableViewTab); Tab rowAndColumnSpanTableViewTab = new Tab("Row/Column Span"); buildRowAndColumnSpanTableViewTab(rowAndColumnSpanTableViewTab); tabPane.getTabs().add(rowAndColumnSpanTableViewTab); // show on screen StackPane root = new StackPane(); root.getChildren().add(tabPane); Scene scene = new Scene(root, 520, 600); // scene.getStylesheets().add(CellSpanTableView.class.getResource("cell-span.css").toExternalForm()); primaryStage.setScene(scene); primaryStage.show(); } private TableView buildBasicTableView(boolean enableCellSpan) { // define columns TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>( "First Name"); firstNameCol.setPrefWidth(120); firstNameCol .setCellValueFactory(new PropertyValueFactory<Person, String>( "firstName")); TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>( "Last Name"); lastNameCol.setPrefWidth(120); lastNameCol .setCellValueFactory(new PropertyValueFactory<Person, String>( "lastName")); TableColumn<Person, String> balanceCol = new TableColumn<Person, String>( "Balance"); balanceCol.setPrefWidth(120); balanceCol .setCellValueFactory(new PropertyValueFactory<Person, String>( "balance")); // create a tableview TableView<Person> tableView = enableCellSpan ? new CellSpanTableView<Person>() : new TableView<Person>(); tableView.getColumns().addAll(firstNameCol, lastNameCol, balanceCol); // insert the test data tableView.setItems(Person.getTestList()); // FXCollections.observableArrayList( // new Person("Jonathan", "Giles", true, 38.23), // new Person("Richard", "Bair", true, 12.32), // new Person("Jasper", "Potts", true, 43.23) // )); // for exploration, we enable single cell selection mode, and also print // out // some debug output to show the currently selected table position final TableView.TableViewSelectionModel<Person> sm = tableView .getSelectionModel(); sm.getSelectedCells().addListener( new ListChangeListener<TablePosition>() { @Override public void onChanged(Change<? extends TablePosition> change) { if (sm.getSelectedCells().isEmpty()) { // System.out.println("No selection"); } else { TablePosition tp = sm.getSelectedCells().get(0); if (tp == null) return; System.out.println("Selection: [ row: " + tp.getRow() + ", column: " + tp.getColumn() + ", column name: " + tp.getTableColumn().getText() + " ] "); } } }); return tableView; } private BorderPane buildBorderPane(Tab tab) { BorderPane pane = new BorderPane(); pane.setPadding(new Insets(10, 10, 10, 10)); tab.setContent(pane); return pane; } private void buildStandardTableViewTab(Tab tab) { BorderPane pane = buildBorderPane(tab); TableView tableView = buildBasicTableView(false); pane.setCenter(tableView); pane.setRight(buildCommonControlGrid(tableView)); } private void buildRowSpanTableViewTab(Tab tab) { BorderPane pane = buildBorderPane(tab); CellSpanTableView tableView = (CellSpanTableView) buildBasicTableView(true); pane.setCenter(tableView); // install the span model tableView.setSpanModel(new SpanModel() { private final CellSpan spanTwoRows = new CellSpan(2, 1); @Override public CellSpan getCellSpanAt(int rowIndex, int columnIndex) { return rowIndex % 3 == 0 && columnIndex == 1 ? spanTwoRows : null; } @Override public boolean isCellSpanEnabled() { return true; } }); pane.setRight(buildCommonControlGrid(tableView)); } private void buildColumnSpanTableViewTab(Tab tab) { BorderPane pane = buildBorderPane(tab); CellSpanTableView tableView = (CellSpanTableView) buildBasicTableView(true); pane.setCenter(tableView); // install the span model tableView.setSpanModel(new SpanModel() { private final CellSpan spanTwoColumns = new CellSpan(1, 2); @Override public CellSpan getCellSpanAt(int rowIndex, int columnIndex) { return rowIndex % 2 == 0 && columnIndex == 0 ? spanTwoColumns : null; } @Override public boolean isCellSpanEnabled() { return true; } }); pane.setRight(buildCommonControlGrid(tableView)); } private void buildRowAndColumnSpanTableViewTab(Tab tab) { BorderPane pane = buildBorderPane(tab); CellSpanTableView tableView = (CellSpanTableView) buildBasicTableView(true); pane.setCenter(tableView); // install the span model tableView.setSpanModel(new SpanModel() { private final CellSpan spanTwoRowsAndTwoColumns = new CellSpan(2, 2); @Override public CellSpan getCellSpanAt(int rowIndex, int columnIndex) { return rowIndex % 3 == 0 && columnIndex == 0 ? spanTwoRowsAndTwoColumns : null; } @Override public boolean isCellSpanEnabled() { return true; } }); pane.setRight(buildCommonControlGrid(tableView)); } private GridPane buildCommonControlGrid(final TableView tableView) { GridPane grid = new GridPane(); grid.setHgap(5); grid.setVgap(5); grid.setPadding(new Insets(5, 5, 5, 5)); // allow user to change between cell selection and row selection modes ChoiceBox<String> rowOrCellSelectionBox = new ChoiceBox( FXCollections.observableArrayList("Row-based", "Cell-based")); rowOrCellSelectionBox.getSelectionModel().select(0); rowOrCellSelectionBox.getSelectionModel().selectedItemProperty() .addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue ov, String t, String t1) { if ("Row-based".equals(t1)) { tableView.getSelectionModel() .setCellSelectionEnabled(false); } else if ("Cell-based".equals(t1)) { tableView.getSelectionModel() .setCellSelectionEnabled(true); } } }); ChoiceBox<SelectionMode> selectionModeBox = new ChoiceBox( FXCollections.observableArrayList(SelectionMode.values())); selectionModeBox.getSelectionModel().select(SelectionMode.SINGLE); selectionModeBox.getSelectionModel().selectedItemProperty() .addListener(new ChangeListener<SelectionMode>() { @Override public void changed(ObservableValue ov, SelectionMode t, SelectionMode t1) { tableView.getSelectionModel().setSelectionMode(t1); } }); grid.add(new Label("Selection Mode:"), 1, 1); grid.add(rowOrCellSelectionBox, 1, 2); grid.add(selectionModeBox, 1, 3); return grid; } }