12
12
import java .awt .event .MouseAdapter ;
13
13
import java .awt .event .MouseEvent ;
14
14
import java .util .ArrayList ;
15
+ import java .util .LinkedList ;
15
16
import java .util .List ;
16
17
import java .util .Map ;
17
18
import java .util .Objects ;
@@ -106,11 +107,6 @@ public class EntryEditor extends JPanel implements EntryContainer {
106
107
107
108
private static final Log LOGGER = LogFactory .getLog (EntryEditor .class );
108
109
109
- /**
110
- * The default index number of the other fields tab
111
- */
112
- private static final int OTHER_FIELDS_DEFAULTPOSITION = 4 ;
113
-
114
110
/**
115
111
* A reference to the entry this object works on.
116
112
*/
@@ -152,14 +148,14 @@ public class EntryEditor extends JPanel implements EntryContainer {
152
148
private final RedoAction redoAction = new RedoAction ();
153
149
private final List <SearchQueryHighlightListener > searchListeners = new ArrayList <>();
154
150
private final JFXPanel container ;
151
+ private final List <EntryEditorTab > tabs ;
155
152
156
153
/**
157
154
* Indicates that we are about to go to the next or previous entry
158
155
*/
159
156
private final BooleanProperty movingToDifferentEntry = new SimpleBooleanProperty ();
160
157
private EntryType entryType ;
161
158
private SourceTab sourceTab ;
162
- private final BorderLayout layout ;
163
159
private TypeLabel typeLabel ;
164
160
165
161
public EntryEditor (BasePanel panel ) {
@@ -168,28 +164,34 @@ public EntryEditor(BasePanel panel) {
168
164
169
165
writeXmp = new WriteXMPEntryEditorAction (panel , this );
170
166
171
- layout = new BorderLayout ();
167
+ BorderLayout layout = new BorderLayout ();
172
168
setLayout (layout );
173
169
174
170
container = OS .LINUX ? new CustomJFXPanel () : new JFXPanel ();
175
171
// Create type-label
176
172
typeLabel = new TypeLabel ("" );
177
173
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
+ });
181
181
add (container , BorderLayout .CENTER );
182
182
183
183
DefaultTaskExecutor .runInJavaFXThread (() -> {
184
184
EasyBind .subscribe (tabbed .getSelectionModel ().selectedItemProperty (), tab -> {
185
185
EntryEditorTab activeTab = (EntryEditorTab ) tab ;
186
186
if (activeTab != null ) {
187
- activeTab .notifyAboutFocus ();
187
+ activeTab .notifyAboutFocus (entry );
188
188
}
189
189
});
190
190
});
191
191
192
192
setupKeyBindings ();
193
+
194
+ tabs = createTabs ();
193
195
}
194
196
195
197
public void setEntry (BibEntry entry ) {
@@ -201,73 +203,29 @@ public void setEntry(BibEntry entry) {
201
203
displayedBibEntryType = entry .getType ();
202
204
203
205
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
+ }
207
210
211
+ // Notify current tab about new entry
212
+ EntryEditorTab selectedTab = (EntryEditorTab ) tabbed .getSelectionModel ().getSelectedItem ();
213
+ selectedTab .notifyAboutFocus (entry );
208
214
});
215
+
209
216
TypedBibEntry typedEntry = new TypedBibEntry (entry , panel .getBibDatabaseContext ().getMode ());
210
217
typeLabel .setText (typedEntry .getTypeForDisplay ());
211
218
}
212
219
213
220
@ Subscribe
214
221
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 ();
219
224
}
220
225
221
226
@ Subscribe
222
227
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 ));
271
229
}
272
230
273
231
/**
@@ -335,53 +293,62 @@ public void close() {
335
293
closeAction .actionPerformed (null );
336
294
}
337
295
338
- private void addTabs (String lastTabName ) {
296
+ private void recalculateVisibleTabs () {
297
+ List <Tab > visibleTabs = tabs .stream ().filter (tab -> tab .shouldShow (entry )).collect (Collectors .toList ());
339
298
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 <>();
341
325
342
326
// Required fields
343
- tabs .add (new RequiredFieldsTab (frame , panel , entryType , this , entry ));
327
+ tabs .add (new RequiredFieldsTab (panel . getDatabaseContext (), panel . getSuggestionProviders () ));
344
328
345
329
// 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 () ));
349
333
350
334
// Other fields
351
- tabs .add (new OtherFieldsTab (frame , panel , entryType , this , entry ));
335
+ tabs .add (new OtherFieldsTab (panel . getDatabaseContext (), panel . getSuggestionProviders () ));
352
336
353
337
// General fields from preferences
354
338
EntryEditorTabList tabList = Globals .prefs .getEntryEditorTabList ();
355
339
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 ()));
360
341
}
361
342
362
343
// 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 ));
366
347
367
348
// Source tab
368
- sourceTab = new SourceTab (panel , entry , movingToDifferentEntry );
349
+ sourceTab = new SourceTab (panel , movingToDifferentEntry );
369
350
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 ;
385
352
}
386
353
387
354
public String getDisplayedBibEntryType () {
@@ -539,11 +506,10 @@ public void setVisibleTab(String name) {
539
506
540
507
public void setFocusToField (String fieldName ) {
541
508
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 )) {
543
510
FieldsEditorTab fieldsEditorTab = (FieldsEditorTab ) tab ;
544
511
tabbed .getSelectionModel ().select (tab );
545
- fieldsEditorTab .setActive (fieldName );
546
- fieldsEditorTab .focus ();
512
+ fieldsEditorTab .requestFocus (fieldName );
547
513
}
548
514
}
549
515
}
@@ -808,9 +774,7 @@ public void actionPerformed(ActionEvent event) {
808
774
// Should only be done if this editor is currently showing:
809
775
// don't select the current entry again (eg use BasePanel#highlightEntry} in case another entry was selected)
810
776
if (!movingAway && isShowing ()) {
811
- SwingUtilities .invokeLater (() -> {
812
- panel .getMainTable ().ensureVisible (entry );
813
- });
777
+ SwingUtilities .invokeLater (() -> panel .getMainTable ().ensureVisible (entry ));
814
778
}
815
779
}
816
780
0 commit comments