Browse Source

Merge remote-tracking branch 'origin/release/11.0' into release/11.0

release/11.0
Destiny.Lin 4 weeks ago
parent
commit
0fa76edd3a
  1. 21
      designer-base/src/main/java/com/fr/design/fun/DefaultValueAdjustProvider.java
  2. 11
      designer-base/src/main/java/com/fr/design/jxbrowser/JxUIPane.java
  3. 20
      designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java
  4. 32
      designer-base/src/main/java/com/fr/design/style/color/ColorConfig.java
  5. 28
      designer-base/src/main/java/com/fr/design/style/color/DeriveAlgorithm.java
  6. 22
      designer-base/src/main/java/com/fr/design/style/color/FRColorSelectorStyle.java
  7. 32
      designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java
  8. 9
      designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java
  9. 2
      designer-chart/src/main/resources/com/fr/design/editor/script/editor.js
  10. 50
      designer-form/src/main/java/com/fr/design/mainframe/FormArea.java
  11. 260
      designer-form/src/main/java/com/fr/design/mainframe/guide/FvsGuidePane.java

21
designer-base/src/main/java/com/fr/design/fun/DefaultValueAdjustProvider.java

@ -3,11 +3,15 @@ package com.fr.design.fun;
import com.fr.base.Utils;
import com.fr.base.chart.BaseChartCollection;
import com.fr.chartx.attr.ChartProvider;
import com.fr.design.style.color.FRColorSelectorStyle;
import com.fr.general.FRFont;
import com.fr.report.cell.CellElement;
import com.fr.stable.collections.combination.Pair;
import com.fr.stable.fun.mark.Selectable;
import java.awt.Color;
import java.awt.Font;
import java.util.List;
/**
* 主要用于fvs报表块内元素默认值的调整以达到所见所得效果后续fvs内置后删除
@ -56,10 +60,27 @@ public interface DefaultValueAdjustProvider extends Selectable {
/**
* 修改设计可用字体默认列表
*
* @return
*/
default String[] getAvailableFontFamilyNames4Report() {
return Utils.getAvailableFontFamilyNames4Report();
}
/**
* 修改配色方案默认值
* @return
*/
default Pair<Color[], Color[]> adjustChartDefaultColorFill() {
return new Pair<>(new Color[0], new Color[0]);
}
/**
* 支持插件自定义主题色选择器风格
* @return 颜色配置list
*/
default List getColorSelector(){
return FRColorSelectorStyle.COLOR_CONFIG;
}
}

11
designer-base/src/main/java/com/fr/design/jxbrowser/JxUIPane.java

@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@ -68,12 +69,22 @@ public class JxUIPane<T> extends ModernUIPane<T> {
if (browser != null) {
return;
}
hackInITInnovationLinuxDesktop();
initDebugIfNeeded();
// 使用公共引擎创建浏览器
browser = JxEngine.getPublicEngineInstance().newBrowser();
add(BrowserView.newInstance(browser), BorderLayout.CENTER);
}
/**
* hack部分 Linux 信创桌面打开需要先初始化 Desktop
*/
private static void hackInITInnovationLinuxDesktop() {
if (OperatingSystem.isLinux()) {
Desktop.getDesktop();
}
}
/**
* 按需初始化debug界面UI
*/

20
designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java

@ -9,6 +9,7 @@ import com.fr.config.predefined.PredefinedColorStyle;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.constants.LayoutConstants;
import com.fr.design.event.UIObserverListener;
import com.fr.design.fun.DefaultValueAdjustProvider;
import com.fr.design.gui.icombobox.ColorSchemeComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
@ -17,7 +18,9 @@ import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.style.background.gradient.FixedGradientBarNoTheme;
import com.fr.design.style.color.ColorAdjustPane;
import com.fr.design.utils.DesignUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.combination.Pair;
import javax.swing.JPanel;
import java.util.Arrays;
@ -70,9 +73,20 @@ public class ColorFillStylePane extends BasicBeanPane<ColorFillStyle> {
changeColorSetPane = new JPanel(cardLayout = new CardLayout());
changeColorSetPane.add(colorGradient = new FixedGradientBarNoTheme(4, 130), "gradient");
gradientColors = new Color[]{Color.WHITE, FixedGradientBarNoTheme.NEW_CHARACTER};
changeColorSetPane.add(colorAdjustPane = new ColorAdjustPane(), "acc");
accColors = ColorAdjustPane.DEFAULT_COLORS;
DefaultValueAdjustProvider adjustProvider = DesignUtils.getValueAdjust();
if (adjustProvider != null) {
Pair<Color[], Color[]> pair = adjustProvider.adjustChartDefaultColorFill();
Color[] groupColors = pair.getFirst();
colorAdjustPane = new ColorAdjustPane(groupColors);
gradientColors = pair.getSecond();
accColors = groupColors;
} else {
colorAdjustPane = new ColorAdjustPane();
gradientColors = new Color[]{Color.WHITE, FixedGradientBarNoTheme.NEW_CHARACTER};
accColors = ColorAdjustPane.DEFAULT_COLORS;
}
changeColorSetPane.add(colorAdjustPane , "acc");
cardLayout.show(changeColorSetPane, "acc");
customPane.add(changeColorSetPane, BorderLayout.CENTER);
initListener();

32
designer-base/src/main/java/com/fr/design/style/color/ColorConfig.java

@ -0,0 +1,32 @@
package com.fr.design.style.color;
import java.awt.Color;
/**
* 颜色选择器中单元颜色具体配置
*/
public class ColorConfig {
private boolean supportTheme;
private DeriveAlgorithm algorithm;
private ColorConfig(boolean supportTheme, DeriveAlgorithm algorithm) {
this.supportTheme = supportTheme;
this.algorithm = algorithm;
}
public static ColorConfig createThemeColorConfig(DeriveAlgorithm deriveAlgorithm) {
return new ColorConfig(true, deriveAlgorithm);
}
public static ColorConfig createThemeColorConfig(boolean supportTheme, DeriveAlgorithm deriveAlgorithm) {
return new ColorConfig(supportTheme, deriveAlgorithm);
}
public boolean isSupportTheme() {
return supportTheme;
}
public Color[] getDeriveColorArr(Color color, int defaultDeriveCount) {
return algorithm.getDeriveColorArr(color, defaultDeriveCount);
}
}

28
designer-base/src/main/java/com/fr/design/style/color/DeriveAlgorithm.java

@ -0,0 +1,28 @@
package com.fr.design.style.color;
import com.fr.base.theme.FineColorDeriveState;
import java.awt.Color;
public interface DeriveAlgorithm {
/**
* 通用的衍生规则
*/
DeriveAlgorithm PLAIN_ALGORITHM = new DeriveAlgorithm() {
@Override
public Color[] getDeriveColorArr(Color color, int defaultDeriveCount) {
return FineColorDeriveState.getDeriveColorArr(color, false, defaultDeriveCount);
}
};
/**
* 默认的衍生规则主要针对字体和背景
*/
DeriveAlgorithm DEFAULT_DERIVE_ALGORITHM = new DeriveAlgorithm() {
public Color[] getDeriveColorArr(Color color, int defaultDeriveCount) {
return FineColorDeriveState.getDeriveColorArr(color, true, defaultDeriveCount);
}
};
Color[] getDeriveColorArr(Color color, int defaultDeriveCount);
}

22
designer-base/src/main/java/com/fr/design/style/color/FRColorSelectorStyle.java

@ -0,0 +1,22 @@
package com.fr.design.style.color;
import java.util.ArrayList;
import java.util.List;
public class FRColorSelectorStyle {
public static final List<ColorConfig> COLOR_CONFIG = new ArrayList<>();
static {
// 8列主题色
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(DeriveAlgorithm.PLAIN_ALGORITHM));
// 2列灰度色
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(false, DeriveAlgorithm.DEFAULT_DERIVE_ALGORITHM));
COLOR_CONFIG.add(ColorConfig.createThemeColorConfig(false, DeriveAlgorithm.DEFAULT_DERIVE_ALGORITHM));
}
}

32
designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java

@ -1,13 +1,13 @@
package com.fr.design.style.color;
import com.fr.base.FineColor;
import com.fr.base.theme.FineColorDeriveState;
import com.fr.base.theme.TemplateTheme;
import com.fr.design.DesignerEnvManager;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.DefaultValueAdjustProvider;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
@ -15,6 +15,7 @@ import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog;
import com.fr.design.utils.DesignUtils;
import javax.swing.BorderFactory;
import javax.swing.JButton;
@ -60,6 +61,8 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
private final JPanel menuColorPane;
private ColorCell[][] themeColorCellGrid;
private List<ColorConfig> colorSelector ;
public static NewColorSelectPane createColorSelectPaneWithTheme(boolean supportTheme) {
return new NewColorSelectPane(true, supportTheme);
}
@ -156,7 +159,11 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
JPanel centerPane = new JPanel(new GridLayout(1, 8, DEFAULT_COLOR_HOR_INTERVAL, 0));
menuColorPane.add(northPane, BorderLayout.NORTH);
menuColorPane.add(centerPane, BorderLayout.CENTER);
this.colorSelector = FRColorSelectorStyle.COLOR_CONFIG;
DefaultValueAdjustProvider valueAdjust = DesignUtils.getValueAdjust();
if (valueAdjust != null) {
this.colorSelector = valueAdjust.getColorSelector();
}
Color[] colorArray = new Color[]{
// 8列主题色
Color.decode("#FFFFFF"),
@ -177,11 +184,11 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
themeColorCellGrid = new ColorCell[colorArray.length][DEFAULT_DERIVE_COUNT];
for (int i = 0; i < colorArray.length; i++) {
ColorCell[] colorCellColumn = new ColorCell[DEFAULT_DERIVE_COUNT];
boolean isDefaultColor = (i == colorArray.length - 1 || i == colorArray.length - 2);
ColorConfig colorConfig = getColorConfig(colorSelector, i);
Color color = colorArray[i];
Color[] deriveColorArr = FineColorDeriveState.getDeriveColorArr(color, isDefaultColor, DEFAULT_DERIVE_COUNT);
Color[] deriveColorArr = colorConfig.getDeriveColorArr(color, DEFAULT_DERIVE_COUNT);
for (int j = 0; j < deriveColorArr.length; j++) {
colorCellColumn[j] = createFineColorCell(deriveColorArr[j], isDefaultColor, i, j);
colorCellColumn[j] = createFineColorCell(deriveColorArr[j], !colorConfig.isSupportTheme(), i, j);
}
themeColorCellGrid[i] = colorCellColumn;
}
@ -218,10 +225,10 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
if (standardColors == null || standardColors.size() < 8) {
return;
}
for (int i = 0; i < themeColorCellGrid.length - 2; i++) {
Color color = standardColors.get(i);
Color[] deriveColorArr = FineColorDeriveState.getDeriveColorArr(color, false, DEFAULT_DERIVE_COUNT);
for (int i = 0; i < standardColors.size(); i++) {
Color standardColor = standardColors.get(i);
ColorConfig colorConfig = getColorConfig(colorSelector, i);
Color[] deriveColorArr = colorConfig.getDeriveColorArr(standardColor, DEFAULT_DERIVE_COUNT);
for (int j = 0; j < deriveColorArr.length; j++) {
themeColorCellGrid[i][j].setColor(deriveColorArr[j]);
}
@ -448,4 +455,11 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable {
}
public ColorConfig getColorConfig(List<ColorConfig> colorConfigs, int i) {
if (i < 0 || i >= colorConfigs.size()) {
return colorConfigs.get(0);
}
return colorConfigs.get(i);
}
}

9
designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java

@ -56,10 +56,11 @@ public class DefaultStyleHelper4Van {
dealChartColor((VanChart) chartProvider);
// //主题中没有的 根据主题深浅色自动 的属性 默认自动
// ((VanChart) chart4Update).setAutoThemeCustom();
DefaultValueAdjustProvider adjustProvider = DesignUtils.getValueAdjust();
if (adjustProvider != null) {
adjustProvider.adjustChart(chartProvider);
}
}
DefaultValueAdjustProvider adjustProvider = DesignUtils.getValueAdjust();
if (adjustProvider != null) {
adjustProvider.adjustChart(chartProvider);
}
}

2
designer-chart/src/main/resources/com/fr/design/editor/script/editor.js

@ -129,7 +129,7 @@
return;
}
value = window.transformI18nText(value);
value = window.transformI18nText(value) ? window.transformI18nText(value) : value;
str += " " + key + "=\"" + value + "\"";

50
designer-form/src/main/java/com/fr/design/mainframe/FormArea.java

@ -17,6 +17,7 @@ import com.fr.design.gui.itextfield.UINumberField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.guide.FvsGuidePane;
import com.fr.design.mainframe.share.ui.base.PopupMenuItem;
import com.fr.design.scrollruler.BaseRuler;
import com.fr.design.scrollruler.HorizontalRuler;
@ -30,6 +31,7 @@ import com.fr.form.main.mobile.FormMobileAttr;
import com.fr.form.ui.container.WBodyLayoutType;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRScreen;
import com.fr.general.IOUtils;
import com.fr.stable.AssistUtils;
@ -105,6 +107,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
if (useScrollBar) {
this.setLayout(new FormRulerLayout());
designer.setBorder(new LineBorder(new Color(198, 198, 198)));
this.add(FormRulerLayout.FVS_GUIDE, new FvsGuidePane(this));
this.add(FormRulerLayout.CENTER, designer);
addFormSize();
this.add(FormRulerLayout.VERTICAL, verScrollBar);
@ -812,6 +815,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
}
private class FormRulerLayout extends RulerLayout {
public static final String FVS_GUIDE = "FvsGuide";
private static final int DESIGNER_WIDTH = 960;
private static final int DESIGNER_HEIGHT = 540;
private static final int TOPGAP = 8;
@ -819,10 +823,20 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
private int DESIGNERWIDTH = DESIGNER_WIDTH;
private int DESIGNERHEIGHT = DESIGNER_HEIGHT;
private FvsGuidePane fvsGuidePane;
public FormRulerLayout() {
super();
}
@Override
public void addLayoutComponent(String name, Component comp) {
super.addLayoutComponent(name, comp);
if (isValid && ComparatorUtils.equals(name, FVS_GUIDE)) {
fvsGuidePane = (FvsGuidePane) comp;
}
}
/**
* 表单用的layout当前不需要标尺
*/
@ -860,6 +874,12 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
DESIGNERWIDTH = right - vbarPreferredSize.width;
int designerLeft = left + (verScrollBar.getX() - DESIGNERWIDTH) / 2;
int designerTop = top + (horScrollBar.getY() - DESIGNERHEIGHT) / 2;
if (fvsGuidePane != null) {
Dimension fvsGuidePreferredSize = fvsGuidePane.getPreferredSize();
fvsGuidePane.setBounds(left, top, right - BARSIZE - 2, fvsGuidePreferredSize.height);
DESIGNERHEIGHT -= fvsGuidePreferredSize.height;
designerTop += fvsGuidePreferredSize.height;
}
rec = new Rectangle(designerLeft, designerTop, DESIGNERWIDTH, DESIGNERHEIGHT);
}
// designer是整个表单设计界面中的面板部分,目前只放自适应布局和参数界面。
@ -867,6 +887,36 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
}
}
@Override
public void removeLayoutComponent(Component comp) {
super.removeLayoutComponent(comp);
if (isValid && ComparatorUtils.equals(comp, fvsGuidePane)) {
fvsGuidePane = null;
}
}
@Override
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = super.preferredLayoutSize(target);
if (isValid && fvsGuidePane != null) {
dim.height += fvsGuidePane.getPreferredSize().height;
}
return dim;
}
}
@Override
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
Dimension dim = super.minimumLayoutSize(target);
if (isValid && fvsGuidePane != null) {
Dimension dim1 = fvsGuidePane.getMinimumSize();
dim.height += dim1.height;
}
return dim;
}
}
}
public boolean isFixLayout(){

260
designer-form/src/main/java/com/fr/design/mainframe/guide/FvsGuidePane.java

@ -0,0 +1,260 @@
package com.fr.design.mainframe.guide;
import com.fr.base.svg.IconUtils;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.HyperlinkEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
/**
* FRM引导提示使用FVS
*
* @author Zhanying
* @since 11.0
* Created on 2024/12/20
*/
public class FvsGuidePane extends JPanel {
private static final String OMIT_TEXT = "...";
private static final Color BACKGROUND_COLOR = new Color(255, 251, 230);
private static final Color BORDER_COLOR = new Color(255, 229, 143);
private static final Icon TIP_ICON = UIManager.getIcon("OptionPane.circularWarningIcon");
private static final Icon CLOSE_ICON = IconUtils.readIcon("/com/fr/design/standard/close/close");
// 引导URL
private static final String GUIDE_URL = "https://help.fanruan.com/finereport/doc-view-4222.html?source=3";
private static final int MAX_PANE_HEIGHT = 80;
private static final int MAX_CONTENT_HEIGHT = 60;
private static final int LINE_HEIGHT = 20;
// 计算文本框最多能容纳的行数 = 最大高度 / 行高,向下取整
private static final int MAX_LINES = (int) Math.floor((double) MAX_CONTENT_HEIGHT / LINE_HEIGHT);
private static final String CONTENT_FORMAT = "<html>\n<body style=\"font-family: %s; font-size: %spt;\">\n %s\n</body>\n</html>";
private final JComponent parent;
private JTextPane textPane;
public FvsGuidePane(JComponent parent) {
super();
this.parent = parent;
initUI();
}
private void initUI() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setLayout(new BorderLayout());
this.setBorder(new LineBorder(BORDER_COLOR));
this.setBackground(BACKGROUND_COLOR);
this.setMaximumSize(new Dimension(Integer.MAX_VALUE, MAX_PANE_HEIGHT));
JPanel wrapPane = new JPanel(new BorderLayout(10, 0));
wrapPane.setBorder(BorderFactory.createEmptyBorder(8, 13, 8, 13));
wrapPane.setBackground(BACKGROUND_COLOR);
wrapPane.add(this.createIconPane(), BorderLayout.WEST);
wrapPane.add(this.createContentPane(), BorderLayout.CENTER);
wrapPane.add(this.createCloseBtnPane(), BorderLayout.EAST);
this.add(wrapPane, BorderLayout.CENTER);
addListener();
}
private void addListener() {
this.textPane.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
refreshText();
}
});
this.textPane.addAncestorListener(new AncestorListener() {
@Override
public void ancestorAdded(AncestorEvent event) {
UIUtil.invokeLaterIfNeeded(FvsGuidePane.this::refreshText);
}
@Override
public void ancestorRemoved(AncestorEvent event) {
}
@Override
public void ancestorMoved(AncestorEvent event) {
}
});
}
private JPanel createIconPane() {
// 图标
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(6, 0, 0, 0));
panel.setBackground(BACKGROUND_COLOR);
UILabel iconLabel = new UILabel(TIP_ICON);
panel.add(iconLabel, BorderLayout.NORTH);
return panel;
}
private JPanel createCloseBtnPane() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(BACKGROUND_COLOR);
JButton closeButton = new JButton(this.closeBtnText(), CLOSE_ICON);
closeButton.setOpaque(false);
closeButton.setBorderPainted(false);
closeButton.setContentAreaFilled(false);
closeButton.addActionListener(this::close);
panel.add(closeButton, BorderLayout.NORTH);
return panel;
}
private JPanel createContentPane() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBackground(BACKGROUND_COLOR);
textPane = new JTextPane();
// 设置文本格式为 HTML
textPane.setContentType("text/html");
textPane.setEditable(false);
textPane.setBackground(BACKGROUND_COLOR);
// 添加超链接监听器
textPane.addHyperlinkListener(e -> {
if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
// 用户点击了超链接,处理跳转
try {
Desktop.getDesktop().browse(e.getURL().toURI());
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
}
});
contentPane.add(textPane, BorderLayout.CENTER);
return contentPane;
}
private void refreshText() {
int textPaneWidth = textPane.getWidth();
if (textPaneWidth <= 0) {
return;
}
// 获取可用宽度:减去可能的左右边距
Insets insets = textPane.getInsets();
int availableWidth = textPaneWidth - insets.left - insets.right - 15;// 留点冗余
// 组装html
String buildHtml = buildHtml(textPane.getFont(), autoChangeLineAndOmit(availableWidth));
textPane.setText(buildHtml);
}
private String tipContent() {
return Toolkit.i18nText("Fine-Design_Form_Guide_Use_Fvs_Tips");
}
private String linkContent() {
return Toolkit.i18nText("Fine-Design_Form_Guide_Use_Fvs_Link_Tips");
}
private void close(ActionEvent e) {
parent.remove(this);
parent.revalidate();
parent.repaint();
}
private String closeBtnText() {
return Toolkit.i18nText("Fine-Design_Form_Guide_Use_Fvs_Close_Tips");
}
private String buildHtml(Font font, String text) {
return String.format(CONTENT_FORMAT, font.getFamily(), font.getSize(), text);
}
private String autoChangeLineAndOmit(double width) {
StringBuilder htmlBuilder = new StringBuilder();
// 获取字体的大小
FontMetrics fontMetrics = textPane.getFontMetrics(textPane.getFont());
// 计算行间距
int lineSpace = LINE_HEIGHT - fontMetrics.getHeight();
String divStart = String.format("<div style=\"margin-bottom: %spt; margin-top: %spt;\">", lineSpace / 2, lineSpace / 2);
htmlBuilder.append(divStart);
// 计算省略号的长度
int omitLength = getStringWidth(OMIT_TEXT, fontMetrics);
String linkContent = linkContent();
// 计算超链的长度
int linkLength = getStringWidth(linkContent, fontMetrics);
String tipContent = tipContent();
// 宽度已经小于省略号+超链的宽度
boolean widthTooSmall = width < omitLength + linkLength;
if (StringUtils.isNotEmpty(tipContent)) {
char[] chars = tipContent.toCharArray();
int row = 1;
int off = 0;
for (int i = 0; i < chars.length; i++) {
// 当前行占的宽度
int currRowWidth = fontMetrics.charsWidth(chars, off, i - off);
// 到最后一行
if (row == MAX_LINES) {
// 计算省略号的位置
if (currRowWidth + omitLength + linkLength > width) {
//拼上省略号
htmlBuilder.append(OMIT_TEXT);
break;
}
}
if (currRowWidth > width) {
// 换行
htmlBuilder.append("</div>").append(divStart);
off = i;
row++;
} else if (widthTooSmall && simulateIfLastLineOverflows(fontMetrics, currRowWidth, row, (OMIT_TEXT + linkContent).toCharArray(), width)) {
//模拟到最后一行是否溢出;其实这么窄展示也没什么意义了
//拼上省略号
htmlBuilder.append(OMIT_TEXT);
break;
}
htmlBuilder.append(chars[i]);
}
}
htmlBuilder.append("<a href=\"").append(GUIDE_URL).append("\">").append(linkContent).append("</a></div>");
return htmlBuilder.toString();
}
private boolean simulateIfLastLineOverflows(FontMetrics fontMetrics, int currRowWidth, int row, char[] omitAndLink, double width) {
int off = 0;
for (int i = 0; i < omitAndLink.length; i++) {
boolean lastRow = row == MAX_LINES;
if (currRowWidth + fontMetrics.charsWidth(omitAndLink, off, i - off) > (lastRow ? width - 30 : width)) { // 最后一行留点冗余
if (lastRow) {
return true;
}
off = i;
currRowWidth = 0;
row++;
}
}
return false;
}
private int getStringWidth(String str, FontMetrics fontMetrics) {
return fontMetrics.charsWidth(str.toCharArray(), 0, str.length());
}
}
Loading…
Cancel
Save