Browse Source

Pull request #4: 无jira任务,合并fbp至最新分支

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
parent
commit
9ae6274bac
  1. 19
      build.gradle
  2. 12
      designer-base/src/main/java/com/fr/base/svg/SVGIcon.java
  3. 18
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  4. 263
      designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java
  5. 16
      designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java
  6. 16
      designer-base/src/main/java/com/fr/design/actions/community/BugAction.java
  7. 15
      designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java
  8. 18
      designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java
  9. 16
      designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java
  10. 16
      designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java
  11. 16
      designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java
  12. 17
      designer-base/src/main/java/com/fr/design/actions/community/SignAction.java
  13. 15
      designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java
  14. 15
      designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java
  15. 19
      designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java
  16. 14
      designer-base/src/main/java/com/fr/design/actions/community/UpAction.java
  17. 15
      designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java
  18. 330
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  19. 8
      designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java
  20. 2
      designer-base/src/main/java/com/fr/design/actions/file/export/AbstractExportAction.java
  21. 20
      designer-base/src/main/java/com/fr/design/actions/help/FineUIAction.java
  22. 20
      designer-base/src/main/java/com/fr/design/actions/help/SystemInfoPane.java
  23. 14
      designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java
  24. 25
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/RemindPane.java
  25. 14
      designer-base/src/main/java/com/fr/design/components/table/TablePanel.java
  26. 2
      designer-base/src/main/java/com/fr/design/condition/LiteConditionPane.java
  27. 15
      designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java
  28. 20
      designer-base/src/main/java/com/fr/design/constants/UIConstants.java
  29. 46
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  30. 9
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  31. 93
      designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java
  32. 1
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java
  33. 16
      designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java
  34. 31
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java
  35. 2
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  36. 3
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java
  37. 59
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java
  38. 7
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java
  39. 7
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/DesensitizationOpenPane.java
  40. 14
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java
  41. 35
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java
  42. 16
      designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java
  43. 14
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  44. 1
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java
  45. 3
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java
  46. 19
      designer-base/src/main/java/com/fr/design/dcm/UniversalDatabasePane.java
  47. 22
      designer-base/src/main/java/com/fr/design/dcm/UniversalDcmBridge.java
  48. 16
      designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java
  49. 20
      designer-base/src/main/java/com/fr/design/dialog/BasicPane.java
  50. 2
      designer-base/src/main/java/com/fr/design/dialog/FineJOptionPane.java
  51. 2
      designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java
  52. 2
      designer-base/src/main/java/com/fr/design/editor/DoubleDeckValueEditorPane.java
  53. 2
      designer-base/src/main/java/com/fr/design/editor/ValueEditorPane.java
  54. 10
      designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java
  55. 10
      designer-base/src/main/java/com/fr/design/env/RemoteDesignerWorkspaceInfo.java
  56. 24
      designer-base/src/main/java/com/fr/design/env/processor/AbstractRemoteDesignerWorkspaceInfoProcessor.java
  57. 25
      designer-base/src/main/java/com/fr/design/env/processor/RemoteDesignerWorkspaceInfoProcessor.java
  58. 184
      designer-base/src/main/java/com/fr/design/extra/PluginBatchModifyDetailPane.java
  59. 110
      designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java
  60. 4
      designer-base/src/main/java/com/fr/design/extra/PluginUtils.java
  61. 127
      designer-base/src/main/java/com/fr/design/extra/exe/callback/AbstractBatchModifyStatusCallback.java
  62. 43
      designer-base/src/main/java/com/fr/design/extra/exe/callback/BatchModifyStatusCallback.java
  63. 77
      designer-base/src/main/java/com/fr/design/extra/exe/callback/BatchUpdateOnlineCallback.java
  64. 15
      designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java
  65. 24
      designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java
  66. 46
      designer-base/src/main/java/com/fr/design/file/FileOperationHelper.java
  67. 7
      designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java
  68. 349
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabMenuFactory.java
  69. 300
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java
  70. 59
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabUtils.java
  71. 10
      designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java
  72. 75
      designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java
  73. 85
      designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java
  74. 17
      designer-base/src/main/java/com/fr/design/formula/DefaultTinyFormulaPane.java
  75. 8
      designer-base/src/main/java/com/fr/design/formula/FormulaPane.java
  76. 8
      designer-base/src/main/java/com/fr/design/formula/TinyFormulaPane.java
  77. 2
      designer-base/src/main/java/com/fr/design/fun/DefaultValueAdjustProvider.java
  78. 6
      designer-base/src/main/java/com/fr/design/fun/impl/AbstractDefaultValueAdjustProvider.java
  79. 5
      designer-base/src/main/java/com/fr/design/gui/UILookAndFeel.java
  80. 8
      designer-base/src/main/java/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java
  81. 19
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java
  82. 53
      designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java
  83. 34
      designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java
  84. 2
      designer-base/src/main/java/com/fr/design/gui/frpane/EditingStringListPane.java
  85. 25
      designer-base/src/main/java/com/fr/design/gui/frpane/FontSizeComboPane.java
  86. 2
      designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java
  87. 8
      designer-base/src/main/java/com/fr/design/gui/frpane/RegPane.java
  88. 2
      designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPane.java
  89. 2
      designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java
  90. 18
      designer-base/src/main/java/com/fr/design/gui/icontainer/UIEastResizableContainer.java
  91. 30
      designer-base/src/main/java/com/fr/design/gui/icontainer/UIResizableContainer.java
  92. 14
      designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java
  93. 2
      designer-base/src/main/java/com/fr/design/gui/imenutable/UIMenuTableUI.java
  94. 2
      designer-base/src/main/java/com/fr/design/gui/itable/UITableUI.java
  95. 17
      designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java
  96. 11
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileNodeConstants.java
  97. 41
      designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java
  98. 47
      designer-base/src/main/java/com/fr/design/i18n/LocaleLinkProvider.java
  99. 27
      designer-base/src/main/java/com/fr/design/icon/WarningIcon.java
  100. 114
      designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java
  101. Some files were not shown because too many files have changed in this diff Show More

19
build.gradle

@ -14,6 +14,7 @@ ext {
outputPath = "build"
ignoreTestFailureSetting = true
languageLevelSetting = 1.8
jxBrowserVersion = '7.26'
}
applyGlobalConfigPathIfExist()
@ -104,8 +105,8 @@ allprojects {
implementation 'com.fr.messenger:fine-messenger:' + carinaVersion
implementation 'com.install4j:install4j-runtime:8.0.4'
implementation 'com.fr.third:jxbrowser:6.23'
implementation 'com.fr.third:jxbrowser-v7:7.22'
implementation 'com.fr.third:jxbrowser-swing-v7:7.22'
implementation "com.fr.third:jxbrowser-v7:${jxBrowserVersion}"
implementation "com.fr.third:jxbrowser-swing-v7:${jxBrowserVersion}"
implementation 'com.fr.third.server:servlet-api:3.0'
implementation 'org.swingexplorer:swexpl:2.0.1'
implementation 'org.swingexplorer:swag:1.0'
@ -125,21 +126,29 @@ allprojects {
implementation 'com.fr.report:engine-chart:' + frDevVersion
implementation 'com.fr.report:engine-i18n:' + frDevVersion
implementation 'com.fr.design:design-i18n:' + frDevVersion
implementation 'com.fine.swing.ui:layout:1.0-SNAPSHOT'
testImplementation 'org.easymock:easymock:3.5.1'
testImplementation 'org.powermock:powermock-module-junit4:1.7.1'
testImplementation 'org.powermock:powermock-api-easymock:1.7.1'
testImplementation 'org.powermock:powermock-api-mockito2:1.7.4'
testImplementation 'junit:junit:4.12'
}
if (OperatingSystem.current().isMacOsX()) {
// mac_x64, mac_aarch64, windows_x64
if (OperatingSystem.current().isMacOsX() && "aarch64".equals(System.getProperty("os.arch"))) {
dependencies {
// jxbrowser 6.23M16.23jar还是需要留着
implementation "com.fr.third:jxbrowser-mac-arm-v7:${jxBrowserVersion}"
}
} else if (OperatingSystem.current().isMacOsX()) {
dependencies {
implementation 'com.fr.third:jxbrowser-mac:6.23'
implementation 'com.fr.third:jxbrowser-mac-v7:7.22'
implementation "com.fr.third:jxbrowser-mac-v7:${jxBrowserVersion}"
}
} else if (OperatingSystem.current().isWindows()) {
dependencies {
implementation 'com.fr.third:jxbrowser-win64:6.23'
implementation 'com.fr.third:jxbrowser-win64-v7:7.22'
implementation "com.fr.third:jxbrowser-win64-v7:${jxBrowserVersion}"
}
}
}

12
designer-base/src/main/java/com/fr/base/svg/SVGIcon.java

@ -1,9 +1,12 @@
package com.fr.base.svg;
import com.fr.design.utils.SvgDrawUtils;
import com.fr.general.IOUtils;
import javax.swing.*;
import java.awt.*;
import javax.swing.Icon;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -34,10 +37,7 @@ public class SVGIcon implements Icon {
public void paintIcon(Component c, Graphics g, int x, int y) {
if (HI_DPI_SURPORT) {
Graphics2D graphics = (Graphics2D) g.create(x, y, image.getWidth(null), image.getHeight(null));
float scale = SYSTEM_SCALE;
graphics.scale(1 / scale, 1 / scale);
graphics.drawImage(image, 0, 0, null);
graphics.scale(1.0D, 1.0D);
SvgDrawUtils.doDrawSVG(graphics, () -> SvgDrawUtils.drawImage(graphics, image, 0, 0, null));
graphics.dispose();
} else {
g.drawImage(image, x, y, null);

18
designer-base/src/main/java/com/fr/design/DesignerEnvManager.java

@ -310,7 +310,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada
private static boolean asyncInitEnvManager() {
AtomicBoolean noEx = new AtomicBoolean(false);
OptimizeUtil.open(DesignerEnvManager.class.getSimpleName().toLowerCase(), OptimizeUtil.Module.COMMON, () -> {
OptimizeUtil.initiateOpen(DesignerEnvManager.class.getSimpleName().toLowerCase(), () -> {
try {
designerEnvManager.initElements(designerEnvManager.getDesignerEnvFile());
noEx.set(true);
@ -901,13 +901,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada
}
public boolean isCloudAnalyticsDelay() {
return designerPushUpdateConfigManager.isCloudAnalyticsDelay();
return designerPushUpdateConfigManager.isCloudAnalyticsDelay() || designerPushUpdateConfigManager.isUseCloudAnalyticsDelayFirst();
}
public void setCloudAnalyticsDelay(boolean cloudAnalyticsDelay) {
designerPushUpdateConfigManager.setCloudAnalyticsDelay(cloudAnalyticsDelay);
}
public void setUseCloudAnalyticsDelayFirst(boolean useCloudAnalyticsDelayFirst) {
designerPushUpdateConfigManager.setUseCloudAnalyticsDelayFirst(useCloudAnalyticsDelayFirst);
}
/**
* 设计器登录相关配置
*/
@ -1023,6 +1028,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada
designerLoginConfigManager.setUseOldVersionLogin(useOldVersionLogin);
}
public boolean isUseNewPluginFirst() {
return designerLoginConfigManager.isUseNewPluginFirst();
}
public void setUseNewPluginFirst(boolean useNewPluginFirst) {
designerLoginConfigManager.setUseNewPluginFirst(useNewPluginFirst);
}
/**
* 内置服务器是否使用时启动
*
@ -1896,6 +1909,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReada
.init("jdkHome", (e) -> this.jdkHome = e.getElementValue())
.init("lastBBSTime", DesignerEnvManager.this::readLastBBSTime)
.init("lastBBSNewsTime", DesignerEnvManager.this::readLastBBSNewsTime)
.init("uuid", DesignerEnvManager.this::readUUID)
.init("ActivationKey", DesignerEnvManager.this::readActiveKey)
.init("status", DesignerEnvManager.this::readActiveStatus)
.init(CAS_PARAS, DesignerEnvManager.this::readHttpsParas)

263
designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java

@ -14,13 +14,16 @@ import com.fr.design.env.DesignerWorkspaceInfoContext;
import com.fr.design.env.DesignerWorkspaceType;
import com.fr.design.env.RemoteDesignerWorkspaceInfo;
import com.fr.design.env.RemoteWorkspace;
import com.fr.design.env.processor.RemoteDesignerWorkspaceInfoProcessor;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.SaveSomeTemplatePane;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.manager.clip.TemplateTreeClipboard;
import com.fr.design.notification.NotificationCenter;
import com.fr.design.plugin.remind.PluginErrorDesignReminder;
import com.fr.design.utils.DesignUtils;
import com.fr.design.versioncheck.VersionCheckUtils;
import com.fr.env.EnvListPane;
@ -31,6 +34,7 @@ import com.fr.invoke.Reflect;
import com.fr.json.JSONArray;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.performance.profile.PerformancePoint;
import com.fr.process.ProcessEventPipe;
import com.fr.process.engine.core.CarryMessageEvent;
import com.fr.process.engine.core.FineProcessContext;
@ -41,12 +45,14 @@ import com.fr.start.server.ServerTray;
import com.fr.workspace.WorkContext;
import com.fr.workspace.WorkContextCallback;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceSwitchProcess;
import com.fr.workspace.base.WorkspaceAPI;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import com.fr.workspace.engine.base.FineObjectPool;
import com.fr.workspace.engine.channel.http.FunctionalHttpRequest;
import com.fr.workspace.engine.exception.WorkspaceConnectionException;
import com.fr.workspace.engine.rpc.WorkspaceProxyPool;
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
@ -58,15 +64,17 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.HashSet;
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
public class EnvChangeEntrance {
private static final String BRANCH_TAG = "#";
private static final String BRANCH_BEGIN = "-";
private static final int BRANCH_SUB_LENGTH = 13;
public static EnvChangeEntrance getInstance() {
return HOLDER.singleton;
@ -100,56 +108,139 @@ public class EnvChangeEntrance {
}
}
/**
* 插件进行用户名转换
*
* @param workspaceInfo 环境信息
*/
private DesignerWorkspaceInfo customUserName(DesignerWorkspaceInfo workspaceInfo) {
//本地环境直接返回
if (workspaceInfo == null || workspaceInfo.getType() == DesignerWorkspaceType.Local) {
return workspaceInfo;
}
RemoteDesignerWorkspaceInfoProcessor processor = ExtraDesignClassManager.getInstance().getSingle(RemoteDesignerWorkspaceInfoProcessor.XML_TAG);
if (processor == null) {
return workspaceInfo;
}
try {
WorkspaceConnectionInfo workspaceConnectionInfo = processor.customUserName(workspaceInfo.getConnection());
return (RemoteDesignerWorkspaceInfo) ((RemoteDesignerWorkspaceInfo) workspaceInfo).cloneWithConnectionInfo(workspaceConnectionInfo);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return workspaceInfo;
}
}
/**
* 切换到新环境
*
* @param envName 新工作环境名称
* @param strategy 提示策略
* @return 是否成功
*/
private boolean switch2Env(final String envName, PopTipStrategy strategy) {
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
DesignerWorkspaceInfo selectedEnv = envManager.getWorkspaceInfo(envName);
DesignerWorkspaceInfoContext.setWorkspaceInfo(selectedEnv);
WorkspaceConnectionInfo connectionInfo = selectedEnv.getConnection();
WorkspaceSwitchProcess lastProcess = WorkContext.getSwitcher().getProcess();
PerformancePoint performancePoint = PerformancePoint.create();
boolean switchStatus = doSwitch2Env(envName, strategy);
WorkspaceSwitchProcess currentProcess = WorkContext.getSwitcher().getProcess();
// 如果相同,代表根本没切换 ==
if (lastProcess != currentProcess) {
// 记录切换耗时
recordSwitchInfos(performancePoint, switchStatus);
// 触发切换埋点
triggerSwitchMetric();
}
return switchStatus;
}
/**
* 由云端运维触发切换埋点
* 内部空实现
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=945327503">实现</a>
*/
private void triggerSwitchMetric() {
}
/**
* 切换到新环境
* 1. 先获取选中的环境
* 2. 生成工作目录
* 3. 验证工作目录
* 4. 触发切换操作
* 5. 触发可能存在异常的切换后动作
* 6. 触发切换后动作
*
* @param envName 新工作环境名称
* @return 是否成功
*/
private boolean doSwitch2Env(final String envName, PopTipStrategy strategy) {
DesignerWorkspaceInfo selectedEnv = getSelectedEnv(envName);
EnvBackupHelper.getInstance().backup();
try {
Workspace workspace = DesignerWorkspaceGenerator.generate(selectedEnv);
boolean checkValid = workspace != null && selectedEnv.checkValid();
if (!checkValid) {
if (notValid(workspace, selectedEnv)) {
return false;
}
// 更新目标环境
EnvBackupHelper.getInstance().prepare4switch(workspace);
WorkContext.switchTo(workspace, new WorkContextCallback() {
@Override
public void done() {
DesignerEnvManager.getEnvManager().setCurEnvName(envName);
DesignUtils.refreshDesignerFrame();
DesignTableDataManager.fireDSChanged(new HashMap<String, String>());
if (WorkContext.getCurrent().isLocal()) {
//初始化一下serverTray
ServerTray.init();
}
EnvBackupHelper.getInstance().success();
}
});
// REPORT-25688如果是war包部署的服务器,给与提示
if (WorkContext.getCurrent().isWarDeploy()) {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_War_Deploy_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE);
}
//REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录
JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (template != null) {
template.refreshToolArea();
}
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
doSwitchAction(envName, workspace);
afterSwitchWithEx();
} catch (Exception exception) {
// 失败的处理
EnvBackupHelper.getInstance().failed();
WorkspaceExceptionHandler.getInstance().handleInSwitch(exception, selectedEnv);
return false;
}
afterSwitch();
return true;
}
private DesignerWorkspaceInfo getSelectedEnv(String envName) {
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
DesignerWorkspaceInfo selectedEnv = customUserName(envManager.getWorkspaceInfo(envName));
DesignerWorkspaceInfoContext.setWorkspaceInfo(selectedEnv);
return selectedEnv;
}
private static boolean notValid(Workspace workspace, DesignerWorkspaceInfo selectedEnv) throws Exception {
boolean checkValid = workspace != null && selectedEnv.checkValid();
return !checkValid;
}
private void doSwitchAction(String envName, Workspace workspace) {
//如果是相同环境
if (isSameEnv(workspace)) {
//目前切换到相同环境需要更新一下名字,后续如果有别的操作直接往里面加就行了
switch2SameEnv(envName);
} else {
//切换到新环境,做下封装
switch2OtherEnv(workspace, envName);
}
}
private static void afterSwitchWithEx() {
EnvBackupHelper.getInstance().success();
// REPORT-25688如果是war包部署的服务器,给与提示
if (WorkContext.getCurrent().isWarDeploy()) {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_War_Deploy_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE);
}
//REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录
JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (JTemplate.isValid(template)) {
template.refreshToolArea();
}
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
}
private static void afterSwitch() {
TemplateTreePane.getInstance().refreshDockingView();
DesignModelAdapter<?, ?> model = DesignModelAdapter.getCurrentModelAdapter();
if (model != null) {
@ -158,7 +249,59 @@ public class EnvChangeEntrance {
NotificationCenter.getInstance().clearAllNotifications();
//切换环境后,清空粘贴板里面的内容
TemplateTreeClipboard.getInstance().reset();
return true;
}
private static void recordSwitchInfos(PerformancePoint performancePoint, boolean switchSuccess) {
performancePoint.end(elapsed -> {
WorkspaceSwitchProcess process = WorkContext.getSwitcher().getProcess();
Optional.ofNullable(process)
.ifPresent((e) -> {
e.recordSwitchElapsed(elapsed);
e.setSwitchSuccess(switchSuccess);
});
});
}
/**
* 切换到其他环境
*
* @param workspace 要切换的环境
* @param envName 要切换的环境名称
*/
private void switch2OtherEnv(Workspace workspace, String envName) {
WorkContext.switchTo(workspace, new WorkContextCallback() {
@Override
public void done() {
DesignerEnvManager.getEnvManager().setCurEnvName(envName);
DesignUtils.refreshDesignerFrame();
DesignTableDataManager.fireDSChanged(new HashMap<String, String>());
if (WorkContext.getCurrent().isLocal()) {
//初始化一下serverTray
ServerTray.init();
}
}
});
}
/**
* 切换到相同环境要做的事情
*
* @param envName 当前的环境名
*/
private void switch2SameEnv(String envName) {
//当前环境名称可能重命名更改过,需要更新一下,防止启动失败
DesignerEnvManager.getEnvManager().setCurEnvName(envName);
}
/**
* 是否切换到相同环境
*
* @param workspace 要切换的环境
* @return 是则返回true
*/
private boolean isSameEnv(Workspace workspace) {
return AssistUtils.equals(WorkContext.getCurrent(), workspace);
}
/**
@ -206,13 +349,14 @@ public class EnvChangeEntrance {
return true;
}
/**
/**
* 对选择的环境做服务检测
*
* @param selectedEnv 选择的工作环境
*/
public void showServiceDialog(DesignerWorkspaceInfo selectedEnv) throws Exception {
//是否需要做服务校验
if(needCheckBranch(selectedEnv)) {
if (needCheckBranch(selectedEnv)) {
String localBranch;
String remoteBranch;
WorkspaceConnectionInfo connectionInfo = selectedEnv.getConnection();
@ -233,18 +377,18 @@ public class EnvChangeEntrance {
StringBuilder textBuilder = new StringBuilder();
for (Class clazz : noExistServiceSet) {
WorkspaceAPI workspaceAPI = (WorkspaceAPI) clazz.getAnnotation(WorkspaceAPI.class);
if(workspaceAPI == null){
if (workspaceAPI == null) {
FineLoggerFactory.getLogger().info("workspace service {} get annotation failed", clazz);
continue;
}
if(workspaceAPI.ignore()){
if (workspaceAPI.ignore()) {
continue;
}
String descriptionOfCN = InterProviderFactory.getProvider().getLocText(workspaceAPI.description());
textBuilder.append(descriptionOfCN).append("\n");
}
String areaText = textBuilder.toString();
if(StringUtils.isEmpty(areaText)){
if (StringUtils.isEmpty(areaText)) {
return;
}
@ -256,24 +400,25 @@ public class EnvChangeEntrance {
* 判断是否需要做版本验证判断依据为
* 1选择的环境为远程环境
* 2一个月内不弹出是否勾选
*
* @param selectedEnv 选择的环境
* @return
*/
private boolean needCheckBranch(DesignerWorkspaceInfo selectedEnv){
if(selectedEnv.getType() == DesignerWorkspaceType.Remote){
private boolean needCheckBranch(DesignerWorkspaceInfo selectedEnv) {
if (selectedEnv.getType() == DesignerWorkspaceType.Remote) {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
if(StringUtils.isEmpty(selectedEnv.getRemindTime())){
if (StringUtils.isEmpty(selectedEnv.getRemindTime())) {
return true;
}
//获取记录的时间
Date remindTime = format.parse(selectedEnv.getRemindTime());
calendar.setTime(remindTime);
//获取一个月后的时间
calendar.add(Calendar.MONTH,1);
calendar.add(Calendar.MONTH, 1);
//与当前时间作对比,然后判断是否提示
if(new Date().after(calendar.getTime())){
if (new Date().after(calendar.getTime())) {
return true;
}
} catch (ParseException e) {
@ -285,21 +430,22 @@ public class EnvChangeEntrance {
/**
* 获取不存在的服务列表
*
* @param info 环境连接信息
* @return 以Set形式返回不存在的服务
*/
public Set<Class> getNoExistServiceSet(WorkspaceConnectionInfo info){
public Set<Class> getNoExistServiceSet(WorkspaceConnectionInfo info) {
Set<Class> noExistServiceSet = new HashSet<Class>();
Set<Class> remoteServiceSet = new HashSet<Class>();
Set<Class> localServiceSet = FineObjectPool.getInstance().getServerPool().keySet();
try {
JSONArray serviceArray = new FunctionalHttpRequest(info).getServiceList();
for(int i = 0; i < serviceArray.size(); i++){
try{
JSONArray serviceArray = new FunctionalHttpRequest(info).getServiceList(info);
for (int i = 0; i < serviceArray.size(); i++) {
try {
Class clazz = Class.forName((String) serviceArray.get(i));
remoteServiceSet.add(clazz);
} catch (Exception e){
} catch (Exception e) {
continue;
}
}
@ -309,12 +455,12 @@ public class EnvChangeEntrance {
} catch (WorkspaceConnectionException e) {
FineLoggerFactory.getLogger().info(e.getMessage());
//根据本地的服务列表做逐一检测
for(Class clazz : localServiceSet) {
for (Class clazz : localServiceSet) {
Method testMethod = Reflect.on(Method.class).create(clazz, "connectTest", new Class[0], String.class, new Class[0], 1025, 8, null, null, null, null).get();
WorkspaceProxyPool proxyPool = (WorkspaceProxyPool) (((RemoteWorkspace) WorkContext.getCurrent()).getClient()).getPool();
Result result = proxyPool.testInvoker(testMethod);
Exception invokeException = (Exception) result.getException();
if(invokeException != null){
if (invokeException != null) {
Exception cause = (Exception) invokeException.getCause();
//获取被包装最底层的异常
while (cause != null) {
@ -322,26 +468,27 @@ public class EnvChangeEntrance {
cause = (Exception) invokeException.getCause();
}
//该异常表示服务不存在
if(invokeException instanceof ClassNotFoundException){
if (invokeException instanceof ClassNotFoundException) {
noExistServiceSet.add(clazz);
}
}
}
return noExistServiceSet;
} catch (Exception e){
FineLoggerFactory.getLogger().error(e.getMessage(),e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return noExistServiceSet;
}
}
/**
* 格式化分支版本号
*
* @param branch 初始的分支版本号
* @return 格式化后的版本号
*/
private String formatBranch(String branch){
if(branch.contains("#")){
return branch.substring(branch.lastIndexOf("-") + 1, branch.length() - 13);
private String formatBranch(String branch) {
if (branch.contains(BRANCH_TAG)) {
return branch.substring(branch.lastIndexOf(BRANCH_BEGIN) + 1, branch.length() - BRANCH_SUB_LENGTH);
}
return branch;
}
@ -375,7 +522,7 @@ public class EnvChangeEntrance {
@Override
public void doOk() {
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true, SwingUtilities.getWindowAncestor(envListPane));
if (!saveSomeTemplatePane.showSavePane()) {
if (!saveSomeTemplatePane.showSavePane(true)) {
// 用户取消保存时,取消切换目录操作
return;
}

16
designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java

@ -1,14 +1,22 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.*;
import javax.swing.KeyStroke;
public class BBSAction extends AbstractDesignerSSO {
/**
* 云中心帆软社区页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Bbs";
/**
* 云中心帆软社区页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Bbs_Default";
public BBSAction() {
this.setMenuKeySet(BBS);
@ -20,7 +28,7 @@ public class BBSAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs", "http://bbs.fanruan.com/");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet BBS = new MenuKeySet() {

16
designer-base/src/main/java/com/fr/design/actions/community/BugAction.java

@ -1,13 +1,23 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.*;
import javax.swing.KeyStroke;
public class BugAction extends AbstractDesignerSSO {
/**
* 云中心产品反馈页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Bugs";
/**
* 云中心产品反馈页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Bugs_Default";
public BugAction() {
this.setMenuKeySet(BUG);
this.setName(getMenuKeySet().getMenuName());
@ -17,7 +27,7 @@ public class BugAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "https://service.fanruan.com/PF/FR/feedback?type=2");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet BUG = new MenuKeySet() {

15
designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java

@ -1,7 +1,7 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.KeyStroke;
@ -9,6 +9,17 @@ import javax.swing.KeyStroke;
* Created by XINZAI on 2018/8/23.
*/
public class CenterAction extends UpAction {
/**
* 云中心活动中心页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Act_Center";
/**
* 云中心活动中心页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Act_Center_Default";
public CenterAction() {
this.setMenuKeySet(CENTER);
this.setName(getMenuKeySet().getMenuName());
@ -18,7 +29,7 @@ public class CenterAction extends UpAction {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.center", "http://bbs.fanruan.com/events/");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet CENTER = new MenuKeySet() {

18
designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java

@ -1,18 +1,28 @@
package com.fr.design.actions.community;
import com.fr.base.BaseUtils;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.menu.MenuKeySet;
import com.fr.design.utils.BrowseUtils;
import com.fr.general.CloudCenter;
import javax.swing.KeyStroke;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
/**
* Created by XINZAI on 2018/8/23.
*/
public class CusDemandAction extends UpAction{
/**
* 云中心发布需求页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Demand";
/**
* 云中心发布需求页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Demand_Default";
public CusDemandAction()
{
this.setMenuKeySet(DEMAND);
@ -25,7 +35,7 @@ public class CusDemandAction extends UpAction{
@Override
public void actionPerformed(ActionEvent arg0)
{
String url = CloudCenter.getInstance().acquireUrlByKind("bbs.demand", "https://market.fanruan.com/demand");
String url = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
BrowseUtils.browser(url);
}

16
designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java

@ -1,14 +1,24 @@
package com.fr.design.actions.community;
import com.fr.base.svg.IconUtils;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.menu.MenuKeySet;
import com.fr.design.utils.BrowseUtils;
import com.fr.general.CloudCenter;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
public class FacebookFansAction extends UpAction {
/**
* 云中心facebook页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_FaceBook";
/**
* 云中心facebook页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_FaceBook_Default";
public FacebookFansAction() {
this.setMenuKeySet(FACEBOOKFANS);
this.setName(getMenuKeySet().getMenuName());
@ -18,7 +28,7 @@ public class FacebookFansAction extends UpAction {
@Override
public void actionPerformed(ActionEvent arg0) {
BrowseUtils.browser(CloudCenter.getInstance().acquireUrlByKind("facebook.fans.tw", "https://www.facebook.com/twfinereport"));
BrowseUtils.browser(LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT));
}
public static final MenuKeySet FACEBOOKFANS = new MenuKeySet() {

16
designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java

@ -1,13 +1,23 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.*;
import javax.swing.KeyStroke;
public class NeedAction extends AbstractDesignerSSO {
/**
* 云中心产品反馈页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Need";
/**
* 云中心产品反馈页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Need_Default";
public NeedAction() {
this.setMenuKeySet(NEED);
this.setName(getMenuKeySet().getMenuName());
@ -18,7 +28,7 @@ public class NeedAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "https://service.fanruan.com/PF/FR/feedback?type=1");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet NEED = new MenuKeySet() {

16
designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java

@ -1,13 +1,23 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.*;
import javax.swing.KeyStroke;
public class QuestionAction extends AbstractDesignerSSO {
/**
* 云中心问答页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Question";
/**
* 云中心问答页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Question_Default";
public QuestionAction() {
this.setMenuKeySet(QUESTIONS);
this.setName(getMenuKeySet().getMenuName());
@ -18,7 +28,7 @@ public class QuestionAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.questions", "http://bbs.fanruan.com/wenda");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet QUESTIONS = new MenuKeySet() {

17
designer-base/src/main/java/com/fr/design/actions/community/SignAction.java

@ -1,14 +1,23 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.*;
import javax.swing.KeyStroke;
public class SignAction extends AbstractDesignerSSO {
/**
* 云中心认证落地页在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Aut";
/**
* 云中心认证落地页默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Aut_Default";
public SignAction() {
this.setMenuKeySet(SIGN);
this.setName(getMenuKeySet().getMenuName());
@ -18,7 +27,7 @@ public class SignAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.aut", "https://bbs.fanruan.com/certification/");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet SIGN = new MenuKeySet() {

15
designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java

@ -1,10 +1,21 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.general.CloudCenter;
public class StudyPlanAction extends AbstractDesignerSSO {
/**
* 云中心帆软学院在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Study";
/**
* 云中心帆软学院默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Study_Default";
public StudyPlanAction() {
this.setName(Toolkit.i18nText("Fine-Design_Study_Plan"));
this.setSmallIcon("/com/fr/design/images/bbs/studyPlan");
@ -12,6 +23,6 @@ public class StudyPlanAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
}

15
designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java

@ -1,8 +1,8 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.KeyStroke;
@ -10,6 +10,17 @@ import javax.swing.KeyStroke;
* Created by XINZAI on 2018/8/23.
*/
public class TechSolutionAction extends AbstractDesignerSSO {
/**
* 云中心社区在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Community";
/**
* 云中心社区默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Community_Default";
public TechSolutionAction() {
this.setMenuKeySet(TSO);
this.setName(getMenuKeySet().getMenuName());
@ -20,7 +31,7 @@ public class TechSolutionAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.solution", "http://bbs.fanruan.com/forum-113-1.html");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet TSO = new MenuKeySet() {

19
designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java

@ -1,21 +1,28 @@
package com.fr.design.actions.community;
import com.fr.base.BaseUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.menu.MenuKeySet;
import com.fr.design.utils.BrowseUtils;
import com.fr.general.CloudCenter;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
/**
* created by Harrison on 2020/03/24
**/
public class TemplateStoreAction extends AbstractDesignerSSO {
/**
* 云中心组件商城模板在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Market_Template";
/**
* 云中心组件商城模板默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Market_Template_Default";
public TemplateStoreAction() {
this.setMenuKeySet(TEMPLATE);
@ -47,6 +54,6 @@ public class TemplateStoreAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
ComponentCollector.getInstance().collectTepMenuEnterClick();
return CloudCenter.getInstance().acquireUrlByKind("design.market.template", "https://market.fanruan.com/template");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
}

14
designer-base/src/main/java/com/fr/design/actions/community/UpAction.java

@ -1,14 +1,24 @@
package com.fr.design.actions.community;
import com.fr.base.BaseUtils;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import javax.swing.KeyStroke;
public class UpAction extends AbstractDesignerSSO {
/**
* 云中心工单中心在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Bbs_Update";
/**
* 云中心工单中心默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Bbs_Update_Default";
public UpAction() {
this.setMenuKeySet(UPDATE);
this.setName(getMenuKeySet().getMenuName());
@ -18,7 +28,7 @@ public class UpAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.update", "http://bbs.fanruan.com/forum.php?mod=collection&action=view&ctid=10");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT);
}
public static final MenuKeySet UPDATE = new MenuKeySet() {

15
designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java

@ -1,7 +1,7 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.general.CloudCenter;
/**
* @Description 工单中心
@ -9,6 +9,17 @@ import com.fr.general.CloudCenter;
* @Date 2021/3/8 14:02
**/
public class WorkOrderCenterAction extends UpAction {
/**
* 云中心工单中心在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Work_Order_Center";
/**
* 云中心工单中心默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Work_Order_Center_Default";
public WorkOrderCenterAction() {
this.setSmallIcon("/com/fr/design/images/bbs/workOrderCenter");
this.setName(Toolkit.i18nText("Fine-Design_Basic_Commuinity_Work_Order_Center"));
@ -16,6 +27,6 @@ public class WorkOrderCenterAction extends UpAction {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.work.order.center", "https://service.fanruan.com/ticket");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
}
}

330
designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java

@ -36,12 +36,15 @@ import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.mainframe.vcs.ui.UIPositiveIntEditor;
import com.fr.design.mainframe.vcs.ui.VcsMovePanel;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.unit.UnitConvertUtil;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRFont;
import com.fr.general.GeneralContext;
import com.fr.general.IOUtils;
import com.fr.general.Inter;
import com.fr.general.log.Log4jConfig;
@ -49,14 +52,22 @@ import com.fr.io.attr.ImageExportAttr;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.report.ReportConfigManager;
import com.fr.scheduler.tool.FineScheduler;
import com.fr.stable.Constants;
import com.fr.stable.os.OperatingSystem;
import com.fr.third.apache.logging.log4j.Level;
import com.fr.third.guava.collect.BiMap;
import com.fr.third.guava.collect.HashBiMap;
import com.fr.transaction.Configurations;
import com.fr.transaction.Worker;
import com.fr.transaction.WorkerAdaptor;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsConfig;
import com.fr.workspace.server.vcs.VcsOperator;
import com.fr.workspace.server.vcs.git.config.GcConfig;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanOperator;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanSchedule;
import com.fr.workspace.server.vcs.v2.scheduler.VcsAutoCleanService;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
@ -65,6 +76,7 @@ import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
@ -77,14 +89,7 @@ import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Window;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
@ -95,6 +100,7 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@ -122,6 +128,7 @@ public class PreferencePane extends BasicPane {
private static final int PREFERENCE_LABEL_MAX_WIDTH = 460;
private static final int OFFSET_HEIGHT = 60;
private static final int VCS_FILL_TOTAL = 5;
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
private static final String BACK_SLASH = "BACK_SLASH";
@ -149,6 +156,34 @@ public class PreferencePane extends BasicPane {
private static final Level[] LOG = {Level.FATAL, Level.ERROR, Level.WARN, Level.INFO, Level.DEBUG};
private static final int ONE_DAY_INT = 1;
private static final int ONE_WEEK_INT = 7;
private static final int ONE_MONTH_INT = 30;
private static final int THREE_MONTH_INT = 90;
private static final int SIX_MONTH_INT = 180;
private static final int ONE_DAY_INDEX = 0;
private static final int ONE_WEEK_INDEX = 1;
private static final int ONE_MONTH_INDEX = 2;
private static final int THREE_MONTH_INDEX = 3;
private static final int SIX_MONTH_INDEX = 4;
private static final String ONE_DAY = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_ONE_DAY");
private static final String ONE_WEEK = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_ONE_WEEK");
private static final String ONE_MONTH = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_ONE_MONTH");
private static final String THREE_MONTH = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_THREE_MONTH");
private static final String SIX_MONTH = Toolkit.i18nText("Fine-Design_Vcs_Auto_Clean_SIX_MONTH");
private static final String[] INTERVAL = {
ONE_DAY,
ONE_WEEK,
ONE_MONTH,
THREE_MONTH,
SIX_MONTH
};
private static final int DEFAULT_INDEX = 3;
private BasicDialog basicDialog;
private boolean languageChanged; // 是否修改了设计器语言设置
//设置是否支持undo
private UICheckBox supportUndoCheckBox;
@ -186,10 +221,24 @@ public class PreferencePane extends BasicPane {
private UICheckBox cloudAnalyticsDelayCheckBox;
private UICheckBox vcsEnableCheckBox;
private UICheckBox useVcsAutoSaveScheduleCheckBox;
private UICheckBox useVcsAutoCleanScheduleCheckBox;
private UIComboBox autoCleanIntervalComboBox;
private UIComboBox autoCleanRetainIntervalComboBox;
private UIPositiveIntEditor autoSaveIntervalEditor;
private UICheckBox saveCommitCheckBox;
private UICheckBox useIntervalCheckBox;
private VcsMovePanel movePanel;
private JPanel saveIntervalPane;
private JPanel autoCleanPane;
private JPanel gcControlPane;
private UICheckBox startupPageEnabledCheckBox;
private IntegerEditor saveIntervalEditor;
private UIPositiveIntEditor saveIntervalEditor;
private UICheckBox gcEnableCheckBox;
private UIButton gcButton;
private UILabel remindVcsLabel;
@ -201,7 +250,7 @@ public class PreferencePane extends BasicPane {
private JProgressBar gcProgressBar;
private Timer gcProgressTimer;
private UIButton gcOkButton = new UIButton(i18nText("Fine-Design_Report_OK"));
private UIRadioButton previewResolutionBtnS;
private UIRadioButton previewResolutionBtnM;
@ -209,7 +258,15 @@ public class PreferencePane extends BasicPane {
private UIRadioButton previewRenderQuality;
private static final int DPI_SCALE_S = 1;
private static final int DPI_SCALE_M = 2;
private static final BiMap<Integer, Integer> INDEX_DAY_MAP = HashBiMap.create(new HashMap<Integer, Integer>() {
{
put(ONE_DAY_INDEX, ONE_DAY_INT);
put(ONE_WEEK_INDEX, ONE_WEEK_INT);
put(ONE_MONTH_INDEX, ONE_MONTH_INT);
put(SIX_MONTH_INDEX, SIX_MONTH_INT);
put(THREE_MONTH_INDEX, THREE_MONTH_INT);
}
});
public PreferencePane() {
this.initComponents();
}
@ -223,17 +280,30 @@ public class PreferencePane extends BasicPane {
JPanel generalPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
UIScrollPane generalScrollPane = patchScroll(generalPane);
jtabPane.addTab(i18nText("Fine-Design_Basic_General"), generalScrollPane);
JPanel advancePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
UIScrollPane adviceScrollPane = patchScroll(advancePane);
jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), adviceScrollPane);
//初始化vcs总面板
JPanel vcsParentPane = new JPanel();
CardLayout cardLayout = new CardLayout();
vcsParentPane.setLayout(cardLayout);
//vcs配置面板
JPanel vcsPane = new JPanel(new BorderLayout());
//添加滚动条
UIScrollPane vcsScrollPane = patchScroll(vcsPane);
//配置面板作为vcs总面板的一张卡片
vcsParentPane.add(vcsScrollPane, VcsMovePanel.SETTING);
jtabPane.addTab(i18nText("Fine-Design_Vcs_Title"), vcsParentPane);
contentPane.add(jtabPane, BorderLayout.NORTH);
createFunctionPane(generalPane);
createEditPane(generalPane);
createColorSettingPane(generalPane);
createVcsSettingPane(generalPane);
// vcsPane
createVcsSettingPane(vcsPane, vcsParentPane, cardLayout);
// ConfPane
JPanel confLocationPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
@ -242,7 +312,7 @@ public class PreferencePane extends BasicPane {
createLogPane(advancePane);
createLanPane(generalPane);
createStartupPagePane(generalPane);
createLengthPane(advancePane);
@ -309,7 +379,7 @@ public class PreferencePane extends BasicPane {
designerStartupOption.add(cloudAnalyticsDelayCheckBox);
advancePane.add(designerStartupOption);
}
private JPanel createImageExportSettingPane() {
previewResolutionBtnS = new UIRadioButton(i18nText("Fine-Design_Image_Export_SD"), true);
previewResolutionBtnM = new UIRadioButton(i18nText("Fine-Design_Image_Export_HD"));
@ -345,20 +415,34 @@ public class PreferencePane extends BasicPane {
generalPanelWithScroll.setPreferredSize(new Dimension(generalPane.getWidth(), 600));
return generalPanelWithScroll;
}
private void createVcsSettingPane(JPanel generalPane) {
JPanel vcsPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Title"));
generalPane.add(vcsPane);
private void createVcsSettingPane(JPanel generalPane,JPanel parentPane, CardLayout cardLayout) {
//迁移面板
movePanel = createMovePane(cardLayout, parentPane);
generalPane.add(movePanel, BorderLayout.NORTH);
JPanel savePane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Save_Setting"));
JPanel vcsPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Clean_Setting"));
JPanel containPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
containPane.add(savePane);
containPane.add(vcsPane);
//填充一下面板
fillPane(containPane, VCS_FILL_TOTAL);
generalPane.add(containPane, BorderLayout.CENTER);
remindVcsLabel = new UILabel(i18nText("Fine-Design_Vcs_Remind"));
remindVcsLabel.setVisible(!VcsHelper.getInstance().needInit());
vcsEnableCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_SaveAuto"));
saveIntervalPane = createSaveIntervalPane();
saveCommitCheckBox = new UICheckBox(i18nText("Fine-Design_Vcs_No_Delete"));
saveIntervalEditor = new IntegerEditor(60);
saveIntervalEditor = new UIPositiveIntEditor(60);
useIntervalCheckBox = new UICheckBox();
savePane.add(vcsEnableCheckBox);
savePane.add(saveIntervalPane);
//gc面板
gcControlPane = createGcControlPane();
JPanel enableVcsPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
enableVcsPanel.add(vcsEnableCheckBox);
enableVcsPanel.add(remindVcsLabel);
JPanel intervalPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
final UILabel everyLabel = new UILabel(i18nText("Fine-Design_Vcs_Every"));
@ -367,6 +451,8 @@ public class PreferencePane extends BasicPane {
intervalPanel.add(everyLabel);
intervalPanel.add(saveIntervalEditor);
intervalPanel.add(delayLabel);
autoCleanPane = createAutoCleanPane();
checkAutoScheduleStartAndUpdateStatus();
vcsEnableCheckBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
@ -388,34 +474,104 @@ public class PreferencePane extends BasicPane {
});
vcsPane.add(enableVcsPanel);
vcsPane.add(intervalPanel);
vcsPane.add(saveCommitCheckBox);
if (VcsHelper.getInstance().isLegacyMode()) {
vcsPane.add(saveCommitCheckBox);
}
vcsPane.add(autoCleanPane);
boolean support = VcsHelper.getInstance().checkV2FunctionSupport();
saveIntervalPane.setVisible(support);
autoCleanPane.setVisible(support);
if (VcsHelper.getInstance().isLegacyMode()) {
// 老版本时才显示gc选项
vcsPane.add(gcControlPane);
}
}
initGcControlPane(vcsPane);
private void fillPane(JPanel containPane, int total) {
for (int i = 0; i < total; i++) {
containPane.add(new JPanel());
}
}
private void initGcControlPane(JPanel vcsPane) {
JPanel gcControlPane = createGcControlPane();
new SwingWorker<Boolean, Boolean>() {
private VcsMovePanel createMovePane(CardLayout cardLayout, JPanel parentPane) {
return new VcsMovePanel(cardLayout, parentPane, new VcsMovePanel.MoveCallBack(){
@Override
protected Boolean doInBackground() throws Exception {
return WorkContext.getCurrent().get(VcsOperator.class).isLegacyMode();
public void doCallBack(boolean useV2) {
saveIntervalPane.setVisible(useV2);
autoCleanPane.setVisible(useV2);
gcControlPane.setVisible(!useV2);
saveCommitCheckBox.setVisible(!useV2);
useVcsAutoCleanScheduleCheckBox.setSelected(useV2);
useVcsAutoSaveScheduleCheckBox.setSelected(useV2);
checkAutoScheduleStartAndUpdateStatus();
useVcsAutoSaveScheduleCheckBox.setEnabled(useV2);
}
}, basicDialog);
};
private JPanel createAutoCleanPane() {
JPanel autoCleanPane = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
useVcsAutoCleanScheduleCheckBox = new UICheckBox();
autoCleanIntervalComboBox = new UIComboBox(INTERVAL);
autoCleanIntervalComboBox.setSelectedIndex(DEFAULT_INDEX);
autoCleanRetainIntervalComboBox = new UIComboBox(INTERVAL);
autoCleanRetainIntervalComboBox.setSelectedIndex(DEFAULT_INDEX);
autoCleanPane.add(useVcsAutoCleanScheduleCheckBox);
autoCleanPane.add(new UILabel(i18nText("Fine-Design_Vcs_Auto_Clean_Every")));
autoCleanPane.add(autoCleanIntervalComboBox);
autoCleanPane.add(new UILabel(i18nText("Fine-Design_Vcs_Auto_Clean_Content")));
autoCleanPane.add(autoCleanRetainIntervalComboBox);
autoCleanPane.add(new UILabel(i18nText("Fine-Design_Vcs_Auto_Clean_Last")));
autoCleanPane.setVisible(false);
return autoCleanPane;
}
@Override
protected void done() {
try {
if (Boolean.TRUE.equals(get())) {
// 老版本时才显示gc选项
vcsPane.add(gcControlPane);
vcsPane.updateUI();
private void checkAutoScheduleStartAndUpdateStatus() {
if (!VcsHelper.getInstance().isLegacyMode()) {
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
return WorkContext.getCurrent().get(VcsAutoCleanOperator.class).isSupport();
}
@Override
protected void done() {
try {
boolean useAutoClean = get();
updateAutoCleanEnabled(useAutoClean);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "[Vcs] retrieve legacy mode error: {}", e.getMessage());
}
}
}.execute();
}.execute();
} else {
updateAutoCleanEnabled(false);
}
}
private void updateAutoCleanEnabled(boolean b) {
useVcsAutoCleanScheduleCheckBox.setEnabled(b);
autoCleanIntervalComboBox.setEnabled(b);
autoCleanRetainIntervalComboBox.setEnabled(b);
if (autoCleanPane != null) {
autoCleanPane.setToolTipText(b ? null : Toolkit.i18nText("Fine-Design_Vcs_Server_Start_Hover"));
}
}
private JPanel createSaveIntervalPane() {
JPanel saveIntervalPane = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
useVcsAutoSaveScheduleCheckBox = new UICheckBox();
autoSaveIntervalEditor = new UIPositiveIntEditor(60);
saveIntervalPane.add(useVcsAutoSaveScheduleCheckBox);
saveIntervalPane.add(new UILabel(i18nText("Fine-Design_Vcs_Every")));
saveIntervalPane.add(autoSaveIntervalEditor);
saveIntervalPane.add(new UILabel(i18nText("Fine-Design_Vcs_Save_Delay")));
useVcsAutoSaveScheduleCheckBox.setEnabled(!VcsHelper.getInstance().isLegacyMode());
saveIntervalPane.setVisible(false);
return saveIntervalPane;
}
/**
* 模创建板版本gc 配置操作面板
*
@ -486,7 +642,7 @@ public class PreferencePane extends BasicPane {
private void createEditPane(JPanel generalPane) {
//samuel:编辑器设置
JPanel editPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Editor_Preference"));
JPanel editPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Basic_Editor_Preference"));
generalPane.add(editPane);
//设置是否支持将字符串编辑为公式
@ -496,7 +652,6 @@ public class PreferencePane extends BasicPane {
//是否默认转化
defaultStringToFormulaBox = new UICheckBox(i18nText("Fine-Design_Basic_Always"));
editPane.add(defaultStringToFormulaBox);
//不支持转化则不能默认执行
supportStringToFormulaBox.addActionListener(new ActionListener() {
@Override
@ -508,7 +663,12 @@ public class PreferencePane extends BasicPane {
keyStrokePane.add(new UILabel(i18nText("Fine-Design_Basic_Support_Auto_Complete_Shortcut") + ":"), BorderLayout.WEST);
shortCutLabel = new UILabel();
keyStrokePane.add(shortCutLabel, BorderLayout.CENTER);
editPane.add(keyStrokePane);
keyStrokePane.setBorder(new EmptyBorder(0, 10,0,0));
JPanel defaultExecutePane = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout());
defaultExecutePane.add(defaultStringToFormulaBox);
defaultExecutePane.add(keyStrokePane);
editPane.add(defaultExecutePane);
shortCutLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@ -796,7 +956,8 @@ public class PreferencePane extends BasicPane {
defaultStringToFormulaBox.setSelected(false);
}
VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager();
if (WorkContext.getCurrent().isCluster()) {
//如果是集群并且是老版本则不可用
if (VcsHelper.getInstance().isLegacyMode() && WorkContext.getCurrent().isCluster()) {
vcsEnableCheckBox.setEnabled(false);
gcEnableCheckBox.setEnabled(false);
}
@ -819,6 +980,12 @@ public class PreferencePane extends BasicPane {
gcEnableCheckBox.setSelected(GcConfig.getInstance().isGcEnable());
gcButton.setEnabled(gcEnableCheckBox.isSelected());
useVcsAutoSaveScheduleCheckBox.setSelected(vcsConfigManager.isUseAutoSave());
useVcsAutoCleanScheduleCheckBox.setSelected(VcsConfig.getInstance().isUseV2AutoClean());
autoSaveIntervalEditor.setValue(vcsConfigManager.getAutoSaveInterval());
autoCleanIntervalComboBox.setSelectedIndex(getIndex(VcsConfig.getInstance().getV2CleanInterval()));
autoCleanRetainIntervalComboBox.setSelectedIndex(getIndex(VcsConfig.getInstance().getV2RetainInterval()));
gridLineColorTBButton.setColor(designerEnvManager.getGridLineColor());
paginationLineColorTBButton.setColor(designerEnvManager.getPaginationLineColor());
@ -834,8 +1001,7 @@ public class PreferencePane extends BasicPane {
this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort()));
if (useOptimizedUPMCheckbox != null) {
useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()
|| DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter());
useOptimizedUPMCheckbox.setSelected(checkOptimizedUPMUse());
}
if (useNewVersionLoginCheckbox != null) {
@ -879,6 +1045,15 @@ public class PreferencePane extends BasicPane {
this.startupPageEnabledCheckBox.setSelected(designerEnvManager.isStartupPageEnabled());
}
private boolean checkOptimizedUPMUse() {
//如果是没手动配置过则默认开启
//isUseNewPluginFirst如果为true说明没手动配置过,直接开启
//走到这里说明checkBox不为空,机型肯定符合
return DesignerEnvManager.getEnvManager().isUseNewPluginFirst()
|| ServerPreferenceConfig.getInstance().isUseOptimizedUPM()
|| DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter();
}
private int chooseCase(int sign) {
switch (sign) {
case 0:
@ -898,6 +1073,14 @@ public class PreferencePane extends BasicPane {
}
}
private int getDay(int dateIndex) {
return INDEX_DAY_MAP.getOrDefault(dateIndex, THREE_MONTH_INT);
}
private int getIndex(int day) {
return INDEX_DAY_MAP.inverse().getOrDefault(day, THREE_MONTH_INDEX);
}
/**
* The method of update.
*/
@ -936,13 +1119,30 @@ public class PreferencePane extends BasicPane {
designerEnvManager.setJoinProductImprove(this.joinProductImproveCheckBox.isSelected());
designerEnvManager.setEmbedServerLazyStartup(this.embedServerLazyStartupCheckBox.isSelected());
designerEnvManager.setImageCompress(this.imageCompressPanelCheckBox.isSelected());
designerEnvManager.setUseOptimizedUPM4Adapter(this.useOptimizedUPMCheckbox != null && this.useOptimizedUPMCheckbox.isSelected());
designerEnvManager.setCloudAnalyticsDelay(this.cloudAnalyticsDelayCheckBox.isSelected());
boolean optimizedUPMFlag = this.useOptimizedUPMCheckbox != null && this.useOptimizedUPMCheckbox.isSelected();
designerEnvManager.setUseOptimizedUPM4Adapter(optimizedUPMFlag);
//只有取消掉使用新插件管理器这个选项才需要把useNewPluginFirst置false(意味着用户手动配置了,如果勾选着的话,这个useNewPluginFirst为true就行了)
designerEnvManager.setUseNewPluginFirst(optimizedUPMFlag);
boolean cloudDelayFlag = this.cloudAnalyticsDelayCheckBox.isSelected();
designerEnvManager.setCloudAnalyticsDelay(cloudDelayFlag);
// cloudDelayFlag默认为true,如果用户手动配置过才会是false,则后续的云端运维配置都按照用户意愿来
designerEnvManager.setUseCloudAnalyticsDelayFirst(cloudDelayFlag);
VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager();
vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue());
vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected());
vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected());
vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected());
vcsConfigManager.setUseAutoSave(this.useVcsAutoSaveScheduleCheckBox.isSelected());
vcsConfigManager.setAutoSaveInterval(this.autoSaveIntervalEditor.getValue());
Configurations.update(new WorkerAdaptor(VcsConfig.class) {
@Override
public void run() {
VcsConfig.getInstance().setUseV2AutoClean(useVcsAutoCleanScheduleCheckBox.isSelected());
VcsConfig.getInstance().setV2CleanInterval(getDay(autoCleanIntervalComboBox.getSelectedIndex()));
VcsConfig.getInstance().setV2RetainInterval(getDay(autoCleanRetainIntervalComboBox.getSelectedIndex()));
}
});
dealWithSchedule();
designerEnvManager.setStartupPageEnabled(this.startupPageEnabledCheckBox.isSelected());
Configurations.update(new Worker() {
@Override
@ -1017,6 +1217,36 @@ public class PreferencePane extends BasicPane {
}
private void dealWithSchedule() {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
boolean v2FunctionSupport = VcsHelper.getInstance().checkV2FunctionSupport();
if (v2FunctionSupport) {
//如果支持V2
if (useVcsAutoSaveScheduleCheckBox.isSelected()) {
FineLoggerFactory.getLogger().info("[VcsV2] start auto save!");
VcsHelper.getInstance().startAutoSave(autoSaveIntervalEditor.getValue());
} else {
VcsHelper.getInstance().stopAutoSave();
}
if (useVcsAutoCleanScheduleCheckBox.isEnabled()) {
if (useVcsAutoCleanScheduleCheckBox.isSelected()) {
FineLoggerFactory.getLogger().info("[VcsV2] start auto clean!");
WorkContext.getCurrent().get(VcsAutoCleanOperator.class).addOrUpdateVcsAutoCleanJob(
VcsAutoCleanService.VCS_AUTO_CLEAN_JOB_NAME,
getDay(autoCleanIntervalComboBox.getSelectedIndex()),
VcsAutoCleanSchedule.class);
} else {
WorkContext.getCurrent().get(VcsAutoCleanOperator.class).stopVcsAutoCleanJob(VcsAutoCleanService.VCS_AUTO_CLEAN_JOB_NAME);
}
}
}
return null;
}
}.execute();
}
// 如果语言设置改变了,则显示重启对话框
public void showRestartDialog() {
if (!languageChanged) {
@ -1045,12 +1275,14 @@ public class PreferencePane extends BasicPane {
@Override
public BasicDialog showWindow(Window window) {
return showWindow(window, new DialogActionAdapter() {
basicDialog = showWindow(window, new DialogActionAdapter() {
@Override
public void doOk() {
languageChanged = !ComparatorUtils.equals(languageComboBox.getSelectedItem(), DesignerEnvManager.getEnvManager(false).getLanguage());
}
});
movePanel.setParentDialog(basicDialog);
return basicDialog;
}
@Override

8
designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java

@ -7,6 +7,7 @@ import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.SaveSomeTemplatePane;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.vcs.ui.VcsMovingExitOption;
import com.fr.design.menu.KeySetUtils;
import com.fr.design.menu.MenuDef;
import com.fr.design.menu.SeparatorDef;
@ -60,6 +61,11 @@ public class SwitchExistEnv extends MenuDef {
* @param e 事件
*/
public void actionPerformed(ActionEvent e) {
//检查是否正在迁移,如果正在迁移就弹出弹窗让用户选择
if (!VcsMovingExitOption.ShowDialogAndConfirmSwitch()) {
//如果用户选择取消切换环境则返回,不然说明用户就是想切换,则往下走
return;
}
final String envName = getName();
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
DesignerWorkspaceInfo selectedEnv = envManager.getWorkspaceInfo(envName);
@ -68,7 +74,7 @@ public class SwitchExistEnv extends MenuDef {
EnvChangeEntrance.getInstance().chooseEnv(envName);
} else {
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true);
if (saveSomeTemplatePane.showSavePane()) {
if (saveSomeTemplatePane.showSavePane(true)) {
// 用户模板保存后,才进行切换目录操作
EnvChangeEntrance.getInstance().switch2Env(envName);
}

2
designer-base/src/main/java/com/fr/design/actions/file/export/AbstractExportAction.java

@ -136,7 +136,7 @@ public abstract class AbstractExportAction<E extends JTemplate<?, ?>> extends JT
int returnVal = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Utils_Would_You_Like_To_Save") + " \"" + e.getEditingFILE() + "\" ?",
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE
);

20
designer-base/src/main/java/com/fr/design/actions/help/FineUIAction.java

@ -3,14 +3,15 @@ package com.fr.design.actions.help;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.jxbrowser.JxUIPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.ui.ModernUIPane;
import com.fr.locale.InterProviderFactory;
import com.fr.web.struct.AssembleComponent;
import com.fr.web.struct.Atom;
import com.fr.web.struct.browser.RequestClient;
import com.fr.web.struct.category.ScriptPath;
import com.fr.web.struct.impl.FineUI;
import com.teamdev.jxbrowser.js.JsAccessible;
import java.awt.event.ActionEvent;
@ -27,14 +28,8 @@ public class FineUIAction extends UpdateAction {
@Override
public void actionPerformed(final ActionEvent e) {
ModernUIPane<?> pane = new ModernUIPane.Builder<>()
// .prepare(new ScriptContextAdapter() {
// @Override
// public void onScriptContextCreated(ScriptContextEvent event) {
// JSValue pool = event.getBrowser().executeJavaScriptAndReturnValue("window.Pool");
// pool.asObject().setProperty("i18n", new I18n());
// }
// })
JxUIPane<?> pane = new JxUIPane.Builder<>()
.bindNamespace("i18n", new I18n())
.withComponent(new AssembleComponent() {
@Override
@ -44,20 +39,21 @@ public class FineUIAction extends UpdateAction {
@Override
public Atom[] refer() {
return new Atom[] {FineUI.KEY};
return new Atom[]{FineUI.KEY};
}
})
.build();
BasicDialog dialog = pane.showLargeWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
BasicDialog dialog = pane.showLargeWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
// Do nothing
}
});
dialog.setVisible(true);
dialog.setVisible(true);
}
@JsAccessible
public static class I18n {
public String i18nText(String key) {

20
designer-base/src/main/java/com/fr/design/actions/help/SystemInfoPane.java

@ -41,16 +41,12 @@ public class SystemInfoPane extends JPanel {
for (int i = 0; i < keys.length; i++) {
Object[] tableRowData = new Object[2];
String keyValue = keys[i].toString();
// james:屏蔽掉exe4j的内容
if (keyValue.indexOf("exe4j") != -1) {
continue;
}
// james:这个也是exe4j的东东
if ("install4j.exeDir".equals(keyValue)) {
if (needToShield(keyValue)) {
continue;
}
if(keyValue.indexOf("FineReport") != -1){
if(keyValue.contains("FineReport")){
keys[i] = keyValue.replaceAll("FineReport", ProductConstants.APP_NAME);
}
@ -66,4 +62,14 @@ public class SystemInfoPane extends JPanel {
add(new JScrollPane(table), BorderLayout.CENTER);
}
/**
* 是否属于需要屏蔽的内容(当前屏蔽掉exe4j与jxbrowser的内容)
*
* @param keyValue 对应的key值
* @return 需要屏蔽则返回true
*/
private boolean needToShield(String keyValue) {
return keyValue.contains("exe4j") || keyValue.contains("jxbrowser") || "install4j.exeDir".equals(keyValue);
}
}

14
designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java

@ -1,9 +1,9 @@
package com.fr.design.actions.help;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.design.menu.MenuKeySet;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.general.http.HttpToolbox;
import com.fr.stable.CommonUtils;
@ -18,6 +18,16 @@ import java.awt.event.KeyEvent;
public class TutorialAction extends AbstractDesignerSSO {
/**
* 云中心社区帮助文档在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Help";
/**
* 云中心社区帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Help_Default";
public TutorialAction() {
this.setMenuKeySet(HELP_TUTORIAL);
this.setName(getMenuKeySet().getMenuName());
@ -28,7 +38,7 @@ public class TutorialAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind(createDocKey(), "http://help.finereport.com");
return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
}
// 生成帮助文档 sitecenter key, help.zh_CN.10

25
designer-base/src/main/java/com/fr/design/actions/help/alphafine/RemindPane.java

@ -4,10 +4,21 @@ import com.fr.design.dialog.UIDialog;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.general.IOUtils;
import javax.swing.*;
import java.awt.*;
import com.fr.general.locale.image.I18nImage;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@ -23,8 +34,10 @@ public class RemindPane extends JPanel {
private Icon checkIcon = IOUtils.readIcon("/com/fr/design/mainframe/alphafine/images/check.png");
private Icon unCheckIcon = IOUtils.readIcon("/com/fr/design/mainframe/alphafine/images/uncheck.png");
private Icon closeIcon = IOUtils.readIcon("/com/fr/design/mainframe/alphafine/images/remind_close.png");
private Icon labelIcon = IOUtils.readIcon("/com/fr/design/mainframe/alphafine/images/remind.png");
private Icon openIcon = IOUtils.readIcon("com/fr/design/mainframe/alphafine/images/open.png");
private static final String REMIND_IMAGE_URL = "/com/fr/design/mainframe/alphafine/images/open/open.png";
private Icon labelIcon = new ImageIcon(I18nImage.getImage(REMIND_IMAGE_URL));
private static final String OPEN_IMAGE_URL = "/com/fr/design/mainframe/alphafine/images/open/open.png";
private final Icon openIcon = new ImageIcon(I18nImage.getImage(OPEN_IMAGE_URL));
private static final int WIDTH = 600;
private static final int HEIGHT = 400;

14
designer-base/src/main/java/com/fr/design/components/table/TablePanel.java

@ -161,6 +161,20 @@ public class TablePanel extends JPanel {
}
cellPanel.add(component);
}
/**
* 为单元格Panel更新tooltip
*
* @param row 行数
* @param column 列数
* @param value tooltip值
*/
public void updateCellToolTip(int row, int column, String value) {
int x = row - 1;
int y = column - 1;
JPanel cellPanel = this.cellPanels[x][y];
cellPanel.setToolTipText(value);
}
public void updateCell(int row, int column, String value) {

2
designer-base/src/main/java/com/fr/design/condition/LiteConditionPane.java

@ -224,7 +224,7 @@ public abstract class LiteConditionPane<T extends Condition> extends BasicBeanPa
}
int returnVal = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(LiteConditionPane.this),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"),
JOptionPane.OK_CANCEL_OPTION);
if (returnVal == JOptionPane.OK_OPTION) {
DefaultTreeModel treeModel = (DefaultTreeModel) conditionsTree.getModel();

15
designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java

@ -11,6 +11,11 @@ import com.fr.event.Null;
* @date 2019-06-18
*/
public enum DesignerLaunchStatus implements Event<Null> {
/**
* 界面前置事件初始化完成
*/
UI_PRE_INIT_COMPLETE,
/**
* 初始化环境完成
*/
@ -46,4 +51,14 @@ public enum DesignerLaunchStatus implements Event<Null> {
status = state;
EventDispatcher.fire(DesignerLaunchStatus.getStatus());
}
/**
* 设置状态并异步触发事件
*
* @param state 当前启动状态
*/
public static void setStatusAndAsyncFire(DesignerLaunchStatus state) {
status = state;
EventDispatcher.asyncFire(DesignerLaunchStatus.getStatus());
}
}

20
designer-base/src/main/java/com/fr/design/constants/UIConstants.java

@ -153,10 +153,10 @@ public interface UIConstants {
public static final BufferedImage DRAG_BAR = IOUtils.readImage("com/fr/design/images/control/bar.png");
public static final BufferedImage DRAG_BAR_LIGHT = IOUtils.readImage("com/fr/design/images/control/bar-light.png");
public static final BufferedImage ARROW_NORTH = IOUtils.readImage("com/fr/design/images/control/up_arrow.png");
public static final BufferedImage ARROW_SOUTH = IOUtils.readImage("com/fr/design/images/control/down_arrow.png");
public static final BufferedImage ARROW_EAST = IOUtils.readImage("com/fr/design/images/control/east_arrow.png");
public static final BufferedImage ARROW_WEST = IOUtils.readImage("com/fr/design/images/control/west_arrow.png");
public static final Image ARROW_NORTH = SVGLoader.load("/com/fr/design/standard/arrowlinear/up_arrow.svg");
public static final Image ARROW_SOUTH = SVGLoader.load("/com/fr/design/standard/arrowlinear/down_arrow.svg");
public static final Image ARROW_EAST = SVGLoader.load("/com/fr/design/standard/arrowlinear/east_arrow.svg");
public static final Image ARROW_WEST = SVGLoader.load("/com/fr/design/standard/arrowlinear/west_arrow.svg");
public static final BufferedImage DRAG_BAR_RIGHT = IOUtils.readImage("com/fr/design/images/control/barm.png");
public static final BufferedImage DRAG_BAR_LEFT = IOUtils.readImage("com/fr/design/images/control/barl.png");
@ -172,24 +172,24 @@ public interface UIConstants {
public static final Image DRAG_LINE = SVGLoader.load("/com/fr/design/standard/dot_line_normal.svg");
public static final BufferedImage ACCESSIBLE_EDITOR_DOT = IOUtils.readImage("com/fr/design/images/control/dot.png");
public static final BufferedImage DRAG_DOT_VERTICAL = IOUtils.readImage("com/fr/design/images/control/dotv.png");
public static final BufferedImage POP_BUTTON_DOWN = IOUtils.readImage("com/fr/design/images/buttonicon/popdownarrow.png");
public static final BufferedImage POP_BUTTON_UP = IOUtils.readImage("com/fr/design/images/buttonicon/popuparrow.png");
public static final Image POP_BUTTON_DOWN = SVGLoader.load("/com/fr/design/standard/poparrow/pop_down_arrow.svg");
public static final Image POP_BUTTON_UP = SVGLoader.load("/com/fr/design/standard/poparrow/pop_up_arrow.svg");
public static final BufferedImage DRAG_DOWN_SELECTED_SMALL = IOUtils.readImage("com/fr/design/images/buttonicon/downSelected.png");
public static final BufferedImage DRAG_LEFT_NORMAL_SMALL = IOUtils.readImage("com/fr/design/images/buttonicon/leftNormal.png");
public static final BufferedImage WATERMARK_BACKGROUND = IOUtils.readImage("/com/fr/design/images/dialog/watermark/" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_WaterMark_Background_Icon_File_Name"));
public static final int MODEL_NORMAL = 0;
public static final int MODEL_PRESS = 1;
public static final Icon ARROW_DOWN_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/arrowdown.png");
public static final Icon ARROW_DOWN_ICON = IconUtils.readIcon("/com/fr/design/standard/arrowlinear/down_arrow.svg");
public static final Icon ARROW_UP_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/arrowup.png");
public static final Icon YES_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/yes.png");
public static final Icon CHOOSEN_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/select_item.png");
public static final Icon PRE_WIDGET_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/prewidget.png");
public static final Icon PRE_WIDGET_NORMAL_ICON = IconUtils.readIcon("com/fr/design/images/buttonicon/prewidget");
public static final Icon EDIT_NORMAL_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/edit");
public static final Icon EDIT_PRESSED_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/edit");
public static final Icon EDIT_PRESSED_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/edit_pressed.svg");
public static final Icon HIDE_NORMAL_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/hide");
public static final Icon HIDE_PRESSED_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/hide");
public static final Icon HIDE_PRESSED_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/hide_pressed.svg");
public static final Icon VIEW_NORMAL_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/view");
//public static final Icon VIEW_PRESSED_ICON = IconUtils.readIcon("/com/fr/design/standard/uimode/view");
@ -221,7 +221,7 @@ public interface UIConstants {
public static final int BUTTON_GROUP_ARC = 0;
public static final int LARGEARC = 6;
public static final Stroke BS = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 2f, new float[]{3, 1}, 0);
public static final Icon PREVIEW_DOWN = IOUtils.readIcon("com/fr/design/images/buttonicon/prevew_down_icon.png");
public static final Icon PREVIEW_DOWN = IconUtils.readIcon("/com/fr/design/standard/preview_down_icon");
public static final Icon CLOSE_OF_AUTHORITY = IOUtils.readIcon("/com/fr/design/images/m_report/close.png");
public static final Icon CLOSE_OVER_AUTHORITY = IOUtils.readIcon("/com/fr/design/images/m_report/close_over.png");
public static final Icon CLOSE_PRESS_AUTHORITY = IOUtils.readIcon("/com/fr/design/images/m_report/close_press.png");

46
designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java

@ -5,14 +5,17 @@ import com.fr.base.TableData;
import com.fr.base.svg.IconUtils;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.impl.DBTableData;
import com.fr.design.DesignModelAdapter;
import com.fr.design.actions.UpdateAction;
import com.fr.design.data.datapane.TableDataCreatorProducer;
import com.fr.design.data.datapane.TableDataNameObjectCreator;
import com.fr.design.data.datapane.TableDataSourceOP;
import com.fr.design.data.datapane.TableDataTree;
import com.fr.design.data.datapane.auth.TableDataAuthHelper;
import com.fr.design.data.tabledata.ResponseDataSourceChange;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane;
import com.fr.design.data.tabledata.wrapper.MultiResultTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
@ -42,6 +45,8 @@ import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.TreeCellEditor;
@ -51,6 +56,7 @@ import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Collection;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
@ -449,7 +455,45 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
storeProcedureDataWrapper.previewData(MultiResultTableDataWrapper.PREVIEW_ALL);
}
} else {
((TableDataWrapper) data).previewData();
TableDataWrapper wrapper = ((TableDataWrapper) data);
if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) {
// 先打开一个Loading面板
TableDataLoadingPane loadingPane = new TableDataLoadingPane();
BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(BasicTableDataTreePane.this), null);
// 查询权限
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
// 获取无权限连接名称集合
Collection<String> noAuthConnections = TableDataAuthHelper.getNoAuthConnections();
// 获取当前数据集对应的数据连接名称
String connectionName = TableDataAuthHelper.getConnectionNameByDBTableData((DBTableData) wrapper.getTableData());
return !noAuthConnections.contains(connectionName);
}
@Override
protected void done() {
try {
Boolean hasAuth = get();
if (hasAuth) {
// 有权限时,关闭Loading面板,打开编辑面板
loadingDialog.setVisible(false);
wrapper.previewData();
} else {
// 无权限时,给出无权限提示
loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage());
// 查询权限失败时,给出报错提示
loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME);
}
}
}.execute();
loadingDialog.setVisible(true);
} else {
wrapper.previewData();
}
}
} catch (Exception ex) {

9
designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java

@ -33,6 +33,7 @@ import com.fr.file.ProcedureConfig;
import com.fr.general.ComparatorUtils;
import com.fr.general.data.DataModel;
import com.fr.general.data.TableDataException;
import com.fr.general.sql.sqlnote.SqlNoteConstants;
import com.fr.log.FineLoggerFactory;
import com.fr.script.Calculator;
import com.fr.stable.ArrayUtils;
@ -573,6 +574,7 @@ public abstract class DesignTableDataManager {
parameter.setValue(parameterMap.get(parameter.getName()));
}
}
addTemplateInfoIfNeed(parameterMap);
PreviewSourceBean bean = new PreviewSourceBean();
TableDataSource source = TableDataSourceTailor.extractTableData(tableDataSource);
bean.setDataSource(source);
@ -605,6 +607,12 @@ public abstract class DesignTableDataManager {
}
}
private static void addTemplateInfoIfNeed(Map<String, Object> parameterMap) {
if (JTemplate.isValid(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate())) {
parameterMap.put(SqlNoteConstants.SQL_NOTE_TEMPLATE, HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath());
}
}
private static boolean checkBean(PreviewSourceBean bean) {
// dataName为空说明是新建的,得用tabledata传
return !bean.getDataName().isEmpty();
@ -687,6 +695,7 @@ public abstract class DesignTableDataManager {
if (needLoadingBar) {
MultiResultTableDataWrapper.loadingBar.start();
}
addTemplateInfoIfNeed(parameterMap);
return DataOperator.getInstance().previewMultiResultTableData(tableData, parameterMap, 0);
}

93
designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java

@ -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 查找出相比origother中有哪些是新增的删除的或者被修改的并分别进行处理
*
* 对比时默认用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 查找出相比origother中有哪些是新增的删除的或者被修改的并分别进行处理
*
* 对比时用自定义的规则来判断是否为 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;
}
}

1
designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java

@ -357,7 +357,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
*/
@Override
public void refresh() {
DBUtils.refreshDatabase();
String schema = StringUtils.isEmpty(schemaBox.getSelectedItem()) ? null : schemaBox.getSelectedItem();
DataCoreUtils.refreshTables(getConnection(), TableProcedure.TABLE, schema);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh_Successfully") + "!", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh_Database"),

16
designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java

@ -6,6 +6,7 @@ import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.esd.common.CacheConstants;
@ -30,8 +31,8 @@ import java.net.URI;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Date;
import java.util.List;
/**
* @author rinoux
@ -39,7 +40,18 @@ import java.util.Date;
* Created by rinoux on 2020/7/22
*/
public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html";
/**
* 云中心定时调度执行频率表达式设定帮助文档链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Cron_Help";
/**
* 云中心定时调度执行频率表达式设定帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Cron_Help_Default";
private static final String CRON_HELP_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
private UIRadioButton selectAutoUpdate;
private UIRadioButton selectBySchema;
private UICheckBox shouldEvolve;

31
designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java

@ -233,17 +233,7 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
@Override
public void update(Map<String, TableData> tableDataMap) {
Nameable[] tableDataArray = this.update();
List<TableDataBean> tableDataBeans = new ArrayList<>();
Map<String, String> map = MapUtils.invertMap(getDsNameChangedMap());
for (int i = 0; i < tableDataArray.length; i++) {
NameObject nameObject = (NameObject) tableDataArray[i];
String oldName = map.get(nameObject.getName());
if (oldName == null) {
oldName = StringUtils.EMPTY;
}
tableDataBeans.add(new TableDataBean(nameObject.getName(), oldName, (TableData) nameObject.getObject()));
}
List<TableDataBean> tableDataBeans = getUpdateTableDataBeans();
try {
WorkContext.getCurrent().get(TableDataOperator.class, new ExceptionHandler() {
@Override
@ -257,6 +247,25 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
}
}
/**
* 获取更新时的数据集快照
*
* @return 快照
*/
private List<TableDataBean> getUpdateTableDataBeans() {
Nameable[] tableDataArray = this.update();
List<TableDataBean> tableDataBeans = new ArrayList<>();
Map<String, String> map = MapUtils.invertMap(getDsNameChangedMap());
for (int i = 0; i < tableDataArray.length; i++) {
NameObject nameObject = (NameObject) tableDataArray[i];
String oldName = map.get(nameObject.getName());
if (oldName == null) {
oldName = StringUtils.EMPTY;
}
tableDataBeans.add(new TableDataBean(nameObject.getName(), oldName, (TableData) nameObject.getObject()));
}
return tableDataBeans;
}
private boolean saveByOldWay(List<TableDataBean> tableDataBean) {
try {
return TableDataOperatorImpl.getInstance().saveTableData(tableDataBean);

2
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -229,7 +229,7 @@ public class TableDataTreePane extends BasicTableDataTreePane {
private TreeSearchToolbarPane initToolBarPane() {
// toolbar
addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add"));
addMenuDef.setIconPath("/com/fr/design/standard/addpopup/addPopup");
addMenuDef.setDisabledIcon("/com/fr/design/standard/addpopup/addPopup", true);
createAddMenuDef();
// 创建插件监听
createPluginListener();

3
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java

@ -21,6 +21,7 @@ import com.fr.general.GeneralContext;
import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
import javax.swing.event.DocumentEvent;
@ -109,6 +110,8 @@ public class ConnectionTableProcedurePane extends BasicPane {
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel());
model.removeElement(EMPTY);
}
@Override

59
designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java

@ -1,6 +1,7 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.GraphHelper;
import com.fr.data.core.db.dialect.DialectFactory;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.pool.DBCPConnectionPoolAttr;
import com.fr.design.dialog.BasicDialog;
@ -31,6 +32,7 @@ import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -43,7 +45,7 @@ public class DBCPAttrPane extends BasicPane {
private static final int ORACLE_DEFAULT_FETCHSIZE = 128;
private static final int DB2_DEFAULT_FETCHSIZE = 50;
private static final int POSTGRE_DEFAULT_FETCHSIZE = 10000;
private static final int EMPTY_FETCHSIZE = -2;
private static final int INVALID_FETCHSIZE = -1;
// carl:DBCP的一些属性
private IntegerEditor DBCP_INITIAL_SIZE = new IntegerEditor();
private IntegerEditor DBCP_MIN_IDLE = new IntegerEditor();
@ -114,12 +116,25 @@ public class DBCPAttrPane extends BasicPane {
this.DBCP_MINEVICTABLEIDLETIMEMILLIS.setValue(dbcpAttr.getMinEvictableIdleTimeMillis() / TIME_MULTIPLE);
this.DBCP_NUMTESTSPEREVICTIONRUN.setValue(dbcpAttr.getNumTestsPerEvictionRun());
this.DBCP_TIMEBETWEENEVICTIONRUNSMILLS.setValue(dbcpAttr.getTimeBetweenEvictionRunsMillis());
Integer fetchSize = DEFAULT_FETCHSIZE_MAP.get(JDBCConnectionDef.getInstance().getDatabaseName());
if (fetchSize != null) {
if (jdbcDatabase.getFetchSize() == EMPTY_FETCHSIZE) {
this.FETCHSIZE.setText(StringUtils.EMPTY);
/*
* 填充FetchSize输入框逻辑
*
* 1. 如果JDBCDatabaseConnection里的fetchSize是有效值>0则显示该有效值
* 2. 如果JDBCDatabaseConnection里的fetchSize是无效值<=0
* 2.1 如果我们对这种数据库有默认值如oracledb2pgsql就显示对应数据库的默认值因为要避免性能问题这几种数据库不支持关闭fetchSize
* 2.2 如果我们对这种数据库无默认值就显示-1
*/
int fetchSize = jdbcDatabase.getFetchSize();
String databaseName = JDBCConnectionDef.getInstance().getDatabaseName();
if (DialectFactory.isValidFetchSize(fetchSize)) {
this.FETCHSIZE.setText(String.valueOf(fetchSize));
} else {
if (DEFAULT_FETCHSIZE_MAP.containsKey(databaseName)) {
this.FETCHSIZE.setText(String.valueOf(DEFAULT_FETCHSIZE_MAP.get(databaseName)));
} else {
this.FETCHSIZE.setText(jdbcDatabase.getFetchSize() == -1 ? String.valueOf(fetchSize) : String.valueOf(jdbcDatabase.getFetchSize()));
this.FETCHSIZE.setText(String.valueOf(INVALID_FETCHSIZE));
}
}
}
@ -137,12 +152,34 @@ public class DBCPAttrPane extends BasicPane {
dbcpAttr.setMinEvictableIdleTimeMillis(((Number) this.DBCP_MINEVICTABLEIDLETIMEMILLIS.getValue()).intValue() * TIME_MULTIPLE);
dbcpAttr.setNumTestsPerEvictionRun(((Number) this.DBCP_NUMTESTSPEREVICTIONRUN.getValue()).intValue());
dbcpAttr.setTimeBetweenEvictionRunsMillis(((Number) this.DBCP_TIMEBETWEENEVICTIONRUNSMILLS.getValue()).intValue());
Integer fetchSize = DEFAULT_FETCHSIZE_MAP.get(JDBCConnectionDef.getInstance().getDatabaseName());
if (fetchSize != null) {
if (StringUtils.isEmpty(this.FETCHSIZE.getText())) {
jdbcDatabase.setFetchSize(EMPTY_FETCHSIZE);
/*
* FetchSize设置逻辑
*
* 1. 如果客户界面上的fetchSize框留空
* 1.1 如果我们对这种数据库有默认值如oracledb2pgsql就存对应数据库的默认值否则会有性能问题这几种数据库我们是不支持关闭fetchSize的
* 1.2 如果我们对这种数据库没有默认值就置为-1
* 2. 如果客户界面上的fetchSize框非空
* 2.1 如果fetchSize是个有效值>0就使用该值
* 2.2 如果fetchSize是个无效值<=0)就置为-1
*
* -1带来的结果就是我们Dialect不会putExecutor最终不会执行java.sql.Statement.setFetchSize
*/
String fetchSizeText = this.FETCHSIZE.getText();
String databaseName = JDBCConnectionDef.getInstance().getDatabaseName();
if (StringUtils.isEmpty(fetchSizeText)) {
if (DEFAULT_FETCHSIZE_MAP.containsKey(databaseName)) {
Optional.ofNullable(DEFAULT_FETCHSIZE_MAP.get(databaseName)).ifPresent(jdbcDatabase::setFetchSize);
} else {
jdbcDatabase.setFetchSize(INVALID_FETCHSIZE);
}
} else {
int fetchSizeSet = Integer.parseInt(fetchSizeText);
if (DialectFactory.isValidFetchSize(fetchSizeSet)) {
jdbcDatabase.setFetchSize(fetchSizeSet);
} else {
jdbcDatabase.setFetchSize(Integer.parseInt(this.FETCHSIZE.getText()));
jdbcDatabase.setFetchSize(INVALID_FETCHSIZE);
}
}
}

7
designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java

@ -446,6 +446,7 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
dealWithException(e);
}
}
@ -573,7 +574,7 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
} else {
path = driverPath;
}
if(JarFileParseUtil.hasDuplicateDriver(con.getDriver(), path)) {
if(hasDuplicateDriver(con.getDriver(), path)) {
testResult.setForeground(Color.RED);
testResult.setText(Toolkit.i18nText("Fine_Designer_Driver_Conflict"));
} else {
@ -589,7 +590,9 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
return xBorderPanel;
}
private boolean hasDuplicateDriver(String driver, String folder) {
return JarFileParseUtil.hasDuplicateDriver(driver, folder);
}
}
}

7
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/DesensitizationOpenPane.java

@ -8,10 +8,12 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.locale.impl.DataMaskMark;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.log.FineLoggerFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@ -58,7 +60,8 @@ public class DesensitizationOpenPane extends JPanel {
@Override
public void mouseClicked(MouseEvent event) {
try {
URL url = new URL(Toolkit.i18nText("Fine-Design_Report_Desensitization_Help_Document_Url"));
LocaleMark<String> dataMaskMark = LocaleCenter.getMark(DataMaskMark.class);
URL url = new URL(dataMaskMark.getValue());
Desktop.getDesktop().browse(url.toURI());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "open browse of table data desensitization help document failed for {}", e.getMessage());

14
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleChoosePane.java

@ -18,9 +18,13 @@ import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.CardLayout;
@ -132,6 +136,16 @@ public class DesensitizationRuleChoosePane extends JPanel {
this.setDefaultRenderer(DesensitizationRuleStatusPane.class, new DesensitizationRuleStatusPane());
this.createTable().getColumnModel().getColumn(0).setMaxWidth(20);
this.createTable().getColumnModel().getColumn(3).setMaxWidth(60);
this.createTable().getColumnModel().getColumn(3).setHeaderRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel headerLabel = new JLabel(value != null ? value.toString() : "");
headerLabel.setToolTipText((String) value);
headerLabel.setHorizontalAlignment(SwingConstants.CENTER);
headerLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 3, 0, new Color(216, 216, 216, 175)));
return headerLabel;
}
});
}
@Override

35
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/rule/DesensitizationRuleEditPane.java

@ -1,5 +1,7 @@
package com.fr.design.data.datapane.preview.desensitization.view.rule;
import com.fine.swing.ui.layout.Column;
import com.fine.swing.ui.layout.Layouts;
import com.fr.data.desensitize.rule.base.DesensitizationCondition;
import com.fr.data.desensitize.rule.base.DesensitizationRule;
import com.fr.data.desensitize.rule.base.DesensitizationRuleSource;
@ -28,6 +30,10 @@ import java.awt.event.FocusListener;
import java.util.Arrays;
import java.util.Set;
import static com.fine.swing.ui.layout.Layouts.cell;
import static com.fine.swing.ui.layout.Layouts.column;
import static com.fine.swing.ui.layout.Layouts.row;
/**
* 脱敏规则编辑页
*
@ -157,26 +163,29 @@ public class DesensitizationRuleEditPane extends BasicBeanPane<DesensitizationRu
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
cardLayout = new CardLayout();
ruleConditionPane = new JPanel(cardLayout);
// 字符替换
JPanel characterReplacePane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
UILabel retainFrontLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_One") + StringUtils.BLANK);
retainFrontTextField = new UINumberField(5);
retainFrontTextField.addFocusListener(retainFrontListener);
UILabel retainBackLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Two") + StringUtils.BLANK);
retainBackTextField = new UINumberField(5);
retainBackTextField.addFocusListener(retainBackListener);
UILabel replaceLabel = new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Three") + StringUtils.BLANK);
firstSymbolTextField = new UITextField(10);
firstSymbolTextField.addFocusListener(firstSymbolListener);
characterReplacePane.add(retainFrontLabel);
characterReplacePane.add(retainFrontTextField);
characterReplacePane.add(retainBackLabel);
characterReplacePane.add(retainBackTextField);
characterReplacePane.add(replaceLabel);
characterReplacePane.add(firstSymbolTextField);
// 字符替换
Layouts.Cell<Column> column = column(
4,
row(
cell(new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_One") + StringUtils.BLANK)),
cell(retainFrontTextField),
cell(new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Two") + StringUtils.BLANK)),
cell(retainBackTextField),
cell(new UILabel(StringUtils.BLANK + Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Four") + StringUtils.BLANK))
),
row(
cell(new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_Part_Three") + StringUtils.BLANK)),
cell(firstSymbolTextField)
)
);
// 整体替换
JPanel characterAllReplacePane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
UILabel allReplaceLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_Desensitization_All_Character_Replace_By") + StringUtils.BLANK);
@ -186,7 +195,7 @@ public class DesensitizationRuleEditPane extends BasicBeanPane<DesensitizationRu
characterAllReplacePane.add(allReplaceLabel);
characterAllReplacePane.add(secondSymbolTextField);
ruleConditionPane.add(characterReplacePane, DesensitizationRuleType.CHARACTER_REPLACE.getRuleTypeName());
ruleConditionPane.add(column.getComponent(), DesensitizationRuleType.CHARACTER_REPLACE.getRuleTypeName());
ruleConditionPane.add(characterAllReplacePane, DesensitizationRuleType.ALL_CHARACTERS_REPLACE.getRuleTypeName());
// 初始化状态为字符替换
switchRuleConditionPane(DesensitizationRuleType.CHARACTER_REPLACE);

16
designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java

@ -11,12 +11,12 @@ import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.link.MessageWithLink;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.parameter.ParameterInputPane;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.log.FineLoggerFactory;
import com.fr.platform.scaffold.provider.config.PreventSqlInjConfigProvider;
@ -64,6 +64,16 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener {
private UILabel imageLabel;
/**
* 云中心防止sql注入帮助文档链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design_Basic_Sql_Injection_Prevention_Help";
/**
* 云中心防止sql注入帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Basic_Sql_Injection_Prevention_Help_Default";
public PreviewPerformedSqlPane(Frame frame, String sql) {
this(frame, sql, null, null, false);
}
@ -85,7 +95,7 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener {
JLabel label = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Preview_Performed_Sql_Message") + Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention") + Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message"));
messagePanel.add(label);
} else {
MessageWithLink message = new MessageWithLink(Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Front_Message"), Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention"), CloudCenter.getInstance().acquireConf(Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention_Help"), "https://help.fanruan.com/finereport/doc-view-2219.html"), Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message"));
MessageWithLink message = new MessageWithLink(Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Front_Message"), Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention"), LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT), Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message"));
messagePanel.add(message);
}
// 提示图标
@ -243,7 +253,7 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener {
private static Parameter[] processParameters(DBTableData tableData, Calculator calculator) {
ParameterProvider[] parameters = tableData.getParameters();
if (parameters == null || parameters.length == 0) {
tableData.setParameters(ParameterHelper.analyze4Parameters(tableData.getQuery(), false));
tableData.setParameters(ParameterHelper.analyze4Parameters(tableData.getQueryWithoutComments(), false));
return new Parameter[0];
}
return Parameter.providers2Parameter(Calculator.processParameters(calculator, parameters));

14
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java

@ -61,6 +61,7 @@ import com.fr.stable.ArrayUtils;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.Box;
@ -416,10 +417,7 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implemen
}
private void checkParameter() {
String[] paramTexts = new String[2];
paramTexts[0] = this.sqlTextPane.getText();
paramTexts[1] = this.pageQuery;
Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false);
Parameter[] parameters = getParameters();
if (parameters.length < 1 && this.editorPane.update().size() < 1) {
return;
@ -443,6 +441,14 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implemen
refreshParameters();
}
@NotNull
private Parameter[] getParameters() {
String[] paramTexts = new String[2];
paramTexts[0] = SqlUtils.clearSqlComments(this.sqlTextPane.getText());
paramTexts[1] = SqlUtils.clearSqlComments(this.pageQuery);
return ParameterHelper.analyze4Parameters(paramTexts, false);
}
@Override
public void populateBean(DBTableData dbTableData) {
this.dbTableData = dbTableData;

1
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java

@ -294,6 +294,7 @@ public class MultiTDTableDataPane extends AbstractTableDataPane<MultiTDTableData
tmp = tmp + "...";
tabledataName = new UILabel(tmp);
}
tabledataName.setToolTipText(name);
UILabel iconLabel = new UILabel(icon);
chekbox.addActionListener(tableDataCheckboxListener);
iconLabel.addMouseListener(chooseTableDataListener);

3
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java

@ -60,7 +60,8 @@ public class ProcedureDataPane extends AbstractTableDataPane<StoreProcedure> imp
"com.microsoft.sqlserver.jdbc.SQLServerDriver",
"com.ibm.db2.jcc.DB2Driver",
"com.mysql.jdbc.Driver",
"org.gjt.mm.mysql.Driver"
"org.gjt.mm.mysql.Driver",
"dm.jdbc.driver.DmDriver"
}; // 需要隐藏面板的数据库的驱动
private static final String PREVIEW_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview");
private ConnectionTableProcedurePane connectionTableProcedurePane;

19
designer-base/src/main/java/com/fr/design/dcm/UniversalDatabasePane.java

@ -1,12 +1,9 @@
package com.fr.design.dcm;
import com.fr.design.dialog.BasicPane;
import com.fr.design.ui.ModernUIPane;
import com.teamdev.jxbrowser.chromium.JSValue;
import com.teamdev.jxbrowser.chromium.events.ScriptContextAdapter;
import com.teamdev.jxbrowser.chromium.events.ScriptContextEvent;
import com.fr.design.jxbrowser.JxUIPane;
import java.awt.*;
import java.awt.BorderLayout;
/**
* @author richie
@ -15,8 +12,6 @@ import java.awt.*;
*/
public class UniversalDatabasePane extends BasicPane {
private ModernUIPane<Object> modernUIPane;
@Override
protected String title4PopupWindow() {
return "Database";
@ -24,15 +19,9 @@ public class UniversalDatabasePane extends BasicPane {
public UniversalDatabasePane() {
setLayout(new BorderLayout());
modernUIPane = new ModernUIPane.Builder<>()
JxUIPane<Object> modernUIPane = new JxUIPane.Builder<>()
.withComponent(UniversalDatabaseComponent.KEY)
.prepare(new ScriptContextAdapter() {
@Override
public void onScriptContextCreated(ScriptContextEvent event) {
JSValue window = event.getBrowser().executeJavaScriptAndReturnValue("window");
window.asObject().setProperty("DcmHelper", UniversalDcmBridge.getBridge(event.getBrowser()));
}
})
.bindWindow("DcmHelper", UniversalDcmBridge::getBridge)
.build();
add(modernUIPane, BorderLayout.CENTER);
}

22
designer-base/src/main/java/com/fr/design/dcm/UniversalDcmBridge.java

@ -2,8 +2,8 @@ package com.fr.design.dcm;
import com.fr.decision.webservice.bean.BaseBean;
import com.fr.design.bridge.exec.JSBridge;
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.JSObject;
import com.teamdev.jxbrowser.js.JsAccessible;
import com.teamdev.jxbrowser.js.JsObject;
/**
* @author richie
@ -11,20 +11,28 @@ import com.teamdev.jxbrowser.chromium.JSObject;
* Created by richie on 2019-05-17
* 桥接Java和JavaScript的类
*/
@JsAccessible
public class UniversalDcmBridge {
public static UniversalDcmBridge getBridge(Browser browser) {
return new UniversalDcmBridge(browser);
/**
* 获取 js-java bridge
*
* @param window 全局环境
* @return bridge
*/
public static UniversalDcmBridge getBridge(JsObject window) {
return new UniversalDcmBridge(window);
}
private JSObject window;
private JsObject window;
private UniversalDcmBridge(Browser browser) {
this.window = browser.executeJavaScriptAndReturnValue("window").asObject();
private UniversalDcmBridge(JsObject window) {
this.window = window;
}
/**
* 获取所有的数据连接
*
* @return 数据连接集合
*/
@JSBridge

16
designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java

@ -167,6 +167,22 @@ public class DeepLinkCore {
markPendingURLConsumed();
}
/**
* 符合条件的url才处理
*
* @param url 接收到的url
* @return true:处理; false:不处理
*/
public boolean accept(String url) {
UrlBean urlBean = UrlBean.create(url);
for (DeepLink deepLink: deepLinkList) {
if (deepLink.accept(urlBean.getUrl(), urlBean.getHost(), urlBean.getPath(), urlBean.getParams())) {
return true;
}
}
return false;
}
private void performDeepLinks(String url, String host, String path, Map<String, Object> params) {
SwingUtilities.invokeLater(new Runnable() {
@Override

20
designer-base/src/main/java/com/fr/design/dialog/BasicPane.java

@ -75,6 +75,26 @@ public abstract class BasicPane extends JPanel {
return dg;
}
/**
* 显示小窗口并允许自定义需不需要按钮
*
* @param window 窗口
* @param isNeedButtonsPane 是否需要确定删除按钮
* @return 对话框
*/
public BasicDialog showSmallWindow(Window window, boolean isNeedButtonsPane) {
BasicDialog dg;
if (window instanceof Frame) {
dg = new DIALOG((Frame) window, isNeedButtonsPane);
} else {
dg = new DIALOG((Dialog) window, isNeedButtonsPane);
}
dg.setBasicDialogSize(BasicDialog.SMALL);
GUICoreUtils.centerWindow(dg);
dg.setResizable(false);
return dg;
}
/**
* 图表类型选择时 弹出的按钮大小, 不适合用最大最小, 因为图表大小 默认是规定好的, 那么界面大小也是必须配合.

2
designer-base/src/main/java/com/fr/design/dialog/FineJOptionPane.java

@ -39,7 +39,7 @@ public class FineJOptionPane extends JOptionPane {
}
private final static String MESSAGE_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Message");
private final static String CONFIRM_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm");
private final static String CONFIRM_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt");
private final static String INPUT_DIALOG_TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips");
/**

2
designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java

@ -34,7 +34,7 @@ public abstract class EditLockChangeChecker {
*/
public void start() {
this.scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("EditLockChangeChecker"));
this.scheduler.scheduleAtFixedRate(new Runnable() {
this.scheduler.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// 判断是否为远程设计环境

2
designer-base/src/main/java/com/fr/design/editor/DoubleDeckValueEditorPane.java

@ -304,7 +304,7 @@ public class DoubleDeckValueEditorPane extends BasicPane implements UIObserver,
if (designerEnvManager.isSupportStringToFormula()) {
if (!designerEnvManager.isDefaultStringToFormula()) {
int returnValue = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Edit_String_To_Formula")
+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_OPTION);
+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.YES_NO_OPTION);
if (returnValue == JOptionPane.OK_OPTION) {
setCurrentEditor(j);

2
designer-base/src/main/java/com/fr/design/editor/ValueEditorPane.java

@ -285,7 +285,7 @@ public class ValueEditorPane extends BasicPane implements UIObserver, GlobalName
if (designerEnvManager.isSupportStringToFormula()) {
if (!designerEnvManager.isDefaultStringToFormula()) {
int returnValue = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Edit_String_To_Formula")
+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_OPTION);
+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.YES_NO_OPTION);
if (returnValue == JOptionPane.OK_OPTION) {
setCurrentEditor(j);

10
designer-base/src/main/java/com/fr/design/editor/editor/NumberEditor.java

@ -38,7 +38,7 @@ public abstract class NumberEditor<T extends Number> extends Editor<T> {
*/
public NumberEditor(T value, String name) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
numberField = new UINumberField();
numberField = createNumberField();
this.add(numberField, BorderLayout.CENTER);
this.numberField.addKeyListener(textKeyListener);
this.numberField.setHorizontalAlignment(UITextField.RIGHT);
@ -46,6 +46,14 @@ public abstract class NumberEditor<T extends Number> extends Editor<T> {
this.setName(name);
}
/**
* 创建NumberField对象
*
*/
protected UINumberField createNumberField() {
return new UINumberField();
}
/**
* 给numberField加键盘事件
*

10
designer-base/src/main/java/com/fr/design/env/RemoteDesignerWorkspaceInfo.java vendored

@ -6,6 +6,7 @@ import com.fr.log.FineLoggerFactory;
import com.fr.security.SecurityToolbox;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.mark.Immutable;
import com.fr.stable.project.ProjectConstants;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
@ -166,6 +167,15 @@ public class RemoteDesignerWorkspaceInfo implements DesignerWorkspaceInfo {
return object;
}
/**
* clone一个自定义连接信息的RemoteDesignerWorkspaceInfo
*/
public Object cloneWithConnectionInfo(WorkspaceConnectionInfo workspaceConnectionInfo) throws CloneNotSupportedException {
RemoteDesignerWorkspaceInfo object = (RemoteDesignerWorkspaceInfo) super.clone();
object.connection = workspaceConnectionInfo;
return object;
}
@Override
public boolean checkValid() throws Exception {

24
designer-base/src/main/java/com/fr/design/env/processor/AbstractRemoteDesignerWorkspaceInfoProcessor.java vendored

@ -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;
}
}

25
designer-base/src/main/java/com/fr/design/env/processor/RemoteDesignerWorkspaceInfoProcessor.java vendored

@ -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);
}

184
designer-base/src/main/java/com/fr/design/extra/PluginBatchModifyDetailPane.java

@ -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);
}
}

110
designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java

@ -3,6 +3,8 @@ package com.fr.design.extra;
import com.fr.design.DesignerEnvManager;
import com.fr.design.bridge.exec.JSCallback;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.extra.exe.callback.BatchModifyStatusCallback;
import com.fr.design.extra.exe.callback.BatchUpdateOnlineCallback;
import com.fr.design.extra.exe.callback.InstallFromDiskCallback;
import com.fr.design.extra.exe.callback.InstallOnlineCallback;
import com.fr.design.extra.exe.callback.ModifyStatusCallback;
@ -28,11 +30,13 @@ import com.fr.plugin.view.PluginView;
import com.fr.plugin.xml.PluginElementName;
import com.fr.plugin.xml.PluginXmlElement;
import com.fr.stable.StringUtils;
import com.teamdev.jxbrowser.chromium.JSArray;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import java.io.File;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
@ -65,12 +69,14 @@ public class PluginOperateUtils {
public static void updatePluginOnline(List<PluginMarker> pluginMarkerList, JSCallback jsCallback) {
for (int i = 0; i < pluginMarkerList.size(); i++) {
updatePluginOnline(pluginMarkerList.get(i), jsCallback);
int size = pluginMarkerList.size();
BatchUpdateOnlineCallback batchUpdateOnlineCallback = size <= 1 ? BatchUpdateOnlineCallback.NONE : new BatchUpdateOnlineCallback(jsCallback, size);
for (int i = 0; i < size; i++) {
updatePluginOnline(pluginMarkerList.get(i), jsCallback, batchUpdateOnlineCallback);
}
}
public static void updatePluginOnline(PluginMarker pluginMarker, JSCallback jsCallback) {
private static void updatePluginOnline(PluginMarker pluginMarker, JSCallback jsCallback, BatchUpdateOnlineCallback batchUpdateOnlineCallback) {
try {
JSONObject latestPluginInfo = PluginUtils.getLatestPluginInfo(pluginMarker.getPluginID());
String latestPluginVersion = latestPluginInfo.getString("version");
@ -79,11 +85,25 @@ public class PluginOperateUtils {
//当前已经安装的相同ID插件marker
PluginMarker currentMarker = PluginMarkerAdapter.create(PluginUtils.getInstalledPluginMarkerByID(pluginMarker.getPluginID()), pluginName);
PluginTask pluginTask = PluginTask.updateTask(currentMarker, toPluginMarker);
PluginControllerHelper.updateOnline(currentMarker, toPluginMarker, new UpdateOnlineCallback(pluginTask, jsCallback), PluginExtraInfo.newBuilder().username(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()).build());
if (!batchUpdateOnlineCallback.equals(BatchUpdateOnlineCallback.NONE)) {
batchUpdateOnlineCallback.createInnerPreTaskCallback(pluginTask, jsCallback);
PluginControllerHelper.updateOnline(currentMarker, toPluginMarker, batchUpdateOnlineCallback.getInnerPreTaskCallback(), PluginExtraInfo.newBuilder().username(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()).build());
} else {
PluginControllerHelper.updateOnline(currentMarker, toPluginMarker, new UpdateOnlineCallback(pluginTask, jsCallback), PluginExtraInfo.newBuilder().username(DesignerEnvManager.getEnvManager().getDesignerLoginUsername()).build());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
/**
* 更新插件
*
* @param pluginMarker 插件marker
* @param jsCallback 回调
*/
public static void updatePluginOnline(PluginMarker pluginMarker, JSCallback jsCallback) {
updatePluginOnline(pluginMarker, jsCallback, BatchUpdateOnlineCallback.NONE);
}
@ -92,6 +112,40 @@ public class PluginOperateUtils {
}
private static void dealWithPluginActive(PluginMarker pluginMarker, BatchModifyStatusCallback modifyStatusCallback) {
PluginContext plugin = PluginManager.getContext(pluginMarker);
boolean running = plugin.isRunning();
modifyStatusCallback.updateActiveStatus(running);
changePluginActive(running, pluginMarker, modifyStatusCallback, plugin);
}
private static void changePluginActive(boolean isRunning, PluginMarker pluginMarker, PluginTaskCallback modifyStatusCallback, PluginContext plugin) {
if (isRunning) {
PluginXmlElement forbidReminder = plugin.getXml().getElement(PluginElementName.ForbidReminder);
if (forbidReminder != null && forbidReminder.getContent() != null) {
// 禁用前提示
int rv = FineJOptionPane.showConfirmDialog(
null,
forbidReminder.getContent(),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE
);
if (rv == JOptionPane.OK_OPTION) {
PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback);
}
} else {
// 正常禁用
PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback);
}
} else {
PluginManager.getController().enablePersistently(pluginMarker, modifyStatusCallback);
}
}
public static void setPluginActive(String pluginInfo, JSCallback jsCallback) {
SwingUtilities.invokeLater(new Runnable() {
@ -99,28 +153,29 @@ public class PluginOperateUtils {
public void run() {
PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo);
PluginContext plugin = PluginManager.getContext(pluginMarker);
boolean isRunning = plugin.isRunning();
PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(isRunning, jsCallback);
if (isRunning) {
PluginXmlElement forbidReminder = plugin.getXml().getElement(PluginElementName.ForbidReminder);
if (forbidReminder != null && forbidReminder.getContent() != null) {
// 禁用前提示
int rv = FineJOptionPane.showConfirmDialog(
null,
forbidReminder.getContent(),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE
);
if (rv == JOptionPane.OK_OPTION) {
PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback);
}
} else {
// 正常禁用
PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback);
}
} else {
PluginManager.getController().enablePersistently(pluginMarker, modifyStatusCallback);
boolean running = plugin.isRunning() || plugin.isPrepare();
PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(running, jsCallback);
changePluginActive(running, pluginMarker, modifyStatusCallback, plugin);
}
});
}
/**
* 批量启用或禁用插件
*
* @param pluginIDs 要处理的插件信息
* @param jsCallback 回调函数
*/
public static void setPluginActive(List<String> pluginIDs, JSCallback jsCallback) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
int len = pluginIDs.size();
BatchModifyStatusCallback modifyStatusCallback = new BatchModifyStatusCallback(jsCallback, len);
for (String pluginInfo : pluginIDs) {
PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo);
dealWithPluginActive(pluginMarker, modifyStatusCallback);
}
}
});
@ -255,8 +310,7 @@ public class PluginOperateUtils {
private static String getPluginName(PluginContext pluginContext, PluginMarker pluginMarker) {
if (pluginContext != null) {
return pluginContext.getName();
}
else if (pluginMarker instanceof PluginMarkerAdapter) {
} else if (pluginMarker instanceof PluginMarkerAdapter) {
return ((PluginMarkerAdapter) pluginMarker).getPluginName();
}
return pluginMarker == null ? StringUtils.EMPTY : pluginMarker.getPluginID();

4
designer-base/src/main/java/com/fr/design/extra/PluginUtils.java

@ -270,8 +270,8 @@ public class PluginUtils {
jo.put("vendor", pluginContext.getVendor());
jo.put("price", pluginContext.getPrice());
jo.put("requiredJarTime", pluginContext.getRequiredJarTime());
// 前端需求的active实际上是插件的运行状态,通过isRunning()获取
jo.put("active", pluginContext.isRunning());
// 前端需求的active实际上是插件的运行状态,通过isRunning()或isPrepare()获取
jo.put("active", pluginContext.isRunning() || pluginContext.isPrepare());
jo.put("hidden", pluginContext.isHidden());
jo.put("free", pluginContext.isFree());
jo.put("licDamaged", pluginContext.isLicDamaged());

127
designer-base/src/main/java/com/fr/design/extra/exe/callback/AbstractBatchModifyStatusCallback.java

@ -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);
}

43
designer-base/src/main/java/com/fr/design/extra/exe/callback/BatchModifyStatusCallback.java

@ -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");
}
}
}

77
designer-base/src/main/java/com/fr/design/extra/exe/callback/BatchUpdateOnlineCallback.java

@ -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);
}
}
}

15
designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java

@ -2,6 +2,7 @@ package com.fr.design.extra.exe.callback.handle;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.dialog.link.MessageWithLink;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.plugin.error.PluginErrorCode;
import com.fr.plugin.manage.control.PluginTaskResult;
@ -16,7 +17,19 @@ public class PluginCallBackHelper {
private static final String REFERENCE = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_Reference");
private static final String HELP_DOCUMENT_NAME = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_NAME");
private static final String CONNECTOR = "-";
private static final String HELP_DOCUMENT_LINK = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK");
/**
* 云中心第三方插件安装失败说明帮助文档在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK";
/**
* 云中心第三方插件安装失败说明帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK_Default";
private static final String HELP_DOCUMENT_LINK = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
/**

24
designer-base/src/main/java/com/fr/design/file/DefaultTemplateTreeDefineProcessor.java

@ -28,7 +28,6 @@ import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
@ -221,6 +220,7 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
/**
* 检测是否能够黏贴
*
* @param treeNodeList
* @return
*/
@ -271,7 +271,7 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
}
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e,"Template paste failed.", e.getMessage());
FineLoggerFactory.getLogger().error(e, "Template paste failed.", e.getMessage());
FineJOptionPane.showConfirmDialog(null,
Toolkit.i18nText("Fine-Design_Basic_Paste_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
@ -286,7 +286,7 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
/**
* 确认粘贴的目标目录是否是复制文件的子目录并确认是否继续执行粘贴任务
*
* @param targetDir 目标文件夹
* @param targetDir 目标文件夹
* @param pasteNodes 待粘贴的文件
* @return 是否继续
*/
@ -433,6 +433,14 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
WARNING_MESSAGE);
return false;
}
// 检查移动的源文件夹是否为目标文件夹相同文件夹或子文件夹
if (FileOperationHelper.getInstance().isSubDirectoryOrSame(getFileTree().getSelectedTreeNodes(), getTargetFileNode())) {
FineJOptionPane.showMessageDialog(this,
Toolkit.i18nText("Fine-Design_Basic_Move_To_SubDirectory"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
WARNING_MESSAGE);
return false;
}
if (TemplateUtils.checkSelectedTemplateIsEditing()) {
return FineJOptionPane.showConfirmDialog(this,
Toolkit.i18nText("Fine-Design_Basic_Template_Is_Editing"),
@ -443,9 +451,7 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
}
private boolean doMove() {
FileNode fileNode = getDirTree().getSelectedFileNode();
ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) getDirTree().getModel().getRoot();
fileNode = fileNode == null ? (FileNode) rootTreeNode.getUserObject() : fileNode;
FileNode fileNode = getTargetFileNode();
boolean moveSuccess = true;
try {
//待移动的文件可以有多个
@ -465,6 +471,12 @@ public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefi
return moveSuccess;
}
private FileNode getTargetFileNode() {
FileNode fileNode = getDirTree().getSelectedFileNode();
ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) getDirTree().getModel().getRoot();
return fileNode == null ? (FileNode) rootTreeNode.getUserObject() : fileNode;
}
@Override
public void dispose() {
TemplateDirTreeSearchManager.getInstance().outOfSearchMode();

46
designer-base/src/main/java/com/fr/design/file/FileOperationHelper.java

@ -16,7 +16,10 @@ import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import com.fr.workspace.resource.ResourceIOException;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
@ -32,6 +35,38 @@ public class FileOperationHelper {
return INSTANCE;
}
/**
* 检查目标文件夹是否为多个源文件夹中的任一文件夹或者任一文件夹的子文件夹
*
* @param fileNodes 需移动的源文件
* @param targetNode 移动后的目标文件夹
* @return
*/
public boolean isSubDirectoryOrSame(@NotNull ExpandMutableTreeNode[] fileNodes, @NotNull FileNode targetNode) {
for (ExpandMutableTreeNode treeNode : fileNodes) {
FileNode sourceFileNode = (FileNode) treeNode.getUserObject();
if (isSubDirectoryOrSame(sourceFileNode, targetNode)) {
return true;
}
}
return false;
}
/**
* 检查目标文件夹是否为源文件夹或源文件夹的子文件夹
*
* @param sourceFileNode 需移动的源文件
* @param targetNode 移动后的目标文件夹
*/
public boolean isSubDirectoryOrSame(@NotNull FileNode sourceFileNode, @NotNull FileNode targetNode) {
if (!sourceFileNode.isDirectory() || !targetNode.isDirectory()) {
return false;
}
Path sourceDir = Paths.get(sourceFileNode.getEnvPath()).normalize();
Path targetDir = Paths.get(targetNode.getEnvPath()).normalize();
return targetDir.startsWith(sourceDir);
}
public String moveFile(FileNode sourceFileNode, String targetDir) {
String targetPath = copyFileAndVcs(sourceFileNode, targetDir);
FileNodeFILE nodeFILE = new FileNodeFILE(sourceFileNode);
@ -51,8 +86,9 @@ public class FileOperationHelper {
/**
* 拷贝文件的同时拷贝对应的版本控制文件
*
* @param sourceFile 源文件或目录
* @param targetDir 目标目录
* @param targetDir 目标目录
* @return 复制后的目标文件的路径
*/
public String copyFileAndVcs(FileNode sourceFile, String targetDir) {
@ -61,8 +97,9 @@ public class FileOperationHelper {
/**
* 只拷贝文件, 不拷贝对应的版本控制文件
*
* @param sourceFile 源文件或目录
* @param targetDir 目标目录
* @param targetDir 目标目录
* @return 复制后的目标文件的路径
*/
public String copyFile(FileNode sourceFile, String targetDir) {
@ -71,7 +108,8 @@ public class FileOperationHelper {
/**
* 检测节点是否被锁住了
* @param node 待检测节点
*
* @param node 待检测节点
* @param dNodes 没有锁住的节点集合
* @param lNodes 锁住的节点集合
* @return 是否存在被锁住的文件
@ -165,7 +203,7 @@ public class FileOperationHelper {
} else {
if (!TemplateResourceManager.getResource().copy(sourcePath, targetPath)) {
throw new ResourceIOException(String.format("copy file failed, from %s to %s", sourcePath, targetPath));
} else if (withCopyVcs){
} else if (withCopyVcs) {
sourcePath = sourcePath.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY);
targetPath = targetPath.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY);
VcsHelper.getInstance().moveVcs(sourcePath, targetPath);

7
designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java

@ -268,7 +268,8 @@ public class HistoryTemplateListCache implements CallbackEvent {
boolean replaceWithJVirtualTemplate = overTemplate.getEditingFILE().exists()
&& overTemplate.isALLSaved()
&& overTemplate != editingTemplate
&& overTemplate.checkEnable();
&& overTemplate.checkEnable()
&& overTemplate.supportCache();
if (replaceWithJVirtualTemplate) {
closeVirtualSelectedReport(overTemplate);
historyList.set(i, new JVirtualTemplate(overTemplate.getEditingFILE()));
@ -297,7 +298,9 @@ public class HistoryTemplateListCache implements CallbackEvent {
int index = iterator.nextIndex();
if (size == index + 1 && index > 0) {
//如果删除的是后一个Tab,则定位到前一个
MultiTemplateTabPane.getInstance().setSelectedIndex(index - 1);
MultiTemplateTabPane.getInstance().setSelectedIndex(
MultiTemplateTabPane.getInstance().calNextShowJTemplateIndex(index - 1));
}
}
}

349
designer-base/src/main/java/com/fr/design/file/MultiTemplateTabMenuFactory.java

@ -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);
}
}
}

300
designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java

@ -1,7 +1,6 @@
package com.fr.design.file;
import com.fr.base.BaseUtils;
import com.fr.base.GraphHelper;
import com.fr.base.svg.IconUtils;
import com.fr.base.vcs.DesignerMode;
@ -19,7 +18,6 @@ import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.TemplateSavingChecker;
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.TemplateUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.gui.GUIPaintUtils;
import com.fr.design.worker.WorkerManager;
@ -42,11 +40,11 @@ import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.MenuElement;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.plaf.basic.BasicMenuItemUI;
import java.awt.AWTEvent;
import java.awt.AlphaComposite;
@ -70,6 +68,8 @@ import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
@ -213,6 +213,35 @@ public class MultiTemplateTabPane extends JComponent {
});
}
/**
* 模板可以关闭的条件
*/
class CloseCondition {
private CloseOption closeOption;
public CloseCondition(CloseOption closeOption) {
this.closeOption = closeOption;
}
/**
* 判断模板是否可以关闭两个条件1是否满足CloseOption里面的条件在左侧在右侧等2是否和当前正在编辑模板属于同一种模板tab操作类型
* @param closeJTemplate
* @param tplIndex
* @param i
* @return
*/
public boolean shouldClose(JTemplate closeJTemplate, int tplIndex, int i) {
boolean matchOption = this.closeOption.shouldClose(tplIndex, i);
JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (!JTemplate.isValid(currentTemplate)) {
return matchOption;
}
return matchOption && ComparatorUtils.equals(closeJTemplate.getTemplateTabOperatorType(),
currentTemplate.getTemplateTabOperatorType());
}
}
enum CloseOption {
Left(Toolkit.i18nText("Fine-Design_Close_templates_To_The_Left")) {
@Override
@ -323,29 +352,34 @@ public class MultiTemplateTabPane extends JComponent {
@Override
public void actionPerformed(ActionEvent e) {
SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false);
if (saveSomeTempaltePane.showSavePane()) {
//只有关闭所有模板才需要判断当前模板,关闭左侧、右侧、其他都不需要
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(option == CloseOption.All);
CloseCondition closeCondition = new CloseCondition(option);
if (saveSomeTemplatePane.showSavePane(closeCondition, false)) {
JTemplate<?, ?>[] templates = new JTemplate<?, ?>[openedTemplate.size()];
for (int i = 0; i < openedTemplate.size(); i++) {
templates[i] = openedTemplate.get(i);
}
JTemplate<?, ?> currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
closeTemplate(templates, currentTemplate);
closeTemplate(closeCondition, templates, currentTemplate);
if (option == CloseOption.All) {
if (openedTemplate.size() == 0) {
DesignerContext.getDesignerFrame().addAndActivateJTemplate();
} else if (option == CloseOption.All){
//openedTemplate(0)是JVirtualTemplate时需重新打开
openedTemplate.get(0).activeOldJTemplate();
} else {
DesignerContext.getDesignerFrame().activateJTemplate(currentTemplate);
currentTemplate.activeOldJTemplate();
}
MultiTemplateTabPane.getInstance().repaint();
}
}
private void closeTemplate(JTemplate<?, ?>[] templates, JTemplate<?, ?> currentTemplate) {
private void closeTemplate(CloseCondition closeCondition, JTemplate<?, ?>[] templates, JTemplate<?, ?> currentTemplate) {
for (int i = 0; i < templates.length; i++) {
if (option.shouldClose(tplIndex, i)) {
if (closeCondition.shouldClose(templates[i], tplIndex, i)) {
JTemplate<?, ?> jTemplate = templates[i];
if (jTemplate == currentTemplate) {
currentTemplate = option == CloseOption.All ? null : templates[tplIndex];
@ -378,6 +412,46 @@ public class MultiTemplateTabPane extends JComponent {
return openedTemplate.get(selectedIndex);
}
/**
* 关闭所有指定模板tab操作类型的模板
* @param operatorType
*/
public void closeOtherByOperatorType(String operatorType){
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false);
if (saveSomeTempaltePane.showSavePane(null, false, true)) {
List<JTemplate<?, ?>> openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList();
JTemplate<?, ?>[] templates = new JTemplate<?, ?>[openedTemplate.size()];
for (int i = 0; i < openedTemplate.size(); i++) {
templates[i] = openedTemplate.get(i);
}
closeTemplate(templates, currentEditingTemplate, operatorType);
DesignerContext.getDesignerFrame().activateJTemplate(currentEditingTemplate);
MultiTemplateTabPane.getInstance().repaint();
}
}
/**
* 关闭指定的非当前编辑模板
* @param templates
* @param operatorType
*/
private static void closeTemplate(JTemplate<?, ?>[] templates, JTemplate<?, ?> currentEditingTemplate, String operatorType) {
for (int i = 0; i < templates.length; i++) {
JTemplate<?, ?> jTemplate = templates[i];
boolean needClose = ComparatorUtils.equals(operatorType, jTemplate.getTemplateTabOperatorType())
&& jTemplate != currentEditingTemplate;
if (!needClose) {
continue;
}
MultiTemplateTabPane.getInstance().closeFormat(jTemplate);
HistoryTemplateListCache.getInstance().closeSelectedReport(jTemplate);
MultiTemplateTabPane.getInstance().closeAndFreeLock(jTemplate);
}
}
/**
* 关闭掉当前已打开文件列表中指定的文件
@ -478,11 +552,7 @@ public class MultiTemplateTabPane extends JComponent {
private String tempalteShowName(JTemplate<?, ?> template) {
String name = TemplateUtils.createLockeTemplatedName(template, template.getTemplateName());
if (!template.isSaved() && !name.endsWith(" *")) {
name += " *";
}
return name;
return template.getTabShowName(template);
}
/**
@ -500,40 +570,7 @@ public class MultiTemplateTabPane extends JComponent {
private void showListDown() {
UIScrollPopUpMenu menu = new UIScrollPopUpMenu();
menu.setBorder(BorderFactory.createEmptyBorder(-3, 3, 3, 0));
menu.add(initCloseOther());
JSeparator separator = new JSeparator() {
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = 1;
return d;
}
};
menu.add(new JPanel() {
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = 1;
return d;
}
});
separator.setForeground(UIConstants.LINE_COLOR);
menu.add(separator);
menu.add(new JPanel() {
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = 1;
return d;
}
});
UIMenuItem[] items = createListDownTemplate();
for (int i = 0; i < items.length; i++) {
menu.add(items[i]);
}
UIScrollPopUpMenu menu = MultiTemplateTabMenuFactory.getInstance().createMenu();
GUICoreUtils.showPopupMenu(menu, MultiTemplateTabPane.getInstance(), MultiTemplateTabPane.getInstance().getWidth() - menu.getPreferredSize().width, getY() - 1 + getHeight());
}
@ -583,6 +620,9 @@ public class MultiTemplateTabPane extends JComponent {
//从可以开始展示在tab面板上的tab开始画
for (int i = minPaintIndex; i <= maxPaintIndex; i++) {
JTemplate template = openedTemplate.get(i);
if (!showJTemplateTab(template)){
continue;
}
Icon icon = template.getIcon();
String name = tempalteShowName(template);
//如果tab名字的长度大于最大能显示的英文字符长度,则进行省略号处理
@ -717,13 +757,67 @@ public class MultiTemplateTabPane extends JComponent {
minPaintIndex = 0;
maxPaintIndex = openedTemplate.size() - 1;
}
//需要根据每个tab的宽度重新check下实际的maxPaintIndex和minPaintIndex
checkActualPaintIndex();
}
/**
* 先计算出需要补充的tab个数
* @return
*/
private int calTabCountComplemented(){
int a = 0;
for (int i = minPaintIndex; i <= maxPaintIndex; i++) {
JTemplate template = openedTemplate.get(i);
if (!showJTemplateTab(template)) {
a++;
}
}
return a;
}
/**
* 由于可能存在宽度为0的tab所以这边需要重新check下先往后补再往前补
*/
private void checkActualPaintIndex(){
int tabCount = calTabCountComplemented();
if (tabCount == 0){
return;
}
if (maxPaintIndex < openedTemplate.size() - 1) {
for (int i = maxPaintIndex + 1; i < openedTemplate.size(); i++) {
JTemplate template = openedTemplate.get(i);
if (showJTemplateTab(template)) {
tabCount--;
}
maxPaintIndex++;
if (tabCount == 0){
return;
}
}
}
if (minPaintIndex > 0){
for (int i = minPaintIndex - 1; i >= 0; i--) {
JTemplate template = openedTemplate.get(i);
if (showJTemplateTab(template)) {
tabCount--;
}
minPaintIndex--;
if (tabCount == 0){
return;
}
}
}
}
//个数小于最多能容纳的个数的情况下,看看宽度每个要画多少
private void calculateRealAverageWidth(double maxwidth, int templateNum) {
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
List<JTemplate<?, ?>> showTemplates = getOpenedJTemplatesByOperator(jTemplate.getTemplateTabOperatorType());
int num = openedTemplate.size() > templateNum ? templateNum : openedTemplate.size();
int num = Math.min(showTemplates.size(), templateNum);
realWidth = (int) (maxwidth / (num));
if (realWidth > MAXWIDTH) {
realWidth = MAXWIDTH;
@ -906,7 +1000,7 @@ public class MultiTemplateTabPane extends JComponent {
if (!specifiedTemplate.isALLSaved() && !DesignerMode.isVcsMode()) {
specifiedTemplate.stopEditing();
int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Would_You_Like_To_Save") + " \"" + specifiedTemplate.getEditingFILE() + "\" ?",
Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (returnVal == JOptionPane.YES_OPTION) {
CallbackSaveWorker worker = specifiedTemplate.save();
worker.addSuccessCallback(new Runnable() {
@ -932,7 +1026,7 @@ public class MultiTemplateTabPane extends JComponent {
activePrevTemplateAfterClose();
}
private void closeAndFreeLock(@Nonnull JTemplate<?, ?> template) {
public void closeAndFreeLock(@Nonnull JTemplate<?, ?> template) {
FILE file = template.getEditingFILE();
// 只有是环境内的文件,才执行释放锁
if (file != null && file.isEnvFile()) {
@ -986,9 +1080,12 @@ public class MultiTemplateTabPane extends JComponent {
// selectIndex 没有变化,但是对应的模板已经变成了前一张模板
if (closeIconIndex == selectedIndex || isCloseCurrent) {
// 如果当前关闭的模板在最右侧,那么预览上一个,防止数组越界
// 关闭的模板是当前选中的模板时,需要重新计算下一个待展示的模板的index
if (selectedIndex >= maxPaintIndex) {
// selectIndex 不会 <0 因为如果关闭的是打开的最后一个模板,那么关闭之后 openedTemplate.isEmpty() = true
selectedIndex--;
selectedIndex = calNextShowJTemplateIndex(selectedIndex - 1);
} else {
selectedIndex = calNextShowJTemplateIndex(selectedIndex);
}
isCloseCurrent = false;
}
@ -1005,6 +1102,16 @@ public class MultiTemplateTabPane extends JComponent {
}
}
/**
* 计算下一个可以展示的模板index
* @param currentIndex
* @return
*/
public int calNextShowJTemplateIndex(int currentIndex) {
JTemplate jTemplate= HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
return MultiTemplateTabUtils.calShowTemplateIndex(currentIndex, openedTemplate, jTemplate.getTemplateTabOperatorType());
}
private boolean isOverCloseIcon(int evtX) {
boolean isOverCloseIcon = false;
@ -1027,7 +1134,7 @@ public class MultiTemplateTabPane extends JComponent {
private int getTemplateIndex(int evtX) {
int textX = 0;
for (int i = minPaintIndex; i <= maxPaintIndex; i++) {
int textWidth = realWidth;
int textWidth = showJTemplateTab(openedTemplate.get(i)) ? realWidth : 0;
if (evtX >= textX && evtX < textX + textWidth) {
return i;
}
@ -1089,6 +1196,7 @@ public class MultiTemplateTabPane extends JComponent {
private class MultiTemplateTabMouseListener implements MouseListener {
private boolean oldLightWeightPopupEnabled;
/**
* 鼠标进入
@ -1097,7 +1205,8 @@ public class MultiTemplateTabPane extends JComponent {
*/
@Override
public void mouseEntered(MouseEvent e) {
// do nothing
this.oldLightWeightPopupEnabled = ToolTipManager.sharedInstance().isLightWeightPopupEnabled();
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
}
/**
@ -1107,6 +1216,9 @@ public class MultiTemplateTabPane extends JComponent {
*/
@Override
public void mouseExited(MouseEvent e) {
ToolTipManager.sharedInstance().setEnabled(false);
ToolTipManager.sharedInstance().setEnabled(true);
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(this.oldLightWeightPopupEnabled);
listDownMode = LIST_DOWN;
closeIconIndex = -1;
mouseOveredIndex = -1;
@ -1184,29 +1296,44 @@ public class MultiTemplateTabPane extends JComponent {
//没有点击关闭和ListDown按钮,则切换到点击的模板处
closeIconIndex = -1;
clodeMode = CLOSE;
int tempSelectedIndex = selectedIndex;
if (selectedIndex != getTemplateIndex(evtX) && getTemplateIndex(evtX) != -1) {
openedTemplate.get(selectedIndex).stopEditing();
selectedIndex = getTemplateIndex(evtX);
//如果在权限编辑情况下,不允许切换到表单类型的工作簿
if (DesignerMode.isAuthorityEditing() && !openedTemplate.get(selectedIndex).isJWorkBook()) {
DesignerContext.getDesignerFrame().addAndActivateJTemplate(openedTemplate.get(tempSelectedIndex));
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Form_Authority_Edited_Cannot_Be_Supported")
+ "!", Toolkit.i18nText("Fine-Design_Basic_Alert"), JOptionPane.WARNING_MESSAGE);
MultiTemplateTabPane.this.repaint();
return;
}
JTemplate evtXTemplate = openedTemplate.get(getTemplateIndex(evtX));
evtXTemplate.activeNewJTemplate();
}
switchJTemplate(getTemplateIndex(evtX));
isShowList = false;
}
MultiTemplateTabPane.this.repaint();
}
}
/**
* 切换到指定模板
* @param jTemplate
*/
public void switchJTemplate(JTemplate jTemplate) {
int switchIndex = this.openedTemplate.indexOf(jTemplate);
if (switchIndex >= 0) {
switchJTemplate(switchIndex);
}
}
/**
* 切换到指定index
* @param switchIndex
*/
private void switchJTemplate(int switchIndex){
int tempSelectedIndex = selectedIndex;
if (selectedIndex != switchIndex && switchIndex != -1) {
openedTemplate.get(selectedIndex).stopEditing();
selectedIndex = switchIndex;
//如果在权限编辑情况下,不允许切换到表单类型的工作簿
if (DesignerMode.isAuthorityEditing() && !openedTemplate.get(selectedIndex).isJWorkBook()) {
DesignerContext.getDesignerFrame().addAndActivateJTemplate(openedTemplate.get(tempSelectedIndex));
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Form_Authority_Edited_Cannot_Be_Supported")
+ "!", Toolkit.i18nText("Fine-Design_Basic_Alert"), JOptionPane.WARNING_MESSAGE);
MultiTemplateTabPane.this.repaint();
return;
}
JTemplate evtXTemplate = openedTemplate.get(switchIndex);
evtXTemplate.activeNewJTemplate();
}
}
private boolean checkCurrentClose(JTemplate template) {
@ -1251,5 +1378,34 @@ public class MultiTemplateTabPane extends JComponent {
}
}
/**
* 判断是否显示在tab栏上
* @param jTemplate
* @return
*/
private boolean showJTemplateTab(JTemplate jTemplate){
JTemplate current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
return ComparatorUtils.equals(current.getTemplateTabOperatorType(), jTemplate.getTemplateTabOperatorType());
}
/**
* 获取tab操作类型的模板
* @param operator
* @return
*/
public List<JTemplate<?, ?>> getOpenedJTemplatesByOperator(String operator) {
return openedTemplate.stream().filter((jTemplate) -> ComparatorUtils.equals(jTemplate.getTemplateTabOperatorType(), operator))
.collect(Collectors.toList());
}
/**
* 根据tab操作类型进行分类
* @return
*/
public Map<String, List<JTemplate<?, ?>>> getOpenedJTemplatesByCategory() {
return openedTemplate.stream()
.collect(Collectors.groupingBy(JTemplate::getTemplateTabOperatorType));
}
}

59
designer-base/src/main/java/com/fr/design/file/MultiTemplateTabUtils.java

@ -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());
}
}

10
designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java

@ -81,11 +81,19 @@ public abstract class NewTemplatePane extends JComponent implements MouseListene
}
if (isOverNewIcon(evtX) && newWorkBookIconMode != GRAY_NEW_CPT) {
newWorkBookIconMode = getMousePressNew();
DesignerContext.getDesignerFrame().addAndActivateJTemplate();
createNewTemplate();
}
this.repaint();
}
/**
* 新建模板
*/
protected void createNewTemplate() {
DesignerContext.getDesignerFrame().addAndActivateJTemplate();
}
/**
*鼠标松开
* @param e 事件

75
designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java

@ -17,6 +17,7 @@ import com.fr.design.mainframe.JTemplate;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@ -47,6 +48,7 @@ public class SaveSomeTemplatePane extends BasicPane {
/**
* 支持自定义设置 dialog的父窗口
*
* @param isNeedTojudgeCurrent
* @param parent
*/
@ -79,11 +81,14 @@ public class SaveSomeTemplatePane extends BasicPane {
this.isJudgeCurrentEditingTemplate = isNeedTojudgeCurrent;
}
private void initTemplatesChoosePane() {
private void initTemplatesChoosePane(boolean judgeJTemplateMustSave) {
templatesChoosePane.setBorder(BorderFactory.createTitledBorder(""));
for (int i = 0; i < unSavedTemplate.size(); i++) {
templateCheckBoxes[i] = new UICheckBox(unSavedTemplate.get(i).getEditingFILE().getName());
templateCheckBoxes[i].setSelected(true);
boolean needSave = judgeJTemplateMustSave && unSavedTemplate.get(i).needSaveBeforeSwitchEnv();
templateCheckBoxes[i].setEnabled(!needSave);
}
final UIList templatesList = new UIList(templateCheckBoxes);
@ -103,7 +108,10 @@ public class SaveSomeTemplatePane extends BasicPane {
boolean isSelected = chooseAllCheckBox.isSelected();
for (int i = 0; i < templatesList.getModel().getSize(); i++) {
UICheckBox checkBox = (UICheckBox) templatesList.getModel().getElementAt(i);
checkBox.setSelected(isSelected);
boolean mustSaveBeforeSwitchEnv = judgeJTemplateMustSave && unSavedTemplate.get(i).needSaveBeforeSwitchEnv();
checkBox.setSelected(mustSaveBeforeSwitchEnv || isSelected);
templateCheckBoxes[i].setEnabled(!mustSaveBeforeSwitchEnv);
}
templatesList.repaint();
}
@ -116,8 +124,10 @@ public class SaveSomeTemplatePane extends BasicPane {
if (index < 0) {
return;
}
boolean mustSaveBeforeSwitchEnv = judgeJTemplateMustSave
&& unSavedTemplate.get(index).needSaveBeforeSwitchEnv();
UICheckBox checkBox = (UICheckBox) templatesList.getModel().getElementAt(index);
checkBox.setSelected(!checkBox.isSelected());
checkBox.setSelected(mustSaveBeforeSwitchEnv ||!checkBox.isSelected());
//根据templateCheckBoxes中的选择情况来更新全选框的状态
int selectedCount = calculateSelectedNum();
@ -139,7 +149,7 @@ public class SaveSomeTemplatePane extends BasicPane {
/**
* 获取templateCheckBoxes中状态为选中状态的CheckBox数量
* */
*/
private int calculateSelectedNum() {
int count = 0;
for (UICheckBox checkBox : templateCheckBoxes) {
@ -152,7 +162,40 @@ public class SaveSomeTemplatePane extends BasicPane {
public boolean showSavePane() {
populate();
return showSavePane(false);
}
/**
* 显示保存模板提醒面板
*
* @param judgeJTemplateMustSave 模板是否必须保存
* @return
*/
public boolean showSavePane(boolean judgeJTemplateMustSave) {
return showSavePane(null, judgeJTemplateMustSave);
}
/**
* 显示保存模板提醒面板
*
* @param option 具体关闭操作
* @param judgeJTemplateMustSave 模板是否必须保存
* @return
*/
public boolean showSavePane(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave) {
return showSavePane(option, judgeJTemplateMustSave, false);
}
/**
* 显示保存模板提醒面板
*
* @param option 具体关闭操作
* @param judgeJTemplateMustSave 模板是否必须保存
* @param judgeSameTabType 是否只包含当前编辑的模板类型
* @return
*/
public boolean showSavePane(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave, boolean judgeSameTabType) {
initAndPopulate(option, judgeJTemplateMustSave, judgeSameTabType);
//如果有未保存的文件 ,则跳出保存对话框,选择要存储的项目
if (!unSavedTemplate.isEmpty()) {
dialog.setVisible(true);
@ -162,19 +205,29 @@ public class SaveSomeTemplatePane extends BasicPane {
return isAllSaved;
}
public void populate() {
java.util.List<JTemplate<?, ?>> opendedTemplate = HistoryTemplateListPane.getInstance().getHistoryList();
protected java.util.List<JTemplate<?, ?>> getOpenedTemplatesToProcess(){
return HistoryTemplateListPane.getInstance().getHistoryList();
}
private void initAndPopulate(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave, boolean judgeSameTabType) {
java.util.List<JTemplate<?, ?>> opendedTemplate = getOpenedTemplatesToProcess();
JTemplate<?, ?> currentTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
int currentIndex = opendedTemplate.indexOf(currentTemplate);
for (int i = 0; i < opendedTemplate.size(); i++) {
if (isneedToAdd(opendedTemplate.get(i), currentTemplate)) {
//满足关闭条件的才继续判断文件是否发生了改动
boolean needClose = option == null || option.shouldClose(opendedTemplate.get(i), currentIndex, i);
if (judgeSameTabType) {
needClose &= ComparatorUtils.equals(opendedTemplate.get(i).getTemplateTabOperatorType(), currentTemplate.getTemplateTabOperatorType());
}
if (needClose && isneedToAdd(opendedTemplate.get(i), currentTemplate)) {
unSavedTemplate.add(opendedTemplate.get(i));
}
}
templateCheckBoxes = new UICheckBox[unSavedTemplate.size()];
initTemplatesChoosePane();
initTemplatesChoosePane(judgeJTemplateMustSave);
}
private boolean isneedToAdd(JTemplate<?, ?> template, JTemplate<?, ?> currentTemplate) {
protected boolean isneedToAdd(JTemplate<?, ?> template, JTemplate<?, ?> currentTemplate) {
//所有模板都判断是不是保存
if (isJudgeCurrentEditingTemplate) {
return !template.isALLSaved();
@ -194,7 +247,7 @@ public class SaveSomeTemplatePane extends BasicPane {
specifiedTemplate.stopEditing();
return specifiedTemplate.saveTemplate();
}
FineLoggerFactory.getLogger().info( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Template_Already_Saved", specifiedTemplate.getEditingFILE().getName()));
FineLoggerFactory.getLogger().info(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Template_Already_Saved", specifiedTemplate.getEditingFILE().getName()));
return true;
}

85
designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java

@ -18,6 +18,7 @@ import com.fr.design.lock.LockInfoDialog;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager;
import com.fr.design.mainframe.manager.search.searcher.control.pane.TemplateSearchRemindPane;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
@ -38,6 +39,7 @@ import java.util.UUID;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
@ -59,9 +61,11 @@ import java.util.Objects;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import com.fr.workspace.server.repository.template.TemplateRepository;
import com.fr.workspace.server.vcs.VcsOperator;
import org.jetbrains.annotations.Nullable;
@ -342,17 +346,11 @@ public class TemplateTreePane extends JPanel implements FileOperations {
if (FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),
tipContent,
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"),
YES_NO_OPTION)
== JOptionPane.YES_OPTION) {
// 删除所有选中的即可
if (!deleteNodes(Arrays.asList(treeNodes))) {
FineJOptionPane.showConfirmDialog(null,
Toolkit.i18nText("Fine-Design_Basic_Delete_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE);
}
deleteNodes(Arrays.asList(treeNodes));
}
} else {
@ -373,21 +371,13 @@ public class TemplateTreePane extends JPanel implements FileOperations {
if (FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),
tipContent,
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"),
YES_NO_OPTION)
== JOptionPane.YES_OPTION) {
// 删除其他
if (!deleteNodes(deletableNodes)) {
FineJOptionPane.showConfirmDialog(null,
Toolkit.i18nText("Fine-Design_Basic_Delete_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE);
}
deleteNodes(deletableNodes);
}
}
Set<FileNode> deletedFileNode = deletableNodes.stream().map(treeNode -> (FileNode) treeNode.getUserObject()).collect(Collectors.toSet());
refreshAfterDelete(deletedFileNode);
}
private void refreshAfterDelete(Set<FileNode> deletedPaths) {
@ -407,23 +397,54 @@ public class TemplateTreePane extends JPanel implements FileOperations {
}
}
private boolean deleteNodes(Collection<ExpandMutableTreeNode> nodes) {
boolean success = true;
for (ExpandMutableTreeNode treeNode : nodes) {
Object node = treeNode.getUserObject();
if (node instanceof FileNode) {
FileNodeFILE nodeFILE = new FileNodeFILE((FileNode) node);
if (nodeFILE.exists()) {
if (TemplateResourceManager.getResource().delete(nodeFILE)) {
HistoryTemplateListCache.getInstance().deleteFile(nodeFILE);
} else {
success = false;
private void deleteNodes(Collection<ExpandMutableTreeNode> nodes) {
new SwingWorker<Boolean,Void>(){
@Override
protected Boolean doInBackground() throws Exception {
boolean success = true;
for (ExpandMutableTreeNode treeNode : nodes) {
Object node = treeNode.getUserObject();
if (node instanceof FileNode) {
FileNodeFILE nodeFILE = new FileNodeFILE((FileNode) node);
if (nodeFILE.exists()) {
if (!VcsHelper.getInstance().isLegacyMode()) {
try {
WorkContext.getCurrent().get(VcsOperator.class).recycleVersion(VcsHelper.getInstance().getCurrentUsername(), nodeFILE.getPath());
} catch (Exception e) {
FineLoggerFactory.getLogger().error("[VcsV2] recycle {} failed", nodeFILE.getName());
}
}
if (TemplateResourceManager.getResource().delete(nodeFILE)) {
HistoryTemplateListCache.getInstance().deleteFile(nodeFILE);
} else {
success = false;
}
}
}
}
return success;
}
}
return success;
@Override
protected void done() {
try {
if (!get()) {
showErrorDialog();
}
Set<FileNode> deletedFileNode = nodes.stream().map(treeNode -> (FileNode) treeNode.getUserObject()).collect(Collectors.toSet());
refreshAfterDelete(deletedFileNode);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
private void showErrorDialog() {
FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Delete_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE);
}

17
designer-base/src/main/java/com/fr/design/formula/DefaultTinyFormulaPane.java

@ -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());
}
}

8
designer-base/src/main/java/com/fr/design/formula/FormulaPane.java

@ -34,6 +34,7 @@ import com.fr.design.gui.itextarea.UITextArea;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants;
import com.fr.design.i18n.DesignSizeI18nManager;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
@ -742,7 +743,8 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
public BasicDialog showLargeWindow(Window window, DialogActionListener l) {
BasicDialog basicDialog = super.showWindowWithCustomSize(window, l, new Dimension(900, 600));
Dimension dimension = DesignSizeI18nManager.getInstance().i18nDimension(this.getClass().getName());
BasicDialog basicDialog = super.showWindowWithCustomSize(window, l, dimension);
basicDialog.setMinimumSize(new Dimension(900, 600));
basicDialog.setResizable(true);
return basicDialog;
@ -1196,7 +1198,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initDescriptionTextArea() {
// Description
descriptionTextArea = new UITextArea(DESCRIPTION_TEXT_AREA_ROW,DESCRIPTION_TEXT_AREA_COLUMN);
descriptionTextArea = new UITextArea(DESCRIPTION_TEXT_AREA_ROW, DESCRIPTION_TEXT_AREA_COLUMN);
descriptionTextArea.setBackground(Color.white);
descriptionTextArea.setLineWrap(true);
descriptionTextArea.setWrapStyleWord(true);
@ -1282,7 +1284,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
desScrollPane.setBorder(null);
panel.add(this.createNamePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Formula_Description") + ":", desScrollPane), BorderLayout.CENTER);
initVariablesTreeSelectionListener();
this.add(panel,BorderLayout.CENTER);
this.add(panel, BorderLayout.CENTER);
}
private void initComponents() {

8
designer-base/src/main/java/com/fr/design/formula/TinyFormulaPane.java

@ -11,9 +11,11 @@ import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.TableLayout;
import com.fr.design.mainframe.DesignerContext;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

@ -14,7 +14,7 @@ import java.awt.Font;
*/
public interface DefaultValueAdjustProvider extends Selectable {
String MARK_STRING = "DefaultValueAdjustProvider";
int CURRENT_LEVEL = 1;
int CURRENT_LEVEL = 2;
/**
* 调整单元格对象默认值

6
designer-base/src/main/java/com/fr/design/fun/impl/AbstractDefaultValueAdjustProvider.java

@ -9,9 +9,13 @@ import com.fr.stable.fun.mark.API;
@API(level = DefaultValueAdjustProvider.CURRENT_LEVEL)
public abstract class AbstractDefaultValueAdjustProvider extends AbstractProvider implements DefaultValueAdjustProvider {
//1.16及之前发布版本插件里面没有实现currentAPILevel方法,运行时候会走到主jar,拿到-2。
//1.16.1及之后发布版本插件实现currentAPILevel方法,编译插件的时候,会把DefaultValueAdjustProvider.CURRENT_LEVEL的值编译给插件,比如1.16.1会拿到2。
private static final int OLD_CURRENT_LEVEL = -2;
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
return OLD_CURRENT_LEVEL;
}
public String mark4Provider() {

5
designer-base/src/main/java/com/fr/design/gui/UILookAndFeel.java

@ -1,5 +1,6 @@
package com.fr.design.gui;
import com.fr.base.svg.IconUtils;
import com.fr.design.gui.borders.UIFrameBorder;
import com.fr.design.gui.borders.UIInternalFrameBorder;
import com.fr.design.gui.borders.UITableHeaderBorder;
@ -160,10 +161,10 @@ public class UILookAndFeel extends MetalLookAndFeel {
table.put("Tree.collapsedIcon", loadIcon("TreePlusIcon.png", this));
table.put("Tree.openIcon", loadIcon("TreeFolderOpenedIcon.png", this));
table.put("Tree.closedIcon", loadIcon("TreeFolderClosedIcon.png", this));
table.put("Tree.leafIcon", loadIcon("TreeLeafIcon.svg", this));
table.put("Tree.leafIcon", loadIcon("TreeLeafIcon.png", this));
table.put("FileView.directoryIcon", loadIcon("DirectoryIcon.png", this));
table.put("FileView.computerIcon", loadIcon("ComputerIcon.png", this));
table.put("FileView.fileIcon", loadIcon("FileIcon.svg", this));
table.put("FileView.fileIcon", IconUtils.readIcon("/com/fr/design/images/lookandfeel/FileIcon.svg"));
table.put("FileView.floppyDriveIcon", loadIcon("FloppyIcon.png", this));
table.put("FileView.hardDriveIcon", loadIcon("HarddiskIcon.png", this));
table.put("FileChooser.detailsViewIcon", loadIcon("FileDetailsIcon.png", this));

8
designer-base/src/main/java/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java

@ -8,12 +8,14 @@
*/
package com.fr.design.gui.autocomplete;
import com.fr.stable.StringUtils;
import javax.swing.text.JTextComponent;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.text.JTextComponent;
/**
@ -186,7 +188,9 @@ public abstract class AbstractCompletionProvider
while (index<completions.size()) {
Completion c = completions.get(index);
if (Util.startsWithIgnoreCase(c.getInputText(), text)) {
String inputText = c.getInputText();
//当输入文本和补全项相等时,不再添加到补全项到窗口中
if (Util.startsWithIgnoreCase(inputText, text) && !StringUtils.equals(inputText, text)) {
retVal.add(c);
index++;
}

19
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java

@ -1,12 +1,10 @@
package com.fr.design.gui.autocomplete;
import com.fr.design.formula.FormulaPane;
import com.fr.stable.StringUtils;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
import java.awt.Window;
/**
* @author Hoky
@ -70,9 +68,18 @@ public class FormulaPaneAutoCompletion extends AutoCompletionWithExtraRefresh {
caret.setDot(start);
caret.moveDot(dot);
if (FormulaPane.containsParam(replacement)) {
textComp.replaceSelection(FormulaPane.getParamPrefix(replacement) + replacement);
int caretPosition = textComp.getCaretPosition();
textComp.setCaretPosition(caretPosition);
String selectedText = textComp.getSelectedText();
//找到选择文本(光标输入位置dot)进行补全
String text = textComp.getText().substring(0, dot);
int index = text.lastIndexOf(selectedText);
//获取replacement的前缀,replacement是不带前缀的,例如变量$$page_number,获取到的replacement是page_number
String paramPrefix = FormulaPane.getParamPrefix(replacement);
//当选择文本之前有和param前缀相同大小的字符串时,截取对比一下,如果内容相同,则前缀已经存在,不用再拼接了
String prefix = (index >= paramPrefix.length()) ? text.substring(index - paramPrefix.length(), index) : StringUtils.EMPTY;
if (!FormulaPane.getParamPrefix(replacement).equals(prefix)) {
replacement = paramPrefix + replacement;
}
textComp.replaceSelection(replacement);
} else {
textComp.replaceSelection(replacement + "()");
int caretPosition = textComp.getCaretPosition();

53
designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java

@ -17,16 +17,20 @@ import com.fr.stable.Nameable;
import com.fr.stable.StringUtils;
import com.fr.stable.core.PropertyChangeAdapter;
import javax.swing.DefaultListCellRenderer;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@ -343,21 +347,48 @@ public abstract class JListControlPane extends JControlPane implements ListContr
}
protected class NameableListCellRenderer extends
DefaultListCellRenderer {
JPanel implements ListCellRenderer<Object> {
private final JLabel textLabel;
private final JLabel iconLabel;
/**
* JList默认单元格渲染器的选中背景色
*/
private final Color selectedBgColor = new Color(65, 155, 249);
protected NameableListCellRenderer() {
setLayout(new BorderLayout());
this.textLabel = new JLabel();
this.iconLabel = new JLabel();
this.textLabel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 1));
this.iconLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 0));
add(this.textLabel, BorderLayout.CENTER);
add(this.iconLabel, BorderLayout.WEST);
this.iconLabel.setBackground(Color.WHITE);
//iconLabel和textLabel的背景颜色不会被JList背景颜色覆盖,开发者自定义
this.textLabel.setOpaque(true);
this.iconLabel.setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
if (value instanceof ListModelElement) {
ListModelElement element = ((ListModelElement) value);
Nameable nameable = element.wrapper;
this.setText(nameable.getName());
this.textLabel.setText(nameable.getName());
boolean iconSet = false;
if(isSelected) {
this.textLabel.setBackground(selectedBgColor);
this.textLabel.setForeground(Color.WHITE);
} else {
this.textLabel.setBackground(Color.WHITE);
this.textLabel.setForeground(Color.BLACK);
}
for (NameableCreator creator : JListControlPane.this.creators()) {
if (creator.menuIcon() != null && creator.acceptObject2Populate(nameable) != null) {
this.setIcon(creator.menuIcon());
this.iconLabel.setIcon(creator.menuIcon());
this.setToolTipText(creator.createTooltip());
iconSet = true;
break;
@ -369,8 +400,16 @@ public abstract class JListControlPane extends JControlPane implements ListContr
}
return this;
}
}
/**
* 改造后兼容子类NoIconNameableListCellRenderer使用,添加此setIcon函数
*
* @param icon 图标,可为null
*/
public void setIcon(Icon icon) {
this.iconLabel.setIcon(icon);
}
}
@Override
public BasicBeanPane createPaneByCreators(NameableCreator creator) {
return Reflect.on(creator.getUpdatePane()).create().get();

34
designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java

@ -28,14 +28,7 @@ import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Constructor;
@ -125,6 +118,9 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li
for (int i = 0, size = widget.getListenerSize(); i < size; i++) {
Listener listener = widget.getListener(i);
if (!listener.isDefault()) {
if (StringUtils.isEmpty(listener.getEventName())) {
continue;
}
String eventName = switchLang(listener.getEventName()) + (nameObjectList.size() + 1);
NameObject nameObject = new NameObject(eventName, listener);
nameObjectList.add(nameObject);
@ -146,7 +142,7 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li
}
this.checkButtonEnabled();
refreshEventListWrapperPane();
this.checkGroupPaneSize();
this.updateGroupPaneSize(contentPane);
isPopulating = false;
}
@ -214,7 +210,7 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li
nameEdList.addModNameActionListener(new ModNameActionListener() {
@Override
public void nameModed(int index, String oldName, String newName) {
checkGroupPaneSize();
updateGroupPaneSize(contentPane);
saveSettings();
}
});
@ -304,24 +300,30 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li
public void onAddItem(NameableCreator creator) {
updateSelectedNameList(creator);
getCommonHandlers().onAddItem(creator);
checkGroupPaneSize();
updateGroupPaneSize(contentPane);
}
@Override
public void onRemoveItem() {
getCommonHandlers().onRemoveItem();
refreshEventListWrapperPane();
checkGroupPaneSize();
updateGroupPaneSize(contentPane);
}
@Override
public void onCopyItem() {
getCommonHandlers().onCopyItem();
checkGroupPaneSize();
updateGroupPaneSize(contentPane);
}
private void checkGroupPaneSize() {
/**
* 根据父面板更新对应的面板宽度
* 如果小于父面板的宽度就填充到与父面板宽度一致
*
* @param parentPane 父面板
*/
private void updateGroupPaneSize(JPanel parentPane) {
int width = 180;
Iterator<Map.Entry<String, ListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
@ -331,7 +333,9 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li
width = Math.max(width, calculateUIListMaxCellWidth(uiList.getModel(), uiList.getFontMetrics(uiList.getFont())));
}
iterator = nameEdListMap.entrySet().iterator();
width += 30;
//contentPane是外层的Panel,如果不进行判断的话宽度就可能会小于contentPanel,右侧会有空隙
//所以需要判断一下,如果外层比较宽就取外层的宽度,防止空隙出现
width = Math.max(width + 30, parentPane == null ? 0 : parentPane.getWidth());
while (iterator.hasNext()) {
Map.Entry<String, ListWrapperPane> entry = iterator.next();
ListWrapperPane wrapperPane = entry.getValue();

2
designer-base/src/main/java/com/fr/design/gui/frpane/EditingStringListPane.java

@ -153,7 +153,7 @@ public abstract class EditingStringListPane extends BasicBeanPane<List<String>>
if (selected != null) {
int re = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(EditingStringListPane.this),
Toolkit.i18nText("Fine-Design_Basic_Sure_To_Delete") + selected.toString() + "?",
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"),
JOptionPane.OK_CANCEL_OPTION);
if (re == JOptionPane.OK_OPTION) {
JListUtils.removeSelectedListItems(jlist);

25
designer-form/src/main/java/com/fr/design/widget/ui/designer/component/FontSizeComboPane.java → designer-base/src/main/java/com/fr/design/gui/frpane/FontSizeComboPane.java

@ -1,7 +1,9 @@
package com.fr.design.widget.ui.designer.component;
package com.fr.design.gui.frpane;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.stable.collections.CollectionUtils;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.Vector;
@ -13,15 +15,22 @@ public class FontSizeComboPane extends JPanel{
private static final int MAX_FONT_SIZE = 100;
private UIComboBox comboBox;
public FontSizeComboPane(){
initComponent();
this(null);
}
public void initComponent(){
this.setLayout(FRGUIPaneFactory.createBorderLayout());
Vector<Integer> integerList = new Vector<Integer>();
for (int i = 1; i < MAX_FONT_SIZE; i++) {
integerList.add(i);
public FontSizeComboPane(Vector<Integer> fontSizes){
initComponent(fontSizes);
}
public void initComponent(Vector<Integer> fontSizes){
if(CollectionUtils.isEmpty(fontSizes)) {
fontSizes = new Vector<>();
for (int i = 1; i < MAX_FONT_SIZE; i++) {
fontSizes.add(i);
}
}
comboBox = new UIComboBox(integerList);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
comboBox = new UIComboBox(fontSizes);
comboBox.setEditable(true);
this.add(comboBox, BorderLayout.CENTER);
}

2
designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java

@ -215,7 +215,7 @@ public class JTreeControlPane extends ControlPane {
public void actionPerformed(ActionEvent e) {
// TODO remove tree node
int val = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?",
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val != JOptionPane.OK_OPTION) {
return;
}

8
designer-base/src/main/java/com/fr/design/gui/frpane/RegPane.java

@ -394,6 +394,7 @@ public class RegPane extends BasicPane {
private static class RegLengthPane extends DisplayPane {
private UISpinner minLenSpinner;
private UISpinner maxLenSpinner;
private final int DEFAULT_WIDTH = 60;
public RegLengthPane(){
this.setLayout(FRGUIPaneFactory.createBorderLayout());
@ -403,8 +404,11 @@ public class RegPane extends BasicPane {
maxLenSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 0);
UILabel minLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Reg_Min_Length"));
UILabel maxLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Reg_Max_Length"));
minLabel.setPreferredSize(new Dimension(60, 20));
maxLabel.setPreferredSize(new Dimension(60, 20));
int minLabelWidth = Math.max(minLabel.getPreferredSize().width, DEFAULT_WIDTH);
int maxLabelWidth = Math.max(maxLabel.getPreferredSize().width, DEFAULT_WIDTH);
minLabel.setPreferredSize(new Dimension(minLabelWidth, 20));
maxLabel.setPreferredSize(new Dimension(maxLabelWidth, 20));
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
Component[][] components = new Component[][]{

2
designer-base/src/main/java/com/fr/design/gui/frpane/UITabbedPane.java

@ -126,7 +126,7 @@ public class UITabbedPane extends JTabbedPane{
* @param i tab索引
*/
public void doRemoveTab(int i){
int re = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(UITabbedPane.this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sure_To_Delete")+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove")
int re = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(UITabbedPane.this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sure_To_Delete")+ "?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt")
, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (re == JOptionPane.OK_OPTION) {
super.removeTabAt(i);

2
designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java

@ -179,7 +179,7 @@ public class LayerDataControlPane extends ControlPane {
public void actionPerformed(ActionEvent e) {
// TODO remove tree node
int val = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?",
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val != JOptionPane.OK_OPTION) {
return;
}

18
designer-base/src/main/java/com/fr/design/gui/icontainer/UIEastResizableContainer.java

@ -5,10 +5,21 @@ import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.utils.SvgDrawUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import javax.swing.*;
import java.awt.*;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.LayoutManager;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
@ -313,7 +324,6 @@ public class UIEastResizableContainer extends JPanel {
@Override
public void paint(Graphics g) {
Image button;
if (containerWidth == leftPaneWidth) {
if (model == UIConstants.MODEL_NORMAL) {
button = UIConstants.DRAG_LEFT_NORMAL;
@ -327,7 +337,7 @@ public class UIEastResizableContainer extends JPanel {
button = UIConstants.DRAG_RIGHT_PRESS;
}
}
g.drawImage(button, 18, 7, this);
SvgDrawUtils.doDrawSVG(g, () -> SvgDrawUtils.drawImage(g, button, 10, 7, null));
}
}
}

30
designer-base/src/main/java/com/fr/design/gui/icontainer/UIResizableContainer.java

@ -3,12 +3,22 @@ package com.fr.design.gui.icontainer;
import com.fr.base.vcs.DesignerMode;
import com.fr.design.constants.UIConstants;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.utils.SvgPaintUtils;
import com.fr.stable.Constants;
import com.fr.design.utils.SvgDrawUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.stable.Constants;
import javax.swing.*;
import java.awt.*;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.LayoutManager;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
@ -411,11 +421,9 @@ public class UIResizableContainer extends JPanel {
Image upButton = (upModel == UIConstants.MODEL_NORMAL ? UIConstants.DRAG_UP_NORMAL : UIConstants.DRAG_UP_PRESS);
Image downButton = (downModel == UIConstants.MODEL_NORMAL ? UIConstants.DRAG_DOWN_NORMAL : UIConstants.DRAG_DOWN_PRESS);
g.drawImage(UIConstants.DRAG_BAR_LIGHT, 0, 0, getWidth(), getHeight(), null);
SvgPaintUtils.beforePaint((Graphics2D) g);
g.drawImage(UIConstants.DRAG_LINE, (getWidth() - toolPaneHeight) / 2, 3, null);
g.drawImage(upButton, ARROW_MARGIN, 1, null);
g.drawImage(downButton, getWidth() - toolPaneHeight - ARROW_MARGIN, 1, null);
SvgPaintUtils.afterPaint((Graphics2D) g);
SvgDrawUtils.doDrawSVG(g, () -> SvgDrawUtils.drawImage(g, UIConstants.DRAG_LINE, (getWidth() - toolPaneHeight) / 2, 3, null));
SvgDrawUtils.doDrawSVG(g, () -> SvgDrawUtils.drawImage(g, upButton, ARROW_MARGIN, 0, null));
SvgDrawUtils.doDrawSVG(g, () -> SvgDrawUtils.drawImage(g, downButton, (getWidth() - toolPaneHeight - ARROW_MARGIN), 0, null));
}
}
@ -512,7 +520,7 @@ public class UIResizableContainer extends JPanel {
button = UIConstants.DRAG_LEFT_PRESS;
}
}
g.drawImage(button, -1, ARROW_MARGIN_VERTICAL, this);
SvgDrawUtils.doDrawSVG(g, () -> SvgDrawUtils.drawImage(g, button, -6, ARROW_MARGIN_VERTICAL, VerticalToolPane.this));
} else {
g.drawImage(UIConstants.DRAG_BAR_LIGHT, 0, 0, toolPaneHeight, getHeight(), null);
if (containerWidth == toolPaneHeight) {
@ -528,7 +536,7 @@ public class UIResizableContainer extends JPanel {
button = UIConstants.DRAG_RIGHT_PRESS;
}
}
g.drawImage(button, 2, ARROW_MARGIN_VERTICAL, this);
SvgDrawUtils.doDrawSVG(g, () -> SvgDrawUtils.drawImage(g, button, 10, ARROW_MARGIN_VERTICAL, VerticalToolPane.this));
}
if (isLeftRightDragEnabled) {
g.drawImage(UIConstants.DRAG_DOT_VERTICAL, 2, getHeight() / 2, 5, toolPaneHeight, null);

14
designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java

@ -11,15 +11,20 @@ import com.fr.stable.core.PropertyChangeAdapter;
import javax.swing.ListModel;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import java.util.ArrayList;
import java.util.Vector;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import java.util.Vector;
public class JNameEdList extends UIList implements CellEditorListener {
private static final int ICON_WIDTH = 20;
/**
* 原值为20,设计器图标由png替换为svg之后JNameEdList的icon大小为16x16
* 重命名是会出现左侧一部分带有背景色的渲染
*/
private static final int ICON_WIDTH = 16;
private boolean editable = true;
// kunsnat: 是否强制ListName是数字 (int型)
@ -175,7 +180,8 @@ public class JNameEdList extends UIList implements CellEditorListener {
}
public void setIllegalIndex(int index) {
setNameAt(NameInspector.ILLEGAL_NAME_HOLDER, index);
//环境如果重名会被命名为请重命名,这个请重命名也会重复,后面加个索引区别一下
setNameAt(NameInspector.ILLEGAL_NAME_HOLDER + index, index);
this.repaint();
}

2
designer-base/src/main/java/com/fr/design/gui/imenutable/UIMenuTableUI.java

@ -76,7 +76,7 @@ public class UIMenuTableUI extends UITableUI{
public void mousePressed(MouseEvent e) {
if (e.getX() >= table.getWidth() - 20) {
int val = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?",
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val == JOptionPane.OK_OPTION) {
uiTable.removeLine(table.rowAtPoint(e.getPoint()));
uiTable.fireTargetChanged();

2
designer-base/src/main/java/com/fr/design/gui/itable/UITableUI.java

@ -134,7 +134,7 @@ public class UITableUI extends BasicTableUI {
}
if (!table.isEditing()) {
int val = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?",
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val == JOptionPane.OK_OPTION) {
((UITable) table).removeLine(table.rowAtPoint(e.getPoint()));
((UITable) table).fireTargetChanged();

17
designer-base/src/main/java/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java

@ -4,6 +4,7 @@ import com.fr.base.BaseUtils;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.log.FineLoggerFactory;
import org.jetbrains.annotations.Nullable;
import javax.swing.JOptionPane;
import javax.swing.JTable;
@ -64,6 +65,20 @@ public abstract class UITableModelAdapter<T> extends AbstractTableModel implemen
return null;
}
/**
* 获取映射后的值
*
* @param row
* @return
*/
@Nullable
public T getConvertRowSelectedValue(int row) {
if (table.getSelectedRow() >= 0) {
return list.get(table.convertRowIndexToModel(row));
}
return null;
}
public void setColumnClass(Class<?>[] classes) {
this.classes = classes;
}
@ -256,7 +271,7 @@ public abstract class UITableModelAdapter<T> extends AbstractTableModel implemen
component = DesignerContext.getDesignerFrame();
}
int val = FineJOptionPane.showConfirmDialog(component, getDeleteTipText()
, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"),
, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val != JOptionPane.OK_OPTION) {
return;

11
designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileNodeConstants.java

@ -12,9 +12,8 @@ import com.fr.report.ExtraReportClassManager;
import com.fr.report.fun.ReportSupportedFileProvider;
import com.fr.workspace.server.repository.template.TemplateRepository;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -24,7 +23,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
*/
public class FileNodeConstants {
private static List<String> supportFileType;
private static Set<String> supportFileType;
private static ReadWriteLock rwl = new ReentrantReadWriteLock();
private FileNodeConstants() {
@ -48,16 +47,14 @@ public class FileNodeConstants {
private static void addAppExtensions(FileExtension[] extensions) {
for (int i = 0, size = extensions.length; i < size; i++) {
if (!supportFileType.contains(extensions[i].getExtension())) {
supportFileType.add(extensions[i].getExtension());
}
supportFileType.add(extensions[i].getExtension());
}
}
private static void initSupportedTypes() {
try {
rwl.writeLock().lock();
supportFileType = new ArrayList<String>();
supportFileType = new LinkedHashSet<>();
//通过插件扩展的
Set<ReportSupportedFileProvider> providers = ExtraReportClassManager.getInstance().getArray(ReportSupportedFileProvider.XML_TAG);
for (ReportSupportedFileProvider provider : providers) {

41
designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java

@ -16,6 +16,7 @@ import com.fr.design.gui.frpane.UIPercentDragPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.LineComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
@ -26,8 +27,8 @@ import com.fr.design.style.color.NewColorSelectBox;
import com.fr.env.utils.DesignerInteractionHistory;
import com.fr.general.Background;
import com.fr.general.IOUtils;
import com.fr.i18n.UrlI18nManager;
import com.fr.general.act.BorderPacker;
import com.fr.i18n.UrlI18nManager;
import com.fr.stable.Constants;
import com.fr.stable.GraphDrawHelper;
import com.fr.stable.ProjectLibrary;
@ -45,10 +46,10 @@ import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
@ -78,7 +79,18 @@ import java.util.Arrays;
public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane implements UIObserver {
private final int SETTING_LABEL_WIDTH = 60;
private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT);
private final String TWEAK_NINE_POINT_HELP_URL = "https://help.fanruan.com/finereport/doc-view-4135.html";
/**
* 云中心点九图帮助文档在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Nine_Patch";
/**
* 云中心点九图帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Nine_Patch_Default";
private final String TWEAK_NINE_POINT_HELP_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
private UIObserverListener uiObserverListener;
@ -125,7 +137,9 @@ public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane imple
}
});
tweakNinePointButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill"));
String buttonText = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Border_Image_Config_Nine_Point_Fill");
tweakNinePointButton = new UIButton(buttonText);
tweakNinePointButton.setToolTipText(buttonText);
borderImageOpacityPane = new UIPercentDragPane();
}
@ -162,23 +176,28 @@ public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane imple
borderedImagePreviewPane.setPreferredSize(new Dimension(145, 145));
borderedImagePreviewPane.add(imagePreviewPane, BorderLayout.CENTER);
JPanel tweakNinePointComposedPane = new JPanel();
tweakNinePointComposedPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
tweakNinePointButton.setPreferredSize(new Dimension(145, 16));
tweakNinePointComposedPane.add(tweakNinePointHelpButton);
tweakNinePointComposedPane.add(tweakNinePointButton);
return TableLayoutHelper.createGapTableLayoutPane(
new JComponent[][]{
{null, borderedImagePreviewPane},
{null, chooseImageButton},
{tweakNinePointComposedPane, null},
{null, createTweakNinePointComposedPane()},
{null, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))},
{null, this.borderImageOpacityPane}
},
rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1);
}
private JPanel createTweakNinePointComposedPane() {
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
return TableLayoutHelper.createGapTableLayoutPane(
new Component[][]{
{tweakNinePointHelpButton, tweakNinePointButton}
},
new double[]{p},
new double[]{p, f},
new int[][]{{1, 1}}, 0, 0);
}
private void initImageFileChooserIfNotExist() {
if (imageFileChooser == null) {
imageFileChooser = new ImageFileChooser();

47
designer-base/src/main/java/com/fr/design/i18n/LocaleLinkProvider.java

@ -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;
}
}

27
designer-base/src/main/java/com/fr/design/icon/WarningIcon.java

@ -1,12 +1,17 @@
package com.fr.design.icon;
import com.fr.base.svg.SVGLoader;
import com.fr.design.utils.SvgPaintUtils;
import com.fr.base.svg.SystemScaleUtils;
import com.fr.design.utils.SvgDrawUtils;
import com.fr.log.FineLoggerFactory;
import javax.swing.GrayFilter;
import javax.swing.ImageIcon;
import java.awt.*;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.ImageObserver;
/**
@ -20,7 +25,8 @@ public class WarningIcon extends ImageIcon {
};
protected final static MediaTracker TRACKER = new MediaTracker(COMPONENT);
private final static Image WARNING_IMAGE = SVGLoader.load("/com/fr/design/standard/warning.svg");
private static final boolean HI_DPI_SUPPORT = SystemScaleUtils.isJreHiDPIEnabled();
public static final float SYSTEM_SCALE = SystemScaleUtils.sysScale();
private Image mainImage = null;
private ImageObserver imageObserver;
private int width = -1;
@ -36,14 +42,15 @@ public class WarningIcon extends ImageIcon {
@Override
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
SvgPaintUtils.beforePaint((Graphics2D) g);
//裁剪绘制svg的位置,以免影响到图标右侧的文字
Graphics2D graphics = (Graphics2D) g.create(x, y, WARNING_IMAGE.getWidth(null), WARNING_IMAGE.getHeight(null));
if (mainImage != null) {
g.drawImage(mainImage, x, y, c);
SvgDrawUtils.doDrawSVG(graphics, () -> SvgDrawUtils.drawImage(graphics, mainImage, x, y, null));
}
if (WARNING_IMAGE != null) {
g.drawImage(WARNING_IMAGE, x, y, c);
SvgDrawUtils.doDrawSVG(graphics, () -> SvgDrawUtils.drawImage(graphics, WARNING_IMAGE, x, y, null));
}
SvgPaintUtils.afterPaint((Graphics2D) g);
graphics.dispose();
}
/**
@ -91,7 +98,8 @@ public class WarningIcon extends ImageIcon {
* @return the width in pixels of this icon
*/
public int getIconWidth() {
return width;
//如果环境支持高清化,drawImage可能会缩放绘制的图像比例,需要保证svg正常显示的同时调整绘制范围
return HI_DPI_SUPPORT ? (int) (width / SYSTEM_SCALE) : width;
}
/**
@ -100,7 +108,8 @@ public class WarningIcon extends ImageIcon {
* @return the height in pixels of this icon
*/
public int getIconHeight() {
return height;
//如果环境支持高清化,drawImage可能会缩放绘制的图像比例,需要保证svg正常显示的同时调整绘制范围
return HI_DPI_SUPPORT ? (int) (height / SYSTEM_SCALE) : height;
}
{

114
designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java

@ -14,18 +14,39 @@ import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextarea.UITextArea;
import com.fr.design.gui.itextfield.PlaceholderTextField;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.javascript.jsapi.JSAPITreeHelper;
import com.fr.design.javascript.jsapi.JSAPIUserObject;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.CloudCenter;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
@ -50,24 +71,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
public class JSContentWithDescriptionPane extends JSContentPane implements KeyListener {
@ -117,6 +122,15 @@ public class JSContentWithDescriptionPane extends JSContentPane implements KeyLi
private static final String RELOAD_CARD = "reloadCard";
private static final String DOC_LIST_CARD = "docListCard";
/**
* 云中心Js高级编辑器帮助链接前缀在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Js_Editor";
/**
* 云中心Js高级编辑器帮助链接前缀在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Js_Editor_Default";
public JSContentWithDescriptionPane(String[] args) {
this.setLayout(new BorderLayout());
//===============================
@ -352,27 +366,55 @@ public class JSContentWithDescriptionPane extends JSContentPane implements KeyLi
private void doHelpDocumentSearch() {
Object value = interfaceNameList.getSelectedValue();
if (value != null) {
String url = CloudCenter.getInstance().acquireUrlByKind("af.doc_search", DOCUMENT_SEARCH_URL) + value.toString();
try {
new SwingWorker<List<HelpDocument>, Void>() {
@Override
protected List<HelpDocument> doInBackground() {
List<HelpDocument> helpDocuments = new ArrayList<>();
updateHelpDocuments(value, helpDocuments);
return helpDocuments;
}
@Override
protected void done() {
try {
List<HelpDocument> helpDocuments = get();
DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel();
helpDOCModel.clear();
for (HelpDocument helpDocument : helpDocuments) {
helpDOCModel.addElement(helpDocument);
}
} catch (InterruptedException | ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}.execute();
}
}
private void updateHelpDocuments(Object value, List<HelpDocument> helpDocuments) {
String url = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT) + value.toString();
try {
JSONArray jsonArray = null;
//目前简中繁中之外的语言高级编辑器功能及文档不完善,右侧展示的文档链接列表暂时为空白
if(GeneralContext.isChineseEnv()) {
String result = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(result);
JSONArray jsonArray = jsonObject.optJSONArray("list");
if (jsonArray != null) {
DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel();
helpDOCModel.clear();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject resultJSONObject = jsonArray.optJSONObject(i);
String docURL = resultJSONObject.optString("url");
String name = resultJSONObject.optString("title").trim();
HelpDocument helpDocument = new HelpDocument(docURL, name);
helpDOCModel.addElement(helpDocument);
}
jsonArray = jsonObject.optJSONArray("list");
}
if (jsonArray != null) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject resultJSONObject = jsonArray.optJSONObject(i);
String docURL = resultJSONObject.optString("url");
String name = resultJSONObject.optString("title").trim();
HelpDocument helpDocument = new HelpDocument(docURL, name);
helpDocuments.add(helpDocument);
}
} catch (JSONException e) {
FineLoggerFactory.getLogger().debug(e.getMessage(), e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
} catch (JSONException e) {
FineLoggerFactory.getLogger().debug(e.getMessage(), e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save