Skip to content

Commit 8dabe6d

Browse files
committed
Merge remote-tracking branch 'upstream/master' into exportPdf
* upstream/master: Fix NPE when calling with bib file as cmd argument (#3343) update mockito-core from 2.10.0 -> 2.11.0 (#3338) Remove underscore in Localized messages (#3336) Localisation: French: new entries translated (#3337) Refactoring: Lazy init of all editor tabs (#3333)
2 parents 5e1117a + c928e20 commit 8dabe6d

27 files changed

+259
-315
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
3434
- We improved the way metadata is updated in remote databases. [#3235](https://github.com/JabRef/jabref/issues/3235)
3535
- We improved font rendering of the Entry Editor for Linux based systems [#3295](https://github.com/JabRef/jabref/issues/3295)
3636
- We fixed an issue where JabRef would freeze when trying to replace the original entry after a merge with new information from identifiers like DOI/ISBN etc. [3294](https://github.com/JabRef/jabref/issues/3294)
37-
37+
- We fixed an issue where JabRef would not show the translated content at some points, although there existed a translation
3838
### Removed
3939

4040

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ dependencies {
130130
compile group: 'com.microsoft.azure', name: 'applicationinsights-logging-log4j2', version: '1.0.9'
131131

132132
testCompile 'junit:junit:4.12'
133-
testCompile 'org.mockito:mockito-core:2.10.0'
133+
testCompile 'org.mockito:mockito-core:2.11.0'
134134
testCompile 'com.github.tomakehurst:wiremock:2.8.0'
135135
testCompile 'org.assertj:assertj-swing-junit:3.8.0'
136136
testCompile 'org.reflections:reflections:0.9.11'

src/main/java/org/jabref/cli/ArgumentProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ private void regenerateBibtexKeys(List<ParserResult> loaded) {
519519
database, entry, Globals.prefs.getBibtexKeyPatternPreferences());
520520
}
521521
} else {
522-
LOGGER.info(Localization.lang("No meta data present in BIB_file. Cannot regenerate BibTeX keys"));
522+
LOGGER.info(Localization.lang("No meta data present in BIB file. Cannot regenerate BibTeX keys"));
523523
}
524524
}
525525
}

src/main/java/org/jabref/gui/EntryTypeDialog.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ protected void done() {
331331
} else if (searchID.trim().isEmpty()) {
332332
JOptionPane.showMessageDialog(frame, Localization.lang("The given search ID was empty."), Localization.lang("Empty search ID"), JOptionPane.WARNING_MESSAGE);
333333
} else if (!fetcherException) {
334-
JOptionPane.showMessageDialog(frame, Localization.lang("Fetcher_'%0'_did_not_find_an_entry_for_id_'%1'.", fetcher.getName(), searchID) + "\n" + fetcherExceptionMessage, Localization.lang("No files found."), JOptionPane.WARNING_MESSAGE);
334+
JOptionPane.showMessageDialog(frame, Localization.lang("Fetcher '%0' did not find an entry for id '%1'.", fetcher.getName(), searchID) + "\n" + fetcherExceptionMessage, Localization.lang("No files found."), JOptionPane.WARNING_MESSAGE);
335335
} else {
336336
JOptionPane.showMessageDialog(frame,
337337
Localization.lang("Error while fetching from %0", fetcher.getName()) + "." + "\n" + fetcherExceptionMessage,

src/main/java/org/jabref/gui/desktop/JabRefDesktop.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public static void openBrowserShowPopup(String url) {
290290
LOGGER.error("Could not open browser", exception);
291291
String couldNotOpenBrowser = Localization.lang("Could not open browser.");
292292
String openManually = Localization.lang("Please open %0 manually.", url);
293-
String copiedToClipboard = Localization.lang("The_link_has_been_copied_to_the_clipboard.");
293+
String copiedToClipboard = Localization.lang("The link has been copied to the clipboard.");
294294
JabRefGUI.getMainFrame().output(couldNotOpenBrowser);
295295
JOptionPane.showMessageDialog(JabRefGUI.getMainFrame(), couldNotOpenBrowser + "\n" + openManually + "\n" +
296296
copiedToClipboard, couldNotOpenBrowser, JOptionPane.ERROR_MESSAGE);
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package org.jabref.gui.entryeditor;
22

3+
import java.util.List;
4+
35
import javafx.scene.control.Tooltip;
46

5-
import org.jabref.gui.BasePanel;
67
import org.jabref.gui.IconTheme;
7-
import org.jabref.gui.JabRefFrame;
8+
import org.jabref.gui.autocompleter.SuggestionProviders;
89
import org.jabref.logic.l10n.Localization;
10+
import org.jabref.model.database.BibDatabaseContext;
911
import org.jabref.model.entry.BibEntry;
1012
import org.jabref.model.entry.EntryType;
1113

1214
public class DeprecatedFieldsTab extends FieldsEditorTab {
13-
public DeprecatedFieldsTab(JabRefFrame frame, BasePanel basePanel, EntryType entryType, EntryEditor parent, BibEntry entry) {
14-
super(frame, basePanel, entryType.getDeprecatedFields(), parent, false, false, entry);
15+
public DeprecatedFieldsTab(BibDatabaseContext databaseContext, SuggestionProviders suggestionProviders) {
16+
super(false, databaseContext, suggestionProviders);
1517

1618
setText(Localization.lang("Deprecated fields"));
1719
setTooltip(new Tooltip(Localization.lang("Show deprecated BibTeX fields")));
1820
setGraphic(IconTheme.JabRefIcon.OPTIONAL.getGraphicNode());
1921
}
22+
23+
@Override
24+
protected List<String> determineFieldsToShow(BibEntry entry, EntryType entryType) {
25+
return entryType.getDeprecatedFields();
26+
}
2027
}

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

Lines changed: 66 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.awt.event.MouseAdapter;
1313
import java.awt.event.MouseEvent;
1414
import java.util.ArrayList;
15+
import java.util.LinkedList;
1516
import java.util.List;
1617
import java.util.Map;
1718
import java.util.Objects;
@@ -106,11 +107,6 @@ public class EntryEditor extends JPanel implements EntryContainer {
106107

107108
private static final Log LOGGER = LogFactory.getLog(EntryEditor.class);
108109

109-
/**
110-
* The default index number of the other fields tab
111-
*/
112-
private static final int OTHER_FIELDS_DEFAULTPOSITION = 4;
113-
114110
/**
115111
* A reference to the entry this object works on.
116112
*/
@@ -152,14 +148,14 @@ public class EntryEditor extends JPanel implements EntryContainer {
152148
private final RedoAction redoAction = new RedoAction();
153149
private final List<SearchQueryHighlightListener> searchListeners = new ArrayList<>();
154150
private final JFXPanel container;
151+
private final List<EntryEditorTab> tabs;
155152

156153
/**
157154
* Indicates that we are about to go to the next or previous entry
158155
*/
159156
private final BooleanProperty movingToDifferentEntry = new SimpleBooleanProperty();
160157
private EntryType entryType;
161158
private SourceTab sourceTab;
162-
private final BorderLayout layout;
163159
private TypeLabel typeLabel;
164160

165161
public EntryEditor(BasePanel panel) {
@@ -168,28 +164,34 @@ public EntryEditor(BasePanel panel) {
168164

169165
writeXmp = new WriteXMPEntryEditorAction(panel, this);
170166

171-
layout = new BorderLayout();
167+
BorderLayout layout = new BorderLayout();
172168
setLayout(layout);
173169

174170
container = OS.LINUX ? new CustomJFXPanel() : new JFXPanel();
175171
// Create type-label
176172
typeLabel = new TypeLabel("");
177173
setupToolBar();
178-
DefaultTaskExecutor.runInJavaFXThread(() ->
179-
container.setScene(new Scene(tabbed))
180-
);
174+
DefaultTaskExecutor.runInJavaFXThread(() -> {
175+
tabbed.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
176+
tabbed.setStyle(
177+
"-fx-font-size: " + Globals.prefs.getFontSizeFX() + "pt;" +
178+
"-fx-open-tab-animation: NONE; -fx-close-tab-animation: NONE;");
179+
container.setScene(new Scene(tabbed));
180+
});
181181
add(container, BorderLayout.CENTER);
182182

183183
DefaultTaskExecutor.runInJavaFXThread(() -> {
184184
EasyBind.subscribe(tabbed.getSelectionModel().selectedItemProperty(), tab -> {
185185
EntryEditorTab activeTab = (EntryEditorTab) tab;
186186
if (activeTab != null) {
187-
activeTab.notifyAboutFocus();
187+
activeTab.notifyAboutFocus(entry);
188188
}
189189
});
190190
});
191191

192192
setupKeyBindings();
193+
194+
tabs = createTabs();
193195
}
194196

195197
public void setEntry(BibEntry entry) {
@@ -201,73 +203,29 @@ public void setEntry(BibEntry entry) {
201203
displayedBibEntryType = entry.getType();
202204

203205
DefaultTaskExecutor.runInJavaFXThread(() -> {
204-
addTabs(this.getVisibleTabName());
205-
206-
tabbed.setStyle("-fx-font-size: " + Globals.prefs.getFontSizeFX() + "pt;");
206+
recalculateVisibleTabs();
207+
if (Globals.prefs.getBoolean(JabRefPreferences.DEFAULT_SHOW_SOURCE)) {
208+
tabbed.getSelectionModel().select(sourceTab);
209+
}
207210

211+
// Notify current tab about new entry
212+
EntryEditorTab selectedTab = (EntryEditorTab) tabbed.getSelectionModel().getSelectedItem();
213+
selectedTab.notifyAboutFocus(entry);
208214
});
215+
209216
TypedBibEntry typedEntry = new TypedBibEntry(entry, panel.getBibDatabaseContext().getMode());
210217
typeLabel.setText(typedEntry.getTypeForDisplay());
211218
}
212219

213220
@Subscribe
214221
public synchronized void listen(FieldAddedOrRemovedEvent event) {
215-
// other field deleted -> update other fields tab
216-
if (OtherFieldsTab.isOtherField(entryType, event.getFieldName())) {
217-
DefaultTaskExecutor.runInJavaFXThread(() -> rebuildOtherFieldsTab());
218-
}
222+
// Rebuild entry editor based on new information (e.g. hide/add tabs)
223+
recalculateVisibleTabs();
219224
}
220225

221226
@Subscribe
222227
public synchronized void listen(EntryChangedEvent event) {
223-
DefaultTaskExecutor.runInJavaFXThread(() -> sourceTab.updateSourcePane());
224-
}
225-
226-
private void rebuildOtherFieldsTab() {
227-
int index = -1;
228-
boolean isOtherFieldsTabSelected = false;
229-
230-
// find tab index and selection status
231-
for (Tab tab : tabbed.getTabs()) {
232-
if (tab instanceof OtherFieldsTab) {
233-
index = tabbed.getTabs().indexOf(tab);
234-
isOtherFieldsTabSelected = tabbed.getSelectionModel().isSelected(index);
235-
break;
236-
}
237-
}
238-
239-
// rebuild tab at index and with prior selection status
240-
if (index != -1) {
241-
readdOtherFieldsTab(index, isOtherFieldsTabSelected);
242-
} else {
243-
// maybe the tab wasn't there but needs to be now
244-
addNewOtherFieldsTabIfNeeded();
245-
}
246-
}
247-
248-
private void readdOtherFieldsTab(int index, boolean isOtherFieldsTabSelected) {
249-
tabbed.getTabs().remove(index);
250-
OtherFieldsTab tab = new OtherFieldsTab(frame, panel, entryType, this, entry);
251-
// if there are no other fields left, no need to readd the tab
252-
if (!(tab.getFields().size() == 0)) {
253-
tabbed.getTabs().add(index, tab);
254-
}
255-
// select the new tab if it was selected before
256-
if (isOtherFieldsTabSelected) {
257-
tabbed.getSelectionModel().select(tab);
258-
}
259-
}
260-
261-
private void addNewOtherFieldsTabIfNeeded() {
262-
OtherFieldsTab tab = new OtherFieldsTab(frame, panel, entryType, this, entry);
263-
if (tab.getFields().size() > 0) {
264-
// add it at default index, but that is just a guess
265-
tabbed.getTabs().add(OTHER_FIELDS_DEFAULTPOSITION, tab);
266-
}
267-
}
268-
269-
private void selectLastUsedTab(String lastTabName) {
270-
tabbed.getTabs().stream().filter(tab -> lastTabName.equals(tab.getText())).findFirst().ifPresent(tab -> tabbed.getSelectionModel().select(tab));
228+
DefaultTaskExecutor.runInJavaFXThread(() -> sourceTab.updateSourcePane(entry));
271229
}
272230

273231
/**
@@ -335,53 +293,62 @@ public void close() {
335293
closeAction.actionPerformed(null);
336294
}
337295

338-
private void addTabs(String lastTabName) {
296+
private void recalculateVisibleTabs() {
297+
List<Tab> visibleTabs = tabs.stream().filter(tab -> tab.shouldShow(entry)).collect(Collectors.toList());
339298

340-
List<EntryEditorTab> tabs = new ArrayList<>();
299+
// Start of ugly hack:
300+
// We need to find out, which tabs will be shown and which not and remove and re-add the appropriate tabs
301+
// to the editor. We don't want to simply remove all and re-add the complete list of visible tabs, because
302+
// the tabs give an ugly animation the looks like all tabs are shifting in from the right.
303+
// This hack is required since tabbed.getTabs().setAll(visibleTabs) changes the order of the tabs in the editor
304+
305+
// First, remove tabs that we do not want to show
306+
List<EntryEditorTab> toBeRemoved = tabs.stream().filter(tab -> !tab.shouldShow(entry)).collect(Collectors.toList());
307+
tabbed.getTabs().removeAll(toBeRemoved);
308+
309+
// Next add all the visible tabs (if not already present) at the right position
310+
for (int i = 0; i < visibleTabs.size(); i++) {
311+
Tab toBeAdded = visibleTabs.get(i);
312+
Tab shown = null;
313+
if (i < tabbed.getTabs().size()) {
314+
shown = tabbed.getTabs().get(i);
315+
}
316+
317+
if (!toBeAdded.equals(shown)) {
318+
tabbed.getTabs().add(i, toBeAdded);
319+
}
320+
}
321+
}
322+
323+
private List<EntryEditorTab> createTabs() {
324+
List<EntryEditorTab> tabs = new LinkedList<>();
341325

342326
// Required fields
343-
tabs.add(new RequiredFieldsTab(frame, panel, entryType, this, entry));
327+
tabs.add(new RequiredFieldsTab(panel.getDatabaseContext(), panel.getSuggestionProviders()));
344328

345329
// Optional fields
346-
tabs.add(new OptionalFieldsTab(frame, panel, entryType, this, entry));
347-
tabs.add(new OptionalFields2Tab(frame, panel, entryType, this, entry));
348-
tabs.add(new DeprecatedFieldsTab(frame, panel, entryType, this, entry));
330+
tabs.add(new OptionalFieldsTab(panel.getDatabaseContext(), panel.getSuggestionProviders()));
331+
tabs.add(new OptionalFields2Tab(panel.getDatabaseContext(), panel.getSuggestionProviders()));
332+
tabs.add(new DeprecatedFieldsTab(panel.getDatabaseContext(), panel.getSuggestionProviders()));
349333

350334
// Other fields
351-
tabs.add(new OtherFieldsTab(frame, panel, entryType, this, entry));
335+
tabs.add(new OtherFieldsTab(panel.getDatabaseContext(), panel.getSuggestionProviders()));
352336

353337
// General fields from preferences
354338
EntryEditorTabList tabList = Globals.prefs.getEntryEditorTabList();
355339
for (int i = 0; i < tabList.getTabCount(); i++) {
356-
FieldsEditorTab newFieldsEditorTab = new FieldsEditorTab(frame, panel, tabList.getTabFields(i), this, false,
357-
false, entry);
358-
newFieldsEditorTab.setText(tabList.getTabName(i));
359-
tabs.add(newFieldsEditorTab);
340+
tabs.add(new UserDefinedFieldsTab(tabList.getTabName(i), tabList.getTabFields(i), panel.getDatabaseContext(), panel.getSuggestionProviders()));
360341
}
361342

362343
// Special tabs
363-
tabs.add(new MathSciNetTab(entry));
364-
tabs.add(new FileAnnotationTab(panel.getAnnotationCache(), entry));
365-
tabs.add(new RelatedArticlesTab(entry));
344+
tabs.add(new MathSciNetTab());
345+
tabs.add(new FileAnnotationTab(panel.getAnnotationCache()));
346+
tabs.add(new RelatedArticlesTab(Globals.prefs));
366347

367348
// Source tab
368-
sourceTab = new SourceTab(panel, entry, movingToDifferentEntry);
349+
sourceTab = new SourceTab(panel, movingToDifferentEntry);
369350
tabs.add(sourceTab);
370-
371-
tabbed.getTabs().clear();
372-
for (EntryEditorTab tab : tabs) {
373-
if (tab.shouldShow()) {
374-
tabbed.getTabs().add(tab);
375-
}
376-
}
377-
tabbed.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
378-
379-
if (Globals.prefs.getBoolean(JabRefPreferences.DEFAULT_SHOW_SOURCE)) {
380-
tabbed.getSelectionModel().select(sourceTab);
381-
} else {
382-
selectLastUsedTab(lastTabName);
383-
}
384-
351+
return tabs;
385352
}
386353

387354
public String getDisplayedBibEntryType() {
@@ -539,11 +506,10 @@ public void setVisibleTab(String name) {
539506

540507
public void setFocusToField(String fieldName) {
541508
for (Tab tab : tabbed.getTabs()) {
542-
if ((tab instanceof FieldsEditorTab) && ((FieldsEditorTab) tab).getFields().contains(fieldName)) {
509+
if ((tab instanceof FieldsEditorTab) && ((FieldsEditorTab) tab).determineFieldsToShow(entry, entryType).contains(fieldName)) {
543510
FieldsEditorTab fieldsEditorTab = (FieldsEditorTab) tab;
544511
tabbed.getSelectionModel().select(tab);
545-
fieldsEditorTab.setActive(fieldName);
546-
fieldsEditorTab.focus();
512+
fieldsEditorTab.requestFocus(fieldName);
547513
}
548514
}
549515
}
@@ -808,9 +774,7 @@ public void actionPerformed(ActionEvent event) {
808774
// Should only be done if this editor is currently showing:
809775
// don't select the current entry again (eg use BasePanel#highlightEntry} in case another entry was selected)
810776
if (!movingAway && isShowing()) {
811-
SwingUtilities.invokeLater(() -> {
812-
panel.getMainTable().ensureVisible(entry);
813-
});
777+
SwingUtilities.invokeLater(() -> panel.getMainTable().ensureVisible(entry));
814778
}
815779
}
816780

0 commit comments

Comments
 (0)