private void typeDeletion(String name) {
    BibtexEntryType type = BibtexEntryType.getType(name);

    if (type instanceof CustomEntryType) {
      if (BibtexEntryType.getStandardType(name) == null) {
        int reply =
            JOptionPane.showConfirmDialog(
                frame,
                Globals.lang(
                    "All entries of this " + "type will be declared " + "typeless. Continue?"),
                Globals.lang("Delete custom format") + " '" + StringUtil.nCase(name) + '\'',
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE);
        if (reply != JOptionPane.YES_OPTION) {
          return;
        }
      }
      BibtexEntryType.removeType(name);
      updateTypesForEntries(StringUtil.nCase(name));
      changed.remove(name);
      reqLists.remove(name);
      optLists.remove(name);
      if (biblatexMode) {
        opt2Lists.remove(name);
      }
    }
    // messageLabel.setText("'"+type.getName()+"' "+
    //        Globals.lang("is a standard type."));

  }
Esempio n. 2
0
 /** force the search button to be large enough for the longer of the two texts */
 private void setSearchButtonSizes() {
   search.setText(Globals.lang("Search specified field(s)"));
   Dimension size1 = search.getPreferredSize();
   search.setText(Globals.lang("Search all fields"));
   Dimension size2 = search.getPreferredSize();
   size2.width = Math.max(size1.width, size2.width);
   search.setMinimumSize(size2);
   search.setPreferredSize(size2);
 }
  /**
   * @param owner the parent Window (Dialog or Frame)
   * @param frame the JabRef Frame
   * @param panel the currently selected BasePanel
   * @param modal should this dialog be modal?
   * @param metaData The metadata of the current database
   * @param fieldName the field this selector is initialized for. May be null.
   */
  public ContentSelectorDialog2(
      Window owner,
      JabRefFrame frame,
      BasePanel panel,
      boolean modal,
      MetaData metaData,
      String fieldName) {
    super(owner, Globals.lang("Setup selectors"));
    this.setModal(modal);
    this.metaData = metaData;
    this.frame = frame;
    this.panel = panel;
    this.currentField = fieldName;

    // 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();
    Util.bindCloseDialogKeyToCancelAction(this.rootPane, cancel.getAction());
    int fieldInd = fieldListModel.indexOf(currentField);
    if (fieldInd >= 0) fieldList.setSelectedIndex(fieldInd);

    pack();
  }
Esempio n. 4
0
  @Override
  public void actionPerformed(ActionEvent e) {

    if (e.getSource() == escape) {
      incSearch = false;
      clearSearchLater();
    } else if (((e.getSource() == searchField) || (e.getSource() == search))
        && !increment.isSelected()
        && (panel != null)) {

      updatePrefs(); // Make sure the user's choices are recorded.
      if (searchField.getText().isEmpty()) {
        // An empty search field should cause the search to be cleared.
        clearSearchLater();
        return;
      }

      fireSearchlistenerEvent(searchField.getText());

      // Setup search parameters common to both normal and float.
      SearchRule searchRule;

      if (Globals.prefs.getBoolean(JabRefPreferences.REG_EXP_SEARCH)) {
        searchRule =
            new BasicRegexSearchRule(
                Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH));
      } else {
        searchRule =
            new BasicSearchRule(Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH));
      }

      try {
        // this searches specified fields if specified,
        // and all fields otherwise
        searchRule =
            new SearchExpression(
                Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH),
                Globals.prefs.getBoolean(JabRefPreferences.REG_EXP_SEARCH));
      } catch (Exception ex) {
        // we'll do a search in all fields
      }

      if (!searchRule.validateSearchStrings(searchField.getText())) {
        panel.output(Globals.lang("Search failed: illegal search expression"));
        panel.stopShowingSearchResults();
        return;
      }
      SearchWorker worker = new SearchWorker(searchRule, searchField.getText());
      worker.getWorker().run();
      worker.getCallBack().update();
      escape.setEnabled(true);

      frame.basePanel().mainTable.setSelected(0);
    }
  }
  private void initGui() {
    Container pane = getContentPane();
    pane.setLayout(new BorderLayout());

    biblatexMode = Globals.prefs.getBoolean("biblatexMode");

    JPanel main = new JPanel(), buttons = new JPanel(), right = new JPanel();
    main.setLayout(new BorderLayout());
    right.setLayout(new GridLayout(biblatexMode ? 2 : 1, 2));

    java.util.List<String> entryTypes = new ArrayList<String>();
    for (String s : BibtexEntryType.ALL_TYPES.keySet()) {
      entryTypes.add(s);
    }

    typeComp = new EntryTypeList(entryTypes);
    typeComp.addListSelectionListener(this);
    typeComp.addAdditionActionListener(this);
    typeComp.addDefaultActionListener(new DefaultListener());
    typeComp.setListSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    // typeComp.setEnabled(false);
    reqComp =
        new FieldSetComponent(
            Globals.lang("Required fields"), new ArrayList<String>(), preset, true, true);
    reqComp.setEnabled(false);
    reqComp.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    ListDataListener dataListener = new DataListener();
    reqComp.addListDataListener(dataListener);
    optComp =
        new FieldSetComponent(
            Globals.lang("Optional fields"), new ArrayList<String>(), preset, true, true);
    optComp.setEnabled(false);
    optComp.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    optComp.addListDataListener(dataListener);
    right.add(reqComp);
    right.add(optComp);

    if (biblatexMode) {
      optComp2 =
          new FieldSetComponent(
              Globals.lang("Optional fields") + " 2", new ArrayList<String>(), preset, true, true);
      optComp2.setEnabled(false);
      optComp2.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
      optComp2.addListDataListener(dataListener);
      right.add(new JPanel());
      right.add(optComp2);
    }

    // right.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
    // Globals.lang("Fields")));
    right.setBorder(BorderFactory.createEtchedBorder());
    ok = new JButton("Ok");
    cancel = new JButton(Globals.lang("Cancel"));
    apply = new JButton(Globals.lang("Apply"));
    ok.addActionListener(this);
    apply.addActionListener(this);
    cancel.addActionListener(this);
    ButtonBarBuilder bb = new ButtonBarBuilder(buttons);
    buttons.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
    bb.addGlue();
    bb.addButton(ok);
    bb.addButton(apply);
    bb.addButton(cancel);
    bb.addGlue();

    AbstractAction closeAction =
        new AbstractAction() {

          @Override
          public void actionPerformed(ActionEvent e) {
            dispose();
          }
        };
    ActionMap am = main.getActionMap();
    InputMap im = main.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    im.put(Globals.prefs.getKey("Close dialog"), "close");
    am.put("close", closeAction);

    // con.fill = GridBagConstraints.BOTH;
    // con.weightx = 0.3;
    // con.weighty = 1;
    // gbl.setConstraints(typeComp, con);
    main.add(typeComp, BorderLayout.WEST);
    main.add(right, BorderLayout.CENTER);
    main.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    pane.add(main, BorderLayout.CENTER);
    pane.add(buttons, BorderLayout.SOUTH);
    pack();
  }
  /** Creates a new instance of EntryCustomizationDialog2 */
  public EntryCustomizationDialog2(JabRefFrame frame) {
    super(frame, Globals.lang("Customize entry types"), false);

    this.frame = frame;
    initGui();
  }
Esempio n. 7
0
 /**
  * Updates the text on the search button to reflect the type of search that will happen on click.
  */
 private void updateSearchButtonText() {
   search.setText(
       isSpecificSearch()
           ? Globals.lang("Search specified field(s)")
           : Globals.lang("Search all fields"));
 }
Esempio n. 8
0
  public SearchManager2(JabRefFrame frame, SidePaneManager manager) {
    super(manager, GUIGlobals.getIconUrl("search"), Globals.lang("Search"));

    this.frame = frame;
    incSearcher = new IncrementalSearcher(Globals.prefs);

    // setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.magenta));

    searchReq =
        new JCheckBoxMenuItem(
            Globals.lang("Search required fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_REQ));
    searchOpt =
        new JCheckBoxMenuItem(
            Globals.lang("Search optional fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_OPT));
    searchGen =
        new JCheckBoxMenuItem(
            Globals.lang("Search general fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_GEN));
    searchAll =
        new JCheckBoxMenuItem(
            Globals.lang("Search all fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_ALL));
    regExpSearch =
        new JCheckBoxMenuItem(
            Globals.lang("Use regular expressions"),
            Globals.prefs.getBoolean(JabRefPreferences.REG_EXP_SEARCH));

    increment = new JRadioButton(Globals.lang("Incremental"), false);
    floatSearch = new JRadioButton(Globals.lang("Float"), true);
    hideSearch = new JRadioButton(Globals.lang("Filter"), true);
    showResultsInDialog = new JRadioButton(Globals.lang("Show results in dialog"), true);
    searchAllBases =
        new JRadioButton(
            Globals.lang("Global search"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_ALL_BASES));
    ButtonGroup types = new ButtonGroup();
    types.add(increment);
    types.add(floatSearch);
    types.add(hideSearch);
    types.add(showResultsInDialog);
    types.add(searchAllBases);

    select = new JCheckBoxMenuItem(Globals.lang("Select matches"), false);
    increment.setToolTipText(Globals.lang("Incremental search"));
    floatSearch.setToolTipText(Globals.lang("Gray out non-matching entries"));
    hideSearch.setToolTipText(Globals.lang("Hide non-matching entries"));
    showResultsInDialog.setToolTipText(Globals.lang("Show search results in a window"));

    // Add an item listener that makes sure we only listen for key events
    // when incremental search is turned on.
    increment.addItemListener(this);
    floatSearch.addItemListener(this);
    hideSearch.addItemListener(this);
    showResultsInDialog.addItemListener(this);
    // Add the global focus listener, so a menu item can see if this field was focused when
    // an action was called.
    searchField.addFocusListener(Globals.focusListener);

    if (searchAll.isSelected()) {
      searchReq.setEnabled(false);
      searchOpt.setEnabled(false);
      searchGen.setEnabled(false);
    }
    searchAll.addChangeListener(
        new ChangeListener() {

          @Override
          public void stateChanged(ChangeEvent event) {
            boolean state = !searchAll.isSelected();
            searchReq.setEnabled(state);
            searchOpt.setEnabled(state);
            searchGen.setEnabled(state);
          }
        });

    caseSensitive =
        new JCheckBoxMenuItem(
            Globals.lang("Case sensitive"),
            Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH));

    highLightWords =
        new JCheckBoxMenuItem(
            Globals.lang("Highlight Words"),
            Globals.prefs.getBoolean(JabRefPreferences.HIGH_LIGHT_WORDS));

    searchAutoComplete =
        new JCheckBoxMenuItem(
            Globals.lang("Autocomplete names"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_AUTO_COMPLETE));
    settings.add(select);

    // 2005.03.29, trying to remove field category searches, to simplify
    // search usability.
    // settings.addSeparator();
    // settings.add(searchReq);
    // settings.add(searchOpt);
    // settings.add(searchGen);
    // settings.addSeparator();
    // settings.add(searchAll);
    // ---------------------------------------------------------------
    settings.addSeparator();
    settings.add(caseSensitive);
    settings.add(regExpSearch);
    settings.addSeparator();
    settings.add(highLightWords);
    settings.addSeparator();
    settings.add(searchAutoComplete);

    searchField.addActionListener(this);
    searchField.addCaretListener(this);
    search.addActionListener(this);
    searchField.addFocusListener(
        new FocusAdapter() {

          @Override
          public void focusGained(FocusEvent e) {
            if (increment.isSelected()) {
              searchField.setText("");
            }
          }

          @Override
          public void focusLost(FocusEvent e) {
            incSearch = false;
            incSearchPos = -1; // Reset incremental
            // search. This makes the
            // incremental search reset
            // once the user moves focus to
            // somewhere else.
            if (increment.isSelected()) {
              // searchField.setText("");
              // System.out.println("focuslistener");
            }
          }
        });
    escape.addActionListener(this);
    escape.setEnabled(false); // enabled after searching

    openset.addActionListener(
        new ActionListener() {

          @Override
          public void actionPerformed(ActionEvent e) {
            if (settings.isVisible()) {
              // System.out.println("oee");
              // settings.setVisible(false);
            } else {
              JButton src = (JButton) e.getSource();
              settings.show(src, 0, openset.getHeight());
            }
          }
        });

    searchAutoComplete.addActionListener(
        new ActionListener() {

          @Override
          public void actionPerformed(ActionEvent actionEvent) {
            Globals.prefs.putBoolean(
                JabRefPreferences.SEARCH_AUTO_COMPLETE, searchAutoComplete.isSelected());
            if (SearchManager2.this.frame.basePanel() != null) {
              SearchManager2.this.frame.basePanel().updateSearchManager();
            }
          }
        });
    Insets margin = new Insets(0, 2, 0, 2);
    // search.setMargin(margin);
    escape.setMargin(margin);
    openset.setMargin(margin);
    JButton help = new JButton(GUIGlobals.getImage("help"));
    int butSize = help.getIcon().getIconHeight() + 5;
    Dimension butDim = new Dimension(butSize, butSize);
    help.setPreferredSize(butDim);
    help.setMinimumSize(butDim);
    help.setMargin(margin);
    help.addActionListener(new HelpAction(Globals.helpDiag, GUIGlobals.searchHelp, "Help"));

    // Select the last used mode of search:
    if (Globals.prefs.getBoolean(JabRefPreferences.INCREMENT_S)) {
      increment.setSelected(true);
    } else if (Globals.prefs.getBoolean(JabRefPreferences.FLOAT_SEARCH)) {
      floatSearch.setSelected(true);
    } else if (Globals.prefs.getBoolean(JabRefPreferences.SHOW_SEARCH_IN_DIALOG)) {
      showResultsInDialog.setSelected(true);
    } else if (Globals.prefs.getBoolean(JabRefPreferences.SEARCH_ALL_BASES)) {
      searchAllBases.setSelected(true);
    } else {
      hideSearch.setSelected(true);
    }

    JPanel main = new JPanel();
    GridBagLayout gbl = new GridBagLayout();
    main.setLayout(gbl);
    GridBagConstraints con = new GridBagConstraints();
    con.gridwidth = GridBagConstraints.REMAINDER;
    con.fill = GridBagConstraints.BOTH;
    con.weightx = 1;

    gbl.setConstraints(searchField, con);
    main.add(searchField);
    // con.gridwidth = 1;
    gbl.setConstraints(search, con);
    main.add(search);
    con.gridwidth = GridBagConstraints.REMAINDER;
    gbl.setConstraints(escape, con);
    main.add(escape);
    con.insets = new Insets(0, 2, 0, 0);
    gbl.setConstraints(increment, con);
    main.add(increment);
    gbl.setConstraints(floatSearch, con);
    main.add(floatSearch);
    gbl.setConstraints(hideSearch, con);
    main.add(hideSearch);
    gbl.setConstraints(showResultsInDialog, con);
    main.add(showResultsInDialog);
    gbl.setConstraints(searchAllBases, con);
    main.add(searchAllBases);
    con.insets = new Insets(0, 0, 0, 0);
    JPanel pan = new JPanel();
    GridBagLayout gb = new GridBagLayout();
    gbl.setConstraints(pan, con);
    pan.setLayout(gb);
    con.weightx = 1;
    con.gridwidth = 1;
    gb.setConstraints(openset, con);
    pan.add(openset);
    con.weightx = 0;
    gb.setConstraints(help, con);
    pan.add(help);
    main.add(pan);
    main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

    setContentContainer(main);

    searchField.getInputMap().put(Globals.prefs.getKey("Repeat incremental search"), "repeat");

    searchField
        .getActionMap()
        .put(
            "repeat",
            new AbstractAction() {

              @Override
              public void actionPerformed(ActionEvent e) {
                if (increment.isSelected()) {
                  repeatIncremental();
                }
              }
            });
    searchField.getInputMap().put(Globals.prefs.getKey("Clear search"), "escape");
    searchField
        .getActionMap()
        .put(
            "escape",
            new AbstractAction() {

              @Override
              public void actionPerformed(ActionEvent e) {
                hideAway();
                // SearchManager2.this.actionPerformed(new ActionEvent(escape, 0, ""));
              }
            });
    setSearchButtonSizes();
    updateSearchButtonText();
  }
Esempio n. 9
0
    @Override
    public void update() {
      panel.output(Globals.lang("Searched database. Number of hits") + ": " + hits);

      // Show the result in the chosen way:
      if (searchAllBases.isSelected()) {
        // Search all databases. This means we need to use the search results dialog.
        // Turn off other search mode, if activated:
        if (startedFloatSearch) {
          panel.mainTable.stopShowingFloatSearch();
          startedFloatSearch = false;
        }
        if (startedFilterSearch) {
          panel.stopShowingSearchResults();
          startedFilterSearch = false;
        }
        // Make sure the search dialog is instantiated and cleared:
        instantiateSearchDialog();
        searchDialog.clear();
        for (int i = 0; i < frame.getTabbedPane().getTabCount(); i++) {
          BasePanel p = frame.baseAt(i);
          for (BibtexEntry entry : p.getDatabase().getEntries()) {
            if (entry.isSearchHit()) {
              searchDialog.addEntry(entry, p);
            }
          }
        }
        searchDialog.selectFirstEntry();
        searchDialog.setVisible(true);
      } else if (showResultsInDialog.isSelected()) {
        // Turn off other search mode, if activated:
        if (startedFloatSearch) {
          panel.mainTable.stopShowingFloatSearch();
          startedFloatSearch = false;
        }
        if (startedFilterSearch) {
          panel.stopShowingSearchResults();
          startedFilterSearch = false;
        }
        // Make sure the search dialog is instantiated and cleared:
        instantiateSearchDialog();
        searchDialog.clear();
        for (BibtexEntry entry : panel.getDatabase().getEntries()) {
          if (entry.isSearchHit()) {
            searchDialog.addEntry(entry, panel);
          }
        }
        searchDialog.selectFirstEntry();
        searchDialog.setVisible(true);
      } else if (hideSearch.isSelected()) {
        // Filtering search - removes non-hits from the table:
        if (startedFloatSearch) {
          panel.mainTable.stopShowingFloatSearch();
          startedFloatSearch = false;
        }
        startedFilterSearch = true;
        panel.setSearchMatcher(new SearchMatcher());

      } else {
        // Float search - floats hits to the top of the table:
        if (startedFilterSearch) {
          panel.stopShowingSearchResults();
          startedFilterSearch = false;
        }
        startedFloatSearch = true;
        panel.mainTable.showFloatSearch(new SearchMatcher());
      }

      // Afterwards, select all text in the search field.
      searchField.select(0, searchField.getText().length());
    }
Esempio n. 10
0
 /** Instantiate the search dialog, unless it has already been instantiated: */
 private void instantiateSearchDialog() {
   if (searchDialog == null) {
     searchDialog = new SearchResultsDialog(frame, Globals.lang("Search results"));
   }
 }
Esempio n. 11
0
public class SearchManager2 extends SidePaneComponent
    implements ActionListener, KeyListener, ItemListener, CaretListener {

  private final JabRefFrame frame;

  private final IncrementalSearcher incSearcher;
  private SearchResultsDialog searchDialog = null;

  private AutoCompleteListener autoCompleteListener = null;

  /** subscribed Objects */
  private final Vector<SearchTextListener> listeners = new Vector<SearchTextListener>();

  // private JabRefFrame frame;
  private final JTextField searchField = new JTextField("", 12);
  private final JPopupMenu settings = new JPopupMenu();
  private final JButton openset = new JButton(Globals.lang("Settings"));
  private final JButton escape = new JButton(Globals.lang("Clear"));
  /** This button's text will be set later. */
  private final JButton search = new JButton();

  private final JCheckBoxMenuItem searchReq;
  private final JCheckBoxMenuItem searchOpt;
  private final JCheckBoxMenuItem searchGen;
  private final JCheckBoxMenuItem searchAll;
  private final JCheckBoxMenuItem caseSensitive;
  private final JCheckBoxMenuItem regExpSearch;
  private final JCheckBoxMenuItem highLightWords;
  private final JCheckBoxMenuItem searchAutoComplete;

  private final JRadioButton increment;
  private final JRadioButton floatSearch;
  private final JRadioButton hideSearch;
  private final JRadioButton showResultsInDialog;
  private final JRadioButton searchAllBases;
  private final JCheckBoxMenuItem select;
  private boolean incSearch = false, startedFloatSearch = false, startedFilterSearch = false;

  private int incSearchPos = -1; // To keep track of where we are in

  // an incremental search. -1 means
  // that the search is inactive.

  public SearchManager2(JabRefFrame frame, SidePaneManager manager) {
    super(manager, GUIGlobals.getIconUrl("search"), Globals.lang("Search"));

    this.frame = frame;
    incSearcher = new IncrementalSearcher(Globals.prefs);

    // setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.magenta));

    searchReq =
        new JCheckBoxMenuItem(
            Globals.lang("Search required fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_REQ));
    searchOpt =
        new JCheckBoxMenuItem(
            Globals.lang("Search optional fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_OPT));
    searchGen =
        new JCheckBoxMenuItem(
            Globals.lang("Search general fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_GEN));
    searchAll =
        new JCheckBoxMenuItem(
            Globals.lang("Search all fields"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_ALL));
    regExpSearch =
        new JCheckBoxMenuItem(
            Globals.lang("Use regular expressions"),
            Globals.prefs.getBoolean(JabRefPreferences.REG_EXP_SEARCH));

    increment = new JRadioButton(Globals.lang("Incremental"), false);
    floatSearch = new JRadioButton(Globals.lang("Float"), true);
    hideSearch = new JRadioButton(Globals.lang("Filter"), true);
    showResultsInDialog = new JRadioButton(Globals.lang("Show results in dialog"), true);
    searchAllBases =
        new JRadioButton(
            Globals.lang("Global search"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_ALL_BASES));
    ButtonGroup types = new ButtonGroup();
    types.add(increment);
    types.add(floatSearch);
    types.add(hideSearch);
    types.add(showResultsInDialog);
    types.add(searchAllBases);

    select = new JCheckBoxMenuItem(Globals.lang("Select matches"), false);
    increment.setToolTipText(Globals.lang("Incremental search"));
    floatSearch.setToolTipText(Globals.lang("Gray out non-matching entries"));
    hideSearch.setToolTipText(Globals.lang("Hide non-matching entries"));
    showResultsInDialog.setToolTipText(Globals.lang("Show search results in a window"));

    // Add an item listener that makes sure we only listen for key events
    // when incremental search is turned on.
    increment.addItemListener(this);
    floatSearch.addItemListener(this);
    hideSearch.addItemListener(this);
    showResultsInDialog.addItemListener(this);
    // Add the global focus listener, so a menu item can see if this field was focused when
    // an action was called.
    searchField.addFocusListener(Globals.focusListener);

    if (searchAll.isSelected()) {
      searchReq.setEnabled(false);
      searchOpt.setEnabled(false);
      searchGen.setEnabled(false);
    }
    searchAll.addChangeListener(
        new ChangeListener() {

          @Override
          public void stateChanged(ChangeEvent event) {
            boolean state = !searchAll.isSelected();
            searchReq.setEnabled(state);
            searchOpt.setEnabled(state);
            searchGen.setEnabled(state);
          }
        });

    caseSensitive =
        new JCheckBoxMenuItem(
            Globals.lang("Case sensitive"),
            Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH));

    highLightWords =
        new JCheckBoxMenuItem(
            Globals.lang("Highlight Words"),
            Globals.prefs.getBoolean(JabRefPreferences.HIGH_LIGHT_WORDS));

    searchAutoComplete =
        new JCheckBoxMenuItem(
            Globals.lang("Autocomplete names"),
            Globals.prefs.getBoolean(JabRefPreferences.SEARCH_AUTO_COMPLETE));
    settings.add(select);

    // 2005.03.29, trying to remove field category searches, to simplify
    // search usability.
    // settings.addSeparator();
    // settings.add(searchReq);
    // settings.add(searchOpt);
    // settings.add(searchGen);
    // settings.addSeparator();
    // settings.add(searchAll);
    // ---------------------------------------------------------------
    settings.addSeparator();
    settings.add(caseSensitive);
    settings.add(regExpSearch);
    settings.addSeparator();
    settings.add(highLightWords);
    settings.addSeparator();
    settings.add(searchAutoComplete);

    searchField.addActionListener(this);
    searchField.addCaretListener(this);
    search.addActionListener(this);
    searchField.addFocusListener(
        new FocusAdapter() {

          @Override
          public void focusGained(FocusEvent e) {
            if (increment.isSelected()) {
              searchField.setText("");
            }
          }

          @Override
          public void focusLost(FocusEvent e) {
            incSearch = false;
            incSearchPos = -1; // Reset incremental
            // search. This makes the
            // incremental search reset
            // once the user moves focus to
            // somewhere else.
            if (increment.isSelected()) {
              // searchField.setText("");
              // System.out.println("focuslistener");
            }
          }
        });
    escape.addActionListener(this);
    escape.setEnabled(false); // enabled after searching

    openset.addActionListener(
        new ActionListener() {

          @Override
          public void actionPerformed(ActionEvent e) {
            if (settings.isVisible()) {
              // System.out.println("oee");
              // settings.setVisible(false);
            } else {
              JButton src = (JButton) e.getSource();
              settings.show(src, 0, openset.getHeight());
            }
          }
        });

    searchAutoComplete.addActionListener(
        new ActionListener() {

          @Override
          public void actionPerformed(ActionEvent actionEvent) {
            Globals.prefs.putBoolean(
                JabRefPreferences.SEARCH_AUTO_COMPLETE, searchAutoComplete.isSelected());
            if (SearchManager2.this.frame.basePanel() != null) {
              SearchManager2.this.frame.basePanel().updateSearchManager();
            }
          }
        });
    Insets margin = new Insets(0, 2, 0, 2);
    // search.setMargin(margin);
    escape.setMargin(margin);
    openset.setMargin(margin);
    JButton help = new JButton(GUIGlobals.getImage("help"));
    int butSize = help.getIcon().getIconHeight() + 5;
    Dimension butDim = new Dimension(butSize, butSize);
    help.setPreferredSize(butDim);
    help.setMinimumSize(butDim);
    help.setMargin(margin);
    help.addActionListener(new HelpAction(Globals.helpDiag, GUIGlobals.searchHelp, "Help"));

    // Select the last used mode of search:
    if (Globals.prefs.getBoolean(JabRefPreferences.INCREMENT_S)) {
      increment.setSelected(true);
    } else if (Globals.prefs.getBoolean(JabRefPreferences.FLOAT_SEARCH)) {
      floatSearch.setSelected(true);
    } else if (Globals.prefs.getBoolean(JabRefPreferences.SHOW_SEARCH_IN_DIALOG)) {
      showResultsInDialog.setSelected(true);
    } else if (Globals.prefs.getBoolean(JabRefPreferences.SEARCH_ALL_BASES)) {
      searchAllBases.setSelected(true);
    } else {
      hideSearch.setSelected(true);
    }

    JPanel main = new JPanel();
    GridBagLayout gbl = new GridBagLayout();
    main.setLayout(gbl);
    GridBagConstraints con = new GridBagConstraints();
    con.gridwidth = GridBagConstraints.REMAINDER;
    con.fill = GridBagConstraints.BOTH;
    con.weightx = 1;

    gbl.setConstraints(searchField, con);
    main.add(searchField);
    // con.gridwidth = 1;
    gbl.setConstraints(search, con);
    main.add(search);
    con.gridwidth = GridBagConstraints.REMAINDER;
    gbl.setConstraints(escape, con);
    main.add(escape);
    con.insets = new Insets(0, 2, 0, 0);
    gbl.setConstraints(increment, con);
    main.add(increment);
    gbl.setConstraints(floatSearch, con);
    main.add(floatSearch);
    gbl.setConstraints(hideSearch, con);
    main.add(hideSearch);
    gbl.setConstraints(showResultsInDialog, con);
    main.add(showResultsInDialog);
    gbl.setConstraints(searchAllBases, con);
    main.add(searchAllBases);
    con.insets = new Insets(0, 0, 0, 0);
    JPanel pan = new JPanel();
    GridBagLayout gb = new GridBagLayout();
    gbl.setConstraints(pan, con);
    pan.setLayout(gb);
    con.weightx = 1;
    con.gridwidth = 1;
    gb.setConstraints(openset, con);
    pan.add(openset);
    con.weightx = 0;
    gb.setConstraints(help, con);
    pan.add(help);
    main.add(pan);
    main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

    setContentContainer(main);

    searchField.getInputMap().put(Globals.prefs.getKey("Repeat incremental search"), "repeat");

    searchField
        .getActionMap()
        .put(
            "repeat",
            new AbstractAction() {

              @Override
              public void actionPerformed(ActionEvent e) {
                if (increment.isSelected()) {
                  repeatIncremental();
                }
              }
            });
    searchField.getInputMap().put(Globals.prefs.getKey("Clear search"), "escape");
    searchField
        .getActionMap()
        .put(
            "escape",
            new AbstractAction() {

              @Override
              public void actionPerformed(ActionEvent e) {
                hideAway();
                // SearchManager2.this.actionPerformed(new ActionEvent(escape, 0, ""));
              }
            });
    setSearchButtonSizes();
    updateSearchButtonText();
  }

  public void setAutoCompleteListener(AutoCompleteListener listener) {
    this.autoCompleteListener = listener;
    updateKeyListeners();
  }

  /**
   * Add the correct key listeners to the search text field, depending on whether and autocomplete
   * listener has been set and whether incremental search is selected.
   */
  private void updateKeyListeners() {
    KeyListener[] listeners = searchField.getKeyListeners();
    for (KeyListener listener : listeners) {
      searchField.removeKeyListener(listener);
    }
    if (increment.isSelected()) {
      searchField.addKeyListener(this);
    } else {
      if (searchAutoComplete.isSelected() && (autoCompleteListener != null)) {
        searchField.addKeyListener(autoCompleteListener);
      }
    }
  }

  /**
   * Subscribe to the SearchListener and receive events, if the user searches for some thing. You
   * will receive a list of words
   *
   * @param l
   */
  public void addSearchListener(SearchTextListener l) {
    if (listeners.contains(l)) {
      return;
    } else {
      listeners.add(l);
    }
    // fire event for the new subscriber
    l.searchText(getSearchwords(searchField.getText()));
  }

  /**
   * Remove object from the SearchListener
   *
   * @param l
   */
  public void removeSearchListener(SearchTextListener l) {
    listeners.remove(l);
  }

  /**
   * parse the search string for valid words and return a list of words Like "The great Vikinger"
   * will be ["The","great","Vikinger"]
   *
   * @param t
   * @return
   */
  private ArrayList<String> getSearchwords(String t) {
    // for now ... just seperate words by whitespace
    String[] strings = t.split(" ");
    ArrayList<String> words = new ArrayList<String>(strings.length);
    Collections.addAll(words, strings);
    return words;
  }

  /**
   * Fires an event if a search was started / canceled
   *
   * @param t
   */
  private void fireSearchlistenerEvent(String t) {
    // parse the Search string to words
    ArrayList<String> words;
    if ((t == null) || (t.isEmpty())) {
      words = null;
    } else {
      words = getSearchwords(t);
    }

    // fire an event for every listener
    for (SearchTextListener s : listeners) {
      s.searchText(words);
    }
  }

  /** force the search button to be large enough for the longer of the two texts */
  private void setSearchButtonSizes() {
    search.setText(Globals.lang("Search specified field(s)"));
    Dimension size1 = search.getPreferredSize();
    search.setText(Globals.lang("Search all fields"));
    Dimension size2 = search.getPreferredSize();
    size2.width = Math.max(size1.width, size2.width);
    search.setMinimumSize(size2);
    search.setPreferredSize(size2);
  }

  /** Instantiate the search dialog, unless it has already been instantiated: */
  private void instantiateSearchDialog() {
    if (searchDialog == null) {
      searchDialog = new SearchResultsDialog(frame, Globals.lang("Search results"));
    }
  }

  public void updatePrefs() {
    Globals.prefs.putBoolean(JabRefPreferences.SEARCH_REQ, searchReq.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.SEARCH_OPT, searchOpt.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.SEARCH_GEN, searchGen.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.SEARCH_ALL, searchAll.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.INCREMENT_S, increment.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.SELECT_S, select.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.FLOAT_SEARCH, floatSearch.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH, caseSensitive.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.REG_EXP_SEARCH, regExpSearch.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.HIGH_LIGHT_WORDS, highLightWords.isSelected());
    Globals.prefs.putBoolean(
        JabRefPreferences.SHOW_SEARCH_IN_DIALOG, showResultsInDialog.isSelected());
    Globals.prefs.putBoolean(JabRefPreferences.SEARCH_ALL_BASES, searchAllBases.isSelected());
  }

  public void startIncrementalSearch() {
    increment.setSelected(true);
    searchField.setText("");
    // System.out.println("startIncrementalSearch");
    searchField.requestFocus();
  }

  /**
   * Clears and focuses the search field if it is not focused. Otherwise, cycles to the next search
   * type.
   */
  public void startSearch() {
    if (increment.isSelected() && incSearch) {
      repeatIncremental();
      return;
    }
    if (!searchField.hasFocus()) {
      // searchField.setText("");
      searchField.selectAll();
      searchField.requestFocus();
    } else {
      if (increment.isSelected()) {
        floatSearch.setSelected(true);
      } else if (floatSearch.isSelected()) {
        hideSearch.setSelected(true);
      } else if (hideSearch.isSelected()) {
        showResultsInDialog.setSelected(true);
      } else if (showResultsInDialog.isSelected()) {
        searchAllBases.setSelected(true);
      } else {
        increment.setSelected(true);
      }
      increment.revalidate();
      increment.repaint();

      searchField.requestFocus();
    }
  }

  private void clearSearchLater() {
    if (panel == null) {
      return;
    }

    Runnable t =
        new Runnable() {

          @Override
          public void run() {
            clearSearch();
          }
        };
    // do this after the button action is over
    SwingUtilities.invokeLater(t);
  }

  @Override
  public void actionPerformed(ActionEvent e) {

    if (e.getSource() == escape) {
      incSearch = false;
      clearSearchLater();
    } else if (((e.getSource() == searchField) || (e.getSource() == search))
        && !increment.isSelected()
        && (panel != null)) {

      updatePrefs(); // Make sure the user's choices are recorded.
      if (searchField.getText().isEmpty()) {
        // An empty search field should cause the search to be cleared.
        clearSearchLater();
        return;
      }

      fireSearchlistenerEvent(searchField.getText());

      // Setup search parameters common to both normal and float.
      SearchRule searchRule;

      if (Globals.prefs.getBoolean(JabRefPreferences.REG_EXP_SEARCH)) {
        searchRule =
            new BasicRegexSearchRule(
                Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH));
      } else {
        searchRule =
            new BasicSearchRule(Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH));
      }

      try {
        // this searches specified fields if specified,
        // and all fields otherwise
        searchRule =
            new SearchExpression(
                Globals.prefs.getBoolean(JabRefPreferences.CASE_SENSITIVE_SEARCH),
                Globals.prefs.getBoolean(JabRefPreferences.REG_EXP_SEARCH));
      } catch (Exception ex) {
        // we'll do a search in all fields
      }

      if (!searchRule.validateSearchStrings(searchField.getText())) {
        panel.output(Globals.lang("Search failed: illegal search expression"));
        panel.stopShowingSearchResults();
        return;
      }
      SearchWorker worker = new SearchWorker(searchRule, searchField.getText());
      worker.getWorker().run();
      worker.getCallBack().update();
      escape.setEnabled(true);

      frame.basePanel().mainTable.setSelected(0);
    }
  }

  class SearchWorker extends AbstractWorker {

    private final SearchRule rule;
    private final String searchTerm;
    int hits = 0;

    public SearchWorker(SearchRule rule, String searchTerm) {
      this.rule = rule;
      this.searchTerm = searchTerm;
    }

    @Override
    public void run() {
      if (!searchAllBases.isSelected()) {
        // Search only the current database:
        for (BibtexEntry entry : panel.getDatabase().getEntries()) {

          boolean hit = rule.applyRule(searchTerm, entry) > 0;
          entry.setSearchHit(hit);
          if (hit) {
            hits++;
          }
        }
      } else {
        // Search all databases:
        for (int i = 0; i < frame.getTabbedPane().getTabCount(); i++) {
          BasePanel p = frame.baseAt(i);
          for (BibtexEntry entry : p.getDatabase().getEntries()) {

            boolean hit = rule.applyRule(searchTerm, entry) > 0;
            entry.setSearchHit(hit);
            if (hit) {
              hits++;
            }
          }
        }
      }
    }

    @Override
    public void update() {
      panel.output(Globals.lang("Searched database. Number of hits") + ": " + hits);

      // Show the result in the chosen way:
      if (searchAllBases.isSelected()) {
        // Search all databases. This means we need to use the search results dialog.
        // Turn off other search mode, if activated:
        if (startedFloatSearch) {
          panel.mainTable.stopShowingFloatSearch();
          startedFloatSearch = false;
        }
        if (startedFilterSearch) {
          panel.stopShowingSearchResults();
          startedFilterSearch = false;
        }
        // Make sure the search dialog is instantiated and cleared:
        instantiateSearchDialog();
        searchDialog.clear();
        for (int i = 0; i < frame.getTabbedPane().getTabCount(); i++) {
          BasePanel p = frame.baseAt(i);
          for (BibtexEntry entry : p.getDatabase().getEntries()) {
            if (entry.isSearchHit()) {
              searchDialog.addEntry(entry, p);
            }
          }
        }
        searchDialog.selectFirstEntry();
        searchDialog.setVisible(true);
      } else if (showResultsInDialog.isSelected()) {
        // Turn off other search mode, if activated:
        if (startedFloatSearch) {
          panel.mainTable.stopShowingFloatSearch();
          startedFloatSearch = false;
        }
        if (startedFilterSearch) {
          panel.stopShowingSearchResults();
          startedFilterSearch = false;
        }
        // Make sure the search dialog is instantiated and cleared:
        instantiateSearchDialog();
        searchDialog.clear();
        for (BibtexEntry entry : panel.getDatabase().getEntries()) {
          if (entry.isSearchHit()) {
            searchDialog.addEntry(entry, panel);
          }
        }
        searchDialog.selectFirstEntry();
        searchDialog.setVisible(true);
      } else if (hideSearch.isSelected()) {
        // Filtering search - removes non-hits from the table:
        if (startedFloatSearch) {
          panel.mainTable.stopShowingFloatSearch();
          startedFloatSearch = false;
        }
        startedFilterSearch = true;
        panel.setSearchMatcher(new SearchMatcher());

      } else {
        // Float search - floats hits to the top of the table:
        if (startedFilterSearch) {
          panel.stopShowingSearchResults();
          startedFilterSearch = false;
        }
        startedFloatSearch = true;
        panel.mainTable.showFloatSearch(new SearchMatcher());
      }

      // Afterwards, select all text in the search field.
      searchField.select(0, searchField.getText().length());
    }
  }

  private void clearSearch() {

    if (panel.isShowingFloatSearch()) {
      startedFloatSearch = false;
      panel.mainTable.stopShowingFloatSearch();
    } else if (panel.isShowingFilterSearch()) {
      startedFilterSearch = false;
      panel.stopShowingSearchResults();
    }

    // clear search means that nothing is searched for
    // even if a word is written in the text field,
    // nothing should be highlighted
    fireSearchlistenerEvent(null);

    // disable "Cancel" button to signal this to the user
    escape.setEnabled(false);
  }

  @Override
  public void itemStateChanged(ItemEvent e) {
    if (e.getSource() == increment) {
      if (startedFilterSearch || startedFloatSearch) {
        clearSearch();
      }
      updateSearchButtonText();

      // Make sure the correct key listener is activated:
      updateKeyListeners();

    } else /*if (e.getSource() == normal)*/ {
      updateSearchButtonText();

      // If this search type is disabled, remove reordering from
      // all databases.
      /*if ((panel != null) && increment.isSelected()) {
          clearSearch();
      } */
    }
  }

  private void repeatIncremental() {
    incSearchPos++;
    if (panel != null) {
      goIncremental();
    }
  }

  /**
   * Used for incremental search. Only activated when incremental is selected.
   *
   * <p>The variable incSearchPos keeps track of which entry was last checked.
   */
  @Override
  public void keyTyped(KeyEvent e) {
    if (e.isControlDown()) {
      return;
    }
    if (panel != null) {
      goIncremental();
    }
  }

  private void goIncremental() {
    incSearch = true;
    escape.setEnabled(true);
    SwingUtilities.invokeLater(
        new Runnable() {

          @Override
          public void run() {
            String text = searchField.getText();

            if (incSearchPos >= panel.getDatabase().getEntryCount()) {
              panel.output(
                  '\''
                      + text
                      + "' : "
                      + Globals.lang("Incremental search failed. Repeat to search from top.")
                      + '.');
              incSearchPos = -1;
              return;
            }

            if (searchField.getText().isEmpty()) {
              return;
            }
            if (incSearchPos < 0) {
              incSearchPos = 0;
            }
            BibtexEntry be = panel.mainTable.getEntryAt(incSearchPos);
            while (!incSearcher.search(text, be)) {
              incSearchPos++;
              if (incSearchPos < panel.getDatabase().getEntryCount()) {
                be = panel.mainTable.getEntryAt(incSearchPos);
              } else {
                panel.output(
                    '\''
                        + text
                        + "' : "
                        + Globals.lang("Incremental search failed. Repeat to search from top."));
                incSearchPos = -1;
                return;
              }
            }
            if (incSearchPos >= 0) {

              panel.selectSingleEntry(incSearchPos);
              panel.output('\'' + text + "' " + Globals.lang("found") + '.');
            }
          }
        });
  }

  @Override
  public void componentClosing() {
    frame.searchToggle.setSelected(false);
    if (panel != null) {
      if (startedFilterSearch || startedFloatSearch) {
        clearSearch();
      }
    }
  }

  @Override
  public void keyPressed(KeyEvent e) {}

  @Override
  public void keyReleased(KeyEvent e) {}

  @Override
  public void caretUpdate(CaretEvent e) {
    if (e.getSource() == searchField) {
      updateSearchButtonText();
    }
  }

  /**
   * Updates the text on the search button to reflect the type of search that will happen on click.
   */
  private void updateSearchButtonText() {
    search.setText(
        isSpecificSearch()
            ? Globals.lang("Search specified field(s)")
            : Globals.lang("Search all fields"));
  }

  private boolean isSpecificSearch() {
    return !increment.isSelected()
        && SearchExpression.isValid(
            caseSensitive.isSelected(), regExpSearch.isSelected(), searchField.getText());
  }

  @Override
  public void setActiveBasePanel(BasePanel panel) {
    super.setActiveBasePanel(panel);
    if (panel != null) {
      escape.setEnabled(panel.isShowingFloatSearch() || panel.isShowingFilterSearch());
    } else {
      escape.setEnabled(false);
    }
  }
}
  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.addButton(ok);
    bsb.addButton(apply);
    bsb.addButton(cancel);
    bsb.addRelatedGap();
    bsb.addButton(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);
  }
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(),
      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>();

  /**
   * @param owner the parent Window (Dialog or Frame)
   * @param frame the JabRef Frame
   * @param panel the currently selected BasePanel
   * @param modal should this dialog be modal?
   * @param metaData The metadata of the current database
   * @param fieldName the field this selector is initialized for. May be null.
   */
  public ContentSelectorDialog2(
      Window owner,
      JabRefFrame frame,
      BasePanel panel,
      boolean modal,
      MetaData metaData,
      String fieldName) {
    super(owner, Globals.lang("Setup selectors"));
    this.setModal(modal);
    this.metaData = metaData;
    this.frame = frame;
    this.panel = panel;
    this.currentField = fieldName;

    // 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();
    Util.bindCloseDialogKeyToCancelAction(this.rootPane, cancel.getAction());
    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.
            }
            if (wordListModel.contains(newVal)) {
              // ensure that word already in list is visible
              index = wordListModel.indexOf(newVal);
              wordList.ensureIndexIsVisible(index);
              return;
            }

            int newIndex = findPos(wordListModel, newVal);
            if (index >= 0) {
              // initiate replacement of selected word
              wordListModel.remove(index);
              if (newIndex > index) {
                // newIndex has to be adjusted after removal of previous entry
                newIndex--;
              }
            }
            wordListModel.add(newIndex, newVal);
            wordList.ensureIndexIsVisible(newIndex);
            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) {
            if (!fieldListModel.get(0).equals(FIELD_FIRST_LINE)) {
              // only add <field name> once
              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() {

          /** Adds the text value to the list */
          public void focusLost(FocusEvent e) {
            String s = fieldNameField.getText();
            fieldNameField.setText("");
            fieldNameField.setEnabled(false);
            if (!FIELD_FIRST_LINE.equals(s) && !"".equals(s)) {
              // user has typed something

              // remove "<first name>" from list
              fieldListModel.remove(0);

              int pos;
              if (fieldListModel.contains(s)) {
                // field already exists, scroll to that field (below)
                pos = fieldListModel.indexOf(s);
              } else {
                // Add new field.
                pos = findPos(fieldListModel, s);
                fieldListModel.add(Math.max(0, pos), s);
              }
              fieldList.setSelectedIndex(pos);
              fieldList.ensureIndexIsVisible(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();
          }
        });

    @SuppressWarnings("serial")
    Action cancelAction =
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            dispose();
          }
        };
    cancelAction.putValue(Action.NAME, Globals.lang("Cancel"));
    cancel.setAction(cancelAction);
  }

  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()) && (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.rebuildAllEntryEditors();
    } else {
      panel.updateAllContentSelectors();
    }
    panel.addContentSelectorValuesToAutoCompleters();
  }

  /** Set the contents of the field selector list. */
  private void setupFieldSelector() {
    fieldListModel.clear();
    SortedSet<String> contents = new TreeSet<String>();
    for (String s : metaData) {
      if (s.startsWith(Globals.SELECTOR_META_PREFIX)) {
        contents.add(s.substring(Globals.SELECTOR_META_PREFIX.length()));
      }
    }
    if (contents.size() == 0) {
      // if nothing was added, put the default fields (as described in the help)
      fieldListModel.addElement("author");
      fieldListModel.addElement("journal");
      fieldListModel.addElement("keywords");
      fieldListModel.addElement("publisher");
    } else {
      for (String s : contents) {
        fieldListModel.addElement(s);
      }
    }

    if (currentField == null) {
      // if dialog is created for the whole database,
      // select the first field to avoid confusions in GUI usage
      fieldList.setSelectedIndex(0);
    } else {
      // a specific field has been chosen at the constructur
      // select this field
      int i = fieldListModel.indexOf(currentField);
      if (i != -1) {
        // field has been found in list, select it
        fieldList.setSelectedIndex(i);
      }
    }
  }

  private void setupWordSelector() {

    // Have we already created a listmodel for this field?
    wordListModel = wordListModels.get(currentField);
    if (wordListModel != null) {
      wordList.setModel(wordListModel);
    } else {
      wordListModel = new DefaultListModel();
      wordList.setModel(wordListModel);
      wordListModels.put(currentField, wordListModel);
      // wordListModel.addElement(WORD_FIRSTLINE_TEXT);
      Vector<String> items = metaData.getData(Globals.SELECTOR_META_PREFIX + currentField);
      if (items != null) {
        wordSet = new TreeSet<String>(items);
        int index = 0;
        for (String s : wordSet) {
          wordListModel.add(index, s);
          index++;
        }
      }
    }
  }

  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 lm.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.addButton(ok);
    bsb.addButton(apply);
    bsb.addButton(cancel);
    bsb.addRelatedGap();
    bsb.addButton(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);
  }
}
  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.
            }
            if (wordListModel.contains(newVal)) {
              // ensure that word already in list is visible
              index = wordListModel.indexOf(newVal);
              wordList.ensureIndexIsVisible(index);
              return;
            }

            int newIndex = findPos(wordListModel, newVal);
            if (index >= 0) {
              // initiate replacement of selected word
              wordListModel.remove(index);
              if (newIndex > index) {
                // newIndex has to be adjusted after removal of previous entry
                newIndex--;
              }
            }
            wordListModel.add(newIndex, newVal);
            wordList.ensureIndexIsVisible(newIndex);
            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) {
            if (!fieldListModel.get(0).equals(FIELD_FIRST_LINE)) {
              // only add <field name> once
              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() {

          /** Adds the text value to the list */
          public void focusLost(FocusEvent e) {
            String s = fieldNameField.getText();
            fieldNameField.setText("");
            fieldNameField.setEnabled(false);
            if (!FIELD_FIRST_LINE.equals(s) && !"".equals(s)) {
              // user has typed something

              // remove "<first name>" from list
              fieldListModel.remove(0);

              int pos;
              if (fieldListModel.contains(s)) {
                // field already exists, scroll to that field (below)
                pos = fieldListModel.indexOf(s);
              } else {
                // Add new field.
                pos = findPos(fieldListModel, s);
                fieldListModel.add(Math.max(0, pos), s);
              }
              fieldList.setSelectedIndex(pos);
              fieldList.ensureIndexIsVisible(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();
          }
        });

    @SuppressWarnings("serial")
    Action cancelAction =
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            dispose();
          }
        };
    cancelAction.putValue(Action.NAME, Globals.lang("Cancel"));
    cancel.setAction(cancelAction);
  }