Add filter input to filter by model name and url

This commit is contained in:
0xboobface 2019-04-05 13:40:08 +02:00
parent 85b809da00
commit 25e7c8a0ea
1 changed files with 104 additions and 27 deletions

View File

@ -13,6 +13,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -31,6 +32,7 @@ import ctbrec.ui.action.PlayAction;
import ctbrec.ui.action.ResumeAction;
import ctbrec.ui.action.StopRecordingAction;
import ctbrec.ui.controls.AutoFillTextField;
import ctbrec.ui.controls.SearchBox;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ -38,6 +40,7 @@ import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
@ -50,6 +53,7 @@ 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.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
@ -63,11 +67,13 @@ import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.util.Duration;
public class RecordedModelsTab extends Tab implements TabSelectionListener {
private static final transient Logger LOG = LoggerFactory.getLogger(RecordedModelsTab.class);
private ReentrantLock lock = new ReentrantLock();
private ScheduledService<List<JavaFxModel>> updateService;
private Recorder recorder;
private List<Site> sites;
@ -76,6 +82,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
ScrollPane scrollPane = new ScrollPane();
TableView<JavaFxModel> table = new TableView<JavaFxModel>();
ObservableList<JavaFxModel> observableModels = FXCollections.observableArrayList();
ObservableList<JavaFxModel> filteredModels = FXCollections.observableArrayList();
ContextMenu popup;
Label modelLabel = new Label("Model");
@ -83,6 +90,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
Button addModelButton = new Button("Record");
Button pauseAll = new Button("Pause All");
Button resumeAll = new Button("Resume All");
TextField filter;
public RecordedModelsTab(String title, Recorder recorder, List<Site> sites) {
super(title);
@ -196,6 +204,27 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
pauseAll.setOnAction(this::pauseAll);
resumeAll.setOnAction(this::resumeAll);
HBox filterContainer = new HBox();
filterContainer.setSpacing(0);
filterContainer.setPadding(new Insets(0));
filterContainer.setAlignment(Pos.CENTER_RIGHT);
HBox.setHgrow(filterContainer, Priority.ALWAYS);
filter = new SearchBox(false);
filter.setPromptText("Filter");
filter.textProperty().addListener( (observableValue, oldValue, newValue) -> {
String q = filter.getText();
lock.lock();
try {
filter(q);
} finally {
lock.unlock();
}
});
filter.getStyleClass().remove("search-box-icon");
filterContainer.getChildren().add(filter);
addModelBox.getChildren().add(filterContainer);
BorderPane root = new BorderPane();
root.setPadding(new Insets(5));
root.setTop(addModelBox);
@ -295,37 +324,44 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
return;
}
for (JavaFxModel updatedModel : models) {
int index = observableModels.indexOf(updatedModel);
if (index == -1) {
observableModels.add(updatedModel);
updatedModel.getPausedProperty().addListener((obs, oldV, newV) -> {
if (newV) {
if(!recorder.isSuspended(updatedModel)) {
pauseRecording(Collections.singletonList(updatedModel));
lock.lock();
try {
for (JavaFxModel updatedModel : models) {
int index = observableModels.indexOf(updatedModel);
if (index == -1) {
observableModels.add(updatedModel);
updatedModel.getPausedProperty().addListener((obs, oldV, newV) -> {
if (newV) {
if(!recorder.isSuspended(updatedModel)) {
pauseRecording(Collections.singletonList(updatedModel));
}
} else {
if(recorder.isSuspended(updatedModel)) {
resumeRecording(Collections.singletonList(updatedModel));
}
}
} else {
if(recorder.isSuspended(updatedModel)) {
resumeRecording(Collections.singletonList(updatedModel));
}
}
});
} else {
// make sure to update the JavaFX online property, so that the table cell is updated
JavaFxModel oldModel = observableModels.get(index);
oldModel.setSuspended(updatedModel.isSuspended());
oldModel.getOnlineProperty().set(updatedModel.getOnlineProperty().get());
oldModel.getRecordingProperty().set(updatedModel.getRecordingProperty().get());
}
}
for (Iterator<JavaFxModel> iterator = observableModels.iterator(); iterator.hasNext();) {
Model model = iterator.next();
if (!models.contains(model)) {
iterator.remove();
});
} else {
// make sure to update the JavaFX online property, so that the table cell is updated
JavaFxModel oldModel = observableModels.get(index);
oldModel.setSuspended(updatedModel.isSuspended());
oldModel.getOnlineProperty().set(updatedModel.getOnlineProperty().get());
oldModel.getRecordingProperty().set(updatedModel.getRecordingProperty().get());
}
}
for (Iterator<JavaFxModel> iterator = observableModels.iterator(); iterator.hasNext();) {
Model model = iterator.next();
if (!models.contains(model)) {
iterator.remove();
}
}
} finally {
lock.unlock();
}
filteredModels.clear();
filter(filter.getText());
table.sort();
});
updateService.setOnFailed((event) -> {
@ -333,6 +369,47 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
});
}
private void filter(String filter) {
lock.lock();
try {
if (StringUtil.isBlank(filter)) {
observableModels.addAll(filteredModels);
filteredModels.clear();
return;
}
String[] tokens = filter.split(" ");
observableModels.addAll(filteredModels);
filteredModels.clear();
for (int i = 0; i < table.getItems().size(); i++) {
StringBuilder sb = new StringBuilder();
for (TableColumn<JavaFxModel, ?> tc : table.getColumns()) {
Object cellData = tc.getCellData(i);
if(cellData != null) {
String content = cellData.toString();
sb.append(content).append(' ');
}
}
String searchText = sb.toString();
boolean tokensMissing = false;
for (String token : tokens) {
if(!searchText.toLowerCase().contains(token.toLowerCase())) {
tokensMissing = true;
break;
}
}
if(tokensMissing) {
JavaFxModel model = table.getItems().get(i);
filteredModels.add(model);
}
}
observableModels.removeAll(filteredModels);
} finally {
lock.unlock();
}
}
private ScheduledService<List<JavaFxModel>> createUpdateService() {
ScheduledService<List<JavaFxModel>> updateService = new ScheduledService<List<JavaFxModel>>() {
@Override