Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Complete rework of the auto completion #2965

Merged
merged 11 commits into from
Jul 11, 2017
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- The buttons were changed to icons.
- Completely new interface to add or modify linked files.
- Removed the hidden feature that a double click in the editor inserted the current date.
- Complete new implementation of the the auto complete feature.
- All authors and editors are separated using semicolons when exporting to csv. [#2762](https://github.com/JabRef/jabref/issues/2762)
- Improved wording of "Show recommendations: into "Show 'Related Articles' tab" in the preferences
- We added integration of the Library of Congress catalog as a fetcher based on the [LCCN identifier](https://en.wikipedia.org/wiki/Library_of_Congress_Control_Number). [Feature request 636 in the forum](http://discourse.jabref.org/t/loc-marc-mods-connection/636)
Expand Down
79 changes: 34 additions & 45 deletions src/main/java/org/jabref/gui/BasePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
import org.jabref.gui.actions.BaseAction;
import org.jabref.gui.actions.CleanupAction;
import org.jabref.gui.actions.CopyBibTeXKeyAndLinkAction;
import org.jabref.gui.autocompleter.AutoCompletePreferences;
import org.jabref.gui.autocompleter.AutoCompleteUpdater;
import org.jabref.gui.autocompleter.PersonNameSuggestionProvider;
import org.jabref.gui.autocompleter.SuggestionProviders;
import org.jabref.gui.bibtexkeypattern.SearchFixDuplicateLabels;
import org.jabref.gui.contentselector.ContentSelectorDialog;
import org.jabref.gui.desktop.JabRefDesktop;
Expand Down Expand Up @@ -96,10 +100,6 @@
import org.jabref.gui.worker.CitationStyleToClipboardWorker;
import org.jabref.gui.worker.MarkEntriesAction;
import org.jabref.gui.worker.SendAsEMailAction;
import org.jabref.logic.autocompleter.AutoCompletePreferences;
import org.jabref.logic.autocompleter.AutoCompleter;
import org.jabref.logic.autocompleter.AutoCompleterFactory;
import org.jabref.logic.autocompleter.ContentAutoCompleters;
import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil;
import org.jabref.logic.citationstyle.CitationStyleCache;
import org.jabref.logic.citationstyle.CitationStyleOutputFormat;
Expand Down Expand Up @@ -131,6 +131,7 @@
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.EntryType;
import org.jabref.model.entry.FieldName;
import org.jabref.model.entry.InternalBibtexFields;
import org.jabref.model.entry.event.EntryChangedEvent;
import org.jabref.model.entry.event.EntryEventSource;
import org.jabref.model.entry.specialfields.SpecialField;
Expand Down Expand Up @@ -179,7 +180,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
private boolean saving;
private boolean updatedExternally;
// AutoCompleter used in the search bar
private AutoCompleter<String> searchAutoCompleter;
private PersonNameSuggestionProvider searchAutoCompleter;
private boolean baseChanged;
private boolean nonUndoableChange;
// Used to track whether the base has changed since last save.
Expand All @@ -193,7 +194,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
private PreambleEditor preambleEditor;
// Keeps track of the preamble dialog if it is open.
private StringDialog stringDialog;
private ContentAutoCompleters autoCompleters;
private SuggestionProviders suggestionProviders;

/** the query the user searches when this basepanel is active */
private Optional<SearchQuery> currentSearchQuery = Optional.empty();
Expand Down Expand Up @@ -258,9 +259,11 @@ public static void runWorker(AbstractWorker worker) throws Exception {
clb.update(); // Runs the update() method on the EDT.
}

// Returns a collection of AutoCompleters, which are populated from the current library
public ContentAutoCompleters getAutoCompleters() {
return autoCompleters;
/**
* Returns a collection of suggestion providers, which are populated from the current library.
*/
public SuggestionProviders getSuggestionProviders() {
return suggestionProviders;
}

public String getTabTitle() {
Expand Down Expand Up @@ -1364,17 +1367,7 @@ public void setupMainPanel() {
instantiateSearchAutoCompleter();
this.getDatabase().registerListener(new SearchAutoCompleteListener());

AutoCompletePreferences autoCompletePreferences = new AutoCompletePreferences(Globals.prefs);
// Set up AutoCompleters for this panel:
if (Globals.prefs.getBoolean(JabRefPreferences.AUTO_COMPLETE)) {
autoCompleters = new ContentAutoCompleters(getDatabase(), bibDatabaseContext.getMetaData(),
autoCompletePreferences, Globals.journalAbbreviationLoader);
// ensure that the autocompleters are in sync with entries
this.getDatabase().registerListener(new AutoCompleteListener());
} else {
// create empty ContentAutoCompleters() if autoCompletion is deactivated
autoCompleters = new ContentAutoCompleters();
}
setupAutoCompletion();

// restore floating search result
// (needed if preferences have been changed which causes a recreation of the main table)
Expand All @@ -1390,17 +1383,30 @@ public void setupMainPanel() {
splitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, event -> saveDividerLocation());
}

/**
* Set up auto completion for this database
*/
private void setupAutoCompletion() {
AutoCompletePreferences autoCompletePreferences = Globals.prefs.getAutoCompletePreferences();
if (autoCompletePreferences.shouldAutoComplete()) {
suggestionProviders = new SuggestionProviders(autoCompletePreferences, Globals.journalAbbreviationLoader);
suggestionProviders.indexDatabase(getDatabase());
// Ensure that the suggestion providers are in sync with entries
this.getDatabase().registerListener(new AutoCompleteUpdater(suggestionProviders));
} else {
// Create empty suggestion providers if auto completion is deactivated
suggestionProviders = new SuggestionProviders();
}
}

public void updateSearchManager() {
frame.getGlobalSearchBar().setAutoCompleter(searchAutoCompleter);
}

private void instantiateSearchAutoCompleter() {
AutoCompletePreferences autoCompletePreferences = new AutoCompletePreferences(Globals.prefs);
AutoCompleterFactory autoCompleterFactory = new AutoCompleterFactory(autoCompletePreferences,
Globals.journalAbbreviationLoader);
searchAutoCompleter = autoCompleterFactory.getPersonAutoCompleter();
searchAutoCompleter = new PersonNameSuggestionProvider(InternalBibtexFields.getPersonNameFields());
for (BibEntry entry : bibDatabaseContext.getDatabase().getEntries()) {
searchAutoCompleter.addBibtexEntry(entry);
searchAutoCompleter.indexEntry(entry);
}
}

Expand Down Expand Up @@ -2107,29 +2113,12 @@ private class SearchAutoCompleteListener {

@Subscribe
public void listen(EntryAddedEvent addedEntryEvent) {
searchAutoCompleter.addBibtexEntry(addedEntryEvent.getBibEntry());
}

@Subscribe
public void listen(EntryChangedEvent entryChangedEvent) {
searchAutoCompleter.addBibtexEntry(entryChangedEvent.getBibEntry());
}
}

/**
* Ensures that auto completers are up to date when entries are changed AKA Let the auto completer, if any, harvest
* words from the entry
*/
private class AutoCompleteListener {

@Subscribe
public void listen(EntryAddedEvent addedEntryEvent) {
BasePanel.this.autoCompleters.addEntry(addedEntryEvent.getBibEntry());
searchAutoCompleter.indexEntry(addedEntryEvent.getBibEntry());
}

@Subscribe
public void listen(EntryChangedEvent entryChangedEvent) {
BasePanel.this.autoCompleters.addEntry(entryChangedEvent.getBibEntry());
searchAutoCompleter.indexEntry(entryChangedEvent.getBibEntry());
}
}

Expand All @@ -2145,7 +2134,7 @@ public void listen(EntryAddedEvent addedEntryEvent) {

@Subscribe
public void listen(EntryChangedEvent entryChangedEvent) {
frame.getGlobalSearchBar().setDontSelectSearchBar(true);
frame.getGlobalSearchBar().setDontSelectSearchBar();
frame.getGlobalSearchBar().performSearch();
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ public void windowClosing(WindowEvent e) {
if (currentSearchQuery.isPresent()) {
content = currentSearchQuery.get().getQuery();
}
globalSearchBar.setSearchTerm(content, true);
globalSearchBar.setSearchTerm(content);
}

currentBasePanel.getPreviewPanel().updateLayout();
Expand Down
37 changes: 1 addition & 36 deletions src/main/java/org/jabref/gui/actions/ManageKeywordsAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,15 @@
import javax.swing.JTextField;

import org.jabref.Globals;
import org.jabref.JabRefGUI;
import org.jabref.gui.BasePanel;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.autocompleter.AutoCompleteListener;
import org.jabref.gui.keyboard.KeyBinding;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableFieldChange;
import org.jabref.logic.autocompleter.AutoCompleter;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.specialfields.SpecialFieldsUtils;
import org.jabref.model.FieldChange;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.FieldName;
import org.jabref.model.entry.Keyword;
import org.jabref.model.entry.KeywordList;
import org.jabref.model.strings.StringUtil;
Expand All @@ -53,19 +49,13 @@
public class ManageKeywordsAction extends MnemonicAwareAction {

private final JabRefFrame frame;

private final KeywordList sortedKeywordsOfAllEntriesBeforeUpdateByUser = new KeywordList();
private JDialog diag;


private DefaultListModel<Keyword> keywordListModel;

private JRadioButton intersectKeywords;
private JRadioButton mergeKeywords;

private boolean canceled;

private final KeywordList sortedKeywordsOfAllEntriesBeforeUpdateByUser = new KeywordList();


public ManageKeywordsAction(JabRefFrame frame) {
putValue(Action.NAME, Localization.menuTitle("Manage keywords"));
Expand Down Expand Up @@ -171,31 +161,6 @@ public void keyPressed(KeyEvent arg0) {
}
});

AutoCompleter<String> autoComp = JabRefGUI.getMainFrame().getCurrentBasePanel().getAutoCompleters()
.get(FieldName.KEYWORDS);
AutoCompleteListener acl = new AutoCompleteListener(autoComp);
keyword.addKeyListener(acl);
keyword.addFocusListener(acl);
keyword.addKeyListener(new KeyListener() {

@Override
public void keyTyped(KeyEvent e) {
// Do nothing
}

@Override
public void keyReleased(KeyEvent e) {
// Do nothing
}

@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
addActionListener.actionPerformed(null);
}
}
});

// Key bindings:
ActionMap am = builder.getPanel().getActionMap();
InputMap im = builder.getPanel().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.jabref.gui.autocompleter;

import java.util.Locale;

public class AppendPersonNamesStrategy implements AutoCompletionStrategy {

/**
* true if the input should be split at a single white space instead of the usual delimiter " and " for names.
* Useful if the input consists of a list of last names.
*/
private final boolean separationBySpace;

public AppendPersonNamesStrategy() {
this(false);
}

public AppendPersonNamesStrategy(boolean separationBySpace) {
this.separationBySpace = separationBySpace;
}

@Override
public AutoCompletionInput analyze(String input) {
if (this.separationBySpace) {
return determinePrefixAndReturnRemainder(input, " ");
} else {
return determinePrefixAndReturnRemainder(input, " and ");
}
}

private AutoCompletionInput determinePrefixAndReturnRemainder(String input, String delimiter) {
int index = input.toLowerCase(Locale.ROOT).lastIndexOf(delimiter);
if (index >= 0) {
String prefix = input.substring(0, index + delimiter.length());
String rest = input.substring(index + delimiter.length());
return new AutoCompletionInput(prefix, rest);
} else {
return new AutoCompletionInput("", input);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.jabref.gui.autocompleter;

/**
* For "ONLY_FULL", the auto completer returns the full name, e.g. "Smith, Bob"
* For "ONLY_ABBREVIATED", the auto completer returns the first name abbreviated, e.g. "Smith, B."
* For "BOTH", the auto completer returns both versions.
*/
public enum AutoCompleteFirstNameMode {
ONLY_FULL,
ONLY_ABBREVIATED,
BOTH;

public static AutoCompleteFirstNameMode parse(String input) {
try {
return AutoCompleteFirstNameMode.valueOf(input);
} catch (IllegalArgumentException ex) {
// Should only occur when preferences are set directly via preferences.put and not via setFirstnameMode
return AutoCompleteFirstNameMode.BOTH;
}
}
}
Loading