Skip to content

Commit

Permalink
Implements #565: Highlighting matches works now also for regular expr…
Browse files Browse the repository at this point in the history
…essions in preview panel and entry editor
  • Loading branch information
simonharrer committed Dec 22, 2015
1 parent edcb399 commit 0bc1810
Show file tree
Hide file tree
Showing 19 changed files with 246 additions and 215 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by
- Icons are shown as Header for icon columns in the entry table (#315)
- Tooltips are shown for header columns and contents which are too wide to be displayed in the entry table (#384)
- Default order in entry table: # | all file based icons (file, URL/DOI, ...) | all bibtex field based icons (bibtexkey, entrytype, author, title, ...) | all activated special field icons (ranking, quality, ...)
- Implements #565: Highlighting matches works now also for regular expressions in preview panel and entry editor

### Fixed
- Fixed #479: Import works again
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/net/sf/jabref/exporter/layout/Layout.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package net.sf.jabref.exporter.layout;

import java.util.Optional;
import java.util.Vector;

import org.apache.commons.logging.Log;
Expand All @@ -23,6 +24,7 @@
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import net.sf.jabref.model.database.BibDatabase;
import net.sf.jabref.model.entry.BibEntry;
Expand Down Expand Up @@ -123,11 +125,11 @@ public String doLayout(BibEntry bibtex, BibDatabase database) {
* string references will be replaced by the strings' contents. Even
* recursive string references are resolved.
*/
public String doLayout(BibEntry bibtex, BibDatabase database, List<String> wordsToHighlight) {
public String doLayout(BibEntry bibtex, BibDatabase database, Optional<Pattern> highlightPattern) {
StringBuilder sb = new StringBuilder(100);

for (LayoutEntry layoutEntry : layoutEntries) {
String fieldText = layoutEntry.doLayout(bibtex, database, wordsToHighlight);
String fieldText = layoutEntry.doLayout(bibtex, database, highlightPattern);

// 2005.05.05 M. Alver
// The following change means we treat null fields as "". This is to fix the
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/net/sf/jabref/exporter/layout/LayoutEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.*;
import java.util.regex.Pattern;

import net.sf.jabref.gui.search.MatchesHighlighter;
import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -173,7 +171,7 @@ private String doLayout(BibEntry bibtex, BibDatabase database) {
return doLayout(bibtex, database, null);
}

public String doLayout(BibEntry bibtex, BibDatabase database, List<String> wordsToHighlight) {
public String doLayout(BibEntry bibtex, BibDatabase database, Optional<Pattern> highlightPattern) {
switch (type) {
case LayoutHelper.IS_LAYOUT_TEXT:
return text;
Expand Down Expand Up @@ -264,7 +262,7 @@ public String doLayout(BibEntry bibtex, BibDatabase database, List<String> words
*
*/
if (bibtex.isSearchHit()) {
sb.append(MatchesHighlighter.highlightWordsWithHTML(fieldText, wordsToHighlight));
sb.append(MatchesHighlighter.highlightWordsWithHTML(fieldText, highlightPattern));
} else {
sb.append(fieldText);
}
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/net/sf/jabref/gui/PreviewPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
Expand All @@ -41,7 +42,7 @@
import net.sf.jabref.exporter.ExportFormats;
import net.sf.jabref.gui.fieldeditors.PreviewPanelTransferHandler;
import net.sf.jabref.gui.keyboard.KeyBinding;
import net.sf.jabref.logic.search.SearchTextListener;
import net.sf.jabref.logic.search.SearchQueryHighlightListener;
import net.sf.jabref.logic.l10n.Localization;
import net.sf.jabref.model.database.BibDatabase;
import net.sf.jabref.model.entry.BibEntry;
Expand All @@ -52,7 +53,7 @@
/**
* Displays an BibEntry using the given layout format.
*/
public class PreviewPanel extends JPanel implements VetoableChangeListener, SearchTextListener, EntryContainer {
public class PreviewPanel extends JPanel implements VetoableChangeListener, SearchQueryHighlightListener, EntryContainer {

private static final Log LOGGER = LogFactory.getLog(PreviewPanel.class);

Expand Down Expand Up @@ -90,7 +91,7 @@ public class PreviewPanel extends JPanel implements VetoableChangeListener, Sear

private final CloseAction closeAction;

private final List<String> wordsToHighlight = new LinkedList<>();
private Optional<Pattern> highlightPattern = Optional.empty();

/**
* @param database
Expand Down Expand Up @@ -335,7 +336,7 @@ public void update() {
ExportFormats.entryNumber = 1; // Set entry number in case that is included in the preview layout.
entry.ifPresent(entry ->
layout.ifPresent(layout ->
sb.append(layout.doLayout(entry, database.orElse(null), wordsToHighlight))
sb.append(layout.doLayout(entry, database.orElse(null), highlightPattern))
)
);
String newValue = sb.toString();
Expand Down Expand Up @@ -368,9 +369,8 @@ public void vetoableChange(PropertyChangeEvent evt)
}

@Override
public void searchText(List<String> words) {
this.wordsToHighlight.clear();
this.wordsToHighlight.addAll(words);
public void highlightPattern(Optional<Pattern> highlightPattern) {
this.highlightPattern = highlightPattern;
update();
}

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
import net.sf.jabref.importer.ParserResult;
import net.sf.jabref.logic.l10n.Localization;
import net.sf.jabref.logic.labelPattern.LabelPatternUtil;
import net.sf.jabref.logic.search.SearchTextListener;
import net.sf.jabref.logic.search.SearchQueryHighlightListener;
import net.sf.jabref.logic.util.date.EasyDateFormat;
import net.sf.jabref.model.database.BibDatabase;
import net.sf.jabref.model.entry.*;
import net.sf.jabref.specialfields.SpecialFieldUpdateListener;
Expand Down Expand Up @@ -449,7 +450,7 @@ public Optional<JComponent> getExtra(final FieldEditor editor) {

private void setupSourcePanel() {
source = new JTextAreaWithHighlighting();
panel.getSearchBar().getSearchTextObservable().addSearchListener((SearchTextListener) source);
panel.getSearchBar().getSearchQueryHighlightObservable().addSearchListener((SearchQueryHighlightListener) source);

source.setEditable(true);
source.setLineWrap(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private void setupPanel(JabRefFrame frame, BasePanel bPanel, boolean addKeyField
defaultHeight = 0;
} else {
fieldEditor = new TextArea(fields[i], null);
bPanel.getSearchBar().getSearchTextObservable().addSearchListener((TextArea) fieldEditor);
bPanel.getSearchBar().getSearchQueryHighlightObservable().addSearchListener((TextArea) fieldEditor);
defaultHeight = fieldEditor.getPane().getPreferredSize().height;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import net.sf.jabref.gui.actions.Actions;
import net.sf.jabref.gui.actions.PasteAction;
import net.sf.jabref.gui.search.MatchesHighlighter;
import net.sf.jabref.logic.search.SearchTextListener;
import net.sf.jabref.logic.search.SearchQueryHighlightListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Expand All @@ -35,11 +35,11 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JTextAreaWithHighlighting extends JTextArea implements SearchTextListener {
public class JTextAreaWithHighlighting extends JTextArea implements SearchQueryHighlightListener {

private static final Log LOGGER = LogFactory.getLog(JTextAreaWithHighlighting.class);

private List<String> wordsToHighlight;
private Optional<Pattern> highlightPattern = Optional.empty();

private UndoManager undo;

Expand Down Expand Up @@ -131,21 +131,20 @@ public void actionPerformed(ActionEvent evt) {
*
* @param words to highlight
*/
private void highLight(List<String> words) {
private void highLight(Optional<Pattern> highlightPattern) {
// highlight all characters that appear in charsToHighlight
Highlighter highlighter = getHighlighter();
highlighter.removeAllHighlights();

if ((words == null) || words.isEmpty() || words.get(0).isEmpty()) {
if (highlightPattern == null || !highlightPattern.isPresent()) {

This comment has been minimized.

Copy link
@koppor

koppor Dec 23, 2015

Member

highlightPattern is an Optional. Why is a null check required?

This comment has been minimized.

Copy link
@simonharrer

simonharrer Dec 23, 2015

Author Contributor

Normally, one should not use optionals as parameters, but in this case it is required as one cannot easily create a null object of a Pattern. This is fine so.

return;
}
String content = getText();
if (content.isEmpty()) {
return;
}

MatchesHighlighter.getPatternForWords(words, Globals.prefs.getBoolean(JabRefPreferences.SEARCH_REG_EXP),
Globals.prefs.getBoolean(JabRefPreferences.SEARCH_CASE_SENSITIVE)).ifPresent(pattern -> {
highlightPattern.ifPresent(pattern -> {
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
try {
Expand All @@ -157,23 +156,21 @@ private void highLight(List<String> words) {
}
});



}

@Override
public void setText(String text) {
super.setText(text);
highLight(wordsToHighlight);
highLight(highlightPattern);
if (undo != null) {
undo.discardAllEdits();
}
}

@Override
public void searchText(List<String> words) {
this.wordsToHighlight = words;
highLight(words);
public void highlightPattern(Optional<Pattern> highlightPattern) {
this.highlightPattern = highlightPattern;
highLight(highlightPattern);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ public MainTableSelectionListener(BasePanel panel, MainTable table) {
new PreviewPanel(panel.database(), null, panel, panel.metaData(), Globals.prefs
.get(JabRefPreferences.PREVIEW_1), true)};

panel.getSearchBar().getSearchTextObservable().addSearchListener(previewPanel[0]);
panel.getSearchBar().getSearchTextObservable().addSearchListener(previewPanel[1]);
panel.getSearchBar().getSearchQueryHighlightObservable().addSearchListener(previewPanel[0]);
panel.getSearchBar().getSearchQueryHighlightObservable().addSearchListener(previewPanel[1]);

this.preview = previewPanel[activePreview];
}
Expand Down
33 changes: 4 additions & 29 deletions src/main/java/net/sf/jabref/gui/search/MatchesHighlighter.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,15 @@ public class MatchesHighlighter {
* @param wordsToHighlight List of all words which must be highlighted
* @return String that was called by the method, with HTML Tags if a word was found
*/
public static String highlightWordsWithHTML(String text, List<String> wordsToHighlight) {
Objects.requireNonNull(wordsToHighlight);
public static String highlightWordsWithHTML(String text, Optional<Pattern> highlightPattern) {
Objects.requireNonNull(highlightPattern);
Objects.requireNonNull(text);

if (text.isEmpty() || wordsToHighlight.isEmpty()) {
if (text.isEmpty() || !highlightPattern.isPresent()) {
return text;
}

Optional<Pattern> patternForWords = getPatternForWords(wordsToHighlight, Globals.prefs.getBoolean(JabRefPreferences.SEARCH_REG_EXP),
Globals.prefs.getBoolean(JabRefPreferences.SEARCH_CASE_SENSITIVE));
if (!patternForWords.isPresent()) {
return text;
}

Matcher matcher = patternForWords.get().matcher(text);
Matcher matcher = highlightPattern.get().matcher(text);

StringBuffer sb = new StringBuffer();
boolean foundSomething = false;
Expand All @@ -62,23 +56,4 @@ public static String highlightWordsWithHTML(String text, List<String> wordsToHig
return text;
}

// Returns a regular expression pattern in the form (w1)|(w2)| ... wi are escaped if no regular expression search is enabled
public static Optional<Pattern> getPatternForWords(List<String> words, boolean useRegex, boolean isCaseSensitive) {
if ((words == null) || words.isEmpty() || words.get(0).isEmpty()) {
return Optional.empty();
}

// compile the words to a regular expression in the form (w1)|(w2)|(w3)
StringJoiner joiner = new StringJoiner(")|(", "(", ")");
for (String word : words) {
joiner.add(useRegex ? word : Pattern.quote(word));
}
String searchPattern = joiner.toString();

if (isCaseSensitive) {
return Optional.of(Pattern.compile(searchPattern));
} else {
return Optional.of(Pattern.compile(searchPattern, Pattern.CASE_INSENSITIVE));
}
}
}
14 changes: 7 additions & 7 deletions src/main/java/net/sf/jabref/gui/search/SearchBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import net.sf.jabref.logic.l10n.Localization;
import net.sf.jabref.logic.search.SearchQuery;
import net.sf.jabref.logic.search.SearchQueryLocalizer;
import net.sf.jabref.logic.search.SearchTextObservable;
import net.sf.jabref.logic.search.SearchQueryHighlightObservable;
import net.sf.jabref.model.entry.BibEntry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand Down Expand Up @@ -58,7 +58,7 @@ public class SearchBar extends JPanel {

private final BasePanel basePanel;

private final SearchTextObservable searchTextObservable;
private final SearchQueryHighlightObservable searchQueryHighlightObservable;
private final JSearchTextField searchField;

private SearchMode searchMode = getSearchModeFromSettings();
Expand All @@ -80,7 +80,7 @@ public SearchBar(BasePanel basePanel) {
super();

this.basePanel = Objects.requireNonNull(basePanel);
this.searchTextObservable = new SearchTextObservable();
this.searchQueryHighlightObservable = new SearchQueryHighlightObservable();

currentResults.setFont(currentResults.getFont().deriveFont(Font.BOLD));

Expand Down Expand Up @@ -248,7 +248,7 @@ private void clearSearch() {
searchField.setText("");
searchField.setBackground(Color.WHITE);

searchTextObservable.fireSearchlistenerEvent(null);
searchQueryHighlightObservable.fireSearchlistenerEvent(null);

this.currentResults.setText("");

Expand Down Expand Up @@ -288,7 +288,7 @@ private void performSearch() {
private void informUserAboutInvalidSearchQuery() {
searchField.setBackground(NO_RESULTS_COLOR);

searchTextObservable.fireSearchlistenerEvent(null);
searchQueryHighlightObservable.fireSearchlistenerEvent(null);

globalSearch.setEnabled(false);
openCurrentResultsInDialog.setEnabled(false);
Expand All @@ -311,8 +311,8 @@ public void setAutoCompleter(AutoCompleter<String> searchCompleter) {
this.autoCompleteSupport.setAutoCompleter(searchCompleter);
}

public SearchTextObservable getSearchTextObservable() {
return searchTextObservable;
public SearchQueryHighlightObservable getSearchQueryHighlightObservable() {
return searchQueryHighlightObservable;
}

public boolean isStillValidQuery(SearchQuery query) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/sf/jabref/gui/search/SearchWorker.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public void update() {
}

basePanel.getSearchBar().updateResults(hits, searchQuery.description, searchQuery.isGrammarBasedSearch());
basePanel.getSearchBar().getSearchTextObservable().fireSearchlistenerEvent(searchQuery);
basePanel.getSearchBar().getSearchQueryHighlightObservable().fireSearchlistenerEvent(searchQuery);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package net.sf.jabref.logic.search;

import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

/**
* Every Listener that wants to receive events from a search needs to
Expand All @@ -24,12 +26,12 @@
* @author Ben
*
*/
public interface SearchTextListener {
public interface SearchQueryHighlightListener {

/**
* Array of words that were searched for
* Pattern with which one can determine what to highlight
*
* @param words null if nothing is searched for
*/
void searchText(List<String> words);
void highlightPattern(Optional<Pattern> highlightPattern);
}
Loading

0 comments on commit 0bc1810

Please sign in to comment.