Skip to content

Commit

Permalink
convert search worker to javafx (#4897)
Browse files Browse the repository at this point in the history
* convert search worker to javafx

* remove obsolete search worker

* Add search query update result count

* First attempt at creating search highlighter for source tab

* Add custom css for codeArea highlighting on Search

* fix exception loop

* inline search listener

* refactor searchQueryHighlightobservable

* fix checkstyle

* fireSearchQueryHighlitghter on focus change

* Add sample js for highlighting

* add search query highlither to handle the highlighting

* add new regex js

* remove highlith listener before adding new one
use innertext in js

* fix merge, move code to new PreviewViewer

* fix checkstyle

* fix search highlighting in source editor
fix listeners

* refactor state manager as parameter
move css for highlighting
binding for searchResultSize

* Get rid of SearchQueryHighlightObservable
Use SearchQuery directly

TODO: fix updating of search results

* update on search

* fix checkstyle

* try again with checkstyle declaration order

* Finally fix the number of search results on multiple libs

* fix checkstyle
  • Loading branch information
Siedlerchr authored Jun 6, 2019
1 parent 9a5b7d1 commit dd4f0a0
Show file tree
Hide file tree
Showing 20 changed files with 205 additions and 342 deletions.
3 changes: 1 addition & 2 deletions src/main/java/org/jabref/gui/BasePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,9 @@ public BasePanel(JabRefFrame frame, BasePanelPreferences preferences, BibDatabas

this.getDatabase().registerListener(new UpdateTimestampListener(Globals.prefs));

this.entryEditor = new EntryEditor(this, preferences.getEntryEditorPreferences(), Globals.getFileUpdateMonitor(), dialogService, externalFileTypes, Globals.TASK_EXECUTOR);
this.entryEditor = new EntryEditor(this, preferences.getEntryEditorPreferences(), Globals.getFileUpdateMonitor(), dialogService, externalFileTypes, Globals.TASK_EXECUTOR, Globals.stateManager);

this.preview = new PreviewPanel(getBibDatabaseContext(), this, dialogService, externalFileTypes, Globals.getKeyPrefs(), preferences.getPreviewPreferences());
frame().getGlobalSearchBar().getSearchQueryHighlightObservable().addSearchListener(preview);
}

@Subscribe
Expand Down
15 changes: 12 additions & 3 deletions src/main/java/org/jabref/gui/StateManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.stream.Collectors;

import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyListProperty;
import javafx.beans.property.ReadOnlyListWrapper;
import javafx.collections.FXCollections;
Expand All @@ -23,9 +24,8 @@
* This class manages the GUI-state of JabRef, including:
* - currently selected database
* - currently selected group
* Coming soon:
* - open databases
* - active search
* - active number of search results
*/
public class StateManager {

Expand All @@ -34,6 +34,7 @@ public class StateManager {
private final ObservableList<BibEntry> selectedEntries = FXCollections.observableArrayList();
private final ObservableMap<BibDatabaseContext, ObservableList<GroupTreeNode>> selectedGroups = FXCollections.observableHashMap();
private final OptionalObjectProperty<SearchQuery> activeSearchQuery = OptionalObjectProperty.empty();
private final ObservableMap<BibDatabaseContext, IntegerProperty> searchResultMap = FXCollections.observableHashMap();

public StateManager() {
activeGroups.bind(Bindings.valueAt(selectedGroups, activeDatabase.orElse(null)));
Expand All @@ -47,6 +48,14 @@ public OptionalObjectProperty<SearchQuery> activeSearchQueryProperty() {
return activeSearchQuery;
}

public void setActiveSearchResultSize(BibDatabaseContext database, IntegerProperty resultSize) {
searchResultMap.put(database, resultSize);
}

public IntegerProperty getSearchResultSize() {
return searchResultMap.get(activeDatabase.getValue().orElse(new BibDatabaseContext()));
}

public ReadOnlyListProperty<GroupTreeNode> activeGroupProperty() {
return activeGroups.getReadOnlyProperty();
}
Expand Down Expand Up @@ -79,7 +88,7 @@ public Optional<BibDatabaseContext> getActiveDatabase() {

public List<BibEntry> getEntriesInCurrentDatabase() {
return OptionalUtil.flatMap(activeDatabase.get(), BibDatabaseContext::getEntries)
.collect(Collectors.toList());
.collect(Collectors.toList());
}

public void clearSearchQuery() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import javafx.scene.Node;

import org.jabref.Globals;
import org.jabref.JabRefGUI;
import org.jabref.gui.preview.PreviewViewer;
import org.jabref.gui.undo.NamedCompound;
Expand All @@ -27,7 +28,7 @@ public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) {

@Override
public Node description() {
PreviewViewer previewViewer = new PreviewViewer(new BibDatabaseContext(), JabRefGUI.getMainFrame().getDialogService());
PreviewViewer previewViewer = new PreviewViewer(new BibDatabaseContext(), JabRefGUI.getMainFrame().getDialogService(), Globals.stateManager);
previewViewer.setEntry(diskEntry);
return previewViewer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import javafx.scene.Node;

import org.jabref.Globals;
import org.jabref.JabRefGUI;
import org.jabref.gui.preview.PreviewViewer;
import org.jabref.gui.undo.NamedCompound;
Expand Down Expand Up @@ -44,7 +45,7 @@ public void makeChange(BibDatabaseContext database, NamedCompound undoEdit) {

@Override
public Node description() {
PreviewViewer previewViewer = new PreviewViewer(new BibDatabaseContext(), JabRefGUI.getMainFrame().getDialogService());
PreviewViewer previewViewer = new PreviewViewer(new BibDatabaseContext(), JabRefGUI.getMainFrame().getDialogService(), Globals.stateManager);
previewViewer.setEntry(memEntry);
return previewViewer;
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/jabref/gui/entryeditor/EntryEditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,10 @@
-fx-padding: 20 20 20 20;
}

#bibtexSourceCodeArea .search {
-fx-fill: red;
}

.bibtexSourceCodeArea .text {
-fx-fill: -fx-text-background-color;
}
52 changes: 17 additions & 35 deletions src/main/java/org/jabref/gui/entryeditor/EntryEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
Expand All @@ -27,6 +26,7 @@
import org.jabref.gui.BasePanel;
import org.jabref.gui.DialogService;
import org.jabref.gui.GUIGlobals;
import org.jabref.gui.StateManager;
import org.jabref.gui.bibtexkeypattern.GenerateBibtexKeySingleAction;
import org.jabref.gui.entryeditor.fileannotationtab.FileAnnotationTab;
import org.jabref.gui.externalfiles.ExternalFilesEntryLinker;
Expand All @@ -43,7 +43,6 @@
import org.jabref.logic.help.HelpFile;
import org.jabref.logic.importer.EntryBasedFetcher;
import org.jabref.logic.importer.WebFetchers;
import org.jabref.logic.search.SearchQueryHighlightListener;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.util.FileUpdateMonitor;
Expand Down Expand Up @@ -71,7 +70,6 @@ public class EntryEditor extends BorderPane {
private final BibDatabaseContext databaseContext;
private final CountingUndoManager undoManager;
private final BasePanel panel;
private final List<SearchQueryHighlightListener> searchListeners = new ArrayList<>();
private Subscription typeSubscription;
private final List<EntryEditorTab> tabs;
private final FileUpdateMonitor fileMonitor;
Expand All @@ -90,15 +88,17 @@ public class EntryEditor extends BorderPane {
private final DialogService dialogService;
private final ExternalFilesEntryLinker fileLinker;
private final TaskExecutor taskExecutor;
private final StateManager stateManager;

public EntryEditor(BasePanel panel, EntryEditorPreferences preferences, FileUpdateMonitor fileMonitor, DialogService dialogService, ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor) {
public EntryEditor(BasePanel panel, EntryEditorPreferences preferences, FileUpdateMonitor fileMonitor, DialogService dialogService, ExternalFileTypes externalFileTypes, TaskExecutor taskExecutor, StateManager stateManager) {
this.panel = panel;
this.databaseContext = panel.getBibDatabaseContext();
this.undoManager = panel.getUndoManager();
this.preferences = Objects.requireNonNull(preferences);
this.fileMonitor = fileMonitor;
this.dialogService = dialogService;
this.taskExecutor = taskExecutor;
this.stateManager = stateManager;

fileLinker = new ExternalFilesEntryLinker(externalFileTypes, Globals.prefs.getFilePreferences(), databaseContext);

Expand All @@ -108,9 +108,9 @@ public EntryEditor(BasePanel panel, EntryEditorPreferences preferences, FileUpda

if (GUIGlobals.currentFont != null) {
setStyle(
"text-area-background: " + ColorUtil.toHex(GUIGlobals.validFieldBackgroundColor) + ";"
+ "text-area-foreground: " + ColorUtil.toHex(GUIGlobals.editorTextColor) + ";"
+ "text-area-highlight: " + ColorUtil.toHex(GUIGlobals.activeBackgroundColor) + ";");
"text-area-background: " + ColorUtil.toHex(GUIGlobals.validFieldBackgroundColor) + ";"
+ "text-area-foreground: " + ColorUtil.toHex(GUIGlobals.editorTextColor) + ";"
+ "text-area-highlight: " + ColorUtil.toHex(GUIGlobals.activeBackgroundColor) + ";");
}

EasyBind.subscribe(tabbed.getSelectionModel().selectedItemProperty(), tab -> {
Expand Down Expand Up @@ -139,58 +139,46 @@ public EntryEditor(BasePanel panel, EntryEditorPreferences preferences, FileUpda

FileDragDropPreferenceType dragDropPreferencesType = Globals.prefs.getEntryEditorFileLinkPreference();

if (dragDropPreferencesType == FileDragDropPreferenceType.MOVE)
{
if (dragDropPreferencesType == FileDragDropPreferenceType.MOVE) {
if (event.getTransferMode() == TransferMode.LINK) //alt on win
{
LOGGER.debug("Mode LINK");
fileLinker.addFilesToEntry(entry, files);
}
else if (event.getTransferMode() == TransferMode.COPY) //ctrl on win, no modifier on Xubuntu
} else if (event.getTransferMode() == TransferMode.COPY) //ctrl on win, no modifier on Xubuntu
{
LOGGER.debug("Mode COPY");
fileLinker.copyFilesToFileDirAndAddToEntry(entry, files);
}
else
{
} else {
LOGGER.debug("Mode MOVE"); //shift on win or no modifier
fileLinker.moveFilesToFileDirAndAddToEntry(entry, files);
}
}

if (dragDropPreferencesType == FileDragDropPreferenceType.COPY)
{
if (dragDropPreferencesType == FileDragDropPreferenceType.COPY) {
if (event.getTransferMode() == TransferMode.COPY) //ctrl on win, no modifier on Xubuntu
{
LOGGER.debug("Mode MOVE");
fileLinker.moveFilesToFileDirAndAddToEntry(entry, files);
}
else if (event.getTransferMode() == TransferMode.LINK) //alt on win
} else if (event.getTransferMode() == TransferMode.LINK) //alt on win
{
LOGGER.debug("Mode LINK");
fileLinker.addFilesToEntry(entry, files);
}
else
{
} else {
LOGGER.debug("Mode COPY"); //shift on win or no modifier
fileLinker.copyFilesToFileDirAndAddToEntry(entry, files);
}
}

if (dragDropPreferencesType == FileDragDropPreferenceType.LINK)
{
if (dragDropPreferencesType == FileDragDropPreferenceType.LINK) {
if (event.getTransferMode() == TransferMode.COPY) //ctrl on win, no modifier on Xubuntu
{
LOGGER.debug("Mode COPY");
fileLinker.copyFilesToFileDirAndAddToEntry(entry, files);
}
else if (event.getTransferMode() == TransferMode.LINK) //alt on win
} else if (event.getTransferMode() == TransferMode.LINK) //alt on win
{
LOGGER.debug("Mode MOVE");
fileLinker.moveFilesToFileDirAndAddToEntry(entry, files);
}
else
{
} else {
LOGGER.debug("Mode LINK"); //shift on win or no modifier
fileLinker.addFilesToEntry(entry, files);
}
Expand Down Expand Up @@ -299,7 +287,7 @@ private List<EntryEditorTab> createTabs() {
tabs.add(new RelatedArticlesTab(preferences, dialogService));

// Source tab
sourceTab = new SourceTab(databaseContext, undoManager, preferences.getLatexFieldFormatterPreferences(), preferences.getImportFormatPreferences(), fileMonitor, dialogService);
sourceTab = new SourceTab(databaseContext, undoManager, preferences.getLatexFieldFormatterPreferences(), preferences.getImportFormatPreferences(), fileMonitor, dialogService, stateManager);
tabs.add(sourceTab);
return tabs;
}
Expand Down Expand Up @@ -396,12 +384,6 @@ private void fetchAndMerge(EntryBasedFetcher fetcher) {
new FetchAndMergeEntry(panel, taskExecutor).fetchAndMerge(entry, fetcher);
}

void addSearchListener(SearchQueryHighlightListener listener) {
// TODO: Highlight search text in entry editors
searchListeners.add(listener);
panel.frame().getGlobalSearchBar().getSearchQueryHighlightObservable().addSearchListener(listener);
}

public void setFocusToField(String fieldName) {
DefaultTaskExecutor.runInJavaFXThread(() -> {
for (Tab tab : tabbed.getTabs()) {
Expand Down
45 changes: 37 additions & 8 deletions src/main/java/org/jabref/gui/entryeditor/SourceTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import java.io.StringWriter;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.undo.UndoManager;

Expand All @@ -16,6 +19,7 @@
import javafx.scene.input.InputMethodRequests;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.undo.CountingUndoManager;
import org.jabref.gui.undo.NamedCompound;
Expand All @@ -31,6 +35,7 @@
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.importer.fileformat.BibtexParser;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.search.SearchQuery;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.database.BibDatabaseMode;
Expand All @@ -53,12 +58,16 @@ public class SourceTab extends EntryEditorTab {
private final BibDatabaseMode mode;
private final UndoManager undoManager;
private final ObjectProperty<ValidationMessage> sourceIsValid = new SimpleObjectProperty<>();
private final ObservableRuleBasedValidator sourceValidator = new ObservableRuleBasedValidator(sourceIsValid);
@SuppressWarnings("unchecked") private final ObservableRuleBasedValidator sourceValidator = new ObservableRuleBasedValidator(sourceIsValid);
private final ImportFormatPreferences importFormatPreferences;
private final FileUpdateMonitor fileMonitor;
private final DialogService dialogService;
private final StateManager stateManager;

public SourceTab(BibDatabaseContext bibDatabaseContext, CountingUndoManager undoManager, LatexFieldFormatterPreferences fieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor, DialogService dialogService) {
private Optional<Pattern> searchHighlightPattern = Optional.empty();
private CodeArea codeArea;

public SourceTab(BibDatabaseContext bibDatabaseContext, CountingUndoManager undoManager, LatexFieldFormatterPreferences fieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor, DialogService dialogService, StateManager stateManager) {
this.mode = bibDatabaseContext.getMode();
this.setText(Localization.lang("%0 source", mode.getFormattedName()));
this.setTooltip(new Tooltip(Localization.lang("Show/edit %0 source", mode.getFormattedName())));
Expand All @@ -68,9 +77,27 @@ public SourceTab(BibDatabaseContext bibDatabaseContext, CountingUndoManager undo
this.importFormatPreferences = importFormatPreferences;
this.fileMonitor = fileMonitor;
this.dialogService = dialogService;
this.stateManager = stateManager;

stateManager.activeSearchQueryProperty().addListener((observable, oldValue, newValue) -> {
searchHighlightPattern = newValue.flatMap(SearchQuery::getPatternForWords);
highlightSearchPattern();
});

}

private void highlightSearchPattern() {
if (searchHighlightPattern.isPresent() && codeArea != null) {
codeArea.setStyleClass(0, codeArea.getLength(), "text");
Matcher matcher = searchHighlightPattern.get().matcher(codeArea.getText());
while (matcher.find()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
codeArea.setStyleClass(matcher.start(), matcher.end(), "search");
}
}
}
}

private static String getSourceString(BibEntry entry, BibDatabaseMode type, LatexFieldFormatterPreferences fieldFormatterPreferences) throws IOException {
StringWriter stringWriter = new StringWriter(200);
LatexFieldFormatter formatter = LatexFieldFormatter.buildIgnoreHashes(fieldFormatterPreferences);
Expand Down Expand Up @@ -115,6 +142,7 @@ private CodeArea createSourceEditor() {
codeArea.insertText(codeArea.getCaretPosition(), committed);
}
});
codeArea.setId("bibtexSourceCodeArea");
return codeArea;
}

Expand All @@ -140,7 +168,7 @@ protected void bindToEntry(BibEntry entry) {
}
});
this.setContent(codeArea);

this.codeArea = codeArea;
// Store source for on focus out event in the source code (within its text area)
// and update source code for every change of entry field values
BindingsHelper.bindContentBidirectional(entry.getFieldsObservable(), codeArea.focusedProperty(), onFocus -> {
Expand All @@ -152,10 +180,12 @@ protected void bindToEntry(BibEntry entry) {
codeArea.clear();
try {
codeArea.appendText(getSourceString(entry, mode, fieldFormatterPreferences));
highlightSearchPattern();

} catch (IOException ex) {
codeArea.setEditable(false);
codeArea.appendText(ex.getMessage() + "\n\n" +
Localization.lang("Correct the entry, and reopen editor to display/edit source."));
Localization.lang("Correct the entry, and reopen editor to display/edit source."));
LOGGER.debug("Incorrect entry", ex);
}
});
Expand Down Expand Up @@ -208,8 +238,7 @@ private void storeSource(BibEntry outOfFocusEntry, String text) {
String fieldValue = field.getValue();

if (InternalBibtexFields.isDisplayableField(fieldName) && !newEntry.hasField(fieldName)) {
compound.addEdit(
new UndoableFieldChange(outOfFocusEntry, fieldName, fieldValue, null));
compound.addEdit(new UndoableFieldChange(outOfFocusEntry, fieldName, fieldValue, null));
outOfFocusEntry.clearField(fieldName);
}
}
Expand All @@ -221,8 +250,7 @@ private void storeSource(BibEntry outOfFocusEntry, String text) {
String newValue = field.getValue();
if (!Objects.equals(oldValue, newValue)) {
// Test if the field is legally set.
new LatexFieldFormatter(fieldFormatterPreferences)
.format(newValue, fieldName);
new LatexFieldFormatter(fieldFormatterPreferences).format(newValue, fieldName);

compound.addEdit(new UndoableFieldChange(outOfFocusEntry, fieldName, oldValue, newValue));
outOfFocusEntry.setField(fieldName, newValue);
Expand All @@ -243,4 +271,5 @@ private void storeSource(BibEntry outOfFocusEntry, String text) {
LOGGER.debug("Incorrect source", ex);
}
}

}
Loading

0 comments on commit dd4f0a0

Please sign in to comment.