Browse Source
Merge in ~DESTINY.LIN/design from mergeFBP to fbp-1.0 * commit '7d2f4e7d7360a4ee2dd2fbfe7cb137a0a942633e': (625 commits) REPORT-123532 控件字体样式设置不生效 【问题原因】设计器端修改字体样式后,没有修改对象中属性值 【改动思路】修改对象属性值 REPORT-123731 数据集含有注释和未注释的参数,但注释参数依然生效 REPORT-122312 【设计器】win系统设计器,报表添加数字控件、文件控件时会出现提示音 REPORT-115178 fix:模板主题管理显示被截断 REPORT-119406 fix:设计器数据脱敏国际化显示不全,影响使用 REPORT-116546 编辑图片控件之后,cpt模板切换到frm卡住 【问题原因】图片控件的listener没有eventName,会产生NPE,导致UI卡顿 【改动思路】判断eventName是否为空 REPORT-114938 fix:其他语言下,frm按钮移动端设置显示不全 REPORT-116316【MT】数据连接丢失【样板客户】 REPORT-120151 feat: 添加 forkId 和相关埋点 REPORT-119601 fix:创建新模板按钮显示不全 REPORT-119567 fix:设计器地图图表默认显示与其他不一致 REPORT-119405 解决打包问题 REPORT-119405 fix:设计器数据脱敏国际化显示问题 修改方法名称 修改方法名称 REPORT-118163 获取到了数据集sql语句中注释的参数 REPORT-120129 【宕机】正式环境工程宕机分析原因 REPORT-118629 FRM并行计算偶发埋点记录失败 INO-19848 fix:英文的翻譯會令客戶誤會 无jira任务,修复单测 ...fbp-1.0
Destiny.Lin-林锦龙
4 months ago
644 changed files with 19253 additions and 3352 deletions
@ -1,93 +0,0 @@
|
||||
package com.fr.design.data; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author rinoux |
||||
* @version 10.0 |
||||
* Created by rinoux on 2022/3/28 |
||||
*/ |
||||
public final class MapCompareUtils { |
||||
|
||||
|
||||
/** |
||||
* 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 |
||||
* |
||||
* 对比时默认用equals方法来判断是否为 EntryEventKind#UPDATED |
||||
* |
||||
* @param orig 原始map |
||||
* @param other 参考的新map |
||||
* @param eventHandler 有区别时的事件处理器 |
||||
* @param <K> K |
||||
* @param <V> V |
||||
*/ |
||||
public static <K, V> void contrastMapEntries(@NotNull Map<K, V> orig, @NotNull Map<K, V> other, @NotNull EventHandler<K, V> eventHandler) { |
||||
|
||||
contrastMapEntries(orig, other, eventHandler, UpdateRule.DEFAULT); |
||||
} |
||||
|
||||
/** |
||||
* 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 |
||||
* |
||||
* 对比时用自定义的规则来判断是否为 EntryEventKind#UPDATED |
||||
* |
||||
* @param orig 原始map |
||||
* @param other 参考的新map |
||||
* @param eventHandler 有区别时的事件处理器 |
||||
* @param updateRule 自定义的Update事件判定规则 |
||||
* @param <K> |
||||
* @param <V> |
||||
*/ |
||||
public static <K, V> void contrastMapEntries(@NotNull Map<K, V> orig, @NotNull Map<K, V> other, @NotNull EventHandler<K, V> eventHandler, @NotNull UpdateRule<K, V> updateRule) { |
||||
|
||||
Map<K, V> copiedOrig = new LinkedHashMap<>(orig); |
||||
|
||||
other.forEach((k, v) -> { |
||||
V existedV = copiedOrig.remove(k); |
||||
if (existedV != null) { |
||||
if (updateRule.needUpdate(existedV, v)) { |
||||
eventHandler.on(EntryEventKind.UPDATED, k, v); |
||||
} |
||||
} else { |
||||
eventHandler.on(EntryEventKind.ADDED, k, v); |
||||
} |
||||
}); |
||||
|
||||
copiedOrig.forEach((k, v) -> eventHandler.on(EntryEventKind.REMOVED, k, v)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 事件处理器,对应比较后的三种结果的事件处理 |
||||
* @param <K> |
||||
* @param <V> |
||||
*/ |
||||
public interface EventHandler<K, V> { |
||||
void on(EntryEventKind entryEventKind, K k, V v); |
||||
} |
||||
|
||||
/** |
||||
* 数据被修改(EntryEventKind.UPDATED) 的判定规则 |
||||
* @param <K> |
||||
* @param <V> |
||||
*/ |
||||
public interface UpdateRule<K, V> { |
||||
|
||||
EntryEventKind eventKind = EntryEventKind.UPDATED; |
||||
|
||||
UpdateRule DEFAULT = new UpdateRule() {}; |
||||
|
||||
default boolean needUpdate(V origin, V v) { |
||||
return !v.equals(origin); |
||||
} |
||||
} |
||||
|
||||
public enum EntryEventKind { |
||||
ADDED, |
||||
REMOVED, |
||||
UPDATED; |
||||
} |
||||
} |
@ -0,0 +1,24 @@
|
||||
package com.fr.design.env.processor; |
||||
|
||||
import com.fr.stable.fun.mark.API; |
||||
|
||||
|
||||
/** |
||||
* 远程设计自定义用户名接口实现抽象类 |
||||
* |
||||
* @author John.Ying |
||||
* @since 11.0 |
||||
* Created on 2023/5/17 |
||||
*/ |
||||
@API(level = RemoteDesignerWorkspaceInfoProcessor.CURRENT_LEVEL) |
||||
public abstract class AbstractRemoteDesignerWorkspaceInfoProcessor implements RemoteDesignerWorkspaceInfoProcessor { |
||||
@Override |
||||
public int currentAPILevel() { |
||||
return CURRENT_LEVEL; |
||||
} |
||||
|
||||
@Override |
||||
public int layerIndex() { |
||||
return DEFAULT_LAYER_INDEX; |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
package com.fr.design.env.processor; |
||||
|
||||
import com.fr.stable.fun.mark.Immutable; |
||||
import com.fr.workspace.connect.WorkspaceConnectionInfo; |
||||
|
||||
/** |
||||
* 远程设计自定义用户名接口 |
||||
* px:为了二开插件开的接口,不建议实现,后面可能会变动 |
||||
* |
||||
* @author John.Ying |
||||
* @since 11.0 |
||||
* Created on 2023/5/17 |
||||
*/ |
||||
public interface RemoteDesignerWorkspaceInfoProcessor extends Immutable { |
||||
|
||||
String XML_TAG = "RemoteDesignerWorkspaceInfoProcessor"; |
||||
|
||||
int CURRENT_LEVEL = 1; |
||||
|
||||
/** |
||||
* 根据链接信息自定义用户名 |
||||
*/ |
||||
WorkspaceConnectionInfo customUserName(WorkspaceConnectionInfo workspaceInfo); |
||||
|
||||
} |
@ -0,0 +1,184 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
|
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.BoxLayout; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JScrollPane; |
||||
import javax.swing.JTextArea; |
||||
import javax.swing.SwingUtilities; |
||||
import javax.swing.UIManager; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Cursor; |
||||
import java.awt.Dialog; |
||||
import java.awt.Dimension; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
/** |
||||
* 插件批量处理弹窗面板 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/5/19 |
||||
*/ |
||||
public class PluginBatchModifyDetailPane { |
||||
private UILabel message = new UILabel(); |
||||
private UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Report_OK")); |
||||
private UILabel uiLabel = new UILabel(); |
||||
private UILabel directUiLabel = new UILabel(); |
||||
private UILabel detailLabel = new UILabel(); |
||||
|
||||
private JPanel upPane; |
||||
private JPanel midPane; |
||||
private JPanel downPane; |
||||
private JPanel hiddenPanel; |
||||
private JTextArea jta; |
||||
private JDialog dialog; |
||||
|
||||
/** |
||||
* 弹窗面板默认大小 |
||||
*/ |
||||
public static final Dimension DEFAULT = new Dimension(380, 150); |
||||
|
||||
/** |
||||
* 弹窗面板展开大小 |
||||
*/ |
||||
public static final Dimension DEFAULT_PRO = new Dimension(380, 270); |
||||
|
||||
public PluginBatchModifyDetailPane(Dialog parent) { |
||||
init(parent); |
||||
} |
||||
|
||||
private void init(Dialog parent) { |
||||
message.setBorder(BorderFactory.createEmptyBorder(8, 5, 0, 0)); |
||||
dialog = new JDialog(parent, Toolkit.i18nText("Fine-Design_Basic_Plugin_Manager"), true); |
||||
dialog.setSize(DEFAULT); |
||||
JPanel jp = new JPanel(); |
||||
initUpPane(); |
||||
initDownPane(); |
||||
initMidPane(); |
||||
initHiddenPanel(); |
||||
initListener(); |
||||
jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS)); |
||||
jp.add(upPane); |
||||
jp.add(midPane); |
||||
jp.add(hiddenPanel); |
||||
jp.add(downPane); |
||||
hiddenPanel.setVisible(false); |
||||
dialog.add(jp); |
||||
dialog.setResizable(false); |
||||
dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(parent)); |
||||
} |
||||
|
||||
private void initDownPane() { |
||||
downPane = new JPanel(); |
||||
downPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 9)); |
||||
downPane.add(cancelButton); |
||||
} |
||||
|
||||
private void initUpPane() { |
||||
upPane = new JPanel(); |
||||
uiLabel = new UILabel(UIManager.getIcon("OptionPane.errorIcon")); |
||||
upPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); |
||||
upPane.add(uiLabel); |
||||
upPane.add(message); |
||||
} |
||||
|
||||
private void initMidPane() { |
||||
midPane = new JPanel(); |
||||
midPane.add(directUiLabel); |
||||
midPane.add(detailLabel); |
||||
midPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0)); |
||||
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Look_Detail")); |
||||
detailLabel.setForeground(Color.BLUE); |
||||
detailLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
||||
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right")); |
||||
} |
||||
|
||||
private void initHiddenPanel() { |
||||
hiddenPanel = new JPanel(); |
||||
hiddenPanel.setLayout(new BorderLayout(2, 0)); |
||||
hiddenPanel.add(new JPanel(), BorderLayout.WEST); |
||||
hiddenPanel.add(new JPanel(), BorderLayout.EAST); |
||||
JPanel borderPanel = new JPanel(); |
||||
borderPanel.setLayout(new BorderLayout()); |
||||
jta = new JTextArea(); |
||||
JScrollPane jsp = new JScrollPane(jta); |
||||
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); |
||||
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); |
||||
jta.setEditable(false); |
||||
borderPanel.add(jsp, BorderLayout.CENTER); |
||||
hiddenPanel.add(borderPanel); |
||||
} |
||||
|
||||
/** |
||||
* 补充更详细的报错信息 |
||||
* |
||||
* @param message 信息 |
||||
*/ |
||||
public void updateDetailArea(String message) { |
||||
jta.append(message + "\n"); |
||||
} |
||||
|
||||
private void initListener() { |
||||
detailLabel.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
if (hiddenPanel.isVisible()) { |
||||
hiddenPanel.setVisible(false); |
||||
dialog.setSize(DEFAULT); |
||||
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Look_Detail")); |
||||
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right")); |
||||
} else { |
||||
dialog.setSize(DEFAULT_PRO); |
||||
hiddenPanel.setVisible(true); |
||||
detailLabel.setText(Toolkit.i18nText("Fine_Designer_Hide_Detail")); |
||||
directUiLabel.setIcon(UIManager.getIcon("OptionPane.narrow.down")); |
||||
} |
||||
} |
||||
|
||||
}); |
||||
cancelButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
hiddenPanel.removeAll(); |
||||
dialog.dispose(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 更新标题 |
||||
* @param title 标题 |
||||
*/ |
||||
public void updateTitle(String title) { |
||||
dialog.setTitle(title); |
||||
} |
||||
|
||||
/** |
||||
* 更新展示信息 |
||||
* |
||||
* @param failedCount 处理失败个数 |
||||
* @param successCount 处理成功个数 |
||||
*/ |
||||
public void updateMessage(int failedCount, int successCount) { |
||||
message.setText(Toolkit.i18nText("Fine-Design_Basic_Plugin_Batch_Modify_Info", failedCount, successCount)); |
||||
} |
||||
|
||||
/** |
||||
* 显示面板 |
||||
*/ |
||||
public void show() { |
||||
dialog.setVisible(true); |
||||
} |
||||
} |
@ -0,0 +1,127 @@
|
||||
package com.fr.design.extra.exe.callback; |
||||
|
||||
import com.fr.design.bridge.exec.JSCallback; |
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.extra.PluginBatchModifyDetailPane; |
||||
import com.fr.design.extra.PluginOperateUtils; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.plugin.DesignerPluginContext; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.context.PluginMarker; |
||||
import com.fr.plugin.manage.control.PluginTask; |
||||
import com.fr.plugin.manage.control.PluginTaskResult; |
||||
import com.fr.plugin.manage.control.ProgressCallback; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.JOptionPane; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 带进度条的批量处理的callback |
||||
* <li> content与title是处理完成后弹出的面板的内容与标题,子类需要在done之前设定好对应的信息 |
||||
* <li> 进度条是以 当前完成任务数/总任务数 来计算的 |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/6/6 |
||||
*/ |
||||
public abstract class AbstractBatchModifyStatusCallback implements ProgressCallback { |
||||
protected JSCallback jsCallback; |
||||
protected Map<String, String> resultMap = new HashMap<>(); |
||||
protected String content = StringUtils.EMPTY; |
||||
protected String title = StringUtils.EMPTY; |
||||
public int pluginCount = 0; |
||||
public int allPluginCount = 0; |
||||
public int successCount = 0; |
||||
public int failedCount = 0; |
||||
public static final int HUNDRED_PERCENT = 100; |
||||
public static final String PERCENT = "%"; |
||||
public static final String DEFAULT = "default"; |
||||
|
||||
public AbstractBatchModifyStatusCallback() { |
||||
} |
||||
|
||||
public AbstractBatchModifyStatusCallback(JSCallback jsCallback, int size) { |
||||
this.jsCallback = jsCallback; |
||||
this.allPluginCount = size; |
||||
} |
||||
|
||||
@Override |
||||
public void done(PluginTaskResult result) { |
||||
String pluginInfo = PluginOperateUtils.getSuccessInfo(result); |
||||
if (result.isSuccess()) { |
||||
successCount++; |
||||
String modifyMessage = updateMessage(pluginInfo); |
||||
FineLoggerFactory.getLogger().info(modifyMessage); |
||||
} else { |
||||
failedCount++; |
||||
resultMap.put(getPluginName(result), pluginInfo); |
||||
} |
||||
updateProgressAndCheckCompletion(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 获取插件名 |
||||
* |
||||
* @param result 任务结果 |
||||
* @return 插件名 |
||||
*/ |
||||
public String getPluginName(PluginTaskResult result) { |
||||
PluginTask pluginTask = result.getCurrentTask(); |
||||
if (pluginTask != null) { |
||||
PluginMarker pluginMarker = pluginTask.getToMarker(); |
||||
if (pluginMarker != null) { |
||||
return pluginMarker.getPluginID(); |
||||
} |
||||
} |
||||
return DEFAULT; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 更新当前Map状态,进度条,如果全部都更新完了就回调 |
||||
*/ |
||||
public void updateProgressAndCheckCompletion() { |
||||
pluginCount++; |
||||
updateProgress(StringUtils.EMPTY, (double) pluginCount / allPluginCount); |
||||
if (pluginCount == allPluginCount) { |
||||
jsCallback.execute("success"); |
||||
showMessageDialog(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 展示信息面板 |
||||
*/ |
||||
public void showMessageDialog() { |
||||
if (failedCount == 0) { |
||||
FineJOptionPane.showMessageDialog(DesignerPluginContext.getPluginDialog(), |
||||
content, |
||||
title, |
||||
JOptionPane.INFORMATION_MESSAGE); |
||||
} else { |
||||
PluginBatchModifyDetailPane detailPane = new PluginBatchModifyDetailPane(DesignerPluginContext.getPluginDialog()); |
||||
for (String key : resultMap.keySet()) { |
||||
detailPane.updateDetailArea(resultMap.get(key)); |
||||
} |
||||
detailPane.updateMessage(failedCount, successCount); |
||||
detailPane.updateTitle(title); |
||||
detailPane.show(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void updateProgress(String description, double progress) { |
||||
jsCallback.execute(progress * HUNDRED_PERCENT + PERCENT); |
||||
} |
||||
|
||||
/** |
||||
* 更新处理成功返回的日志信息 |
||||
* |
||||
* @return 返回的日志信息 |
||||
*/ |
||||
abstract public String updateMessage(String pluginInfo); |
||||
} |
@ -0,0 +1,43 @@
|
||||
package com.fr.design.extra.exe.callback; |
||||
|
||||
|
||||
import com.fr.design.bridge.exec.JSCallback; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
|
||||
|
||||
/** |
||||
* 批量启用/禁用插件的Callback |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/5/18 |
||||
*/ |
||||
public class BatchModifyStatusCallback extends AbstractBatchModifyStatusCallback { |
||||
private boolean active; |
||||
private boolean operatorFlag = false; |
||||
|
||||
public BatchModifyStatusCallback(JSCallback jsCallback, int size) { |
||||
super(jsCallback, size); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public String updateMessage(String pluginInfo) { |
||||
return active ? pluginInfo + Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Disabled_Duplicate") : pluginInfo + Toolkit.i18nText("Fine-Design_Plugin_Has_Been_Actived_Duplicate"); |
||||
} |
||||
|
||||
/** |
||||
* 更新启用/禁用信息 |
||||
* |
||||
* @param active |
||||
*/ |
||||
public void updateActiveStatus(boolean active) { |
||||
if (!operatorFlag) { |
||||
this.active = active; |
||||
this.operatorFlag = true; |
||||
this.title = active ? Toolkit.i18nText("Fine-Design_Basic_Plugin_Stop") : Toolkit.i18nText("Fine-Design_Basic_Plugin_Start"); |
||||
this.content = active ? Toolkit.i18nText("Fine-Design_Basic_Plugin_Batch_Modify_Stop_Success") : Toolkit.i18nText("Fine-Design_Basic_Plugin_Batch_Modify_Start_Success"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,77 @@
|
||||
package com.fr.design.extra.exe.callback; |
||||
|
||||
|
||||
import com.fr.design.bridge.exec.JSCallback; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.manage.control.PluginTask; |
||||
import com.fr.plugin.manage.control.PluginTaskResult; |
||||
|
||||
|
||||
/** |
||||
* 批量更新的callback |
||||
* |
||||
* @author Destiny.Lin |
||||
* @since 11.0 |
||||
* Created on 2023/6/6 |
||||
*/ |
||||
public class BatchUpdateOnlineCallback extends AbstractBatchModifyStatusCallback{ |
||||
public static final BatchUpdateOnlineCallback NONE = new BatchUpdateOnlineCallback(); |
||||
|
||||
/** |
||||
* 可自动处理前置任务的callback,用来处理实际更新逻辑 |
||||
*/ |
||||
private InnerUpdateCallback innerPreTaskCallback; |
||||
|
||||
public BatchUpdateOnlineCallback() { |
||||
} |
||||
|
||||
public BatchUpdateOnlineCallback(JSCallback jsCallback, int size) { |
||||
super(jsCallback, size); |
||||
this.title = Toolkit.i18nText("Fine-Design_Basic_Plugin_Update"); |
||||
this.content = Toolkit.i18nText("Fine-Design_Basic_Plugin_Update_Success"); |
||||
} |
||||
|
||||
/** |
||||
* 更新任务 |
||||
* |
||||
* @param pluginTask 任务 |
||||
* @param jsCallback callback |
||||
*/ |
||||
public void createInnerPreTaskCallback(PluginTask pluginTask, JSCallback jsCallback) { |
||||
innerPreTaskCallback = new InnerUpdateCallback(pluginTask, jsCallback); |
||||
} |
||||
|
||||
|
||||
|
||||
public InnerUpdateCallback getInnerPreTaskCallback() { |
||||
return innerPreTaskCallback; |
||||
} |
||||
|
||||
@Override |
||||
public String updateMessage(String pluginInfo) { |
||||
return pluginInfo + Toolkit.i18nText("Fine-Design_Basic_Plugin_Update_Success"); |
||||
} |
||||
|
||||
/** |
||||
* 可自动处理前置任务的callback,用来处理实际更新逻辑 |
||||
*/ |
||||
public class InnerUpdateCallback extends UpdateOnlineCallback { |
||||
|
||||
|
||||
public InnerUpdateCallback(PluginTask pluginTask, JSCallback jsCallback) { |
||||
super(pluginTask, jsCallback); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void updateProgress(String description, double aProgress) { |
||||
//不进行处理
|
||||
} |
||||
|
||||
@Override |
||||
public void allDone(PluginTaskResult result) { |
||||
BatchUpdateOnlineCallback.this.done(result); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,349 @@
|
||||
package com.fr.design.file; |
||||
|
||||
import com.fr.base.svg.IconUtils; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.imenu.UIMenuItem; |
||||
import com.fr.design.gui.imenu.UIScrollPopUpMenu; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.design.utils.TemplateUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.collections.CollectionUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 右侧下拉菜单的工厂类 |
||||
* @author Carlson |
||||
* @since 11.0 |
||||
* created on 2023-04-14 |
||||
**/ |
||||
public class MultiTemplateTabMenuFactory { |
||||
|
||||
private static final Icon CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close"); |
||||
private static final Icon MOUSE_OVER_CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close_mouseover.svg"); |
||||
private static final Icon MOUSE_PRESS_CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close_press.svg"); |
||||
|
||||
private static final int ITEM_SIZE = 25; |
||||
|
||||
private UIScrollPopUpMenu menu = null; |
||||
|
||||
private static MultiTemplateTabMenuFactory INSTANCE = new MultiTemplateTabMenuFactory(); |
||||
|
||||
private MultiTemplateTabMenuFactory() { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 返回右侧下拉菜单的工厂类 |
||||
* @return |
||||
*/ |
||||
public static MultiTemplateTabMenuFactory getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* tab上的下拉菜单 |
||||
*/ |
||||
public UIScrollPopUpMenu createMenu() { |
||||
menu = new UIScrollPopUpMenu(); |
||||
menu.setBorder(BorderFactory.createEmptyBorder(-3, 3, 3, 0)); |
||||
|
||||
menu.add(initCloseOther()); |
||||
menu.add(createEmptyRow()); |
||||
menu.addSeparator(); |
||||
menu.add(createEmptyRow()); |
||||
menu.add(createCategory(Toolkit.i18nText("Fine-Design_Basic_Tab_Current_Category_Templates"))); |
||||
Component[] items = createCurrentCategory(); |
||||
for (Component item : items) { |
||||
menu.add(item); |
||||
} |
||||
items = createOtherCategory(); |
||||
if (items.length > 0) { |
||||
menu.addSeparator(); |
||||
menu.add(createEmptyRow()); |
||||
menu.add(createCategory(Toolkit.i18nText("Fine-Design_Basic_Tab_Other_Category_Templates"))); |
||||
for (Component item : items) { |
||||
menu.add(item); |
||||
} |
||||
} |
||||
Dimension dimension = menu.getPreferredSize(); |
||||
dimension.width += ITEM_SIZE; |
||||
menu.setPreferredSize(dimension); |
||||
return menu; |
||||
} |
||||
|
||||
/** |
||||
* 关闭其它按钮 |
||||
*/ |
||||
private UIMenuItem initCloseOther() { |
||||
UIMenuItem closeOther = new UIMenuItem(Toolkit.i18nText("Fine-Design_Basic_Tab_Close_Other_Templates_Of_Current_Category")); |
||||
closeOther.setHorizontalAlignment(SwingConstants.CENTER); |
||||
Dimension dimension = closeOther.getPreferredSize(); |
||||
dimension.height = ITEM_SIZE; |
||||
closeOther.setPreferredSize(dimension); |
||||
String currentOperator = getCurrentTabOperatorType(); |
||||
closeOther.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
MultiTemplateTabPane.getInstance().closeOtherByOperatorType(currentOperator); |
||||
} |
||||
}); |
||||
if (MultiTemplateTabPane.getInstance().getOpenedJTemplatesByOperator(currentOperator).size() <= 1) { |
||||
closeOther.setEnabled(false); |
||||
} |
||||
return closeOther; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 美观用 |
||||
*/ |
||||
private JPanel createEmptyRow() { |
||||
return new JPanel() { |
||||
@Override |
||||
public Dimension getPreferredSize() { |
||||
Dimension d = super.getPreferredSize(); |
||||
d.height = 1; |
||||
return d; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* 模板分类item |
||||
*/ |
||||
private UIButton createCategory(String categoryName) { |
||||
UIButton button = new UIButton(categoryName); |
||||
button.setBorderPainted(false); |
||||
button.setExtraPainted(false); |
||||
button.setPreferredSize(new Dimension(menu.getWidth(), ITEM_SIZE)); |
||||
button.setOpaque(true); |
||||
button.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
button.setHorizontalAlignment(SwingConstants.LEFT); |
||||
button.setForeground(UIConstants.FLESH_BLUE); |
||||
return button; |
||||
} |
||||
|
||||
/** |
||||
* 创建 当前分类模板 item数组 |
||||
*/ |
||||
private Component[] createCurrentCategory() { |
||||
return createListDownItem(MultiTemplateTabPane.getInstance().getOpenedJTemplatesByOperator(getCurrentTabOperatorType())); |
||||
} |
||||
|
||||
private String getCurrentTabOperatorType(){ |
||||
JTemplate jTemplate= HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
return jTemplate.getTemplateTabOperatorType(); |
||||
} |
||||
|
||||
/** |
||||
* 创建 其它分类模板 item数组 |
||||
*/ |
||||
private Component[] createOtherCategory() { |
||||
String currentOperator = getCurrentTabOperatorType(); |
||||
List<JTemplate<?, ?>> openedTemplates = new ArrayList<>(); |
||||
Map<String, List<JTemplate<?, ?>>> map = MultiTemplateTabPane.getInstance().getOpenedJTemplatesByCategory(); |
||||
for (Map.Entry<String, List<JTemplate<?, ?>>> entry : map.entrySet()) { |
||||
if (!StringUtils.equals(currentOperator, entry.getKey())) { |
||||
openedTemplates.addAll(entry.getValue()); |
||||
} |
||||
} |
||||
return createListDownItem(openedTemplates); |
||||
} |
||||
|
||||
/** |
||||
* 根据template列表创建多个item |
||||
*/ |
||||
private Component[] createListDownItem(List<JTemplate<?, ?>> openedTemplates) { |
||||
if (!CollectionUtils.isEmpty(openedTemplates)) { |
||||
Component[] templates = new Component[openedTemplates.size()]; |
||||
for (int i = 0; i < openedTemplates.size(); i++) { |
||||
templates[i] = createListDownMenuItem(openedTemplates.get(i)); |
||||
} |
||||
return templates; |
||||
} |
||||
return new Component[0]; |
||||
} |
||||
|
||||
/** |
||||
* 根据template对象创建item |
||||
*/ |
||||
private Component createListDownMenuItem(JTemplate<?, ?> template) { |
||||
JPanel jPanel = new JPanel(); |
||||
jPanel.setPreferredSize(new Dimension(menu.getWidth(), ITEM_SIZE)); |
||||
jPanel.setLayout(new BorderLayout()); |
||||
|
||||
MenuItemButtonGroup menuItemButtonGroup = new MenuItemButtonGroup(template); |
||||
if (template == HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()) { |
||||
menuItemButtonGroup.templateButton.setForeground(UIConstants.FLESH_BLUE); |
||||
} |
||||
|
||||
jPanel.add(menuItemButtonGroup.iconButton, BorderLayout.WEST); |
||||
jPanel.add(menuItemButtonGroup.templateButton, BorderLayout.CENTER); |
||||
jPanel.add(menuItemButtonGroup.closeButton, BorderLayout.EAST); |
||||
|
||||
return jPanel; |
||||
} |
||||
|
||||
/** |
||||
* menu的item由模板图标、模板名、模板关闭按钮组成 |
||||
*/ |
||||
private class MenuItemButtonGroup { |
||||
|
||||
private final UIButton iconButton; |
||||
private final UIButton templateButton; |
||||
private final UIButton closeButton; |
||||
|
||||
public MenuItemButtonGroup(JTemplate<?, ?> template) { |
||||
iconButton = createIconButton(template); |
||||
templateButton = createTemplateButton(template); |
||||
closeButton = createCloseButton(); |
||||
initListener(template); |
||||
} |
||||
|
||||
/** |
||||
* item[0] 模板图标按钮初始化 |
||||
*/ |
||||
private UIButton createIconButton(JTemplate<?, ?> template) { |
||||
UIButton button = new UIButton(template.getIcon(), template.getIcon(), template.getIcon()); |
||||
button.setPreferredSize(new Dimension(ITEM_SIZE, ITEM_SIZE)); |
||||
button.setOpaque(true); |
||||
button.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
return button; |
||||
} |
||||
|
||||
/** |
||||
* item[1] 切换模板按钮初始化 |
||||
*/ |
||||
private UIButton createTemplateButton(JTemplate<?, ?> template) { |
||||
UIButton button = new UIButton(TemplateUtils.createLockeTemplatedName(template, template.getTemplateName())); |
||||
button.setBorderPainted(false); |
||||
button.setExtraPainted(false); |
||||
button.setPreferredSize(new Dimension(menu.getWidth() - ITEM_SIZE * 2, ITEM_SIZE)); |
||||
button.setOpaque(true); |
||||
button.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
button.setHorizontalAlignment(SwingConstants.LEFT); |
||||
return button; |
||||
} |
||||
|
||||
/** |
||||
* item[2] 关闭模板图标按钮初始化 |
||||
*/ |
||||
private UIButton createCloseButton() { |
||||
UIButton button = new UIButton(CLOSE, MOUSE_OVER_CLOSE, MOUSE_PRESS_CLOSE); |
||||
button.setPreferredSize(new Dimension(ITEM_SIZE, ITEM_SIZE)); |
||||
button.setOpaque(true); |
||||
button.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
button.setVisible(false); |
||||
return button; |
||||
} |
||||
|
||||
private void initListener(JTemplate<?, ?> template) { |
||||
initIconButtonListener(); |
||||
initTemplateButtonListener(template); |
||||
initCloseButtonListener(template); |
||||
} |
||||
|
||||
/** |
||||
* item[0] 模板图标按钮鼠标事件 |
||||
*/ |
||||
private void initIconButtonListener() { |
||||
iconButton.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
fireMouseEnteredEvent(); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
fireMouseExitedEvent(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* item[1] 切换模板按钮鼠标事件 |
||||
*/ |
||||
private void initTemplateButtonListener(JTemplate<?, ?> template) { |
||||
templateButton.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
menu.setVisible(false); |
||||
MultiTemplateTabPane.getInstance().switchJTemplate(template); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
fireMouseEnteredEvent(); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
fireMouseExitedEvent(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* item[2] 关闭模板按钮鼠标事件 |
||||
*/ |
||||
private void initCloseButtonListener(JTemplate<?, ?> template) { |
||||
closeButton.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
menu.setVisible(false); |
||||
MultiTemplateTabPane.getInstance().setIsCloseCurrent(template == HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()); |
||||
MultiTemplateTabPane.getInstance().closeFormat(template); |
||||
MultiTemplateTabPane.getInstance().closeSpecifiedTemplate(template); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseEntered(MouseEvent e) { |
||||
fireMouseEnteredEvent(); |
||||
} |
||||
|
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
fireMouseExitedEvent(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* mouse移入item范围 |
||||
*/ |
||||
private void fireMouseEnteredEvent() { |
||||
iconButton.setBackground(UIConstants.HOVER_BLUE); |
||||
templateButton.setBackground(UIConstants.HOVER_BLUE); |
||||
closeButton.setBackground(UIConstants.HOVER_BLUE); |
||||
closeButton.setVisible(true); |
||||
} |
||||
|
||||
/** |
||||
* mouse移出item范围 |
||||
*/ |
||||
private void fireMouseExitedEvent() { |
||||
iconButton.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
templateButton.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
closeButton.setBackground(UIConstants.NORMAL_BACKGROUND); |
||||
closeButton.setVisible(false); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,59 @@
|
||||
package com.fr.design.file; |
||||
|
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.general.ComparatorUtils; |
||||
|
||||
import java.util.List; |
||||
import java.util.function.Predicate; |
||||
|
||||
public class MultiTemplateTabUtils { |
||||
/** |
||||
* 计算离currentIndex最近的相同模式的模板index值(优先左边) |
||||
* |
||||
* @param currentIndex 当前index |
||||
* @param openedTemplate 模板list |
||||
* @param type 当前显示模式 |
||||
* @return |
||||
*/ |
||||
public static int calShowTemplateIndex(int currentIndex, List<JTemplate<?, ?>> openedTemplate, String type) { |
||||
if (currentIndex < 0 || currentIndex > openedTemplate.size() - 1) { |
||||
return -1; |
||||
} |
||||
int result = getShowJTemplateTab(currentIndex, openedTemplate, template -> showJTemplateTab(type, template)); |
||||
if (result != -1) return result; |
||||
return getShowJTemplateTab(currentIndex, openedTemplate, template -> !showJTemplateTab(type, template)); |
||||
} |
||||
|
||||
/** |
||||
* 先从左找,再从右找离得最近的满足条件的模板 |
||||
* |
||||
* @param currentIndex 当前index |
||||
* @param openedTemplate 模板list |
||||
* @param predicate |
||||
* @return |
||||
*/ |
||||
private static int getShowJTemplateTab(int currentIndex, List<JTemplate<?, ?>> openedTemplate, Predicate<JTemplate<?, ?>> predicate) { |
||||
for (int i = currentIndex; i >= 0; i--) { |
||||
if (predicate.test(openedTemplate.get(i))) { |
||||
return i; |
||||
} |
||||
} |
||||
for (int i = currentIndex + 1; i < openedTemplate.size(); i++) { |
||||
if (predicate.test(openedTemplate.get(i))) { |
||||
return i; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
/** |
||||
* 是否显示模板 |
||||
* |
||||
* @param type 模板类型 |
||||
* @param jTemplate 模板 |
||||
* @return |
||||
*/ |
||||
private static boolean showJTemplateTab(String type, JTemplate<?, ?> jTemplate) { |
||||
return ComparatorUtils.equals(type, jTemplate.getTemplateTabOperatorType()); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
package com.fr.design.formula; |
||||
|
||||
import com.fr.base.BaseFormula; |
||||
|
||||
/** |
||||
* @author Carlson |
||||
* @version 11.0 |
||||
* Created by Carlson on 2023/8/14 17:15 |
||||
* @description 默认的公式输入面板(包含一个输入框和一个F(x)按钮),清空公式内容后不会显示“$$$”,主要在图表配置面板里使用 |
||||
**/ |
||||
public class DefaultTinyFormulaPane extends TinyFormulaPane{ |
||||
|
||||
@Override |
||||
protected void populateTextField(BaseFormula fm) { |
||||
formulaTextField.setText(fm.getContent()); |
||||
} |
||||
} |
@ -0,0 +1,47 @@
|
||||
package com.fr.design.i18n; |
||||
|
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
/** |
||||
* 国际化链接获取工具 |
||||
* 根据配置文件key获取云中心key对应的链接或者默认链接 |
||||
* |
||||
* @author obo |
||||
* @since 11.0 |
||||
* Created on 2023/4/7 |
||||
*/ |
||||
public final class LocaleLinkProvider { |
||||
|
||||
private LocaleLinkProvider(){}; |
||||
|
||||
/** |
||||
* 单一实例 |
||||
*/ |
||||
private static final LocaleLinkProvider INSTANCE = new LocaleLinkProvider(); |
||||
|
||||
/** |
||||
* 返回LocaleLinkProvider的单一实例 |
||||
* |
||||
* @return LocaleLinkProvider单一实例 |
||||
*/ |
||||
public static LocaleLinkProvider getInstance(){ |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* 根据配置文件项中的key获取链接 |
||||
* |
||||
* @param propsKey 配置项key |
||||
* @param defaultKey 默认链接项key |
||||
* @return 对应的生成器 |
||||
*/ |
||||
public String getLink(String propsKey, String defaultKey) { |
||||
String cloudKey = DesignI18nImpl.getInstance().i18nText(propsKey); |
||||
String url = CloudCenter.getInstance().acquireUrlByKind(cloudKey); |
||||
if(StringUtils.isEmpty(url)) { |
||||
return DesignI18nImpl.getInstance().i18nText(defaultKey); |
||||
} |
||||
return url; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue