Skip to content

Commit b7526e3

Browse files
committed
UI/UX: Highlighting search keyword in alert log content
1 parent 4310216 commit b7526e3

File tree

1 file changed

+69
-1
lines changed

1 file changed

+69
-1
lines changed

src/main/java/root/javafx/CustomView/AlertLogListViewCell.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
package root.javafx.CustomView;
22

33
import java.io.IOException;
4-
4+
import java.util.Collection;
5+
import java.util.Collections;
6+
import java.util.function.Consumer;
7+
import java.util.function.Function;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
11+
import org.fxmisc.richtext.GenericStyledArea;
512
import org.fxmisc.richtext.StyleClassedTextArea;
13+
import org.fxmisc.richtext.model.Paragraph;
14+
import org.fxmisc.richtext.model.StyleSpans;
15+
import org.fxmisc.richtext.model.StyleSpansBuilder;
16+
import org.reactfx.collection.ListModification;
617

718
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
19+
import javafx.application.Platform;
820
import javafx.fxml.FXML;
921
import javafx.fxml.FXMLLoader;
1022
import javafx.geometry.Insets;
@@ -24,6 +36,8 @@
2436
public class AlertLogListViewCell extends ListCell<Log> {
2537
private FXMLLoader loader;
2638

39+
private Pattern KEYWORD_PATTERN;
40+
2741
@FXML
2842
AnchorPane rootAP;
2943
@FXML
@@ -36,6 +50,11 @@ public class AlertLogListViewCell extends ListCell<Log> {
3650
HBox logContentHBox;
3751

3852
public AlertLogListViewCell(String... highlightKeywords) {
53+
String join = String.join("|", highlightKeywords);
54+
KEYWORD_PATTERN = Pattern.compile("(?<KEYWORD1>\\b(" + join + ")\\b)"
55+
+ "|(?<KEYWORD2>\\b(" + join + ")\\B)"
56+
+ "|(?<KEYWORD3>\\B(" + join + ")\\b)"
57+
+ "|(?<KEYWORD4>\\B(" + join + ")\\B)");
3958
}
4059

4160
@Override
@@ -80,6 +99,8 @@ protected void updateItem(Log logObj, boolean empty) {
8099
codeArea.getStylesheets()
81100
.add(getClass().getResource(baseDir + "/css/alertLogListViewCell.css").toExternalForm());
82101
codeArea.getStyleClass().add("code-area");
102+
codeArea.getVisibleParagraphs()
103+
.addModificationObserver(new VisibleParagraphStyler<>(codeArea, this::computeHighlighting));
83104

84105
codeArea.replaceText(0, 0, logObj.getFullLogString());
85106
if (isErrorLog) {
@@ -109,4 +130,51 @@ private boolean isErrorLog(String logContent) {
109130
// TODO Remove hard-coding that identifying error log
110131
return logContent.contains("ORA-");
111132
}
133+
134+
private StyleSpans<Collection<String>> computeHighlighting(String text) {
135+
Matcher matcher = KEYWORD_PATTERN.matcher(text);
136+
int lastKeywordEnd = 0;
137+
StyleSpansBuilder<Collection<String>> spansBuilder = new StyleSpansBuilder<>();
138+
while (matcher.find()) {
139+
String styleClass = matcher.group("KEYWORD1") != null ? "keyword"
140+
: matcher.group("KEYWORD2") != null ? "keyword"
141+
: matcher.group("KEYWORD3") != null ? "keyword"
142+
: matcher.group("KEYWORD4") != null ? "keyword" : null;
143+
spansBuilder.add(Collections.emptyList(), matcher.start() - lastKeywordEnd);
144+
spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start());
145+
lastKeywordEnd = matcher.end();
146+
}
147+
spansBuilder.add(Collections.emptyList(), text.length() - lastKeywordEnd);
148+
149+
return spansBuilder.create();
150+
}
151+
152+
private class VisibleParagraphStyler<PS, SEG, S>
153+
implements Consumer<ListModification<? extends Paragraph<PS, SEG, S>>> {
154+
private final GenericStyledArea<PS, SEG, S> area;
155+
private final Function<String, StyleSpans<S>> computeStyles;
156+
private int prevParagraph, prevTextLength;
157+
158+
public VisibleParagraphStyler(GenericStyledArea<PS, SEG, S> area,
159+
Function<String, StyleSpans<S>> computeStyles) {
160+
this.computeStyles = computeStyles;
161+
this.area = area;
162+
}
163+
164+
@Override
165+
public void accept(ListModification<? extends Paragraph<PS, SEG, S>> lm) {
166+
if (lm.getAddedSize() > 0) {
167+
int paragraph = Math.min(area.firstVisibleParToAllParIndex() + lm.getFrom(),
168+
area.getParagraphs().size() - 1);
169+
String text = area.getText(paragraph, 0, paragraph, area.getParagraphLength(paragraph));
170+
171+
if (paragraph != prevParagraph || text.length() != prevTextLength) {
172+
int startPos = area.getAbsolutePosition(paragraph, 0);
173+
Platform.runLater(() -> area.setStyleSpans(startPos, computeStyles.apply(text)));
174+
prevTextLength = text.length();
175+
prevParagraph = paragraph;
176+
}
177+
}
178+
}
179+
}
112180
}

0 commit comments

Comments
 (0)