Initial project

This commit is contained in:
Timi
2025-07-14 15:08:16 +08:00
parent c26de45a80
commit 40f556d0e1
133 changed files with 15044 additions and 95 deletions

View File

@@ -0,0 +1,172 @@
package com.imyeyu.fx.ui.components;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.java.ref.Ref;
import com.sun.javafx.scene.control.skin.Utils;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Skin;
import javafx.scene.control.TextArea;
import javafx.scene.control.skin.TextAreaSkin;
import javafx.scene.layout.Region;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import java.util.List;
/**
* 可选中的标签组件,实际上是无样式文本域,此组件适应布局最大宽度
*
* @author 夜雨
* @since 2022-01-29 01:24
*/
public class SelectableLabel extends TextArea implements TimiFXUI, TimiFXUI.Colorful {
private static final String STYLE_CLASS = "selectable-label";
private final ObjectProperty<Paint> textFillProperty;
private final ObjectProperty<TextAlignment> textAlignmentProperty;
/** 默认构造 */
public SelectableLabel() {
this("");
}
/**
* 构造器
*
* @param text 文本内容
*/
public SelectableLabel(String text) {
super(text);
textFillProperty = new SimpleObjectProperty<>(BLACK);
textAlignmentProperty = new SimpleObjectProperty<>(TextAlignment.LEFT);
setCursor(Cursor.TEXT);
setEditable(false);
setWrapText(true);
setMaxWidth(Double.MAX_VALUE);
setMinSize(Double.MIN_VALUE, Double.MIN_VALUE);
setPrefHeight(0);
setPrefSize(0, 0);
getStyleClass().setAll(STYLE_CLASS, CSS.MINECRAFT);
focusedProperty().addListener((obs, o, isFocused) -> {
if (!isFocused) {
deselect();
}
});
}
@Override
protected Skin<?> createDefaultSkin() {
Skin<?> defaultSkin = super.createDefaultSkin();
if (defaultSkin instanceof TextAreaSkin skin) {
try {
ScrollPane sp = Ref.getFieldValue(skin, "scrollPane", ScrollPane.class);
sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
if (sp.getContent() instanceof Region region) {
region.heightProperty().addListener((obs, o, newHeight) -> Platform.runLater(() -> {
// 需要 runLater因为是 Region 适应 Skin 变化
setPrefHeight(newHeight.doubleValue());
}));
}
Group paragraphNodes = Ref.getFieldValue(skin, "paragraphNodes", Group.class);
paragraphNodes.getChildren().addListener((ListChangeListener<Node>) c -> {
if (c.next()) {
if (c.wasAdded()) {
bindTextStyle(c.getAddedSubList());
}
}
});
bindTextStyle(paragraphNodes.getChildren());
widthProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue.doubleValue() < newValue.doubleValue()) {
if (paragraphNodes.getChildren().get(0) instanceof Text text) {
setPrefHeight(Utils.computeTextHeight(getFont(), getText(), getWidth(), text.getBoundsType()));
}
}
});
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return defaultSkin;
}
/**
* 绑定文本样式
*
* @param list 文本节点,必须是 {@link Text}
*/
private void bindTextStyle(List<? extends Node> list) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof Text text) {
text.fillProperty().bind(textFillProperty);
text.textAlignmentProperty().bind(textAlignmentProperty);
}
}
}
/**
* 设置字体颜色
*
* @param textFill 字体颜色
*/
public void setTextFill(Paint textFill) {
this.textFillProperty.set(textFill);
}
/**
* 获取字体颜色
*
* @return 字体颜色
*/
public Paint getTextFill() {
return textFillProperty.get();
}
/**
* 获取字体颜色绑定
*
* @return 字体颜色绑定
*/
public ObjectProperty<Paint> textFillProperty() {
return textFillProperty;
}
/**
* 设置文本对齐方式
*
* @param textAlignment 文本对齐方式
*/
public void setTextAlignment(TextAlignment textAlignment) {
this.textAlignmentProperty.set(textAlignment);
}
/**
* 获取文本对齐方式
*
* @return 文本对齐方式
*/
public TextAlignment getTextAlignment() {
return textAlignmentProperty.get();
}
/**
* 获取文本对齐方式绑定
*
* @return 文本对齐方式绑定
*/
public ObjectProperty<TextAlignment> textAlignmentProperty() {
return textAlignmentProperty;
}
}