From 2415c3cefe474996042ef109f769b1f3b3ad17d9 Mon Sep 17 00:00:00 2001 From: LeonhardWolz Date: Thu, 21 Feb 2019 22:24:22 +0100 Subject: [PATCH] fixes #4610. Changed the way the GroupDialog description is displayed. (#4660) * Changed the way the GroupDialog description is displayed. It now uses a TextFlow Node to display the stylised text. The string with html tags is parsed and the sections of text within html tags are put in stylised Text Nodes. Rearranged the GroupDialog window, since the window grew larger then the display size. GroupDialog window is no longer resizable. fixes #4610 * Added a check to see if a database is currently open when attempting to create a new group. If no database is open we show a warning to the user. Added a german translation. * Changed wording of an error message. Databases are nor referred to as libraries. --- .../jabref/gui/groups/GroupDescriptions.java | 6 +- .../org/jabref/gui/groups/GroupDialog.java | 103 +++++++++++++----- .../jabref/gui/groups/GroupTreeViewModel.java | 12 +- src/main/resources/l10n/JabRef_de.properties | 4 + src/main/resources/l10n/JabRef_en.properties | 4 + 5 files changed, 96 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/jabref/gui/groups/GroupDescriptions.java b/src/main/java/org/jabref/gui/groups/GroupDescriptions.java index 07fd780be6b..6548c0cb1a8 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDescriptions.java +++ b/src/main/java/org/jabref/gui/groups/GroupDescriptions.java @@ -14,9 +14,9 @@ private GroupDescriptions() { public static String getDescriptionForPreview(String field, String expr, boolean caseSensitive, boolean regExp) { String header = regExp ? Localization.lang( "This group contains entries whose %0 field contains the regular expression %1", - field, StringUtil.quoteForHTML(expr)) : Localization.lang( + field, expr) : Localization.lang( "This group contains entries whose %0 field contains the keyword %1", - field, StringUtil.quoteForHTML(expr)); + field, expr); String caseSensitiveText = caseSensitive ? Localization.lang("case sensitive") : Localization .lang("case insensitive"); String footer = regExp ? Localization @@ -30,7 +30,7 @@ public static String getDescriptionForPreview(String field, String expr, boolean + "then using the context menu. " + "This process removes the term %1 from " + "each entry's %0 field.", - field, StringUtil.quoteForHTML(expr)); + field, expr); return String.format("%s (%s). %s", header, caseSensitiveText, footer); } diff --git a/src/main/java/org/jabref/gui/groups/GroupDialog.java b/src/main/java/org/jabref/gui/groups/GroupDialog.java index 3d334919446..dc7d4ebd615 100644 --- a/src/main/java/org/jabref/gui/groups/GroupDialog.java +++ b/src/main/java/org/jabref/gui/groups/GroupDialog.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Optional; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -9,6 +10,7 @@ import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; +import javafx.geometry.Orientation; import javafx.scene.Node; import javafx.scene.control.ButtonType; import javafx.scene.control.CheckBox; @@ -16,6 +18,7 @@ import javafx.scene.control.RadioButton; import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane.ScrollBarPolicy; +import javafx.scene.control.Separator; import javafx.scene.control.TextField; import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; @@ -26,7 +29,6 @@ import javafx.scene.text.FontPosture; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; -import javafx.scene.web.WebView; import org.jabref.Globals; import org.jabref.JabRefGUI; @@ -104,7 +106,7 @@ class GroupDialog extends BaseDialog { private final TextField texGroupFilePath = new TextField(); // for all types - private final WebView descriptionWebView = new WebView(); + private final TextFlow descriptionTextFlow = new TextFlow(); private final StackPane optionsPanel = new StackPane(); @@ -120,7 +122,10 @@ public GroupDialog(JabRefFrame jabrefFrame, AbstractGroup editedGroup) { explicitRadioButton.setSelected(true); - descriptionWebView.setPrefWidth(585); + descriptionTextFlow.setMinWidth(585); + descriptionTextFlow.setPrefWidth(585); + descriptionTextFlow.setMinHeight(180); + descriptionTextFlow.setPrefHeight(180); // set default values (overwritten if editedGroup != null) keywordGroupSearchField.setText(jabrefFrame.prefs().get(JabRefPreferences.GROUPS_DEFAULT_FIELD)); @@ -196,26 +201,31 @@ public GroupDialog(JabRefFrame jabrefFrame, AbstractGroup editedGroup) { selectPanel.setPadding(new Insets(0, 0, 0, 10)); // Description panel - ScrollPane descriptionPane = new ScrollPane(descriptionWebView); + ScrollPane descriptionPane = new ScrollPane(descriptionTextFlow); descriptionPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED); descriptionPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED); // create layout - VBox mainPanel = new VBox(15); + HBox mainPanel = new HBox(15); getDialogPane().setContent(mainPanel); mainPanel.setPadding(new Insets(5, 15, 5, 15)); mainPanel.getChildren().setAll( - generalPanel, new VBox(5, - new Label(Localization.lang("Type")), - selectPanel - ), - new VBox( - new Label(Localization.lang("Options")), - optionsPanel + generalPanel, + new VBox(5, + new Label(Localization.lang("Type")), + selectPanel + ) ), - new Label(Localization.lang("Description")), - descriptionPane + new Separator(Orientation.VERTICAL), + new VBox(5, + new VBox( + new Label(Localization.lang("Options")), + optionsPanel + ), + new Label(Localization.lang("Description")), + descriptionPane + ) ); updateComponents(); @@ -393,6 +403,9 @@ groupName, getContext(), texGroupFilePath.setText(group.getFilePath().toString()); } } + + setResizable(false); + getDialogPane().getScene().getWindow().sizeToScene(); } public GroupDialog() { @@ -517,7 +530,7 @@ private void updateComponents() { boolean okEnabled = !nameField.getText().trim().isEmpty(); if (!okEnabled) { setDescription(Localization.lang("Please enter a name for the group.")); - //TODO: okButton.setDisable(true); + getDialogPane().lookupButton(ButtonType.OK).setDisable(true); return; } String s1; @@ -532,18 +545,18 @@ private void updateComponents() { try { Pattern.compile(s2); setDescription(GroupDescriptions.getDescriptionForPreview(s1, s2, keywordGroupCaseSensitive.isSelected(), - keywordGroupRegExp.isSelected())); + keywordGroupRegExp.isSelected())); } catch (PatternSyntaxException e) { okEnabled = false; setDescription(formatRegExException(s2, e)); } } else { setDescription(GroupDescriptions.getDescriptionForPreview(s1, s2, keywordGroupCaseSensitive.isSelected(), - keywordGroupRegExp.isSelected())); + keywordGroupRegExp.isSelected())); } } else { setDescription(Localization.lang( - "Please enter the field to search (e.g. keywords) and the keyword to search it for (e.g. electrical).")); + "Please enter the field to search (e.g. keywords) and the keyword to search it for (e.g. electrical).")); } setNameFontItalic(true); } else if (searchRadioButton.isSelected()) { @@ -551,8 +564,8 @@ private void updateComponents() { okEnabled = okEnabled & !s1.isEmpty(); if (okEnabled) { setDescription(fromTextFlowToHTMLString(SearchDescribers.getSearchDescriberFor( - new SearchQuery(s1, isCaseSensitive(), isRegex())) - .getDescription())); + new SearchQuery(s1, isCaseSensitive(), isRegex())) + .getDescription())); if (isRegex()) { try { @@ -564,17 +577,17 @@ private void updateComponents() { } } else { setDescription(Localization - .lang("Please enter a search term. For example, to search all fields for Smith, enter:

" - + "smith

" - + "To search the field Author for Smith and the field Title for electrical, enter:

" - + "author=smith and title=electrical")); + .lang("Please enter a search term. For example, to search all fields for Smith, enter:

" + + "smith

" + + "To search the field Author for Smith and the field Title for electrical, enter:

" + + "author=smith and title=electrical")); } setNameFontItalic(true); } else if (explicitRadioButton.isSelected()) { setDescription(GroupDescriptions.getDescriptionForPreview()); setNameFontItalic(false); } - //TODO: okButton.setDisable(!okEnabled); + getDialogPane().lookupButton(ButtonType.OK).setDisable(!okEnabled); } private String fromTextFlowToHTMLString(TextFlow textFlow) { @@ -596,7 +609,45 @@ private boolean isCaseSensitive() { } private void setDescription(String description) { - descriptionWebView.getEngine().loadContent("" + description + ""); + descriptionTextFlow.getChildren().setAll(createFormattedDescription(description)); + } + + private ArrayList createFormattedDescription(String descriptionHTML) { + ArrayList nodes = new ArrayList<>(); + + descriptionHTML = descriptionHTML.replaceAll("

|
", "\n"); + + String[] boldSplit = descriptionHTML.split("(?=)|(?<=)|(?=)|(?<=)|(?=)|(?<=)|(?=)|(?<=)"); + + for (String bs : boldSplit) { + + if (bs.matches("[^<>]*")) { + + bs = bs.replaceAll("|", ""); + Text textElement = new Text(bs); + textElement.setStyle("-fx-font-weight: bold"); + nodes.add(textElement); + + } else if (bs.matches("[^<>]*")) { + + bs = bs.replaceAll("|", ""); + Text textElement = new Text(bs); + textElement.setStyle("-fx-font-style: italic"); + nodes.add(textElement); + + } else if (bs.matches("[^<>]*|[^<>]*")) { + + bs = bs.replaceAll("|||", ""); + Text textElement = new Text(bs); + textElement.setStyle("-fx-font-family: 'Courier New', Courier, monospace"); + nodes.add(textElement); + + } else { + nodes.add(new Text(bs)); + } + } + + return nodes; } /** diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index ab1cb4449e6..de4c279e59c 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -106,7 +106,11 @@ private void onSelectedGroupChanged(ObservableList newValue) * Opens "New Group Dialog" and add the resulting group to the root */ public void addNewGroupToRoot() { - addNewSubgroup(rootGroup.get()); + if (currentDatabase.isPresent()) { + addNewSubgroup(rootGroup.get()); + } else { + dialogService.showWarningDialogAndWait(Localization.lang("Cannot create group"), Localization.lang("Cannot create group. Please create a library first.")); + } } /** @@ -124,8 +128,8 @@ private void onActiveDatabaseChanged(Optional newDatabase) { rootGroup.setValue(newRoot); this.selectedGroups.setAll( stateManager.getSelectedGroup(newDatabase.get()).stream() - .map(selectedGroup -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup, localDragboard)) - .collect(Collectors.toList())); + .map(selectedGroup -> new GroupNodeViewModel(newDatabase.get(), stateManager, taskExecutor, selectedGroup, localDragboard)) + .collect(Collectors.toList())); } else { rootGroup.setValue(GroupNodeViewModel.getAllEntriesGroup(new BibDatabaseContext(), stateManager, taskExecutor, localDragboard)); } @@ -228,7 +232,7 @@ public void removeGroupKeepSubgroups(GroupNodeViewModel group) { //panel.getUndoManager().addEdit(undo); GroupTreeNode groupNode = group.getGroupNode(); groupNode.getParent() - .ifPresent(parent -> groupNode.moveAllChildrenTo(parent, parent.getIndexOfChild(groupNode).get())); + .ifPresent(parent -> groupNode.moveAllChildrenTo(parent, parent.getIndexOfChild(groupNode).get())); groupNode.removeFromParent(); dialogService.notify(Localization.lang("Removed group \"%0\".", group.getDisplayName())); diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index af35ed23e3e..775e06a9ae7 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -127,6 +127,10 @@ Cancel=Abbrechen Cannot\ add\ entries\ to\ group\ without\ generating\ keys.\ Generate\ keys\ now?=Einträge können einer Gruppe nicht hinzugefügt werden, ohne Keys zu generieren. Sollen die Keys jetzt generiert werden? +Cannot\ create\ group=Gruppe kann nicht erstellt werden + +Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Gruppe kann nicht erstellt werden. Erstellen sie zuerst eine Bibliothek. + Cannot\ merge\ this\ change=Kann diese Änderung nicht einfügen case\ insensitive=Groß-/Kleinschreibung wird nicht unterschieden diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 9275461a40a..352b53bbb83 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -114,6 +114,10 @@ Cancel=Cancel Cannot\ add\ entries\ to\ group\ without\ generating\ keys.\ Generate\ keys\ now?=Cannot add entries to group without generating keys. Generate keys now? +Cannot\ create\ group=Cannot create group + +Cannot\ create\ group.\ Please\ create\ a\ library\ first.=Cannot create group. Please create a library first. + Cannot\ merge\ this\ change=Cannot merge this change case\ insensitive=case insensitive