Skip to content

Commit f3f36c4

Browse files
committed
preferences: Split 'Add new field' into ComboBox and TextField
Replaces the single editable SearchableComboBox with two separate components: a SearchableComboBox for existing fields and a new TextField for custom fields
1 parent 9cab4c1 commit f3f36c4

File tree

4 files changed

+81
-14
lines changed

4 files changed

+81
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
114114
- We improved the citations relations caching by implementing an offline storage. [#11189](https://github.com/JabRef/jabref/issues/11189)
115115
- A space is now added by default after citations inserted via the Libre/OpenOffice integration. [#13559](https://github.com/JabRef/jabref/issues/13559)
116116
- We replaced the standard ComboBox with a SearchableComboBox in custom Entry Types [#14082](https://github.com/JabRef/jabref/issues/14082)
117+
- We replaced the standard ComboBox with a SearchableComboBox and added a free text field in custom Entry Types [#14082](https://github.com/JabRef/jabref/issues/14082)
117118

118119
### Fixed
119120

jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTab.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class CustomEntryTypesTab extends AbstractPreferenceTabView<CustomEntryTy
4747
@FXML private TableColumn<EntryTypeViewModel, String> entryTypColumn;
4848
@FXML private TableColumn<EntryTypeViewModel, String> entryTypeActionsColumn;
4949
@FXML private TextField addNewEntryType;
50+
@FXML private TextField addNewCustomFieldText;
5051
@FXML private TableView<FieldViewModel> fields;
5152
@FXML private TableColumn<FieldViewModel, String> fieldNameColumn;
5253
@FXML private TableColumn<FieldViewModel, Boolean> fieldTypeColumn;
@@ -55,6 +56,7 @@ public class CustomEntryTypesTab extends AbstractPreferenceTabView<CustomEntryTy
5556
@FXML private SearchableComboBox<Field> addNewField;
5657
@FXML private Button addNewEntryTypeButton;
5758
@FXML private Button addNewFieldButton;
59+
@FXML private Button addNewCustomFieldButton;
5860

5961
@Inject private StateManager stateManager;
6062

@@ -89,9 +91,13 @@ public void initialize() {
8991
addNewEntryTypeButton.disableProperty().bind(viewModel.entryTypeValidationStatus().validProperty().not());
9092
addNewFieldButton.disableProperty().bind(viewModel.fieldValidationStatus().validProperty().not().or(viewModel.selectedEntryTypeProperty().isNull()));
9193

94+
viewModel.newCustomFieldToAddProperty().bindBidirectional(addNewCustomFieldText.textProperty());
95+
addNewCustomFieldButton.disableProperty().bind(viewModel.customFieldValidationStatus().validProperty().not().or(viewModel.selectedEntryTypeProperty().isNull()));
96+
9297
Platform.runLater(() -> {
9398
visualizer.initVisualization(viewModel.entryTypeValidationStatus(), addNewEntryType, true);
9499
visualizer.initVisualization(viewModel.fieldValidationStatus(), addNewField, true);
100+
visualizer.initVisualization(viewModel.customFieldValidationStatus(), addNewCustomFieldText, true);
95101
});
96102
}
97103

@@ -203,7 +209,7 @@ private void setupFieldsTable() {
203209
viewModel.newFieldToAddProperty().bindBidirectional(addNewField.valueProperty());
204210
// The valueProperty() of addNewField ComboBox needs to be updated by typing text in the ComboBox textfield,
205211
// since the enabled/disabled state of addNewFieldButton won't update otherwise
206-
EasyBind.subscribe(addNewField.getEditor().textProperty(), text -> addNewField.setValue(FieldsUtil.FIELD_STRING_CONVERTER.fromString(text)));
212+
// EasyBind.subscribe(addNewField.getEditor().textProperty(), text -> addNewField.setValue(FieldsUtil.FIELD_STRING_CONVERTER.fromString(text)));
207213
}
208214

209215
private void makeRotatedColumnHeader(TableColumn<?, ?> column, String text) {
@@ -269,6 +275,11 @@ void addNewField() {
269275
viewModel.addNewField();
270276
}
271277

278+
@FXML
279+
void addNewCustomField() {
280+
viewModel.addNewCustomField();
281+
}
282+
272283
@FXML
273284
void resetEntryTypes() {
274285
boolean reset = dialogService.showConfirmationDialogAndWait(

jabgui/src/main/java/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTabViewModel.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.jabref.model.entry.field.FieldProperty;
3232
import org.jabref.model.entry.field.FieldTextMapper;
3333
import org.jabref.model.entry.field.OrFields;
34+
import org.jabref.model.entry.field.UnknownField;
3435
import org.jabref.model.entry.types.EntryType;
3536
import org.jabref.model.entry.types.UnknownEntryType;
3637

@@ -45,6 +46,7 @@ public class CustomEntryTypesTabViewModel implements PreferenceTabViewModel {
4546
private final ObjectProperty<EntryTypeViewModel> selectedEntryType = new SimpleObjectProperty<>();
4647
private final StringProperty entryTypeToAdd = new SimpleStringProperty("");
4748
private final ObjectProperty<Field> newFieldToAdd = new SimpleObjectProperty<>();
49+
private final StringProperty newCustomFieldToAdd = new SimpleStringProperty("");
4850
private final ObservableList<EntryTypeViewModel> entryTypesWithFields = FXCollections.observableArrayList(extractor -> new Observable[] {extractor.entryType(), extractor.fields()});
4951
private final List<BibEntryType> entryTypesToDelete = new ArrayList<>();
5052

@@ -55,6 +57,7 @@ public class CustomEntryTypesTabViewModel implements PreferenceTabViewModel {
5557

5658
private final Validator entryTypeValidator;
5759
private final Validator fieldValidator;
60+
private final Validator customFieldValidator;
5861
private final Set<Field> multiLineFields = new HashSet<>();
5962

6063
Predicate<Field> isMultiline = field -> this.multiLineFields.contains(field) || field.getProperties().contains(FieldProperty.MULTILINE_TEXT);
@@ -78,6 +81,11 @@ public CustomEntryTypesTabViewModel(BibDatabaseMode mode,
7881
newFieldToAdd,
7982
input -> (input != null) && StringUtil.isNotBlank(FieldTextMapper.getDisplayName(input)),
8083
ValidationMessage.error(Localization.lang("Field cannot be empty. Please enter a name.")));
84+
customFieldValidator = new FunctionBasedValidator<>(
85+
newCustomFieldToAdd,
86+
input -> StringUtil.isNotBlank(input) && !input.contains(" "),
87+
ValidationMessage.error(Localization.lang("Field cannot be empty and must not contain spaces."))
88+
);
8189
}
8290

8391
@Override
@@ -167,6 +175,26 @@ public void addNewField() {
167175
newFieldToAddProperty().setValue(null);
168176
}
169177

178+
public void addNewCustomField() {
179+
String fieldName = newCustomFieldToAdd.get().trim();
180+
Field newField = new UnknownField(fieldName);
181+
182+
boolean fieldExists = displayNameExists(FieldTextMapper.getDisplayName(newField));
183+
184+
if (fieldExists) {
185+
dialogService.showWarningDialogAndWait(
186+
Localization.lang("Duplicate fields"),
187+
Localization.lang("Warning: You added field \"%0\" twice. Only one will be kept.", FieldTextMapper.getDisplayName(newField)));
188+
} else {
189+
this.selectedEntryType.getValue().addField(new FieldViewModel(
190+
newField,
191+
FieldViewModel.Mandatory.REQUIRED,
192+
FieldPriority.IMPORTANT,
193+
false));
194+
}
195+
newCustomFieldToAdd.set("");
196+
}
197+
170198
public boolean displayNameExists(String displayName) {
171199
ObservableList<FieldViewModel> entryFields = this.selectedEntryType.getValue().fields();
172200
return entryFields.stream().anyMatch(fieldViewModel ->
@@ -202,11 +230,19 @@ public ObservableList<Field> fieldsForAdding() {
202230
return this.fieldsForAdding;
203231
}
204232

233+
public StringProperty newCustomFieldToAddProperty() {
234+
return this.newCustomFieldToAdd;
235+
}
236+
205237
public ValidationStatus entryTypeValidationStatus() {
206238
return entryTypeValidator.getValidationStatus();
207239
}
208240

209241
public ValidationStatus fieldValidationStatus() {
210242
return fieldValidator.getValidationStatus();
211243
}
244+
245+
public ValidationStatus customFieldValidationStatus() {
246+
return customFieldValidator.getValidationStatus();
247+
}
212248
}

jabgui/src/main/resources/org/jabref/gui/preferences/customentrytypes/CustomEntryTypesTab.fxml

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
</columnResizePolicy>
3131
</TableView>
3232
<HBox spacing="10.0">
33-
<TextField fx:id="addNewEntryType"/>
33+
<TextField fx:id="addNewEntryType" promptText="Type new entry type..."/>
3434
<Button fx:id="addNewEntryTypeButton"
3535
prefHeight="20.0" prefWidth="20.0"
3636
styleClass="icon-button,narrow" onAction="#addEntryType">
@@ -60,18 +60,37 @@
6060
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
6161
</columnResizePolicy>
6262
</TableView>
63-
<HBox spacing="10.0" alignment="BASELINE_CENTER">
64-
<SearchableComboBox fx:id="addNewField" editable="true" prefWidth="150.0"/>
65-
<Button fx:id="addNewFieldButton"
66-
prefHeight="20.0" prefWidth="20.0"
67-
styleClass="icon-button,narrow" onAction="#addNewField">
68-
<graphic>
69-
<JabRefIconView glyph="ADD_NOBOX"/>
70-
</graphic>
71-
<tooltip>
72-
<Tooltip text="%Add new Field"/>
73-
</tooltip>
74-
</Button>
63+
<HBox spacing="10.0" alignment="BASELINE_LEFT">
64+
<VBox spacing="5.0">
65+
<HBox spacing="10.0" alignment="BASELINE_CENTER">
66+
<SearchableComboBox fx:id="addNewField" editable="true" prefWidth="150.0"/>
67+
<Button fx:id="addNewFieldButton"
68+
prefHeight="20.0" prefWidth="20.0"
69+
styleClass="icon-button,narrow" onAction="#addNewField">
70+
<graphic>
71+
<JabRefIconView glyph="ADD_NOBOX"/>
72+
</graphic>
73+
<tooltip>
74+
<Tooltip text="%Add new Field"/>
75+
</tooltip>
76+
</Button>
77+
</HBox>
78+
79+
<HBox spacing="10.0" alignment="BASELINE_CENTER">
80+
<TextField fx:id="addNewCustomFieldText" prefWidth="150.0" promptText="%Type new custom field..."/>
81+
<Button fx:id="addNewCustomFieldButton"
82+
prefHeight="20.0" prefWidth="20.0"
83+
styleClass="icon-button,narrow" onAction="#addNewCustomField">
84+
<graphic>
85+
<JabRefIconView glyph="ADD_NOBOX"/>
86+
</graphic>
87+
<tooltip>
88+
<Tooltip text="%Add new custom field"/>
89+
</tooltip>
90+
</Button>
91+
</HBox>
92+
</VBox>
93+
7594
<Region HBox.hgrow="ALWAYS" />
7695
<Button text="%Reset to default" onAction="#resetEntryTypes">
7796
<graphic>

0 commit comments

Comments
 (0)