diff --git a/CHANGELOG.md b/CHANGELOG.md index fea2161c7ac..deda2cda1a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ We refer to [GitHub issues](/~https://github.com/JabRef/jabref/issues) by using `# - We cleaned up the group add/edit dialog. [#5826](/~https://github.com/JabRef/jabref/pull/5826) - We reintroduced the index column. [#5844](/~https://github.com/JabRef/jabref/pull/5844) +- We reimplemented and improved the dialog "Customize entry types" [#4719](/~https://github.com/JabRef/jabref/issues/4719) ### Fixed diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 1ab27163108..5f164f1745e 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -75,4 +75,5 @@ requires org.antlr.antlr4.runtime; requires flowless; requires org.apache.tika.core; + requires javafx.base; } diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 10bbccfd383..8eef085787b 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -831,7 +831,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), factory.createMenuItem(StandardActions.MANAGE_CONTENT_SELECTORS, new ManageContentSelectorAction(this, stateManager)), - factory.createMenuItem(StandardActions.CUSTOMIZE_ENTRY_TYPES, new CustomizeEntryAction(this)) + factory.createMenuItem(StandardActions.CUSTOMIZE_ENTRY_TYPES, new CustomizeEntryAction(stateManager, Globals.entryTypesManager)) ); help.getItems().addAll( diff --git a/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypeDialogViewModel.java b/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypeDialogViewModel.java index 8ce62756fb7..cc73ffe2040 100644 --- a/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypeDialogViewModel.java +++ b/src/main/java/org/jabref/gui/customentrytypes/CustomEntryTypeDialogViewModel.java @@ -19,9 +19,10 @@ import javafx.collections.ObservableList; import javafx.util.StringConverter; -import org.jabref.Globals; +import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntryType; +import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.entry.field.BibField; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; @@ -49,61 +50,61 @@ public Field fromString(String string) { } }; - private ListProperty entryTypesProperty; - private ListProperty fieldsProperty; - private ObjectProperty selectedEntryTypesProperty = new SimpleObjectProperty<>(); - private ListProperty fieldsForTypeProperty; - private ObjectProperty selectedFieldToAddProperty = new SimpleObjectProperty<>(); - private StringProperty entryTypeToAddProperty = new SimpleStringProperty(""); - private ObservableList entryTypes; - private ObservableList fieldsForType = FXCollections.observableArrayList(extractor -> new Observable[] {extractor.fieldNameProperty(), extractor.fieldTypeProperty()}); - private ObjectProperty newFieldToAddProperty = new SimpleObjectProperty<>(); + private ListProperty entryTypes; + private ListProperty fields; + private ObjectProperty selectedEntryTypes = new SimpleObjectProperty<>(); + private ListProperty fieldsForType; + private ObjectProperty selectedFieldToAdd = new SimpleObjectProperty<>(); + private StringProperty entryTypeToAdd = new SimpleStringProperty(""); + private ObservableList allEntryTypes; + private ObservableList allFieldsForType = FXCollections.observableArrayList(extractor -> new Observable[] {extractor.fieldName(), extractor.fieldType()}); + private ObjectProperty newFieldToAdd = new SimpleObjectProperty<>(); private BibDatabaseMode mode; private Map> typesWithFields = new HashMap<>(); private List typesToRemove = new ArrayList<>(); private PreferencesService preferencesService; + private BibEntryTypesManager entryTypesManager; - public CustomEntryTypeDialogViewModel(BibDatabaseMode mode, PreferencesService preferencesService) { + public CustomEntryTypeDialogViewModel(BibDatabaseMode mode, PreferencesService preferencesService, BibEntryTypesManager entryTypesManager) { this.mode = mode; this.preferencesService = preferencesService; + this.entryTypesManager = entryTypesManager; - Collection allTypes = Globals.entryTypesManager.getAllTypes(mode); - allTypes.addAll(Globals.entryTypesManager.getAllCustomTypes(mode)); + Collection allTypes = entryTypesManager.getAllTypes(mode); + allTypes.addAll(entryTypesManager.getAllCustomTypes(mode)); - entryTypes = FXCollections.observableArrayList(allTypes); - entryTypesProperty = new SimpleListProperty<>(entryTypes); + allEntryTypes = FXCollections.observableArrayList(allTypes); + entryTypes = new SimpleListProperty<>(allEntryTypes); - fieldsProperty = new SimpleListProperty<>(FXCollections.observableArrayList(FieldFactory.getAllFields())); + fields = new SimpleListProperty<>(FXCollections.observableArrayList(FieldFactory.getCommonFields())); for (BibEntryType entryType : allTypes) { List fields = entryType.getAllFields().stream().map(bibField -> new FieldViewModel(bibField.getField(), entryType.isRequired(bibField.getField()), bibField.getPriority(), entryType)).collect(Collectors.toList()); typesWithFields.put(entryType, fields); } - this.fieldsForTypeProperty = new SimpleListProperty<>(fieldsForType); + this.fieldsForType = new SimpleListProperty<>(allFieldsForType); - EasyBind.subscribe(selectedEntryTypesProperty, type -> { + EasyBind.subscribe(selectedEntryTypes, type -> { if (type != null) { - List typesForField = typesWithFields.get(type); - fieldsForType.setAll(typesForField); + allFieldsForType.setAll(typesWithFields.get(type)); } }); - } - public ListProperty entryTypesProperty() { - return this.entryTypesProperty; + public ListProperty entryTypes() { + return this.entryTypes; } - public ListProperty fieldsProperty() { - return this.fieldsProperty; + public ListProperty fields() { + return this.fields; } public enum FieldType { - REQUIRED("Required"), - OPTIONAL("Optional"); + REQUIRED(Localization.lang("Required")), + OPTIONAL(Localization.lang("Optional")); private String name; @@ -122,68 +123,72 @@ public String toString() { } public void addNewField() { - Field field = newFieldToAddProperty.getValue(); - FieldViewModel model = new FieldViewModel(field, true, FieldPriority.IMPORTANT, selectedEntryTypesProperty.getValue()); - typesWithFields.computeIfAbsent(selectedEntryTypesProperty.getValue(), key -> new ArrayList<>()).add(model); - fieldsForType.add(model); + Field field = newFieldToAdd.getValue(); + FieldViewModel model = new FieldViewModel(field, true, FieldPriority.IMPORTANT, selectedEntryTypes.getValue()); + typesWithFields.computeIfAbsent(selectedEntryTypes.getValue(), key -> new ArrayList<>()).add(model); + allFieldsForType.add(model); + newFieldToAddProperty().setValue(null); } public void addNewCustomEntryType() { - EntryType newentryType = new UnknownEntryType(entryTypeToAddProperty.getValue()); + EntryType newentryType = new UnknownEntryType(entryTypeToAdd.getValue()); BibEntryType type = new BibEntryType(newentryType, new ArrayList<>(), Collections.emptyList()); - this.entryTypes.add(type); - + this.allEntryTypes.add(type); + this.entryTypeToAdd.setValue(""); this.typesWithFields.put(type, new ArrayList<>()); } public ObjectProperty selectedEntryTypeProperty() { - return this.selectedEntryTypesProperty; + return this.selectedEntryTypes; } public ListProperty fieldsforTypesProperty() { - return this.fieldsForTypeProperty; + return this.fieldsForType; } public ObjectProperty selectedFieldToAddProperty() { - return this.selectedFieldToAddProperty; + return this.selectedFieldToAdd; } public StringProperty entryTypeToAddProperty() { - return this.entryTypeToAddProperty; + return this.entryTypeToAdd; } public ObjectProperty newFieldToAddProperty() { - return this.newFieldToAddProperty; + return this.newFieldToAdd; } public void removeEntryType(BibEntryType focusedItem) { typesToRemove.add(focusedItem); typesWithFields.remove(focusedItem); - entryTypes.remove(focusedItem); + allEntryTypes.remove(focusedItem); } public void removeField(FieldViewModel focusedItem) { - typesWithFields.computeIfAbsent(selectedEntryTypesProperty.getValue(), key -> new ArrayList<>()).remove(focusedItem); - fieldsForType.remove(focusedItem); + typesWithFields.computeIfAbsent(selectedEntryTypes.getValue(), key -> new ArrayList<>()).remove(focusedItem); + allFieldsForType.remove(focusedItem); } public void apply() { - for (var entry : typesWithFields.entrySet()) { - BibEntryType type = entry.getKey(); - List allFields = entry.getValue(); + for (var typeWithField : typesWithFields.entrySet()) { + BibEntryType type = typeWithField.getKey(); + List allFields = typeWithField.getValue(); List requiredFields = allFields.stream().filter(field -> field.getFieldType() == FieldType.REQUIRED).map(FieldViewModel::getField).map(OrFields::new).collect(Collectors.toList()); List otherFields = allFields.stream().filter(field -> field.getFieldType() == FieldType.OPTIONAL).map(bibField -> new BibField(bibField.getField(), bibField.getFieldPriority())).collect(Collectors.toList()); BibEntryType newType = new BibEntryType(type.getType(), otherFields, requiredFields); - Globals.entryTypesManager.addCustomOrModifiedType(newType, mode); + entryTypesManager.addCustomOrModifiedType(newType, mode); } for (var type : typesToRemove) { - Globals.entryTypesManager.removeCustomEntryType(type, mode); + entryTypesManager.removeCustomOrModifiedEntryType(type, mode); } preferencesService.saveCustomEntryTypes(); + //Reload types from preferences to make sure any modifications are present when reopening the dialog + entryTypesManager.addCustomOrModifiedTypes(preferencesService.loadBibEntryTypes(BibDatabaseMode.BIBTEX), + preferencesService.loadBibEntryTypes(BibDatabaseMode.BIBLATEX)); } } diff --git a/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryAction.java b/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryAction.java index 64684b8c29c..a320dcc0b45 100644 --- a/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryAction.java +++ b/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryAction.java @@ -1,19 +1,27 @@ package org.jabref.gui.customentrytypes; -import org.jabref.gui.JabRefFrame; +import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntryTypesManager; + +import static org.jabref.gui.actions.ActionHelper.needsDatabase; public class CustomizeEntryAction extends SimpleCommand { - private final JabRefFrame frame; + private final StateManager stateManager; + private final BibEntryTypesManager entryTypesManager; - public CustomizeEntryAction(JabRefFrame frame) { - this.frame = frame; + public CustomizeEntryAction(StateManager stateManager, BibEntryTypesManager entryTypesManager) { + this.stateManager = stateManager; + this.executable.bind(needsDatabase(this.stateManager)); + this.entryTypesManager = entryTypesManager; } @Override public void execute() { - CustomizeEntryTypeDialogView dialog = new CustomizeEntryTypeDialogView(this.frame.getCurrentBasePanel().getBibDatabaseContext()); + BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null")); + CustomizeEntryTypeDialogView dialog = new CustomizeEntryTypeDialogView(database, entryTypesManager); dialog.showAndWait(); } } diff --git a/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialog.fxml b/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialog.fxml index 6ed035d2754..c0905e4cc70 100644 --- a/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialog.fxml +++ b/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialog.fxml @@ -15,7 +15,7 @@ - diff --git a/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialogView.java b/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialogView.java index fdc178041e6..c3ef30db5ee 100644 --- a/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialogView.java +++ b/src/main/java/org/jabref/gui/customentrytypes/CustomizeEntryTypeDialogView.java @@ -16,11 +16,13 @@ import org.jabref.gui.customentrytypes.CustomEntryTypeDialogViewModel.FieldType; import org.jabref.gui.icon.IconTheme; import org.jabref.gui.util.BaseDialog; +import org.jabref.gui.util.RadioButtonCell; import org.jabref.gui.util.ValueTableCellFactory; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntryType; +import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.entry.field.Field; import org.jabref.preferences.PreferencesService; @@ -28,6 +30,9 @@ public class CustomizeEntryTypeDialogView extends BaseDialog { + private final BibDatabaseMode mode; + private final BibEntryTypesManager entryTypesManager; + @FXML private TableView entryTypes; @FXML private TableColumn entryTypColumn; @FXML private TableColumn entryTypeActionsColumn; @@ -42,10 +47,10 @@ public class CustomizeEntryTypeDialogView extends BaseDialog { @Inject private PreferencesService preferencesService; private CustomEntryTypeDialogViewModel viewModel; - private BibDatabaseMode mode; - public CustomizeEntryTypeDialogView(BibDatabaseContext bibDatabaseContext) { + public CustomizeEntryTypeDialogView(BibDatabaseContext bibDatabaseContext, BibEntryTypesManager entryTypesManager) { this.mode = bibDatabaseContext.getMode(); + this.entryTypesManager = entryTypesManager; ViewLoader.view(this) .load() @@ -61,15 +66,15 @@ public CustomizeEntryTypeDialogView(BibDatabaseContext bibDatabaseContext) { @FXML private void initialize() { - viewModel = new CustomEntryTypeDialogViewModel(mode, preferencesService); - + viewModel = new CustomEntryTypeDialogViewModel(mode, preferencesService, entryTypesManager); setupTable(); } private void setupTable() { + fields.setEditable(true); //Table View must be editable, otherwise the change of the Radiobuttons does not propagate the commit event entryTypColumn.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getType().getDisplayName())); - entryTypes.itemsProperty().bind(viewModel.entryTypesProperty()); + entryTypes.itemsProperty().bind(viewModel.entryTypes()); entryTypes.getSelectionModel().selectFirst(); entryTypeActionsColumn.setSortable(false); @@ -78,27 +83,33 @@ private void setupTable() { new ValueTableCellFactory() .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) .withTooltip(name -> Localization.lang("Remove entry type") + " " + name) - .withOnMouseClickedEvent(item -> evt -> viewModel.removeEntryType(entryTypes.getFocusModel().getFocusedItem())) + .withOnMouseClickedEvent(item -> evt -> viewModel.removeEntryType(entryTypes.getSelectionModel().getSelectedItem())) .install(entryTypeActionsColumn); fieldTypeColumn.setCellFactory(cellData -> new RadioButtonCell<>(EnumSet.allOf(FieldType.class))); - fieldTypeColumn.setCellValueFactory(item -> item.getValue().fieldTypeProperty()); - fieldNameColumn.setCellValueFactory(item -> item.getValue().fieldNameProperty()); + fieldTypeColumn.setCellValueFactory(item -> item.getValue().fieldType()); + + fieldTypeColumn.setEditable(true); + fieldTypeColumn.setOnEditCommit(event -> { + event.getTableView().getItems().get(event.getTablePosition().getRow()).setFieldType(event.getNewValue()); + }); + + fieldNameColumn.setCellValueFactory(item -> item.getValue().fieldName()); viewModel.selectedEntryTypeProperty().bind(entryTypes.getSelectionModel().selectedItemProperty()); viewModel.entryTypeToAddProperty().bind(addNewEntryType.textProperty()); - addNewField.setItems(viewModel.fieldsProperty()); + addNewField.setItems(viewModel.fields()); addNewField.setConverter(viewModel.FIELD_STRING_CONVERTER); fieldTypeActionColumn.setSortable(false); fieldTypeActionColumn.setReorderable(false); - fieldTypeActionColumn.setCellValueFactory(cellData -> cellData.getValue().fieldNameProperty()); + fieldTypeActionColumn.setCellValueFactory(cellData -> cellData.getValue().fieldName()); new ValueTableCellFactory() .withGraphic(item -> IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode()) .withTooltip(name -> Localization.lang("Remove field from entry type") + " " + name) - .withOnMouseClickedEvent(item -> evt -> viewModel.removeField(fields.getFocusModel().getFocusedItem())) + .withOnMouseClickedEvent(item -> evt -> viewModel.removeField(fields.getSelectionModel().getSelectedItem())) .install(fieldTypeActionColumn); viewModel.newFieldToAddProperty().bindBidirectional(addNewField.valueProperty()); diff --git a/src/main/java/org/jabref/gui/customentrytypes/EntryTypeCustomizationDialog.java b/src/main/java/org/jabref/gui/customentrytypes/EntryTypeCustomizationDialog.java deleted file mode 100644 index ba034b8bdb2..00000000000 --- a/src/main/java/org/jabref/gui/customentrytypes/EntryTypeCustomizationDialog.java +++ /dev/null @@ -1,377 +0,0 @@ -package org.jabref.gui.customentrytypes; - -import org.jabref.gui.util.BaseDialog; - -public class EntryTypeCustomizationDialog extends BaseDialog { - - // TODO: Re-implement customize entry types feature (/~https://github.com/JabRef/jabref/issues/4719) - /* - protected GridBagLayout gbl = new GridBagLayout(); - protected GridBagConstraints con = new GridBagConstraints(); - protected JButton delete; - private final JabRefFrame frame; - private FieldSetComponent reqComp; - private FieldSetComponent optComp; - private FieldSetComponent optComp2; - private EntryTypeList typeComp; - private final List preset = InternalBibtexFields.getAllPublicFieldNames(); - private String lastSelected; - private final Map> reqLists = new HashMap<>(); - private final Map> optLists = new HashMap<>(); - private final Map> opt2Lists = new HashMap<>(); - private final Set defaulted = new HashSet<>(); - private final Set changed = new HashSet<>(); - - private boolean biblatexMode; - private BibDatabaseMode bibDatabaseMode; - - public EntryTypeCustomizationDialog(JabRefFrame frame) { - super(Localization.lang("Customize entry types"), false, EntryTypeCustomizationDialog.class); - - this.frame = frame; - initGui(); - } - - private void initGui() { - Container pane = getContentPane(); - pane.setLayout(new BorderLayout()); - - if (frame.getCurrentBasePanel() == null) { - bibDatabaseMode = Globals.prefs.getDefaultBibDatabaseMode(); - } else { - bibDatabaseMode = frame.getCurrentBasePanel().getBibDatabaseContext().getMode(); - } - biblatexMode = BibDatabaseMode.BIBLATEX.equals(bibDatabaseMode); - - JPanel main = new JPanel(); - JPanel buttons = new JPanel(); - JPanel right = new JPanel(); - main.setLayout(new BorderLayout()); - right.setLayout(new GridLayout(biblatexMode ? 2 : 1, 2)); - - List entryTypes = new ArrayList<>(); - entryTypes.addAll(EntryTypeFactory.getAllTypes(bibDatabaseMode)); - - typeComp = new EntryTypeList(frame.getDialogService(), entryTypes, bibDatabaseMode); - typeComp.addListSelectionListener(this); - typeComp.addAdditionActionListener(e -> typeComp.selectField(e.getActionCommand())); - typeComp.addDefaultActionListener(new DefaultListener()); - typeComp.setListSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - //typeComp.setEnabled(false); - reqComp = new FieldSetComponent(Localization.lang("Required fields"), new ArrayList<>(), preset, true, true); - reqComp.setEnabled(false); - reqComp.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - ListDataListener dataListener = new DataListener(); - reqComp.addListDataListener(dataListener); - optComp = new FieldSetComponent(Localization.lang("Optional fields"), new ArrayList<>(), preset, true, true); - optComp.setEnabled(false); - optComp.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - optComp.addListDataListener(dataListener); - right.add(reqComp); - right.add(optComp); - - if (biblatexMode) { - optComp2 = new FieldSetComponent(Localization.lang("Optional fields") + " 2", new ArrayList<>(), preset, true, true); - optComp2.setEnabled(false); - optComp2.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - optComp2.addListDataListener(dataListener); - right.add(new JPanel()); - right.add(optComp2); - } - - //right.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), Globals.lang("Fields"))); - right.setBorder(BorderFactory.createEtchedBorder()); - JButton ok = new JButton(Localization.lang("OK")); - JButton cancel = new JButton(Localization.lang("Cancel")); - JButton apply = new JButton(Localization.lang("Apply")); - ok.addActionListener(e -> { - applyChanges(); - dispose(); - }); - apply.addActionListener(e -> applyChanges()); - cancel.addActionListener(e -> dispose()); - ButtonBarBuilder bb = new ButtonBarBuilder(buttons); - buttons.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - bb.addGlue(); - bb.addButton(ok); - bb.addButton(apply); - bb.addButton(cancel); - bb.addGlue(); - - AbstractAction closeAction = new AbstractAction() { - - @Override - public void actionPerformed(ActionEvent e) { - dispose(); - } - }; - ActionMap am = main.getActionMap(); - InputMap im = main.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - im.put(Globals.getKeyPrefs().getKey(KeyBinding.CLOSE), "close"); - am.put("close", closeAction); - - //con.fill = GridBagConstraints.BOTH; - //con.weightx = 0.3; - //con.weighty = 1; - //gbl.setConstraints(typeComp, con); - main.add(typeComp, BorderLayout.WEST); - main.add(right, BorderLayout.CENTER); - main.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - pane.add(main, BorderLayout.CENTER); - pane.add(buttons, BorderLayout.SOUTH); - pack(); - } - - @Override - public void valueChanged(ListSelectionEvent e) { - if (e.getValueIsAdjusting()) { - return; - } - - if (lastSelected != null) { - // The entry type lastSelected is now unselected, so we store the current settings - // for that type in our two maps. - reqLists.put(lastSelected, reqComp.getFields()); - optLists.put(lastSelected, optComp.getFields()); - if (biblatexMode) { - opt2Lists.put(lastSelected, optComp2.getFields()); - } - } - - String selectedTypeName = typeComp.getFirstSelected(); - if (selectedTypeName == null) { - return; - } - Set requiredFieldsSelectedType = reqLists.get(selectedTypeName); - if (requiredFieldsSelectedType == null) { - Optional type = EntryTypeFactory.getType(selectedTypeName, bibDatabaseMode); - if (type.isPresent()) { - Set req = type.get().getRequiredFields(); - - Set opt; - if (biblatexMode) { - opt = type.get().getPrimaryOptionalFields(); - - Set opt2 = type.get().getSecondaryOptionalFields(); - - optComp2.setFields(opt2); - optComp2.setEnabled(true); - } else { - opt = type.get().getOptionalFields(); - } - reqComp.setFields(req); - reqComp.setEnabled(true); - optComp.setFields(opt); - optComp.setEnabled(true); - } else { - // New entry - reqComp.setFields(new HashSet<>()); - reqComp.setEnabled(true); - optComp.setFields(new HashSet<>()); - optComp.setEnabled(true); - if (biblatexMode) { - optComp2.setFields(new HashSet<>()); - optComp2.setEnabled(true); - } - reqComp.requestFocus(); - } - } else { - reqComp.setFields(requiredFieldsSelectedType); - optComp.setFields(optLists.get(selectedTypeName)); - if (biblatexMode) { - optComp2.setFields(opt2Lists.get(selectedTypeName)); - } - } - - lastSelected = selectedTypeName; - typeComp.enable(selectedTypeName, changed.contains(lastSelected) && !defaulted.contains(lastSelected)); - } - - private void applyChanges() { - valueChanged(new ListSelectionEvent(new JList<>(), 0, 0, false)); - - List actuallyChangedTypes = new ArrayList<>(); - - // Iterate over our map of required fields, and list those types if necessary: - Set types = typeComp.getFields(); - for (Map.Entry> stringListEntry : reqLists.entrySet()) { - if (!types.contains(stringListEntry.getKey())) { - continue; - } - - Set requiredFieldsList = stringListEntry.getValue(); - Set optionalFieldsList = optLists.get(stringListEntry.getKey()); - Set secondaryOptionalFieldsLists = opt2Lists.get(stringListEntry.getKey()); - - if (secondaryOptionalFieldsLists == null) { - secondaryOptionalFieldsLists = new HashSet<>(0); - } - - // If this type is already existing, check if any changes have - // been made - boolean changesMade = true; - - if (defaulted.contains(stringListEntry.getKey())) { - // This type should be reverted to its default setup. - EntryTypeFactory.removeType(stringListEntry.getKey(), bibDatabaseMode); - - actuallyChangedTypes.add(stringListEntry.getKey().toLowerCase(Locale.ENGLISH)); - defaulted.remove(stringListEntry.getKey()); - continue; - } - - Optional oldType = EntryTypeFactory.getType(stringListEntry.getKey(), bibDatabaseMode); - if (oldType.isPresent()) { - Set oldRequiredFieldsList = oldType.get().getRequiredFieldsFlat(); - Set oldOptionalFieldsList = oldType.get().getOptionalFields(); - if (biblatexMode) { - Set oldPrimaryOptionalFieldsLists = oldType.get().getPrimaryOptionalFields(); - Set oldSecondaryOptionalFieldsList = oldType.get().getSecondaryOptionalFields(); - if (Arrays.equals(oldRequiredFieldsList.toArray(), requiredFieldsList.toArray()) - && Arrays.equals(oldPrimaryOptionalFieldsLists.toArray(), optionalFieldsList.toArray()) - && Arrays.equals(oldSecondaryOptionalFieldsList.toArray(), secondaryOptionalFieldsLists.toArray())) { - changesMade = false; - } - } else if (Arrays.equals(oldRequiredFieldsList.toArray(), requiredFieldsList.toArray()) - && Arrays.equals(oldOptionalFieldsList.toArray(), optionalFieldsList.toArray())) { - changesMade = false; - } - } - - if (changesMade) { - BibEntryType customType = biblatexMode ? - new BibEntryType(StringUtil.capitalizeFirst(stringListEntry.getKey()), requiredFieldsList, optionalFieldsList, secondaryOptionalFieldsLists) : - new BibEntryType(StringUtil.capitalizeFirst(stringListEntry.getKey()), requiredFieldsList, optionalFieldsList); - - EntryTypeFactory.addOrModifyBibEntryType(customType, bibDatabaseMode); - actuallyChangedTypes.add(customType.getName().toLowerCase(Locale.ENGLISH)); - } - } - - // update all affected entries if something has been changed - if (!actuallyChangedTypes.isEmpty()) { - updateEntriesForChangedTypes(actuallyChangedTypes); - } - - Set typesToRemove = new HashSet<>(); - for (String existingType : EntryTypeFactory.getAllTypes(bibDatabaseMode)) { - if (!types.contains(existingType)) { - typesToRemove.add(existingType); - } - } - - // Remove those that should be removed: - if (!typesToRemove.isEmpty()) { - for (String typeToRemove : typesToRemove) { - deleteType(typeToRemove); - } - } - - BibEntryTypesManager.saveBibEntryTypes(Globals.prefs); - } - - private void deleteType(String name) { - Optional type = EntryTypeFactory.getType(name, bibDatabaseMode); - - if (type.isPresent() && (type.get() instanceof BibEntryType)) { - if (!EntryTypeFactory.getStandardType(name, bibDatabaseMode).isPresent()) { - - boolean deleteCustomClicked = frame.getDialogService().showConfirmationDialogAndWait(Localization.lang("Delete custom format") + - " '" + StringUtil.capitalizeFirst(name) + '\'', Localization.lang("All entries of this " - + "type will be declared " - + "typeless. Continue?"), - Localization.lang("Delete custom format"), Localization.lang("Cancel")); - - if (!deleteCustomClicked) { - return; - } - } - EntryTypeFactory.removeType(name, bibDatabaseMode); - updateEntriesForChangedTypes(Collections.singletonList(name.toLowerCase(Locale.ENGLISH))); - changed.remove(name); - reqLists.remove(name); - optLists.remove(name); - if (biblatexMode) { - opt2Lists.remove(name); - } - } - } - - private void updateEntriesForChangedTypes(List actuallyChangedTypes) { - for (BasePanel bp : frame.getBasePanelList()) { - // get all affected entries - List filtered = bp.getDatabase().getEntries().stream() - .filter(entry -> actuallyChangedTypes.contains(entry.getType().toLowerCase(Locale.ENGLISH))).collect(Collectors.toList()); - - // update all affected entries with new type - filtered.forEach(entry -> EntryTypeFactory.getType(entry.getType(), bibDatabaseMode).ifPresent(entry::setType)); - } - } - - // DEFAULT button pressed. Remember that this entry should be reset to default, - // unless changes are made later. - private class DefaultListener implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - if (lastSelected == null) { - return; - } - defaulted.add(lastSelected); - - Optional type = EntryTypeFactory.getStandardType(lastSelected, bibDatabaseMode); - if (type.isPresent()) { - Set of = type.get().getOptionalFields(); - Set req = type.get().getRequiredFields(); - Set opt1 = new HashSet<>(); - Set opt2 = new HashSet<>(); - - if (!(of.isEmpty())) { - if (biblatexMode) { - opt1 = type.get().getPrimaryOptionalFields(); - opt2 = type.get().getSecondaryOptionalFields(); - } else { - opt1 = of; - } - } - - reqComp.setFields(req); - reqComp.setEnabled(true); - optComp.setFields(opt1); - if (biblatexMode) { - optComp2.setFields(opt2); - } - } - } - } - - class DataListener implements ListDataListener { - - @Override - public void intervalAdded(ListDataEvent e) { - record(); - } - - @Override - public void intervalRemoved(ListDataEvent e) { - record(); - } - - @Override - public void contentsChanged(ListDataEvent e) { - record(); - } - - private void record() { - if (lastSelected == null) { - return; - } - defaulted.remove(lastSelected); - changed.add(lastSelected); - typeComp.enable(lastSelected, true); - } - } - - */ -} diff --git a/src/main/java/org/jabref/gui/customentrytypes/FieldViewModel.java b/src/main/java/org/jabref/gui/customentrytypes/FieldViewModel.java index 7cd59136b0b..b000871aa67 100644 --- a/src/main/java/org/jabref/gui/customentrytypes/FieldViewModel.java +++ b/src/main/java/org/jabref/gui/customentrytypes/FieldViewModel.java @@ -12,8 +12,8 @@ public class FieldViewModel { - private final ObjectProperty fieldTypeProperty = new SimpleObjectProperty<>(); - private final StringProperty fieldNameProperty = new SimpleStringProperty(""); + private final ObjectProperty fieldType; + private final StringProperty fieldName = new SimpleStringProperty(""); private final Field field; private final FieldPriority fieldPriority; private BibEntryType entryType; @@ -21,8 +21,8 @@ public class FieldViewModel { public FieldViewModel(Field field, FieldType fieldType, FieldPriority fieldPriority, BibEntryType entryType) { this.field = field; this.entryType = entryType; - this.fieldNameProperty.setValue(field.getDisplayName()); - this.fieldTypeProperty.setValue(fieldType); + this.fieldName.setValue(field.getDisplayName()); + this.fieldType = new SimpleObjectProperty<>(fieldType); this.fieldPriority = fieldPriority; } @@ -30,12 +30,12 @@ public FieldViewModel(Field field, boolean required, FieldPriority fieldPriority this(field, required ? FieldType.REQUIRED : FieldType.OPTIONAL, fieldPriority, entryType); } - public ObjectProperty fieldTypeProperty() { - return this.fieldTypeProperty; + public ObjectProperty fieldType() { + return this.fieldType; } - public StringProperty fieldNameProperty() { - return this.fieldNameProperty; + public StringProperty fieldName() { + return this.fieldName; } public Field getField() { @@ -51,7 +51,11 @@ public FieldPriority getFieldPriority() { } public FieldType getFieldType() { - return this.fieldTypeProperty.getValue(); + return this.fieldType.getValue(); + } + + public void setFieldType(FieldType type) { + this.fieldType.setValue(type); } @Override diff --git a/src/main/java/org/jabref/gui/customentrytypes/RadioButtonCell.java b/src/main/java/org/jabref/gui/util/RadioButtonCell.java similarity index 70% rename from src/main/java/org/jabref/gui/customentrytypes/RadioButtonCell.java rename to src/main/java/org/jabref/gui/util/RadioButtonCell.java index ec3bfdc890e..6dbe8b8b613 100644 --- a/src/main/java/org/jabref/gui/customentrytypes/RadioButtonCell.java +++ b/src/main/java/org/jabref/gui/util/RadioButtonCell.java @@ -1,13 +1,10 @@ -package org.jabref.gui.customentrytypes; +package org.jabref.gui.util; import java.util.EnumSet; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.geometry.Pos; import javafx.scene.control.RadioButton; import javafx.scene.control.TableCell; -import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; @@ -20,6 +17,7 @@ public RadioButtonCell(EnumSet enumeration) { this.enumeration = enumeration; } + @SuppressWarnings("unchecked") @Override protected void updateItem(T item, boolean empty) { super.updateItem(item, empty); @@ -36,24 +34,21 @@ protected void updateItem(T item, boolean empty) { RadioButton radioButton = new RadioButton(enumElement.toString()); radioButton.setUserData(enumElement); radioButton.setToggleGroup(group); + radioButton.setMinWidth(USE_PREF_SIZE); hb.getChildren().add(radioButton); if (enumElement.equals(item)) { radioButton.setSelected(true); } + hb.setMinWidth(USE_PREF_SIZE); hb.setHgrow(radioButton, Priority.ALWAYS); } // issue events on change of the selected radio button - group.selectedToggleProperty().addListener(new ChangeListener() { - - @SuppressWarnings("unchecked") - @Override - public void changed(ObservableValue observable, - Toggle oldValue, Toggle newValue) { - getTableView().edit(getIndex(), getTableColumn()); - RadioButtonCell.this.commitEdit((T) newValue.getUserData()); - } + group.selectedToggleProperty().addListener((oservable, oldValue, newValue) -> { + getTableView().edit(getIndex(), getTableColumn()); + RadioButtonCell.this.commitEdit((T) newValue.getUserData()); }); + setGraphic(hb); } } diff --git a/src/main/java/org/jabref/model/entry/BibEntryTypesManager.java b/src/main/java/org/jabref/model/entry/BibEntryTypesManager.java index 81bd2d75ef3..97f40a15a01 100644 --- a/src/main/java/org/jabref/model/entry/BibEntryTypesManager.java +++ b/src/main/java/org/jabref/model/entry/BibEntryTypesManager.java @@ -112,11 +112,11 @@ public void addCustomOrModifiedType(BibEntryType entryType, BibDatabaseMode mode } } - public void removeCustomEntryType(BibEntryType entryType, BibDatabaseMode mode) { + public void removeCustomOrModifiedEntryType(BibEntryType entryType, BibDatabaseMode mode) { if (BibDatabaseMode.BIBLATEX == mode) { - BIBLATEX.removeCustomEntryType(entryType); + BIBLATEX.removeCustomOrModifiedEntryType(entryType); } else if (BibDatabaseMode.BIBTEX == mode) { - BIBTEX.removeCustomEntryType(entryType); + BIBTEX.removeCustomOrModifiedEntryType(entryType); } } @@ -179,7 +179,7 @@ private void addCustomOrModifiedType(BibEntryType type) { customOrModifiedType.add(type); } - private void removeCustomEntryType(BibEntryType type) { + private void removeCustomOrModifiedEntryType(BibEntryType type) { customOrModifiedType.remove(type); } diff --git a/src/main/java/org/jabref/model/entry/field/FieldFactory.java b/src/main/java/org/jabref/model/entry/field/FieldFactory.java index 7372ffc1345..a5086283f6a 100644 --- a/src/main/java/org/jabref/model/entry/field/FieldFactory.java +++ b/src/main/java/org/jabref/model/entry/field/FieldFactory.java @@ -118,7 +118,7 @@ private static Set getFieldsFiltered(Predicate selector) { .collect(Collectors.toSet()); } - public static Set getAllFields() { + private static Set getAllFields() { Set fields = new HashSet<>(); fields.addAll(EnumSet.allOf(IEEEField.class)); fields.addAll(EnumSet.allOf(InternalField.class)); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 8170d2881bb..08037697918 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -1250,6 +1250,7 @@ public void storeBibEntryTypes(List BibEntryTypes, BibDatabaseMode } } + @Override public List loadBibEntryTypes(BibDatabaseMode bibDatabaseMode) { List storedEntryTypes = new ArrayList<>(); Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); @@ -2096,8 +2097,7 @@ public void saveCustomEntryTypes() { } private void saveCustomEntryTypes(BibDatabaseMode bibDatabaseMode) { - List customBiblatexBibTexTypes = Globals.entryTypesManager.getAllTypes(bibDatabaseMode).stream() - .filter(type -> type instanceof BibEntryType) + List customBiblatexBibTexTypes = Globals.entryTypesManager.getAllTypes(bibDatabaseMode).stream() .map(entryType -> entryType).collect(Collectors.toList()); storeBibEntryTypes(customBiblatexBibTexTypes, bibDatabaseMode); diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java index 19b88c79d26..b8456acc59b 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -19,6 +19,8 @@ import org.jabref.logic.util.UpdateFieldPreferences; import org.jabref.logic.util.io.AutoLinkPreferences; import org.jabref.logic.xmp.XmpPreferences; +import org.jabref.model.database.BibDatabaseMode; +import org.jabref.model.entry.BibEntryType; import org.jabref.model.entry.field.Field; import org.jabref.model.metadata.FilePreferences; import org.jabref.model.metadata.SaveOrderConfig; @@ -104,4 +106,6 @@ public interface PreferencesService { boolean getAllowIntegerEdition(); EntryEditorPreferences getEntryEditorPreferences(); + + List loadBibEntryTypes(BibDatabaseMode mode); } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 548086cc2d3..ed15dabc0d5 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -51,7 +51,6 @@ Added\ string=Added string Advanced=Advanced All\ entries=All entries -All\ entries\ of\ this\ type\ will\ be\ declared\ typeless.\ Continue?=All entries of this type will be declared typeless. Continue? Always\ reformat\ BIB\ file\ on\ save\ and\ export=Always reformat BIB file on save and export @@ -219,8 +218,6 @@ Execute\ default\ action\ in\ dialog=Execute default action in dialog Delete=Delete -Delete\ custom\ format=Delete custom format - Delete\ entry=Delete entry Delete\ multiple\ entries=Delete multiple entries @@ -2108,3 +2105,6 @@ Required\ and\ optional\ fields=Required and optional fields Index=Index Remove\ entry\ type=Remove entry type Remove\ field\ from\ entry\ type=Remove field from entry type + +Optional=Optional +Required=Required