package org.jabref.gui.preftabs; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToolBar; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import org.jabref.gui.BasePanel; import org.jabref.gui.IconTheme; import org.jabref.gui.JabRefFrame; import org.jabref.gui.OSXCompatibleToolbar; import org.jabref.gui.externalfiletype.ExternalFileType; import org.jabref.gui.externalfiletype.ExternalFileTypes; import org.jabref.gui.help.HelpAction; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibtexSingleField; import org.jabref.model.entry.FieldName; import org.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; class TableColumnsTab extends JPanel implements PrefsTab { private static final Log LOGGER = LogFactory.getLog(TableColumnsTab.class); private final JabRefPreferences prefs; private boolean tableChanged; private final JTable colSetup; private int rowCount = -1; private int ncWidth = -1; private final List<TableRow> tableRows = new ArrayList<>(10); private final JabRefFrame frame; private final JCheckBox urlColumn; private final JCheckBox fileColumn; private final JCheckBox arxivColumn; private final JCheckBox extraFileColumns; private final JList<String> listOfFileColumns; private final JRadioButton preferUrl; private final JRadioButton preferDoi; /*** begin: special fields ***/ private final JCheckBox specialFieldsEnabled; private final JCheckBox rankingColumn; private final JCheckBox qualityColumn; private final JCheckBox priorityColumn; private final JCheckBox relevanceColumn; private final JCheckBox printedColumn; private final JCheckBox readStatusColumn; private final JRadioButton syncKeywords; private final JRadioButton writeSpecialFields; private boolean oldSpecialFieldsEnabled; private boolean oldRankingColumn; private boolean oldQualityColumn; private boolean oldPriorityColumn; private boolean oldRelevanceColumn; private boolean oldPrintedColumn; private boolean oldReadStatusColumn; private boolean oldSyncKeyWords; private boolean oldWriteSpecialFields; /*** end: special fields ***/ static class TableRow { private String name; private int length; public TableRow() { name = ""; length = BibtexSingleField.DEFAULT_FIELD_LENGTH; } public TableRow(String name) { this.name = name; length = BibtexSingleField.DEFAULT_FIELD_LENGTH; } public TableRow(String name, int length) { this.name = name; this.length = length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } } /** * Customization of external program paths. * * @param prefs a <code>JabRefPreferences</code> value */ public TableColumnsTab(JabRefPreferences prefs, JabRefFrame frame) { this.prefs = prefs; this.frame = frame; setLayout(new BorderLayout()); TableModel tm = new AbstractTableModel() { @Override public int getRowCount() { return rowCount; } @Override public int getColumnCount() { return 2; } @Override public Object getValueAt(int row, int column) { int internalRow = row; if (internalRow == 0) { return column == 0 ? FieldName.NUMBER_COL : String.valueOf(ncWidth); } internalRow--; if (internalRow >= tableRows.size()) { return ""; } TableRow rowContent = tableRows.get(internalRow); if (rowContent == null) { return ""; } // Only two columns if (column == 0) { return rowContent.getName(); } else { return rowContent.getLength() > 0 ? Integer.toString(rowContent.getLength()) : ""; } } @Override public String getColumnName(int col) { return col == 0 ? Localization.lang("Field name") : Localization.lang("Column width"); } @Override public Class<?> getColumnClass(int column) { if (column == 0) { return String.class; } return Integer.class; } @Override public boolean isCellEditable(int row, int col) { return !((row == 0) && (col == 0)); } @Override public void setValueAt(Object value, int row, int col) { tableChanged = true; // Make sure the vector is long enough. while (row >= tableRows.size()) { tableRows.add(new TableRow("", -1)); } if ((row == 0) && (col == 1)) { ncWidth = Integer.parseInt(value.toString()); return; } TableRow rowContent = tableRows.get(row - 1); if (col == 0) { rowContent.setName(value.toString()); if ("".equals(getValueAt(row, 1))) { setValueAt(String.valueOf(BibtexSingleField.DEFAULT_FIELD_LENGTH), row, 1); } } else { if (value == null) { rowContent.setLength(-1); } else { rowContent.setLength(Integer.parseInt(value.toString())); } } } }; colSetup = new JTable(tm); TableColumnModel cm = colSetup.getColumnModel(); cm.getColumn(0).setPreferredWidth(140); cm.getColumn(1).setPreferredWidth(80); FormLayout layout = new FormLayout ("1dlu, 8dlu, left:pref, 4dlu, fill:pref",""); DefaultFormBuilder builder = new DefaultFormBuilder(layout); JPanel pan = new JPanel(); JPanel tabPanel = new JPanel(); tabPanel.setLayout(new BorderLayout()); JScrollPane sp = new JScrollPane (colSetup, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); colSetup.setPreferredScrollableViewportSize(new Dimension(250, 200)); sp.setMinimumSize(new Dimension(250, 300)); tabPanel.add(sp, BorderLayout.CENTER); JToolBar toolBar = new OSXCompatibleToolbar(SwingConstants.VERTICAL); toolBar.setFloatable(false); AddRowAction addRow = new AddRowAction(); DeleteRowAction deleteRow = new DeleteRowAction(); MoveRowUpAction moveUp = new MoveRowUpAction(); MoveRowDownAction moveDown = new MoveRowDownAction(); toolBar.setBorder(null); toolBar.add(addRow); toolBar.add(deleteRow); toolBar.addSeparator(); toolBar.add(moveUp); toolBar.add(moveDown); tabPanel.add(toolBar, BorderLayout.EAST); fileColumn = new JCheckBox(Localization.lang("Show file column")); urlColumn = new JCheckBox(Localization.lang("Show URL/DOI column")); preferUrl = new JRadioButton(Localization.lang("Show URL first")); preferDoi = new JRadioButton(Localization.lang("Show DOI first")); ButtonGroup preferUrlDoiGroup = new ButtonGroup(); preferUrlDoiGroup.add(preferUrl); preferUrlDoiGroup.add(preferDoi); urlColumn.addChangeListener(arg0 -> { preferUrl.setEnabled(urlColumn.isSelected()); preferDoi.setEnabled(urlColumn.isSelected()); }); arxivColumn = new JCheckBox(Localization.lang("Show ArXiv column")); Collection<ExternalFileType> fileTypes = ExternalFileTypes.getInstance().getExternalFileTypeSelection(); String[] fileTypeNames = new String[fileTypes.size()]; int i = 0; for (ExternalFileType fileType : fileTypes) { fileTypeNames[i++] = fileType.getName(); } listOfFileColumns = new JList<>(fileTypeNames); JScrollPane listOfFileColumnsScrollPane = new JScrollPane(listOfFileColumns); listOfFileColumns.setVisibleRowCount(3); extraFileColumns = new JCheckBox(Localization.lang("Show extra columns")); extraFileColumns.addChangeListener(arg0 -> listOfFileColumns.setEnabled(extraFileColumns.isSelected())); /*** begin: special table columns and special fields ***/ JButton helpButton = new HelpAction(Localization.lang("Help on special fields"), HelpFile.SPECIAL_FIELDS).getHelpButton(); rankingColumn = new JCheckBox(Localization.lang("Show rank")); qualityColumn = new JCheckBox(Localization.lang("Show quality")); priorityColumn = new JCheckBox(Localization.lang("Show priority")); relevanceColumn = new JCheckBox(Localization.lang("Show relevance")); printedColumn = new JCheckBox(Localization.lang("Show printed status")); readStatusColumn = new JCheckBox(Localization.lang("Show read status")); // "sync keywords" and "write special" fields may be configured mutually exclusive only // The implementation supports all combinations (TRUE+TRUE and FALSE+FALSE, even if the latter does not make sense) // To avoid confusion, we opted to make the setting mutually exclusive syncKeywords = new JRadioButton(Localization.lang("Synchronize with keywords")); writeSpecialFields = new JRadioButton(Localization.lang("Write values of special fields as separate fields to BibTeX")); ButtonGroup group = new ButtonGroup(); group.add(syncKeywords); group.add(writeSpecialFields); specialFieldsEnabled = new JCheckBox(Localization.lang("Enable special fields")); specialFieldsEnabled.addChangeListener(event -> { boolean isEnabled = specialFieldsEnabled.isSelected(); rankingColumn.setEnabled(isEnabled); qualityColumn.setEnabled(isEnabled); priorityColumn.setEnabled(isEnabled); relevanceColumn.setEnabled(isEnabled); printedColumn.setEnabled(isEnabled); readStatusColumn.setEnabled(isEnabled); syncKeywords.setEnabled(isEnabled); writeSpecialFields.setEnabled(isEnabled); }); builder.appendSeparator(Localization.lang("Special table columns")); builder.nextLine(); builder.append(pan); DefaultFormBuilder specialTableColumnsBuilder = new DefaultFormBuilder(new FormLayout( "8dlu, 8dlu, 8cm, 8dlu, 8dlu, left:pref:grow", "pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref")); CellConstraints cc = new CellConstraints(); specialTableColumnsBuilder.add(specialFieldsEnabled, cc.xyw(1, 1, 3)); specialTableColumnsBuilder.add(rankingColumn, cc.xyw(2, 2, 2)); specialTableColumnsBuilder.add(relevanceColumn, cc.xyw(2, 3, 2)); specialTableColumnsBuilder.add(qualityColumn, cc.xyw(2, 4, 2)); specialTableColumnsBuilder.add(priorityColumn, cc.xyw(2, 5, 2)); specialTableColumnsBuilder.add(printedColumn, cc.xyw(2, 6, 2)); specialTableColumnsBuilder.add(readStatusColumn, cc.xyw(2, 7, 2)); specialTableColumnsBuilder.add(syncKeywords, cc.xyw(2, 10, 2)); specialTableColumnsBuilder.add(writeSpecialFields, cc.xyw(2, 11, 2)); specialTableColumnsBuilder.add(helpButton, cc.xyw(1, 12, 2)); specialTableColumnsBuilder.add(fileColumn, cc.xyw(5, 1, 2)); specialTableColumnsBuilder.add(urlColumn, cc.xyw(5, 2, 2)); specialTableColumnsBuilder.add(preferUrl, cc.xy(6, 3)); specialTableColumnsBuilder.add(preferDoi, cc.xy(6, 4)); specialTableColumnsBuilder.add(arxivColumn, cc.xyw(5, 5, 2)); specialTableColumnsBuilder.add(extraFileColumns, cc.xyw(5, 6, 2)); specialTableColumnsBuilder.add(listOfFileColumnsScrollPane, cc.xywh(5, 7, 2, 6)); builder.append(specialTableColumnsBuilder.getPanel()); builder.nextLine(); /*** end: special table columns and special fields ***/ builder.appendSeparator(Localization.lang("Entry table columns")); builder.nextLine(); builder.append(pan); builder.append(tabPanel); builder.nextLine(); builder.append(pan); JButton buttonWidth = new JButton(new UpdateWidthsAction()); JButton buttonOrder = new JButton(new UpdateOrderAction()); builder.append(buttonWidth); builder.nextLine(); builder.append(pan); builder.append(buttonOrder); builder.nextLine(); builder.append(pan); builder.nextLine(); pan = builder.getPanel(); pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); add(pan, BorderLayout.CENTER); } @Override public void setValues() { fileColumn.setSelected(prefs.getBoolean(JabRefPreferences.FILE_COLUMN)); urlColumn.setSelected(prefs.getBoolean(JabRefPreferences.URL_COLUMN)); preferUrl.setSelected(!prefs.getBoolean(JabRefPreferences.PREFER_URL_DOI)); preferDoi.setSelected(prefs.getBoolean(JabRefPreferences.PREFER_URL_DOI)); fileColumn.setSelected(prefs.getBoolean(JabRefPreferences.FILE_COLUMN)); arxivColumn.setSelected(prefs.getBoolean(JabRefPreferences.ARXIV_COLUMN)); extraFileColumns.setSelected(prefs.getBoolean(JabRefPreferences.EXTRA_FILE_COLUMNS)); if (extraFileColumns.isSelected()) { List<String> desiredColumns = prefs.getStringList(JabRefPreferences.LIST_OF_FILE_COLUMNS); int listSize = listOfFileColumns.getModel().getSize(); int[] indicesToSelect = new int[listSize]; for (int i = 0; i < listSize; i++) { indicesToSelect[i] = listSize + 1; for (String desiredColumn : desiredColumns) { if (listOfFileColumns.getModel().getElementAt(i).equals(desiredColumn)) { indicesToSelect[i] = i; break; } } } listOfFileColumns.setSelectedIndices(indicesToSelect); } else { listOfFileColumns.setSelectedIndices(new int[] {}); } /*** begin: special fields ***/ oldRankingColumn = prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_RANKING); rankingColumn.setSelected(oldRankingColumn); oldQualityColumn = prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_QUALITY); qualityColumn.setSelected(oldQualityColumn); oldPriorityColumn = prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_PRIORITY); priorityColumn.setSelected(oldPriorityColumn); oldRelevanceColumn = prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_RELEVANCE); relevanceColumn.setSelected(oldRelevanceColumn); oldPrintedColumn = prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_PRINTED); printedColumn.setSelected(oldPrintedColumn); oldReadStatusColumn = prefs.getBoolean(JabRefPreferences.SHOWCOLUMN_READ); readStatusColumn.setSelected(oldReadStatusColumn); oldSyncKeyWords = prefs.getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); syncKeywords.setSelected(oldSyncKeyWords); oldWriteSpecialFields = prefs.getBoolean(JabRefPreferences.SERIALIZESPECIALFIELDS); writeSpecialFields.setSelected(oldWriteSpecialFields); // has to be called as last to correctly enable/disable the other settings oldSpecialFieldsEnabled = prefs.getBoolean(JabRefPreferences.SPECIALFIELDSENABLED); specialFieldsEnabled.setSelected(!oldSpecialFieldsEnabled); specialFieldsEnabled.setSelected(oldSpecialFieldsEnabled); // Call twice to make sure the ChangeListener is triggered /*** end: special fields ***/ tableRows.clear(); List<String> names = prefs.getStringList(JabRefPreferences.COLUMN_NAMES); List<String> lengths = prefs.getStringList(JabRefPreferences.COLUMN_WIDTHS); for (int i = 0; i < names.size(); i++) { if (i < lengths.size()) { tableRows.add(new TableRow(names.get(i), Integer.parseInt(lengths.get(i)))); } else { tableRows.add(new TableRow(names.get(i))); } } rowCount = tableRows.size() + 5; ncWidth = prefs.getInt(JabRefPreferences.NUMBER_COL_WIDTH); } class DeleteRowAction extends AbstractAction { public DeleteRowAction() { super("Delete row", IconTheme.JabRefIcon.REMOVE_NOBOX.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Delete rows")); } @Override public void actionPerformed(ActionEvent e) { int[] rows = colSetup.getSelectedRows(); if (rows.length == 0) { return; } int offs = 0; for (int i = rows.length - 1; i >= 0; i--) { if ((rows[i] <= tableRows.size()) && (rows[i] != 0)) { tableRows.remove(rows[i] - 1); offs++; } } rowCount -= offs; if (rows.length > 1) { colSetup.clearSelection(); } colSetup.revalidate(); colSetup.repaint(); tableChanged = true; } } class AddRowAction extends AbstractAction { public AddRowAction() { super("Add row", IconTheme.JabRefIcon.ADD_NOBOX.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Insert rows")); } @Override public void actionPerformed(ActionEvent e) { int[] rows = colSetup.getSelectedRows(); if (rows.length == 0) { // No rows selected, so we just add one at the end. rowCount++; colSetup.revalidate(); colSetup.repaint(); return; } for (int i = 0; i < rows.length; i++) { if (((rows[i] + i) - 1) < tableRows.size()) { tableRows.add(Math.max(0, (rows[i] + i) - 1), new TableRow()); } } rowCount += rows.length; if (rows.length > 1) { colSetup.clearSelection(); } colSetup.revalidate(); colSetup.repaint(); tableChanged = true; } } abstract class AbstractMoveRowAction extends AbstractAction { public AbstractMoveRowAction(String string, Icon image) { super(string, image); } public void swap(int i, int j) { if ((i < 0) || (i >= tableRows.size())) { return; } if ((j < 0) || (j >= tableRows.size())) { return; } TableRow tmp = tableRows.get(i); tableRows.set(i, tableRows.get(j)); tableRows.set(j, tmp); } } class MoveRowUpAction extends AbstractMoveRowAction { public MoveRowUpAction() { super("Up", IconTheme.JabRefIcon.UP.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Move up")); } @Override public void actionPerformed(ActionEvent e) { int[] selected = colSetup.getSelectedRows(); Arrays.sort(selected); // first element (#) not inside tableRows // don't move if a selected element is at bounce if ((selected.length > 0) && (selected[0] > 1)) { boolean[] newSelected = new boolean[colSetup.getRowCount()]; for (int i : selected) { swap(i - 1, i - 2); newSelected[i - 1] = true; } // select all and remove unselected colSetup.setRowSelectionInterval(0, colSetup.getRowCount() - 1); for (int i = 0; i < colSetup.getRowCount(); i++) { if (!newSelected[i]) { colSetup.removeRowSelectionInterval(i, i); } } colSetup.revalidate(); colSetup.repaint(); tableChanged = true; } } } class MoveRowDownAction extends AbstractMoveRowAction { public MoveRowDownAction() { super("Down", IconTheme.JabRefIcon.DOWN.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Down")); } @Override public void actionPerformed(ActionEvent e) { int[] selected = colSetup.getSelectedRows(); Arrays.sort(selected); final int last = selected.length - 1; boolean[] newSelected = new boolean[colSetup.getRowCount()]; // don't move if a selected element is at bounce if ((selected.length > 0) && (selected[last] < tableRows.size())) { for (int i = last; i >= 0; i--) { swap(selected[i] - 1, selected[i]); newSelected[selected[i] + 1] = true; } // select all and remove unselected colSetup.setRowSelectionInterval(0, colSetup.getRowCount() - 1); for (int i = 0; i < colSetup.getRowCount(); i++) { if (!newSelected[i]) { colSetup.removeRowSelectionInterval(i, i); } } colSetup.revalidate(); colSetup.repaint(); tableChanged = true; } } } class UpdateOrderAction extends AbstractAction { public UpdateOrderAction() { super(Localization.lang("Update to current column order")); } @Override public void actionPerformed(ActionEvent e) { BasePanel panel = frame.getCurrentBasePanel(); if (panel == null) { return; } // idea: sort elements according to value stored in hash, keep // everything not inside hash/mainTable as it was final HashMap<String, Integer> map = new HashMap<>(); // first element (#) not inside tableRows for (int i = 1; i < panel.getMainTable().getColumnCount(); i++) { String name = panel.getMainTable().getColumnName(i); if ((name != null) && !name.isEmpty()) { map.put(name.toLowerCase(Locale.ROOT), i); } } Collections.sort(tableRows, (o1, o2) -> { Integer n1 = map.get(o1.getName()); Integer n2 = map.get(o2.getName()); if ((n1 == null) || (n2 == null)) { return 0; } return n1.compareTo(n2); }); colSetup.revalidate(); colSetup.repaint(); tableChanged = true; } } class UpdateWidthsAction extends AbstractAction { public UpdateWidthsAction() { super(Localization.lang("Update to current column widths")); } @Override public void actionPerformed(ActionEvent e) { BasePanel panel = frame.getCurrentBasePanel(); if (panel == null) { return; } TableColumnModel colMod = panel.getMainTable().getColumnModel(); colSetup.setValueAt(String.valueOf(colMod.getColumn(0).getWidth()), 0, 1); for (int i = 1; i < colMod.getColumnCount(); i++) { try { String name = panel.getMainTable().getColumnName(i).toLowerCase(Locale.ROOT); int width = colMod.getColumn(i).getWidth(); if ((i <= tableRows.size()) && ((String) colSetup.getValueAt(i, 0)).equalsIgnoreCase(name)) { colSetup.setValueAt(String.valueOf(width), i, 1); } else { // Doesn't match; search for a matching col in our table for (int j = 0; j < colSetup.getRowCount(); j++) { if ((j < tableRows.size()) && ((String) colSetup.getValueAt(j, 0)).equalsIgnoreCase(name)) { colSetup.setValueAt(String.valueOf(width), j, 1); break; } } } } catch (Throwable ex) { LOGGER.warn("Problem with table columns", ex); } colSetup.revalidate(); colSetup.repaint(); } } } /** * Store changes to table preferences. This method is called when * the user clicks Ok. * */ @Override public void storeSettings() { prefs.putBoolean(JabRefPreferences.FILE_COLUMN, fileColumn.isSelected()); prefs.putBoolean(JabRefPreferences.URL_COLUMN, urlColumn.isSelected()); prefs.putBoolean(JabRefPreferences.PREFER_URL_DOI, preferDoi.isSelected()); prefs.putBoolean(JabRefPreferences.ARXIV_COLUMN, arxivColumn.isSelected()); prefs.putBoolean(JabRefPreferences.EXTRA_FILE_COLUMNS, extraFileColumns.isSelected()); if (extraFileColumns.isSelected() && !listOfFileColumns.isSelectionEmpty()) { int numberSelected = listOfFileColumns.getSelectedIndices().length; List<String> selections = new ArrayList<>(numberSelected); for (int i = 0; i < numberSelected; i++) { selections.add(listOfFileColumns.getModel().getElementAt(listOfFileColumns.getSelectedIndices()[i])); } prefs.putStringList(JabRefPreferences.LIST_OF_FILE_COLUMNS, selections); } else { prefs.putStringList(JabRefPreferences.LIST_OF_FILE_COLUMNS, new ArrayList<>()); } /*** begin: special fields ***/ boolean newSpecialFieldsEnabled = specialFieldsEnabled.isSelected(); boolean newRankingColumn = rankingColumn.isSelected(); boolean newQualityColumn = qualityColumn.isSelected(); boolean newPriorityColumn = priorityColumn.isSelected(); boolean newRelevanceColumn = relevanceColumn.isSelected(); boolean newPrintedColumn = printedColumn.isSelected(); boolean newReadStatusColumn = readStatusColumn.isSelected(); boolean newSyncKeyWords = syncKeywords.isSelected(); boolean newWriteSpecialFields = writeSpecialFields.isSelected(); boolean restartRequired; restartRequired = (oldSpecialFieldsEnabled != newSpecialFieldsEnabled) || (oldRankingColumn != newRankingColumn) || (oldQualityColumn != newQualityColumn) || (oldPriorityColumn != newPriorityColumn) || (oldRelevanceColumn != newRelevanceColumn) || (oldPrintedColumn != newPrintedColumn) || (oldReadStatusColumn != newReadStatusColumn) || (oldSyncKeyWords != newSyncKeyWords) || (oldWriteSpecialFields != newWriteSpecialFields); if (restartRequired) { JOptionPane.showMessageDialog(null, Localization.lang("You have changed settings for special fields.") .concat(" ") .concat(Localization.lang("You must restart JabRef for this to come into effect.")), Localization.lang("Changed special field settings"), JOptionPane.WARNING_MESSAGE); } // restart required implies that the settings have been changed // the seetings need to be stored if (restartRequired) { prefs.putBoolean(JabRefPreferences.SPECIALFIELDSENABLED, newSpecialFieldsEnabled); prefs.putBoolean(JabRefPreferences.SHOWCOLUMN_RANKING, newRankingColumn); prefs.putBoolean(JabRefPreferences.SHOWCOLUMN_PRIORITY, newPriorityColumn); prefs.putBoolean(JabRefPreferences.SHOWCOLUMN_QUALITY, newQualityColumn); prefs.putBoolean(JabRefPreferences.SHOWCOLUMN_RELEVANCE, newRelevanceColumn); prefs.putBoolean(JabRefPreferences.SHOWCOLUMN_PRINTED, newPrintedColumn); prefs.putBoolean(JabRefPreferences.SHOWCOLUMN_READ, newReadStatusColumn); prefs.putBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS, newSyncKeyWords); prefs.putBoolean(JabRefPreferences.SERIALIZESPECIALFIELDS, newWriteSpecialFields); } /*** end: special fields ***/ if (colSetup.isEditing()) { int col = colSetup.getEditingColumn(); int row = colSetup.getEditingRow(); colSetup.getCellEditor(row, col).stopCellEditing(); } // Now we need to make sense of the contents the user has made to the // table setup table. if (tableChanged) { // First we remove all rows with empty names. int i = 0; while (i < tableRows.size()) { if (tableRows.get(i).getName().isEmpty()) { tableRows.remove(i); } else { i++; } } // Then we make arrays List<String> names = new ArrayList<>(tableRows.size()); List<String> widths = new ArrayList<>(tableRows.size()); List<Integer> nWidths = new ArrayList<>(tableRows.size()); prefs.putInt(JabRefPreferences.NUMBER_COL_WIDTH, ncWidth); for (TableRow tr : tableRows) { names.add(tr.getName().toLowerCase(Locale.ROOT)); nWidths.add(tr.getLength()); widths.add(String.valueOf(tr.getLength())); } // Finally, we store the new preferences. prefs.putStringList(JabRefPreferences.COLUMN_NAMES, names); prefs.putStringList(JabRefPreferences.COLUMN_WIDTHS, widths); } } @Override public boolean validateSettings() { return true; } @Override public String getTabName() { return Localization.lang("Entry table columns"); } }