Skip to content

Commit ec912dc

Browse files
ZachCrawSiedlerchr
andauthored
Feat/field jumping 12276 (#14120)
* feat(JabRef #12276): Adding in Keybind enum for JUMP_TO_FIELD * feat(JabRef #12276): Initialising JumpToField command * docs(JabRef #12276): Adding in english localisation for JUMP to FIELD entries * feat(JabRef #12276): Creating base fxml for JUMP to field box * feat(JabRef #12276): FXML action class to search through loaded fields * feat(JabRef #12276): Class to extract fieldNames for comparison and autocorrect * feat(JabRef #12276): Implementing field search handling within entryEditor * docs(JabRef #12276): Explained addition in CHANGELOG.md * docs(JabRef #12276): Fixing missing blank line in CHANGELOG * fix(JabRef #12276): Reverting docs deletion to include implementation spec * fix(JabRef #12276): Fixing frame focusing and scene hierarchy. * fix(JabRef #12276): Removing necessary initialisation. * docs(JabRef #12276): Changing function names to reflect "select" pattern. --------- Co-authored-by: Christoph <[email protected]>
1 parent 29bdb09 commit ec912dc

File tree

7 files changed

+169
-11
lines changed

7 files changed

+169
-11
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
1111

1212
### Added
1313

14+
- We added a "Jump to Field" dialog (`Ctrl+J`) to quickly search for and navigate to any field across all tabs. [#12276](https://github.com/JabRef/jabref/issues/12276).
15+
- We made the "Configure API key" option in the Web Search preferences tab searchable via preferences search. [#13929](https://github.com/JabRef/jabref/issues/13929)
16+
- We added the integrity check to the jabkit cli application. [#13848](https://github.com/JabRef/jabref/issues/13848)
17+
- We added support for Cygwin-file paths on a Windows Operating System. [#13274](https://github.com/JabRef/jabref/issues/13274)
18+
- We fixed an issue where "Print preview" would throw a `NullPointerException` if no printers were available. [#13708](https://github.com/JabRef/jabref/issues/13708)
1419
- We added "IEEE" as another option for parsing plain text citations. [#14233](github.com/JabRef/jabref/pull/14233)
1520
- We added automatic date-based groups that create year/month/day subgroups from an entry’s date fields. [#10822](https://github.com/JabRef/jabref/issues/10822)
1621
- We added `doi-to-bibtex` to `JabKit`. [#14244](https://github.com/JabRef/jabref/pull/14244)

jabgui/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import javafx.scene.input.KeyEvent;
2929
import javafx.scene.input.TransferMode;
3030
import javafx.scene.layout.BorderPane;
31+
import javafx.stage.Modality;
3132

3233
import org.jabref.gui.DialogService;
3334
import org.jabref.gui.LibraryTab;
@@ -171,15 +172,14 @@ public EntryEditor(Supplier<LibraryTab> tabSupplier, UndoAction undoAction, Redo
171172
});
172173

173174
stateManager.getSelectedEntries().addListener((InvalidationListener) _ -> {
174-
if (stateManager.getSelectedEntries().isEmpty()) {
175-
// [impl->req~entry-editor.keep-showing~1]
176-
// No change in the entry editor
177-
// We allow users to edit the "old" entry
178-
} else {
179-
setCurrentlyEditedEntry(stateManager.getSelectedEntries().getFirst());
180-
}
181-
}
182-
);
175+
if (stateManager.getSelectedEntries().isEmpty()) {
176+
// [impl->req~entry-editor.keep-showing~1]
177+
// No change in the entry editor
178+
// We allow users to edit the "old" entry
179+
} else {
180+
setCurrentlyEditedEntry(stateManager.getSelectedEntries().getFirst());
181+
}
182+
});
183183

184184
EasyBind.listen(preferences.getPreviewPreferences().showPreviewAsExtraTabProperty(),
185185
(_, _, newValue) -> {
@@ -248,6 +248,10 @@ private void setupKeyBindings() {
248248
tabSupplier.get().selectPreviousEntry();
249249
event.consume();
250250
break;
251+
case JUMP_TO_FIELD:
252+
selectFieldDialog();
253+
event.consume();
254+
break;
251255
case HELP:
252256
new HelpAction(HelpFile.ENTRY_EDITOR, dialogService, preferences.getExternalApplicationsPreferences()).execute();
253257
event.consume();
@@ -268,6 +272,15 @@ private void setupKeyBindings() {
268272
});
269273
}
270274

275+
public void selectFieldDialog() {
276+
if (getCurrentlyEditedEntry() == null) {
277+
return;
278+
}
279+
JumpToFieldDialog dialog = new JumpToFieldDialog(this);
280+
dialog.initModality(Modality.NONE);
281+
dialog.show();
282+
}
283+
271284
@FXML
272285
private void close() {
273286
stateManager.getEditorShowing().set(false);
@@ -420,6 +433,10 @@ public BibEntry getCurrentlyEditedEntry() {
420433
return currentlyEditedEntry;
421434
}
422435

436+
public List<EntryEditorTab> getAllPossibleTabs() {
437+
return allPossibleTabs;
438+
}
439+
423440
public void setCurrentlyEditedEntry(@NonNull BibEntry currentlyEditedEntry) {
424441
if (Objects.equals(this.currentlyEditedEntry, currentlyEditedEntry)) {
425442
return;
@@ -434,15 +451,26 @@ public void setCurrentlyEditedEntry(@NonNull BibEntry currentlyEditedEntry) {
434451
}
435452

436453
typeSubscription = EasyBind.subscribe(this.currentlyEditedEntry.typeProperty(), _ -> {
437-
typeLabel.setText(new TypedBibEntry(currentlyEditedEntry, tabSupplier.get().getBibDatabaseContext().getMode()).getTypeForDisplay());
454+
typeLabel.setText(new TypedBibEntry(this.currentlyEditedEntry, tabSupplier.get().getBibDatabaseContext().getMode()).getTypeForDisplay());
438455
adaptVisibleTabs();
439456
setupToolBar();
440-
getSelectedTab().notifyAboutFocus(currentlyEditedEntry);
457+
getSelectedTab().notifyAboutFocus(this.currentlyEditedEntry);
441458
});
442459

460+
typeLabel.setText(new TypedBibEntry(currentlyEditedEntry, tabSupplier.get().getBibDatabaseContext().getMode()).getTypeForDisplay());
461+
462+
adaptVisibleTabs();
463+
464+
setupToolBar();
465+
443466
if (preferences.getEntryEditorPreferences().showSourceTabByDefault()) {
444467
tabbed.getSelectionModel().select(sourceTab);
445468
}
469+
470+
EntryEditorTab selectedTab = getSelectedTab();
471+
if (selectedTab != null) {
472+
Platform.runLater(() -> selectedTab.notifyAboutFocus(currentlyEditedEntry));
473+
}
446474
}
447475

448476
private EntryEditorTab getSelectedTab() {
@@ -492,6 +520,10 @@ private void fetchAndMerge(EntryBasedFetcher fetcher) {
492520
new FetchAndMergeEntry(tabSupplier.get().getBibDatabaseContext(), taskExecutor, preferences, dialogService, undoManager).fetchAndMerge(currentlyEditedEntry, fetcher);
493521
}
494522

523+
public void selectField(String fieldName) {
524+
setFocusToField(org.jabref.model.entry.field.FieldFactory.parseField(fieldName));
525+
}
526+
495527
public void setFocusToField(Field field) {
496528
UiTaskExecutor.runInJavaFXThread(() -> {
497529
getTabContainingField(field).ifPresentOrElse(
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.jabref.gui.entryeditor;
2+
3+
import javafx.application.Platform;
4+
import javafx.fxml.FXML;
5+
import javafx.scene.control.Button;
6+
import javafx.scene.control.ButtonType;
7+
import javafx.scene.control.TextField;
8+
9+
import org.jabref.gui.util.BaseDialog;
10+
import org.jabref.logic.l10n.Localization;
11+
12+
import com.airhacks.afterburner.views.ViewLoader;
13+
import org.controlsfx.control.textfield.TextFields;
14+
15+
public class JumpToFieldDialog extends BaseDialog<Void> {
16+
@FXML private TextField searchField;
17+
private final EntryEditor entryEditor;
18+
private JumpToFieldViewModel viewModel;
19+
20+
public JumpToFieldDialog(EntryEditor entryEditor) {
21+
this.entryEditor = entryEditor;
22+
this.setTitle(Localization.lang("Jump to field"));
23+
24+
ViewLoader.view(this)
25+
.load()
26+
.setAsDialogPane(this);
27+
28+
this.getDialogPane().getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL);
29+
30+
this.setResultConverter(button -> {
31+
if (button == ButtonType.OK) {
32+
jumpToSelectedField();
33+
}
34+
return null;
35+
});
36+
37+
Platform.runLater(() -> searchField.requestFocus());
38+
}
39+
40+
@FXML
41+
private void initialize() {
42+
viewModel = new JumpToFieldViewModel(this.entryEditor);
43+
searchField.textProperty().bindBidirectional(viewModel.searchTextProperty());
44+
TextFields.bindAutoCompletion(searchField, viewModel.getFieldNames());
45+
46+
searchField.setOnAction(event -> {
47+
Button okButton = (Button) getDialogPane().lookupButton(ButtonType.OK);
48+
if (okButton != null) {
49+
okButton.fire();
50+
}
51+
event.consume();
52+
});
53+
}
54+
55+
private void jumpToSelectedField() {
56+
String selectedField = searchField.getText();
57+
58+
if (selectedField != null && !selectedField.isEmpty()) {
59+
String fieldToJumpTo = selectedField.toLowerCase();
60+
entryEditor.selectField(fieldToJumpTo);
61+
}
62+
}
63+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.jabref.gui.entryeditor;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.stream.Collectors;
6+
7+
import javafx.beans.property.SimpleStringProperty;
8+
import javafx.beans.property.StringProperty;
9+
10+
import org.jabref.gui.AbstractViewModel;
11+
import org.jabref.model.entry.field.Field;
12+
13+
public class JumpToFieldViewModel extends AbstractViewModel {
14+
15+
private final StringProperty searchText = new SimpleStringProperty("");
16+
private final EntryEditor entryEditor;
17+
18+
public JumpToFieldViewModel(EntryEditor entryEditor) {
19+
this.entryEditor = entryEditor;
20+
}
21+
22+
public StringProperty searchTextProperty() {
23+
return searchText;
24+
}
25+
26+
public List<String> getFieldNames() {
27+
if (entryEditor.getCurrentlyEditedEntry() == null) {
28+
return Collections.emptyList();
29+
}
30+
31+
List<String> fieldNames = entryEditor.getAllPossibleTabs().stream()
32+
.filter(FieldsEditorTab.class::isInstance)
33+
.map(FieldsEditorTab.class::cast)
34+
.flatMap(tab -> tab.getShownFields().stream())
35+
.map(Field::getName)
36+
.distinct()
37+
.sorted()
38+
.collect(Collectors.toList());
39+
return fieldNames;
40+
}
41+
}

jabgui/src/main/java/org/jabref/gui/keyboard/KeyBinding.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public enum KeyBinding {
3636
CLOSE("Close dialog", Localization.lang("Close dialog"), "Esc", KeyBindingCategory.VIEW),
3737
COPY("Copy", Localization.lang("Copy"), "ctrl+C", KeyBindingCategory.EDIT),
3838
COPY_TITLE("Copy title", Localization.lang("Copy title"), "ctrl+shift+alt+T", KeyBindingCategory.EDIT),
39+
JUMP_TO_FIELD("Jump to field", Localization.lang("Jump to field"), "ctrl+J", KeyBindingCategory.EDIT),
3940

4041
// We migrated from "Copy \\cite{citation key}" to "Copy citation key with configured cite command", therefore we keep the "old string" for backwards comppatibility
4142
COPY_CITE_CITATION_KEY("Copy \\cite{citation key}", Localization.lang("Copy citation key with configured cite command"), "ctrl+K", KeyBindingCategory.EDIT),
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import javafx.scene.control.DialogPane?>
4+
<?import javafx.scene.control.TextField?>
5+
<?import javafx.scene.layout.VBox?>
6+
7+
<DialogPane prefWidth="300" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
8+
fx:controller="org.jabref.gui.entryeditor.JumpToFieldDialog">
9+
<content>
10+
<VBox>
11+
<TextField fx:id="searchField" promptText="%Type a field name"/>
12+
</VBox>
13+
</content>
14+
</DialogPane>

jablib/src/main/resources/l10n/JabRef_en.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ Duplicate\ citation\ key=Duplicate citation key
436436
Citation\ key\ '%0'\ to\ select\ not\ found\ in\ open\ libraries.=Citation key '%0' to select not found in open libraries.
437437

438438
Jump\ to\ entry\ in\ library=Jump to entry in library
439+
Jump\ to\ field=Jump to field
439440

440441
Autolink\ files\ with\ names\ starting\ with\ the\ citation\ key=Autolink files with names starting with the citation key
441442
Autolink\ only\ files\ that\ match\ the\ citation\ key=Autolink only files that match the citation key
@@ -2372,6 +2373,7 @@ Title\ of\ the\ work.=Title of the work.
23722373
Total\ number\ of\ pages\ of\ the\ work.=Total number of pages of the work.
23732374
Total\ number\ of\ volumes\ of\ a\ multi-volume\ work.=Total number of volumes of a multi-volume work.
23742375
Type\ of\ the\ eprint\ identifier,\ e.g.,\ the\ name\ of\ the\ archive,\ repository,\ service,\ or\ system\ the\ eprint\ field\ refers\ to.=Type of the eprint identifier, e.g., the name of the archive, repository, service, or system the eprint field refers to.
2376+
Type\ a\ field\ name=Type a field name
23752377
URL\ of\ an\ online\ publication.=URL of an online publication.
23762378
Volume\ of\ a\ multi-volume\ book\ or\ a\ periodical.=Volume of a multi-volume book or a periodical.
23772379
Year\ of\ publication.=Year of publication.

0 commit comments

Comments
 (0)