Skip to content

Commit

Permalink
Improvements around searching in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Chwedczuk committed Dec 25, 2021
1 parent d26a838 commit b3dcc0c
Show file tree
Hide file tree
Showing 26 changed files with 223 additions and 170 deletions.

This file was deleted.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import javafx.stage.Stage;
import javafx.stage.Window;
import pl.marcinchwedczuk.elfviewer.elfreader.ElfReader;
import pl.marcinchwedczuk.elfviewer.elfreader.elf.arch.LongNativeWord;
import pl.marcinchwedczuk.elfviewer.elfreader.elf.shared.ElfFile;
import pl.marcinchwedczuk.elfviewer.elfreader.io.FileSystemFile;
import pl.marcinchwedczuk.elfviewer.gui.mainwindow.renderer.NothingRenderer;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -56,8 +58,8 @@ public static MainWindow showOn(Stage window) {
private TextField searchText;

@FXML
private TreeView<DisplayAction> treeView;
private TreeItem<DisplayAction> rootItem;
private TreeView<RenderDataAction<?>> treeView;
private TreeItem<RenderDataAction<?>> rootItem;

@FXML
private TableView<Object> tableView;
Expand All @@ -75,18 +77,27 @@ public static MainWindow showOn(Stage window) {
public void initialize(URL url, ResourceBundle resourceBundle) {
openFileChooser = newOpenFileChooser();

rootItem = new TreeItem<>(new DisplayAction("No ELF file loaded"));
rootItem = new TreeItem<>(new RenderDataAction<>(
"No ELF file loaded",
new NothingRenderer<>(new LongNativeWord())));
rootItem.setExpanded(true);

treeView.setRoot(rootItem);

// Selection mode
treeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
treeView.getSelectionModel()
.selectedItemProperty()
.addListener((observable, oldTreeItem, newTreeItem) -> {
if (oldTreeItem != null) {
oldTreeItem.getValue().unmountView();
}

// Clear filter while changing views
searchText.clear();

if (newTreeItem != null) {
newTreeItem.getValue().displayOn(tableView);
newTreeItem.getValue()
.mountView(tableView, searchText.textProperty());
} else {
clearTable();
}
Expand All @@ -96,17 +107,6 @@ public void initialize(URL url, ResourceBundle resourceBundle) {

recentlyOpenFiles = new RecentlyOpenFiles(recentlyOpen, this::loadElfFile);
recentlyOpenFiles.initialize();

searchText.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
applySearchFilter(newValue);
}
});
}

private void applySearchFilter(String searchPhrase) {

}

private void clearTable() {
Expand All @@ -123,13 +123,14 @@ private void loadElfFile(File f) {
recentlyOpenFiles.onFileOpen(f);
}

@SuppressWarnings("unchecked")
private void recreateTreeView() {
rootItem = new ElfExplorerTreeViewBuilder(
currentElfPath,
currentElfFile,
tableView,
searchText.textProperty())
.build();
rootItem = (TreeItem<RenderDataAction<?>>)(TreeItem<?>) new ElfExplorerTreeViewBuilder<>(
currentElfPath,
currentElfFile,
tableView,
searchText.textProperty())
.build();
treeView.setRoot(rootItem);
rootItem.setExpanded(true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package pl.marcinchwedczuk.elfviewer.gui.mainwindow;

import javafx.beans.property.StringProperty;
import javafx.scene.control.TableView;
import pl.marcinchwedczuk.elfviewer.gui.mainwindow.renderer.BaseRenderer;
import pl.marcinchwedczuk.elfviewer.gui.mainwindow.renderer.NothingRenderer;

import java.util.function.Consumer;

public class RenderDataAction<
NATIVE_WORD extends Number & Comparable<NATIVE_WORD>
>
{
private final String displayName;
private final BaseRenderer<?, NATIVE_WORD> renderer;

public RenderDataAction(String displayName,
BaseRenderer<?, NATIVE_WORD> renderer) {
this.displayName = displayName;
this.renderer = renderer;
}

@Override
public String toString() {
return displayName;
}

public void mountView(TableView<Object> tableView,
StringProperty filter) {
renderer.filterPhaseProperty().bind(filter);
renderer.renderDataOn(tableView);
}

public void unmountView() {
renderer.filterPhaseProperty().unbind();
renderer.filterPhaseProperty().setValue("");
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package pl.marcinchwedczuk.elfviewer.gui.mainwindow.renderer;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.transformation.FilteredList;
Expand All @@ -10,6 +11,7 @@
import pl.marcinchwedczuk.elfviewer.elfreader.elf.arch.NativeWord;
import pl.marcinchwedczuk.elfviewer.gui.mainwindow.LambdaValueFactory;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
Expand All @@ -19,14 +21,15 @@
public abstract class BaseRenderer<R, NATIVE_WORD extends Number & Comparable<NATIVE_WORD>>
implements Renderer {
private final NativeWord<NATIVE_WORD> nativeWordMetadata;
private final StringProperty filter;

protected BaseRenderer(NativeWord<NATIVE_WORD> nativeWordMetadata,
StringProperty searchPhrase) {
private final StringProperty filterPhase = new SimpleStringProperty();

protected BaseRenderer(NativeWord<NATIVE_WORD> nativeWordMetadata) {
this.nativeWordMetadata = nativeWordMetadata;
this.filter = searchPhrase;
}

public StringProperty filterPhaseProperty() { return filterPhase; }

@Override
@SuppressWarnings("unchecked")
public void renderDataOn(TableView<Object> tableView) {
Expand All @@ -39,13 +42,13 @@ public void renderDataOn(TableView<Object> tableView) {
// there should be wrapper
FilteredList<R> filteredList = new FilteredList<>(
FXCollections.observableArrayList(defineRows()),
createFilter(filter.getValue()));
createFilter(filterPhase.getValue()));

// TODO: Make sure to clear search field listeners when changing view
filter.addListener((observable, oldValue, newValue) ->
filteredList.setPredicate(createFilter(filter.get())));
filterPhase.addListener((observable, oldValue, newValue) ->
filteredList.setPredicate(createFilter(filterPhase.get())));

tableView.itemsProperty().set((FilteredList<Object>) (FilteredList<?>) filteredList);
tableView.itemsProperty()
.set((FilteredList<Object>) (FilteredList<?>) filteredList);
}

protected abstract List<TableColumn<R, String>> defineColumns();
Expand Down Expand Up @@ -112,26 +115,43 @@ protected static String[] mkStrings(String... strings) {
}

protected static Predicate<String[]> mkStringsFilter(String phrase) {
// TODO: Support multiple keywords 'foo bar'
// TODO: Support detaching search phrase listener
return mkMatcher(phrase);
}

Pattern p = (phrase != null && !phrase.isEmpty())
? Pattern.compile(Pattern.quote(phrase), Pattern.CASE_INSENSITIVE)
: null;
private static Predicate<String[]> mkMatcher(String pattern) {
if (pattern == null || pattern.isBlank())
return (strings) -> true;

return (strings) -> {
if (p == null)
return true;
String[] parts = pattern.split("\\s+");
if (parts.length == 0)
return (strings) -> true;

Pattern[] subPatterns = Arrays.stream(parts)
.map(Pattern::quote)
.map(q -> Pattern.compile(q, Pattern.CASE_INSENSITIVE))
.toArray(Pattern[]::new);

return (strings) -> {
// strings represents a row, we match when the row contains all parts of the pattern
if (strings == null || strings.length == 0)
return false;

for (int i = 0; i < strings.length; i++) {
if (strings[i] != null && p.matcher(strings[i]).find())
return true;
// TODO: Not very efficient - can we make it faster?
for (int i = 0; i < subPatterns.length; i++) {
Pattern p = subPatterns[i];

boolean hasMatch = false;
for (int j = 0; j < strings.length; j++) {
if (p.matcher(strings[j]).find()) {
hasMatch = true;
break;
}
}

if (!hasMatch) return false;
}

return false;
return true;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ public class ElfDynamicSectionRenderer<NATIVE_WORD extends Number & Comparable<N
private final ElfDynamicSection<NATIVE_WORD> dynamicSection;

public ElfDynamicSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhrase,
ElfDynamicSection<NATIVE_WORD> dynamicSection) {
super(nativeWord, searchPhrase);
super(nativeWord);
this.dynamicSection = dynamicSection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ public class ElfGnuHashSectionRenderer<NATIVE_WORD extends Number & Comparable<N
private final ElfGnuHashSection<NATIVE_WORD> section;

public ElfGnuHashSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfGnuHashSection<NATIVE_WORD> section) {
super(nativeWord, searchPhase);
super(nativeWord);
this.section = section;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ public class ElfGnuVersionDefinitionsSectionRenderer<NATIVE_WORD extends Number

public ElfGnuVersionDefinitionsSectionRenderer(
NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfGnuVersionDefinitionsSection<NATIVE_WORD> section) {
super(nativeWord, searchPhase);
super(nativeWord);
this.section = section;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ public class ElfGnuVersionRequirementsSectionRenderer<NATIVE_WORD extends Number

public ElfGnuVersionRequirementsSectionRenderer(
NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfGnuVersionRequirementsSection<NATIVE_WORD> section) {
super(nativeWord, searchPhase);
super(nativeWord);
this.section = section;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ public class ElfGnuVersionSectionRenderer<NATIVE_WORD extends Number & Comparabl
private final ElfGnuVersionSection<NATIVE_WORD> section;

public ElfGnuVersionSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfGnuVersionSection<NATIVE_WORD> section) {
super(nativeWord, searchPhase);
super(nativeWord);
this.section = section;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public class ElfGnuWarningSectionRenderer<NATIVE_WORD extends Number & Comparabl
private final ElfGnuWarningSection warningSection;

public ElfGnuWarningSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfGnuWarningSection warningSection) {
super(nativeWord, searchPhase);
super(nativeWord);
this.warningSection = warningSection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ public class ElfHashSectionRenderer<NATIVE_WORD extends Number & Comparable<NATI
private final ElfHashSection<NATIVE_WORD> hashSection;

public ElfHashSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfHashSection<NATIVE_WORD> hashSection) {
super(nativeWord, searchPhase);
super(nativeWord);
this.hashSection = hashSection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public class ElfHeaderRenderer<NATIVE_WORD extends Number & Comparable<NATIVE_WO
private final ElfHeader<NATIVE_WORD> header;

public ElfHeaderRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfHeader<NATIVE_WORD> header) {
super(nativeWord, searchPhase);
super(nativeWord);
this.header = header;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ public class ElfIdentificationRenderer<NATIVE_WORD extends Number & Comparable<N
private final ElfIdentification identification;

public ElfIdentificationRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfIdentification identification) {
super(nativeWord, searchPhase);
super(nativeWord);
this.identification = identification;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public class ElfInterpreterSectionRenderer<NATIVE_WORD extends Number & Comparab
private final ElfInterpreterSection interpreterSection;

public ElfInterpreterSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfInterpreterSection interpreterSection) {
super(nativeWord, searchPhase);
super(nativeWord);
this.interpreterSection = interpreterSection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public class ElfInvalidSectionRenderer<NATIVE_WORD extends Number & Comparable<N
private final ElfInvalidSection<NATIVE_WORD> invalidSection;

public ElfInvalidSectionRenderer(NativeWord<NATIVE_WORD> nativeWord,
StringProperty searchPhase,
ElfInvalidSection<NATIVE_WORD> invalidSection) {
super(nativeWord, searchPhase);
super(nativeWord);
this.invalidSection = invalidSection;
}

Expand Down
Loading

0 comments on commit b3dcc0c

Please sign in to comment.