diff --git a/src/main/java/com/imyeyu/fx/ui/components/TextFlower.java b/src/main/java/com/imyeyu/fx/ui/components/TextFlower.java deleted file mode 100644 index a6b6743..0000000 --- a/src/main/java/com/imyeyu/fx/ui/components/TextFlower.java +++ /dev/null @@ -1,334 +0,0 @@ -package com.imyeyu.fx.ui.components; - -import com.imyeyu.fx.icon.TimiFXIcon; -import com.imyeyu.fx.ui.TimiFXUI; -import com.imyeyu.java.TimiJava; -import javafx.scene.Node; -import javafx.scene.paint.Paint; -import javafx.scene.text.Text; -import javafx.scene.text.TextFlow; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * 文本流组件,支持插入超链文本,解析富文本:{@link #matcher(String)} - * - * @author 夜雨 - * @since 2022-09-05 10:41 - */ -public class TextFlower extends TextFlow implements TimiFXUI { - - /** 默认构造器 */ - public TextFlower() { - getStyleClass().add(CSS.MINECRAFT); - } - - /** - * 文本开始,添加一个制表符 - * - * @return 本实例 - */ - public TextFlower textStart() { - getChildren().add(new Text("\t")); - return this; - } - - /** - * 追加文本,左侧补充一个制表符,通常是段落开始 - * - * @param text 文本 - * @return 本实例 - */ - public TextFlower textStart(String text) { - getChildren().add(new Text("\t" + text)); - return this; - } - - /** - * 追加文本 - * - * @param text 文本 - * @return 本实例 - */ - public TextFlower text(String text) { - getChildren().add(new Text(text)); - return this; - } - - /** - * 追加文本,左侧补充空格 - * - * @param text 文本 - * @return 本实例 - */ - public TextFlower textLSP(String text) { - getChildren().add(new Text(" " + text)); - return this; - } - - /** - * 追加文本,右侧补充空格 - * - * @param text 文本 - * @return 本实例 - */ - public TextFlower textRSP(String text) { - getChildren().add(new Text(text + " ")); - return this; - } - - /** - * 追加链接文本 - * - * @param text 显示文本 - * @param link 访问链接 - * @return 本实例 - */ - public TextFlower link(String text, String link) { - getChildren().add(new XHyperlink(text, link)); - return this; - } - - /** - * 追加链接文本 - * - * @param icon 图标 - * @param text 显示文本 - * @param link 访问链接 - * @return 本实例 - */ - public TextFlower link(Node icon, String text, String link) { - getChildren().add(new XHyperlink(icon, text, link)); - return this; - } - - /** - * 追加链接,显示文本为链接 - * - * @param value 内容 - * @return 本实例 - */ - public TextFlower syncLink(String value) { - getChildren().add(new XHyperlink(value, value)); - return this; - } - - /** - * 设置最后一个文本节点为链接 - * - * @param link 链接 - * @return 本实例 - */ - public TextFlower asLink(String link) { - Node text = getChildren().removeLast(); - if (text instanceof Text t) { - getChildren().add(new XHyperlink(t.getText(), link)); - } - return this; - } - - /** - * 富文本匹配解析字符串,转义使用 '\' - *
- *

格式标准: - *

- * - * @param value 字符串 - * @return 本实例 - */ - public TextFlower matcher(String value) { - if (TimiJava.isNotEmpty(value)) { - getChildren().addAll(RichMatcher.parse(value)); - } - return this; - } - - /** - * 富文本匹配 - * - * @author 夜雨 - * @since 2022-10-10 11:23 - */ - private static class RichMatcher { - - /** - * 匹配正则 - * - * @author 夜雨 - * @since 2022-10-10 11:58 - */ - private enum Regex { - - LINK("\\[(.*?)]"), - - ICON("<(.*?)>"), - - SPAN("`(.*?)`"); - - final Pattern pattern; - - Regex(String regex) { - this.pattern = Pattern.compile(regex); - } - } - - /** - * 重点内容样式 - * - * @author 夜雨 - * @since 2022-10-10 11:58 - */ - private enum Style { - - UNDERLINE("u", "underline"); - - private final String[] matches; - - Style(String... matches) { - this.matches = matches; - } - - static Style fromMatcher(String matcher) { - Style[] values = values(); - for (Style value : values) { - String[] matches = value.matches; - for (String match : matches) { - if (match.equalsIgnoreCase(matcher)) { - return value; - } - } - } - return null; - } - } - - /** - * 解析富文本匹配 - * - * @param data 文本内容 - * @return 匹配节点列表 - */ - static List parse(String data) { - List result = new ArrayList<>(); - - Regex[] regexes = Regex.values(); - - Map nodeMap = new HashMap<>(); - - int[] insertI = {0}; - String value = data; - Matcher matcher; - for (int i = 0; i < regexes.length; i++) { - final int j = i; - matcher = regexes[i].pattern.matcher(value); - - value = matcher.replaceAll(matchResult -> { - if (matchResult.start() - 1 != -1) { - if (data.charAt(matchResult.start() - 1) == '\\') { - return matchResult.group(); - } - } - nodeMap.put(String.valueOf(insertI[0]), node(regexes[j], value(regexes[j], matchResult.group()))); - return "[" + insertI[0]++ + "]"; - }); - } - - // 二次解析 - matcher = Pattern.compile("\\[(.*?)]").matcher(value); - int end = 0; - while (matcher.find()) { - if (matcher.start() - 1 != -1) { - if (data.charAt(matcher.start() - 1) == '\\') { - continue; - } - } - if (end != matcher.start()) { - result.add(new Text(value.substring(end, matcher.start()))); - } - result.add(nodeMap.get(value(Regex.LINK, matcher.group()))); - end = matcher.end(); - } - result.add(new Text(value.substring(end))); - return result; - } - - /** - * 解析正则匹配值 - * - * @param regex 匹配正则 - * @param matcherResult 匹配结果 - * @return 匹配值 - */ - private static String value(Regex regex, String matcherResult) { - return switch (regex) { - case LINK, ICON, SPAN -> matcherResult.substring(1, matcherResult.length() - 1); - }; - } - - /** - * 解析节点 - * - * @param regex 匹配正则 - * @param value 匹配值 - * @return 节点 - */ - private static Node node(Regex regex, String value) { - return switch (regex) { - // 超链 - case LINK -> { - int sp = value.indexOf(","); - if (sp == -1) { - yield new XHyperlink(value.trim()); - } else { - while (value.charAt(sp - 1) == '\\') { - sp = value.indexOf(",", sp + 1); - } - yield new XHyperlink(value.substring(0, sp).trim(), value.substring(sp + 1).trim()); - } - } - // 图标 - case ICON -> { - Text icon; - int sp = value.lastIndexOf(","); - if (sp == -1) { - icon = TimiFXIcon.fromName(value); - } else { - icon = TimiFXIcon.fromName(value.substring(sp + 1).trim()); - icon.setFill(Paint.valueOf(value.substring(0, sp).trim())); - } - yield icon; - } - // 重点内容 - case SPAN -> { - int sp = value.indexOf(","); - if (sp == -1) { - yield new Text(value); - } else { - Text text = new Text(value.substring(sp + 1).trim()); - String[] styles = value.substring(0, sp).trim().split(" "); - for (String s : styles) { - Style style = Style.fromMatcher(s); - if (style == null) { - text.setFill(Paint.valueOf(s)); - } else { - if (style == Style.UNDERLINE) { - text.setUnderline(true); - } - } - } - yield text; - } - } - }; - } - } -}