diff --git a/CHANGELOG.md b/CHANGELOG.md index 70946eed714..8a0202f45b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We changed the default paths for the OpenOffice/LibreOffice binaries to the default path for LibreOffice - We no longer create a new entry editor when selecting a new entry to increase performance. [#3187](https://github.com/JabRef/jabref/pull/3187) - We increased performance and decreased the memory footprint of the entry editor drastically. [#3331](https://github.com/JabRef/jabref/pull/3331) +- Late initialization of the context menus in the entry editor. This improves performance and memory footprint further [#3340](https://github.com/JabRef/jabref/pull/3340) ### Fixed diff --git a/build.gradle b/build.gradle index e9a12b9f7f3..021ff7eb120 100644 --- a/build.gradle +++ b/build.gradle @@ -355,7 +355,7 @@ task media(type: com.install4j.gradle.Install4jTask, dependsOn: "releaseJar") { checkstyle { // do not use other packages for checkstyle, excluding gen(erated) sources checkstyleMain.source = "src/main/java" - toolVersion = '8.0' + toolVersion = '8.3' } checkstyleMain.shouldRunAfter test diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java index 06a4a2179ed..19a98457601 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java @@ -3,6 +3,7 @@ import java.net.URL; import java.util.List; import java.util.ResourceBundle; +import java.util.function.Supplier; import javafx.fxml.Initializable; import javafx.scene.control.ContextMenu; @@ -49,14 +50,16 @@ public EditorTextArea(String text) { } /** - * Adds the given list of menu items to the context menu. + * Adds the given list of menu items to the context menu. The usage of {@link Supplier} prevents that the menus need + * to be instantiated at this point. They are populated when the user needs them which prevents many unnecessary + * allocations when the main table is just scrolled with the entry editor open. */ - public void addToContextMenu(List items) { + public void addToContextMenu(Supplier> items) { TextAreaSkin customContextSkin = new TextAreaSkin(this) { @Override public void populateContextMenu(ContextMenu contextMenu) { super.populateContextMenu(contextMenu); - contextMenu.getItems().addAll(0, items); + contextMenu.getItems().addAll(0, items.get()); } }; setSkin(customContextSkin); diff --git a/src/main/java/org/jabref/gui/fieldeditors/IdentifierEditor.java b/src/main/java/org/jabref/gui/fieldeditors/IdentifierEditor.java index 12d546554a6..2e0bc0a457f 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/IdentifierEditor.java +++ b/src/main/java/org/jabref/gui/fieldeditors/IdentifierEditor.java @@ -1,14 +1,11 @@ package org.jabref.gui.fieldeditors; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.Parent; import javafx.scene.control.Button; -import javafx.scene.control.MenuItem; import javafx.scene.control.Tooltip; import javafx.scene.layout.HBox; @@ -43,12 +40,11 @@ public IdentifierEditor(String fieldName, TaskExecutor taskExecutor, DialogServi lookupIdentifierButton.setTooltip( new Tooltip(Localization.lang("Look up %0", FieldName.getDisplayName(fieldName)))); - List menuItems = new ArrayList<>(); if (fieldName.equalsIgnoreCase(FieldName.DOI)) { - menuItems.addAll(EditorMenus.getDOIMenu(textArea)); + textArea.addToContextMenu(EditorMenus.getDOIMenu(textArea)); + } else { + textArea.addToContextMenu(EditorMenus.getDefaultMenu(textArea)); } - menuItems.addAll(EditorMenus.getDefaultMenu(textArea)); - textArea.addToContextMenu(menuItems); new EditorValidator(preferences).configureValidation(viewModel.getFieldValidator().getValidationStatus(), textArea); } @@ -82,5 +78,4 @@ private void lookupIdentifier(ActionEvent event) { private void openExternalLink(ActionEvent event) { viewModel.openExternalLink(); } - } diff --git a/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java b/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java index 62387c56798..8c7c7698cda 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java +++ b/src/main/java/org/jabref/gui/fieldeditors/contextmenu/EditorMenus.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; import javax.swing.AbstractAction; import javax.swing.Action; @@ -14,42 +15,73 @@ import javafx.scene.control.Tooltip; import org.jabref.gui.actions.CopyDoiUrlAction; +import org.jabref.gui.fieldeditors.EditorTextArea; import org.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter; import org.jabref.logic.l10n.Localization; +/** + * Provides context menus for the text fields of the entry editor. Note that we use {@link Supplier} to prevent an early + * instantiation of the menus. Therefore, they are attached to each text field but instantiation happens on the first + * right-click of the user in that field. The late instantiation is done by {@link + * EditorTextArea#addToContextMenu(java.util.function.Supplier)}. + */ public class EditorMenus { - public static List getDefaultMenu(TextArea textArea) { - List menuItems = new ArrayList<>(5); - menuItems.add(new CaseChangeMenu(textArea.textProperty())); - menuItems.add(new ConversionMenu(textArea.textProperty())); - menuItems.add(new SeparatorMenuItem()); - menuItems.add(new ProtectedTermsMenu(textArea)); - menuItems.add(new SeparatorMenuItem()); - return menuItems; + /** + * The default menu that contains functions for changing the case of text and doing several conversions. + * + * @param textArea text-area that this menu will be connected to + * @return default context menu available for most text fields + */ + public static Supplier> getDefaultMenu(TextArea textArea) { + return () -> { + List menuItems = new ArrayList<>(5); + menuItems.add(new CaseChangeMenu(textArea.textProperty())); + menuItems.add(new ConversionMenu(textArea.textProperty())); + menuItems.add(new SeparatorMenuItem()); + menuItems.add(new ProtectedTermsMenu(textArea)); + menuItems.add(new SeparatorMenuItem()); + return menuItems; + }; } - public static List getNameMenu(TextArea textArea) { - CustomMenuItem normalizeNames = new CustomMenuItem(new Label(Localization.lang("Normalize to BibTeX name format"))); - normalizeNames.setOnAction(event -> textArea.setText(new NormalizeNamesFormatter().format(textArea.getText()))); - Tooltip toolTip = new Tooltip(Localization.lang("If possible, normalize this list of names to conform to standard BibTeX name formatting")); - Tooltip.install(normalizeNames.getContent(),toolTip); + /** + * The default context menu with a specific menu for normalizing person names regarding to BibTex rules. + * + * @param textArea text-area that this menu will be connected to + * @return menu containing items of the default menu and an item for normalizing person names + */ + public static Supplier> getNameMenu(TextArea textArea) { + return () -> { + CustomMenuItem normalizeNames = new CustomMenuItem(new Label(Localization.lang("Normalize to BibTeX name format"))); + normalizeNames.setOnAction(event -> textArea.setText(new NormalizeNamesFormatter().format(textArea.getText()))); + Tooltip toolTip = new Tooltip(Localization.lang("If possible, normalize this list of names to conform to standard BibTeX name formatting")); + Tooltip.install(normalizeNames.getContent(), toolTip); - List menuItems = new ArrayList<>(6); - menuItems.add(normalizeNames); - menuItems.addAll(getDefaultMenu(textArea)); - - return menuItems; + List menuItems = new ArrayList<>(6); + menuItems.add(normalizeNames); + menuItems.addAll(getDefaultMenu(textArea).get()); + return menuItems; + }; } - public static List getDOIMenu(TextArea textArea) { - AbstractAction copyDoiUrlAction = new CopyDoiUrlAction(textArea); - MenuItem copyDoiUrlMenuItem = new MenuItem((String) copyDoiUrlAction.getValue(Action.NAME)); - copyDoiUrlMenuItem.setOnAction(event -> copyDoiUrlAction.actionPerformed(null)); + /** + * The default context menu with a specific menu copying a DOI URL. + * + * @param textArea text-area that this menu will be connected to + * @return menu containing items of the default menu and an item for copying a DOI URL + */ + public static Supplier> getDOIMenu(TextArea textArea) { + return () -> { + AbstractAction copyDoiUrlAction = new CopyDoiUrlAction(textArea); + MenuItem copyDoiUrlMenuItem = new MenuItem((String) copyDoiUrlAction.getValue(Action.NAME)); + copyDoiUrlMenuItem.setOnAction(event -> copyDoiUrlAction.actionPerformed(null)); - List menuItems = new ArrayList<>(); - menuItems.add(copyDoiUrlMenuItem); - menuItems.add(new SeparatorMenuItem()); - return menuItems; + List menuItems = new ArrayList<>(); + menuItems.add(copyDoiUrlMenuItem); + menuItems.add(new SeparatorMenuItem()); + menuItems.addAll(getDefaultMenu(textArea).get()); + return menuItems; + }; } }