173 lines
4.4 KiB
Java
173 lines
4.4 KiB
Java
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().getFirst() 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 (Node node : list) {
|
||
if (node 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;
|
||
}
|
||
}
|