b89805cc1b286ac7acfc4de26b6a085497aed05d
[debian/jabref.git] / src / java / net / sf / jabref / EntryEditorTab.java
1 /*
2  * Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
3  *
4  * All programs in this directory and subdirectories are published under the GNU
5  * General Public License as described below.
6  *
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option) any later
10  * version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19  * Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * Further information about the GNU GPL is available at:
22  * http://www.gnu.org/copyleft/gpl.ja.html
23  *
24  */
25 package net.sf.jabref;
26
27 import javax.swing.*;
28 import javax.swing.text.JTextComponent;
29 import java.util.*;
30 import java.util.List;
31 import java.awt.*;
32 import java.awt.event.*;
33
34 public class EntryEditorTab {
35
36     private JPanel panel = new JPanel();
37     private String[] fields;
38     private final static Object[] ARRAY = new String[0];
39     private EntryEditor parent;
40     private HashMap editors = new HashMap();
41     private FieldEditor activeField = null;
42     private JScrollPane sp = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
43     //    private BibtexEntry entry;
44
45     public EntryEditorTab(List fields, EntryEditor parent, boolean addKeyField, String name) {
46         if (fields != null)
47                 this.fields = (String[])fields.toArray(ARRAY);
48         else
49             this.fields = new String[] {};
50         this.parent = parent;
51         setupPanel(addKeyField, name);
52
53         // The following line makes sure focus cycles inside tab instead of being lost
54         // to other parts of the frame:
55         panel.setFocusCycleRoot(true);
56
57     }
58
59
60     private final void setupPanel(boolean addKeyField, String title) {
61         GridBagLayout gbl = new GridBagLayout();
62         GridBagConstraints con = new GridBagConstraints();
63         panel.setLayout(gbl);
64         double totalWeight = 0;
65         
66         //panel.setOpaque(true);
67         //panel.setBackground(java.awt.Color.white);
68
69         for (int i=0; i<fields.length; i++) {
70
71             // Create the text area:
72             FieldTextArea ta = new FieldTextArea(fields[i], null);//stringContent);
73         JComponent ex = parent.getExtra(fields[i], ta);
74             // Attach listeners and key bindings:
75             setupJTextComponent(ta);
76             ta.addFocusListener(new FieldListener(ta));
77
78             // Store the editor for later reference:
79             editors.put(fields[i], ta);
80             if (i == 0)
81                 activeField = ta;
82             
83             // The label for this field:
84             con.insets = new Insets(5, 5, 0, 0);
85             con.anchor = GridBagConstraints.WEST;
86             con.fill = GridBagConstraints.BOTH;
87             con.gridwidth = 1;
88             con.weightx = 0;
89             con.weighty = 0;
90             con.anchor = GridBagConstraints.NORTH;
91             con.fill = GridBagConstraints.BOTH;
92             gbl.setConstraints(ta.getLabel(), con);
93             panel.add(ta.getLabel());
94
95             // The field itself:
96             con.fill = GridBagConstraints.BOTH;
97             con.weightx = 1;
98             con.weighty = GUIGlobals.getFieldWeight(fields[i]);
99             totalWeight += con.weighty;
100             // The gridwidth depends on whether we will add an extra component to the right:
101             if (ex != null)
102                 con.gridwidth = 1;
103             else
104                 con.gridwidth = GridBagConstraints.REMAINDER;
105             gbl.setConstraints(ta.getPane(), con);
106             panel.add(ta.getPane());
107             
108             // Possibly an extra component:
109             if (ex != null) {
110                 con.gridwidth = GridBagConstraints.REMAINDER;
111                 con.anchor = GridBagConstraints.NORTH;
112                 con.fill = GridBagConstraints.HORIZONTAL;
113                 con.weightx = 0;
114                 gbl.setConstraints(ex, con);
115                 panel.add(ex);
116             }
117         panel.setName(title);
118         }
119
120         // Add the edit field for Bibtex-key.
121         if (addKeyField) {
122             con.insets.top += 25;
123             con.insets.bottom = 10;
124             con.gridwidth = 1;
125             con.weighty = 0;
126             con.weightx = 0;
127             con.fill = GridBagConstraints.HORIZONTAL;
128             con.anchor = GridBagConstraints.SOUTHWEST;
129             FieldTextField tf = new FieldTextField(Globals.KEY_FIELD, (String) parent.getEntry().getField(Globals.KEY_FIELD), true);
130         editors.put("bibtexkey", tf);
131
132         // If the key field is the only field, we should have only one editor, and this one should be set
133         // as active initially:
134         if (editors.size() == 1)
135             activeField = tf;
136         
137             gbl.setConstraints(tf.getLabel(), con);
138             panel.add(tf.getLabel());
139             con.gridwidth = GridBagConstraints.REMAINDER;
140             con.weightx = 1;        
141             setupJTextComponent(tf);
142             tf.addFocusListener(new FieldListener(tf));
143             gbl.setConstraints(tf, con);
144             panel.add(tf);
145         }
146
147
148     }
149
150
151     public void setActive(FieldEditor c) {
152         activeField = c;
153         //System.out.println(c.toString());
154     }
155     
156     public FieldEditor getActive() {
157         return activeField;
158     }
159
160     public List getFields() {
161         return java.util.Arrays.asList(fields);
162     }
163
164     public void activate() {
165         if (activeField != null)
166             activeField.requestFocus();
167
168
169         //System.out.println("Activate, hurra");
170     }
171
172     public void updateAll() {
173         // Test: make sure all fields are correct:
174         setEntry(parent.getEntry());
175         /*for (int i=0; i<fields.length; i++) {
176             FieldEditor fe = (FieldEditor)editors.get(fields[i]);
177             fe.setText(e);
178         }  */
179     }
180
181     public void setEntry(BibtexEntry entry) {
182         for (Iterator i=editors.keySet().iterator(); i.hasNext();) {
183             String field = (String)i.next();
184             FieldEditor ed = (FieldEditor)editors.get(field);
185             Object content = entry.getField(ed.getFieldName());
186             ed.setText((content == null) ? "" : content.toString());
187         }
188     }
189
190     public boolean updateField(String field, String content) {
191         if (!editors.containsKey(field))
192             return false;
193         FieldEditor ed = (FieldEditor)editors.get(field);
194         ed.setText(content);
195         return true;
196     }
197
198     public void validateAllFields() {
199         for (Iterator i=editors.keySet().iterator(); i.hasNext();) {
200             String field = (String)i.next();
201             FieldEditor ed = (FieldEditor)editors.get(field);
202         if (((Component)ed).hasFocus())
203             ed.setBackground(GUIGlobals.activeEditor);
204         else
205                 ed.setBackground(GUIGlobals.validFieldBackground);
206         }
207     }
208
209     public void setEnabled(boolean enabled) {
210         for (Iterator i=editors.keySet().iterator(); i.hasNext();) {
211             String field = (String)i.next();
212             FieldEditor ed = (FieldEditor)editors.get(field);
213             ed.setEnabled(enabled);
214         }
215     }
216
217     public Component getPane() {
218
219         return panel;
220     }
221
222     public void setupJTextComponent(JTextComponent ta) {
223         // Activate autocompletion if it should be used for this field.
224         
225         // Set up key bindings and focus listener for the FieldEditor.
226         InputMap im = ta.getInputMap(JComponent.WHEN_FOCUSED);
227         ActionMap am = ta.getActionMap();
228
229         im.put(Globals.prefs.getKey("Entry editor, previous entry"), "prev");
230         am.put("prev", parent.prevEntryAction);
231         im.put(Globals.prefs.getKey("Entry editor, next entry"), "next");
232         am.put("next", parent.nextEntryAction);
233     
234         im.put(Globals.prefs.getKey("Entry editor, store field"), "store");
235         am.put("store", parent.storeFieldAction);
236         im.put(Globals.prefs.getKey("Entry editor, next panel"), "right");
237         im.put(Globals.prefs.getKey("Entry editor, next panel 2"), "right");
238         am.put("left", parent.switchLeftAction);
239         im.put(Globals.prefs.getKey("Entry editor, previous panel"), "left");
240         im.put(Globals.prefs.getKey("Entry editor, previous panel 2"), "left");
241         am.put("right", parent.switchRightAction);
242         im.put(Globals.prefs.getKey("Help"), "help");
243         am.put("help", parent.helpAction);
244         im.put(Globals.prefs.getKey("Save database"), "save");
245         am.put("save", parent.saveDatabaseAction);
246         im.put(Globals.prefs.getKey("Next tab"), "nexttab");
247     am.put("nexttab", parent.frame.nextTab);
248     im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
249     am.put("prevtab", parent.frame.prevTab);
250         
251
252         try {
253             HashSet keys =
254                 new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
255             keys.clear();
256             keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB"));
257             ta.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
258             keys =
259                 new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
260             keys.clear();
261             keys.add(KeyStroke.getKeyStroke("shift pressed TAB"));
262             ta.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
263         } catch (Throwable t) {
264             System.err.println(t);
265         }
266         
267     }
268
269
270     /*
271      * Focus listener that fires the storeFieldAction when a FieldTextArea loses
272      * focus.
273      */
274     class FieldListener extends FocusAdapter {
275
276         FieldEditor fe;
277
278         public FieldListener(FieldEditor fe) {
279             this.fe = fe;
280         }
281
282         public void focusGained(FocusEvent e) {
283             setActive(fe);
284         }
285         
286         public void focusLost(FocusEvent e) {
287             if (!e.isTemporary())
288                 parent.updateField(fe);
289         }
290     }
291     
292 }
293