Use StatePersistingTableView for RecordedModels and RecordLater

This commit is contained in:
0xb00bface 2021-09-11 18:19:21 +02:00
parent abf65b1cc2
commit 4cbb21bdb6
5 changed files with 41 additions and 245 deletions

View File

@ -7,6 +7,7 @@ import java.util.Map;
import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.StringUtil;
import javafx.scene.control.TableColumn.SortType;
public class SettingTableViewStateStore implements TableViewStateStore {
@ -51,7 +52,12 @@ public class SettingTableViewStateStore implements TableViewStateStore {
@Override
public SortType loadSortType() {
return SortType.valueOf(loadSetting(sortTypeSetting));
String sortType = loadSetting(sortTypeSetting);
if (StringUtil.isBlank(sortType)) {
return SortType.ASCENDING;
} else {
return SortType.valueOf(sortType);
}
}
@SuppressWarnings("unchecked")

View File

@ -1,5 +1,7 @@
package ctbrec.ui.tabs.recorded;
import static ctbrec.ui.action.AbstractPortraitAction.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -32,7 +34,6 @@ import ctbrec.ui.PreviewPopupHandler;
import ctbrec.ui.action.AbstractPortraitAction.PortraitChangedEvent;
import ctbrec.ui.action.MarkForLaterRecordingAction;
import ctbrec.ui.action.PlayAction;
import ctbrec.ui.action.SetPortraitAction;
import ctbrec.ui.action.StartRecordingAction;
import ctbrec.ui.controls.CustomMouseBehaviorContextMenu;
import ctbrec.ui.controls.DateTimeCellFactory;
@ -40,6 +41,8 @@ import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.controls.SearchBox;
import ctbrec.ui.controls.autocomplete.AutoFillTextField;
import ctbrec.ui.controls.autocomplete.ObservableListSuggester;
import ctbrec.ui.controls.table.SettingTableViewStateStore;
import ctbrec.ui.controls.table.StatePersistingTableView;
import ctbrec.ui.menu.ModelMenuContributor;
import ctbrec.ui.tabs.TabSelectionListener;
import javafx.application.Platform;
@ -50,11 +53,9 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
@ -62,9 +63,7 @@ import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.SortType;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.control.cell.PropertyValueFactory;
@ -89,7 +88,8 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
protected ObservableList<JavaFxModel> observableModels = FXCollections.observableArrayList();
protected ObservableList<JavaFxModel> filteredModels = FXCollections.observableArrayList();
protected TableView<JavaFxModel> table = new TableView<>();
protected SettingTableViewStateStore tableStateStore;
protected StatePersistingTableView<JavaFxModel> table;
protected List<TableColumn<JavaFxModel, ?>> columns = new ArrayList<>();
protected LoadingCache<Model, Image> portraitCache = CacheBuilder.newBuilder()
.expireAfterAccess(1, TimeUnit.DAYS)
@ -113,9 +113,11 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
protected Config config;
AbstractRecordedModelsTab(String text) {
AbstractRecordedModelsTab(String text, String stateStorePrefix) {
super(text);
config = Config.getInstance();
tableStateStore = new SettingTableViewStateStore(config, stateStorePrefix);
table = new StatePersistingTableView<>(tableStateStore);
registerPortraitListener();
}
@ -215,13 +217,7 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
});
filter.getStyleClass().remove("search-box-icon");
var columnSelection = new Button("");
columnSelection.setOnAction(this::showColumnSelection);
columnSelection.setTooltip(new Tooltip("Select columns"));
columnSelection.prefHeightProperty().bind(filter.prefHeightProperty());
columnSelection.prefWidthProperty().bind(columnSelection.prefHeightProperty());
filterContainer.getChildren().addAll(columnSelection, filter);
filterContainer.getChildren().addAll(filter);
addModelBox.getChildren().add(filterContainer);
}
@ -229,9 +225,6 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
TableColumn<JavaFxModel, String> preview = addTableColumn("preview", "🎥", columnIdx, 35);
preview.setCellValueFactory(cdf -> new SimpleStringProperty(""));
preview.setEditable(false);
if (!Config.getInstance().getSettings().livePreviews) {
preview.setVisible(false);
}
}
protected void addPortraitColumn(int columnIdx) {
@ -311,16 +304,10 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
tc.setPrefWidth(width);
tc.setStyle("-fx-alignment: CENTER-LEFT;");
columns.add(tc);
addTableColumnIfEnabled(tc);
table.getColumns().add(tc);
return tc;
}
protected void addTableColumnIfEnabled(TableColumn<JavaFxModel, ?> tc) {
if(isColumnEnabled(tc)) {
table.getColumns().add(tc);
}
}
protected ContextMenu createContextMenu() {
List<Model> selectedModels = table.getSelectionModel().getSelectedItems().stream().map(JavaFxModel::getDelegate).collect(Collectors.toList());
if (selectedModels.isEmpty()) {
@ -486,74 +473,14 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
}
}
abstract String getSortColumn();
abstract void setSortColumn(String column);
abstract String getSortType();
abstract void setSortType(String sortType);
abstract String[] getColumnIds();
abstract void setColumnIds(String[] ids);
abstract double[] getColumnWidths();
abstract void setColumnWidths(double[] widths);
abstract List<String> getDisabledColumns();
public void saveState() {
if (!table.getSortOrder().isEmpty()) {
TableColumn<JavaFxModel, ?> col = table.getSortOrder().get(0);
setSortColumn(col.getText());
setSortType(col.getSortType().toString());
}
int tableColumns = table.getColumns().size();
var columnWidths = new double[tableColumns];
var columnIds = new String[tableColumns];
for (var i = 0; i < columnWidths.length; i++) {
columnWidths[i] = table.getColumns().get(i).getWidth();
columnIds[i] = table.getColumns().get(i).getId();
}
setColumnWidths(columnWidths);
setColumnIds(columnIds);
table.saveState();
}
protected void restoreState() {
restoreColumnOrder();
restoreColumnWidths();
restoreSorting();
}
private void restoreSorting() {
String sortCol = getSortColumn();
if (StringUtil.isNotBlank(sortCol)) {
for (TableColumn<JavaFxModel, ?> col : table.getColumns()) {
if (Objects.equals(sortCol, col.getText())) {
col.setSortType(SortType.valueOf(getSortType()));
table.getSortOrder().clear();
table.getSortOrder().add(col);
break;
}
}
}
}
private void restoreColumnOrder() {
String[] columnIds = getColumnIds();
ObservableList<TableColumn<JavaFxModel,?>> tableColumns = table.getColumns();
for (var i = 0; i < columnIds.length; i++) {
for (var j = 0; j < table.getColumns().size(); j++) {
if(Objects.equals(columnIds[i], tableColumns.get(j).getId())) {
TableColumn<JavaFxModel, ?> col = tableColumns.get(j);
tableColumns.remove(j); // NOSONAR
tableColumns.add(Math.min(i, tableColumns.size()), col);
}
}
}
}
private void restoreColumnWidths() {
double[] columnWidths = getColumnWidths();
if (columnWidths != null && columnWidths.length == table.getColumns().size()) {
for (var i = 0; i < columnWidths.length; i++) {
table.getColumns().get(i).setPrefWidth(columnWidths[i]);
}
table.restoreState();
if (!config.getSettings().livePreviews) {
table.getColumns().stream().filter(tc -> Objects.equals(tc.getId(), "preview")).findFirst().ifPresent(tc -> tc.setVisible(false));
}
}
@ -584,7 +511,7 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
if (StringUtil.isNotBlank(portraitId)) {
File configDir = Config.getInstance().getConfigDir();
File portraitDir = new File(configDir, "portraits");
File portraitFile = new File(portraitDir, portraitId + '.' + SetPortraitAction.FORMAT);
File portraitFile = new File(portraitDir, portraitId + '.' + FORMAT);
try {
return new Image(new FileInputStream(portraitFile));
} catch (FileNotFoundException e) {
@ -593,51 +520,4 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
}
return SILHOUETTE;
}
protected void showColumnSelection(ActionEvent evt) {
ContextMenu menu = new CustomMouseBehaviorContextMenu();
for (TableColumn<JavaFxModel, ?> tc : columns) {
var item = new CheckMenuItem(tc.getText());
item.setSelected(isColumnEnabled(tc));
menu.getItems().add(item);
item.setOnAction(e -> {
try {
if (item.isSelected()) {
getDisabledColumns().remove(tc.getText());
boolean added = false;
for (int i = table.getColumns().size() - 1; i >= 0; i--) {
TableColumn<JavaFxModel, ?> other = table.getColumns().get(i);
if (!other.isVisible()) {
continue;
}
int idx = (int) tc.getUserData();
int otherIdx = (int) other.getUserData();
if (otherIdx < idx) {
table.getColumns().add(i + 1, tc);
added = true;
break;
}
}
if (!added) {
table.getColumns().add(0, tc);
}
} else {
getDisabledColumns().add(tc.getText());
table.getColumns().remove(tc);
}
} catch (Exception ex) {
LOG.error("Couldn't activate column {}", tc, ex);
}
});
}
Button src = (Button) evt.getSource();
Point2D location = src.localToScreen(src.getTranslateX(), src.getTranslateY());
menu.show(getTabPane().getScene().getWindow(), location.getX(), location.getY() + src.getHeight() + 5);
}
private boolean isColumnEnabled(TableColumn<JavaFxModel, ?> tc) {
return !getDisabledColumns().contains(tc.getText());
}
}

View File

@ -37,7 +37,7 @@ public class RecordLaterTab extends AbstractRecordedModelsTab implements TabSele
private ScheduledService<List<JavaFxModel>> updateService;
public RecordLaterTab(String title, Recorder recorder, List<Site> sites) {
super(title);
super(title, "recordLaterTable");
this.recorder = recorder;
this.sites = sites;
createGui();
@ -179,51 +179,6 @@ public class RecordLaterTab extends AbstractRecordedModelsTab implements TabSele
}
}
@Override
String getSortColumn() {
return Config.getInstance().getSettings().recordLaterSortColumn;
}
@Override
void setSortColumn(String column) {
Config.getInstance().getSettings().recordLaterSortColumn = column;
}
@Override
String getSortType() {
return Config.getInstance().getSettings().recordLaterSortType;
}
@Override
void setSortType(String sortType) {
Config.getInstance().getSettings().recordLaterSortType = sortType;
}
@Override
String[] getColumnIds() {
return Config.getInstance().getSettings().recordLaterColumnIds;
}
@Override
void setColumnIds(String[] columnIds) {
Config.getInstance().getSettings().recordLaterColumnIds = columnIds;
}
@Override
double[] getColumnWidths() {
return Config.getInstance().getSettings().recordLaterColumnWidths;
}
@Override
void setColumnWidths(double[] widths) {
Config.getInstance().getSettings().recordLaterColumnWidths = widths;
}
@Override
List<String> getDisabledColumns() {
return Config.getInstance().getSettings().recordLaterDisabledColumns;
}
@Override
boolean getMarkModelsForLaterRecording() {
return true;

View File

@ -67,7 +67,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
ToggleButton toggleRecording = new ToggleButton("Pause Recording");
public RecordedModelsTab(String title, Recorder recorder, List<Site> sites) {
super(title);
super(title, "recordedModelsTable");
this.recorder = recorder;
this.sites = sites;
createGui();
@ -95,7 +95,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
online.setUserData(idx++);
online.setStyle(STYLE_ALIGN_CENTER);
columns.add(online);
addTableColumnIfEnabled(online);
table.getColumns().add(online);
TableColumn<JavaFxModel, Boolean> recording = new TableColumn<>("Recording");
recording.setCellValueFactory(cdf -> cdf.getValue().getRecordingProperty());
recording.setCellFactory(tc -> new RecordingTableCell());
@ -105,7 +105,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
recording.setUserData(idx++);
recording.setStyle(STYLE_ALIGN_CENTER);
columns.add(recording);
addTableColumnIfEnabled(recording);
table.getColumns().add(recording);
TableColumn<JavaFxModel, Boolean> paused = new TableColumn<>("Paused");
paused.setCellValueFactory(cdf -> cdf.getValue().getPausedProperty());
paused.setCellFactory(CheckBoxTableCell.forTableColumn(paused));
@ -115,7 +115,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
paused.setUserData(idx++);
paused.setStyle(STYLE_ALIGN_CENTER);
columns.add(paused);
addTableColumnIfEnabled(paused);
table.getColumns().add(paused);
TableColumn<JavaFxModel, Number> priority = new TableColumn<>("Priority");
priority.setCellValueFactory(param -> param.getValue().getPriorityProperty());
priority.setCellFactory(new PriorityCellFactory());
@ -127,7 +127,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
priority.setId("priority");
priority.setUserData(idx++);
columns.add(priority);
addTableColumnIfEnabled(priority);
table.getColumns().add(priority);
TableColumn<JavaFxModel, Instant> lastSeen = new TableColumn<>("last seen");
lastSeen.setCellValueFactory(cdf -> cdf.getValue().lastSeenProperty());
lastSeen.setCellFactory(new DateTimeCellFactory<>());
@ -137,7 +137,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
lastSeen.setUserData(idx++);
lastSeen.setStyle(STYLE_ALIGN_CENTER);
columns.add(lastSeen);
addTableColumnIfEnabled(lastSeen);
table.getColumns().add(lastSeen);
TableColumn<JavaFxModel, Instant> lastRecorded = new TableColumn<>("last recorded");
lastRecorded.setCellValueFactory(cdf -> cdf.getValue().lastRecordedProperty());
lastRecorded.setCellFactory(new DateTimeCellFactory<>());
@ -147,7 +147,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
lastRecorded.setUserData(idx++);
lastRecorded.setStyle(STYLE_ALIGN_CENTER);
columns.add(lastRecorded);
addTableColumnIfEnabled(lastRecorded);
table.getColumns().add(lastRecorded);
addAddedTimestampColumn(idx++);
addNotesColumn(idx);
@ -409,49 +409,4 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
boolean getMarkModelsForLaterRecording() {
return false;
}
@Override
String getSortColumn() {
return Config.getInstance().getSettings().recordedModelsSortColumn;
}
@Override
void setSortColumn(String column) {
Config.getInstance().getSettings().recordedModelsSortColumn = column;
}
@Override
String getSortType() {
return Config.getInstance().getSettings().recordedModelsSortType;
}
@Override
void setSortType(String sortType) {
Config.getInstance().getSettings().recordedModelsSortType = sortType;
}
@Override
String[] getColumnIds() {
return Config.getInstance().getSettings().recordedModelsColumnIds;
}
@Override
void setColumnIds(String[] ids) {
Config.getInstance().getSettings().recordedModelsColumnIds = ids;
}
@Override
double[] getColumnWidths() {
return Config.getInstance().getSettings().recordedModelsColumnWidths;
}
@Override
void setColumnWidths(double[] widths) {
Config.getInstance().getSettings().recordedModelsColumnWidths = widths;
}
@Override
List<String> getDisabledColumns() {
return Config.getInstance().getSettings().recordedModelsDisabledTableColumns;
}
}

View File

@ -138,16 +138,16 @@ public class Settings {
public ProxyType proxyType = ProxyType.DIRECT;
public String proxyUser;
public boolean recentlyWatched = true;
public double[] recordLaterColumnWidths = new double[0];
public String[] recordLaterColumnIds = new String[0];
public List<String> recordLaterDisabledColumns = new ArrayList<>();
public String recordLaterSortColumn = "";
public String recordLaterSortType = "";
public double[] recordedModelsColumnWidths = new double[0];
public String[] recordedModelsColumnIds = new String[0];
public List<String> recordedModelsDisabledTableColumns = new ArrayList<>();
public String recordedModelsSortColumn = "";
public String recordedModelsSortType = "";
public List<String> recordLaterTableColumnOrder = new ArrayList<>();
public Map<String, Boolean> recordLaterTableColumnVisibility = new HashMap<>();
public Map<String, Double> recordLaterTableColumnWidth = new HashMap<>();
public String recordLaterTableSortColumn = "";
public String recordLaterTableSortType = "";
public List<String> recordedModelsTableColumnOrder = new ArrayList<>();
public Map<String, Boolean> recordedModelsTableColumnVisibility = new HashMap<>();
public Map<String, Double> recordedModelsTableColumnWidth = new HashMap<>();
public String recordedModelsTableSortColumn = "";
public String recordedModelsTableSortType = "";
public List<String> recordingsTableColumnOrder = new ArrayList<>();
public Map<String, Boolean> recordingsTableColumnVisibility = new HashMap<>();
public Map<String, Double> recordingsTableColumnWidth = new HashMap<>();