-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Show compound patterns in the dropdown for citation key patterns #12580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
82b8e7d
7c0092c
7dc7da0
69d92d5
c0ff147
9ddcfa5
4a90978
8099176
437c9cd
c73970d
0dffef6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package org.jabref.gui.commonfxcontrols; | ||
|
||
import java.util.ArrayList; | ||
import java.util.LinkedHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
@@ -16,9 +17,13 @@ | |
import javafx.scene.control.cell.TextFieldTableCell; | ||
import javafx.stage.Window; | ||
|
||
import org.jabref.gui.DialogService; | ||
import org.jabref.logic.citationkeypattern.CitationKeyPattern; | ||
import org.jabref.logic.l10n.Localization; | ||
|
||
import com.airhacks.afterburner.injection.Injector; | ||
import jakarta.inject.Inject; | ||
|
||
public class CitationKeyPatternSuggestionCell extends TextFieldTableCell<CitationKeyPatternsPanelItemModel, String> { | ||
private final CitationKeyPatternSuggestionTextField searchField; | ||
|
||
|
@@ -60,11 +65,22 @@ public void updateItem(String item, boolean empty) { | |
} | ||
|
||
static class CitationKeyPatternSuggestionTextField extends TextField { | ||
// Maximum number of entries that can be displayed in the popup menu. | ||
private static final int MAX_ENTRIES = 7; | ||
|
||
private final int ALL_PATTERNS_POSITION = 0; | ||
|
||
private final List<String> citationKeyPatterns; | ||
private final ContextMenu suggestionsList; | ||
private int selectionCount = 0; | ||
private int heightOfMenuItem; | ||
private final StringBuilder selectedPatterns = new StringBuilder(); | ||
|
||
@Inject private DialogService dialogService; | ||
|
||
public CitationKeyPatternSuggestionTextField(List<String> citationKeyPatterns) { | ||
Injector.registerExistingAndInject(this); | ||
|
||
this.citationKeyPatterns = new ArrayList<>(citationKeyPatterns); | ||
this.suggestionsList = new ContextMenu(); | ||
// Initial reasonable estimate before the menu items are populated. We overwrite this dynamically | ||
|
@@ -93,11 +109,14 @@ private void setListener() { | |
} else { | ||
suggestionsList.hide(); | ||
} | ||
createCompoundPatternsSubMenu(); | ||
} | ||
}); | ||
|
||
focusedProperty().addListener((observable, oldValue, newValue) -> { | ||
suggestionsList.hide(); | ||
if (!newValue) { | ||
suggestionsList.hide(); | ||
} | ||
Comment on lines
+117
to
+119
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code should follow the fail-fast principle by immediately handling invalid states and returning early instead of nesting logic inside else branches. |
||
}); | ||
} | ||
|
||
|
@@ -112,7 +131,6 @@ private void populatePopup(List<String> searchResult) { | |
for (int i = 0; i < count; i++) { | ||
final String result = searchResult.get(i); | ||
Label entryLabel = new Label(result); | ||
entryLabel.setPrefWidth(getWidth()); | ||
|
||
CustomMenuItem item = new CustomMenuItem(entryLabel, true); | ||
item.setHideOnClick(false); | ||
|
@@ -131,7 +149,8 @@ private void populatePopup(List<String> searchResult) { | |
} | ||
|
||
suggestionsList.getItems().clear(); | ||
suggestionsList.getItems().add(createPatternsSubMenu()); | ||
suggestionsList.getItems().add(ALL_PATTERNS_POSITION, createPatternsSubMenu()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of magic numbers like ALL_PATTERNS_POSITION should be avoided. Consider using a more descriptive constant or comment. |
||
suggestionsList.getItems().add(ALL_PATTERNS_POSITION + 1, createCompoundPatternsSubMenu()); | ||
suggestionsList.getItems().addAll(menuItems); | ||
|
||
if (!menuItems.isEmpty()) { | ||
|
@@ -163,13 +182,12 @@ private Menu createPatternsSubMenu() { | |
CitationKeyPattern.getAllPatterns().stream() | ||
.collect(Collectors.groupingBy(CitationKeyPattern::getCategory)); | ||
|
||
Map<CitationKeyPattern.Category, String> categoryNames = Map.of( | ||
CitationKeyPattern.Category.AUTHOR_RELATED, Localization.lang("Author related"), | ||
CitationKeyPattern.Category.EDITOR_RELATED, Localization.lang("Editor related"), | ||
CitationKeyPattern.Category.TITLE_RELATED, Localization.lang("Title related"), | ||
CitationKeyPattern.Category.OTHER_FIELDS, Localization.lang("Other fields"), | ||
CitationKeyPattern.Category.BIBENTRY_FIELDS, Localization.lang("Entry fields") | ||
); | ||
Map<CitationKeyPattern.Category, String> categoryNames = new LinkedHashMap<>(); | ||
categoryNames.put(CitationKeyPattern.Category.AUTHOR_RELATED, Localization.lang("Author related")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The localization strings should be prefixed with % for proper localization handling in JabRef. |
||
categoryNames.put(CitationKeyPattern.Category.EDITOR_RELATED, Localization.lang("Editor related")); | ||
categoryNames.put(CitationKeyPattern.Category.TITLE_RELATED, Localization.lang("Title related")); | ||
categoryNames.put(CitationKeyPattern.Category.OTHER_FIELDS, Localization.lang("Other fields")); | ||
categoryNames.put(CitationKeyPattern.Category.BIBENTRY_FIELDS, Localization.lang("Entry fields")); | ||
|
||
for (Map.Entry<CitationKeyPattern.Category, String> entry : categoryNames.entrySet()) { | ||
CitationKeyPattern.Category category = entry.getKey(); | ||
|
@@ -191,5 +209,62 @@ private Menu createPatternsSubMenu() { | |
} | ||
return patternsSubMenu; | ||
} | ||
|
||
private Menu createCompoundPatternsSubMenu() { | ||
Menu compoundPatternsSubMenu = new Menu(Localization.lang("Create compound pattern")); | ||
|
||
Map<CitationKeyPattern.Category, List<CitationKeyPattern>> categorizedPatterns = | ||
CitationKeyPattern.getAllPatterns().stream() | ||
.collect(Collectors.groupingBy(CitationKeyPattern::getCategory)); | ||
|
||
Map<CitationKeyPattern.Category, String> categoryNames = new LinkedHashMap<>(); | ||
categoryNames.put(CitationKeyPattern.Category.AUTHOR_RELATED, Localization.lang("Author related")); | ||
categoryNames.put(CitationKeyPattern.Category.EDITOR_RELATED, Localization.lang("Editor related")); | ||
categoryNames.put(CitationKeyPattern.Category.TITLE_RELATED, Localization.lang("Title related")); | ||
categoryNames.put(CitationKeyPattern.Category.OTHER_FIELDS, Localization.lang("Other fields")); | ||
categoryNames.put(CitationKeyPattern.Category.BIBENTRY_FIELDS, Localization.lang("Entry fields")); | ||
|
||
for (Map.Entry<CitationKeyPattern.Category, String> entry : categoryNames.entrySet()) { | ||
CitationKeyPattern.Category category = entry.getKey(); | ||
String categoryName = entry.getValue(); | ||
|
||
Menu categoryMenu = new Menu(categoryName); | ||
List<CitationKeyPattern> patterns = categorizedPatterns.getOrDefault(category, List.of()); | ||
|
||
for (CitationKeyPattern pattern : patterns) { | ||
MenuItem menuItem = new MenuItem(pattern.stringRepresentation()); | ||
menuItem.setOnAction(event -> { | ||
setText(pattern.stringRepresentation()); | ||
positionCaret(pattern.stringRepresentation().length()); | ||
suggestionsList.hide(); | ||
|
||
if (selectionCount == 0) { | ||
selectionCount++; | ||
selectedPatterns.append(pattern.stringRepresentation()); | ||
setText(selectedPatterns.toString()); | ||
positionCaret(selectedPatterns.length()); | ||
dialogService.notify(Localization.lang("Select one more item to create a compound pattern.")); | ||
if (getScene() != null) { | ||
suggestionsList.getItems().remove(ALL_PATTERNS_POSITION); | ||
double screenX = localToScreen(0, 0).getX(); | ||
double screenY = localToScreen(0, 0).getY() + getHeight(); | ||
suggestionsList.show(this, screenX, screenY); | ||
} | ||
} else if (selectionCount == 1) { | ||
selectedPatterns.append("_").append(pattern.stringRepresentation()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how this whole things works. Somewhere, it should be explained, how |
||
setText(selectedPatterns.toString()); | ||
positionCaret(selectedPatterns.length()); | ||
suggestionsList.hide(); | ||
selectionCount = 0; | ||
selectedPatterns.setLength(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not understandable at first sight - comment needed. |
||
} | ||
}); | ||
categoryMenu.getItems().add(menuItem); | ||
} | ||
compoundPatternsSubMenu.getItems().add(categoryMenu); | ||
} | ||
|
||
return compoundPatternsSubMenu; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StringBuilder is used for concatenating strings, which can be replaced with StringJoiner for better readability and maintainability.