Browser list performance improvements

This commit is contained in:
crschnick 2023-06-06 13:54:08 +00:00
parent f58c304d6f
commit 84e054978c
2 changed files with 82 additions and 56 deletions

View file

@ -23,6 +23,7 @@ import javafx.beans.property.*;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.css.PseudoClass; import javafx.css.PseudoClass;
import javafx.geometry.Bounds; import javafx.geometry.Bounds;
import javafx.geometry.Pos; import javafx.geometry.Pos;
@ -108,19 +109,7 @@ final class BrowserFileListComp extends SimpleComp {
table.getSortOrder().add(filenameCol); table.getSortOrder().add(filenameCol);
table.setFocusTraversable(true); table.setFocusTraversable(true);
table.setSortPolicy(param -> { table.setSortPolicy(param -> {
var comp = table.getComparator(); return sort(table, param.getItems());
if (comp == null) {
return true;
}
var syntheticFirst = Comparator.<BrowserEntry, Boolean>comparing(path -> !path.isSynthetic());
var dirsFirst = Comparator.<BrowserEntry, Boolean>comparing(
path -> path.getRawFileEntry().getKind() != FileKind.DIRECTORY);
Comparator<? super BrowserEntry> us =
syntheticFirst.thenComparing(dirsFirst).thenComparing(comp);
FXCollections.sort(param.getItems(), us);
return true;
}); });
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN); table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
filenameCol.minWidthProperty().bind(table.widthProperty().multiply(0.5)); filenameCol.minWidthProperty().bind(table.widthProperty().multiply(0.5));
@ -135,6 +124,22 @@ final class BrowserFileListComp extends SimpleComp {
return table; return table;
} }
private boolean sort(TableView<BrowserEntry> table, ObservableList<BrowserEntry> list) {
var comp = table.getComparator();
if (comp == null) {
return true;
}
var syntheticFirst = Comparator.<BrowserEntry, Boolean>comparing(path -> !path.isSynthetic());
var dirsFirst = Comparator.<BrowserEntry, Boolean>comparing(
path -> path.getRawFileEntry().getKind() != FileKind.DIRECTORY);
Comparator<? super BrowserEntry> us =
syntheticFirst.thenComparing(dirsFirst).thenComparing(comp);
FXCollections.sort(list, us);
return true;
}
private void prepareTableSelectionModel(TableView<BrowserEntry> table) { private void prepareTableSelectionModel(TableView<BrowserEntry> table) {
if (!fileList.getMode().isMultiple()) { if (!fileList.getMode().isMultiple()) {
table.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); table.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
@ -232,33 +237,44 @@ final class BrowserFileListComp extends SimpleComp {
table.setRowFactory(param -> { table.setRowFactory(param -> {
TableRow<BrowserEntry> row = new TableRow<>(); TableRow<BrowserEntry> row = new TableRow<>();
row.accessibleTextProperty().bind(Bindings.createStringBinding(() -> { row.accessibleTextProperty()
return row.getItem() != null ? row.getItem().getFileName() : null; .bind(Bindings.createStringBinding(
}, row.itemProperty())); () -> {
row.focusTraversableProperty().bind(Bindings.createBooleanBinding(() -> { return row.getItem() != null ? row.getItem().getFileName() : null;
return row.getItem() != null; },
}, row.itemProperty())); row.itemProperty()));
new ContextMenuAugment<>(event -> { row.focusTraversableProperty()
if (row.getItem() == null) { .bind(Bindings.createBooleanBinding(
return event.getButton() == MouseButton.SECONDARY; () -> {
} return row.getItem() != null;
},
row.itemProperty()));
new ContextMenuAugment<>(
event -> {
if (row.getItem() == null) {
return event.getButton() == MouseButton.SECONDARY;
}
if (row.getItem() != null && row.getItem().getRawFileEntry().getKind() == FileKind.DIRECTORY) { if (row.getItem() != null
return event.getButton() == MouseButton.SECONDARY; && row.getItem().getRawFileEntry().getKind() == FileKind.DIRECTORY) {
} return event.getButton() == MouseButton.SECONDARY;
}
if (row.getItem() != null && row.getItem().getRawFileEntry().getKind() != FileKind.DIRECTORY) { if (row.getItem() != null
return event.getButton() == MouseButton.SECONDARY || event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2; && row.getItem().getRawFileEntry().getKind() != FileKind.DIRECTORY) {
} return event.getButton() == MouseButton.SECONDARY
|| event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2;
}
return false; return false;
}, () -> { },
if (row.getItem() != null && row.getItem().isSynthetic()) { () -> {
return null; if (row.getItem() != null && row.getItem().isSynthetic()) {
} return null;
}
return new BrowserContextMenu(fileList.getFileSystemModel(), row.getItem()); return new BrowserContextMenu(fileList.getFileSystemModel(), row.getItem());
}) })
.augment(new SimpleCompStructure<>(row)); .augment(new SimpleCompStructure<>(row));
var listEntry = Bindings.createObjectBinding( var listEntry = Bindings.createObjectBinding(
() -> new BrowserFileListCompEntry(row, row.getItem(), fileList), row.itemProperty()); () -> new BrowserFileListCompEntry(row, row.getItem(), fileList), row.itemProperty());
@ -347,8 +363,11 @@ final class BrowserFileListComp extends SimpleComp {
} }
if (!table.getItems().equals(newItems)) { if (!table.getItems().equals(newItems)) {
table.getItems().setAll(newItems); // Sort the list ourselves as sorting the table would incur a lot of cell updates
table.sort(); var obs = FXCollections.observableList(newItems);
sort(table, obs);
table.getItems().setAll(obs);
// table.sort();
} }
var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory(); var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory();
@ -410,13 +429,17 @@ final class BrowserFileListComp extends SimpleComp {
.createRegion(); .createRegion();
private final StackPane textField = private final StackPane textField =
new LazyTextFieldComp(text).createStructure().get(); new LazyTextFieldComp(text).createStructure().get();
private final HBox graphic;
private final BooleanProperty updating = new SimpleBooleanProperty(); private final BooleanProperty updating = new SimpleBooleanProperty();
public FilenameCell(Property<BrowserEntry> editing) { public FilenameCell(Property<BrowserEntry> editing) {
accessibleTextProperty().bind(Bindings.createStringBinding(() -> { accessibleTextProperty()
return getItem() != null ? getItem() : null; .bind(Bindings.createStringBinding(
}, itemProperty())); () -> {
return getItem() != null ? getItem() : null;
},
itemProperty()));
setAccessibleRole(AccessibleRole.TEXT); setAccessibleRole(AccessibleRole.TEXT);
editing.addListener((observable, oldValue, newValue) -> { editing.addListener((observable, oldValue, newValue) -> {
@ -436,30 +459,29 @@ final class BrowserFileListComp extends SimpleComp {
updateItem(getItem(), isEmpty()); updateItem(getItem(), isEmpty());
}; };
text.addListener(listener); text.addListener(listener);
graphic = new HBox(imageView, textField);
graphic.setSpacing(10);
graphic.setAlignment(Pos.CENTER_LEFT);
HBox.setHgrow(textField, Priority.ALWAYS);
setGraphic(graphic);
} }
@Override @Override
protected void updateItem(String fullPath, boolean empty) { protected void updateItem(String newName, boolean empty) {
if (updating.get()) { if (updating.get()) {
super.updateItem(fullPath, empty); super.updateItem(newName, empty);
return; return;
} }
try (var ignored = new BusyProperty(updating)) { try (var ignored = new BusyProperty(updating)) {
super.updateItem(fullPath, empty); super.updateItem(newName, empty);
setText(null); if (empty || newName == null) {
if (empty || getTableRow() == null || getTableRow().getItem() == null) {
// Don't set image as that would trigger image comp update // Don't set image as that would trigger image comp update
// and cells are emptied on each change, leading to unnecessary changes // and cells are emptied on each change, leading to unnecessary changes
// img.set(null); // img.set(null);
setGraphic(null); setOpacity(0.0);
} else { } else {
var box = new HBox(imageView, textField);
box.setSpacing(10);
box.setAlignment(Pos.CENTER_LEFT);
HBox.setHgrow(textField, Priority.ALWAYS);
setGraphic(box);
var isParentLink = getTableRow() var isParentLink = getTableRow()
.getItem() .getItem()
.getRawFileEntry() .getRawFileEntry()
@ -473,11 +495,12 @@ final class BrowserFileListComp extends SimpleComp {
var isDirectory = getTableRow().getItem().getRawFileEntry().getKind() == FileKind.DIRECTORY; var isDirectory = getTableRow().getItem().getRawFileEntry().getKind() == FileKind.DIRECTORY;
pseudoClassStateChanged(FOLDER, isDirectory); pseudoClassStateChanged(FOLDER, isDirectory);
var fileName = isParentLink ? ".." : FileNames.getFileName(fullPath); var fileName = isParentLink ? ".." : FileNames.getFileName(newName);
var hidden = !isParentLink var hidden = !isParentLink
&& (getTableRow().getItem().getRawFileEntry().isHidden() || fileName.startsWith(".")); && (getTableRow().getItem().getRawFileEntry().isHidden() || fileName.startsWith("."));
getTableRow().pseudoClassStateChanged(HIDDEN, hidden); getTableRow().pseudoClassStateChanged(HIDDEN, hidden);
text.set(fileName); text.set(fileName);
setOpacity(1.0);
} }
} }
} }

View file

@ -95,7 +95,9 @@ public class SvgView {
private WebView createWebView() { private WebView createWebView() {
var wv = new WebView(); var wv = new WebView();
wv.setPageFill(Color.TRANSPARENT); // Sometimes a web view might not render when the background is said to transparent, at least according to stack overflow
wv.setPageFill(Color.valueOf("#00000001"));
// wv.setPageFill(Color.BLACK);
wv.getEngine().setJavaScriptEnabled(false); wv.getEngine().setJavaScriptEnabled(false);
wv.setContextMenuEnabled(false); wv.setContextMenuEnabled(false);
wv.setFocusTraversable(false); wv.setFocusTraversable(false);
@ -114,8 +116,9 @@ public class SvgView {
wv.getChildrenUnmodifiable().addListener((ListChangeListener<Node>) change -> { wv.getChildrenUnmodifiable().addListener((ListChangeListener<Node>) change -> {
Set<Node> scrolls = wv.lookupAll(".scroll-bar"); Set<Node> scrolls = wv.lookupAll(".scroll-bar");
for (Node scroll : scrolls) { for (Node scroll : scrolls) {
scroll.setVisible(false);
scroll.setFocusTraversable(false); scroll.setFocusTraversable(false);
scroll.setVisible(false);
scroll.setManaged(false);
} }
}); });