Skip to content

Commit 40138d6

Browse files
committed
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 JabRef#4610
1 parent 891a93b commit 40138d6

File tree

2 files changed

+80
-29
lines changed

2 files changed

+80
-29
lines changed

src/main/java/org/jabref/gui/groups/GroupDescriptions.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ private GroupDescriptions() {
1414
public static String getDescriptionForPreview(String field, String expr, boolean caseSensitive, boolean regExp) {
1515
String header = regExp ? Localization.lang(
1616
"This group contains entries whose <b>%0</b> field contains the regular expression <b>%1</b>",
17-
field, StringUtil.quoteForHTML(expr)) : Localization.lang(
17+
field, expr) : Localization.lang(
1818
"This group contains entries whose <b>%0</b> field contains the keyword <b>%1</b>",
19-
field, StringUtil.quoteForHTML(expr));
19+
field, expr);
2020
String caseSensitiveText = caseSensitive ? Localization.lang("case sensitive") : Localization
2121
.lang("case insensitive");
2222
String footer = regExp ? Localization
@@ -30,7 +30,7 @@ public static String getDescriptionForPreview(String field, String expr, boolean
3030
+ "then using the context menu. "
3131
+ "This process removes the term <b>%1</b> from "
3232
+ "each entry's <b>%0</b> field.",
33-
field, StringUtil.quoteForHTML(expr));
33+
field, expr);
3434
return String.format("%s (%s). %s", header, caseSensitiveText, footer);
3535
}
3636

src/main/java/org/jabref/gui/groups/GroupDialog.java

+77-26
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@
22

33
import java.io.IOException;
44
import java.nio.file.Paths;
5+
import java.util.ArrayList;
56
import java.util.Optional;
67
import java.util.regex.Pattern;
78
import java.util.regex.PatternSyntaxException;
89

910
import javafx.beans.value.ChangeListener;
1011
import javafx.beans.value.ObservableValue;
1112
import javafx.geometry.Insets;
13+
import javafx.geometry.Orientation;
1214
import javafx.scene.Node;
1315
import javafx.scene.control.ButtonType;
1416
import javafx.scene.control.CheckBox;
1517
import javafx.scene.control.Label;
1618
import javafx.scene.control.RadioButton;
1719
import javafx.scene.control.ScrollPane;
1820
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
21+
import javafx.scene.control.Separator;
1922
import javafx.scene.control.TextField;
2023
import javafx.scene.control.Toggle;
2124
import javafx.scene.control.ToggleGroup;
@@ -26,7 +29,6 @@
2629
import javafx.scene.text.FontPosture;
2730
import javafx.scene.text.Text;
2831
import javafx.scene.text.TextFlow;
29-
import javafx.scene.web.WebView;
3032

3133
import org.jabref.Globals;
3234
import org.jabref.JabRefGUI;
@@ -104,7 +106,7 @@ class GroupDialog extends BaseDialog<AbstractGroup> {
104106
private final TextField texGroupFilePath = new TextField();
105107

106108
// for all types
107-
private final WebView descriptionWebView = new WebView();
109+
private final TextFlow descriptionTextFlow = new TextFlow();
108110
private final StackPane optionsPanel = new StackPane();
109111

110112

@@ -120,7 +122,10 @@ public GroupDialog(JabRefFrame jabrefFrame, AbstractGroup editedGroup) {
120122

121123
explicitRadioButton.setSelected(true);
122124

123-
descriptionWebView.setPrefWidth(585);
125+
descriptionTextFlow.setMinWidth(585);
126+
descriptionTextFlow.setPrefWidth(585);
127+
descriptionTextFlow.setMinHeight(180);
128+
descriptionTextFlow.setPrefHeight(180);
124129

125130
// set default values (overwritten if editedGroup != null)
126131
keywordGroupSearchField.setText(jabrefFrame.prefs().get(JabRefPreferences.GROUPS_DEFAULT_FIELD));
@@ -196,26 +201,31 @@ public GroupDialog(JabRefFrame jabrefFrame, AbstractGroup editedGroup) {
196201
selectPanel.setPadding(new Insets(0, 0, 0, 10));
197202

198203
// Description panel
199-
ScrollPane descriptionPane = new ScrollPane(descriptionWebView);
204+
ScrollPane descriptionPane = new ScrollPane(descriptionTextFlow);
200205
descriptionPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
201206
descriptionPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
202207

203208
// create layout
204-
VBox mainPanel = new VBox(15);
209+
HBox mainPanel = new HBox(15);
205210
getDialogPane().setContent(mainPanel);
206211
mainPanel.setPadding(new Insets(5, 15, 5, 15));
207212
mainPanel.getChildren().setAll(
208-
generalPanel,
209213
new VBox(5,
210-
new Label(Localization.lang("Type")),
211-
selectPanel
212-
),
213-
new VBox(
214-
new Label(Localization.lang("Options")),
215-
optionsPanel
214+
generalPanel,
215+
new VBox(5,
216+
new Label(Localization.lang("Type")),
217+
selectPanel
218+
)
216219
),
217-
new Label(Localization.lang("Description")),
218-
descriptionPane
220+
new Separator(Orientation.VERTICAL),
221+
new VBox(5,
222+
new VBox(
223+
new Label(Localization.lang("Options")),
224+
optionsPanel
225+
),
226+
new Label(Localization.lang("Description")),
227+
descriptionPane
228+
)
219229
);
220230

221231
updateComponents();
@@ -393,6 +403,9 @@ groupName, getContext(),
393403
texGroupFilePath.setText(group.getFilePath().toString());
394404
}
395405
}
406+
407+
setResizable(false);
408+
getDialogPane().getScene().getWindow().sizeToScene();
396409
}
397410

398411
public GroupDialog() {
@@ -517,7 +530,7 @@ private void updateComponents() {
517530
boolean okEnabled = !nameField.getText().trim().isEmpty();
518531
if (!okEnabled) {
519532
setDescription(Localization.lang("Please enter a name for the group."));
520-
//TODO: okButton.setDisable(true);
533+
getDialogPane().lookupButton(ButtonType.OK).setDisable(true);
521534
return;
522535
}
523536
String s1;
@@ -532,27 +545,27 @@ private void updateComponents() {
532545
try {
533546
Pattern.compile(s2);
534547
setDescription(GroupDescriptions.getDescriptionForPreview(s1, s2, keywordGroupCaseSensitive.isSelected(),
535-
keywordGroupRegExp.isSelected()));
548+
keywordGroupRegExp.isSelected()));
536549
} catch (PatternSyntaxException e) {
537550
okEnabled = false;
538551
setDescription(formatRegExException(s2, e));
539552
}
540553
} else {
541554
setDescription(GroupDescriptions.getDescriptionForPreview(s1, s2, keywordGroupCaseSensitive.isSelected(),
542-
keywordGroupRegExp.isSelected()));
555+
keywordGroupRegExp.isSelected()));
543556
}
544557
} else {
545558
setDescription(Localization.lang(
546-
"Please enter the field to search (e.g. <b>keywords</b>) and the keyword to search it for (e.g. <b>electrical</b>)."));
559+
"Please enter the field to search (e.g. <b>keywords</b>) and the keyword to search it for (e.g. <b>electrical</b>)."));
547560
}
548561
setNameFontItalic(true);
549562
} else if (searchRadioButton.isSelected()) {
550563
s1 = searchGroupSearchExpression.getText().trim();
551564
okEnabled = okEnabled & !s1.isEmpty();
552565
if (okEnabled) {
553566
setDescription(fromTextFlowToHTMLString(SearchDescribers.getSearchDescriberFor(
554-
new SearchQuery(s1, isCaseSensitive(), isRegex()))
555-
.getDescription()));
567+
new SearchQuery(s1, isCaseSensitive(), isRegex()))
568+
.getDescription()));
556569

557570
if (isRegex()) {
558571
try {
@@ -564,17 +577,17 @@ private void updateComponents() {
564577
}
565578
} else {
566579
setDescription(Localization
567-
.lang("Please enter a search term. For example, to search all fields for <b>Smith</b>, enter:<p>"
568-
+ "<tt>smith</tt><p>"
569-
+ "To search the field <b>Author</b> for <b>Smith</b> and the field <b>Title</b> for <b>electrical</b>, enter:<p>"
570-
+ "<tt>author=smith and title=electrical</tt>"));
580+
.lang("Please enter a search term. For example, to search all fields for <b>Smith</b>, enter:<p>"
581+
+ "<tt>smith</tt><p>"
582+
+ "To search the field <b>Author</b> for <b>Smith</b> and the field <b>Title</b> for <b>electrical</b>, enter:<p>"
583+
+ "<tt>author=smith and title=electrical</tt>"));
571584
}
572585
setNameFontItalic(true);
573586
} else if (explicitRadioButton.isSelected()) {
574587
setDescription(GroupDescriptions.getDescriptionForPreview());
575588
setNameFontItalic(false);
576589
}
577-
//TODO: okButton.setDisable(!okEnabled);
590+
getDialogPane().lookupButton(ButtonType.OK).setDisable(!okEnabled);
578591
}
579592

580593
private String fromTextFlowToHTMLString(TextFlow textFlow) {
@@ -596,7 +609,45 @@ private boolean isCaseSensitive() {
596609
}
597610

598611
private void setDescription(String description) {
599-
descriptionWebView.getEngine().loadContent("<html>" + description + "</html>");
612+
descriptionTextFlow.getChildren().setAll(createFormattedDescription(description));
613+
}
614+
615+
private ArrayList<Node> createFormattedDescription(String description) {
616+
ArrayList<Node> nodes = new ArrayList<>();
617+
618+
description = description.replaceAll("<p>|<br>", "\n");
619+
620+
String[] boldSplit = description.split("(?=<b>)|(?<=</b>)|(?=<i>)|(?<=</i>)|(?=<tt>)|(?<=</tt>)|(?=<kbd>)|(?<=</kbd>)");
621+
622+
for (String bs : boldSplit) {
623+
624+
if (bs.matches("<b>[^<>]*</b>")) {
625+
626+
bs = bs.replaceAll("<b>|</b>", "");
627+
Text textElement = new Text(bs);
628+
textElement.setStyle("-fx-font-weight: bold");
629+
nodes.add(textElement);
630+
631+
} else if (bs.matches("<i>[^<>]*</i>")) {
632+
633+
bs = bs.replaceAll("<i>|</i>", "");
634+
Text textElement = new Text(bs);
635+
textElement.setStyle("-fx-font-style: italic");
636+
nodes.add(textElement);
637+
638+
} else if (bs.matches("<tt>[^<>]*</tt>|<kbd>[^<>]*</kbd>")) {
639+
640+
bs = bs.replaceAll("<tt>|</tt>|<kbd>|</kbd>", "");
641+
Text textElement = new Text(bs);
642+
textElement.setStyle("-fx-font-family: 'Courier New', Courier, monospace");
643+
nodes.add(textElement);
644+
645+
} else {
646+
nodes.add(new Text(bs));
647+
}
648+
}
649+
650+
return nodes;
600651
}
601652

602653
/**

0 commit comments

Comments
 (0)