package org.jabref.gui.importer.fetcher;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import org.jabref.Globals;
import org.jabref.JabRefExecutorService;
import org.jabref.gui.IconTheme;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.SidePaneComponent;
import org.jabref.gui.SidePaneManager;
import org.jabref.gui.help.HelpAction;
import org.jabref.gui.importer.FetcherPreviewDialog;
import org.jabref.gui.importer.ImportInspectionDialog;
import org.jabref.gui.keyboard.KeyBinding;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.OS;
import org.jabref.preferences.JabRefPreferences;
public class GeneralFetcher extends SidePaneComponent implements ActionListener {
private final JTextField tf = new JTextField();
private final CardLayout optionsCards = new CardLayout();
private final JPanel optionsPanel = new JPanel(optionsCards);
private final JPanel optPanel = new JPanel(new BorderLayout());
private final ToggleAction action;
private final JabRefFrame frame;
private EntryFetcher activeFetcher;
public GeneralFetcher(JabRefFrame frame, SidePaneManager sidePaneManager) {
super(sidePaneManager, IconTheme.JabRefIcon.WWW.getSmallIcon(), Localization.lang("Web search"));
this.frame = frame;
List<EntryFetcher> fetchers = new EntryFetchers(Globals.journalAbbreviationLoader).getEntryFetchers();
EntryFetcher[] fetcherArray = fetchers.toArray(new EntryFetcher[fetchers.size()]);
Arrays.sort(fetcherArray, new EntryFetcherComparator());
//JLabel[] choices = new JLabel[fetchers.size()];
String[] choices = new String[fetcherArray.length];
for (int i = 0; i < fetcherArray.length; i++) {
choices[i] = fetcherArray[i].getTitle();
}
JComboBox<String> fetcherChoice = new JComboBox<>(choices);
int defaultFetcher = Globals.prefs.getInt(JabRefPreferences.SELECTED_FETCHER_INDEX);
if (defaultFetcher >= fetcherArray.length) {
defaultFetcher = 0;
}
this.activeFetcher = fetcherArray[defaultFetcher];
fetcherChoice.setSelectedIndex(defaultFetcher);
if (this.activeFetcher.getOptionsPanel() != null) {
optPanel.add(this.activeFetcher.getOptionsPanel(), BorderLayout.CENTER);
}
HelpAction help = new HelpAction(activeFetcher.getHelpPage());
JButton helpBut = help.getHelpButton();
helpBut.setEnabled(activeFetcher.getHelpPage() != null);
fetcherChoice.addActionListener(actionEvent -> {
activeFetcher = fetcherArray[fetcherChoice.getSelectedIndex()];
Globals.prefs.putInt(JabRefPreferences.SELECTED_FETCHER_INDEX, fetcherChoice.getSelectedIndex());
if (activeFetcher.getHelpPage() == null) {
helpBut.setEnabled(false);
} else {
help.setHelpFile(activeFetcher.getHelpPage());
helpBut.setEnabled(true);
}
optionsCards.show(optionsPanel, String.valueOf(fetcherChoice.getSelectedIndex()));
optPanel.removeAll();
if (activeFetcher.getOptionsPanel() != null) {
optPanel.add(activeFetcher.getOptionsPanel(), BorderLayout.CENTER);
}
revalidate();
});
action = new ToggleAction(Localization.lang("Web search"),
Localization.lang("Toggle web search interface"),
Globals.getKeyPrefs().getKey(KeyBinding.WEB_SEARCH),
IconTheme.JabRefIcon.WWW);
helpBut.setMargin(new Insets(0, 0, 0, 0));
tf.setPreferredSize(new Dimension(1, tf.getPreferredSize().height));
if (OS.OS_X) {
tf.putClientProperty("JTextField.variant", "search");
}
tf.setName("tf");
// add action to reset-button. resets tf and requests focus
JButton reset = new JButton(Localization.lang("Reset"));
reset.addActionListener(event -> {
tf.setText("");
tf.requestFocus();
});
JPanel main = new JPanel();
GridBagLayout gbl = new GridBagLayout();
main.setLayout(gbl);
GridBagConstraints con = new GridBagConstraints();
con.fill = GridBagConstraints.BOTH;
con.insets = new Insets(0, 0, 2, 0);
con.gridwidth = GridBagConstraints.REMAINDER;
con.weightx = 1;
con.weighty = 1;
con.insets = new Insets(1, 0, 1, 0);
con.fill = GridBagConstraints.BOTH;
gbl.setConstraints(fetcherChoice, con);
main.add(fetcherChoice);
con.insets = new Insets(0, 0, 0, 0);
gbl.setConstraints(tf, con);
main.add(tf);
// Go Button
con.weighty = 0;
con.gridwidth = 1;
JButton go = new JButton(Localization.lang("Fetch"));
gbl.setConstraints(go, con);
main.add(go);
// Reset Button
reset.setName("reset");
gbl.setConstraints(reset, con);
main.add(reset);
// Help Button
con.gridwidth = GridBagConstraints.REMAINDER;
gbl.setConstraints(helpBut, con);
main.add(helpBut);
gbl.setConstraints(optPanel, con);
main.add(optPanel);
main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
add(main, BorderLayout.CENTER);
go.addActionListener(this);
tf.addActionListener(this);
}
private JTextField getTextField() {
return tf;
}
@Override
public ToggleAction getToggleAction() {
return action;
}
@Override
public void actionPerformed(ActionEvent e) {
if (tf.getText().trim().isEmpty()) {
frame.output(Localization.lang("Please enter a search string"));
return;
}
if (frame.getCurrentBasePanel() == null) {
frame.output(Localization.lang("Please open or start a new library before searching"));
return;
}
// We have two categories of fetchers. One category can show previews first and ask the
// user which ones to download:
if (activeFetcher instanceof PreviewEntryFetcher) {
frame.output(Localization.lang("Searching..."));
frame.setProgressBarIndeterminate(true);
frame.setProgressBarVisible(true);
final PreviewEntryFetcher pFetcher = (PreviewEntryFetcher) activeFetcher;
final FetcherPreviewDialog dialog = new FetcherPreviewDialog(frame,
pFetcher.getWarningLimit(), pFetcher.getPreferredPreviewHeight());
JabRefExecutorService.INSTANCE.execute(() -> {
final boolean result = pFetcher.processQueryGetPreview(tf.getText().trim(), dialog, dialog);
SwingUtilities.invokeLater(() -> {
frame.setProgressBarVisible(false);
frame.output("");
if (result) {
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
if (dialog.isOkPressed()) {
final ImportInspectionDialog d2 = new ImportInspectionDialog(frame,
frame.getCurrentBasePanel(), activeFetcher.getTitle(), false);
d2.addCallBack(activeFetcher);
d2.setLocationRelativeTo(frame);
d2.setVisible(true);
JabRefExecutorService.INSTANCE.execute(() -> {
pFetcher.getEntries(dialog.getSelection(), d2);
d2.entryListComplete();
});
}
}
});
});
}
// The other category downloads the entries first, then asks the user which ones to keep:
else {
final ImportInspectionDialog dialog = new ImportInspectionDialog(frame, frame.getCurrentBasePanel(),
activeFetcher.getTitle(), false);
dialog.addCallBack(activeFetcher);
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
JabRefExecutorService.INSTANCE.execute(() -> {
if (activeFetcher.processQuery(tf.getText().trim(), dialog, dialog)) {
dialog.entryListComplete();
} else {
dialog.dispose();
}
});
}
}
@Override
public void grabFocus() {
getTextField().grabFocus();
}
@Override
public void componentClosing() {
super.componentClosing();
getToggleAction().setSelected(false);
Globals.prefs.putBoolean(JabRefPreferences.WEB_SEARCH_VISIBLE, Boolean.FALSE);
}
@Override
public void componentOpening() {
super.componentOpening();
Globals.prefs.putBoolean(JabRefPreferences.WEB_SEARCH_VISIBLE, Boolean.TRUE);
}
@Override
public int getRescalingWeight() {
return 0;
}
private static class EntryFetcherComparator implements Comparator<EntryFetcher> {
@Override
public int compare(EntryFetcher entryFetcher, EntryFetcher entryFetcher1) {
return entryFetcher.getTitle().compareTo(entryFetcher1.getTitle());
}
}
}