package org.jabref.gui.preftabs; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ItemListener; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; import org.jabref.gui.DialogService; import org.jabref.gui.FXDialogService; import org.jabref.gui.JabRefFrame; import org.jabref.gui.help.HelpAction; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; import org.jabref.model.entry.FieldName; import org.jabref.model.metadata.FileDirectoryPreferences; import org.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; /** * Preferences tab for file options. These options were moved out from GeneralTab to * resolve the space issue. */ class FileTab extends JPanel implements PrefsTab { private final JabRefPreferences prefs; private final JabRefFrame frame; private final JCheckBox backup; private final JCheckBox localAutoSave; private final JCheckBox openLast; private final JComboBox<String> newlineSeparator; private final JCheckBox reformatFileOnSaveAndExport; private final JRadioButton resolveStringsStandard; private final JRadioButton resolveStringsAll; private final JTextField nonWrappableFields; private final JTextField doNotResolveStringsFor; private final JTextField fileDir; private final JCheckBox bibLocAsPrimaryDir; private final JCheckBox runAutoFileSearch; private final JCheckBox allowFileAutoOpenBrowse; private final JRadioButton useRegExpComboBox; private final JRadioButton matchExactKeyOnly = new JRadioButton( Localization.lang("Autolink only files that match the BibTeX key")); private final JRadioButton matchStartsWithKey = new JRadioButton( Localization.lang("Autolink files with names starting with the BibTeX key")); private final JTextField regExpTextField; public FileTab(JabRefFrame frame, JabRefPreferences prefs) { this.prefs = prefs; this.frame = frame; fileDir = new JTextField(25); bibLocAsPrimaryDir = new JCheckBox(Localization.lang("Use the BIB file location as primary file directory")); bibLocAsPrimaryDir.setToolTipText(Localization.lang("When downloading files, or moving linked files to the " + "file directory, prefer the BIB file location rather than the file directory set above")); runAutoFileSearch = new JCheckBox( Localization.lang("When opening file link, search for matching file if no link is defined")); allowFileAutoOpenBrowse = new JCheckBox( Localization.lang("Automatically open browse dialog when creating new file link")); regExpTextField = new JTextField(25); useRegExpComboBox = new JRadioButton(Localization.lang("Use regular expression search")); ItemListener regExpListener = e -> regExpTextField.setEditable(useRegExpComboBox.isSelected()); useRegExpComboBox.addItemListener(regExpListener); ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(matchExactKeyOnly); buttonGroup.add(matchStartsWithKey); buttonGroup.add(useRegExpComboBox); openLast = new JCheckBox(Localization.lang("Open last edited libraries at startup")); backup = new JCheckBox(Localization.lang("Backup old file when saving")); localAutoSave = new JCheckBox(Localization.lang("Autosave local libraries")); resolveStringsAll = new JRadioButton(Localization.lang("Resolve strings for all fields except") + ":"); resolveStringsStandard = new JRadioButton(Localization.lang("Resolve strings for standard BibTeX fields only")); ButtonGroup bg = new ButtonGroup(); bg.add(resolveStringsAll); bg.add(resolveStringsStandard); // This is sort of a quick hack newlineSeparator = new JComboBox<>(new String[] {"CR", "CR/LF", "LF"}); reformatFileOnSaveAndExport = new JCheckBox(Localization.lang("Always reformat BIB file on save and export")); nonWrappableFields = new JTextField(25); doNotResolveStringsFor = new JTextField(30); FormLayout layout = new FormLayout("left:pref, 4dlu, fill:150dlu, 4dlu, fill:pref", ""); // left:pref, 4dlu, fill:pref DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.appendSeparator(Localization.lang("General")); builder.nextLine(); builder.append(openLast, 3); builder.nextLine(); builder.append(backup, 3); builder.nextLine(); JLabel label = new JLabel(Localization.lang("Do not wrap the following fields when saving") + ":"); builder.append(label); builder.append(nonWrappableFields); builder.nextLine(); builder.append(resolveStringsStandard, 3); builder.nextLine(); builder.append(resolveStringsAll); builder.append(doNotResolveStringsFor); builder.nextLine(); JLabel lab = new JLabel(Localization.lang("Newline separator") + ":"); builder.append(lab); builder.append(newlineSeparator); builder.nextLine(); builder.append(reformatFileOnSaveAndExport, 3); builder.nextLine(); builder.appendSeparator(Localization.lang("External file links")); builder.nextLine(); lab = new JLabel(Localization.lang("Main file directory") + ':'); builder.append(lab); builder.append(fileDir); JButton browse = new JButton(Localization.lang("Browse")); browse.addActionListener(e -> { DialogService ds = new FXDialogService(); DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder() .withInitialDirectory(Paths.get(fileDir.getText())).build(); DefaultTaskExecutor.runInJavaFXThread(() -> ds.showDirectorySelectionDialog(dirDialogConfiguration)) .ifPresent(f -> fileDir.setText(f.toString())); }); builder.append(browse); builder.nextLine(); builder.append(bibLocAsPrimaryDir, 3); builder.nextLine(); builder.append(matchStartsWithKey, 3); builder.nextLine(); builder.append(matchExactKeyOnly, 3); builder.nextLine(); builder.append(useRegExpComboBox); builder.append(regExpTextField); builder.append(new HelpAction(Localization.lang("Help on regular expression search"), HelpFile.REGEX_SEARCH) .getHelpButton()); builder.nextLine(); builder.append(runAutoFileSearch, 3); builder.nextLine(); builder.append(allowFileAutoOpenBrowse); builder.nextLine(); builder.appendSeparator(Localization.lang("Autosave")); builder.append(localAutoSave, 1); JButton help = new HelpAction(HelpFile.AUTOSAVE).getHelpButton(); help.setPreferredSize(new Dimension(24, 24)); JPanel hPan = new JPanel(); hPan.setLayout(new BorderLayout()); hPan.add(help, BorderLayout.EAST); builder.append(hPan); builder.nextLine(); JPanel pan = builder.getPanel(); pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); setLayout(new BorderLayout()); add(pan, BorderLayout.CENTER); } @Override public void setValues() { fileDir.setText(prefs.get(FieldName.FILE + FileDirectoryPreferences.DIR_SUFFIX)); bibLocAsPrimaryDir.setSelected(prefs.getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR)); runAutoFileSearch.setSelected(prefs.getBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH)); allowFileAutoOpenBrowse.setSelected(prefs.getBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE)); regExpTextField.setText(prefs.get(JabRefPreferences.AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY)); if (prefs.getBoolean(JabRefPreferences.AUTOLINK_USE_REG_EXP_SEARCH_KEY)) { useRegExpComboBox.setSelected(true); } else if (prefs.getBoolean(JabRefPreferences.AUTOLINK_EXACT_KEY_ONLY)) { matchExactKeyOnly.setSelected(true); } else { matchStartsWithKey.setSelected(true); } openLast.setSelected(prefs.getBoolean(JabRefPreferences.OPEN_LAST_EDITED)); backup.setSelected(prefs.getBoolean(JabRefPreferences.BACKUP)); String newline = prefs.get(JabRefPreferences.NEWLINE); if ("\r".equals(newline)) { newlineSeparator.setSelectedIndex(0); } else if ("\n".equals(newline)) { newlineSeparator.setSelectedIndex(2); } else { // fallback: windows standard newlineSeparator.setSelectedIndex(1); } reformatFileOnSaveAndExport.setSelected(prefs.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT)); resolveStringsAll.setSelected(prefs.getBoolean(JabRefPreferences.RESOLVE_STRINGS_ALL_FIELDS)); resolveStringsStandard.setSelected(!resolveStringsAll.isSelected()); doNotResolveStringsFor.setText(prefs.get(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR)); nonWrappableFields.setText(prefs.get(JabRefPreferences.NON_WRAPPABLE_FIELDS)); localAutoSave.setSelected(prefs.getBoolean(JabRefPreferences.LOCAL_AUTO_SAVE)); } @Override public void storeSettings() { prefs.put(FieldName.FILE + FileDirectoryPreferences.DIR_SUFFIX, fileDir.getText()); prefs.putBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR, bibLocAsPrimaryDir.isSelected()); prefs.putBoolean(JabRefPreferences.RUN_AUTOMATIC_FILE_SEARCH, runAutoFileSearch.isSelected()); prefs.putBoolean(JabRefPreferences.ALLOW_FILE_AUTO_OPEN_BROWSE, allowFileAutoOpenBrowse.isSelected()); prefs.putBoolean(JabRefPreferences.AUTOLINK_USE_REG_EXP_SEARCH_KEY, useRegExpComboBox.isSelected()); prefs.putBoolean(JabRefPreferences.AUTOLINK_EXACT_KEY_ONLY, matchExactKeyOnly.isSelected()); if (useRegExpComboBox.isSelected()) { prefs.put(JabRefPreferences.AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY, regExpTextField.getText()); } String newline; switch (newlineSeparator.getSelectedIndex()) { case 0: newline = "\r"; break; case 2: newline = "\n"; break; default: newline = "\r\n"; break; } prefs.put(JabRefPreferences.NEWLINE, newline); // we also have to change Globals variable as globals is not a getter, but a constant OS.NEWLINE = newline; prefs.putBoolean(JabRefPreferences.BACKUP, backup.isSelected()); prefs.putBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT, reformatFileOnSaveAndExport.isSelected()); prefs.putBoolean(JabRefPreferences.OPEN_LAST_EDITED, openLast.isSelected()); prefs.putBoolean(JabRefPreferences.RESOLVE_STRINGS_ALL_FIELDS, resolveStringsAll.isSelected()); prefs.put(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR, doNotResolveStringsFor.getText().trim()); doNotResolveStringsFor.setText(prefs.get(JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR)); if (!nonWrappableFields.getText().trim().equals(prefs.get(JabRefPreferences.NON_WRAPPABLE_FIELDS))) { prefs.put(JabRefPreferences.NON_WRAPPABLE_FIELDS, nonWrappableFields.getText()); } prefs.putBoolean(JabRefPreferences.LOCAL_AUTO_SAVE, localAutoSave.isSelected()); } @Override public boolean validateSettings() { Path path = Paths.get(fileDir.getText()); boolean valid = Files.exists(path) && Files.isDirectory(path); if (!valid) { String content = String.format("%s -> %s %n %n %s: %n %s", Localization.lang("File"), Localization.lang("Main file directory"), Localization.lang("Directory not found"), path); JOptionPane.showMessageDialog(this.frame, content, Localization.lang("Error"), JOptionPane.ERROR_MESSAGE); } return valid; } @Override public String getTabName() { return Localization.lang("File"); } }