146dd3f1ead410f7954f7b1a47621b97271cdeb0
[debian/jabref.git] / src / java / net / sf / jabref / TableColumnsTab.java
1 /*  Copyright (C) 2003-2011 JabRef contributors.
2     This program is free software; you can redistribute it and/or modify
3     it under the terms of the GNU General Public License as published by
4     the Free Software Foundation; either version 2 of the License, or
5     (at your option) any later version.
6
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10     GNU General Public License for more details.
11
12     You should have received a copy of the GNU General Public License along
13     with this program; if not, write to the Free Software Foundation, Inc.,
14     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15 */
16 package net.sf.jabref;
17
18 import java.awt.BorderLayout;
19 import java.awt.Dimension;
20 import java.awt.event.ActionEvent;
21 import java.util.*;
22
23 import javax.swing.*;
24 import javax.swing.event.ChangeEvent;
25 import javax.swing.event.ChangeListener;
26 import javax.swing.table.AbstractTableModel;
27 import javax.swing.table.TableColumnModel;
28 import javax.swing.table.TableModel;
29
30 import net.sf.jabref.specialfields.SpecialFieldsUtils;
31
32 import com.jgoodies.forms.builder.DefaultFormBuilder;
33 import com.jgoodies.forms.layout.CellConstraints;
34 import com.jgoodies.forms.layout.FormLayout;
35
36 class TableColumnsTab extends JPanel implements PrefsTab {
37
38     JabRefPreferences _prefs;
39     private boolean tableChanged = false;
40     private JTable colSetup;
41     private int rowCount = -1, ncWidth = -1;
42     private Vector<TableRow> tableRows = new Vector<TableRow>(10);
43     private JabRefFrame frame;
44
45     private JCheckBox pdfColumn, urlColumn, fileColumn, arxivColumn;
46     
47     private JCheckBox showOneLetterHeadingForIconColumns;
48     private boolean oldShowOneLetterHeadingForIconColumns;
49
50         /*** begin: special fields ***/
51         private JCheckBox specialFieldsEnabled, rankingColumn, compactRankingColumn, qualityColumn, priorityColumn, relevanceColumn;
52         private JRadioButton syncKeywords, writeSpecialFields;
53         private boolean oldSpecialFieldsEnabled, oldRankingColumn, oldCompcatRankingColumn, oldQualityColumn, oldPriorityColumn, oldRelevanceColumn, oldSyncKeyWords, oldWriteSpecialFields;
54         private final JButton hlb; 
55         /*** end: special fields ***/
56
57     class TableRow {
58         String name;
59         int length;
60         public TableRow(String name) {
61             this.name = name;
62             length = GUIGlobals.DEFAULT_FIELD_LENGTH;
63         }
64         public TableRow(int length) {
65             this.length = length;
66             name = "";
67         }
68         public TableRow(String name, int length) {
69             this.name = name;
70             this.length = length;
71         }
72     }
73
74
75     /**
76      * Customization of external program paths.
77      *
78      * @param prefs a <code>JabRefPreferences</code> value
79      */
80     public TableColumnsTab(JabRefPreferences prefs, JabRefFrame frame) {
81         _prefs = prefs;
82         this.frame = frame;
83         setLayout(new BorderLayout());
84
85         TableModel tm = new AbstractTableModel() {
86                 public int getRowCount() { return rowCount; }
87                 public int getColumnCount() { return 2; }
88                 public Object getValueAt(int row, int column) {
89                   if (row == 0)
90                     return (column==0 ? GUIGlobals.NUMBER_COL : ""+ncWidth);
91                   row--;
92                   if (row >= tableRows.size())
93                     return "";
94                   Object rowContent = tableRows.elementAt(row);
95                   if (rowContent == null)
96                     return "";
97                   TableRow tr = (TableRow)rowContent;
98                   switch (column) {
99                     case 0:
100                       return tr.name;
101                     case 1:
102                       return ((tr.length > 0) ? Integer.toString(tr.length) : "");
103                   }
104                   return null; // Unreachable.
105                 }
106
107                 public String getColumnName(int col) {
108                     return (col == 0 ? Globals.lang("Field name") : Globals.lang("Column width"));
109                 }
110                 public Class<?> getColumnClass(int column) {
111                     if (column == 0)
112                         return String.class;
113                     else
114                         return Integer.class;
115                 }
116                 public boolean isCellEditable(int row, int col) {
117                     return !((row == 0) && (col == 0));
118                 }
119                 public void setValueAt(Object value, int row, int col) {
120                     tableChanged = true;
121                     // Make sure the vector is long enough.
122                     while (row >= tableRows.size())
123                         tableRows.add(new TableRow("", -1));
124
125                         if ((row == 0) && (col == 1)) {
126                           ncWidth = Integer.parseInt(value.toString());
127                           return;
128                         }
129
130                     TableRow rowContent = tableRows.elementAt(row-1);
131
132                     if (col == 0) {
133                         rowContent.name = value.toString();
134                         if (((String)getValueAt(row, 1)).equals(""))
135                             setValueAt(""+GUIGlobals.DEFAULT_FIELD_LENGTH, row, 1);
136                     }
137                     else {
138                         if (value == null) rowContent.length = -1;
139                         else rowContent.length = Integer.parseInt(value.toString());
140                     }
141                 }
142
143             };
144
145         colSetup = new JTable(tm);
146         TableColumnModel cm = colSetup.getColumnModel();
147         cm.getColumn(0).setPreferredWidth(140);
148         cm.getColumn(1).setPreferredWidth(80);
149
150         FormLayout layout = new FormLayout
151             ("1dlu, 8dlu, left:pref, 4dlu, fill:pref",//, 4dlu, fill:60dlu, 4dlu, fill:pref",
152              "");
153         DefaultFormBuilder builder = new DefaultFormBuilder(layout);
154         JPanel pan = new JPanel();
155         JPanel tabPanel = new JPanel();
156         tabPanel.setLayout(new BorderLayout());
157         JScrollPane sp = new JScrollPane
158             (colSetup, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
159              JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
160         colSetup.setPreferredScrollableViewportSize(new Dimension(250,200));
161         sp.setMinimumSize(new Dimension(250,300));
162         tabPanel.add(sp, BorderLayout.CENTER);
163         JToolBar tlb = new JToolBar(SwingConstants.VERTICAL);
164         tlb.setFloatable(false);
165         //tlb.setRollover(true);
166         //tlb.setLayout(gbl);
167         AddRowAction ara = new AddRowAction();
168         DeleteRowAction dra = new DeleteRowAction();
169         MoveRowUpAction moveUp = new MoveRowUpAction();
170         MoveRowDownAction moveDown = new MoveRowDownAction();
171         tlb.setBorder(null);
172         tlb.add(ara);
173         tlb.add(dra);
174         tlb.addSeparator();
175         tlb.add(moveUp);
176         tlb.add(moveDown);
177         //tlb.addSeparator();
178         //tlb.add(new UpdateWidthsAction());
179         tabPanel.add(tlb, BorderLayout.EAST);
180         
181         showOneLetterHeadingForIconColumns = new JCheckBox(Globals.lang("Show one letter heading for icon columns"));
182
183         fileColumn = new JCheckBox(Globals.lang("Show file column"));
184         pdfColumn = new JCheckBox(Globals.lang("Show PDF/PS column"));
185                 urlColumn = new JCheckBox(Globals.lang("Show URL/DOI column"));
186                 arxivColumn = new JCheckBox(Globals.lang("Show ArXiv column"));
187
188                 /*** begin: special table columns and special fields ***/
189
190                 HelpAction help = new HelpAction(frame.helpDiag, GUIGlobals.specialFieldsHelp);
191             hlb = new JButton(GUIGlobals.getImage("helpSmall"));
192             hlb.setToolTipText(Globals.lang("Help on special fields"));
193             hlb.addActionListener(help);
194                 
195                 specialFieldsEnabled = new JCheckBox(Globals.lang("Enable special fields"));
196 //              .concat(". ").concat(Globals.lang("You must restart JabRef for this to come into effect.")));
197                 specialFieldsEnabled.addChangeListener(new ChangeListener() {
198                         public void stateChanged(ChangeEvent event) {
199                                 boolean isEnabled = specialFieldsEnabled.isSelected();
200                                 rankingColumn.setEnabled(isEnabled);
201                                 compactRankingColumn.setEnabled(isEnabled?rankingColumn.isSelected():false);
202                                 qualityColumn.setEnabled(isEnabled);
203                                 priorityColumn.setEnabled(isEnabled);
204                                 relevanceColumn.setEnabled(isEnabled);
205                                 syncKeywords.setEnabled(isEnabled);
206                                 writeSpecialFields.setEnabled(isEnabled);
207                         }
208                 });
209                 rankingColumn = new JCheckBox(Globals.lang("Show rank"));
210                 rankingColumn.addChangeListener(new ChangeListener() {
211                         public void stateChanged(ChangeEvent event) {
212                                 compactRankingColumn.setEnabled(rankingColumn.isSelected());
213                         }
214                 });
215                 compactRankingColumn = new JCheckBox(Globals.lang("Compact rank"));
216                 qualityColumn = new JCheckBox(Globals.lang("Show quality"));
217                 priorityColumn = new JCheckBox(Globals.lang("Show priority"));
218                 relevanceColumn = new JCheckBox(Globals.lang("Show relevance"));
219                 
220                 // "sync keywords" and "write special" fields may be configured mutually exclusive only
221                 // The implementation supports all combinations (TRUE+TRUE and FALSE+FALSE, even if the latter does not make sense)
222                 // To avoid confusion, we opted to make the setting mutually exclusive
223                 syncKeywords = new JRadioButton(Globals.lang("Synchronize with keywords"));
224                 writeSpecialFields = new JRadioButton(Globals.lang("Write values of special fields as separate fields to BibTeX"));
225                 ButtonGroup group = new ButtonGroup();
226                 group.add(syncKeywords);
227                 group.add(writeSpecialFields);
228                 
229                 builder.appendSeparator(Globals.lang("Special table columns"));
230                 builder.nextLine();
231                 builder.append(pan);
232
233                 DefaultFormBuilder specialTableColumnsBuilder = new DefaultFormBuilder(new FormLayout(
234                                 "8dlu, 8dlu, 8cm, 8dlu, left:pref", "pref, pref, pref, pref, pref, pref, pref, pref, pref, pref"));
235         CellConstraints cc = new CellConstraints();
236                 
237         specialTableColumnsBuilder.add(specialFieldsEnabled, cc.xyw(1, 1, 3));
238         specialTableColumnsBuilder.add(rankingColumn, cc.xyw(2, 2, 2));
239         specialTableColumnsBuilder.add(compactRankingColumn, cc.xy(3, 3));
240         specialTableColumnsBuilder.add(relevanceColumn, cc.xyw(2, 4, 2));
241         specialTableColumnsBuilder.add(qualityColumn, cc.xyw(2, 5, 2));
242         specialTableColumnsBuilder.add(priorityColumn, cc.xyw(2, 6, 2));
243         specialTableColumnsBuilder.add(syncKeywords, cc.xyw(2, 7, 2));
244         specialTableColumnsBuilder.add(writeSpecialFields, cc.xyw(2, 8, 2));
245         specialTableColumnsBuilder.add(showOneLetterHeadingForIconColumns, cc.xyw(1, 9, 5));
246                 specialTableColumnsBuilder.add(hlb, cc.xyw(1, 10, 2));
247
248                 specialTableColumnsBuilder.add(fileColumn, cc.xy(5, 1));        
249                 specialTableColumnsBuilder.add(pdfColumn, cc.xy(5, 2)); 
250                 specialTableColumnsBuilder.add(urlColumn, cc.xy(5, 3)); 
251                 specialTableColumnsBuilder.add(arxivColumn, cc.xy(5, 4));       
252
253                 builder.append(specialTableColumnsBuilder.getPanel());
254                 builder.nextLine();
255
256                 /*** end: special table columns and special fields ***/
257
258         builder.appendSeparator(Globals.lang("Entry table columns"));
259         builder.nextLine();
260         builder.append(pan); builder.append(tabPanel); builder.nextLine();
261 //      lab = new JLabel("<HTML>("+Globals.lang("this button will update the column width settings<BR>"
262 //                                              +"to match the current widths in your table")+")</HTML>");
263 //        lab = new JLabel("<HTML>("+Globals.lang("this_button_will_update") +")</HTML>") ;
264         builder.append(pan);
265         JButton buttonWidth = new JButton(new UpdateWidthsAction());
266         JButton buttonOrder = new JButton(new UpdateOrderAction());
267         builder.append(buttonWidth);builder.nextLine();
268         builder.append(pan);
269         builder.append(buttonOrder);builder.nextLine();
270         builder.append(pan);
271         //builder.append(lab);
272         builder.nextLine();
273         pan = builder.getPanel();
274         pan.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
275         add(pan, BorderLayout.CENTER);
276     }
277
278     public void setValues() {
279                 fileColumn.setSelected(_prefs.getBoolean("fileColumn"));
280         pdfColumn.setSelected(_prefs.getBoolean("pdfColumn"));
281                 urlColumn.setSelected(_prefs.getBoolean("urlColumn"));
282         fileColumn.setSelected(_prefs.getBoolean("fileColumn"));
283         arxivColumn.setSelected(_prefs.getBoolean("arxivColumn"));
284
285         /*** begin: special fields ***/
286
287         oldRankingColumn = _prefs.getBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_RANKING);
288         rankingColumn.setSelected(oldRankingColumn);
289         
290         oldCompcatRankingColumn = _prefs.getBoolean(SpecialFieldsUtils.PREF_RANKING_COMPACT);
291         compactRankingColumn.setSelected(oldCompcatRankingColumn);
292                 
293         oldQualityColumn = _prefs.getBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_QUALITY);
294         qualityColumn.setSelected(oldQualityColumn);
295         
296                 oldPriorityColumn = _prefs.getBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_PRIORITY);
297         priorityColumn.setSelected(oldPriorityColumn);
298                 
299                 oldRelevanceColumn = _prefs.getBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_RELEVANCE);
300         relevanceColumn.setSelected(oldRelevanceColumn);
301                 
302                 oldSyncKeyWords = _prefs.getBoolean(SpecialFieldsUtils.PREF_AUTOSYNCSPECIALFIELDSTOKEYWORDS);
303                 syncKeywords.setSelected(oldSyncKeyWords);
304                 
305                 oldWriteSpecialFields = _prefs.getBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS);
306                 writeSpecialFields.setSelected(oldWriteSpecialFields);
307
308                 // has to be called as last to correctly enable/disable the other settings
309                 oldSpecialFieldsEnabled = _prefs.getBoolean(SpecialFieldsUtils.PREF_SPECIALFIELDSENABLED);
310                 specialFieldsEnabled.setSelected(oldSpecialFieldsEnabled);
311                 
312         /*** end: special fields ***/
313                 
314                 oldShowOneLetterHeadingForIconColumns = _prefs.getBoolean(JabRefPreferences.SHOWONELETTERHEADINGFORICONCOLUMNS);
315                 showOneLetterHeadingForIconColumns.setSelected(oldShowOneLetterHeadingForIconColumns);
316
317                 tableRows.clear();
318         String[] names = _prefs.getStringArray("columnNames"),
319             lengths = _prefs.getStringArray("columnWidths");
320         for (int i=0; i<names.length; i++) {
321             if (i<lengths.length)
322                 tableRows.add(new TableRow(names[i], Integer.parseInt(lengths[i])));
323             else
324                 tableRows.add(new TableRow(names[i]));
325         }
326         rowCount = tableRows.size()+5;
327         ncWidth = _prefs.getInt("numberColWidth");
328
329     }
330
331
332     class DeleteRowAction extends AbstractAction {
333         public DeleteRowAction() {
334           super("Delete row", GUIGlobals.getImage("remove"));
335           putValue(SHORT_DESCRIPTION, Globals.lang("Delete rows"));
336         }
337         public void actionPerformed(ActionEvent e) {
338           int[] rows = colSetup.getSelectedRows();
339           if (rows.length == 0)
340             return;
341           int offs = 0;
342           for (int i=rows.length-1; i>=0; i--) {
343             if ((rows[i] <= tableRows.size()) && (rows[i] != 0)) {
344                 tableRows.remove(rows[i]-1);
345                 offs++;
346             }
347           }
348           rowCount -= offs;
349           if (rows.length > 1) colSetup.clearSelection();
350           colSetup.revalidate();
351           colSetup.repaint();
352           tableChanged = true;
353         }
354       }
355
356     class AddRowAction extends AbstractAction {
357         public AddRowAction() {
358           super("Add row", GUIGlobals.getImage("add"));
359           putValue(SHORT_DESCRIPTION, Globals.lang("Insert rows"));
360         }
361         public void actionPerformed(ActionEvent e) {
362             int[] rows = colSetup.getSelectedRows();
363             if (rows.length == 0) {
364                 // No rows selected, so we just add one at the end.
365                 rowCount++;
366                 colSetup.revalidate();
367                 colSetup.repaint();
368                 return;
369             }
370             for (int i=0; i<rows.length; i++) {
371                 if (rows[i]+i-1 < tableRows.size())
372                     tableRows.add(Math.max(0, rows[i]+i-1), new TableRow(GUIGlobals.DEFAULT_FIELD_LENGTH));
373             }
374             rowCount += rows.length;
375             if (rows.length > 1) colSetup.clearSelection();
376             colSetup.revalidate();
377             colSetup.repaint();
378             tableChanged = true;
379         }
380     }
381
382     abstract class AbstractMoveRowAction extends AbstractAction {
383                 public AbstractMoveRowAction(String string, ImageIcon image) {
384                         super(string, image);
385                 }
386
387                 protected void swap(int i, int j) {
388                         if (i < 0 || i >= tableRows.size())
389                                 return;
390                         if (j < 0 || j >= tableRows.size())
391                                 return;
392                         TableRow tmp = tableRows.get(i);
393                         tableRows.set(i, tableRows.get(j));
394                         tableRows.set(j, tmp);
395                 }
396         }
397
398         class MoveRowUpAction extends AbstractMoveRowAction {
399                 public MoveRowUpAction() {
400                         super("Up", GUIGlobals.getImage("up"));
401                         putValue(SHORT_DESCRIPTION, Globals.lang("Move up"));
402                 }
403
404                 public void actionPerformed(ActionEvent e) {
405                         int selected[] = colSetup.getSelectedRows();
406                         Arrays.sort(selected);
407                         // first element (#) not inside tableRows
408                         // don't move if a selected element is at bounce
409                         if (selected.length > 0 && selected[0] > 1) {
410                                 boolean newSelected[] = new boolean[colSetup.getRowCount()];
411                                 for (int i : selected) {
412                                         swap(i - 1, i - 2);
413                                         newSelected[i - 1] = true;
414                                 }
415                                 // select all and remove unselected
416                                 colSetup.setRowSelectionInterval(0, colSetup.getRowCount() - 1);
417                                 for (int i = 0; i < colSetup.getRowCount(); i++) {
418                                         if (!newSelected[i])
419                                                 colSetup.removeRowSelectionInterval(i, i);
420                                 }
421                                 colSetup.revalidate();
422                                 colSetup.repaint();
423                                 tableChanged = true;
424                         }
425                 }
426         }
427
428         class MoveRowDownAction extends AbstractMoveRowAction {
429                 public MoveRowDownAction() {
430                         super("Down", GUIGlobals.getImage("down"));
431                         putValue(SHORT_DESCRIPTION, Globals.lang("Down"));
432                 }
433
434                 public void actionPerformed(ActionEvent e) {
435                         int selected[] = colSetup.getSelectedRows();
436                         Arrays.sort(selected);
437                         final int last = selected.length - 1;
438                         boolean newSelected[] = new boolean[colSetup.getRowCount()];
439                         // don't move if a selected element is at bounce
440                         if (selected.length > 0 && selected[last] < tableRows.size()) {
441                                 for (int i = last; i >= 0; i--) {
442                                         swap(selected[i] - 1, selected[i]);
443                                         newSelected[selected[i] + 1] = true;
444                                 }
445                                 // select all and remove unselected
446                                 colSetup.setRowSelectionInterval(0, colSetup.getRowCount() - 1);
447                                 for (int i = 0; i < colSetup.getRowCount(); i++) {
448                                         if (!newSelected[i])
449                                                 colSetup.removeRowSelectionInterval(i, i);
450                                 }
451                                 colSetup.revalidate();
452                                 colSetup.repaint();
453                                 tableChanged = true;
454                         }
455                 }
456         }
457
458         class UpdateOrderAction extends AbstractAction {
459                 public UpdateOrderAction() {
460                         super(Globals.lang("Update to current column order"));
461                 }
462
463                 public void actionPerformed(ActionEvent e) {
464                         BasePanel panel = frame.basePanel();
465                         if (panel == null) {
466                                 return;
467                         }
468                         // idea: sort elements according to value stored in hash, keep
469                         // everything not inside hash/mainTable as it was
470                         final HashMap<String, Integer> map = new HashMap<String, Integer>();
471
472                         // first element (#) not inside tableRows
473                         for (int i = 1; i < panel.mainTable.getColumnCount(); i++) {
474                                 String name = panel.mainTable.getColumnName(i);
475                                 if (name != null && name.length() != 0) {
476                                         map.put(name.toLowerCase(), i);
477                                 }
478                         }
479                         Collections.sort(tableRows, new Comparator<TableRow>() {
480                                 public int compare(TableRow o1, TableRow o2) {
481                                         Integer n1 = map.get(o1.name);
482                                         Integer n2 = map.get(o2.name);
483                                         if (n1 == null || n2 == null) {
484                                                 return 0;
485                                         }
486                                         return n1.compareTo(n2);
487                                 }
488                         });
489
490                         colSetup.revalidate();
491                         colSetup.repaint();
492                         tableChanged = true;
493                 }
494         }
495
496     class UpdateWidthsAction extends AbstractAction {
497         public UpdateWidthsAction() {
498           //super(Globals.lang("Update to current column widths"));
499           super(Globals.lang("Update to current column widths"));
500           //putValue(SHORT_DESCRIPTION, Globals.lang("Update to current column widths"));
501         }
502         public void actionPerformed(ActionEvent e) {
503             BasePanel panel = frame.basePanel();
504             if (panel == null) return;
505             TableColumnModel colMod = panel.mainTable.getColumnModel();
506             colSetup.setValueAt(""+colMod.getColumn(0).getWidth(), 0, 1);
507             for (int i=1; i<colMod.getColumnCount(); i++) {
508             try {
509                 String name = panel.mainTable.getColumnName(i).toLowerCase();
510                 int width = colMod.getColumn(i).getWidth();
511                 //Util.pr(":"+((String)colSetup.getValueAt(i-1, 0)).toLowerCase());
512                 //Util.pr("-"+name);
513                 if ((i <= tableRows.size()) && (((String)colSetup.getValueAt(i, 0)).toLowerCase()).equals(name))
514                     colSetup.setValueAt(""+width, i, 1);
515                 else { // Doesn't match; search for a matching col in our table
516                     for (int j=0; j<colSetup.getRowCount(); j++) {
517                         if ((j < tableRows.size()) &&
518                             (((String)colSetup.getValueAt(j, 0)).toLowerCase()).equals(name)) {
519                             colSetup.setValueAt(""+width, j, 1);
520                             break;
521                         }
522                     }
523                 }
524             } catch (Throwable ex) {
525                 ex.printStackTrace();
526             }
527             colSetup.revalidate();
528             colSetup.repaint();
529         }
530
531         }
532     }
533
534
535     /**
536      * Store changes to table preferences. This method is called when
537      * the user clicks Ok.
538      *
539      */
540     public void storeSettings() {
541         _prefs.putBoolean("fileColumn", fileColumn.isSelected());
542         _prefs.putBoolean("pdfColumn", pdfColumn.isSelected());
543                 _prefs.putBoolean("urlColumn", urlColumn.isSelected());
544                 _prefs.putBoolean("arxivColumn", arxivColumn.isSelected());
545                 
546                 _prefs.putBoolean(JabRefPreferences.SHOWONELETTERHEADINGFORICONCOLUMNS, showOneLetterHeadingForIconColumns.isSelected());
547
548         /*** begin: special fields ***/
549         
550                 boolean 
551                 newSpecialFieldsEnabled = specialFieldsEnabled.isSelected(),
552                 newRankingColumn = rankingColumn.isSelected(),
553                 newCompactRankingColumn = compactRankingColumn.isSelected(),
554                 newQualityColumn = qualityColumn.isSelected(), 
555                 newPriorityColumn = priorityColumn.isSelected(), 
556                 newRelevanceColumn = relevanceColumn.isSelected(), 
557                 newSyncKeyWords = syncKeywords.isSelected(), 
558                 newWriteSpecialFields = writeSpecialFields.isSelected();
559                 
560                 boolean restartRequired = false;
561                 restartRequired = (oldSpecialFieldsEnabled != newSpecialFieldsEnabled) ||
562                                 (oldRankingColumn != newRankingColumn) ||
563                                 (oldCompcatRankingColumn != newCompactRankingColumn) ||
564                                 (oldQualityColumn != newQualityColumn) ||
565                                 (oldPriorityColumn != newPriorityColumn) ||
566                                 (oldRelevanceColumn != newRelevanceColumn) ||
567                                 (oldSyncKeyWords != newSyncKeyWords) ||
568                                 (oldWriteSpecialFields != newWriteSpecialFields);
569                 if (restartRequired) {
570                 JOptionPane.showMessageDialog(null, 
571                                 Globals.lang("You have changed settings for special fields.")
572                                 .concat(" ")
573                                 .concat(Globals.lang("You must restart JabRef for this to come into effect.")),
574                                 Globals.lang("Changed special field settings"),
575                                 JOptionPane.WARNING_MESSAGE);
576                 }
577                 
578                 // restart required implies that the settings have been changed
579                 // the seetings need to be stored
580                 if (restartRequired) {
581                         _prefs.putBoolean(SpecialFieldsUtils.PREF_SPECIALFIELDSENABLED, newSpecialFieldsEnabled);
582                         _prefs.putBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_RANKING, newRankingColumn);
583                         _prefs.putBoolean(SpecialFieldsUtils.PREF_RANKING_COMPACT, newCompactRankingColumn);
584                         _prefs.putBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_PRIORITY, newPriorityColumn);
585                         _prefs.putBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_QUALITY, newQualityColumn);
586                         _prefs.putBoolean(SpecialFieldsUtils.PREF_SHOWCOLUMN_RELEVANCE, newRelevanceColumn);
587                         _prefs.putBoolean(SpecialFieldsUtils.PREF_AUTOSYNCSPECIALFIELDSTOKEYWORDS, newSyncKeyWords);
588                         _prefs.putBoolean(SpecialFieldsUtils.PREF_SERIALIZESPECIALFIELDS, newWriteSpecialFields);
589                 }
590                 
591         /*** end: special fields ***/
592
593                 if (colSetup.isEditing()) {
594             int col = colSetup.getEditingColumn(),
595                 row = colSetup.getEditingRow();
596             colSetup.getCellEditor(row, col).stopCellEditing();
597         }
598
599
600         //_prefs.putStringArray("columnNames", getChoices());
601         /*String[] cols = tableFields.getText().replaceAll("\\s+","")
602             .replaceAll("\\n+","").toLowerCase().split(";");
603         if (cols.length > 0) for (int i=0; i<cols.length; i++)
604             cols[i] = cols[i].trim();
605             else cols = null;*/
606
607         // Now we need to make sense of the contents the user has made to the
608         // table setup table.
609         if (tableChanged) {
610             // First we remove all rows with empty names.
611             int i=0;
612             while (i < tableRows.size()) {
613                 if (tableRows.elementAt(i).name.equals(""))
614                     tableRows.removeElementAt(i);
615                 else i++;
616             }
617             // Then we make arrays
618             String[] names = new String[tableRows.size()],
619                 widths = new String[tableRows.size()];
620             int[] nWidths = new int[tableRows.size()];
621
622             _prefs.putInt("numberColWidth", ncWidth);
623             for (i=0; i<tableRows.size(); i++) {
624                 TableRow tr = tableRows.elementAt(i);
625                 names[i] = tr.name.toLowerCase();
626                 nWidths[i] = tr.length;
627                 widths[i] = ""+tr.length;
628                 //Util.pr(names[i]+"   "+widths[i]);
629             }
630
631             // Finally, we store the new preferences.
632             _prefs.putStringArray("columnNames", names);
633             _prefs.putStringArray("columnWidths", widths);
634         }
635
636     }
637
638     public boolean readyToClose() {
639         return true;
640     }
641
642         public String getTabName() {
643             return Globals.lang("Entry table columns");
644         }
645 }