package net.sf.jabref; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.util.*; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import com.jgoodies.forms.builder.ButtonBarBuilder; public class ContentSelectorDialog2 extends JDialog { ActionListener wordEditFieldListener = null; GridBagLayout gbl = new GridBagLayout(); GridBagConstraints con = new GridBagConstraints(); JPanel fieldPan = new JPanel(), wordPan = new JPanel(), buttonPan = new JPanel(), fieldNamePan = new JPanel(), wordEditPan = new JPanel(); final String WORD_EMPTY_TEXT = Globals.lang("<no field>"), WORD_FIRSTLINE_TEXT = Globals.lang("<select word>"), FIELD_FIRST_LINE = Globals.lang("<field name>"); MetaData metaData; String currentField = null; TreeSet<String> fieldSet, wordSet; JabRefFrame frame; BasePanel panel; JButton help = new JButton(Globals.lang("Help")), newField = new JButton(Globals.lang("New")), removeField = new JButton(Globals.lang("Remove")), newWord = new JButton(Globals.lang("New")), removeWord = new JButton(Globals.lang("Remove")), ok = new JButton(Globals.lang("Ok")), cancel = new JButton(Globals.lang("Cancel")), apply = new JButton(Globals.lang("Apply")); DefaultListModel fieldListModel = new DefaultListModel(), wordListModel = new DefaultListModel(); JList fieldList = new JList(fieldListModel), wordList = new JList(wordListModel); JTextField fieldNameField = new JTextField("", 20), wordEditField = new JTextField("", 20); JScrollPane fPane = new JScrollPane(fieldList), wPane = new JScrollPane(wordList); HashMap<String, DefaultListModel> wordListModels = new HashMap<String, DefaultListModel>(); ArrayList<String> removedFields = new ArrayList<String>(); public ContentSelectorDialog2(Frame owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData, String fieldName) { super(owner, Globals.lang("Setup selectors"), modal); this.metaData = metaData; this.frame = frame; this.panel = panel; this.currentField = fieldName; doInit(); } public ContentSelectorDialog2(Dialog owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData, String fieldName) { super(owner, Globals.lang("Setup selectors"), modal); this.metaData = metaData; this.frame = frame; this.panel = panel; this.currentField = fieldName; doInit(); } /** Called from constructors */ private void doInit() { //help = new JButton(Globals.lang("Help")); //help.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help")); //help = new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help"); initLayout(); // wordSelector.addItem(WORD_EMPTY_TEXT); setupFieldSelector(); setupWordSelector(); setupActions(); int fieldInd = fieldListModel.indexOf(currentField); if (fieldInd >= 0) fieldList.setSelectedIndex(fieldInd); pack(); } private void setupActions() { wordList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { wordEditField.setText((String)wordList.getSelectedValue()); wordEditField.selectAll(); new FocusRequester(wordEditField); } }); newWord.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { newWordAction(); } }); wordEditFieldListener = new ActionListener() { public void actionPerformed(ActionEvent e) { int index = wordList.getSelectedIndex(); String old = (String)wordList.getSelectedValue(), newVal = wordEditField.getText(); if (newVal.equals("") || newVal.equals(old)) return; // Empty string or no change. int newIndex = findPos(wordListModel, newVal); if (index >= 0) { wordListModel.remove(index); wordListModel.add((newIndex <= index ? newIndex : newIndex-1), newVal); } else wordListModel.add(newIndex, newVal); wordEditField.selectAll(); } }; wordEditField.addActionListener(wordEditFieldListener); removeWord.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = wordList.getSelectedIndex(); if (index == -1) return; wordListModel.remove(index); wordEditField.setText(""); if (wordListModel.size() > 0) wordList.setSelectedIndex(Math.min(index, wordListModel.size()-1)); } }); fieldList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { currentField = (String)fieldList.getSelectedValue(); fieldNameField.setText(""); setupWordSelector(); } }); newField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fieldListModel.add(0, FIELD_FIRST_LINE); fieldList.setSelectedIndex(0); fPane.getVerticalScrollBar().setValue(0); fieldNameField.setEnabled(true); fieldNameField.setText(currentField); fieldNameField.selectAll(); new FocusRequester(fieldNameField); } }); fieldNameField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fieldNameField.transferFocus(); } }); fieldNameField.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { String s = fieldNameField.getText(); fieldNameField.setText(""); fieldNameField.setEnabled(false); if (!FIELD_FIRST_LINE.equals(s) && !"".equals(s)) { // Add new field. int pos = findPos(fieldListModel, s); fieldListModel.remove(0); fieldListModel.add(Math.max(0, pos-1), s); fieldList.setSelectedIndex(pos); currentField = s; setupWordSelector(); newWordAction(); //new FocusRequester(wordEditField); } } }); removeField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = fieldList.getSelectedIndex(); if (index == -1) return; String fieldName = (String)fieldListModel.get(index); removedFields.add(fieldName); fieldListModel.remove(index); wordListModels.remove(fieldName); fieldNameField.setText(""); if (fieldListModel.size() > 0) fieldList.setSelectedIndex(Math.min(index, wordListModel.size()-1)); } }); help.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { frame.helpDiag.showPage(GUIGlobals.contentSelectorHelp); } }); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { applyChanges(); dispose(); } }); apply.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // Store if an entry is currently being edited: if (!wordEditField.getText().equals("")) { wordEditFieldListener.actionPerformed(null); } applyChanges(); } }); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); } private void newWordAction() { if ((wordListModel.size() == 0) || !wordListModel.get(0).equals(WORD_FIRSTLINE_TEXT)) wordListModel.add(0, WORD_FIRSTLINE_TEXT); wordList.setSelectedIndex(0); wPane.getVerticalScrollBar().setValue(0); } private void applyChanges() { boolean changedFieldSet = false; // Watch if we need to rebuild entry editors // First remove the mappings for fields that have been deleted. // If these were re-added, they will be added below, so it doesn't // cause any harm to remove them here. for (Iterator<String> i=removedFields.iterator(); i.hasNext();) { String fieldName = i.next(); metaData.remove(Globals.SELECTOR_META_PREFIX+fieldName); changedFieldSet = true; } // Cycle through all fields that we have created listmodels for: loop: for (Iterator<String> i=wordListModels.keySet().iterator(); i.hasNext();) { // For each field name, store the values: String fieldName = i.next(); if ((fieldName == null) || FIELD_FIRST_LINE.equals(fieldName)) continue loop; DefaultListModel lm = wordListModels.get(fieldName); int start = 0; // Avoid storing the <new word> marker if it is there: if (lm.size() > 0) while ((start<lm.size()) && ((String)lm.get(start)).equals(WORD_FIRSTLINE_TEXT)) start++; Vector<String> data = metaData.getData(Globals.SELECTOR_META_PREFIX+fieldName); boolean newField = false; if (data == null) { newField = true; data = new Vector<String>(); changedFieldSet = true; } else data.clear(); for (int wrd=start; wrd<lm.size(); wrd++) { String word = (String)lm.get(wrd); data.add(word); } if (newField) metaData.putData(Globals.SELECTOR_META_PREFIX+fieldName, data); } // System.out.println("TODO: remove metadata for removed selector field."); panel.markNonUndoableBaseChanged(); // Update all selectors in the current BasePanel. if (!changedFieldSet) panel.updateAllContentSelectors(); else { panel.rebuildAllEntryEditors(); } panel.addContentSelectorValuesToAutoCompleters(); } /** * Set the contents of the field selector list. * */ private void setupFieldSelector() { fieldListModel.clear(); for (String s : metaData){ if (s.startsWith(Globals.SELECTOR_META_PREFIX)) fieldListModel.addElement(s.substring(Globals.SELECTOR_META_PREFIX.length())); } } private void setupWordSelector() { // Have we already created a listmodel for this field? Object o = wordListModels.get(currentField); if (o != null) { wordListModel = (DefaultListModel) o; wordList.setModel(wordListModel); } else { wordListModel = new DefaultListModel(); wordList.setModel(wordListModel); wordListModels.put(currentField, wordListModel); wordListModel.clear(); // wordListModel.addElement(WORD_FIRSTLINE_TEXT); Vector<String> items = metaData .getData(Globals.SELECTOR_META_PREFIX + currentField); if ((items != null)) { // && (items.size() > 0)) { wordSet = new TreeSet<String>(items); for (String s : wordSet){ int index = findPos(wordListModel, s); wordListModel.add(index, s); } } } } private int findPos(DefaultListModel lm, String item) { for (int i=0; i<lm.size(); i++) { String s = (String)lm.get(i); if (item.compareToIgnoreCase(s) < 0) { // item precedes s return i; } } return wordListModel.size(); } private void initLayout() { fieldNameField.setEnabled(false); fieldList.setVisibleRowCount(4); wordList.setVisibleRowCount(10); final String VAL = "Uren luren himmelturen, ja Besseggen."; fieldList.setPrototypeCellValue(VAL); wordList.setPrototypeCellValue(VAL); fieldPan.setBorder(BorderFactory.createTitledBorder (BorderFactory.createEtchedBorder(), Globals.lang("Field name"))); wordPan.setBorder(BorderFactory.createTitledBorder (BorderFactory.createEtchedBorder(), Globals.lang("Keyword"))); fieldPan.setLayout(gbl); wordPan.setLayout(gbl); con.insets = new Insets(2, 2, 2, 2); con.fill = GridBagConstraints.BOTH; con.gridwidth = 2; con.weightx = 1; con.weighty = 1; con.gridx = 0; con.gridy = 0; gbl.setConstraints(fPane, con); fieldPan.add(fPane); gbl.setConstraints(wPane, con); wordPan.add(wPane); con.gridwidth = 1; con.gridx = 2; //con.weightx = 0.7; con.gridheight = 2; gbl.setConstraints(fieldNamePan, con); fieldPan.add(fieldNamePan); gbl.setConstraints(wordEditPan, con); wordPan.add(wordEditPan); con.gridx = 0; con.gridy = 1; con.weightx = 0; con.weighty = 0; con.gridwidth = 1; con.gridheight = 1; con.fill = GridBagConstraints.NONE; con.anchor = GridBagConstraints.WEST; gbl.setConstraints(newField, con); fieldPan.add(newField); gbl.setConstraints(newWord, con); wordPan.add(newWord); con.gridx = 1; //con.anchor = GridBagConstraints.EAST; gbl.setConstraints(removeField, con); fieldPan.add(removeField); gbl.setConstraints(removeWord, con); wordPan.add(removeWord); con.anchor = GridBagConstraints.WEST; con.gridx = 0; con.gridy = 0; gbl.setConstraints(fieldNameField, con); fieldNamePan.add(fieldNameField); gbl.setConstraints(wordEditField, con); wordEditPan.add(wordEditField); // Add buttons: ButtonBarBuilder bsb = new ButtonBarBuilder(buttonPan); bsb.addGlue(); bsb.addGridded(ok); bsb.addGridded(apply); bsb.addGridded(cancel); bsb.addRelatedGap(); bsb.addGridded(help); bsb.addGlue(); // Add panels to dialog: con.fill = GridBagConstraints.BOTH; getContentPane().setLayout(gbl); con.weightx = 1; con.weighty = 0.5; con.gridwidth = 1; con.gridheight = 1; con.gridx = 0; con.gridy = 0; gbl.setConstraints(fieldPan, con); getContentPane().add(fieldPan); con.gridy = 1; gbl.setConstraints(wordPan, con); getContentPane().add(wordPan); con.weighty = 0; con.gridy = 2; con.insets = new Insets(12, 2, 2, 2); gbl.setConstraints(buttonPan, con); getContentPane().add(buttonPan); } }