Created
September 16, 2015 20:53
-
-
Save Groostav/fe3a53ada46f80da0922 to your computer and use it in GitHub Desktop.
Attempts to make tab and commit-on-click work
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com; | |
import com.empowerops.common.exceptions.ExceptionUtilities; | |
import javafx.beans.value.ChangeListener; | |
import javafx.scene.Node; | |
import javafx.scene.control.*; | |
import javafx.scene.input.KeyCode; | |
import javafx.scene.input.KeyEvent; | |
import javafx.scene.input.MouseEvent; | |
import javafx.util.StringConverter; | |
/** | |
* Created by Josh on 1/1/2015. | |
*/ | |
public class OASISTableCell<TTable,TCell> extends TableCell<TTable, TCell> { | |
protected TextField localTextField; | |
protected boolean isCancelEditManually = false; | |
private ChangeListener<TablePosition> focusListener = (e, oldCell, newCell) -> { | |
updateFocus(newCell); | |
}; | |
private ChangeListener<TablePosition<TTable, ?>> terminatingListener = | |
(e, oldPosition, newPosition) -> terminateEdit(newPosition); | |
public OASISTableCell() { | |
tableViewProperty().addListener( | |
(e, oldValue, newValue) -> { | |
uninstallFocusListener(oldValue); | |
installFocusListener(newValue); | |
} | |
); | |
tableViewProperty().addListener( | |
(e, oldTable, newTable) -> { | |
uninstallTerminatingListener(oldTable); | |
installTerminatingListener(newTable); | |
addListenerToTableView(newTable); | |
} | |
); | |
} | |
protected void updateFocus(TablePosition<TTable, ?> focusedCell) { | |
setFocused(match(focusedCell)); | |
} | |
protected boolean match(TablePosition<TTable, ?> pos) { | |
return pos != null && pos.getRow() == getIndex() | |
&& pos.getTableColumn() == getTableColumn(); | |
} | |
@Override | |
public void startEdit() { | |
if (!isEmpty()) { | |
localTextField = new TextField(getString()); | |
localTextField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2); | |
addListenerToTextField(localTextField); | |
setText(null); | |
setGraphic(localTextField); | |
localTextField.selectAll(); | |
super.startEdit(); | |
localTextField.requestFocus(); | |
} | |
} | |
@Override | |
public void updateItem(TCell item, boolean empty) { | |
if (item == getItem()) | |
return; | |
super.updateItem(item, empty); | |
if (item == null) { | |
super.setText(null); | |
super.setGraphic(null); | |
} else if (item instanceof Node) { | |
super.setText(null); | |
super.setGraphic((Node) item); | |
} else { | |
super.setText(item.toString()); | |
super.setGraphic(null); | |
} | |
} | |
@Override | |
public void cancelEdit() { | |
// do nothing, but we have write here | |
} | |
@Override | |
protected Skin<?> createDefaultSkin() { | |
return new OASISTableCellSkin<TTable, TCell>(this); | |
} | |
protected void cancelEditByUser() { | |
super.cancelEdit(); | |
if (null != getItem()) { | |
ExceptionUtilities.failOnException(() -> { | |
setText((String) getItem()); | |
localTextField.setText((String)getItem()); | |
}); | |
} | |
setGraphic(null); | |
} | |
protected void terminateEdit(TablePosition<TTable, ?> newPosition) { | |
if (!isEditing() || !match(newPosition)) { | |
return; | |
} | |
localCommitEdit(); | |
} | |
private String getString() { | |
return getItem() == null ? "" : getItem().toString(); | |
} | |
protected void localCommitEdit() { | |
StringConverter<TCell> converter = new CastingConverter<>(); | |
if (localTextField != null) { | |
TCell edited = converter.fromString(localTextField.getText()); | |
if (! isCancelEditManually ) { | |
super.commitEdit(edited); | |
} | |
isCancelEditManually = false; | |
} | |
} | |
protected void installFocusListener(TableView<TTable> table) { | |
if (table == null) { | |
return; | |
} | |
TableView.TableViewFocusModel<TTable> model = table.getFocusModel(); | |
if (model != null) { | |
model.focusedCellProperty().addListener(focusListener); | |
} | |
} | |
protected void uninstallFocusListener(TableView<TTable> table) { | |
if (table == null) { | |
return; | |
} | |
TableView.TableViewFocusModel<TTable> model = table.getFocusModel(); | |
if (model != null) { | |
model.focusedCellProperty().removeListener(focusListener); | |
} | |
} | |
protected void installTerminatingListener(TableView<TTable> newTable) { | |
if (newTable instanceof OASISTableView) { | |
((OASISTableView<TTable>) newTable).terminatingCellProperty().addListener(terminatingListener); | |
} | |
} | |
protected void uninstallTerminatingListener(TableView<TTable> oldTable) { | |
if (oldTable instanceof OASISTableView) { | |
((OASISTableView) oldTable).terminatingCellProperty().removeListener(terminatingListener); | |
} | |
} | |
public static class CastingConverter<TConverted> extends StringConverter<TConverted> { | |
@Override | |
public String toString(TConverted object) { | |
return (String) object; | |
} | |
@Override | |
public TConverted fromString(String string) { | |
return (TConverted) string; | |
} | |
} | |
protected void addListenerToTableView(TableView<TTable> tableView) { | |
tableView.setOnKeyReleased( | |
(KeyEvent event) -> { | |
if (event.getCode() == KeyCode.ESCAPE) { | |
isCancelEditManually = true; | |
cancelEditByUser(); | |
event.consume(); | |
} | |
if (event.getCode() == KeyCode.TAB) { | |
findNextLogicalCell(); | |
event.consume(); | |
} | |
} | |
); | |
tableView.addEventFilter( | |
MouseEvent.MOUSE_CLICKED, | |
event -> { | |
if (event.isPopupTrigger()) { | |
event.consume(); | |
} | |
} | |
); | |
tableView.setOnKeyPressed( | |
event -> { | |
if (! event.isControlDown() && | |
(event.getCode().isLetterKey() || event.getCode().isDigitKey() || event.getCode() == KeyCode.MINUS) | |
|| event.getCode() == KeyCode.QUOTE | |
|| event.getCode() == KeyCode.BACK_QUOTE) { | |
TablePosition tablePosition = tableView.getFocusModel().getFocusedCell(); | |
tableView.edit(tablePosition.getRow(), tablePosition.getTableColumn()); | |
} | |
} | |
); | |
} | |
protected void addListenerToTextField(TextField localTextField) { | |
localTextField.focusedProperty().addListener( | |
(event, wasFocused, isNowFocused) -> { | |
if (wasFocused && ! isNowFocused) { | |
localCommitEdit(); | |
} | |
} | |
); | |
localTextField.setOnKeyReleased( | |
(KeyEvent keyEvent) -> { | |
if (keyEvent.getCode() == KeyCode.ENTER | |
|| keyEvent.getCode() == KeyCode.TAB) { | |
findNextLogicalCell(); | |
keyEvent.consume(); | |
} | |
if (keyEvent.getCode() == KeyCode.ESCAPE) { | |
isCancelEditManually = true; | |
cancelEditByUser(); | |
keyEvent.consume(); | |
} | |
} | |
); | |
localTextField.addEventFilter( | |
MouseEvent.MOUSE_CLICKED, | |
event -> { | |
if (event.isPopupTrigger()) { | |
event.consume(); | |
} | |
} | |
); | |
} | |
@SuppressWarnings("unchecked") //figuring out the cell types from here is impossible. | |
protected void findNextLogicalCell() { | |
localCommitEdit(); | |
TableView<TTable> tableView = this.getTableView(); | |
TableView.TableViewFocusModel<TTable> focusModel = tableView.getFocusModel(); | |
TablePosition tp = focusModel.getFocusedCell(); | |
if (tp.getColumn() != tableView.getColumns().size() - 1) { | |
focusModel.focusRightCell(); | |
} | |
else { | |
focusModel.focusBelowCell(); | |
while(focusModel.getFocusedCell().getColumn() != 0) { | |
focusModel.focusLeftCell(); | |
} | |
} | |
TablePosition nextTargetCell = focusModel.getFocusedCell(); | |
getTableView().getSelectionModel().select(nextTargetCell.getRow(), nextTargetCell.getTableColumn()); | |
getTableView().edit(nextTargetCell.getRow(), nextTargetCell.getTableColumn()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com; | |
import com.sun.javafx.scene.control.behavior.TableCellBehavior; | |
import javafx.scene.control.TableCell; | |
import javafx.scene.control.TableView; | |
import javafx.scene.input.MouseButton; | |
public class OASISTableCellBehavior<S, T> extends TableCellBehavior<S, T>{ | |
public OASISTableCellBehavior(TableCell<S, T> control) { | |
super(control); | |
} | |
protected void tryTerminateEdit() { | |
TableCell<S, T> cell = getControl(); | |
TableView<S> table = cell.getTableColumn().getTableView(); | |
if (table instanceof OASISTableView) { | |
((OASISTableView<S>) table).terminateEdit(); | |
} | |
} | |
@Override | |
protected void handleClicks(MouseButton button, int clickCount, | |
boolean isAlreadySelected) { | |
tryTerminateEdit(); | |
super.handleClicks(button, clickCount, isAlreadySelected); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com; | |
import com.sun.javafx.scene.control.behavior.TableCellBehavior; | |
import com.sun.javafx.scene.control.skin.TableCellSkinBase; | |
import javafx.beans.property.BooleanProperty; | |
import javafx.beans.property.ReadOnlyDoubleProperty; | |
import javafx.scene.control.TableCell; | |
import javafx.scene.control.TableColumn; | |
public class OASISTableCellSkin<S,T> extends TableCellSkinBase<TableCell<S,T>, TableCellBehavior<S,T>> { | |
private final TableCell<S,T> tableCell; | |
private final TableColumn<S,T> tableColumn; | |
public OASISTableCellSkin(TableCell<S, T> tableCell) { | |
super(tableCell, new OASISTableCellBehavior<S,T>(tableCell)); | |
this.tableCell = tableCell; | |
this.tableColumn = tableCell.getTableColumn(); | |
super.init(tableCell); | |
} | |
@Override | |
protected BooleanProperty columnVisibleProperty() { | |
return tableColumn.visibleProperty(); | |
} | |
@Override | |
protected ReadOnlyDoubleProperty columnWidthProperty() { | |
return tableColumn.widthProperty(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com; | |
import javafx.beans.property.SimpleStringProperty; | |
import javafx.beans.property.StringProperty; | |
import javafx.scene.control.TableCell; | |
import javafx.scene.control.TableColumn; | |
public class OASISTableColumn<TTable extends TableColumn, TCell extends TableCell> | |
extends TableColumn<TTable, TCell> { | |
private StringProperty cellType = new SimpleStringProperty(this, "cellType") { | |
@Override | |
protected void invalidated() { | |
setCellFactory(new CellFactory<>(getValue())); | |
} | |
}; | |
public OASISTableColumn() { | |
} | |
public OASISTableColumn(String text) { | |
super(text); | |
} | |
public StringProperty cellTypeProperty() { | |
return cellType; | |
} | |
public String getCellType() { | |
return cellTypeProperty().get(); | |
} | |
public void setCellType(String value) { | |
cellTypeProperty().set(value); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com; | |
import javafx.beans.property.ReadOnlyObjectProperty; | |
import javafx.beans.property.ReadOnlyObjectWrapper; | |
import javafx.scene.control.TableColumn; | |
import javafx.scene.control.TablePosition; | |
import javafx.scene.control.TableView; | |
public class OASISTableView<S> extends TableView<S> { | |
public boolean isTerminating = false; | |
@Override | |
public void edit(int row, TableColumn<S, ?> column) { | |
super.edit(row, column); | |
setTerminatingCell(null); | |
} | |
public void terminateEdit() { | |
if (!isTerminating()) { | |
return; | |
} | |
isTerminating = true; | |
setTerminatingCell(getEditingCell()); | |
} | |
public boolean isTerminating() { | |
return getEditingCell() != null; | |
} | |
private ReadOnlyObjectWrapper<TablePosition<S,?>> terminatingCell; | |
protected void setTerminatingCell(TablePosition<S, ?> terminatingPosition) { | |
terminatingCellPropertyImpl().set(terminatingPosition); | |
} | |
public final ReadOnlyObjectProperty<TablePosition<S,?>> terminatingCellProperty() { | |
return terminatingCellPropertyImpl().getReadOnlyProperty(); | |
} | |
private ReadOnlyObjectWrapper<TablePosition<S,?>> terminatingCellPropertyImpl() { | |
if (terminatingCell == null) { | |
terminatingCell = new ReadOnlyObjectWrapper<>(this, "terminatingCell"); | |
} | |
return terminatingCell; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment