diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java index 05439dd4e58..00a7fe44565 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditor.java @@ -115,30 +115,31 @@ public class EntryEditor extends JPanel implements EntryContainer { private static final Log LOGGER = LogFactory.getLog(EntryEditor.class); - // A reference to the entry this object works on. + /** A reference to the entry this object works on. */ private BibEntry entry; - // The currently displayed type + /** The currently displayed type */ private final String displayedBibEntryType; - // The action concerned with closing the window. - private final CloseAction closeAction; - - // The action that deletes the current entry, and closes the editor. + /** The action concerned with closing the window. */ + private final CloseAction closeAction = new CloseAction(); + /** The action that deletes the current entry, and closes the editor. */ private final DeleteAction deleteAction = new DeleteAction(); - // Actions for switching to next/previous entry. + /** The action for switching to the next entry. */ private final AbstractAction nextEntryAction = new NextEntryAction(); + /** The action for switching to the previous entry. */ private final AbstractAction prevEntryAction = new PrevEntryAction(); - // The action concerned with storing a field value. - private final StoreFieldAction storeFieldAction; + /** The action concerned with storing a field value. */ + private final StoreFieldAction storeFieldAction = new StoreFieldAction(); - // The actions concerned with switching the panels. + /** The action for switching to the next tab */ private final SwitchLeftAction switchLeftAction = new SwitchLeftAction(); + /** The action for switching to the previous tab */ private final SwitchRightAction switchRightAction = new SwitchRightAction(); - // The action which generates a bibtexkey for this entry. - private final GenerateKeyAction generateKeyAction; + /** The action which generates a BibTeX key for this entry. */ + private final GenerateKeyAction generateKeyAction = new GenerateKeyAction(); // UGLY HACK to have a pointer to the fileListEditor to call autoSetLinks() private FileListEditor fileListEditor; @@ -158,25 +159,33 @@ public class EntryEditor extends JPanel implements EntryContainer { private final BasePanel panel; - private boolean updateSource = true; // This can be set to false to stop the source - private boolean movingToDifferentEntry; // Indicates that we are about to go to the next or previous entry + /** + * This can be set to false to stop the source text area from getting updated. This is used in cases where the + * source couldn't be parsed, and the user is given the option to edit it. + */ + private boolean updateSource = true; + /** Indicates that we are about to go to the next or previous entry */ + private boolean movingToDifferentEntry; private boolean validEntry = true; private final List tabs = new ArrayList<>(); - // text area from getting updated. This is used in cases where the source - // couldn't be parsed, and the user is given the option to edit it. private boolean lastFieldAccepted = true; - private boolean lastSourceAccepted = true; // This indicates whether the last attempt - // at parsing the source was successful. It is used to determine whether the - // dialog should close; it should stay open if the user received an error - // message about the source, whatever he or she chose to do about it. - private String lastSourceStringAccepted; // This is used to prevent double fields. - // These values can be used to calculate the preferred height for the form. - // reqW starts at 1 because it needs room for the bibtex key field. - private int sourceIndex = -1; // The index the source panel has in tabbed. - private final HelpAction helpAction; + /** + * This indicates whether the last attempt at parsing the source was successful. It is used to determine whether + * the dialog should close; it should stay open if the user received an error message about the source, + * whatever he or she chose to do about it. + */ + private boolean lastSourceAccepted = true; + + /** This is used to prevent double updates after editing source. */ + private String lastSourceStringAccepted; + + /** The index the source panel has in tabbed. */ + private int sourceIndex = -1; + + private final HelpAction helpAction = new HelpAction(HelpFile.ENTRY_EDITOR, IconTheme.JabRefIcon.HELP.getIcon()); private final UndoAction undoAction = new UndoAction(); @@ -197,10 +206,6 @@ public EntryEditor(JabRefFrame frame, BasePanel panel, BibEntry entry) { displayedBibEntryType = entry.getType(); - helpAction = new HelpAction(HelpFile.ENTRY_EDITOR, IconTheme.JabRefIcon.HELP.getIcon()); - closeAction = new CloseAction(); - generateKeyAction = new GenerateKeyAction(); - storeFieldAction = new StoreFieldAction(); writeXmp = new WriteXMPEntryEditorAction(panel, this); BorderLayout borderLayout = new BorderLayout(); @@ -231,19 +236,13 @@ private void setupFieldPanels() { addRequiredTab(type); // optional fields - List displayedOptionalFields = new ArrayList<>(); Set deprecatedFields = new HashSet<>(EntryConverter.FIELD_ALIASES_TEX_TO_LTX.keySet()); Set usedOptionalFieldsDeprecated = new HashSet<>(deprecatedFields); if ((type.getOptionalFields() != null) && !type.getOptionalFields().isEmpty()) { if (!frame.getCurrentBasePanel().getBibDatabaseContext().isBiblatexMode()) { - displayedOptionalFields.addAll(type.getOptionalFields()); - addOptionalTab(type); } else { - displayedOptionalFields.addAll(type.getPrimaryOptionalFields()); - displayedOptionalFields.addAll(type.getSecondaryOptionalFields()); - addOptionalTab(type); deprecatedFields.add(FieldName.YEAR); @@ -328,7 +327,7 @@ private void addSourceTab() { srcPanel.setName(panelName); tabbed.addTab(panelName, IconTheme.JabRefIcon.SOURCE.getSmallIcon(), srcPanel, toolTip); tabs.add(srcPanel); - sourceIndex = tabs.size() - 1; // Set the sourceIndex variable. + sourceIndex = tabs.size() - 1; srcPanel.setFocusCycleRoot(true); } @@ -394,8 +393,7 @@ private void setupToolBar() { toolBar.setMargin(new Insets(0, 0, 0, 2)); - // The toolbar carries all the key bindings that are valid for the whole - // window. + // The toolbar carries all the key bindings that are valid for the whole window. ActionMap actionMap = toolBar.getActionMap(); InputMap inputMap = toolBar.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); @@ -458,22 +456,6 @@ private void setupToolBar() { add(leftPan, BorderLayout.WEST); } - /** - * Rebuild the field tabs. This is called e.g. when a new content selector - * has been added. - */ - public void rebuildPanels() { - // Remove change listener, because the rebuilding causes meaningless - // events and trouble: - tabbed.removeChangeListener(tabListener); - - setupFieldPanels(); - // Add the change listener again: - tabbed.addChangeListener(tabListener); - revalidate(); - repaint(); - } - /** * getExtra checks the field name against InternalBibtexFields.getFieldExtras(name). * If the name has an entry, the proper component to be shown is created and @@ -549,7 +531,7 @@ void addSearchListener(SearchQueryHighlightListener listener) { panel.frame().getGlobalSearchBar().getSearchQueryHighlightObservable().addSearchListener(listener); } - void removeSearchListeners() { + private void removeSearchListeners() { for (SearchQueryHighlightListener listener : searchListeners) { panel.frame().getGlobalSearchBar().getSearchQueryHighlightObservable().removeSearchListener(listener); } @@ -563,25 +545,12 @@ public void updateSource() { source.setText(srcString); lastSourceStringAccepted = srcString; - ////////////////////////////////////////////////////////// // Set the current Entry to be selected. - // Fixes the bug of losing selection after, e.g. - // an autogeneration of a BibTeX key. - // - ILC (16/02/2010) - - ////////////////////////////////////////////////////////// - SwingUtilities.invokeLater(() -> { - final int row = panel.getMainTable().findEntry(entry); - if (row >= 0) { - if (panel.getMainTable().getSelectedRowCount() == 0) { - panel.getMainTable().setRowSelectionInterval(row, row); - } - panel.getMainTable().ensureVisible(row); - } - }); + // Fixes the bug of losing selection after, e.g. an autogeneration of a BibTeX key. + SwingUtilities.invokeLater(() -> panel.highlightEntry(entry)); } catch (IOException ex) { source.setText(ex.getMessage() + "\n\n" + - Localization.lang("Correct the entry, and " - + "reopen editor to display/edit source.")); + Localization.lang("Correct the entry, and reopen editor to display/edit source.")); source.setEditable(false); LOGGER.debug("Incorrect entry", ex); } @@ -589,7 +558,7 @@ public void updateSource() { } } - public static String getSourceString(BibEntry entry, BibDatabaseMode type) throws IOException { + private static String getSourceString(BibEntry entry, BibDatabaseMode type) throws IOException { StringWriter stringWriter = new StringWriter(200); LatexFieldFormatter formatter = LatexFieldFormatter .buildIgnoreHashes(Globals.prefs.getLatexFieldFormatterPreferences()); @@ -650,7 +619,7 @@ private void activateVisible() { Object activeTab = tabs.get(tabbed.getSelectedIndex()); if (activeTab instanceof EntryEditorTab) { - ((EntryEditorTab) activeTab).activate(); + ((EntryEditorTab) activeTab).focus(); } else { source.requestFocus(); } @@ -678,17 +647,6 @@ public void setEnabled(boolean enabled) { } - /** - * Centers the given row, and highlights it. - * - * @param row an int value - */ - private void scrollTo(int row) { - movingToDifferentEntry = true; - panel.getMainTable().setRowSelectionInterval(row, row); - panel.getMainTable().ensureVisible(row); - } - /** * Makes sure the current edit is stored. */ @@ -702,15 +660,6 @@ public void storeCurrentEdit() { } } - /** - * Returns the index of the active (visible) panel. - * - * @return an int value - */ - public int getVisiblePanel() { - return tabbed.getSelectedIndex(); - } - /** * Returns the name of the currently selected component. */ @@ -736,35 +685,11 @@ public void setFocusToField(String fieldName) { EntryEditorTab entryEditorTab = (EntryEditorTab) tab; setVisiblePanel(entryEditorTab.getTabTitle()); entryEditorTab.setActive(fieldName); - entryEditorTab.activate(); + entryEditorTab.focus(); } } } - /** - * Updates this editor to show the given entry, regardless of type - * correspondence. - * - * @param switchEntry a BibEntry value - */ - public synchronized void switchTo(BibEntry switchEntry) { - storeCurrentEdit(); - - // Remove this instance as property listener for the entry: - this.entry.unregisterListener(this); - - this.entry = switchEntry; - - // Register as property listener for the new entry: - this.entry.registerListener(this); - - updateAllFields(); - validateAllFields(); - updateSource(); - panel.newEntryShowing(switchEntry); - - } - private boolean storeSource() { BibtexParser bibtexParser = new BibtexParser(Globals.prefs.getImportFormatPreferences()); try { @@ -856,12 +781,7 @@ private boolean storeSource() { // TODO: does updating work properly after source stored? panel.markBaseChanged(); - SwingUtilities.invokeLater(() -> { - final int row = panel.getMainTable().findEntry(entry); - if (row >= 0) { - panel.getMainTable().ensureVisible(row); - } - }); + SwingUtilities.invokeLater(() -> panel.highlightEntry(entry)); return true; } catch (IllegalStateException | IOException ex) { @@ -911,21 +831,11 @@ public void updateAllFields() { } } - /** - * Removes the "invalid field" color from all text areas. - */ - public void validateAllFields() { - for (Object tab : tabs) { - if (tab instanceof EntryEditorTab) { - ((EntryEditorTab) tab).validateAllFields(); - } - } - } - /** * Update the JTextArea when a field has changed. */ @Subscribe + @SuppressWarnings("unused") public void listen(FieldChangedEvent fieldChangedEvent) { String newValue = fieldChangedEvent.getNewValue() == null ? "" : fieldChangedEvent.getNewValue(); if (SwingUtilities.isEventDispatchThread()) { @@ -1001,17 +911,10 @@ public void paintComponent(Graphics g) { } } + /** + * Focus listener that fires the storeFieldAction when a TextArea loses focus. + */ private class FieldListener extends FocusAdapter { - - /* - * Focus listener that fires the storeFieldAction when a TextArea - * loses focus. - */ - @Override - public void focusGained(FocusEvent e) { - // Do nothing - } - @Override public void focusLost(FocusEvent event) { if (!event.isTemporary()) { @@ -1023,10 +926,8 @@ public void focusLost(FocusEvent event) { private class TabListener implements ChangeListener { @Override public void stateChanged(ChangeEvent event) { - // We tell the editor tab to update all its fields. - // This makes sure they are updated even if the tab we - // just left contained one - // or more of the same fields as this one: + // We tell the editor tab to update all its fields. This makes sure they are updated even if the tab we + // just left contained one or more of the same fields as this one: SwingUtilities.invokeLater(() -> { Object activeTab = tabs.get(tabbed.getSelectedIndex()); if (activeTab instanceof EntryEditorTab) { @@ -1088,7 +989,6 @@ public CloseAction() { @Override public void actionPerformed(ActionEvent e) { close(); - } } @@ -1185,12 +1085,13 @@ public void actionPerformed(ActionEvent event) { && toSet.equals(entry.getField(fieldEditor.getFieldName()).orElse(null))); } - if (set) { + if (!set) { + // We set the field and label color. + fieldEditor.setValidBackgroundColor(); + } else { try { - // The following statement attempts to write the - // new contents into a StringWriter, and this will - // cause an IOException if the field is not - // properly formatted. If that happens, the field + // The following statement attempts to write the new contents into a StringWriter, and this will + // cause an IOException if the field is not properly formatted. If that happens, the field // is not stored and the textarea turns red. if (toSet != null) { new LatexFieldFormatter(Globals.prefs.getLatexFieldFormatterPreferences()).format(toSet, @@ -1241,10 +1142,6 @@ public void actionPerformed(ActionEvent event) { requestFocus(); } } - } else { - // set == false - // We set the field and label color. - fieldEditor.setValidBackgroundColor(); } if (fieldEditor.getTextComponent().hasFocus()) { fieldEditor.setBackground(GUIGlobals.ACTIVE_EDITOR_COLOR); @@ -1256,12 +1153,7 @@ public void actionPerformed(ActionEvent event) { // Make sure we scroll to the entry if it moved in the table. // Should only be done if this editor is currently showing: if (!movingAway && isShowing()) { - SwingUtilities.invokeLater(() -> { - final int row = panel.getMainTable().findEntry(entry); - if (row >= 0) { - panel.getMainTable().ensureVisible(row); - } - }); + SwingUtilities.invokeLater(() -> panel.highlightEntry(entry)); } } } @@ -1334,14 +1226,12 @@ public void actionPerformed(ActionEvent e) { // 1. get BibEntry for selected index (already have) // 2. update label - // Store the current edit in case this action is called during the - // editing of a field: + // Store the current edit in case this action is called during the editing of a field: storeCurrentEdit(); // This is a partial clone of net.sf.jabref.gui.BasePanel.setupActions().new AbstractWorker() {...}.run() - // this updates the table automatically, on close, but not - // within the tab + // this updates the table automatically, on close, but not within the tab Optional oldValue = entry.getCiteKeyOptional(); if (oldValue.isPresent()) { diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java index a72ed5b6da4..d5762a8f294 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTab.java @@ -93,10 +93,7 @@ public EntryEditorTab(JabRefFrame frame, BasePanel panel, List fields, E setupPanel(frame, panel, addKeyField, compressed, tabTitle); - /* - * The following line makes sure focus cycles inside tab instead of - * being lost to other parts of the frame: - */ + // The following line makes sure focus cycles inside tab instead of being lost to other parts of the frame: scrollPane.setFocusCycleRoot(true); } @@ -214,37 +211,26 @@ private void setupPanel(JabRefFrame frame, BasePanel bPanel, boolean addKeyField } private String getPrompt(String field) { - String prompt = ""; + + Set fieldProperties = InternalBibtexFields.getFieldProperties(field); + if (fieldProperties.contains(FieldProperty.PERSON_NAMES)) { + return String.format("%1$s and %1$s and others", Localization.lang("Firstname Lastname")); + } else if (fieldProperties.contains(FieldProperty.DOI)) { + return "10.ORGANISATION/ID"; + } else if (fieldProperties.contains(FieldProperty.DATE)) { + return "YYYY-MM-DD"; + } + switch (field) { - case FieldName.AUTHOR: - prompt = String.format("%1$s and %1$s and others", Localization.lang("Firstname Lastname")); - break; - case FieldName.EDITOR: - prompt = String.format("%1$s and %1$s and others", Localization.lang("Firstname Lastname")); - break; - case FieldName.YEAR: - prompt = String.format("YYYY"); - break; - case FieldName.DATE: - prompt = String.format("YYYY-MM-DD"); - break; - case FieldName.URLDATE: - prompt = String.format("YYYY-MM-DD"); - break; - case FieldName.EVENTDATE: - prompt = String.format("YYYY-MM-DD"); - break; - case FieldName.ORIGDATE: - prompt = String.format("YYYY-MM-DD"); - break; - case FieldName.URL: - prompt = String.format("https://"); - break; - default: - prompt = ""; - break; + case FieldName.YEAR: + return "YYYY"; + case FieldName.MONTH: + return "MM or #mmm#"; + case FieldName.URL: + return "https://"; } - return prompt; + + return ""; } private BibEntry getEntry() { @@ -262,8 +248,7 @@ private boolean isFieldModified(FieldEditor fieldEditor) { } public void markIfModified(FieldEditor fieldEditor) { - // Only mark as changed if not already is and the field was indeed - // modified + // Only mark as changed if not already is and the field was indeed modified if (!updating && !basePanel.isModified() && isFieldModified(fieldEditor)) { markBaseChanged(); } @@ -276,7 +261,7 @@ private void markBaseChanged() { /** * Only sets the activeField variable but does not focus it. *

- * Call activate afterwards. + * If you want to focus it call {@link #focus()} afterwards. * * @param fieldEditor */ @@ -298,11 +283,8 @@ public List getFields() { return fields; } - public void activate() { + public void focus() { if (activeField != null) { - /** - * Corrected to fix [ 1594169 ] Entry editor: navigation between panels - */ activeField.getTextComponent().requestFocus(); } } @@ -314,8 +296,6 @@ public void updateAll() { setEntry(getEntry()); } - - public void setEntry(BibEntry entry) { try { updating = true; @@ -357,19 +337,6 @@ public boolean updateField(String field, String content) { return true; } - public void validateAllFields() { - for (Map.Entry stringFieldEditorEntry : editors.entrySet()) { - FieldEditor ed = stringFieldEditorEntry.getValue(); - ed.updateFontColor(); - ed.setEnabled(true); - if (((Component) ed).hasFocus()) { - ed.setActiveBackgroundColor(); - } else { - ed.setValidBackgroundColor(); - } - } - } - public void setEnabled(boolean enabled) { for (FieldEditor editor : editors.values()) { editor.setEnabled(enabled); diff --git a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabFocusListener.java b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabFocusListener.java index 4344b8b1da4..5e46972359c 100644 --- a/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabFocusListener.java +++ b/src/main/java/net/sf/jabref/gui/entryeditor/EntryEditorTabFocusListener.java @@ -13,16 +13,19 @@ import net.sf.jabref.gui.fieldeditors.FieldEditor; -/* - * Focus listener that fires the storeFieldAction when a TextArea loses - * focus. + +/** + * Focus listener that fires the storeFieldAction when a TextArea loses focus. */ class EntryEditorTabFocusListener implements FocusListener { + /** The component this DocumentListener is currently tied to */ private JTextComponent textComponent; + /** The listener which gets tied to each TextComponent (and removed) */ private DocumentListener documentListener; + /** The EntryEditorTab this FocusListener is currently tied to */ private final EntryEditorTab entryEditorTab; @@ -32,7 +35,6 @@ public EntryEditorTabFocusListener(final EntryEditorTab entryEditorTab) { @Override public void focusGained(FocusEvent event) { - synchronized (this) { if (textComponent != null) { textComponent.getDocument().removeDocumentListener(documentListener); @@ -41,15 +43,9 @@ public void focusGained(FocusEvent event) { } if (event.getSource() instanceof JTextComponent) { - textComponent = (JTextComponent) event.getSource(); - /** - * [ 1553552 ] Not properly detecting changes to flag as - * changed - */ documentListener = new DocumentListener() { - - void fire() { + private void fire() { if (textComponent.isFocusOwner()) { entryEditorTab.markIfModified((FieldEditor) textComponent); } @@ -72,16 +68,14 @@ public void removeUpdate(DocumentEvent e) { }; textComponent.getDocument().addDocumentListener(documentListener); - /** - * Makes the vertical scroll panel view follow the focus - */ - Component scrollPane = textComponent.getParent().getParent(); - if (scrollPane instanceof JScrollPane) { - JScrollPane componentPane = (JScrollPane) scrollPane; - Component cPane = componentPane.getParent(); - if (cPane instanceof JPanel) { - JPanel panel = (JPanel) cPane; - Rectangle bounds = componentPane.getBounds(); + // Makes the vertical scroll panel view follow the focus + Component component = textComponent.getParent().getParent(); + if (component instanceof JScrollPane) { + JScrollPane scrollPane = (JScrollPane) component; + Component scrollPaneParent = scrollPane.getParent(); + if (scrollPaneParent instanceof JPanel) { + JPanel panel = (JPanel) scrollPaneParent; + Rectangle bounds = scrollPane.getBounds(); panel.scrollRectToVisible(bounds); } } @@ -90,7 +84,6 @@ public void removeUpdate(DocumentEvent e) { } entryEditorTab.setActive((FieldEditor) event.getSource()); - } @Override @@ -106,4 +99,5 @@ public void focusLost(FocusEvent event) { entryEditorTab.getParent().updateField(event.getSource()); } } + }