38d2c8f22ab6fa26d436557b21be4f35d4de28a9
[debian/jabref.git] / src / java / net / sf / jabref / ContentSelectorDialog2.java
1 package net.sf.jabref;
2
3 import java.awt.*;
4 import javax.swing.*;
5 import javax.swing.border.*;
6 import javax.swing.event.*;
7 import java.awt.event.*;
8 import java.util.Iterator;
9 import java.util.Vector;
10 import java.util.HashMap;
11 import java.util.TreeSet;
12 import java.util.ArrayList;
13
14 public class ContentSelectorDialog2 extends JDialog {
15
16     ActionListener wordEditFieldListener = null;
17     GridBagLayout gbl = new GridBagLayout();
18     GridBagConstraints con = new GridBagConstraints();
19     JPanel fieldPan = new JPanel(),
20         wordPan = new JPanel(),
21         buttonPan = new JPanel(),
22         fieldNamePan = new JPanel(),
23         wordEditPan = new JPanel();
24
25     final String
26         WORD_EMPTY_TEXT = Globals.lang("<no field>"),
27         WORD_FIRSTLINE_TEXT = Globals.lang("<select word>"),
28         FIELD_FIRST_LINE = Globals.lang("<field name>");
29     MetaData metaData;
30     String currentField = null;
31     TreeSet fieldSet, wordSet;
32     JabRefFrame frame;
33     BasePanel panel;
34     JButton help = new JButton(Globals.lang("Help")),
35         newField = new JButton(Globals.lang("New")),
36         removeField = new JButton(Globals.lang("Remove")),
37         newWord = new JButton(Globals.lang("New")),
38         removeWord = new JButton(Globals.lang("Remove")),
39         ok = new JButton(Globals.lang("Ok")),
40         cancel = new JButton(Globals.lang("Cancel")),
41         apply = new JButton(Globals.lang("Apply"));
42     DefaultListModel fieldListModel = new DefaultListModel(),
43         wordListModel = new DefaultListModel();
44     JList fieldList = new JList(fieldListModel),
45         wordList = new JList(wordListModel);
46     JTextField fieldNameField = new JTextField("", 20),
47         wordEditField = new JTextField("", 20);
48     JScrollPane fPane = new JScrollPane(fieldList),
49         wPane = new JScrollPane(wordList);
50
51     HashMap wordListModels = new HashMap();
52     ArrayList removedFields = new ArrayList();
53
54     public ContentSelectorDialog2(Frame owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData,
55               String fieldName) {
56         super(owner, Globals.lang("Setup selectors"), modal);
57         this.metaData = metaData;
58         this.frame = frame;
59         this.panel = panel;
60         this.currentField = fieldName;
61         doInit();
62     }
63     
64     public ContentSelectorDialog2(Dialog owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData,
65               String fieldName) {
66         super(owner, Globals.lang("Setup selectors"), modal);
67         this.metaData = metaData;
68         this.frame = frame;
69         this.panel = panel;
70         this.currentField = fieldName;
71         doInit();
72     }
73     
74     /** Called from constructors */
75     private void doInit() {
76         //help = new JButton(Globals.lang("Help"));
77         //help.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help"));
78         //help = new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help");
79         initLayout();
80         //  wordSelector.addItem(WORD_EMPTY_TEXT);
81     
82         setupFieldSelector();
83         setupWordSelector();
84         setupActions();
85         int fieldInd = fieldListModel.indexOf(currentField);
86         if (fieldInd >= 0)
87             fieldList.setSelectedIndex(fieldInd);
88     
89         pack();
90     }
91
92
93     private void setupActions() {
94
95         wordList.addListSelectionListener(new ListSelectionListener() {
96                 public void valueChanged(ListSelectionEvent e) {
97                     wordEditField.setText((String)wordList.getSelectedValue());
98                     wordEditField.selectAll();
99                     new FocusRequester(wordEditField);
100                 }
101             });
102
103         newWord.addActionListener(new ActionListener() {
104                 public void actionPerformed(ActionEvent e) {
105                     newWordAction();
106                 }
107             });
108                 
109         wordEditFieldListener = new ActionListener() {
110             public void actionPerformed(ActionEvent e) {
111                 int index = wordList.getSelectedIndex();
112                 String old = (String)wordList.getSelectedValue(),
113                 newVal = wordEditField.getText();
114                 if (newVal.equals("") || newVal.equals(old))
115                     return; // Empty string or no change.
116                 int newIndex = findPos(wordListModel, newVal);
117                 if (index >= 0) {
118                     wordListModel.remove(index);
119                     wordListModel.add((newIndex <= index ? newIndex : newIndex-1),
120                       newVal);
121                 } else
122                     wordListModel.add(newIndex, newVal);
123                     
124                 wordEditField.selectAll();
125             }
126         };
127         wordEditField.addActionListener(wordEditFieldListener);
128         
129         removeWord.addActionListener(new ActionListener() {
130                 public void actionPerformed(ActionEvent e) {
131                     int index = wordList.getSelectedIndex();
132                     if (index == -1)
133                         return;
134                     wordListModel.remove(index);
135                     wordEditField.setText("");
136                     if (wordListModel.size() > 0)
137                         wordList.setSelectedIndex(Math.min(index, wordListModel.size()-1));
138                 }
139             });
140
141
142         fieldList.addListSelectionListener(new ListSelectionListener() {
143                 public void valueChanged(ListSelectionEvent e) {
144                     currentField = (String)fieldList.getSelectedValue();
145                     fieldNameField.setText("");
146                     setupWordSelector();
147                 }
148             });
149
150         newField.addActionListener(new ActionListener() {
151                 public void actionPerformed(ActionEvent e) {
152                     fieldListModel.add(0, FIELD_FIRST_LINE);
153                     fieldList.setSelectedIndex(0);
154                     fPane.getVerticalScrollBar().setValue(0);
155                     fieldNameField.setEnabled(true);
156                     fieldNameField.setText(currentField);
157                     fieldNameField.selectAll();
158
159                     new FocusRequester(fieldNameField);
160                 }
161             });
162
163         fieldNameField.addActionListener(new ActionListener() {
164                 public void actionPerformed(ActionEvent e) {
165                     fieldNameField.transferFocus();
166                 }
167             });
168
169         fieldNameField.addFocusListener(new FocusAdapter() {
170                 public void focusLost(FocusEvent e) {
171                     String s = fieldNameField.getText();
172                     fieldNameField.setText("");
173                     fieldNameField.setEnabled(false);
174                     if (!FIELD_FIRST_LINE.equals(s) && !"".equals(s)) {
175                         // Add new field.
176                         int pos = findPos(fieldListModel, s);
177                         fieldListModel.remove(0);
178                         fieldListModel.add(Math.max(0, pos-1), s);
179                         fieldList.setSelectedIndex(pos);
180                         currentField = s;
181                         setupWordSelector();
182                         newWordAction();
183                         //new FocusRequester(wordEditField);
184                     }
185                 }
186             });
187
188         removeField.addActionListener(new ActionListener() {
189                 public void actionPerformed(ActionEvent e) {
190                     int index = fieldList.getSelectedIndex();
191                     if (index == -1)
192                         return;
193                     String fieldName = (String)fieldListModel.get(index);
194                     removedFields.add(fieldName);
195                     fieldListModel.remove(index);
196                     wordListModels.remove(fieldName);
197                     fieldNameField.setText("");
198                     if (fieldListModel.size() > 0)
199                         fieldList.setSelectedIndex(Math.min(index, wordListModel.size()-1));
200                 }
201             });
202
203         help.addActionListener(new ActionListener() {
204                 public void actionPerformed(ActionEvent e) {
205                     frame.helpDiag.showPage(GUIGlobals.contentSelectorHelp);
206                 }
207             });
208
209         ok.addActionListener(new ActionListener() {
210                 public void actionPerformed(ActionEvent e) {
211                     applyChanges();
212                     dispose();
213                 }
214             });
215
216         apply.addActionListener(new ActionListener() {
217                 public void actionPerformed(ActionEvent e) {
218             // Store if an entry is currently being edited:
219             if (!wordEditField.getText().equals("")) {
220                 wordEditFieldListener.actionPerformed(null);
221             }
222                     applyChanges();
223                 }
224             });
225
226         cancel.addActionListener(new ActionListener() {
227                 public void actionPerformed(ActionEvent e) {
228                     dispose();
229                 }
230             });
231
232     }
233
234     private void newWordAction() {
235         if ((wordListModel.size() == 0) || 
236             !wordListModel.get(0).equals(WORD_FIRSTLINE_TEXT))
237             wordListModel.add(0, WORD_FIRSTLINE_TEXT);
238         wordList.setSelectedIndex(0);
239         wPane.getVerticalScrollBar().setValue(0);
240     }
241
242
243     private void applyChanges() {
244         boolean changedFieldSet = false; // Watch if we need to rebuild entry editors
245
246         // First remove the mappings for fields that have been deleted.
247         // If these were re-added, they will be added below, so it doesn't
248         // cause any harm to remove them here.
249         for (Iterator i=removedFields.iterator(); i.hasNext();) {
250             String fieldName = (String)i.next();
251             metaData.remove(Globals.SELECTOR_META_PREFIX+fieldName);
252             changedFieldSet = true;
253         }
254
255         // Cycle through all fields that we have created listmodels for:
256         loop: for (Iterator i=wordListModels.keySet().iterator(); i.hasNext();) {
257             // For each field name, store the values:
258             String fieldName = (String)i.next();
259             if ((fieldName == null) || FIELD_FIRST_LINE.equals(fieldName))
260                 continue loop;
261             DefaultListModel lm = (DefaultListModel)wordListModels.get(fieldName);
262             int start = 0;
263             // Avoid storing the <new word> marker if it is there:
264             if (lm.size() > 0)
265                 while ((start<lm.size()) && ((String)lm.get(start)).equals(WORD_FIRSTLINE_TEXT))
266                     start++;
267             Vector data = metaData.getData(Globals.SELECTOR_META_PREFIX+fieldName);
268             boolean newField = false;
269             if (data == null) {
270                 newField = true;
271                 data = new Vector();
272                 changedFieldSet = true;
273
274             } else
275                 data.clear();
276             for (int wrd=start; wrd<lm.size(); wrd++) {
277                 String word = (String)lm.get(wrd);
278                 data.add(word);
279             }
280             if (newField)
281                 metaData.putData(Globals.SELECTOR_META_PREFIX+fieldName, data);
282         }
283
284         // System.out.println("TODO: remove metadata for removed selector field.");
285         panel.markNonUndoableBaseChanged();
286
287         // Update all selectors in the current BasePanel.
288         if (!changedFieldSet)
289             panel.updateAllContentSelectors();
290         else {
291             panel.rebuildAllEntryEditors();
292         }
293     }
294
295     /**
296      * Set the contents of the field selector list.
297      *
298      */
299     private void setupFieldSelector() {
300         fieldListModel.clear();
301         //fieldListModel.addElement(FIELD_FIRST_LINE);
302         for (Iterator i=metaData.iterator(); i.hasNext();) {
303             String s = (String)i.next();
304             if (s.startsWith(Globals.SELECTOR_META_PREFIX))
305                 fieldListModel.addElement(s.substring(Globals.SELECTOR_META_PREFIX.length()));
306         }
307
308     }
309
310
311     private void setupWordSelector() {
312
313         // Have we already created a listmodel for this field?
314         Object o = wordListModels.get(currentField);
315         if (o != null) {
316             wordListModel = (DefaultListModel)o;
317             wordList.setModel(wordListModel);
318         } else {
319             wordListModel = new DefaultListModel();
320             wordList.setModel(wordListModel);
321             wordListModels.put(currentField, wordListModel);
322             wordListModel.clear();
323             //wordListModel.addElement(WORD_FIRSTLINE_TEXT);
324             Vector items = metaData.getData(Globals.SELECTOR_META_PREFIX+currentField);
325             if ((items != null)) { // && (items.size() > 0)) {
326                 wordSet = new TreeSet(items);
327                 for (Iterator i=wordSet.iterator(); i.hasNext();) {
328                     String s = (String)i.next();
329                     int index = findPos(wordListModel, s);
330                     wordListModel.add(index, s);
331                 }
332             }
333         }
334     }
335
336     private int findPos(DefaultListModel lm, String item) {
337         for (int i=0; i<lm.size(); i++) {
338             String s = (String)lm.get(i);
339             if (item.compareToIgnoreCase(s) < 0) { // item precedes s
340                 return i;
341             }
342         }
343         return wordListModel.size();
344     }
345
346     private void initLayout() {
347         fieldNameField.setEnabled(false);
348         fieldList.setVisibleRowCount(4);
349         wordList.setVisibleRowCount(10);
350         final String VAL = "Uren luren himmelturen, ja Besseggen.";
351         fieldList.setPrototypeCellValue(VAL);
352         wordList.setPrototypeCellValue(VAL);
353
354         fieldPan.setBorder(BorderFactory.createTitledBorder
355                                (BorderFactory.createEtchedBorder(),
356                                 Globals.lang("Field name")));
357         wordPan.setBorder(BorderFactory.createTitledBorder
358                                (BorderFactory.createEtchedBorder(),
359                                 Globals.lang("Keyword")));
360         fieldPan.setLayout(gbl);
361         wordPan.setLayout(gbl);
362         con.insets = new Insets(2, 2, 2, 2);
363         con.fill = GridBagConstraints.BOTH;
364         con.gridwidth = 2;
365         con.weightx = 1;
366         con.weighty = 1;
367         con.gridx = 0;
368         con.gridy = 0;
369         gbl.setConstraints(fPane, con);
370         fieldPan.add(fPane);
371         gbl.setConstraints(wPane, con);
372         wordPan.add(wPane);
373         con.gridwidth = 1;
374         con.gridx = 2;
375         //con.weightx = 0.7;
376         con.gridheight = 2;
377         gbl.setConstraints(fieldNamePan, con);
378         fieldPan.add(fieldNamePan);
379         gbl.setConstraints(wordEditPan, con);
380         wordPan.add(wordEditPan);
381         con.gridx = 0;
382         con.gridy = 1;
383         con.weightx = 0;
384         con.weighty = 0;
385         con.gridwidth = 1;
386         con.gridheight = 1;
387         con.fill = GridBagConstraints.NONE;
388         con.anchor = GridBagConstraints.WEST;
389         gbl.setConstraints(newField, con);
390         fieldPan.add(newField);
391         gbl.setConstraints(newWord, con);
392         wordPan.add(newWord);
393         con.gridx = 1;
394         //con.anchor = GridBagConstraints.EAST;
395         gbl.setConstraints(removeField, con);
396         fieldPan.add(removeField);
397         gbl.setConstraints(removeWord, con);
398         wordPan.add(removeWord);
399         con.anchor = GridBagConstraints.WEST;
400         con.gridx = 0;
401         con.gridy = 0;
402         gbl.setConstraints(fieldNameField, con);
403         fieldNamePan.add(fieldNameField);
404         gbl.setConstraints(wordEditField, con);
405         wordEditPan.add(wordEditField);
406
407         // Add buttons:
408         buttonPan.add(help);
409         buttonPan.add(Box.createHorizontalStrut(10));
410         buttonPan.add(ok);
411         buttonPan.add(apply);
412         buttonPan.add(cancel);
413
414         // Add panels to dialog:
415         con.fill = GridBagConstraints.BOTH;
416         getContentPane().setLayout(gbl);
417         con.weightx = 1;
418         con.weighty = 0.5;
419         con.gridwidth = 1;
420         con.gridheight = 1;
421         con.gridx = 0;
422         con.gridy = 0;
423         gbl.setConstraints(fieldPan, con);
424         getContentPane().add(fieldPan);
425         con.gridy = 1;
426         gbl.setConstraints(wordPan, con);
427         getContentPane().add(wordPan);
428         con.weighty = 0;
429         con.gridy = 2;
430         con.insets = new Insets(12, 2, 2, 2);
431         gbl.setConstraints(buttonPan, con);
432         getContentPane().add(buttonPan);
433
434
435     }
436
437
438 }