-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Searchable/Filterable preferences (#4415)
* add search box to preferences * replace deprecated method call * Fix codestyle/checkstyle * Add Preferences Search Handler still work in progress mapping search to preference and start searching it still needs a way to filter the found items * Remove unused variable * Add a list of filtered preftabs instead of filtered preftabnames * 🎉 Add the actual filtering of the elements * Favor SimpleListProperty over SimpleObjectProperty * Fix Imports also be explicit about method visibility * Add filtering of labels * Remove some unneeded member variables * extract filterBy methods * Fix Type of ListProperty * Remove todo Verified this is not the case: label names dont contain tab names * Reformat code * Favor regular List over ObservableList * Use existing translated text for prompt * Revert: Favor regular List over ObservableList because build (guiTest) fails * Favor regular List over ObservableList is not the cause of the build failure * Adding search highlight while filtering * Replacing map by multimaps and changing the mapping relation * Fixing checkstyle error * Added Locale.ROOT when converting to lower case * Removed redundant comments * Removed LabeledWrapper inner class and refactored PreferencesSearchHandler * Fixed checkstyle error * add bidiretional binding to searchProperty * Added change listener on searchBox and removed search text property Co-authored-by: Yash Kothari <yashkothari199767@gmail.com>
- Loading branch information
1 parent
44163bf
commit ef5710c
Showing
3 changed files
with
119 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
98 changes: 98 additions & 0 deletions
98
src/main/java/org/jabref/gui/preferences/PreferencesSearchHandler.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package org.jabref.gui.preferences; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Locale; | ||
|
||
import javafx.beans.property.ListProperty; | ||
import javafx.beans.property.SimpleListProperty; | ||
import javafx.collections.FXCollections; | ||
import javafx.css.PseudoClass; | ||
import javafx.scene.Node; | ||
import javafx.scene.Parent; | ||
import javafx.scene.control.Labeled; | ||
|
||
import com.google.common.collect.ArrayListMultimap; | ||
|
||
class PreferencesSearchHandler { | ||
|
||
private static PseudoClass labelHighlight = PseudoClass.getPseudoClass("search-highlight"); | ||
private final List<PrefsTab> preferenceTabs; | ||
private final ListProperty<PrefsTab> filteredPreferenceTabs; | ||
private final ArrayListMultimap<PrefsTab, Labeled> preferenceTabsLabelNames; | ||
private final ArrayList<Labeled> highlightedLabels = new ArrayList<>(); | ||
|
||
PreferencesSearchHandler(List<PrefsTab> preferenceTabs) { | ||
this.preferenceTabs = preferenceTabs; | ||
this.preferenceTabsLabelNames = getPrefsTabLabelMap(); | ||
this.filteredPreferenceTabs = new SimpleListProperty<>(FXCollections.observableArrayList(preferenceTabs)); | ||
} | ||
|
||
public void filterTabs(String text) { | ||
clearHighlights(); | ||
if (text.isEmpty()) { | ||
clearSearch(); | ||
return; | ||
} | ||
|
||
filteredPreferenceTabs.clear(); | ||
for (PrefsTab tab : preferenceTabsLabelNames.keySet()) { | ||
boolean tabContainsLabel = false; | ||
for (Labeled labeled : preferenceTabsLabelNames.get(tab)) { | ||
if (labelContainsText(labeled, text)) { | ||
tabContainsLabel = true; | ||
highlightLabel(labeled); | ||
} | ||
} | ||
boolean tabNameIsMatchedByQuery = tab.getTabName().toLowerCase(Locale.ROOT).contains(text); | ||
if (tabContainsLabel || tabNameIsMatchedByQuery) { | ||
filteredPreferenceTabs.add(tab); | ||
} | ||
} | ||
} | ||
|
||
private boolean labelContainsText(Labeled labeled, String text) { | ||
return labeled.getText().toLowerCase(Locale.ROOT).contains(text); | ||
} | ||
|
||
private void highlightLabel(Labeled labeled) { | ||
labeled.pseudoClassStateChanged(labelHighlight, true); | ||
highlightedLabels.add(labeled); | ||
} | ||
|
||
private void clearHighlights() { | ||
highlightedLabels.forEach(labeled -> labeled.pseudoClassStateChanged(labelHighlight, false)); | ||
} | ||
|
||
private void clearSearch() { | ||
filteredPreferenceTabs.setAll(preferenceTabs); | ||
} | ||
|
||
/* | ||
* Traverse all nodes of a PrefsTab and return a | ||
* mapping from PrefsTab to all its Labeled type nodes. | ||
*/ | ||
private ArrayListMultimap<PrefsTab, Labeled> getPrefsTabLabelMap() { | ||
ArrayListMultimap<PrefsTab, Labeled> prefsTabLabelMap = ArrayListMultimap.create(); | ||
for (PrefsTab prefsTab : preferenceTabs) { | ||
Node builder = prefsTab.getBuilder(); | ||
if (builder instanceof Parent) { | ||
Parent parentBuilder = (Parent) builder; | ||
for (Node child : parentBuilder.getChildrenUnmodifiable()) { | ||
if (child instanceof Labeled) { | ||
Labeled labeled = (Labeled) child; | ||
if (!labeled.getText().isEmpty()) { | ||
prefsTabLabelMap.put(prefsTab, labeled); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return prefsTabLabelMap; | ||
} | ||
|
||
protected ListProperty<PrefsTab> filteredPreferenceTabsProperty() { | ||
return filteredPreferenceTabs; | ||
} | ||
|
||
} |