Browse Source

Pull request #1: KERNEL-14569 merge: feature/x合并到research/11.0

Merge in ~CLOUD.LIU/design from feature/x to research/11.0

* commit '1a584a9a6b57e7f2c0330370ffa8a16d2a6ba79f': (1579 commits)
  常量命名规范修复
  REPORT-82787回退
  REPORT-92147 REPORT-92159问题修复
  REPORT-82787 图表空数据提示配置页面,默认图片需补充繁中版
  REPORT-92134,REPORT-92120,REPORT-92123 问题修复
  REPORT-89253 命名和读取规范化处理,回退右下角异常小标记
  REPORT-89253 修正插入悬浮元素图标项文件路径
  REPORT-89253 设计器替换高清svg图标第2次提交
  REPORT-91610 数据脱敏-设计器内en下面板文案显示不全 【问题原因】en、ja、ko下面板文案显示不全 【改动思路】与产品沟通后,调大这几个语言下弹窗的宽度 【review建议】
  REPORT-89253 设计器替换高清svg图标-第1次提交
  REPORT-91657 设计器单元格属性-其他面板文本显示截断 【问题原因】不同语言显示长度不同 【改动思路】选项面板水平布局修改为垂直布局
  REPORT-91743 设计器通过关闭模板A的方式触发保存,设计器页面显示还是模板A的内容
  REPORT-91743 设计器通过关闭模板A的方式触发保存,设计器页面显示还是模板A的内容
  REPORT-91486 不打开任何报表进入设计器,选项弹窗触发下保存,模板tab栏会自动弹出来
  REPORT-91591 单元格控件的自定义样式设置--代码格式调整
  REPORT-91316 不打开任何报表的情况下,编辑工具栏点不动
  REPORT-91591 单元格控件的自定义样式设置
  REPORT-91591 单元格控件的自定义样式设置
  REPORT-80651 模板版本管理重构一期 - 优化代码结构
  REPORT-80651 模板版本管理重构一期 - 修改代码
  ...
research/11.0
Cloud.Liu-刘学真 1 year ago
parent
commit
b145cc60b5
  1. 31
      build.gradle
  2. 24
      designer-base/src/main/java/com/fr/base/function/ThrowableRunnable.java
  3. 24
      designer-base/src/main/java/com/fr/base/function/UITerminator.java
  4. 3
      designer-base/src/main/java/com/fr/base/svg/IconUtils.java
  5. 6
      designer-base/src/main/java/com/fr/base/svg/SVGIcon.java
  6. 92
      designer-base/src/main/java/com/fr/base/svg/SVGLoader.java
  7. 181
      designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java
  8. 101
      designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java
  9. 12
      designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java
  10. 29
      designer-base/src/main/java/com/fr/design/DesignModelAdapter.java
  11. 193
      designer-base/src/main/java/com/fr/design/DesignerCloudURLManager.java
  12. 514
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  13. 40
      designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java
  14. 4
      designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java
  15. 4
      designer-base/src/main/java/com/fr/design/RestartHelper.java
  16. 4
      designer-base/src/main/java/com/fr/design/actions/AllowAuthorityEditAction.java
  17. 14
      designer-base/src/main/java/com/fr/design/actions/UpdateAction.java
  18. 2
      designer-base/src/main/java/com/fr/design/actions/community/BugAction.java
  19. 2
      designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java
  20. 17
      designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java
  21. 32
      designer-base/src/main/java/com/fr/design/actions/core/ActionFactory.java
  22. 2
      designer-base/src/main/java/com/fr/design/actions/edit/CopyAction.java
  23. 2
      designer-base/src/main/java/com/fr/design/actions/edit/CutAction.java
  24. 2
      designer-base/src/main/java/com/fr/design/actions/edit/PasteAction.java
  25. 8
      designer-base/src/main/java/com/fr/design/actions/file/CloseCurrentTemplateAction.java
  26. 50
      designer-base/src/main/java/com/fr/design/actions/file/DelFileAction.java
  27. 10
      designer-base/src/main/java/com/fr/design/actions/file/ExitDesignerAction.java
  28. 163
      designer-base/src/main/java/com/fr/design/actions/file/LocateAction.java
  29. 5
      designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java
  30. 217
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  31. 346
      designer-base/src/main/java/com/fr/design/actions/file/RenameAction.java
  32. 7
      designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java
  33. 4
      designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java
  34. 200
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineCloudConstants.java
  35. 196
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java
  36. 302
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java
  37. 111
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConstants.java
  38. 44
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java
  39. 30
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java
  40. 229
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/CustomSortPane.java
  41. 96
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabel.java
  42. 34
      designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabelPane.java
  43. 19
      designer-base/src/main/java/com/fr/design/actions/help/replace/ITReplaceOperator.java
  44. 1
      designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java
  45. 33
      designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java
  46. 28
      designer-base/src/main/java/com/fr/design/carton/CartonFiles.java
  47. 161
      designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java
  48. 45
      designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java
  49. 408
      designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java
  50. 406
      designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java
  51. 36
      designer-base/src/main/java/com/fr/design/carton/MonthlyCartonFile.java
  52. 312
      designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java
  53. 180
      designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java
  54. 152
      designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java
  55. 148
      designer-base/src/main/java/com/fr/design/components/loading/LoadingPane.java
  56. 21
      designer-base/src/main/java/com/fr/design/components/notification/NotificationAction.java
  57. 391
      designer-base/src/main/java/com/fr/design/components/notification/NotificationDialog.java
  58. 39
      designer-base/src/main/java/com/fr/design/components/notification/NotificationDialogProperties.java
  59. 88
      designer-base/src/main/java/com/fr/design/components/notification/NotificationMessage.java
  60. 39
      designer-base/src/main/java/com/fr/design/components/notification/NotificationModel.java
  61. 16
      designer-base/src/main/java/com/fr/design/components/notification/NotificationType.java
  62. 78
      designer-base/src/main/java/com/fr/design/components/page/PageControlModel.java
  63. 151
      designer-base/src/main/java/com/fr/design/components/page/PageControlPanel.java
  64. 184
      designer-base/src/main/java/com/fr/design/components/table/TablePanel.java
  65. 105
      designer-base/src/main/java/com/fr/design/components/tooltip/ModernToolTip.java
  66. 52
      designer-base/src/main/java/com/fr/design/config/DesignerProperties.java
  67. 24
      designer-base/src/main/java/com/fr/design/constants/DesignerColor.java
  68. 7
      designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java
  69. 5
      designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java
  70. 52
      designer-base/src/main/java/com/fr/design/constants/UIConstants.java
  71. 60
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  72. 7
      designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java
  73. 151
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  74. 93
      designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java
  75. 6
      designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java
  76. 119
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java
  77. 2
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java
  78. 36
      designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java
  79. 73
      designer-base/src/main/java/com/fr/design/data/datapane/SummaryMethodComboBox.java
  80. 28
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataCreatorProducer.java
  81. 12
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataNameObjectCreator.java
  82. 82
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java
  83. 75
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataSourceOP.java
  84. 254
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java
  85. 513
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  86. 57
      designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java
  87. 145
      designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java
  88. 44
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  89. 12
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java
  90. 281
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  91. 7
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java
  92. 2
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java
  93. 115
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java
  94. 35
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java
  95. 388
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java
  96. 16
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java
  97. 280
      designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java
  98. 301
      designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java
  99. 165
      designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java
  100. 74
      designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java
  101. Some files were not shown because too many files have changed in this diff Show More

31
build.gradle

@ -1,4 +1,5 @@
import org.gradle.plugins.ide.idea.model.IdeaLanguageLevel
import org.gradle.internal.os.OperatingSystem
plugins {
id 'java'
@ -9,6 +10,7 @@ plugins {
//
ext {
frVersion = ""
cbbVersion = ""
outputPath = "build"
ignoreTestFailureSetting = true
languageLevelSetting = 1.8
@ -44,6 +46,9 @@ allprojects {
repositories {
mavenLocal()
maven {
url 'https://maven.ej-technologies.com/repository'
}
}
idea {
@ -57,18 +62,18 @@ allprojects {
}
dependencies {
implementation 'com.fr.essential:fine-essential:' + cbbVersion
implementation 'com.fr.cbb:fine-universal-skeleton:' + cbbVersion
implementation 'com.install4j:install4j-runtime:8.0.4'
implementation 'com.fr.third:jxbrowser:6.23'
implementation 'com.fr.third:jxbrowser-mac:6.23'
implementation 'com.fr.third:jxbrowser-win64:6.23'
implementation 'com.fr.third:jxbrowser-v7:7.15'
implementation 'com.fr.third:jxbrowser-mac-v7:7.15'
implementation 'com.fr.third:jxbrowser-win64-v7:7.15'
implementation 'com.fr.third:jxbrowser-swing-v7:7.15'
implementation 'com.fr.third:jxbrowser-v7:7.22'
implementation 'com.fr.third:jxbrowser-swing-v7:7.22'
implementation 'com.fr.third.server:servlet-api:3.0'
implementation 'org.swingexplorer:swexpl:2.0.1'
implementation 'org.swingexplorer:swag:1.0'
implementation 'net.java.dev.jna:jna:5.4.0'
implementation 'org.apache.tomcat:tomcat-catalina:8.5.69'
implementation 'org.apache.tomcat:tomcat-catalina:8.5.72'
implementation 'org.apache.tomcat:tomcat-websocket:8.5.72'
implementation 'io.socket:socket.io-client:0.7.0'
implementation 'com.fr.third:fine-third:' + frVersion
implementation 'com.fr.core:fine-core:' + frDevVersion
@ -86,4 +91,16 @@ allprojects {
testImplementation 'org.powermock:powermock-api-easymock:1.7.1'
testImplementation 'junit:junit:4.12'
}
if (OperatingSystem.current().isMacOsX()) {
dependencies {
implementation 'com.fr.third:jxbrowser-mac:6.23'
implementation 'com.fr.third:jxbrowser-mac-v7:7.22'
}
} else if (OperatingSystem.current().isWindows()) {
dependencies {
implementation 'com.fr.third:jxbrowser-win64:6.23'
implementation 'com.fr.third:jxbrowser-win64-v7:7.22'
}
}
}

24
designer-base/src/main/java/com/fr/base/function/ThrowableRunnable.java

@ -0,0 +1,24 @@
package com.fr.base.function;
import com.fr.log.FineLoggerFactory;
/**
* 可抛出异常的 Runnable
*
* created by Harrison on 2022/05/24
**/
public interface ThrowableRunnable<T extends Exception> {
void run() throws T;
static <T extends Exception> Runnable toRunnable(ThrowableRunnable<T> runnable) {
return () -> {
try {
runnable.run();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
};
}
}

24
designer-base/src/main/java/com/fr/base/function/UITerminator.java

@ -0,0 +1,24 @@
package com.fr.base.function;
import com.fr.design.utils.DesignUtils;
import com.fr.runtime.FineRuntime;
/**
* UI 终止动作
*
* created by Harrison on 2022/07/14
**/
public abstract class UITerminator {
public void run() {
// 先执行必须的逻辑
FineRuntime.start();
DesignUtils.initLookAndFeel();
// 在执行核心逻辑
doRun();
}
protected abstract void doRun();
}

3
designer-base/src/main/java/com/fr/base/svg/IconUtils.java

@ -6,8 +6,7 @@ import com.fr.stable.bridge.StableFactory;
import com.fr.stable.fun.ResourcePathTransformer;
import com.fr.stable.plugin.ExtraClassManagerProvider;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

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

@ -2,10 +2,8 @@ package com.fr.base.svg;
import com.fr.general.IOUtils;
import javax.swing.Icon;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

92
designer-base/src/main/java/com/fr/base/svg/SVGLoader.java

@ -1,92 +0,0 @@
package com.fr.base.svg;
import com.fr.general.IOUtils;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.xmlgraphics.java2d.Dimension2DDouble;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
/**
* SVG图标加载器
* @author Yvan
* @version 10.0
* Created by Yvan on 2020/12/17
*/
public class SVGLoader {
public static final int ICON_DEFAULT_SIZE = 16;
public SVGLoader() {
}
@Nullable
public static Image load(@NotNull String url) {
try {
URL resource = IOUtils.getResource(url, SVGLoader.class);
if (resource == null) {
return null;
}
return load(resource, SVGIcon.SYSTEM_SCALE);
} catch (IOException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull URL url) throws IOException {
return load(url, SVGIcon.SYSTEM_SCALE);
}
@Nullable
public static Image load(@NotNull URL url, double scale) throws IOException {
try {
String svgUri = url.toString();
TranscoderInput input = new TranscoderInput(svgUri);
return SVGTranscoder.createImage(scale, input).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull URL url, double scale, Dimension2DDouble dimension) throws IOException {
try {
String svgUri = url.toString();
TranscoderInput input = new TranscoderInput(svgUri);
return SVGTranscoder.createImage(scale, input,
(float) (dimension.getWidth() * scale), (float) (dimension.getHeight() * scale)).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull URL url, double scale, double overriddenWidth, double overriddenHeight) throws IOException {
try {
String svgUri = url.toString();
TranscoderInput input = new TranscoderInput(svgUri);
return SVGTranscoder.createImage(scale, input, (float) (overriddenWidth * scale), (float) (overriddenHeight * scale)).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull String url, float width, float height) {
try {
URL resource = IOUtils.getResource(url, SVGLoader.class);
if (resource == null) {
return null;
}
TranscoderInput input = new TranscoderInput(resource.toString());
return SVGTranscoder.createImage(SVGIcon.SYSTEM_SCALE, input, -1, -1, width, height).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
}

181
designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java

@ -1,181 +0,0 @@
package com.fr.base.svg;
import com.fr.stable.AssistUtils;
import com.fr.value.AtomicNotNullLazyValue;
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.anim.dom.SVGOMDocument;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.XMLResourceDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringReader;
/**
* 可以根据某个缩放倍数scale将SVG图片转化为Image对象
* @author Yvan
* @version 10.0
* Created by Yvan on 2020/12/17
*/
public class SVGTranscoder extends ImageTranscoder {
private static final float DEFAULT_VALUE = -1.0F;
public static final float ICON_DEFAULT_SIZE = 16F;
private float origDocWidth;
private float origDocHeight;
@Nullable
private BufferedImage image;
private final double scale;
@NotNull
private static AtomicNotNullLazyValue<Double> iconMaxSize = new AtomicNotNullLazyValue<Double>() {
@NotNull
@Override
protected Double compute() {
double maxSize = Double.MAX_VALUE;
if (!GraphicsEnvironment.isHeadless()) {
GraphicsDevice defaultScreenDevice = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice();
Rectangle bounds = defaultScreenDevice.getDefaultConfiguration().getBounds();
AffineTransform tx = defaultScreenDevice
.getDefaultConfiguration()
.getDefaultTransform();
maxSize = Math.max(bounds.width * tx.getScaleX(), bounds.height * tx.getScaleY());
}
return maxSize;
}
};
public SVGTranscoder(double scale) {
this.scale = scale;
this.width = ICON_DEFAULT_SIZE;
this.height = ICON_DEFAULT_SIZE;
}
public SVGTranscoder(double scale, float width, float height) {
this.scale = scale;
this.width = width;
this.height = height;
}
public final float getOrigDocWidth() {
return this.origDocWidth;
}
public final void setOrigDocWidth(float origDocWidth) {
this.origDocWidth = origDocWidth;
}
public final float getOrigDocHeight() {
return this.origDocHeight;
}
public final void setOrigDocHeight(float origDocHeight) {
this.origDocHeight = origDocHeight;
}
public static double getIconMaxSize() {
return iconMaxSize.getValue();
}
@Nullable
public final BufferedImage getImage() {
return this.image;
}
@NotNull
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input) throws TranscoderException {
return createImage(scale, input, -1, -1);
}
@NotNull
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight) throws TranscoderException {
return createImage(scale, input, overriddenWidth, overriddenHeight, ICON_DEFAULT_SIZE, ICON_DEFAULT_SIZE);
}
@NotNull
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight, float width, float height) throws TranscoderException {
SVGTranscoder transcoder = new SVGTranscoder(scale, width, height);
if (!AssistUtils.equals(overriddenWidth, DEFAULT_VALUE)) {
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, overriddenWidth);
}
if (!AssistUtils.equals(overriddenHeight, DEFAULT_VALUE)) {
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, overriddenHeight);
}
double iconMaxSize = SVGTranscoder.iconMaxSize.getValue();
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_WIDTH, (float) iconMaxSize);
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_HEIGHT, (float) iconMaxSize);
transcoder.transcode(input, null);
return transcoder;
}
private static SVGDocument createFallbackPlaceholder() {
try {
String fallbackIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\">\n" +
" <rect x=\"1\" y=\"1\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"red\" stroke-width=\"2\"/>\n" +
" <line x1=\"1\" y1=\"1\" x2=\"15\" y2=\"15\" stroke=\"red\" stroke-width=\"2\"/>\n" +
" <line x1=\"1\" y1=\"15\" x2=\"15\" y2=\"1\" stroke=\"red\" stroke-width=\"2\"/>\n" +
"</svg>\n";
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
return (SVGDocument) factory.createDocument(null, new StringReader(fallbackIcon));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
protected void setImageSize(float docWidth, float docHeight) {
super.setImageSize((float) (docWidth * this.scale), (float) (docHeight * this.scale));
this.origDocWidth = docWidth;
this.origDocHeight = docHeight;
}
@Override
@NotNull
public BufferedImage createImage(int width, int height) {
return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
@Override
public void writeImage(@NotNull BufferedImage image, @Nullable TranscoderOutput output) {
this.image = image;
}
@Override
@NotNull
protected UserAgent createUserAgent() {
return new SVGAbstractTranscoderUserAgent() {
@Override
@NotNull
public SVGDocument getBrokenLinkDocument(@NotNull Element e, @NotNull String url, @NotNull String message) {
return createFallbackPlaceholder();
}
};
}
/**
* 开放访问权限
*/
@Override
public BridgeContext createBridgeContext(SVGOMDocument doc) {
return super.createBridgeContext(doc);
}
}

101
designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java

@ -1,101 +0,0 @@
package com.fr.base.svg;
import com.bulenkov.iconloader.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.os.OperatingSystem;
import org.jetbrains.annotations.NotNull;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicReference;
/**
* 获取系统Scale相关的工具类
* @author Yvan
* @version 10.0
* Created by Yvan on 2020/12/17
*/
public class SystemScaleUtils {
private static final AtomicReference<Boolean> JRE_HIDPI = new AtomicReference<>();
private static final String HI_DPI = "hidpi";
/**
* 判断是否支持高清
* @return
*/
public static boolean isJreHiDPIEnabled() {
if (JRE_HIDPI.get() != null) {
return JRE_HIDPI.get();
}
if (OperatingSystem.isMacos()) {
// 如果是mac os系统,直接返回true
return true;
}
if (OperatingSystem.isWindows() && StableUtils.getMajorJavaVersion() <= 8) {
// 如果是jdk8 + Windows系统,直接返回false
return false;
}
synchronized (JRE_HIDPI) {
if (JRE_HIDPI.get() != null) {
return JRE_HIDPI.get();
}
boolean result = false;
if (getBooleanProperty(HI_DPI, true)) {
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Class<?> sunGraphicsEnvironmentClass = Class.forName("sun.java2d.SunGraphicsEnvironment");
if (sunGraphicsEnvironmentClass.isInstance(ge)) {
try {
Method method = sunGraphicsEnvironmentClass.getDeclaredMethod("isUIScaleEnabled");
method.setAccessible(true);
result = (Boolean)method.invoke(ge);
}
catch (NoSuchMethodException e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
}
}
catch (Throwable ignore) {
}
}
JRE_HIDPI.set(result);
return result;
}
}
public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) {
final String value = System.getProperty(key);
return value == null ? defaultValue : Boolean.parseBoolean(value);
}
/**
* 获取系统Scale
* @return
*/
public static float sysScale() {
// 如果检测到是retina,直接返回2
if (UIUtil.isRetina()) {
return 2.0f;
}
float scale = 1.0f;
// 先判断是否支持高清,不支持代表此时是Windows + jdk8 的设计器,返回的scale值为1.0
if (isJreHiDPIEnabled()) {
// 获取屏幕图形设备对象
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (graphicsDevice != null) {
// 获取图形配置对象
GraphicsConfiguration configuration = graphicsDevice.getDefaultConfiguration();
if (configuration != null && configuration.getDevice().getType() != GraphicsDevice.TYPE_PRINTER) {
// 获取屏幕缩放率,Windows+jdk11环境下会得到用户设置的dpi值
scale = (float) configuration.getDefaultTransform().getScaleX();
}
}
}
return scale;
}
}

12
designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java

@ -0,0 +1,12 @@
package com.fr.common.exception;
/**
* @author hades
* @version 11.0
* Created by hades on 2021/12/7
*/
public interface ThrowableHandler {
boolean process(Throwable e);
}

29
designer-base/src/main/java/com/fr/design/DesignModelAdapter.java

@ -4,6 +4,7 @@ import com.fr.base.Parameter;
import com.fr.base.ParameterConfig;
import com.fr.base.TableData;
import com.fr.base.io.BaseBook;
import com.fr.base.param.ParameterSource;
import com.fr.data.TableDataSource;
import com.fr.data.operator.DataOperator;
import com.fr.design.file.HistoryTemplateListCache;
@ -19,8 +20,8 @@ import com.fr.stable.Filter;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.stable.js.WidgetName;
import com.fr.util.ParameterApplyHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -275,22 +276,28 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
protected void addTableDataParameters(Map<String, ParameterProvider> map, Filter<ParameterProvider> filter) {
Iterator<String> it = this.getBook().getTableDataNameIterator();
List<String> names = new ArrayList<>();
try {
// 清空下缓存
tableDataParametersMap.clear();
List<TableData> tableDatas = new ArrayList<>();
while (it.hasNext()) {
String name = it.next();
TableData tableData = this.getBook().getTableData(name);
ParameterProvider[] parameterProviders = DataOperator.getInstance().getTableDataParameters(tableData);
tableDatas.add(tableData);
names.add(name);
}
ParameterProvider[][] totalParameterProviders = DataOperator.getInstance().getTotalTableDataParameters(tableDatas);
tableDataParametersMap.clear();
for (int i = 0; i < totalParameterProviders.length; i++) {
ParameterProvider[] parameterProviders = totalParameterProviders[i];
if (filter != null) {
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter);
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter, null, ParameterSource.DEFAULT_SOURCE);
} else {
ParameterApplyHelper.addPara2Map(map, parameterProviders);
ParameterApplyHelper.addPara2Map(map, parameterProviders, null, ParameterSource.TEMPLATE_SOURCE);
}
tableDataParametersMap.put(name, parameterProviders);
tableDataParametersMap.put(names.get(i), parameterProviders);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
}
@ -353,9 +360,9 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
*/
private void updateParaMap(Map<String, ParameterProvider> map, ParameterProvider[] parameterProviders, Filter<ParameterProvider> filter) {
if (filter != null) {
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter);
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter, null, ParameterSource.DEFAULT_SOURCE);
} else {
ParameterApplyHelper.addPara2Map(map, parameterProviders);
ParameterApplyHelper.addPara2Map(map, parameterProviders, null, ParameterSource.DEFAULT_SOURCE);
}
}
@ -378,7 +385,7 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
protected void addGlobalParameters(Map<String, ParameterProvider> map) {
// 添加全局参数
Parameter[] glbParas = ParameterConfig.getInstance().getGlobalParameters();
ParameterApplyHelper.addPara2Map(map, glbParas);
ParameterApplyHelper.addPara2Map(map, glbParas, null, ParameterSource.GLOBAL_SOURCE);
}

193
designer-base/src/main/java/com/fr/design/DesignerCloudURLManager.java

@ -0,0 +1,193 @@
package com.fr.design;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.general.CloudCenter;
import com.fr.general.CloudCenterConfig;
import com.fr.general.http.HttpToolbox;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReaderHelper;
import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.javax.xml.stream.XMLStreamException;
import com.fr.third.org.apache.commons.io.FileUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by kerry on 2021/10/22
*/
public class DesignerCloudURLManager implements XMLable {
private static final String CLOUD_URL_INFO = "cloudUrl.info";
private static final String ROOT_XML_TAG = "CloudUrlInfoList";
private static final String CHILD_XML_TAG = "CloudUrlInfo";
private final Map<String, String> urlMap = new HashMap<>();
public static DesignerCloudURLManager getInstance() {
return DesignerCloudURLManager.HOLDER.singleton;
}
private final ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("TestCloudConnectThread"));
private volatile boolean testResult;
private static class HOLDER {
private static final DesignerCloudURLManager singleton = new DesignerCloudURLManager();
}
private DesignerCloudURLManager() {
loadURLXMLFile();
}
public String acquireUrlByKind(String key) {
String url = urlMap.getOrDefault(key, StringUtils.EMPTY);
if (StringUtils.isEmpty(url)) {
//本地缓存中为空时,直接从云中心获取,获取完成后异步更新本地缓存文件
String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY);
executorService.submit(() -> {
updateURLXMLFile(key, latestUrl);
});
return latestUrl;
}
//本地缓存不为空时,直接返回对应 url,同时异步更新
executorService.submit(() -> {
String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY);
updateURLXMLFile(key, latestUrl);
});
return url;
}
private synchronized void updateURLXMLFile(String key, String url) {
if (StringUtils.isNotEmpty(url) && (!urlMap.containsKey(key) || !url.equals(urlMap.get(key)))) {
urlMap.put(key, url);
saveURLXMLFile();
}
}
public void testConnect() {
executorService.submit(() -> {
testResult = isOnline();
});
}
public boolean isConnected() {
return testResult;
}
public boolean isOnline() {
if (CloudCenterConfig.getInstance().isOnline()) {
String ping = acquireUrlByKind("ping");
if (StringUtils.isNotEmpty(ping)) {
try {
return StringUtils.isEmpty(HttpToolbox.get(ping));
} catch (Exception ignore) {
}
}
}
return false;
}
/**
* 加载本地 url 管理文件
*/
private void loadURLXMLFile() {
if (!getInfoFile().exists()) {
return;
}
XMLableReader reader = null;
try (InputStream in = new FileInputStream(getInfoFile())) {
// XMLableReader 还是应该考虑实现 Closable 接口的,这样就能使用 try-with 语句了
reader = XMLReaderHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER);
if (reader == null) {
return;
}
reader.readXMLObject(this);
} catch (FileNotFoundException e) {
// do nothing
} catch (XMLStreamException | IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (XMLStreamException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
private File getInfoFile() {
File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), CLOUD_URL_INFO));
try {
if (!file.exists()) {
file.createNewFile();
}
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
return file;
}
/**
* 保存到本地 URL 管理文件中存放在 .Finereport110
*/
void saveURLXMLFile() {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLTools.writeOutputStreamXML(this, out);
out.flush();
out.close();
String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);
FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8);
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage());
}
}
@Override
public void readXML(XMLableReader reader) {
String tagName = reader.getTagName();
if (tagName.equals(CHILD_XML_TAG)) {
String key = reader.getAttrAsString("key", StringUtils.EMPTY);
String value = reader.getAttrAsString("url", StringUtils.EMPTY);
this.urlMap.put(key, value);
}
}
@Override
public void writeXML(XMLPrintWriter xmlPrintWriter) {
xmlPrintWriter.startTAG(ROOT_XML_TAG);
Iterator<Map.Entry<String, String>> iterable = urlMap.entrySet().iterator();
while (iterable.hasNext()) {
Map.Entry<String, String> entry = iterable.next();
xmlPrintWriter.startTAG(CHILD_XML_TAG).attr("key", entry.getKey()).attr("url", entry.getValue()).end();
}
xmlPrintWriter.end();
}
@Override
public Object clone() throws CloneNotSupportedException {
return null;
}
}

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

@ -4,8 +4,11 @@
package com.fr.design;
import com.fr.base.BaseXMLUtils;
import com.fr.base.OptimizeUtil;
import com.fr.base.Utils;
import com.fr.collections.api.Callback;
import com.fr.design.actions.help.alphafine.AlphaFineConfigManager;
import com.fr.design.carton.SwitchForSwingChecker;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.dialog.ErrorDialog;
@ -19,14 +22,18 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.locale.impl.ProductImproveMark;
import com.fr.design.login.DesignerLoginType;
import com.fr.design.login.config.DesignerLoginConfigManager;
import com.fr.design.mainframe.ComponentReuseNotifyUtil;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.mainframe.simple.SimpleDesignerConfig;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.notification.SnapChatConfig;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.port.DesignerPortContext;
import com.fr.design.style.color.ColorSelectConfigManager;
import com.fr.design.update.push.DesignerPushUpdateConfigManager;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.DesignerPort;
import com.fr.env.detect.base.EnvDetectorConfig;
import com.fr.exit.DesignerExiter;
import com.fr.file.FILEFactory;
import com.fr.general.ComparatorUtils;
@ -36,6 +43,12 @@ import com.fr.general.SupportLocale;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.general.xml.GeneralXMLTools;
import com.fr.general.xml.async.AsyncXmlElement;
import com.fr.general.xml.async.AsyncXmlReadable;
import com.fr.general.xml.async.SimpleXmlElement;
import com.fr.general.xml.async.XmlElement;
import com.fr.general.xml.async.XmlException;
import com.fr.general.xml.async.XmlInitialFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.log.LogHandler;
import com.fr.stable.CommonUtils;
@ -52,7 +65,11 @@ import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.apache.log4j.FileAppender;
import com.fr.start.common.DesignerStartupConfig;
import com.fr.start.common.DesignerStartupPool;
import com.fr.third.apache.logging.log4j.core.appender.FileAppender;
import com.fr.third.apache.logging.log4j.core.layout.PatternLayout;
import com.fr.third.org.apache.commons.io.FileUtils;
import com.fr.third.org.apache.commons.io.FilenameUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.WorkContextCallback;
@ -79,37 +96,50 @@ import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* The manager of Designer GUI.
* 下面的作者日期都是随手写的具体作者已经无法考究
*
* @author anonymous
* @version 11.0
* created by anonymous on 2002/11/08
*/
public class DesignerEnvManager implements XMLReadable, XMLWriter {
public class DesignerEnvManager implements XMLReadable, XMLWriter, AsyncXmlReadable {
private static final int MAX_SHOW_NUM = 10;
private static final String VERSION_80 = "80";
private static final String VERSION_90 = "90";
private static final String VERSION100 = "100";
private static final int CACHINGTEMPLATE_LIMIT = 5;
private static final String WEB_NAME = "webapps";
public static final int LAYOUT_TEMPLATE_SIMPLE_STYLE = 0;
public static final int LAYOUT_TEMPLATE_REAL_STYLE = 1;
/**
* 指定默认工作空间
*/
public static final String DEFAULT_WORKSPACE_PATH = "fr.designer.workspace.default";
public static final String LAST_EAST_REGION_LAYOUT = "LastEastRegionLayout";
public static final String LAST_WEST_REGION_LAYOUT = "LastWestRegionLayout";
private static DesignerEnvManager designerEnvManager; // gui.
private String activationKey = null;
private String logLocation = null;
private Rectangle windowBounds = null; // window bounds.
private String DialogCurrentDirectory = null;
private String CurrentDirectoryPrefix = null;
private Map<String, List<String>> recentOpenedFileListMap = new HashMap<>();
private List<String> tempRecentOpenedFilePathList = new ArrayList<String>();
private XmlElement<Map<String, List<String>>> recentOpenedMapping = SimpleXmlElement.of(recentOpenedFileListMap);
private boolean showPaintToolBar = true;
private int maxNumberOrPreviewRow = 200;
// name和Env的键值对
private Map<String, DesignerWorkspaceInfo> nameEnvMap = new ListMap<>();
// marks: 当前报表服务器名字
private String curEnvName = null;
private XmlElement<EnvConfiguration> envConfig = SimpleXmlElement.of(new EnvConfiguration());
private boolean showProjectPane = true;
private boolean showDataPane = true;
//p:这是当前选择的数据库连接的名字,这个在新建数据源的时候用到.
@ -163,10 +193,16 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private boolean embedServerLazyStartup = false;
//最近使用的颜色
private ColorSelectConfigManager configManager = new ColorSelectConfigManager();
/**
* 环境检测配置
*/
private EnvDetectorConfig envDetectorConfig = EnvDetectorConfig.getInstance();
/**
* alphafine
*/
private AlphaFineConfigManager alphaFineConfigManager = AlphaFineConfigManager.getInstance();
private XmlElement<AlphaFineConfigManager> alphaFineConfigManager = SimpleXmlElement.of(AlphaFineConfigManager.getInstance());
/**
* 阅后即焚的配置项
@ -176,7 +212,11 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private DesignerPushUpdateConfigManager designerPushUpdateConfigManager = DesignerPushUpdateConfigManager.getInstance();
private VcsConfigManager vcsConfigManager = VcsConfigManager.getInstance();
private DesignerStartupConfig designerStartupConfig = DesignerStartupConfig.getInstance();
private SwitchForSwingChecker switchForSwingChecker = SwitchForSwingChecker.getInstance();
public static final String CAS_CERTIFICATE_PATH = "certificatePath";
public static final String CAS_CERTIFICATE_PASSWORD = "certificatePass";
@ -205,6 +245,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private boolean showTemplateMissingPlugin = true;
private int layoutTemplateStyle = LAYOUT_TEMPLATE_SIMPLE_STYLE;
private boolean useOptimizedUPM4Adapter;
private boolean propertiesUsable;
private XmlElement<SimpleDesignerConfig> fvsDesignerConfig = SimpleXmlElement.of(SimpleDesignerConfig.getInstance("FvsDesignerConfig"));
/**
* DesignerEnvManager.
*/
@ -217,13 +265,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
designerEnvManager = new DesignerEnvManager();
//REPORT-15332有一个国际化调用比较早,需要在这边就设置好locale,由于后台GeneralContext默认是China
GeneralContext.setLocale(designerEnvManager.getLanguage());
try {
XMLTools.readFileXML(designerEnvManager, designerEnvManager.getDesignerEnvFile());
} catch (FileNotFoundException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
XmlHandler.Self.handle(e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
if (!asyncInitEnvManager()) {
// 如果异步读取失败, 则恢复原来的逻辑
compatibleInitEnvManager();
}
// james:如果没有env定义,要设置一个默认的
@ -240,13 +285,47 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
return designerEnvManager;
}
private static void compatibleInitEnvManager() {
try {
XMLTools.readFileXML(designerEnvManager, designerEnvManager.getDesignerEnvFile());
} catch (FileNotFoundException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
XmlHandler.Self.handle(e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
/**
* 异步初始化环境管理, 提供配置, 帮助处理预期外的问题
* 1-当优化开启时才走异步逻辑
* 2-如果异步执行中出错则返回异常 false, 否则返回 true
*
* @return /
*/
private static boolean asyncInitEnvManager() {
AtomicBoolean noEx = new AtomicBoolean(false);
OptimizeUtil.open(DesignerEnvManager.class.getSimpleName().toLowerCase(), OptimizeUtil.Module.COMMON, () -> {
try {
designerEnvManager.initElements(designerEnvManager.getDesignerEnvFile());
noEx.set(true);
} catch (Throwable retryEx) {
FineLoggerFactory.getLogger().debug("try async init DesignerEnvManager failed", retryEx);
}
});
return noEx.get();
}
public ColorSelectConfigManager getColorConfigManager() {
return this.configManager;
}
public static void checkNameEnvMap() {
if (designerEnvManager == null || designerEnvManager.nameEnvMap.size() > 0) {
if (designerEnvManager == null || designerEnvManager.getNameEnvMap().size() > 0) {
return;
}
String installHome = StableUtils.getInstallHome();
@ -319,18 +398,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
if (!new File(fileName).exists()) {
StableUtils.makesureFileExist(new File(fileName));
}
LogHandler handler = new LogHandler<FileAppender>() {
final FileAppender appender = new FileAppender(
new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"),
fileName
);
LogHandler<FileAppender> handler = new LogHandler<FileAppender>() {
final FileAppender appender = FileAppender.newBuilder().
setName(FileAppender.class.getSimpleName()).
setLayout(PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n").build()).
withFileName(fileName).build();
@Override
public FileAppender getHandler() {
return appender;
}
};
handler.getHandler().start();
FineLoggerFactory.getLogger().addLogAppender(handler);
} catch (SecurityException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
@ -411,15 +490,21 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private void compatibilityPrevVersion(File prevEnvFile) {
try {
XMLTools.readFileXML(designerEnvManager, prevEnvFile);
clearOldVersionDesignerEnvProperties();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
// 清空前一个版本中的工作目录和最近打开
nameEnvMap = new ListMap<String, DesignerWorkspaceInfo>();
curEnvName = null;
getEnvConfig().setNameEnvMap(new ListMap<>());
getEnvConfig().setCurEnvName(null);
designerEnvManager.saveXMLFile();
}
private void clearOldVersionDesignerEnvProperties() {
SnapChatConfig snapChatConfig = designerEnvManager.getSnapChatConfig();
snapChatConfig.resetRead(ComponentReuseNotifyUtil.COMPONENT_SNAP_CHAT_KEY);
}
public static void setEnvFile(File envFile) {
DesignerEnvManager.envFile = envFile;
}
@ -427,12 +512,35 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private static File envFile = null;
private File getEnvFile() {
checkDebugStart();
if (envFile == null) {
envFile = new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "Env.xml");
}
return envFile;
}
/**
* 在VM options里加入-Ddebug=true激活
*/
private static void checkDebugStart() {
if (ComparatorUtils.equals("true", System.getProperty("debug"))) {
setDebugEnv();
}
}
/**
* 端口改一下环境配置文件改一下便于启动两个设计器进行对比调试
*/
private static void setDebugEnv() {
DesignUtils.setPort(DesignerPort.getInstance().getDebugMessagePort());
DesignerEnvManager.setEnvFile(new File(StableUtils.pathJoin(
ProductConstants.getEnvHome(),
ProductConstants.APP_NAME + "Env_debug.xml"
)));
}
/**
* 是否启用了https
*
@ -550,7 +658,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
String installHome = StableUtils.getInstallHome();
String defaultenvPath = getDefaultenvPath(installHome);
defaultenvPath = new File(defaultenvPath).getPath();
Iterator<Entry<String, DesignerWorkspaceInfo>> entryIt = nameEnvMap.entrySet().iterator();
Iterator<Entry<String, DesignerWorkspaceInfo>> entryIt = getNameEnvMap().entrySet().iterator();
while (entryIt.hasNext()) {
Entry<String, DesignerWorkspaceInfo> entry = entryIt.next();
DesignerWorkspaceInfo env = entry.getValue();
@ -571,8 +679,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
String installHome = StableUtils.getInstallHome();
String defaultenvPath = getDefaultenvPath(installHome);
defaultenvPath = new File(defaultenvPath).getPath();
if (nameEnvMap.size() >= 0) {
Iterator<Entry<String, DesignerWorkspaceInfo>> entryIt = nameEnvMap.entrySet().iterator();
if (getNameEnvMap().size() >= 0) {
Iterator<Entry<String, DesignerWorkspaceInfo>> entryIt = getNameEnvMap().entrySet().iterator();
while (entryIt.hasNext()) {
Entry<String, DesignerWorkspaceInfo> entry = entryIt.next();
DesignerWorkspaceInfo env = entry.getValue();
@ -653,6 +761,22 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.showTemplateMissingPlugin = showTemplateMissingPlugin;
}
public boolean isUseOptimizedUPM4Adapter() {
return useOptimizedUPM4Adapter;
}
public void setUseOptimizedUPM4Adapter(boolean useOptimizedUPM4Adapter) {
this.useOptimizedUPM4Adapter = useOptimizedUPM4Adapter;
}
public boolean isPropertiesUsable() {
return this.propertiesUsable;
}
public void setPropertiesUsable(boolean propertiesUsable) {
this.propertiesUsable = propertiesUsable;
}
/**
* 知否自动备份
*
@ -774,6 +898,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
designerPushUpdateConfigManager.setAutoPushUpdateEnabled(autoPushUpdateEnabled);
}
public boolean isCloudAnalyticsDelay() {
return designerPushUpdateConfigManager.isCloudAnalyticsDelay();
}
public void setCloudAnalyticsDelay(boolean cloudAnalyticsDelay) {
designerPushUpdateConfigManager.setCloudAnalyticsDelay(cloudAnalyticsDelay);
}
/**
* 设计器登录相关配置
*/
@ -881,6 +1013,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
designerLoginConfigManager.setPluginRemindOnFirstLaunch(pluginRemindOnFirstLaunch);
}
public boolean isUseOldVersionLogin() {
return designerLoginConfigManager.isUseOldVersionLogin();
}
public void setUseOldVersionLogin(boolean useOldVersionLogin) {
designerLoginConfigManager.setUseOldVersionLogin(useOldVersionLogin);
}
/**
* 内置服务器是否使用时启动
*
@ -921,19 +1061,31 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
public void setLanguage(Locale locale) {
this.language = locale;
}
public boolean isStartupPageEnabled() {
return this.designerStartupConfig.isEnabled();
}
public void setStartupPageEnabled(boolean enabled) {
this.designerStartupConfig.setEnabled(enabled);
}
public SimpleDesignerConfig getFvsDesignerConfig() {
return fvsDesignerConfig.getValue();
}
/**
* 返回环境名称迭代器
*/
public Iterator<String> getEnvNameIterator() {
return this.nameEnvMap.keySet().iterator();
return this.getNameEnvMap().keySet().iterator();
}
/**
* 根据名称返回环境
*/
public DesignerWorkspaceInfo getWorkspaceInfo(String name) {
return this.nameEnvMap.get(name);
return this.getNameEnvMap().get(name);
}
/**
@ -944,7 +1096,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
*/
public void putEnv(String name, DesignerWorkspaceInfo info) {
this.nameEnvMap.put(name, info);
this.getNameEnvMap().put(name, info);
}
/**
@ -953,14 +1105,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
* @param name 环境的名字
*/
public void removeEnv(String name) {
this.nameEnvMap.remove(name);
this.getNameEnvMap().remove(name);
}
/**
* 清除全部环境
*/
public void clearAllEnv() {
this.nameEnvMap.clear();
this.getNameEnvMap().clear();
}
/**
@ -982,14 +1134,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
* 返回当前环境的名称.
*/
public String getCurEnvName() {
return this.curEnvName;
return getEnvConfig().getCurEnvName();
}
/**
* 设置当前环境的名称
*/
public void setCurEnvName(String envName) {
this.curEnvName = envName;
getEnvConfig().setCurEnvName(envName);
}
/**
@ -1040,23 +1192,26 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
public void setCurrentDirectoryPrefix(String prefix) {
this.CurrentDirectoryPrefix = prefix;
}
/**
* 返回最近打开的文件路径列表
*/
public List<String> getRecentOpenedFilePathList() {
if (StringUtils.isEmpty(getCurEnvName())) {
public List<String> getRecentOpenedFilePathList4Env(String envName) {
if (StringUtils.isEmpty(envName)) {
return tempRecentOpenedFilePathList;
} else {
if (!recentOpenedFileListMap.containsKey(getCurEnvName())) {
recentOpenedFileListMap.put(getCurEnvName(), tempRecentOpenedFilePathList);
if (!recentOpenedMapping.getValue().containsKey(envName)) {
recentOpenedMapping.getValue().put(envName, tempRecentOpenedFilePathList);
}
}
return recentOpenedMapping.getValue().get(envName);
}
return recentOpenedFileListMap.get(getCurEnvName());
/**
* 返回最近打开的文件路径列表
*/
public List<String> getRecentOpenedFilePathList() {
return this.getRecentOpenedFilePathList4Env(getCurEnvName());
}
/**
@ -1652,11 +1807,11 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
public AlphaFineConfigManager getAlphaFineConfigManager() {
return alphaFineConfigManager;
return alphaFineConfigManager.getValue();
}
public void setAlphaFineConfigManager(AlphaFineConfigManager alphaFineConfigManager) {
this.alphaFineConfigManager = alphaFineConfigManager;
this.alphaFineConfigManager.setValue(alphaFineConfigManager);
}
public boolean isImageCompress() {
@ -1691,6 +1846,108 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.openDebug = openDebug;
}
public int getLayoutTemplateStyle() {
return layoutTemplateStyle;
}
public void setLayoutTemplateStyle(int layoutTemplateStyle) {
this.layoutTemplateStyle = layoutTemplateStyle;
}
@Override
public void initElements(File xmlFile) throws XmlException {
try {
backupOldXmlFile();
XmlInitialFactory xmlInitialFactory = XmlInitialFactory.create(xmlFile);
xmlInitialFactory
.init("XMLVersion", DesignerEnvManager.this::readXMLVersion)
.init("Attributes", DesignerEnvManager.this::readAttributes)
.init("ReportPaneAttributions", DesignerEnvManager.this::readReportPaneAttributions)
.init("RecentOpenedFilePath", (e) -> {
this.recentOpenedMapping = AsyncXmlElement.of(DesignerStartupPool.common(), () -> {
DesignerEnvManager.this.readRecentOpenFileList0(e);
return recentOpenedFileListMap;
}).callback(new Callback<Map<String, List<String>>>() {
@Override
public void exec(Map<String, List<String>> stringListMap) {
checkRecentOpenedFileNum();
}
});
})
.init("EnvConfigMap", (e) -> {
final EnvConfiguration previousConfig = this.envConfig.getValue();
this.envConfig = AsyncXmlElement.of(DesignerStartupPool.common(), () -> {
DesignerEnvManager.this.readEnvConfigMap(e, previousConfig);
return previousConfig;
});
})
.init("LogLocation", DesignerEnvManager.this::readLogLocation)
.init("Language", DesignerEnvManager.this::readLanguage)
.init("JettyServerPort", DesignerEnvManager.this::readJettyPort)
.init("PLengthUnit", DesignerEnvManager.this::readPageLengthUnit)
.init("RLengthUnit", DesignerEnvManager.this::readReportLengthUnit)
.init("LastOpenFilePath", DesignerEnvManager.this::readLastOpenFile)
.init("EncryptionKey", DesignerEnvManager.this::readEncrytionKey)
.init("jdkHome", (e) -> this.jdkHome = e.getElementValue())
.init("lastBBSTime", DesignerEnvManager.this::readLastBBSTime)
.init("lastBBSNewsTime", DesignerEnvManager.this::readLastBBSNewsTime)
.init("ActivationKey", DesignerEnvManager.this::readActiveKey)
.init("status", DesignerEnvManager.this::readActiveStatus)
.init(CAS_PARAS, DesignerEnvManager.this::readHttpsParas)
.init(EnvDetectorConfig.XML_TAG, DesignerEnvManager.this::readEnvDetectorConfig)
.init(DesignerStartupConfig.XML_TAG, DesignerEnvManager.this::readStartupConfig)
.init("AlphaFineConfigManager", (e) -> {
this.alphaFineConfigManager = AsyncXmlElement.of(DesignerStartupPool.common(), () -> {
AlphaFineConfigManager config = AlphaFineConfigManager.getInstance();
e.readXMLObject(config);
return config;
});
})
.init("RecentColors", DesignerEnvManager.this::readRecentColor)
.init("OpenDebug", DesignerEnvManager.this::readOpenDebug)
.init(ComponentReuseNotificationInfo.XML_TAG, DesignerEnvManager.this::readComponentReuseNotificationInfo)
.init(DesignerPushUpdateConfigManager.XML_TAG, DesignerEnvManager.this::readDesignerPushUpdateAttr)
.init(VcsConfigManager.XML_TAG, DesignerEnvManager.this::readVcsAttr)
.init(DesignerPort.XML_TAG, DesignerEnvManager.this::readDesignerPort)
.init(SnapChatConfig.XML_TAG, DesignerEnvManager.this::readSnapChatConfig)
.init(DesignerLoginConfigManager.XML_TAG, DesignerEnvManager.this::readDesignerLoginAttr)
.init(fvsDesignerConfig.getValue().getName(), (e) -> {
SimpleDesignerConfig config = this.fvsDesignerConfig.getValue();
this.fvsDesignerConfig = AsyncXmlElement.of(() -> {
e.readXMLObject(config);
return config;
});
})
.init(SwitchForSwingChecker.XML_TAG, DesignerEnvManager.this::readSwitchForSwingCheckerAttr)
.init(LAST_WEST_REGION_LAYOUT, DesignerEnvManager.this::readLastWestRegionLayout)
.init(LAST_EAST_REGION_LAYOUT, DesignerEnvManager.this::readLastEastRegionLayout);
} catch (Exception e) {
throw new XmlException(e);
}
}
/**
* 备份老的 xml 文件, 防止第一次修改存在问题
* 但是只备份一次其他都走老逻辑
*/
private void backupOldXmlFile() {
try {
File oldFile = getEnvFile();
String newFilePath = ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "Env_backup.xml";
File newFile = new File(newFilePath);
if (newFile.exists()) {
return;
}
if (oldFile.exists()) {
FileUtils.copyFile(oldFile, newFile);
}
} catch (Exception ignored) {
}
}
/**
* Read XML.<br>
* The method will be invoked when read data from XML file.<br>
@ -1740,6 +1997,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
readActiveStatus(reader);
} else if (ComparatorUtils.equals(CAS_PARAS, name)) {
readHttpsParas(reader);
} else if (name.equals(EnvDetectorConfig.XML_TAG)) {
readEnvDetectorConfig(reader);
} else if (name.equals(DesignerStartupConfig.XML_TAG)) {
readStartupConfig(reader);
} else if (name.equals("AlphaFineConfigManager")) {
readAlphaFineAttr(reader);
} else if (name.equals("RecentColors")) {
@ -1750,7 +2011,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
readComponentReuseNotificationInfo(reader);
} else if (name.equals(DesignerPushUpdateConfigManager.XML_TAG)) {
readDesignerPushUpdateAttr(reader);
} else if (name.equals(vcsConfigManager.XML_TAG)) {
} else if (name.equals(VcsConfigManager.XML_TAG)) {
readVcsAttr(reader);
} else if (DesignerPort.XML_TAG.equals(name)) {
readDesignerPort(reader);
@ -1758,6 +2019,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
readSnapChatConfig(reader);
} else if (name.equals(DesignerLoginConfigManager.XML_TAG)) {
readDesignerLoginAttr(reader);
} else if (name.equals(fvsDesignerConfig.getValue().getName())) {
readFvsDesignerConfig(reader);
} else if (name.equals(SwitchForSwingChecker.XML_TAG)) {
readSwitchForSwingCheckerAttr(reader);
} else {
readLayout(reader, name);
}
@ -1774,7 +2039,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
private void readAlphaFineAttr(XMLableReader reader) {
reader.readXMLObject(this.alphaFineConfigManager = AlphaFineConfigManager.getInstance());
AlphaFineConfigManager config = AlphaFineConfigManager.getInstance();
reader.readXMLObject(config);
this.alphaFineConfigManager = SimpleXmlElement.of(config);
}
private void readEnvDetectorConfig(XMLableReader reader) {
reader.readXMLObject(this.envDetectorConfig);
}
private void readStartupConfig(XMLableReader reader) {
reader.readXMLObject(this.designerStartupConfig);
}
private void readHttpsParas(XMLableReader reader) {
@ -1791,9 +2067,9 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private void readLayout(XMLableReader reader, String name) {
if ("LastEastRegionLayout".equals(name)) {
if (LAST_EAST_REGION_LAYOUT.equals(name)) {
this.readLastEastRegionLayout(reader);
} else if ("LastWestRegionLayout".equals(name)) {
} else if (LAST_WEST_REGION_LAYOUT.equals(name)) {
this.readLastWestRegionLayout(reader);
}
}
@ -1860,7 +2136,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
this.setEmbedServerLazyStartup(reader.getAttrAsBoolean("embedServerLazyStartup", false));
this.setShowTemplateMissingPlugin(reader.getAttrAsBoolean("showTemplateMissingPlugin", true));
this.setUseOptimizedUPM4Adapter(reader.getAttrAsBoolean("useOptimizedUPM4Adapter", SupportOSImpl.MACOS_12_VERSION_ADAPTER.support()));
this.setPropertiesUsable(reader.getAttrAsBoolean("propertiesUsable", false));
this.setShowServerDatasetAuthTip(reader.getAttrAsBoolean("showServerDatasetAuthTip", true));
this.setLayoutTemplateStyle(reader.getAttrAsInt("layoutTemplateStyle", LAYOUT_TEMPLATE_SIMPLE_STYLE));
}
private void readReportPaneAttributions(XMLableReader reader) {
@ -1885,6 +2164,40 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.setPaginationLineColor(new Color(Integer.parseInt(tmpVal)));
}
}
private void readEnvConfigMap(XMLableReader reader, EnvConfiguration envConfigs) {
String currentEnv = reader.getAttrAsString("currentEnv", StringUtils.EMPTY);
envConfigs.setCurEnvName(currentEnv);
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader reader) {
if (reader.isAttr()) {
envConfigs.getNameEnvMap().clear();
} else if (reader.isChildNode()) {
String tagName = reader.getTagName();
if ("EnvConfigElement".equals(tagName)) {
final String name = reader.getAttrAsString("name", StringUtils.EMPTY);
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader reader) {
if (reader.isChildNode()) {
String tagName = reader.getTagName();
if (DesignerWorkspaceType.Local.toString().equals(tagName)) {
LocalDesignerWorkspaceInfo envConfig = (LocalDesignerWorkspaceInfo) GeneralXMLTools.readXMLable(reader);
envConfigs.getNameEnvMap().put(name, envConfig);
} else if (DesignerWorkspaceType.Remote.toString().equals(tagName)) {
RemoteDesignerWorkspaceInfo envConfig = (RemoteDesignerWorkspaceInfo) GeneralXMLTools.readXMLable(reader);
envConfigs.getNameEnvMap().put(name, envConfig);
}
}
}
});
}
}
}
});
}
private void readEnvConfigMap(XMLableReader reader) {
String currentEnv = reader.getAttrAsString("currentEnv", StringUtils.EMPTY);
@ -1918,8 +2231,15 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
});
}
private void readRecentOpenFileList(XMLableReader reader) {
readRecentOpenFileList0(reader);
checkRecentOpenedFileNum();
}
private void readRecentOpenFileList0(XMLableReader reader) {
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader reader) {
@ -1951,7 +2271,6 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
}
});
checkRecentOpenedFileNum();
}
private void readDesignerPushUpdateAttr(XMLableReader reader) {
@ -1966,6 +2285,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
reader.readXMLObject(DesignerPort.getInstance());
}
private void readSwitchForSwingCheckerAttr(XMLableReader reader) {
reader.readXMLObject(switchForSwingChecker);
}
/**
* Write XML.<br>
* The method will be invoked when save data to XML file.<br>
@ -1987,6 +2310,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writeActiveStatus(writer);
writeHttpsParas(writer);
writeAlphaFineAttr(writer);
writeEnvDetectorConfig(writer);
writeStartupConfig(writer);
writeRecentColor(writer);
writeOpenDebug(writer);
writeDesignerPushUpdateAttr(writer);
@ -1995,6 +2320,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writeSnapChatConfig(writer);
writeComponentReuseNotificationInfo(writer);
writeDesignerLoginAttr(writer);
writeFvsDesignerConfig(writer);
writeSwitchForSwingChecker(writer);
writer.end();
}
@ -2013,7 +2340,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private void writeAlphaFineAttr(XMLPrintWriter writer) {
if (this.alphaFineConfigManager != null) {
this.alphaFineConfigManager.writeXML(writer);
this.alphaFineConfigManager.getValue().writeXML(writer);
}
}
@ -2030,6 +2357,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writer.end();
}
}
private void writeEnvDetectorConfig(XMLPrintWriter writer) {
if (this.envDetectorConfig != null) {
this.envDetectorConfig.writeXML(writer);
}
}
private void writeStartupConfig(XMLPrintWriter writer) {
if (this.designerStartupConfig != null) {
this.designerStartupConfig.writeXML(writer);
}
}
//写入uuid
private void writeUUID(XMLPrintWriter writer) {
@ -2078,10 +2417,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writer.end();
writer.startTAG("EnvConfigMap");
if (this.curEnvName != null) {
writer.attr("currentEnv", this.curEnvName);
if (this.getCurEnvName() != null) {
writer.attr("currentEnv", this.getCurEnvName());
}
for (Entry<String, DesignerWorkspaceInfo> entry : nameEnvMap.entrySet()) {
for (Entry<String, DesignerWorkspaceInfo> entry : getNameEnvMap().entrySet()) {
writer.startTAG("EnvConfigElement").attr("name", entry.getKey());
DesignerWorkspaceInfo envConfig = entry.getValue();
GeneralXMLTools.writeXMLable(writer, envConfig, envConfig.getType().toString());
@ -2134,7 +2473,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
if (!this.isShowTemplateMissingPlugin()) {
writer.attr("showTemplateMissingPlugin", this.isShowTemplateMissingPlugin());
}
writer.attr("layoutTemplateStyle", this.getLayoutTemplateStyle());
writer.attr("showServerDatasetAuthTip", this.isShowServerDatasetAuthTip());
writer.attr("useOptimizedUPM4Adapter", this.isUseOptimizedUPM4Adapter());
writer.attr("propertiesUsable", this.isPropertiesUsable());
writer.end();
}
@ -2286,6 +2628,21 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.designerLoginConfigManager.writeXML(writer);
}
private void readFvsDesignerConfig(XMLableReader reader) {
SimpleDesignerConfig config = fvsDesignerConfig.getValue();
reader.readXMLObject(config);
fvsDesignerConfig = SimpleXmlElement.of(config);
}
private void writeFvsDesignerConfig(XMLPrintWriter writer) {
this.fvsDesignerConfig.getValue().writeXML(writer);
}
private void writeSwitchForSwingChecker(XMLPrintWriter writer) {
this.switchForSwingChecker.writeXML(writer);
}
enum XmlHandler {
Self;
@ -2310,4 +2667,43 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
DesignerExiter.getInstance().execute();
}
}
public SnapChatConfig getSnapChatConfig() {
return snapChatConfig;
}
private EnvConfiguration getEnvConfig() {
return envConfig.getValue();
}
private Map<String, DesignerWorkspaceInfo> getNameEnvMap() {
return getEnvConfig().getNameEnvMap();
}
private static class EnvConfiguration {
// name和Env的键值对
private Map<String, DesignerWorkspaceInfo> nameEnvMap = new ListMap<>();
// marks: 当前报表服务器名字
private String curEnvName = null;
public Map<String, DesignerWorkspaceInfo> getNameEnvMap() {
return nameEnvMap;
}
public void setNameEnvMap(Map<String, DesignerWorkspaceInfo> nameEnvMap) {
this.nameEnvMap = nameEnvMap;
}
public String getCurEnvName() {
return curEnvName;
}
public void setCurEnvName(String curEnvName) {
this.curEnvName = curEnvName;
}
}
}

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

@ -1,7 +1,8 @@
package com.fr.design;
import com.fr.common.report.ReportState;
import com.fr.decision.webservice.v10.plugin.helper.PluginErrorRemindHandler;
import com.fr.design.mainframe.manager.clip.TemplateTreeClipboard;
import com.fr.design.plugin.remind.PluginErrorDesignReminder;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
@ -13,6 +14,7 @@ import com.fr.design.env.DesignerWorkspaceType;
import com.fr.design.env.RemoteDesignerWorkspaceInfo;
import com.fr.design.env.RemoteWorkspace;
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;
@ -34,7 +36,6 @@ import com.fr.process.engine.core.FineProcessContext;
import com.fr.rpc.Result;
import com.fr.stable.AssistUtils;
import com.fr.stable.StringUtils;
import com.fr.env.PluginErrorRemindDialog;
import com.fr.start.server.ServerTray;
import com.fr.workspace.WorkContext;
import com.fr.workspace.WorkContextCallback;
@ -138,7 +139,7 @@ public class EnvChangeEntrance {
if (template != null) {
template.refreshToolArea();
}
pluginErrorRemind();
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
} catch (Exception exception) {
// 失败的处理
WorkspaceExceptionHandler.getInstance().handleInSwitch(exception, selectedEnv);
@ -150,6 +151,8 @@ public class EnvChangeEntrance {
model.envChanged();
}
NotificationCenter.getInstance().clearAllNotifications();
//切换环境后,清空粘贴板里面的内容
TemplateTreeClipboard.getInstance().reset();
return true;
}
@ -244,28 +247,6 @@ public class EnvChangeEntrance {
}
}
/**
* 插件启动错误信息提示
*/
public void pluginErrorRemind() {
if (!WorkContext.getCurrent().isLocal()) {
return;
}
String content = PluginErrorRemindHandler.pluginErrorContent();
if (StringUtils.isNotEmpty(content)) {
// 该操作需要在当前awt操作之后执行,使用SwingUtilities.invokeLater将其置于awt操作对列末尾
// 若使用UIUtil.invokeLaterIfNeeded,会立即执行,影响其他UI操作
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PluginErrorRemindDialog dialog = new PluginErrorRemindDialog(DesignerContext.getDesignerFrame(), content);
dialog.setVisible(true);
}
});
}
}
/**
* 判断是否需要做版本验证判断依据为
* 1选择的环境为远程环境
@ -388,6 +369,11 @@ public class EnvChangeEntrance {
@Override
public void doOk() {
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true, SwingUtilities.getWindowAncestor(envListPane));
if (!saveSomeTemplatePane.showSavePane()) {
// 用户取消保存时,取消切换目录操作
return;
}
boolean changeResult = envListOkAction(envListPane, PopTipStrategy.LATER);
// 切换完成后清理密码
updateNotRememberPwdEnv();
@ -427,7 +413,9 @@ public class EnvChangeEntrance {
DesignerExiter.getInstance().execute();
} else {
updateNotRememberPwdEnv();
VersionCheckUtils.showVersionCheckDialog(envListPane.getSelectedName());
if (DesignerContext.getDesignerFrame().isVisible()) {
VersionCheckUtils.showVersionCheckDialog(envListPane.getSelectedName());
}
}
}

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

@ -114,7 +114,7 @@ public class ExtraDesignClassManager extends AbstractExtraClassManager implement
for (ParameterWidgetOptionProvider provider : set) {
WidgetOption option = WidgetOptionFactory.createByWidgetClass(
provider.nameForWidget(),
IOUtils.readIcon(provider.iconPathForWidget()),
provider.iconPathForWidget(),
provider.classForWidget()
);
result.add(option);
@ -186,7 +186,7 @@ public class ExtraDesignClassManager extends AbstractExtraClassManager implement
if (provider.isContainer() == isContainer) {
WidgetOption option = WidgetOptionFactory.createByWidgetClass(
provider.nameForWidget(),
BaseUtils.readIcon(provider.iconPathForWidget()),
provider.iconPathForWidget(),
provider.classForWidget()
);
result.add(option);

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

@ -57,10 +57,8 @@ public class RestartHelper {
properties.setProperty((i + size) + "", files[i]);
}
}
try {
FileOutputStream file2DeleteOutputStream = new FileOutputStream(file);
try (FileOutputStream file2DeleteOutputStream = new FileOutputStream(file)) {
properties.store(file2DeleteOutputStream, "save");
file2DeleteOutputStream.close();
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}

4
designer-base/src/main/java/com/fr/design/actions/AllowAuthorityEditAction.java

@ -1,9 +1,9 @@
package com.fr.design.actions;
import com.fr.base.svg.IconUtils;
import com.fr.base.vcs.DesignerMode;
import com.fr.design.constants.UIConstants;
import com.fr.design.menu.KeySetUtils;
import com.fr.design.module.DesignModuleFactory;
import com.fr.design.roleAuthority.ReportAndFSManagePane;
import com.fr.design.roleAuthority.RolesAlreadyEditedPane;
import com.fr.design.designer.TargetComponent;
@ -61,6 +61,8 @@ public class AllowAuthorityEditAction extends TemplateComponentAction {
DesignerContext.getDesignerFrame().refreshDottedLine();
EastRegionContainerPane.getInstance().replaceConfiguredRolesPane(RolesAlreadyEditedPane.getInstance());
EastRegionContainerPane.getInstance().removeParameterPane();
//进入时要关闭查找替换面板
DesignModuleFactory.getReplaceOperator().close();
//画虚线
return true;

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

@ -185,12 +185,24 @@ public abstract class UpdateAction extends ShortCut implements Action {
* @param resource 图标资源路径
*/
public void setSmallIcon(String resource) {
setSmallIcon(resource, true);
}
/**
* 使用传入资源url的方式设置Icon会自动设置_normal.svg然后通过needDisable参数判断是否需要自动设置_disable.svg
* 因为有些地方是不需要设置灰化图标的所以不存在灰化图标资源这边如果一并设置就会报错文件找不到
* @param resource
* @param needDisable
*/
public void setSmallIcon(String resource, boolean needDisable) {
if (StringUtils.equals(resource, StringUtils.EMPTY)) {
this.putValue(Action.SMALL_ICON, null);
return;
}
this.putValue(Action.SMALL_ICON, IconUtils.readIcon(resource));
this.putValue(UpdateAction.DISABLED_ICON, IconUtils.readSVGIcon(resource, IconUtils.ICON_TYPE_DISABLED));
if (needDisable) {
this.putValue(UpdateAction.DISABLED_ICON, IconUtils.readSVGIcon(resource, IconUtils.ICON_TYPE_DISABLED));
}
}
public void setSmallIcon(Icon[] smallIcon, boolean white) {

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

@ -17,7 +17,7 @@ public class BugAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "http://bbs.fanruan.com/forum-156-1.html");
return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "https://service.fanruan.com/PF/FR/feedback?type=2");
}
public static final MenuKeySet BUG = new MenuKeySet() {

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

@ -18,7 +18,7 @@ public class NeedAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "http://bbs.fanruan.com/forum-56-1.html");
return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "https://service.fanruan.com/PF/FR/feedback?type=1");
}
public static final MenuKeySet NEED = new MenuKeySet() {

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

@ -0,0 +1,17 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.general.CloudCenter;
public class StudyPlanAction extends AbstractDesignerSSO {
public StudyPlanAction() {
this.setName(Toolkit.i18nText("Fine-Design_Study_Plan"));
this.setSmallIcon("/com/fr/design/images/bbs/studyPlan");
}
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport");
}
}

32
designer-base/src/main/java/com/fr/design/actions/core/ActionFactory.java

@ -6,6 +6,7 @@ import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.MenuKeySet;
import com.fr.design.selection.QuickEditor;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
@ -32,6 +33,7 @@ public class ActionFactory {
private static Set<Class<?>> actionClasses = new CopyOnWriteArraySet<>();
private static Set<Class<?>> floatActionClasses = new CopyOnWriteArraySet<>();
private static Class chartCollectionClass = null;
/**
* 无需每次实例化的悬浮元素编辑器
*/
@ -57,7 +59,6 @@ public class ActionFactory {
private ActionFactory() {
}
/**
* 元素编辑器释放模板对象
*/
@ -69,7 +70,34 @@ public class ActionFactory {
entry.getValue().release();
}
}
/**
* 注册异步加载的单元格编辑器
* 首先放到 classMap 当初始化成功后则移除并放到 cellEditor
* 如果已经存在则覆盖
*
* @param keyClazz 作为 key 的类
* @param editorClazz 作为 编辑器 的类
*/
public static void registerAsyncInitCellEditorClass(Class keyClazz, Class<? extends QuickEditor> editorClazz) {
cellEditorClass.put(keyClazz, editorClazz);
// 这里直接用 invokeLater 放到 UI 线程中去调用。
// 不阻塞主逻辑的启动
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
try {
QuickEditor quickEditor = editorClazz.newInstance();
cellEditorClass.remove(keyClazz);
cellEditor.put(keyClazz, quickEditor);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
});
}
/**
* 注册无需每次实例化的单元格元素编辑器

2
designer-base/src/main/java/com/fr/design/actions/edit/CopyAction.java

@ -21,7 +21,7 @@ public class CopyAction extends TemplateComponentAction {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_M_Edit_Copy"));
this.setMnemonic('C');
this.setSmallIcon("/com/fr/design/images/m_edit/copy");
this.setSmallIcon("/com/fr/design/standard/copy/copy");
this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, DEFAULT_MODIFIER));
this.setEnabled(!DesignModeContext.isBanCopyAndCut());
}

2
designer-base/src/main/java/com/fr/design/actions/edit/CutAction.java

@ -25,7 +25,7 @@ public class CutAction extends TemplateComponentAction {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_M_Edit_Cut"));
this.setMnemonic('T');
this.setSmallIcon("/com/fr/design/images/m_edit/cut");
this.setSmallIcon("/com/fr/design/standard/cut/cut");
this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, DEFAULT_MODIFIER));
this.setEnabled(!DesignModeContext.isBanCopyAndCut());
}

2
designer-base/src/main/java/com/fr/design/actions/edit/PasteAction.java

@ -24,7 +24,7 @@ public class PasteAction extends TemplateComponentAction {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_M_Edit_Paste"));
this.setMnemonic('P');
this.setSmallIcon("/com/fr/design/images/m_edit/paste");
this.setSmallIcon("/com/fr/design/standard/paste/paste");
this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, DEFAULT_MODIFIER));
}

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

@ -3,7 +3,7 @@ package com.fr.design.actions.file;
import com.fr.design.actions.UpdateAction;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.file.MutilTempalteTabPane;
import com.fr.design.file.MultiTemplateTabPane;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.KeySetUtils;
@ -28,9 +28,9 @@ public class CloseCurrentTemplateAction extends UpdateAction {
* @param e 事件
*/
public void actionPerformed(ActionEvent e) {
MutilTempalteTabPane.getInstance().setIsCloseCurrent(true);
MutilTempalteTabPane.getInstance().closeFormat(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
MultiTemplateTabPane.getInstance().setIsCloseCurrent(true);
MultiTemplateTabPane.getInstance().closeFormat(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
MultiTemplateTabPane.getInstance().closeSpecifiedTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
}
@Override

50
designer-base/src/main/java/com/fr/design/actions/file/DelFileAction.java

@ -0,0 +1,50 @@
package com.fr.design.actions.file;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.FileOperations;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.utils.TemplateUtils;
import javax.swing.JOptionPane;
import java.awt.event.ActionEvent;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
/*
* 删除指定文件
*/
public class DelFileAction extends UpdateAction {
public DelFileAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove"));
this.setSmallIcon("/com/fr/design/standard/remove/remove");
}
@Override
public void actionPerformed(ActionEvent evt) {
FileOperations selectedOperation = DesignerFrameFileDealerPane.getInstance().getSelectedOperation();
if (!selectedOperation.access()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
WARNING_MESSAGE);
return;
}
if (TemplateUtils.checkSelectedTemplateIsEditing()) {
if (FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Template_Is_Editing"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
YES_NO_OPTION) != JOptionPane.YES_OPTION) {
return;
}
}
selectedOperation.deleteFile();
DesignerFrameFileDealerPane.getInstance().stateChange();
DesignerContext.getDesignerFrame().setTitle();
}
}

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

@ -3,6 +3,7 @@
*/
package com.fr.design.actions.file;
import com.fr.design.file.SaveSomeTemplatePane;
import com.fr.design.mainframe.TemplateSavingChecker;
import java.awt.event.ActionEvent;
@ -28,9 +29,14 @@ public class ExitDesignerAction extends UpdateAction {
* @param e 事件
*/
public void actionPerformed(ActionEvent e) {
// 检查是否有正在保存的模板
if (!TemplateSavingChecker.check()) {
return;
}
DesignerContext.getDesignerFrame().exit();
// 提示用户保存模板
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true);
if (saveSomeTemplatePane.showSavePane()) {
DesignerContext.getDesignerFrame().exit();
}
}
}
}

163
designer-base/src/main/java/com/fr/design/actions/file/LocateAction.java

@ -0,0 +1,163 @@
package com.fr.design.actions.file;
import com.fr.design.actions.UpdateAction;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.gui.itree.filetree.TemplateFileTree;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.gui.itree.refreshabletree.RefreshableJTree;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.stable.CoreConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.project.ProjectConstants;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.event.ActionEvent;
import java.io.File;
/**
* 模板定位功能
*/
public class LocateAction extends UpdateAction {
public LocateAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Locate"));
this.setSmallIcon("/com/fr/design/standard/locate/locate");
}
@Override
public void actionPerformed(ActionEvent e) {
JTemplate<?, ?> current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
gotoEditingTemplateLeaf(current.getEditingFILE().getPath(), false);
}
/**
* 在左侧模板树定位到指定模板
*
* @param locatedPath
*/
public static void gotoEditingTemplateLeaf(String locatedPath) {
gotoEditingTemplateLeaf(locatedPath, true);
}
private static void gotoEditingTemplateLeaf(String locatedPath, boolean needRefreshMode) {
if (locatedPath == null) {
return;
}
if (TemplateTreeSearchManager.getInstance().isInSearchMode()) {
TemplateTreeSearchManager.getInstance().outOfSearchMode();
}
DefaultTreeModel model = (DefaultTreeModel) getTemplateFileTree().getModel();
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot();
if (needRefreshMode) {
treeNode.removeAllChildren();
ExpandMutableTreeNode[] childTreeNodes = getTemplateFileTree().loadChildTreeNodes(treeNode);
treeNode.addChildTreeNodes(childTreeNodes);
model.reload(treeNode);
}
recursiveSelectPath(treeNode, locatedPath, model);
TreePath selectedTreePath = getTemplateFileTree().getSelectionPath();
if (selectedTreePath != null) {
getTemplateFileTree().scrollPathToVisible(selectedTreePath);
}
}
private static TemplateFileTree getTemplateFileTree() {
return TemplateTreePane.getInstance().getTemplateFileTree();
}
private static void recursiveSelectPath(TreeNode treeNode, String currentPath, DefaultTreeModel m_model) {
for (int i = 0, len = treeNode.getChildCount(); i < len; i++) {
TreeNode node = treeNode.getChildAt(i);
// 取出当前的childTreeNode,并append到searchingPath后面
ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) node;
if (selectFilePath(childTreeNode, ProjectConstants.REPORTLETS_NAME, currentPath, m_model)) {
break;
}
if (!node.isLeaf()) {
for (int j = 0; j < node.getChildCount(); j++) {
recursiveSelectPath(node.getChildAt(j), currentPath, m_model);
}
}
}
}
/*
* 在currentTreeNode下找寻filePath
*
* prefix + currentTreeNode.getName() = currentTreeNode所对应的Path
*
* 返回currentTreeNode下是否找到了filePath
*/
private static boolean selectFilePath(ExpandMutableTreeNode currentTreeNode, String prefix, String filePath, DefaultTreeModel model) {
Object userObj = currentTreeNode.getUserObject();
if (!(userObj instanceof FileNode)) {
return false;
}
FileNode fileNode = (FileNode) userObj;
String nodePath = fileNode.getName();
String currentTreePath = StableUtils.pathJoin(prefix, nodePath);
boolean result = false;
// 如果equals,说明找到了,不必再找下去了
if (ComparatorUtils.equals(new File(currentTreePath), new File(filePath))) {
getTemplateFileTree().setSelectionPath(new TreePath(model.getPathToRoot(currentTreeNode)));
result = true;
}
// 如果当前路径是currentFilePath的ParentFile,则expandTreeNode,并继续往下找
else if (isParentFile(currentTreePath, filePath)) {
loadPendingChildTreeNode(currentTreeNode);
prefix = currentTreePath + CoreConstants.SEPARATOR;
for (int i = 0, len = currentTreeNode.getChildCount(); i < len; i++) {
ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) currentTreeNode.getChildAt(i);
if (selectFilePath(childTreeNode, prefix, filePath, model)) {
result = true;
}
}
}
return result;
}
protected static void loadPendingChildTreeNode(ExpandMutableTreeNode currentTreeNode) {
if (currentTreeNode.isLeaf()) {
return;
}
// 判断第一个孩子节点.UserObject是不是PENDING,如果是PENDING的话,需要重新加载这个TreeNode
ExpandMutableTreeNode flag = (ExpandMutableTreeNode) currentTreeNode.getFirstChild();
if (flag == null || !flag.getUserObject().toString().equals(RefreshableJTree.PENDING.toString())) {
return;
}
// 删除所有的节点.
currentTreeNode.removeAllChildren();
ExpandMutableTreeNode[] children = getTemplateFileTree().loadChildTreeNodes(currentTreeNode);
for (ExpandMutableTreeNode c : children) {
currentTreeNode.add(c);
}
}
private static boolean isParentFile(String var0, String var1) {
File var2 = new File(var0);
File var3 = new File(var1);
while (!ComparatorUtils.equals(var2, var3)) {
var3 = var3.getParentFile();
if (var3 == null) {
return false;
}
}
return true;
}
}

5
designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java

@ -40,7 +40,10 @@ public class PreferenceAction extends UpdateAction {
DesignerEnvManager.loadLogSetting();
DesignerEnvManager.getEnvManager().saveXMLFile();
JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
jt.refreshToolArea();
//不能只单纯判断!=null,JTemplate还有可能是JNullTemplate.NULL,这个时候模板也是空内容的
if (JTemplate.isValid(jt)) {
jt.refreshToolArea();
}
preferencePane.showRestartDialog();
DesignerFrameFileDealerPane.getInstance().refreshDockingView();
}

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

@ -9,27 +9,31 @@ import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.DialogActionListener;
import com.fr.design.editor.editor.IntegerEditor;
import com.fr.design.file.SaveSomeTemplatePane;
import com.fr.design.gui.frpane.UITabbedPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIColorButton;
import com.fr.design.gui.ibutton.UINoThemeColorButton;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIDictionaryComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ifilechooser.FileChooserArgs;
import com.fr.design.gui.ifilechooser.FileChooserFactory;
import com.fr.design.gui.ifilechooser.FileChooserProvider;
import com.fr.design.gui.ifilechooser.FileSelectionMode;
import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.UIProgressBarUI;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.jdk.JdkVersion;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.os.impl.SupportOSImpl;
@ -41,31 +45,36 @@ import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.general.Inter;
import com.fr.general.log.Log4jConfig;
import com.fr.io.attr.ImageExportAttr;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.report.ReportConfigManager;
import com.fr.stable.Constants;
import com.fr.stable.os.OperatingSystem;
import com.fr.third.apache.log4j.Level;
import com.fr.third.apache.logging.log4j.Level;
import com.fr.transaction.Configurations;
import com.fr.transaction.Worker;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import com.fr.workspace.server.vcs.git.config.GcConfig;
import com.sun.javafx.tk.FileChooserType;
import javafx.stage.FileChooser;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
@ -110,7 +119,8 @@ public class PreferencePane extends BasicPane {
private static final int CACHING_DEFAULT = 5;
private static final int CACHING_GAP = 5;
private static final int MEMORY_TIP_LABEL_MAX_WIDTH = 230;
private static final int OFFSET_HEIGHT = 50;
private static final int PREFERENCE_LABEL_MAX_WIDTH = 460;
private static final int OFFSET_HEIGHT = 60;
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
@ -167,15 +177,18 @@ public class PreferencePane extends BasicPane {
private UICheckBox oracleSpace;
private UISpinner cachingTemplateSpinner;
private UICheckBox useOptimizedUPMCheckbox;
private UICheckBox useNewVersionLoginCheckbox;
private UICheckBox useUniverseDBMCheckbox;
private UICheckBox joinProductImproveCheckBox;
private UICheckBox autoPushUpdateCheckBox;
private UICheckBox embedServerLazyStartupCheckBox;
private UICheckBox imageCompressPanelCheckBox;
private UICheckBox cloudAnalyticsDelayCheckBox;
private UICheckBox vcsEnableCheckBox;
private UICheckBox saveCommitCheckBox;
private UICheckBox useIntervalCheckBox;
private UICheckBox startupPageEnabledCheckBox;
private IntegerEditor saveIntervalEditor;
private UICheckBox gcEnableCheckBox;
private UIButton gcButton;
@ -188,6 +201,14 @@ 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;
private UIRadioButton previewRenderSpeed;
private UIRadioButton previewRenderQuality;
private static final int DPI_SCALE_S = 1;
private static final int DPI_SCALE_M = 2;
public PreferencePane() {
this.initComponents();
@ -200,9 +221,13 @@ public class PreferencePane extends BasicPane {
UITabbedPane jtabPane = new UITabbedPane();
JPanel generalPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
jtabPane.addTab(i18nText("Fine-Design_Basic_General"), generalPane);
UIScrollPane generalScrollPane = patchScroll(generalPane);
jtabPane.addTab(i18nText("Fine-Design_Basic_General"), generalScrollPane);
JPanel advancePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), advancePane);
UIScrollPane adviceScrollPane = patchScroll(advancePane);
jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), adviceScrollPane);
contentPane.add(jtabPane, BorderLayout.NORTH);
createFunctionPane(generalPane);
@ -217,6 +242,8 @@ public class PreferencePane extends BasicPane {
createLogPane(advancePane);
createLanPane(generalPane);
createStartupPagePane(generalPane);
createLengthPane(advancePane);
@ -233,6 +260,13 @@ public class PreferencePane extends BasicPane {
advancePane.add(upmSelectorPane);
}
if (SupportOSImpl.DESIGNER_LOGIN.support()) {
JPanel loginSelectorPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Login_Manager"));
useNewVersionLoginCheckbox = new UICheckBox(i18nText("Fine-Design_Basic_Use_New_Login_Manager"));
loginSelectorPane.add(useNewVersionLoginCheckbox);
advancePane.add(loginSelectorPane);
}
JPanel dbmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Database_Manager"));
useUniverseDBMCheckbox = new UICheckBox(i18nText("Fine-Design_Basic_Use_Universe_Database_Manager"));
//dbmSelectorPane.add(useUniverseDBMCheckbox);
@ -266,9 +300,51 @@ public class PreferencePane extends BasicPane {
JPanel imageCompressPanel = FRGUIPaneFactory.createVerticalTitledBorderPane(i18nText("Fine-Design_Template_Preview_Performance"));
imageCompressPanelCheckBox = new UICheckBox(i18nText("Fine-Design_Image_Compress"));
imageCompressPanel.add(imageCompressPanelCheckBox);
imageCompressPanel.add(createImageExportSettingPane());
advancePane.add(imageCompressPanel);
JPanel designerStartupOption = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Startup_Option"));
cloudAnalyticsDelayCheckBox = new UICheckBox(i18nText("Fine-Design_Cloud_Analytics_Delay"));
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"));
ButtonGroup previewResolutionBtnGroup = new ButtonGroup();
previewResolutionBtnGroup.add(previewResolutionBtnS);
previewResolutionBtnGroup.add(previewResolutionBtnM);
previewRenderSpeed = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Speed_Priority"));
previewRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First"));
ButtonGroup previewRenderGroup = new ButtonGroup();
previewRenderGroup.add(previewRenderQuality);
previewRenderGroup.add(previewRenderSpeed);
JPanel imageExportSettingPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
JComponent[][] templateComps = {
{new UILabel(Toolkit.i18nText("Fine-Design_Report_Engine_Enlarge_Or_Reduce") + ":"), this.previewResolutionBtnS, this.previewResolutionBtnM},
{new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Rendering_Quality") + ":"), this.previewRenderQuality, this.previewRenderSpeed},
};
imageExportSettingPane.add(
TableLayoutHelper.createGapTableLayoutPane(
templateComps,
new double[]{TableLayout.FILL, TableLayout.FILL},
new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
20, 0),
BorderLayout.CENTER);
imageExportSettingPane.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
return imageExportSettingPane;
}
@NotNull
private UIScrollPane patchScroll(JPanel generalPane) {
UIScrollPane generalPanelWithScroll = new UIScrollPane(generalPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
generalPanelWithScroll.setBorder(new EmptyBorder(0, 0, 0, 0));
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);
@ -280,8 +356,6 @@ public class PreferencePane extends BasicPane {
useIntervalCheckBox = new UICheckBox();
//gc面板
JPanel gcControlPane = createGcControlPane();
JPanel enableVcsPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout());
enableVcsPanel.add(vcsEnableCheckBox);
enableVcsPanel.add(remindVcsLabel);
@ -314,7 +388,31 @@ public class PreferencePane extends BasicPane {
vcsPane.add(enableVcsPanel);
vcsPane.add(intervalPanel);
vcsPane.add(saveCommitCheckBox);
vcsPane.add(gcControlPane);
initGcControlPane(vcsPane);
}
private void initGcControlPane(JPanel vcsPane) {
JPanel gcControlPane = createGcControlPane();
new SwingWorker<Boolean, Boolean>() {
@Override
protected Boolean doInBackground() throws Exception {
return WorkContext.getCurrent().get(VcsOperator.class).isLegacyMode();
}
@Override
protected void done() {
try {
if (Boolean.TRUE.equals(get())) {
// 老版本时才显示gc选项
vcsPane.add(gcControlPane);
vcsPane.updateUI();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "[Vcs] retrieve legacy mode error: {}", e.getMessage());
}
}
}.execute();
}
/**
@ -348,22 +446,20 @@ public class PreferencePane extends BasicPane {
private void createFunctionPane(JPanel generalPane) {
JPanel topVerticalTitledBorderPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Function"));
JPanel upper = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout());
JPanel lower = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout());
topVerticalTitledBorderPane.add(upper);
topVerticalTitledBorderPane.add(lower);
JPanel supportUndoPanel = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout());
topVerticalTitledBorderPane.add(supportUndoPanel);
generalPane.add(topVerticalTitledBorderPane);
//添加supportUndo选择项
supportUndoCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Support_Undo"));
upper.add(supportUndoCheckBox);
supportUndoPanel.add(supportUndoCheckBox);
//添加maxUndoLimit
//String[] undoTimes = {"最大撤销次数","5次","10次","15次","20次","50次"};
String[] undoTimes = {i18nText("Fine-Design_Basic_Max_Undo_Limit"), MAX_UNDO_LIMIT_5 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_10 + i18nText("Fine-Design_Basic_Time(s)")
, MAX_UNDO_LIMIT_15 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_20 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_50 + i18nText("Fine-Design_Basic_Time(s)")};
maxUndoLimit = new UIComboBox(undoTimes);
upper.add(maxUndoLimit);
supportUndoPanel.add(maxUndoLimit);
//不支持撤销则不能选择撤销可缓存,也不能设置最大撤销次数
supportUndoCheckBox.addActionListener(new ActionListener() {
@ -377,14 +473,14 @@ public class PreferencePane extends BasicPane {
//添加supportDefaultParentCalculate选择项
supportDefaultParentCalculateCheckBox = new UICheckBox(
i18nText("Fine-Design_Basic_Preference_Support_Default_Parent_Calculate"));
upper.add(supportDefaultParentCalculateCheckBox);
topVerticalTitledBorderPane.add(supportDefaultParentCalculateCheckBox);
//添加是否展示打开模板提示缺少插件选择项
showTemplateMissingPlugin = new UICheckBox(
i18nText("Fine-Design_Basic_Preference_Show-Template-Missing-Plugin"));
upper.add(showTemplateMissingPlugin);
topVerticalTitledBorderPane.add(showTemplateMissingPlugin);
startWithEmptyFile = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Start_Empty_File"));
lower.add(startWithEmptyFile);
topVerticalTitledBorderPane.add(startWithEmptyFile);
}
private void createEditPane(JPanel generalPane) {
@ -438,10 +534,10 @@ public class PreferencePane extends BasicPane {
requestFocusInWindow();
label = new UILabel(text);
add(GUICoreUtils.createBorderLayoutPane(
new UILabel(i18nText("Fine-Design_Basic_Support_Current_Auto_Complete_Shortcut") + ":"),
BorderLayout.WEST,
label,
BorderLayout.CENTER),
new UILabel(i18nText("Fine-Design_Basic_Support_Current_Auto_Complete_Shortcut") + ":"),
BorderLayout.WEST,
label,
BorderLayout.CENTER),
BorderLayout.NORTH);
addKeyListener(new KeyAdapter() {
@Override
@ -508,9 +604,8 @@ public class PreferencePane extends BasicPane {
@Override
public void actionPerformed(ActionEvent evt) {
FileChooserProvider fileChooserProvider =
new JavaFxNativeFileChooser.Builder().
fileSelectionMode(FileSelectionMode.DIR).
build();
FileChooserFactory.createFileChooser(FileChooserArgs.newBuilder().
setFileSelectionMode(FileSelectionMode.DIR).build());
int saveValue = fileChooserProvider.showDialog(chooseDirBtn);
if (saveValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooserProvider.getSelectedFile();
@ -576,6 +671,21 @@ public class PreferencePane extends BasicPane {
languageComboBox.setFont(FRFont.getInstance("Dialog", Font.PLAIN, 12));//为了在中文系统中显示韩文
return languageComboBox;
}
private void createStartupPagePane(JPanel generalPane) {
// ben:选择版本语言;
JPanel startupPagePaneWrapper = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
JPanel startupPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Startup_Page_Config"));
generalPane.add(startupPagePaneWrapper);
startupPagePaneWrapper.add(startupPane);
startupPageEnabledCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Startup_Page_Config_Check_Text"));
startupPane.add(startupPageEnabledCheckBox);
UILabel descLabel = FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Startup_Page_Config_Desc"), PREFERENCE_LABEL_MAX_WIDTH);
descLabel.setForeground(new Color(51, 51, 52, (int)Math.round(0.5 * 255)));
startupPane.add(descLabel);
}
private String getDisplayShortCut(String shotrCut) {
return shotrCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH)
@ -723,7 +833,12 @@ public class PreferencePane extends BasicPane {
this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort()));
if (useOptimizedUPMCheckbox != null) {
useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM());
useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()
|| DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter());
}
if (useNewVersionLoginCheckbox != null) {
useNewVersionLoginCheckbox.setSelected(!DesignerEnvManager.getEnvManager().isUseOldVersionLogin());
}
useUniverseDBMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseUniverseDBM());
@ -740,6 +855,27 @@ public class PreferencePane extends BasicPane {
this.startWithEmptyFile.setSelected(designerEnvManager.isStartWithEmptyFile());
this.imageCompressPanelCheckBox.setSelected(designerEnvManager.isImageCompress());
ImageExportAttr attr = ReportConfigManager.getProviderInstance().getImageExportAttr();
if (attr.getPreviewRenderQuality() == ImageExportAttr.RENDER_SPEED) {
previewRenderSpeed.setSelected(true);
} else {
previewRenderQuality.setSelected(true);
}
if (attr.getPreviewResolutionScale() == DPI_SCALE_S) {
previewResolutionBtnS.setSelected(true);
} else {
previewResolutionBtnM.setSelected(true);
}
boolean enabled = WorkContext.getCurrent().isLocal() || WorkContext.getCurrent().isRoot();
previewRenderSpeed.setEnabled(enabled);
previewRenderQuality.setEnabled(enabled);
previewResolutionBtnS.setEnabled(enabled);
previewResolutionBtnM.setEnabled(enabled);
this.cloudAnalyticsDelayCheckBox.setSelected(designerEnvManager.isCloudAnalyticsDelay());
this.startupPageEnabledCheckBox.setSelected(designerEnvManager.isStartupPageEnabled());
}
private int chooseCase(int sign) {
@ -799,11 +935,14 @@ 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());
VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager();
vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue());
vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected());
vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected());
vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected());
designerEnvManager.setStartupPageEnabled(this.startupPageEnabledCheckBox.isSelected());
Configurations.update(new Worker() {
@Override
public void run() {
@ -820,6 +959,10 @@ public class PreferencePane extends BasicPane {
designerEnvManager.setAutoPushUpdateEnabled(this.autoPushUpdateCheckBox.isSelected());
}
if (useNewVersionLoginCheckbox != null) {
designerEnvManager.setUseOldVersionLogin(!this.useNewVersionLoginCheckbox.isSelected());
}
designerEnvManager.setUndoLimit(maxUndoLimit.getSelectedIndex() * SELECTED_INDEX_5);
if (maxUndoLimit.getSelectedIndex() == SELECTED_INDEX_5) {
designerEnvManager.setUndoLimit(MAX_UNDO_LIMIT_50);
@ -859,6 +1002,18 @@ public class PreferencePane extends BasicPane {
}
});
ImageExportAttr attr = ReportConfigManager.getProviderInstance().getImageExportAttr();
if (previewRenderSpeed.isSelected()) {
attr.setPreviewRenderQuality(ImageExportAttr.RENDER_SPEED);
} else {
attr.setPreviewRenderQuality(ImageExportAttr.RENDER_QUALITY);
}
if (previewResolutionBtnS.isSelected()) {
attr.setPreviewResolutionScale(DPI_SCALE_S);
} else {
attr.setPreviewResolutionScale(DPI_SCALE_M);
}
}
// 如果语言设置改变了,则显示重启对话框
@ -866,6 +1021,12 @@ public class PreferencePane extends BasicPane {
if (!languageChanged) {
return;
}
// 重启弹窗出现之前提示用户保存模板
SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(true, SwingUtilities.getWindowAncestor(this));
if (!saveSomeTempaltePane.showSavePane()) {
// 保存失败时,直接返回
return;
}
int rv = JOptionPane.showOptionDialog(
null,
i18nText("Fine-Design_Basic_Language_Change_Successful"),

346
designer-base/src/main/java/com/fr/design/actions/file/RenameAction.java

@ -0,0 +1,346 @@
package com.fr.design.actions.file;
import com.fr.base.BaseUtils;
import com.fr.chartx.TwoTuple;
import com.fr.design.DesignerEnvManager;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.FileOperations;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MultiTemplateTabPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.utils.TemplateUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.event.EventDispatcher;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.stable.CoreConstants;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.third.org.apache.commons.io.FilenameUtils;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.regex.Pattern;
import static javax.swing.JOptionPane.DEFAULT_OPTION;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
/**
* 模板/目录重命名操作
*/
public class RenameAction extends UpdateAction {
private FileOperations selectedOperation;
public RenameAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Rename"));
this.setSmallIcon("/com/fr/design/standard/rename/rename");
}
@Override
public void actionPerformed(ActionEvent evt) {
selectedOperation = DesignerFrameFileDealerPane.getInstance().getSelectedOperation();
if (!selectedOperation.access()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
WARNING_MESSAGE);
return;
}
FileNode node = selectedOperation.getFileNode();
String lock = node.getLock();
if (lock != null && !lock.equals(node.getUserID())) {
// 提醒被锁定模板无法重命名
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Unable_Rename_Locked_File"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
WARNING_MESSAGE);
return;
}
new FileRenameDialog(node);
MultiTemplateTabPane.getInstance().repaint();
DesignerFrameFileDealerPane.getInstance().stateChange();
}
/**
* 重命名对话框
* 支持快捷键EnterESC
*/
private class FileRenameDialog extends JDialog {
private UITextField nameField;
private UILabel warnLabel;
private UIButton confirmButton;
/**
* 操作的节点
*/
private FileNodeFILE fnf;
private KeyListener keyListener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
dispose();
} else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
if (confirmButton.isEnabled()) {
confirmClose();
}
}
}
};
private FileRenameDialog(FileNode node) {
super(DesignerContext.getDesignerFrame(), true);
if (node == null) {
return;
}
fnf = new FileNodeFILE(node);
String oldName = fnf.getName();
String suffix = fnf.isDirectory() ? StringUtils.EMPTY : oldName.substring(oldName.lastIndexOf(CoreConstants.DOT), oldName.length());
oldName = StringUtils.replaceLast(oldName, suffix, StringUtils.EMPTY);
initPane(oldName);
}
private void initPane(String oldName) {
this.setLayout(new BorderLayout());
// 输入框前提示
UILabel newNameLabel = new UILabel(Toolkit.i18nText(
fnf.isDirectory() ?
"Fine-Design_Basic_Enter_New_Folder_Name" : "Fine-Design_Basic_Enter_New_File_Name")
);
newNameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
newNameLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
//newNameLabel.setPreferredSize(new Dimension(118, 15));
// 重命名输入框
nameField = new UITextField(oldName);
nameField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
validInput();
}
@Override
public void insertUpdate(DocumentEvent e) {
validInput();
}
@Override
public void removeUpdate(DocumentEvent e) {
validInput();
}
});
nameField.selectAll();
nameField.setPreferredSize(new Dimension(170, 20));
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 5));
topPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 0, 15));
topPanel.add(newNameLabel);
topPanel.add(nameField);
// 增加enter以及esc快捷键的支持
nameField.addKeyListener(keyListener);
// 重名提示
warnLabel = new UILabel();
warnLabel.setPreferredSize(new Dimension(300, 50));
warnLabel.setHorizontalAlignment(SwingConstants.LEFT);
warnLabel.setVerticalAlignment(SwingConstants.TOP);
warnLabel.setForeground(Color.RED);
warnLabel.setVisible(false);
JPanel midPanel = new JPanel(new BorderLayout());
midPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15));
midPanel.add(warnLabel, BorderLayout.WEST);
// 确认按钮
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm"));
confirmButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
confirmClose();
}
});
// 取消按钮
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
JPanel buttonsPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
buttonsPane.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 10));
buttonsPane.add(confirmButton);
buttonsPane.add(cancelButton);
this.add(
TableLayoutHelper.createTableLayoutPane(
new Component[][]{
new Component[]{topPanel},
new Component[]{midPanel},
new Component[]{buttonsPane}
},
new double[]{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED},
new double[]{TableLayout.FILL}
),
BorderLayout.CENTER);
this.setSize(340, 200);
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Rename"));
this.setResizable(false);
this.setIconImage(BaseUtils.readImage("/com/fr/base/images/oem/logo.png"));
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
GUICoreUtils.centerWindow(this);
this.setVisible(true);
}
private void confirmClose() {
if (TemplateUtils.checkSelectedTemplateIsEditing()) {
if (FineJOptionPane.showConfirmDialog(this,
Toolkit.i18nText("Fine-Design_Basic_Template_Is_Editing"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
YES_NO_OPTION) != JOptionPane.YES_OPTION) {
return;
}
}
String userInput = nameField.getText().trim();
String path = FilenameUtils.standard(fnf.getPath());
String oldName = fnf.getName();
String suffix = fnf.isDirectory() ? StringUtils.EMPTY : oldName.substring(oldName.lastIndexOf(CoreConstants.DOT), oldName.length());
oldName = StringUtils.replaceLast(oldName, suffix, StringUtils.EMPTY);
// 输入为空或者没有修改
if (ComparatorUtils.equals(userInput, oldName)) {
this.dispose();
return;
}
String parentPath = FilenameUtils.standard(fnf.getParent().getPath());
// 简单执行old new 替换是不可行的,例如 /abc/abc/abc/abc/
String newPath = parentPath + CoreConstants.SEPARATOR + userInput + suffix;
this.dispose();
//模版重命名
boolean success = selectedOperation.rename(fnf, path, newPath);
if (success) {
afterRename(path, newPath);
} else {
FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Rename_Failure"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
DEFAULT_OPTION,
ERROR_MESSAGE);
}
}
private void afterRename(String path, String newPath) {
EventDispatcher.fire(DesignerFrameFileDealerPane.TEMPLATE_RENAME, new TwoTuple<>(path, newPath));
HistoryTemplateListCache.getInstance().rename(fnf, path, newPath);
DesignerEnvManager.getEnvManager().replaceRecentOpenedFilePath(fnf.isDirectory(), path, newPath);
selectedOperation.refreshParent();
if (!fnf.isDirectory()) {
//版本控制:未打开模板时重命名,是个纯文件操作
//不借助JTemplate的事件触发机制实现(需要新创建JTemplate,并添加监听,不确定会不会有问题)
path = path.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY);
VcsHelper.getInstance().moveVcs(path, newPath.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY));
}
DesignerContext.getDesignerFrame().setTitle();
LocateAction.gotoEditingTemplateLeaf(newPath);
}
private void validInput() {
String userInput = nameField.getText().trim();
String oldName = fnf.getName();
String suffix = fnf.isDirectory() ? StringUtils.EMPTY : oldName.substring(oldName.lastIndexOf(CoreConstants.DOT), oldName.length());
oldName = oldName.replaceAll(suffix, StringUtils.EMPTY);
if (StringUtils.isEmpty(userInput)) {
confirmButton.setEnabled(false);
return;
}
if (ComparatorUtils.equals(userInput, oldName)) {
warnLabel.setVisible(false);
confirmButton.setEnabled(true);
return;
}
String errorMsg = doCheck(userInput, suffix, fnf.isDirectory());
if (StringUtils.isNotEmpty(errorMsg)) {
nameField.selectAll();
// 如果文件名已存在,则灰掉确认按钮
warnLabel.setText(errorMsg);
warnLabel.setVisible(true);
confirmButton.setEnabled(false);
} else {
warnLabel.setVisible(false);
confirmButton.setEnabled(true);
}
}
private String doCheck (String userInput, String suffix, boolean isDirectory) {
String errorMsg = StringUtils.EMPTY;
if (selectedOperation.duplicated(userInput, suffix, false)) {
errorMsg = Toolkit.i18nText(isDirectory ?
"Fine-Design_Basic_Folder_Name_Duplicate" :
"Fine-Design_Basic_Template_File_Name_Duplicate",
userInput);
}
if (!Pattern.compile(DesignerFrameFileDealerPane.FILE_NAME_LIMIT).matcher(userInput).matches()) {
errorMsg = Toolkit.i18nText("Fine-Design_Basic_Template_Name_Illegal");
}
return errorMsg;
}
}
}

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

@ -5,6 +5,7 @@ import com.fr.design.EnvChangeEntrance;
import com.fr.design.actions.UpdateAction;
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.menu.KeySetUtils;
import com.fr.design.menu.MenuDef;
@ -66,7 +67,11 @@ public class SwitchExistEnv extends MenuDef {
// 打开配置目录面板
EnvChangeEntrance.getInstance().chooseEnv(envName);
} else {
EnvChangeEntrance.getInstance().switch2Env(envName);
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true);
if (saveSomeTemplatePane.showSavePane()) {
// 用户模板保存后,才进行切换目录操作
EnvChangeEntrance.getInstance().switch2Env(envName);
}
}
}

4
designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java

@ -126,8 +126,8 @@ public class AboutPane extends JPanel {
if (GeneralContext.getLocale().equals(Locale.TAIWAN)) {
return;
}
boxCenterAlignmentPane = new BoxCenterAligmentPane("QQ: " + CloudCenter.getInstance().acquireUrlByKind("help.qq"));
contentPane.add(boxCenterAlignmentPane);
JPanel servicePlatformPane = getURLActionPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Service_Platform"), CloudCenter.getInstance().acquireUrlByKind("service.platform"));
contentPane.add(servicePlatformPane);
}
// 是否显示鸣谢面板

200
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineCloudConstants.java

@ -0,0 +1,200 @@
package com.fr.design.actions.help.alphafine;
import com.fr.design.i18n.Toolkit;
import com.fr.general.CloudCenter;
import com.fr.json.JSONArray;
import java.util.HashMap;
import java.util.Map;
/**
* 云端变量统一管理
*
* @author Link
* @version 11.0
* Created by Link on 2022/9/21
*/
public class AlphaFineCloudConstants {
private static final String PLUGIN_SEARCH_API = "plugin.searchAPI";
private static final String PLUGIN_ALL_SEARCH_API = "plugin.all.searchAPI";
private static final String AF_PLUGIN_INFO = "af.pluginInfo";
private static final String AF_REUSE_INFO = "af.reuseInfo";
private static final String AF_DOC_VIEW = "af.doc_view";
private static final String AF_DOC_SEARCH = "af.doc_search";
private static final String AF_DOC_INFO = "af.doc_info";
private static final String AF_PLUGIN_IMAGE = "af.plugin_image";
private static final String AF_RECORD = "af.record";
private static final String AF_CLOUD_SEARCH = "af.cloud_search";
private static final String AF_SIMILAR_SEARCH = "af.similar_search";
private static final String AF_ADVICE_SEARCH = "af.advice_search";
private static final String AF_HOT_SEARCH = "af.hot_search";
private static final String AF_GO_FORUM = "af.go_fourm";
private static final String AF_GO_WEB = "af.go_web";
private static final String AF_PREVIEW = "af.preview";
private static final String AF_CID_NEW = "af.cid.new";
private static final String AF_CID_USER_GROUP_INFO = "af.cid.user.group.info";
private static final String AF_HELP_QUICK_START = "af.help.quick.start";
private static final String AF_HELP_REPORT_LEARNING_PATH = "af.help.report.learning.path";
private static final String AF_HELP_PARAM_LEARNING_PATH = "af.help.param.learning.path";
private static final String AF_HELP_FILL_LEARNING_PATH = "af.help.fill.learning.path";
private static final String AF_HELP_API_SUMMARY = "af.help.api.summary";
private static final String AF_HELP_MONTHLY_DOCUMENT = "af.help.monthly.document";
private static final String AF_RECOMMEND = "af.recommend";
private static final String LINK_NAME = "name";
private static final String LINK_URL = "link";
/**
* 获取插件搜索api
*/
public static String getPluginSearchUrl() {
return CloudCenter.getInstance().acquireUrlByKind(PLUGIN_SEARCH_API);
};
/**
* 帆软市场里全部插件api
*/
public static String getSearchAllPluginUrl() {
return CloudCenter.getInstance().acquireUrlByKind(PLUGIN_ALL_SEARCH_API);
}
/**
* 获取插件信息api
*/
public static String getPluginUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_PLUGIN_INFO);
}
/**
* 获取组件信息api
*/
public static String getReuseUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_REUSE_INFO);
}
/**
* 获取帮助文档url
*/
public static String getDocumentDocUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_VIEW);
}
/**
* 帮助文档搜索api
*/
public static String getDocumentSearchUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_SEARCH);
}
/**
* 帮助文档信息api
*/
public static String getDocumentInformationUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_INFO);
}
/**
* 插件图片api
*/
public static String getPluginImageUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_PLUGIN_IMAGE);
}
/**
* 获取云端接口用于上传alphafine搜索记录
*/
public static String getCloudServerUrl() {
return CloudCenter.getInstance().acquireUrlByKind(AF_RECORD);
}
/**
* 获取搜索api输入搜索词返回fr的相关功能
*/
public static String getSearchApi() {
return CloudCenter.getInstance().acquireUrlByKind(AF_CLOUD_SEARCH);
}
/**
* 获取模糊搜索api前缀输入搜索词返回alphaFine相关内容插件文档功能等
*/
public static String getSimilarSearchUrlPrefix() {
return CloudCenter.getInstance().acquireUrlByKind(AF_SIMILAR_SEARCH);
}
/**
* 补全建议搜索结果 api与AF_SIMILAR_SEARCH接口类似但是返回的信息更全
*/
public static String getComplementAdviceSearchUrlPrefix() {
return CloudCenter.getInstance().acquireUrlByKind(AF_ADVICE_SEARCH);
}
/**
* 获取热门问题
*/
public static String getAlphaHotSearch() {
return CloudCenter.getInstance().acquireUrlByKind(AF_HOT_SEARCH);
}
/**
* 跳转论坛url
*/
public static String getAlphaGoToForum() {
return CloudCenter.getInstance().acquireUrlByKind(AF_GO_FORUM);
}
/**
* 推荐搜索api输入搜索词返回猜你想搜的内容html格式
*/
public static String getAlphaGoToWeb() {
return CloudCenter.getInstance().acquireUrlByKind(AF_GO_WEB);
}
/**
* 帆软智能客服页面url
*/
public static String getAlphaPreview() {
return CloudCenter.getInstance().acquireUrlByKind(AF_PREVIEW);
}
/**
* cid系统的产品动态api
*/
public static String getAlphaCid() {
return CloudCenter.getInstance().acquireUrlByKind(AF_CID_NEW);
}
/**
* cid系统的 用户组信息api
*/
public static String getAlphaCidUserGroupInfo() {
return CloudCenter.getInstance().acquireUrlByKind(AF_CID_USER_GROUP_INFO);
}
private static String getDefaultRecommend() {
String[][] links = new String[][]{
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Quick_Start"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_QUICK_START)},
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Report_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_REPORT_LEARNING_PATH)},
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Parameter_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_PARAM_LEARNING_PATH)},
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Fill_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_FILL_LEARNING_PATH)},
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Api_Summary"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_API_SUMMARY)},
{Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Monthly_Document"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_MONTHLY_DOCUMENT)}
};
JSONArray jsonArray = new JSONArray();
for (String[] link : links) {
Map<String, String> map = new HashMap<>();
map.put(LINK_NAME, link[0]);
map.put(LINK_URL, link[1]);
jsonArray.put(map);
}
return jsonArray.toString();
}
/**
* 获取默认推荐帮助文档url
*/
public static String getAlphaHelpRecommend() {
return CloudCenter.getInstance().acquireUrlByKind(AF_RECOMMEND, getDefaultRecommend());
}
}

196
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java

@ -1,5 +1,7 @@
package com.fr.design.actions.help.alphafine;
import com.fr.base.FRContext;
import com.fr.design.DesignerEnvManager;
import com.fr.general.ComparatorUtils;
import com.fr.license.function.VT4FR;
import com.fr.stable.OperatingSystem;
@ -10,10 +12,14 @@ import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.KeyStroke;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
/**
* AlphaFine配置类
@ -23,6 +29,7 @@ import java.util.Map;
*/
public class AlphaFineConfigManager implements XMLable {
public static final String COMMA = ",";
private static final long serialVersionUID = -8170289826729582122L;
private static AlphaFineConfigManager alphaFineConfigManager = new AlphaFineConfigManager();
/**
@ -46,13 +53,17 @@ public class AlphaFineConfigManager implements XMLable {
*/
private boolean containRecommend = true;
/**
* 设置
* 功能
*/
private boolean containAction = true;
/**
* 帮助文档
*/
private boolean containDocument = true;
/**
* 我的模板
* */
private boolean containMyTemplate = true;
/**
* 模板
*/
@ -62,7 +73,7 @@ public class AlphaFineConfigManager implements XMLable {
*/
private boolean containFileContent;
/**
* 应用中心
* 插件中心
*/
private boolean containPlugin = true;
/**
@ -81,10 +92,36 @@ public class AlphaFineConfigManager implements XMLable {
* 是否提醒
*/
private boolean needRemind = true;
/**
* 产品动态
*/
private boolean productDynamics = true;
/**
* 模板商城是否展示
*/
private boolean showTemplateShop = true;
/**
* tab页排序
* 默认排序动态模板商城帮助文档插件中心功能我的模板
*/
private String[] tabOrder;
private Map<String, String> actionSearchTextCache = new HashMap<>(8);
private String cacheBuildNO;
private static final String CONTAIN_TEMPLATE_SHOP = "isContainTemplateShop";
/**
* key: 登录的bbs用户
* value: alphaFine历史搜索记录
*/
private Map<String, Stack<String>> historySearchMap = new LinkedHashMap<>();
/**
* key: 登录的bbs用户
* value: 已读的cid的集合
*/
private Map<String, Set<Long>> readSetMap = new LinkedHashMap<>();
/**
* 直接操作菜单次数
*/
@ -115,17 +152,24 @@ public class AlphaFineConfigManager implements XMLable {
this.setContainPlugin(reader.getAttrAsBoolean("isContainDocument", true));
this.setContainDocument(reader.getAttrAsBoolean("isContainDocument", true));
this.setContainRecommend(reader.getAttrAsBoolean("isContainRecommend", true));
this.setShowTemplateShop(reader.getAttrAsBoolean(CONTAIN_TEMPLATE_SHOP, true));
this.setContainAction(reader.getAttrAsBoolean("isContainAction", true));
this.setContainTemplate(reader.getAttrAsBoolean("isContainTemplate", true));
this.setContainFileContent(reader.getAttrAsBoolean("isContainFileContent", false));
this.setNeedSegmentationCheckbox(reader.getAttrAsBoolean("needSegmentationCheckbox", true));
this.setNeedIntelligentCustomerService(reader.getAttrAsBoolean("needIntelligentCustomerService", true));
this.setProductDynamics(reader.getAttrAsBoolean("productDynamics", true));
this.setShortcuts(reader.getAttrAsString("shortcuts", getDefaultShortCuts()));
this.setNeedRemind(reader.getAttrAsBoolean("isNeedRemind", true));
this.setOperateCount(reader.getAttrAsInt("operateCount", 0));
this.setTabOrder(reader.getAttrAsString("tabOrder", getDefaultTabOrder()).split(","));
} else if (reader.isChildNode()) {
if (ComparatorUtils.equals(reader.getTagName(), "ActionSearchTextCache")) {
readActionSearchTextCacheXML(reader);
} else if ("SearchHistory".equals(reader.getTagName())) {
readHistorySearch(reader);
} else if ("ReadSet".equals(reader.getTagName())) {
readReadSet(reader);
}
}
}
@ -152,6 +196,53 @@ public class AlphaFineConfigManager implements XMLable {
});
}
private void readHistorySearch(XMLableReader reader) {
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader xmLableReader) {
if (ComparatorUtils.equals(reader.getTagName(), "history")) {
String tmpVal = reader.getElementValue();
if (tmpVal != null) {
tmpVal = tmpVal.replace("[", StringUtils.EMPTY).replace("]", StringUtils.EMPTY);
Stack<String> stack = new SizedStack<>(3);
String[] historyList = tmpVal.split(",");
for (String history : historyList) {
String value = history.trim();
if (StringUtils.isNotEmpty(value)) {
stack.add(value);
}
}
historySearchMap.put(reader.getAttrAsString("user", StringUtils.EMPTY), stack);
}
}
}
});
}
private void readReadSet(XMLableReader reader) {
reader.readXMLObject(new XMLReadable() {
@Override
public void readXML(XMLableReader xmLableReader) {
if (ComparatorUtils.equals(reader.getTagName(), "readId")) {
String tmpVal = reader.getElementValue();
if (tmpVal != null) {
tmpVal = tmpVal.replace("[", StringUtils.EMPTY).replace("]", StringUtils.EMPTY);
String[] idArr = tmpVal.split(",");
Set<Long> setId = new HashSet<>();
for (String id : idArr) {
String value = id.trim();
if (StringUtils.isNotEmpty(value)) {
setId.add(Long.parseLong(value));
}
}
readSetMap.put(reader.getAttrAsString("user", StringUtils.EMPTY), setId);
}
}
}
});
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG("AlphaFineConfigManager");
@ -167,8 +258,13 @@ public class AlphaFineConfigManager implements XMLable {
.attr("isNeedRemind", this.isNeedRemind())
.attr("operateCount", this.getOperateCount())
.attr("needSegmentationCheckbox", this.isNeedSegmentationCheckbox())
.attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService());
.attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService())
.attr("productDynamics", this.isProductDynamics())
.attr(CONTAIN_TEMPLATE_SHOP, this.showTemplateShop)
.attr("tabOrder", this.getTabOrderString());
writeActionSearchTextCacheXML(writer);
writeSearchHistory(writer);
writeReadSet(writer);
writer.end();
}
@ -183,6 +279,22 @@ public class AlphaFineConfigManager implements XMLable {
writer.end();
}
private void writeSearchHistory(XMLPrintWriter writer) {
writer.startTAG("SearchHistory");
for (Map.Entry<String, Stack<String>> entry : historySearchMap.entrySet()) {
writer.startTAG("history").attr("user", entry.getKey()).textNode(entry.getValue().toString()).end();
}
writer.end();
}
private void writeReadSet(XMLPrintWriter writer) {
writer.startTAG("ReadSet");
for (Map.Entry<String, Set<Long>> entry : readSetMap.entrySet()) {
writer.startTAG("readId").attr("user", entry.getKey()).textNode(entry.getValue().toString()).end();
}
writer.end();
}
public boolean isSearchOnLine() {
return searchOnLine;
}
@ -212,6 +324,13 @@ public class AlphaFineConfigManager implements XMLable {
return OperatingSystem.isMacOS() ? "meta + D" : "ctrl + D";
}
/**
* 返回默认排序
*/
private String getDefaultTabOrder() {
return AlphaFineConstants.PRODUCT_NEWS + COMMA + AlphaFineConstants.TEMPLATE_SHOP + COMMA + AlphaFineConstants.HELP + COMMA + AlphaFineConstants.PLUGIN + COMMA + AlphaFineConstants.FUNCTION + COMMA + AlphaFineConstants.MY_TEMPLATES;
}
public boolean isContainAction() {
return containAction;
}
@ -228,6 +347,14 @@ public class AlphaFineConfigManager implements XMLable {
this.containDocument = containDocument;
}
public boolean isContainMyTemplate() {
return containMyTemplate;
}
public void setContainMyTemplate(boolean containMyTemplate) {
this.containMyTemplate = containMyTemplate;
}
public boolean isContainTemplate() {
return containTemplate;
}
@ -335,4 +462,61 @@ public class AlphaFineConfigManager implements XMLable {
public void setCacheBuildNO(@NotNull String cacheBuildNO) {
this.cacheBuildNO = cacheBuildNO;
}
public Stack<String> getHistorySearch() {
return historySearchMap.computeIfAbsent(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), k -> new SizedStack<>(3));
}
public Set<Long> getReadSet() {
return readSetMap.computeIfAbsent(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), k -> new HashSet<>());
}
public boolean isProductDynamics() {
return productDynamics && FRContext.isChineseEnv();
}
public void setProductDynamics(boolean productDynamics) {
this.productDynamics = productDynamics;
}
public boolean hasTemplateShop() {
return showTemplateShop && FRContext.isChineseEnv();
}
public void setShowTemplateShop(boolean showTemplateShop) {
this.showTemplateShop = showTemplateShop;
}
/**
* 是否展示alphafine窗口设置-搜索范围 0勾选则不显示
*/
public boolean needShowAlphaFineDialog() {
return hasTemplateShop() || isContainDocument() || isContainPlugin() ||
isContainAction() || isProductDynamics() || isContainMyTemplate();
}
/**
* 返回tab显示顺序
*/
public String[] getTabOrder() {
if (tabOrder == null) {
tabOrder = getDefaultTabOrder().split(COMMA);
}
return tabOrder;
}
public void setTabOrder(String[] tabOrder) {
this.tabOrder = tabOrder;
}
/**
* getTabOrder的tostring
*/
public String getTabOrderString() {
StringBuilder sb = new StringBuilder();
for (String s : getTabOrder()) {
sb.append(s + COMMA);
}
return sb.toString();
}
}

302
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java

@ -1,23 +1,41 @@
package com.fr.design.actions.help.alphafine;
import com.fr.base.FRContext;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.actions.help.alphafine.component.CustomSortPane;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicPane;
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.imenu.UIPopupMenu;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.log.FineLoggerFactory;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
/**
* Created by XiaXiang on 2017/4/6.
@ -25,39 +43,32 @@ import java.awt.event.MouseEvent;
public class AlphaFineConfigPane extends BasicPane {
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
private static final String BACK_SLASH = "BACK_SLASH";
private static final String DISPLAY_BACK_SLASH = "\\";
private static final String SLASH = "SLASH";
private static final String DISPLAY_SLASH = "/";
private static final String CONTROL = "CONTROL";
private static final String DISPLAY_CONTROL = "ctrl";
private static final String OPEN_BRACKET = "OPEN_BRACKET";
private static final String DISPLAY_OPEN_BRACKET = "{";
private static final String CLOSE_BRACKET = "CLOSE_BRACKET";
private static final String DISPLAY_CLOSE_BRACKET = "}";
private static final String COMMA = "COMMA";
private static final String DISPLAY_COMMA = ",";
private static final String PERIOD = "PERIOD";
private static final String DISPLAY_PERIOD = ".";
private static final String SEMICOLON = "SEMICOLON";
private static final String DISPLAY_SEMICOLON = ";";
private static final String QUOTE = "QUOTE";
private static final String DISPLAY_QUOTE = "'";
private static final String EQUALS = "EQUALS";
private static final String DISPLAY_EQUALS = "+";
private static final String MINUS = "MINUS";
private static final String DISPLAY_MINUS = "-";
private static final String COMMAND = "META";
private static final String SMALL_COMMAND = "meta";
private static final String DISPLAY_COMMAND = "\u2318";
private static final double COLUMN_GAP = 180;
private static final double ROW_GAP = 25;
private static final Color LABEL_TEXT = new Color(0x919193);
private static final int SEARCH_CONFIG_PANE_HEIGHT = 70;
private static final int SEARCH_CONFIG_PANE_WIDTH = 87;
private static final double COLUMN_WIDTH = 150;
private static final double ROW_HEIGHT = 25;
private KeyStroke shortCutKeyStore = null;
private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox, needIntelligentCustomerService, containRecommendCheckbox, containActionCheckbox, containDocumentCheckbox, containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox;
private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox;
private UICheckBox productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox,
containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox;
// 自定义排序按钮
private ActionLabel customSortLabel;
private UITextField shortcutsField;
// 当前tab排序。点击确定后会保存到配置文件中
private String[] currentOrder;
// 搜索范围-我的模板,相关组件
private JPanel containMyTemplatePane;
private JButton myTemplateSearchConfigButton;
private UIPopupMenu myTemplateSearchMenu;
private UICheckBox containTemplateNameSearchCheckbox, containFileContentSearchCheckbox;
public AlphaFineConfigPane() {
this.initComponents();
}
@ -70,16 +81,6 @@ public class AlphaFineConfigPane extends BasicPane {
createSearchConfigPane(contentPane);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.add(contentPane, BorderLayout.NORTH);
}
private Component[][] initSearchRangeComponents() {
Component[][] components = new Component[][]{
new Component[]{containRecommendCheckbox, containActionCheckbox, containDocumentCheckbox},
new Component[]{containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox},
new Component[]{needIntelligentCustomerService, null, null}
};
return components;
}
private Component[][] initOnlineComponents() {
@ -89,24 +90,143 @@ public class AlphaFineConfigPane extends BasicPane {
return components;
}
// 搜索范围
private void createSearchConfigPane(JPanel contentPane) {
double[] rowSize = {ROW_GAP, ROW_GAP, ROW_GAP};
double[] rowSize = {ROW_HEIGHT, ROW_HEIGHT, ROW_HEIGHT};
double[] columnSize = {COLUMN_WIDTH, COLUMN_WIDTH, COLUMN_WIDTH};
double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP};
JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Search_Range"));
containRecommendCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Recommend"));
containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set"));
JPanel searchConfigWrapperPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Search_Range"));
// 搜索选项
productDynamicsCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News"));
containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Function"));
containPluginCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon"));
containDocumentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help"));
containTemplateCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Templates"));
containFileContentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Templates_Content"));
needIntelligentCustomerService = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Intelligent_Customer_Service"));
containMyTemplateCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_My_Templates"));
containFileContentSearchCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Templates_Content"));
containTemplateShopCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Shop"));
containMyTemplateCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_My_Templates"));
JPanel searchConfigPane = TableLayoutHelper.createTableLayoutPane(initSearchRangeComponents(), rowSize, columnSize);
northPane.add(searchConfigPane);
contentPane.add(northPane);
// 自定义排序
JPanel customSortWrapperPane = new JPanel();
customSortWrapperPane.setPreferredSize(new Dimension(SEARCH_CONFIG_PANE_HEIGHT, SEARCH_CONFIG_PANE_WIDTH));
customSortWrapperPane.setAlignmentY(JPanel.TOP_ALIGNMENT);
customSortLabel = new ActionLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Config_Custom_Sort"), false);
customSortLabel.setForeground(UIConstants.NORMAL_BLUE);
customSortLabel.addActionListener((event)->{
if (customSortLabel.isEnabled()) {
openCustomSortMenu();
}
});
customSortWrapperPane.add(customSortLabel);
if (!hasSelectedSearchRangeCheckBox()) {
customSortLabel.setEnabled(false);
}
searchConfigWrapperPane.add(searchConfigPane);
searchConfigWrapperPane.add(customSortWrapperPane);
contentPane.add(searchConfigWrapperPane);
}
/**
* 打开自定义排序面板
* */
private void openCustomSortMenu() {
CustomSortPane customSortPane = new CustomSortPane(getSelectedSearchRangeCheckBox(), this);
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(customSortPane);
GUICoreUtils.showPopupMenu(popupMenu, customSortLabel, 0, customSortLabel.getHeight());
}
private Component[][] initSearchRangeComponents() {
// 我的模板checkbox设置,点击后
initMyTemplateSearchPane();
Component[][] components = new Component[][]{
new Component[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox},
new Component[]{containPluginCheckbox, containActionCheckbox, containMyTemplatePane},
};
// 添加选项点事件,无选中选项时自定排序按钮置灰
UICheckBox[] checkBoxes = new UICheckBox[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox, containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox};
for (UICheckBox box : checkBoxes) {
box.addActionListener((e)->{
customSortLabel.setEnabled(hasSelectedSearchRangeCheckBox());
});
}
return components;
}
/**
* 搜索范围中的复选框有无选中的
* */
private boolean hasSelectedSearchRangeCheckBox() {
return productDynamicsCheckbox.isSelected() || containTemplateShopCheckbox.isSelected() || containDocumentCheckbox.isSelected()
|| containPluginCheckbox.isSelected() || containActionCheckbox.isSelected() || containMyTemplateCheckbox.isSelected();
}
/**
* 获取当前选中的搜索范围选项
* */
private List<UICheckBox> getSelectedSearchRangeCheckBox() {
List<UICheckBox> res = new ArrayList<>();
UICheckBox[] checkBoxes = new UICheckBox[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox, containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox};
for (UICheckBox c : checkBoxes) {
if (c.isSelected()) {
res.add(c);
}
}
return res;
}
/**
* 搜索范围-我的模板
*/
private void initMyTemplateSearchPane() {
containMyTemplatePane = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 5));
containMyTemplateCheckbox.setBorder(BorderFactory.createEmptyBorder());
containMyTemplateCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (containMyTemplateCheckbox.isSelected()) {
myTemplateSearchConfigButton.setVisible(true);
} else {
myTemplateSearchConfigButton.setVisible(false);
}
}
});
myTemplateSearchConfigButton = new JButton();
myTemplateSearchConfigButton.setBorder(BorderFactory.createEmptyBorder());
myTemplateSearchConfigButton.setMargin(new Insets(0, 0, 0, 0));
myTemplateSearchConfigButton.setIcon(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/config.svg"));
myTemplateSearchMenu = new UIPopupMenu();
containTemplateNameSearchCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_AlphaFine_Config_Name_Search"));
containFileContentSearchCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_AlphaFine_Config_Content_Search"));
containTemplateNameSearchCheckbox.setSelected(true);
containTemplateNameSearchCheckbox.setEnabled(false);
containTemplateNameSearchCheckbox.setBackground(null);
containFileContentSearchCheckbox.setBackground(null);
myTemplateSearchMenu.add(containTemplateNameSearchCheckbox);
myTemplateSearchMenu.add(containFileContentSearchCheckbox);
myTemplateSearchConfigButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
GUICoreUtils.showPopupMenu(myTemplateSearchMenu, containMyTemplatePane, containMyTemplateCheckbox.getWidth(), containMyTemplatePane.getY());
}
@Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
myTemplateSearchMenu.setVisible(false);
}
});
containMyTemplatePane.add("containMyTemplateCheckbox", containMyTemplateCheckbox);
containMyTemplatePane.add("myTemplateSearchConfigButton", myTemplateSearchConfigButton);
}
private void createShortcutsPane(JPanel contentPane) {
JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Shortcut_Config"));
shortcutsField = new UITextField();
@ -117,7 +237,7 @@ public class AlphaFineConfigPane extends BasicPane {
northPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open") + ":"));
northPane.add(shortcutsField);
UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_SetShortcuts"));
label.setForeground(Color.RED);
label.setForeground(LABEL_TEXT);
northPane.add(label);
contentPane.add(northPane);
}
@ -139,7 +259,7 @@ public class AlphaFineConfigPane extends BasicPane {
int keyCode = e.getKeyCode();
shortCutKeyStore = KeyStroke.getKeyStroke(keyCode, modifier);
String str = shortCutKeyStore.toString();
shortcutsField.setText(getDisplayShortCut(str));
shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(str));
shortcutsField.selectAll();
}
});
@ -153,24 +273,24 @@ public class AlphaFineConfigPane extends BasicPane {
@Override
public void actionPerformed(ActionEvent e) {
if (!searchOnlineCheckbox.isSelected()) {
containRecommendCheckbox.setEnabled(false);
productDynamicsCheckbox.setEnabled(false);
containPluginCheckbox.setEnabled(false);
containDocumentCheckbox.setEnabled(false);
needIntelligentCustomerService.setEnabled(false);
containRecommendCheckbox.setSelected(false);
containTemplateShopCheckbox.setEnabled(false);
productDynamicsCheckbox.setSelected(false);
containPluginCheckbox.setSelected(false);
containDocumentCheckbox.setSelected(false);
needIntelligentCustomerService.setSelected(false);
containTemplateShopCheckbox.setSelected(false);
} else {
containRecommendCheckbox.setEnabled(true);
productDynamicsCheckbox.setEnabled(true);
containPluginCheckbox.setEnabled(true);
containDocumentCheckbox.setEnabled(true);
needIntelligentCustomerService.setEnabled(true);
containTemplateShopCheckbox.setEnabled(true);
}
}
});
double[] rowSize = {ROW_GAP};
double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP};
double[] rowSize = {ROW_HEIGHT};
double[] columnSize = {COLUMN_WIDTH, COLUMN_WIDTH, COLUMN_WIDTH};
JPanel onlinePane = TableLayoutHelper.createTableLayoutPane(initOnlineComponents(), rowSize, columnSize);
northPane.add(onlinePane);
contentPane.add(northPane);
@ -198,8 +318,10 @@ public class AlphaFineConfigPane extends BasicPane {
this.searchOnlineCheckbox.setSelected(enabled4Locale);
this.containActionCheckbox.setSelected(alphaFineConfigManager.isContainAction());
this.containTemplateCheckbox.setSelected(alphaFineConfigManager.isContainTemplate());
this.containFileContentCheckbox.setSelected(alphaFineConfigManager.isContainFileContent());
this.containMyTemplateCheckbox.setSelected(alphaFineConfigManager.isContainMyTemplate());
this.myTemplateSearchConfigButton.setVisible(alphaFineConfigManager.isContainMyTemplate());
this.containFileContentSearchCheckbox.setSelected(alphaFineConfigManager.isContainFileContent());
this.containDocumentCheckbox.setSelected(alphaFineConfigManager.isContainDocument() && enabled4Locale);
this.containDocumentCheckbox.setEnabled(enabled4Locale);
@ -207,17 +329,25 @@ public class AlphaFineConfigPane extends BasicPane {
this.containPluginCheckbox.setSelected(alphaFineConfigManager.isContainPlugin() && enabled4Locale);
this.containPluginCheckbox.setEnabled(enabled4Locale);
this.containRecommendCheckbox.setSelected(alphaFineConfigManager.isContainRecommend() && enabled4Locale);
this.containRecommendCheckbox.setEnabled(enabled4Locale);
this.productDynamicsCheckbox.setSelected(alphaFineConfigManager.isProductDynamics() && enabled4Locale);
this.productDynamicsCheckbox.setEnabled(enabled4Locale);
this.shortcutsField.setText(getDisplayShortCut(alphaFineConfigManager.getShortcuts()));
this.containTemplateShopCheckbox.setSelected(alphaFineConfigManager.hasTemplateShop() && enabled4Locale);
this.containTemplateShopCheckbox.setEnabled(enabled4Locale);
this.needSegmentationCheckbox.setSelected(alphaFineConfigManager.isNeedSegmentationCheckbox());
this.shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(alphaFineConfigManager.getShortcuts()));
this.needIntelligentCustomerService.setSelected(alphaFineConfigManager.isNeedIntelligentCustomerService() && enabled4Locale);
this.needIntelligentCustomerService.setEnabled(enabled4Locale);
this.needSegmentationCheckbox.setSelected(alphaFineConfigManager.isNeedSegmentationCheckbox());
shortCutKeyStore = convert2KeyStroke(alphaFineConfigManager.getShortcuts());
this.currentOrder = alphaFineConfigManager.getTabOrder().clone();
if (!hasSelectedSearchRangeCheckBox()) {
customSortLabel.setEnabled(false);
} else {
customSortLabel.setEnabled(true);
}
}
public void update() {
@ -226,14 +356,17 @@ public class AlphaFineConfigPane extends BasicPane {
alphaFineConfigManager.setContainPlugin(this.containPluginCheckbox.isSelected());
alphaFineConfigManager.setContainAction(this.containActionCheckbox.isSelected());
alphaFineConfigManager.setContainDocument(this.containDocumentCheckbox.isSelected());
alphaFineConfigManager.setContainRecommend(this.containRecommendCheckbox.isSelected());
alphaFineConfigManager.setProductDynamics(this.productDynamicsCheckbox.isSelected());
alphaFineConfigManager.setShowTemplateShop(this.containTemplateShopCheckbox.isSelected());
alphaFineConfigManager.setEnabled(this.enabledCheckbox.isSelected());
alphaFineConfigManager.setSearchOnLine(this.searchOnlineCheckbox.isSelected());
alphaFineConfigManager.setContainTemplate(this.containTemplateCheckbox.isSelected());
alphaFineConfigManager.setContainFileContent(this.containFileContentCheckbox.isSelected());
alphaFineConfigManager.setContainMyTemplate(this.containMyTemplateCheckbox.isSelected());
alphaFineConfigManager.setContainFileContent(this.containFileContentSearchCheckbox.isSelected());
alphaFineConfigManager.setNeedSegmentationCheckbox(this.needSegmentationCheckbox.isSelected());
alphaFineConfigManager.setNeedIntelligentCustomerService(this.needIntelligentCustomerService.isSelected());
alphaFineConfigManager.setShortcuts(shortCutKeyStore != null ? shortCutKeyStore.toString().replace(TYPE, DISPLAY_TYPE) : this.shortcutsField.getText());
alphaFineConfigManager.setTabOrder(currentOrder);
designerEnvManager.setAlphaFineConfigManager(alphaFineConfigManager);
try {
DesignerEnvManager.loadLogSetting();
@ -245,13 +378,6 @@ public class AlphaFineConfigPane extends BasicPane {
}
private String getDisplayShortCut(String shortCut) {
return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH)
.replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET)
.replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE)
.replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND);
}
private KeyStroke convert2KeyStroke(String ks) {
return KeyStroke.getKeyStroke(ks.replace(DISPLAY_TYPE, TYPE));
@ -266,10 +392,18 @@ public class AlphaFineConfigPane extends BasicPane {
}
public UICheckBox getIsContainFileContentCheckbox() {
return containFileContentCheckbox;
return containFileContentSearchCheckbox;
}
public void setIsContainFileContentCheckbox(UICheckBox isContainFileContentCheckbox) {
this.containFileContentCheckbox = isContainFileContentCheckbox;
this.containFileContentSearchCheckbox = isContainFileContentCheckbox;
}
public String[] getCurrentOrder() {
return currentOrder;
}
public void setCurrentOrder(String[] currentOrder) {
this.currentOrder = currentOrder;
}
}

111
designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineConstants.java → designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConstants.java

@ -1,13 +1,19 @@
package com.fr.design.mainframe.alphafine;
package com.fr.design.actions.help.alphafine;
import com.fr.base.extension.FileExtension;
import com.fr.base.svg.IconUtils;
import com.fr.design.i18n.Toolkit;
import com.fr.design.utils.DesignUtils;
import com.fr.general.CloudCenter;
import com.fr.general.IOUtils;
import javax.swing.Icon;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
/**
@ -15,6 +21,19 @@ import java.util.ArrayList;
*/
public class AlphaFineConstants {
public static final String FUNCTION = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Function");
public static final String MY_TEMPLATES = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_My_Templates");
public static final String PRODUCT_NEWS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News");
public static final String HELP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help");
public static final String PLUGIN = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon");
public static final String TEMPLATE_SHOP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Shop");
public static final int SHOW_SIZE = 5;
public static final int MAX_FILE_SIZE = 1000;
@ -33,7 +52,7 @@ public class AlphaFineConstants {
public static final int CONTENT_HEIGHT = 405;
public static final int CELL_HEIGHT = 32;
public static final int CELL_HEIGHT = 29;
public static final int CELL_TITLE_HEIGHT = 24;
@ -41,6 +60,15 @@ public class AlphaFineConstants {
public static final int HOT_ITEMS = 6;
/**
* 限制搜索字符长度
*/
public static final int LEN_LIMIT = 50;
/**
* 帮助文档搜索间隔ms api限制了1s之内只能搜索一次
*/
public static final long DOCUMENT_SEARCH_GAP = 1000;
public static final Dimension FULL_SIZE = new Dimension(680, 460);
@ -54,10 +82,17 @@ public class AlphaFineConstants {
public static final Dimension HOT_ISSUES_JAPNEL_SIZE = new Dimension(213, 182);
/**
* 展示面板的尺寸
*/
public static final Dimension PREVIEW_SIZE = new Dimension(680, 305);
public static final Dimension CLOSE_BUTTON_SIZE = new Dimension(40, 40);
public static final Color WHITE = new Color(0xf9f9f9);
public static final Color LABEL_SELECTED = new Color(0x419bf9);
public static final Color GRAY = new Color(0xd2d2d2);
public static final Color LIGHT_GRAY = new Color(0xcccccc);
@ -88,60 +123,65 @@ public class AlphaFineConstants {
public static final String ALPHA_HOT_IMAGE_NAME = "alphafine_hot";
public static final String PLUGIN_SEARCH_URL = CloudCenter.getInstance().acquireUrlByKind("plugin.searchAPI");
public static final String PLUGIN_URL = CloudCenter.getInstance().acquireUrlByKind("af.pluginInfo");
public static final String REUSE_URL = CloudCenter.getInstance().acquireUrlByKind("af.reuseInfo");
public static final String SPECIAL_CHARACTER_REGEX = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】';:”“’。,、?]";
public static final String BOTTOM_REGEX_FIRST = "<div class=\"bang\">([\\s\\S]*?)class=\"jiaoyes\">YES</a><br/>";
public static final String DOCUMENT_DOC_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_view");
public static final String BOTTOM_REGEX_SECOND = "<div class=\"yes_([\\s\\S]*?)帮助</a></div></div>";
public static final String DOCUMENT_SEARCH_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_search");
public static final String LINK_REGEX = "javascript:;\"([\\s\\S]*?)','";
public static final String DOCUMENT_INFORMATION_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_info");
public static final String LINK_REGEX_ANOTHER = "javascript:([\\s\\S]*?)url=\"";
public static final String PLUGIN_IMAGE_URL = CloudCenter.getInstance().acquireUrlByKind("af.plugin_image");
public static final String ALPHA_ROBOT_SEARCH_TOKEN = "K8dl0Np6l0gs";
public static final String CLOUD_SERVER_URL = CloudCenter.getInstance().acquireUrlByKind("af.record");
public static final String SEARCH_BY_ID = "?id=";
public static final String SEARCH_API = CloudCenter.getInstance().acquireUrlByKind("af.cloud_search");
public static final String JAVASCRIPT_PREFIX = "javascript:SendJava";
public static final String SPECIAL_CHARACTER_REGEX = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】';:”“’。,、?]";
public static final String CHINESE_CHARACTERS = "[\\u4e00-\\u9fa5]";
public static final String BOTTOM_REGEX_FIRST = "<div class=\"bang\">([\\s\\S]*?)class=\"jiaoyes\">YES</a><br/>";
public static final String FIRST_PAGE = "-1";
public static final String BOTTOM_REGEX_SECOND = "<div class=\"yes_([\\s\\S]*?)帮助</a></div></div>";
public static final FileExtension[] FILE_EXTENSIONS = new FileExtension[]{FileExtension.CPT, FileExtension.FRM};
public static final String LINK_REGEX = "javascript:;\"([\\s\\S]*?)','";
public static final int RECOMMEND_MAX_ITEM_NUM = 3;
public static final String LINK_REGEX_ANOTHER = "javascript:([\\s\\S]*?)url=\"";
public static final String BACK_ICON_NAME = "back@1x.png";
public static final String ALPHA_ROBOT_SEARCH_TOKEN = "K8dl0Np6l0gs";
public static final Icon NO_RESULT_ICON = IOUtils.readIcon(AlphaFineConstants.IMAGE_URL + "noresult.png");
public static final String SIMILAR_SEARCH_URL_PREFIX = CloudCenter.getInstance().acquireUrlByKind("af.similar_search");
public static final Color SUSPENDED_COLOR = new Color(84, 165, 249);
public static final String COMPLEMENT_ADVICE_SEARCH_URL_PREFIX = CloudCenter.getInstance().acquireUrlByKind("af.advice_search");
public static final Color FOREGROUND_COLOR = new Color(51, 51, 52);
public static final String ALPHA_HOT_SEARCH = CloudCenter.getInstance().acquireUrlByKind("af.hot_search");
/**
* 后面数字代表透明度 80%
*/
public static final Color FOREGROUND_COLOR_8 = new Color(51, 51, 52, 204);
public static final String ALPHA_GO_TO_FORUM = CloudCenter.getInstance().acquireUrlByKind("af.go_fourm");
public static final Color FOREGROUND_COLOR_6 = new Color(51, 51, 52, 153);
public static final String ALPHA_GO_TO_WEB = CloudCenter.getInstance().acquireUrlByKind("af.go_web");
public static final Color FOREGROUND_COLOR_5 = new Color(51, 51, 52, 128);
public static final String ALPHA_PREVIEW = CloudCenter.getInstance().acquireUrlByKind("af.preview");
public static final Color BACKGROUND_COLOR = new Color(245, 245, 247);
public static final String JAVASCRIPT_PREFIX = "javascript:SendJava";
public static final Icon BULB_ICON = IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bulb.svg");
public static final String CHINESE_CHARACTERS = "[\\u4e00-\\u9fa5]";
public static final Icon YELLOW_BULB_ICON = IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/yellow_bulb.svg");
public static final String FIRST_PAGE = "-1";
public static final Icon LIGHT_YELLOW_BULB_ICON = IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/light_yellow_bulb.svg");
public static final FileExtension[] FILE_EXTENSIONS = new FileExtension[]{FileExtension.CPT, FileExtension.FRM};
public static final String HOT_SEARCH = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search");
public static final int RECOMMEND_MAX_ITEM_NUM = 3;
public static final Set<String> HOT_SEARCH_SET = new LinkedHashSet<>(
Arrays.asList(
Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_ONE"),
Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_TWO"),
Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_THREE")
)
);
public static final String BACK_ICON_NAME = "back@1x.png";
public static final ArrayList<String> CONJUNCTION = new ArrayList<String>() {{
add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_HE"));
@ -149,4 +189,11 @@ public class AlphaFineConstants {
add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_DE"));
}};
public static final String LOADING = "loading";
public static final String NETWORK_ERROR = "network error";
public static final String TITLE = "AlphaFine";
public static final int DEFAULT_CLICK_COUNT = 1;
}

44
designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java

@ -0,0 +1,44 @@
package com.fr.design.actions.help.alphafine;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/4/26
*/
public class AlphaFineShortCutUtil {
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
private static final String BACK_SLASH = "BACK_SLASH";
private static final String DISPLAY_BACK_SLASH = "\\";
private static final String SLASH = "SLASH";
private static final String DISPLAY_SLASH = "/";
private static final String CONTROL = "CONTROL";
private static final String DISPLAY_CONTROL = "ctrl";
private static final String OPEN_BRACKET = "OPEN_BRACKET";
private static final String DISPLAY_OPEN_BRACKET = "{";
private static final String CLOSE_BRACKET = "CLOSE_BRACKET";
private static final String DISPLAY_CLOSE_BRACKET = "}";
private static final String COMMA = "COMMA";
private static final String DISPLAY_COMMA = ",";
private static final String PERIOD = "PERIOD";
private static final String DISPLAY_PERIOD = ".";
private static final String SEMICOLON = "SEMICOLON";
private static final String DISPLAY_SEMICOLON = ";";
private static final String QUOTE = "QUOTE";
private static final String DISPLAY_QUOTE = "'";
private static final String EQUALS = "EQUALS";
private static final String DISPLAY_EQUALS = "+";
private static final String MINUS = "MINUS";
private static final String DISPLAY_MINUS = "-";
private static final String COMMAND = "META";
private static final String SMALL_COMMAND = "meta";
private static final String DISPLAY_COMMAND = "\u2318";
public static String getDisplayShortCut(String shortCut) {
return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH)
.replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET)
.replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE)
.replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND);
}
}

30
designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java

@ -0,0 +1,30 @@
package com.fr.design.actions.help.alphafine;
import java.util.Stack;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/4/23
*/
public class SizedStack<T> extends Stack<T> {
private final int maxSize;
public SizedStack(int size) {
super();
this.maxSize = size;
}
@Override
public T push(T object) {
while (this.size() >= maxSize) {
this.remove(0);
}
// 不重复
if (this.contains(object)) {
return object;
}
return super.push(object);
}
}

229
designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/CustomSortPane.java

@ -0,0 +1,229 @@
package com.fr.design.actions.help.alphafine.component;
import com.fr.base.svg.IconUtils;
import com.fr.design.actions.help.alphafine.AlphaFineConfigPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.PanelUI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* alphafine设置 - 搜索范围 - 自定义排序 - 弹出面板
*
* @author Link
* @version 11.0
* Created by Link on 2022/9/18
*/
public class CustomSortPane extends JPanel {
private static final int WIDTH = 147;
private static final int ITEM_HEIGHT = 23;
private static final int GAP = 1;
private static final Color BACKGROUND_COLOR = new Color(0xdadadd);
private UIButton top;
private UIButton bottom;
private UIButton up;
private UIButton down;
private JPanel toolbarPane;
private MenuLabelPane sortItemPane;
private List<UICheckBox> sortItems;
private MenuLabel selectedLabel;
private AlphaFineConfigPane parentPane;
public CustomSortPane(List<UICheckBox> items, AlphaFineConfigPane parentPane) {
this.sortItems = items;
this.parentPane = parentPane;
setLayout(new BorderLayout(GAP, GAP));
int height = (sortItems.size() + 1) * (ITEM_HEIGHT + GAP) + GAP;
setPreferredSize(new Dimension(WIDTH, height));
initComponent();
add(toolbarPane, BorderLayout.NORTH);
add(sortItemPane, BorderLayout.CENTER);
revalidate();
this.setVisible(true);
}
@Override
public void setUI(PanelUI ui) {
super.setUI(ui);
setBackground(BACKGROUND_COLOR);
}
private void initComponent() {
createToolbarPane();
createSortItemPane();
}
private void createToolbarPane() {
top = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/top.svg"), false);
bottom = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bottom.svg"), false);
up = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/up.svg"), false);
down = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/down.svg"), false);
top.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/top_disable.svg"));
bottom.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bottom_disable.svg"));
up.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/up_disable.svg"));
down.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/down_disable.svg"));
top.addActionListener(e -> {
SwingUtilities.invokeLater(() -> {
sortItemPane.setComponentZOrder(selectedLabel, 0);
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount());
CustomSortPane.this.revalidate();
CustomSortPane.this.repaint();
refreshCurrentOrder();
});
});
bottom.addActionListener(e -> {
SwingUtilities.invokeLater(() -> {
sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentCount() - 1);
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount());
CustomSortPane.this.revalidate();
CustomSortPane.this.repaint();
refreshCurrentOrder();
});
});
up.addActionListener(e -> {
SwingUtilities.invokeLater(() -> {
sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentZOrder(selectedLabel) - 1);
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount());
CustomSortPane.this.revalidate();
CustomSortPane.this.repaint();
refreshCurrentOrder();
});
});
down.addActionListener(e -> {
SwingUtilities.invokeLater(() -> {
sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentZOrder(selectedLabel) + 1);
setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount());
CustomSortPane.this.revalidate();
CustomSortPane.this.repaint();
refreshCurrentOrder();
});
});
toolbarPane = new JPanel(new FlowLayout(FlowLayout.TRAILING, GAP, GAP));
toolbarPane.setBorder(BorderFactory.createEmptyBorder());
toolbarPane.add(top);
toolbarPane.add(bottom);
toolbarPane.add(up);
toolbarPane.add(down);
}
private void createSortItemPane() {
String[] currentTabOrder = parentPane.getCurrentOrder();
Map<String, Integer> sortMap = new HashMap<>();
for (int i = 0; i < currentTabOrder.length; i++) {
sortMap.put(currentTabOrder[i], i);
}
List<MenuLabel> sortLabels = new ArrayList<>();
for (UICheckBox item : sortItems) {
MenuLabel label = new MenuLabel(item.getText(), (Function<MenuLabel, Object>) o -> {
selectedLabel = o;
disableButton();
return null;
});
sortLabels.add(label);
}
sortLabels.sort(Comparator.comparingInt(tab -> sortMap.get(tab.getText())));
sortItemPane = new MenuLabelPane(sortLabels);
}
/**
* 如果选中第一个和最后一个则置灰向上和向下的按钮
*/
private void disableButton() {
int order = sortItemPane.getComponentZOrder(selectedLabel);
if (order == 0) {
setToolbarEnable(false, false, true, true);
} else if (order == sortItemPane.getComponentCount() - 1) {
setToolbarEnable(true, true, false, false);
} else {
setToolbarEnable(true, true, true, true);
}
}
/**
* 设置 置顶上移下移置底 按钮的状态
* true启用
* false关闭
*/
private void setToolbarEnable(boolean top, boolean up, boolean down, boolean bottom) {
this.top.setEnabled(top);
this.up.setEnabled(up);
this.down.setEnabled(down);
this.bottom.setEnabled(bottom);
}
/**
* 根据选项当前位置以及菜单大小设置 置顶上移下移置底 按钮的状态
*/
private void setToolbarEnable(int order, int maxOrder) {
this.top.setEnabled(true);
this.up.setEnabled(true);
this.down.setEnabled(true);
this.bottom.setEnabled(true);
// 选项处于顶端,则置灰上移和置顶按钮
if (order == 0) {
this.top.setEnabled(false);
this.up.setEnabled(false);
}
// 选项处于底端,则置灰下移和置底按钮
if (order == maxOrder - 1) {
this.down.setEnabled(false);
this.bottom.setEnabled(false);
}
}
private void refreshCurrentOrder() {
String[] currentTabOrder = parentPane.getCurrentOrder();
HashSet<String> selectedTab = new HashSet<>();
for (UICheckBox item : sortItems) {
selectedTab.add(item.getText());
}
// 未选中的tab,保持原排序不变
Map<String, Integer> exTab = new HashMap<>();
for (int i = 0; i < currentTabOrder.length; i++) {
if (!selectedTab.contains(currentTabOrder[i])) {
exTab.put(currentTabOrder[i], i);
}
}
// 计算当前排序
String[] newOrder = new String[currentTabOrder.length];
Component[] components = sortItemPane.getComponents();
for (String s : exTab.keySet()) {
newOrder[exTab.get(s)] = s;
}
int t = 0;
for (int i = 0; i < newOrder.length; i++) {
if (StringUtils.isEmpty(newOrder[i])) {
newOrder[i] = ((MenuLabel) components[t++]).getText();
}
}
parentPane.setCurrentOrder(newOrder);
}
}

96
designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabel.java

@ -0,0 +1,96 @@
package com.fr.design.actions.help.alphafine.component;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.utils.DesignUtils;
import javax.swing.BorderFactory;
import javax.swing.plaf.LabelUI;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.function.Function;
/**
* 菜单选项label
*
* @author Link
* @version 11.0
* Created by Link on 2022/9/18
*/
public class MenuLabel extends UILabel {
private static final Color BACKGROUND_COLOR = Color.white;
private static final Color SELECTED_COLOR = new Color(0x419BF9);
private static final Color HOVERED_COLOR = new Color(0xd9ebfe);
private static final int HEIGHT = 23;
private static final int WIDTH = 147;
private MenuLabelPane parentMenu;
private final Function function;
private boolean selected;
public MenuLabel(String text, Function function) {
super(text);
this.function = function;
setOpaque(true);
addMouseListener(createMouseListener());
}
public void setParentMenu(MenuLabelPane menu) {
this.parentMenu = menu;
}
@Override
public void setUI(LabelUI ui) {
super.setUI(ui);
this.setBackground(BACKGROUND_COLOR);
this.setBorder(BorderFactory.createEmptyBorder(2, 10, 1, 10));
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
this.setFont(DesignUtils.getDefaultGUIFont().applySize(12));
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
if (selected) {
parentMenu.setNoneSelected();
setBackground(SELECTED_COLOR);
function.apply(this);
this.selected = true;
} else {
setBackground(BACKGROUND_COLOR);
this.selected = false;
}
}
MouseListener createMouseListener() {
return new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
setSelected(true);
}
@Override
public void mouseEntered(MouseEvent e) {
super.mouseEntered(e);
if (!selected) {
setBackground(HOVERED_COLOR);
}
}
@Override
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
if (!selected) {
setBackground(BACKGROUND_COLOR);
}
}
};
}
}

34
designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabelPane.java

@ -0,0 +1,34 @@
package com.fr.design.actions.help.alphafine.component;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.util.List;
/**
* 简单菜单面板
*
* @author Link
* @version 11.0
* Created by Link on 2022/9/18
*/
public class MenuLabelPane extends JPanel {
private static final int GAP = 1;
private List<MenuLabel> labels;
public MenuLabelPane(List<MenuLabel> labels) {
this.labels = labels;
setLayout(new FlowLayout(FlowLayout.CENTER, GAP, GAP));
for (MenuLabel label : labels) {
label.setParentMenu(this);
add(label);
}
}
public void setNoneSelected() {
for (MenuLabel label : labels) {
label.setSelected(false);
}
}
}

19
designer-base/src/main/java/com/fr/design/actions/help/replace/ITReplaceOperator.java

@ -0,0 +1,19 @@
package com.fr.design.actions.help.replace;
/**
* 定义一些底层操作
*
* @author Destiny.Lin
* @version 11.0
* created by Destiny.Lin on 2022-09-27
*/
public interface ITReplaceOperator {
/**
* 关闭面板
*/
void close();
}

1
designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java

@ -88,7 +88,6 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS
}
protected void renameConnection(final String oldName, final String newName) {
tableDataConfig.renameTableData(oldName, newName);
StrategyEventsNotifier.modifyDataSet(DSMapping.ofServerDS(new DsNameTarget(oldName)));
}
};

33
designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java

@ -27,11 +27,7 @@ public abstract class ClipboardFilter {
}
public static <T> T cut(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) {
for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) {
if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).cut(selection);
}
@ -40,10 +36,7 @@ public abstract class ClipboardFilter {
}
public static <T> T copy(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) {
for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) {
if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).copy(selection);
}
@ -52,15 +45,27 @@ public abstract class ClipboardFilter {
}
public static <T> T paste(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) {
for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) {
if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).paste(selection);
}
}
return selection;
}
private static Set<ClipboardHandlerProvider> getClipboardHandlerProviders() {
Set<ClipboardHandlerProvider> providers = new HashSet<>();
for (ClipboardHandlerProvider clipboardHandlerProvider : clipboardHandlerProviders) {
providers.add(clipboardHandlerProvider);
}
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> pluginProviders = manager.getArray(ClipboardHandlerProvider.XML_TAG);
for (ClipboardHandlerProvider clipboardHandlerProvider : pluginProviders) {
providers.add(clipboardHandlerProvider);
}
return providers;
}
}

28
designer-base/src/main/java/com/fr/design/carton/CartonFiles.java

@ -0,0 +1,28 @@
package com.fr.design.carton;
import java.io.File;
public class CartonFiles {
private File easyCheckerFile;
private File timerCheckerFile;
public CartonFiles() {
}
public File getEasyCheckerFile() {
return easyCheckerFile;
}
public void setEasyCheckerFile(File easyCheckerFile) {
this.easyCheckerFile = easyCheckerFile;
}
public File getTimerCheckerFile() {
return timerCheckerFile;
}
public void setTimerCheckerFile(File timerCheckerFile) {
this.timerCheckerFile = timerCheckerFile;
}
}

161
designer-base/src/main/java/com/fr/design/carton/CartonThreadExecutorPool.java

@ -0,0 +1,161 @@
package com.fr.design.carton;
import com.fr.base.SimpleDateFormatThreadSafe;
import com.fr.design.i18n.Toolkit;
import com.fr.json.JSONObject;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
public class CartonThreadExecutorPool extends ThreadPoolExecutor {
private static final int MAX_LIVE_TIME = 3000;
private static final int MAX_WORKER_THREADS = 10;
/**
* 开启间隔检测后两次检测的相隔时间ms
*/
private static final long CHECK_INTERVAL_MS = 100;
private final ThreadLocal<StackTraceElement[]> startReportedStack = new ThreadLocal<>();
private volatile static CartonThreadExecutorPool cartonThreadExecutorPool;
private static final ConcurrentHashMap<Long, ThreadInfo> concurrentHashMap = new ConcurrentHashMap<>();
private static final SimpleDateFormatThreadSafe simpleDateFormatThreadSafe = new SimpleDateFormatThreadSafe();
private final static AtomicLong hangCount = new AtomicLong(0);
private Timer timer;
/**
* 一个变量用于控制easy监测模式的开关
*/
private boolean easyWitch = false;
public boolean isEasyWitch() {
return easyWitch;
}
public void setEasyWitch(boolean easyWitch) {
this.easyWitch = easyWitch;
}
private static class ThreadInfo {
private ThreadInfo () {
hangNumber = hangCount.getAndAdd(1);
}
private long hangNumber;
private final Thread eventThread = Thread.currentThread();
private StackTraceElement[] lastReportedStack;
private final long startTime = System.currentTimeMillis();
public void checkForHang() {
if (timeSoFar() > MAX_LIVE_TIME) {
examineHang();
}
}
private long timeSoFar() {
return (System.currentTimeMillis() - startTime);
}
private void examineHang() {
StackTraceElement[] currentStack = eventThread.getStackTrace();
if (lastReportedStack!=null && EventDispatchThreadHangMonitor.stacksEqual(currentStack, lastReportedStack)) {
return;
}
lastReportedStack = currentStack;
String stackTrace = EventDispatchThreadHangMonitor.stackTraceToString(currentStack);
JSONObject jsonObject = new JSONObject();
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormatThreadSafe.format(System.currentTimeMillis()));
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + hangNumber);
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar() + "ms");
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace);
EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG);
EventDispatchThreadHangMonitor.checkForDeadlock();
}
}
/**
* 来自SwingWorker类
*/
public static ThreadFactory threadFactory =
new ThreadFactory() {
final ThreadFactory defaultFactory =
Executors.defaultThreadFactory();
@Override
public Thread newThread(final Runnable r) {
Thread thread =
defaultFactory.newThread(r);
thread.setName("SwingWorker-"
+ thread.getName());
thread.setDaemon(true);
return thread;
}
};
public static CartonThreadExecutorPool getTimerThreadExecutorPool () {
if (cartonThreadExecutorPool == null) {
synchronized (CartonThreadExecutorPool.class) {
if (cartonThreadExecutorPool == null) {
cartonThreadExecutorPool =
new CartonThreadExecutorPool(MAX_WORKER_THREADS, MAX_WORKER_THREADS,
10L, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(),threadFactory
);
}
}
}
return cartonThreadExecutorPool;
}
private CartonThreadExecutorPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
simpleDateFormatThreadSafe.applyPattern("yyyy-MM-dd HH:mm:ss");
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
startReportedStack.set(t.getStackTrace());
concurrentHashMap.put(t.getId(), new ThreadInfo());
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
long currentThreadId = Thread.currentThread().getId();
long runTime = (System.currentTimeMillis() - concurrentHashMap.get(currentThreadId).startTime);
//加~是为了之后输出的时候换行。
if (isEasyWitch() && runTime > MAX_LIVE_TIME) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormatThreadSafe.format(System.currentTimeMillis()));
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "swingWorker_" + concurrentHashMap.get(currentThreadId).hangNumber);
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormatThreadSafe.format(concurrentHashMap.get(currentThreadId).startTime));
jsonObject.put(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), runTime + "ms");
EventDispatchThreadHangMonitor.outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG);
}
concurrentHashMap.remove(currentThreadId);
}
public class Checker extends TimerTask {
@Override
public void run() {
if (cartonThreadExecutorPool == null || concurrentHashMap.isEmpty()) {
return;
}
for (Map.Entry<Long, ThreadInfo> map : concurrentHashMap.entrySet()) {
map.getValue().checkForHang();
}
}
}
public void initTimer() {
timer = new Timer("CheckerSwingWorker",true);
timer.schedule(new Checker(), 0, CHECK_INTERVAL_MS);
}
public void stopTimer() {
if (timer != null) {
timer.cancel();
}
}
}

45
designer-base/src/main/java/com/fr/design/carton/CartonUploadMessage.java

@ -0,0 +1,45 @@
package com.fr.design.carton;
public class CartonUploadMessage {
private String hangCount;
private String slowTime;
private String threadTime;
private String info;
public CartonUploadMessage() {
}
public String getHangCount() {
return hangCount;
}
public void setHangCount(String hangCount) {
this.hangCount = hangCount;
}
public String getSlowTime() {
return slowTime;
}
public void setSlowTime(String slowTime) {
this.slowTime = slowTime;
}
public String getThreadTime() {
return threadTime;
}
public void setThreadTime(String threadTime) {
this.threadTime = threadTime;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}

408
designer-base/src/main/java/com/fr/design/carton/EventDispatchThreadHangMonitor.java

@ -0,0 +1,408 @@
package com.fr.design.carton;
import com.fr.concurrent.FineExecutors;
import com.fr.design.ui.util.UIUtil;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.ProductConstantsBase;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.SwingUtilities;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.AWTEvent;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 参考自git swinghelper
* 用于卡顿检测
* 主要是两块内容
* 1.获取eventQueue中每个事件的执行时间
* 2.用一个Timer定时去检测当前执行任务的线程
*/
public final class EventDispatchThreadHangMonitor extends EventQueue {
/**
* 日期事件格式
*/
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static final EventDispatchThreadHangMonitor INSTANCE = new EventDispatchThreadHangMonitor();
/**
* 一个timer
*/
private Timer timer;
/**
* 开启间隔检测后两次检测的相隔时间ms
*/
private static final long CHECK_INTERVAL_MS = 100;
/**
* 最大的事件允许执行时间超过该时间则打印堆栈等相关信息
*/
private static final long UNREASONABLE_DISPATCH_DURATION_MS = 1500;
/**
* 事件唯一编码用于方便日志的查看
*/
private static long hangCount = 0;
/**
* 输出日志所在地址
*/
private static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log");
/**
* 类似于一个开关当该值为默认的false启动时定时任务在窗口开启前都不会对执行的事件进行检查
*/
private boolean haveShownSomeComponent = false;
/**
* 该链表为主要的实现定时任务的容器在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表由post方法remove
*/
private final LinkedList<DispatchInfo> dispatches = new LinkedList<DispatchInfo>();
/**
* 一个变量用于控制easy监测模式的开关
*/
private boolean easyWitch = false;
private static ScheduledExecutorService scheduledExecutorService;
public boolean isEasyWitch() {
return easyWitch;
}
public void setEasyWitch(boolean easyWitch) {
this.easyWitch = easyWitch;
}
/**
* 一个变量用于记录Timer的开关
*/
public boolean isTimerWitch() {
return timerWitch;
}
public void setTimerWitch(boolean timerWitch) {
this.timerWitch = timerWitch;
}
private boolean timerWitch = false;
private synchronized static long getHangCount() {
return hangCount++;
}
/**
* @param a can not be null
* @param b can not be null
* @return
*/
public static boolean stacksEqual(@NotNull StackTraceElement[] a, @NotNull StackTraceElement[] b) {
if (!ArrayUtils.isSameLength(a, b)) {
return false;
}
for (int i = 0; i < a.length; ++i) {
if (!a[i].equals(b[i])) {
return false;
}
}
return true;
}
/**
* 用于判断是不是特定的堆栈
*/
public static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) {
return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative;
}
/**
* 用于判断某个堆栈是否在等待另一个事件
* 取当前堆栈前三层判断是是不是匹配等待堆栈的格式
*/
public static boolean isWaitingForNextEvent(StackTraceElement[] currentStack) {
return currentStack != null && currentStack.length >= 3 &&
stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true)
&& stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false)
&& stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false);
}
/**
* event事件的包装类
*/
public static class DispatchInfo {
// 上一次被打印的堆栈ou
private StackTraceElement[] lastReportedStack;
//获取执行该事件的线程
private final Thread eventDispatchThread = Thread.currentThread();
//在队列中等待执行的事件最后未执行的时间,当有一个事件执行完后就遍历dispatches给该值赋当前时间
private long lastDispatchTimeMillis = System.currentTimeMillis();
//事件开始的时间
private final long startDispatchTimeMillis = System.currentTimeMillis();
//事件编号
private long hangNumber;
//构造函数,给当前对象赋一个递增的唯一编号
public DispatchInfo() {
hangNumber = getHangCount();
}
//定时调度任务检测的入口,如果执行时间大于设定的值就进入examineHang()方法
public void checkForHang() {
if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) {
examineHang();
}
}
//超时堆栈的具体处理
private void examineHang() {
//获取执行线程的当前堆栈
StackTraceElement[] currentStack = eventDispatchThread.getStackTrace();
if (isWaitingForNextEvent(currentStack)) {
return;
}
//某个事件执行时间很长,定时处理时可能会连续打很多个堆栈,对同一个事件的相同堆栈只打一次
if (lastReportedStack !=null && stacksEqual(lastReportedStack, currentStack)) {
return;
}
String stackTrace = stackTraceToString(currentStack);
lastReportedStack = currentStack;
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.format(System.currentTimeMillis()));
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber);
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Duration_Task_Execute"), timeSoFar() + "ms");
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info"), stackTrace);
outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.TIMER_CHECK_FLAG);
checkForDeadlock();
}
//记录连续运行了多长时间
private long timeSoFar() {
return (System.currentTimeMillis() - lastDispatchTimeMillis);
}
//记录一个事件从被分发到结束的总运行时间
private long totalTime() {
return (System.currentTimeMillis() - startDispatchTimeMillis);
}
//事件处理完后的时间判断
public void dispose() {
if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) {
exportCartonLog(true);
} else if (lastReportedStack != null){
exportCartonLog(false);
}
}
/**
*
* @param flag 判断一下输出日志时要输出哪个时间
*/
private void exportCartonLog(boolean flag) {
JSONObject jsonObject = new JSONObject();
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time"), simpleDateFormat.format(System.currentTimeMillis()));
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number"), "eventQueue_" + hangNumber);
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Start_Time"), simpleDateFormat.format(startDispatchTimeMillis));
if (flag) {
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), timeSoFar() + "ms");
} else {
jsonObject.put(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time"), totalTime() + "ms");
}
outPutJournalLog(jsonObject.toString(), SwitchForSwingChecker.EASY_CHECK_FLAG);
}
}
public static void outPutJournalLog(String message, int flag) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(System.currentTimeMillis());
String filename = flag == SwitchForSwingChecker.EASY_CHECK_FLAG ? SwitchForSwingChecker.EASY_CHECKER_FILE_NAME: SwitchForSwingChecker.TIMER_CHECKER_FILE_NAME;
String[] split = date.split("-");
int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]);
String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date);
File dirFile = new File(dirPath);
File file = new File( StableUtils.pathJoin(dirPath, filename));
try {
if (!file.exists()) {
if (!dirFile.exists()) {
dirFile.mkdirs();
}
file.createNewFile();
}
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true));
String outputMessage = new StringBuilder(message.replaceAll("~", "\r\n")).append(",").append("\r\n").toString();
bufferedWriter.write(outputMessage);
bufferedWriter.close();
} catch (IOException e) {
FineLoggerFactory.getLogger().error("output fail", e);
}
}
private EventDispatchThreadHangMonitor() {
}
/**
* 参考SwingExplorer,在处理模态框时没有做特殊处理也不会输出卡顿堆栈
* 原因是SwingExplorer窗口一直有一个监听事件不断的addremove
* 由于卡顿日志输出的是事件连续执行的时间所以一个长时间存在的模态框被不断重复的监听事件刷新时间就不会输出了
* 当检测开关打开后在这里模拟一下监听事件给个不耗时的任务就可以
*/
public void startFilterModalWindow() {
scheduledExecutorService = FineExecutors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//不用干事,切个片就可以
}
});
}
}, 0, 500, TimeUnit.MILLISECONDS);
}
public void stopFilterModalWindow() {
if (scheduledExecutorService != null) {
scheduledExecutorService.shutdown();
}
}
/**
* Sets up a timer to check for hangs frequently.
* 初始化一个Timer
*/
public void initTimer() {
final long initialDelayMs = 0;
final boolean daemon = true;
timer = new Timer("EventDispatchThreadHangMonitor", daemon);
timer.schedule(new HangChecker(), initialDelayMs, CHECK_INTERVAL_MS);
}
/**
* /消除Timer
*/
public void stopTimer() {
if (timer != null) {
timer.cancel();
}
}
/**
* /定时执行的任务
*/
public class HangChecker extends TimerTask {
@Override
public void run() {
synchronized (dispatches) {
//如果链表为空或者窗口还没启开,定时检测就不进行
if (dispatches.isEmpty() || !haveShownSomeComponent) {
return;
}
dispatches.getLast().checkForHang();
}
}
}
/**
* 将swing中默认的EventQueue换成自己的
*/
public static void initMonitoring() {
UIUtil.invokeLaterIfNeeded(() -> Toolkit.getDefaultToolkit().getSystemEventQueue().push(INSTANCE));
}
/**
* Overrides EventQueue.dispatchEvent to call our pre and post hooks either
* side of the system's event dispatch code.
* 重写
*/
@Override
protected void dispatchEvent(AWTEvent event) {
//如果两个开关都没开,那就不走重写方法了
if (!isEasyWitch() && !isTimerWitch()) {
super.dispatchEvent(event);
} else {
try {
preDispatchEvent();
super.dispatchEvent(event);
} finally {
postDispatchEvent();
if (!haveShownSomeComponent &&
event instanceof WindowEvent && event.getID() == WindowEvent.WINDOW_OPENED) {
haveShownSomeComponent = true;
}
}
}
}
/**
* Starts tracking a dispatch.
*/
private synchronized void preDispatchEvent() {
synchronized (dispatches) {
dispatches.addLast(new DispatchInfo());
}
}
/**
* Stops tracking a dispatch.
*/
private synchronized void postDispatchEvent() {
synchronized (dispatches) {
DispatchInfo justFinishedDispatch = dispatches.removeLast();
if (isEasyWitch()) {
justFinishedDispatch.dispose();
}
//嵌套最深的事件执行完毕后刷新链表中其他事件的lastDispatchTimeMillis
Thread currentEventDispatchThread = Thread.currentThread();
for (DispatchInfo dispatchInfo : dispatches) {
if (dispatchInfo.eventDispatchThread == currentEventDispatchThread) {
dispatchInfo.lastDispatchTimeMillis = System.currentTimeMillis();
}
}
}
}
/**
* 检查死锁
*/
public static void checkForDeadlock() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.findDeadlockedThreads();
if (threadIds == null) {
return;
}
FineLoggerFactory.getLogger().warn("deadlock detected involving the following threads:");
ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
for (ThreadInfo info : threadInfos) {
FineLoggerFactory.getLogger().warn("Thread # {} {} ( {} ) waiting on {} held by {} {}", info.getThreadId(), info.getThreadName(),
info.getThreadState(), info.getLockName(), info.getLockOwnerName(), stackTraceToStringForConsole(info.getStackTrace()));
}
}
public static String stackTraceToString(StackTraceElement[] stackTrace) {
StringBuilder result = new StringBuilder();
for (StackTraceElement stackTraceElement : stackTrace) {
String indentation = " ";
result.append("~").append(indentation).append(stackTraceElement);
}
return result.toString();
}
public static String stackTraceToStringForConsole(StackTraceElement[] stackTrace) {
StringBuilder result = new StringBuilder();
for (StackTraceElement stackTraceElement : stackTrace) {
String indentation = " ";
result.append("\r\n").append(indentation).append(stackTraceElement);
}
return result.toString();
}
}

406
designer-base/src/main/java/com/fr/design/carton/FeedbackToolboxDialog.java

@ -0,0 +1,406 @@
package com.fr.design.carton;
import com.fr.decision.webservice.v10.log.download.utils.LogZipUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.gui.date.UIDatePicker;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.env.detect.ui.EnvDetectorDialog;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.FILEFactory;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.general.GeneralUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import org.jetbrains.annotations.Nullable;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.filechooser.FileSystemView;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.ParseException;
import java.util.List;
import java.util.Objects;
public class FeedbackToolboxDialog extends JDialog {
private UIDatePicker uiDatePicker;
private JPanel generalSettingPanel = null;
private UICheckBox easyCheckerButton = null;
private UICheckBox timerCheckerButton = null;
private UIButton uploadButton = null;
private UILabel exportLogLabel = null;
private final Color backgroundColor = new Color(240, 240, 243, 1);
private final Color lineColor = new Color(192, 192, 192, 120);
private JPanel body = null;
private static final String WORK_SPACE_PATH = "reportlets";
private static final int BUFFER_SIZE = 2 * 1024;
public FeedbackToolboxDialog(Frame owner) {
super(owner, Toolkit.i18nText("Fine-Design_Basic_Carton_Feedback_ToolBox"));
setResizable(false);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
createBodyPanel();
add(body);
setSize(body.getPreferredSize());
setSwitches(!StringUtils.isEmpty(GeneralUtils.objectToString(uiDatePicker.getSelectedItem())));
repaint();
GUICoreUtils.centerWindow(this);
}
public void createBodyPanel() {
JPanel body = FRGUIPaneFactory.createBorderLayout_L_Pane();
body.setBackground(backgroundColor);
JPanel titlePane = createTitlePane();
JPanel tailPane = createTailPane();
JPanel midPane = createMidPane();
JPanel infoPane = createInfoPane();
body.add(titlePane, BorderLayout.NORTH);
body.add(tailPane, BorderLayout.SOUTH);
body.add(midPane, BorderLayout.CENTER);
midPane.add(infoPane, BorderLayout.NORTH);
Dimension dimension = new Dimension(662, 556);
body.setPreferredSize(dimension);
this.body = body;
}
private JPanel createInfoPane() {
JPanel northPane = FRGUIPaneFactory.createNColumnGridInnerContainer_Pane(2, 10, 10);
UILabel title = new UILabel();
title.setText(" " + Toolkit.i18nText("Fine-Design_Basic_Carton_Record_Lag_Time") + ": ");
//判断一下当天是否有卡顿日志记录,如果有将日期设置为当天,如果没有设置为空
boolean cartonExists = SwitchForSwingChecker.isCartonExists();
if (cartonExists) {
this.uiDatePicker = new UIDatePicker(UIDatePicker.STYLE_CN_DATE1, this);
} else {
this.uiDatePicker = new UIDatePicker(UIDatePicker.STYLE_CN_DATE1, null, this);
}
Dimension dimension = new Dimension(160, 100);
uiDatePicker.setPreferredSize(dimension);
northPane.add(GUICoreUtils.createFlowPane(new Component[]{title, uiDatePicker}, FlowLayout.LEFT));
exportLogLabel = new UILabel();
exportLogLabel.setText(Toolkit.i18nText("Fine-Design_Basic_Carton_Export_Carton_Log"));
exportLogLabel.setForeground(UIConstants.FLESH_BLUE);
exportLogLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (exportLogLabel.isEnabled()) {
exportLogFile();
}
}
@Override
public void mouseEntered(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof UILabel) {
((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
});
northPane.add(GUICoreUtils.createFlowPane(exportLogLabel, FlowLayout.RIGHT));
return northPane;
}
private void exportLogFile() {
String selectDate = GeneralUtils.objectToString(uiDatePicker.getSelectedItem());
FILEChooserPane fileChooserPane = FILEChooserPane.getInstance();
StringBuilder fileName = new StringBuilder();
fileName.append(selectDate).append(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Log"));
fileChooserPane.setFileNameTextField(fileName.toString(), " ");
fileChooserPane.removeAllFilter();
fileChooserPane.addChooseFILEFilter(new ChooseFileFilter("zip", Toolkit.i18nText("Fine-Design_Basic_Carton_Compile_File")));
//默认选择桌面
FILE desktop = FILEFactory.createFILE(FILEFactory.FILE_PREFIX + FileSystemView.getFileSystemView().getHomeDirectory().getPath());
fileChooserPane.setCurrentDirectory(desktop);
int chooseResult = fileChooserPane.showSaveDialog(DesignerContext.getDesignerFrame());
if (chooseResult == 0) {
FILE selectedFile = fileChooserPane.getSelectedFILE();
String path = selectedFile.getPath();
//selectDate 2002-03-09例子
String[] split = selectDate.split("-");
int month = Integer.parseInt(split[1]);
String sourceFilePath = StableUtils.pathJoin(SwitchForSwingChecker.JOURNAL_FILE_PATH, split[0], "month-" + month, selectDate);
File sourceFile = new File(sourceFilePath);
if (sourceFile.exists()) {
exportCartonLog(sourceFile, path, sourceFilePath);
}
fileChooserPane.removeAllFilter();
}
}
private JPanel createTailPane() {
JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
tailPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, lineColor));
JPanel actionsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionsPanel.setLayout(FRGUIPaneFactory.createM_BorderLayout());
{
uploadButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Carton_Upload_Carton_Log"));
uploadButton.addActionListener((e) -> {
try {
List<CartonUploadMessage> list = SwitchForSwingChecker.uploadJournalLog(uiDatePicker.getSelectedDate());
if (list.isEmpty()) {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine_Design_Basic_Upload_Fail"), UIManager.getString("OptionPane.messageDialogTitle"), JOptionPane.ERROR_MESSAGE);
} else {
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_Upload_Success"));
}
} catch (ParseException parseException) {
FineLoggerFactory.getLogger().error("parse error", parseException);
}
});
actionsPanel.add(uploadButton, BorderLayout.WEST);
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
cancelButton.addActionListener((e) -> {
setVisible(false);
EnvDetectorDialog envDetectorDialog = new EnvDetectorDialog(DesignerContext.getDesignerFrame());
envDetectorDialog.setVisible(true);
dispose();
});
actionsPanel.add(cancelButton, BorderLayout.EAST);
}
UIButton currencySetButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Carton_General_Settings"));
currencySetButton.addActionListener((e -> {
createGeneralSettingPanel();
this.remove(body);
this.add(generalSettingPanel);
setSize(generalSettingPanel.getPreferredSize());
repaint();
setVisible(true);
}));
tailPanel.add(actionsPanel, BorderLayout.EAST);
tailPanel.add(currencySetButton, BorderLayout.WEST);
return tailPanel;
}
private JPanel createTitlePane() {
JPanel titlePane = FRGUIPaneFactory.createBorderLayout_M_Pane();
titlePane.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, lineColor));
UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Journal_Record"));
uiLabel.setForeground(UIConstants.FLESH_BLUE);
titlePane.add(uiLabel, BorderLayout.WEST);
return titlePane;
}
private JPanel createMidPane() {
JPanel midPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
return midPanel;
}
/**
* 下面是通用设置的面板
*/
private void createGeneralSettingPanel() {
JPanel generalSettingPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
JPanel tailPaneInGeneralSettings = createTailPaneInGeneralSettings();
generalSettingPanel.add(tailPaneInGeneralSettings, BorderLayout.SOUTH);
JPanel titlePaneInGeneralSettings = createTitlePaneInGeneralSettings();
generalSettingPanel.add(titlePaneInGeneralSettings, BorderLayout.NORTH);
JPanel midPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
generalSettingPanel.add(midPanel, BorderLayout.CENTER);
JPanel infoPane = createInfoPanelInGeneralSettings();
midPanel.add(infoPane, BorderLayout.NORTH);
Dimension dimension = new Dimension(662, 556);
generalSettingPanel.setPreferredSize(dimension);
generalSettingPanel.setBackground(backgroundColor);
this.generalSettingPanel = generalSettingPanel;
}
private JPanel createTitlePaneInGeneralSettings() {
JPanel titlePane = FRGUIPaneFactory.createBorderLayout_L_Pane();
titlePane.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, lineColor));
UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Journal_Record") + "/");
uiLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
createBodyPanel();
remove(generalSettingPanel);
add(body);
setPreferredSize(body.getPreferredSize());
setSwitches(!StringUtils.isEmpty(GeneralUtils.objectToString(uiDatePicker.getSelectedItem())));
repaint();
setVisible(true);
}
@Override
public void mouseEntered(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof UILabel) {
((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
});
UILabel uiCurrentLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_General_Settings"));
uiCurrentLabel.setForeground(UIConstants.FLESH_BLUE);
titlePane.add(GUICoreUtils.createFlowPane(new Component[]{uiLabel, uiCurrentLabel}, FlowLayout.LEFT));
return titlePane;
}
private JPanel createTailPaneInGeneralSettings() {
JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
tailPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, lineColor));
JPanel actionsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionsPanel.setLayout(FRGUIPaneFactory.createM_BorderLayout());
{
UIButton confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Save"));
confirmButton.addActionListener((e) -> {
if (easyCheckerButton.isSelected()) {
SwitchForSwingChecker.startEasyChecker();
} else {
SwitchForSwingChecker.stopEasyChecker();
}
if (timerCheckerButton.isSelected()) {
SwitchForSwingChecker.startTimerChecker();
} else {
SwitchForSwingChecker.stopTimerChecker();
}
createBodyPanel();
remove(generalSettingPanel);
add(body);
setPreferredSize(body.getPreferredSize());
setSwitches(!StringUtils.isEmpty(GeneralUtils.objectToString(uiDatePicker.getSelectedItem())));
repaint();
setVisible(true);
});
actionsPanel.add(confirmButton, BorderLayout.WEST);
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
cancelButton.addActionListener((e) -> {
createBodyPanel();
remove(generalSettingPanel);
add(body);
setPreferredSize(body.getPreferredSize());
repaint();
setVisible(true);
});
actionsPanel.add(cancelButton, BorderLayout.EAST);
}
tailPanel.add(actionsPanel, BorderLayout.EAST);
return tailPanel;
}
private JPanel createInfoPanelInGeneralSettings() {
JPanel infoPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(1);
easyCheckerButton = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Carton_Operation_Time_Consuming_Detection"));
timerCheckerButton = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Carton_Carton_Operation_Class_Capture"));
easyCheckerButton.setSelected(SwitchForSwingChecker.isEasyChecker());
timerCheckerButton.setSelected(SwitchForSwingChecker.isCheckerTimerSwitch());
infoPane.add(GUICoreUtils.createFlowPane(easyCheckerButton, FlowLayout.LEFT));
infoPane.add(GUICoreUtils.createFlowPane(timerCheckerButton, FlowLayout.LEFT));
return infoPane;
}
@Override
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
EnvDetectorDialog envDetectorDialog = new EnvDetectorDialog(DesignerContext.getDesignerFrame());
envDetectorDialog.setVisible(true);
}
}
/**
* 上传和导出卡顿日志的可用化处理如果没有选择日期就不可用
*/
public void setSwitches(boolean flag) {
uploadButton.setEnabled(flag);
exportLogLabel.setEnabled(flag);
}
/**
* 导出卡顿日志到本地或远程服务器WEB-INF下
*
* @param sourceFile 导出的卡顿日志所在文件夹
* @param path 文件需要导出到的路径
* @param sourceFilePath 导出的卡顿日志所在文件夹的路径
*/
private void exportCartonLog(File sourceFile, String path, String sourceFilePath) {
File[] files = sourceFile.listFiles();
if (!Objects.isNull(files)) {
try {
if (path.startsWith(WORK_SPACE_PATH)) {
if (WorkContext.getCurrent().isLocal()) {
String curEnvName = DesignerEnvManager.getEnvManager().getCurEnvName();
DesignerWorkspaceInfo workspaceInfo = DesignerEnvManager.getEnvManager().getWorkspaceInfo(curEnvName);
String workspaceInfoPath = workspaceInfo.getPath();
path = StableUtils.pathJoin(workspaceInfoPath, path);
LogZipUtils.compress(files, path, false);
} else {
String sourceFilePathZip = sourceFilePath + ".zip";
LogZipUtils.compress(files, sourceFilePathZip, false);
byte[] bytesByFile = getBytesByFile(sourceFilePathZip);
WorkContext.getWorkResource().write(path, bytesByFile);
LogZipUtils.delDir(sourceFilePathZip);
}
} else {
LogZipUtils.compress(files, path, false);
}
FineJOptionPane.showMessageDialog(this, Toolkit.i18nText("Fine-Design_Report_Exported_Successfully"));
} catch (Exception exception) {
FineJOptionPane.showMessageDialog(this, Toolkit.i18nText("Fine-Design_Report_Export_Failed"), UIManager.getString("OptionPane.messageDialogTitle"), JOptionPane.ERROR_MESSAGE);
FineLoggerFactory.getLogger().error("export file fail", exception);
}
}
}
/**
* 根据文件地址将文件转换成byte[]
*
* @param pathStr 本地文件目录
* @return 本地文件转成的byte[]
*/
@Nullable
private static byte[] getBytesByFile(String pathStr) {
File file = new File(pathStr);
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_SIZE);
byte[] b = new byte[BUFFER_SIZE];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
byte[] data = bos.toByteArray();
bos.close();
return data;
} catch (Exception e) {
FineLoggerFactory.getLogger().error("reading local file fail", e);
}
return null;
}
}

36
designer-base/src/main/java/com/fr/design/carton/MonthlyCartonFile.java

@ -0,0 +1,36 @@
package com.fr.design.carton;
import java.io.File;
public class MonthlyCartonFile {
private File currentMonthFile;
private File lastMonthFile;
private File nextMonthFile;
public MonthlyCartonFile() {
}
public File getCurrentMonthFile() {
return currentMonthFile;
}
public void setCurrentMonthFile(File currentMonthFile) {
this.currentMonthFile = currentMonthFile;
}
public File getLastMonthFile() {
return lastMonthFile;
}
public void setLastMonthFile(File lastMonthFile) {
this.lastMonthFile = lastMonthFile;
}
public File getNextMonthFile() {
return nextMonthFile;
}
public void setNextMonthFile(File nextMonthFile) {
this.nextMonthFile = nextMonthFile;
}
}

312
designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java

@ -0,0 +1,312 @@
package com.fr.design.carton;
import com.fr.design.i18n.Toolkit;
import com.fr.general.GeneralUtils;
import com.fr.json.JSON;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstantsBase;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import sun.awt.AppContext;
import javax.swing.SwingWorker;
import java.io.IOException;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;
public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
/**
* Designer4Debug类名
*/
private static final String DEBUG_MAIN_CLASS_NAME = "com.fr.start.Designer4Debug";
/**
* XML标签
*/
public static final String XML_TAG = "SwitchForSwingChecker";
/**
* 定时任务的开关
*/
private static boolean checkerTimerSwitch = false;
/**
* 简单记录事件执行时间的开关
*/
private static boolean easyChecker = false;
/**
* 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测
*/
public static final int TIMER_CHECK_FLAG = 0;
public static final int EASY_CHECK_FLAG = 1;
/**
* 日志存储地址
*/
public static final String JOURNAL_FILE_PATH = StableUtils.pathJoin(ProductConstantsBase.getEnvHome(), "journal_log");
public static final String EASY_CHECKER_FILE_NAME = "easy_check_log.csv";
public static final String TIMER_CHECKER_FILE_NAME = "timer_check_log.csv";
public static boolean isCheckerTimerSwitch() {
return checkerTimerSwitch;
}
public static boolean isEasyChecker() {
return easyChecker;
}
public static volatile SwitchForSwingChecker switchForSwingChecker = new SwitchForSwingChecker();
public static SwitchForSwingChecker getInstance() {
return switchForSwingChecker;
}
public static void startTimerChecker() {
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
checkerTimerSwitch = true;
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow();
}
}
}
public static void stopTimerChecker() {
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.stopTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().stopTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(false);
checkerTimerSwitch = false;
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.stopFilterModalWindow();
}
}
}
public static void startEasyChecker() {
if (!easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true);
easyChecker = true;
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow();
}
}
}
public static void stopEasyChecker() {
if (easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(false);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(false);
easyChecker = false;
if (!checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.stopFilterModalWindow();
}
}
}
/**
* 获取文件名字以及判断文件是否存在
*/
private static CartonFiles getFiles(String date) {
String[] split = date.split("-");
int month = StringUtils.isEmpty(split[1]) ? -1 : Integer.parseInt(split[1]);
String dirPath = StableUtils.pathJoin(JOURNAL_FILE_PATH, split[0], "month-" + month, date);
File file1 = new File(StableUtils.pathJoin(dirPath, EASY_CHECKER_FILE_NAME));
File file2 = new File(StableUtils.pathJoin(dirPath, TIMER_CHECKER_FILE_NAME));
File[] files = new File[2];
files[0] = file1;
files[1] = file2;
CartonFiles cartonFiles = new CartonFiles();
cartonFiles.setEasyCheckerFile(file1);
cartonFiles.setTimerCheckerFile(file2);
return cartonFiles;
}
/**
*处理文件
* 一共四种情况
* 两个文件都不存在
* 文件一存在文件二不存在
* 文件二存在文件一不存在
* 两个文件都存在
*/
private static List<CartonUploadMessage> getCartonLog(File easyFile, File timerFile) {
List<CartonUploadMessage> res = new ArrayList<>();
List<CartonUploadMessage> easyFileCartonLog = getEasyFileCartonLog(easyFile);
List<CartonUploadMessage> timerFileCartonLog = getTimerFileCartonLog(timerFile);
Map<String, CartonUploadMessage> easyFileMap = new HashMap<>();
for (CartonUploadMessage cartonUploadMessage : easyFileCartonLog) {
easyFileMap.put(cartonUploadMessage.getHangCount(), cartonUploadMessage);
res.add(cartonUploadMessage);
}
for (CartonUploadMessage cartonUploadMessage : timerFileCartonLog) {
String hangCount = cartonUploadMessage.getHangCount();
if (easyFileMap.containsKey(hangCount)) {
cartonUploadMessage.setThreadTime(easyFileMap.get(hangCount).getThreadTime());
}
res.add(cartonUploadMessage);
}
return res;
}
private static List<CartonUploadMessage> getTimerFileCartonLog(File file) {
List<CartonUploadMessage> res = new ArrayList<>();
try {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
BufferedReader bufferedReader1 = new BufferedReader(new FileReader(file));
String line1;
while ((line1 = bufferedReader1.readLine()) != null) {
stringBuilder.append(line1);
}
bufferedReader1.close();
stringBuilder.append("]");
JSONArray easyCheckerJSON = JSON.ARRAY.createJSON(GeneralUtils.objectToString(stringBuilder));
for (Object jsonObject : easyCheckerJSON) {
CartonUploadMessage cartonUploadMessage = new CartonUploadMessage();
JSONObject x = (JSONObject) jsonObject;
cartonUploadMessage.setHangCount(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number")));
cartonUploadMessage.setSlowTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time")));
cartonUploadMessage.setThreadTime("undefined");
//这个跟输出到文件中的格式匹配,参考EventDis里的stackTraceToString方法
String indentation = " ";
String logMessage = x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Stack_Info")).replaceAll(indentation, "\r\n ");
cartonUploadMessage.setInfo(logMessage);
res.add(cartonUploadMessage);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error("upload fail", e);
}
return res;
}
private static List<CartonUploadMessage> getEasyFileCartonLog(File file) {
List<CartonUploadMessage> res = new ArrayList<>();
try {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
BufferedReader bufferedReader1 = new BufferedReader(new FileReader(file));
String line1;
while ((line1 = bufferedReader1.readLine()) != null) {
stringBuilder.append(line1);
}
bufferedReader1.close();
stringBuilder.append("]");
JSONArray timerCheckerJSON = JSON.ARRAY.createJSON(GeneralUtils.objectToString(stringBuilder));
for (Object jsonObject : timerCheckerJSON) {
JSONObject x = (JSONObject) jsonObject;
CartonUploadMessage cartonUploadMessage = new CartonUploadMessage();
cartonUploadMessage.setHangCount(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Event_Number")));
cartonUploadMessage.setSlowTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Output_Time")));
cartonUploadMessage.setThreadTime(x.getString(Toolkit.i18nText("Fine-Design_Basic_Carton_Task_Total_Time")));
cartonUploadMessage.setInfo("undefined");
res.add(cartonUploadMessage);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error("upload fail", e);
}
return res;
}
/**
* /埋点方法上传卡顿信息入口
date为 2022-09-08的格式
*/
public static List<CartonUploadMessage> uploadJournalLog(Date dateTime) {
List<CartonUploadMessage> res = new ArrayList<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
CartonFiles files = getFiles(simpleDateFormat.format(dateTime));
File easyCheckerFile = files.getEasyCheckerFile();
File timerCheckerFile = files.getTimerCheckerFile();
if (easyCheckerFile.exists() && timerCheckerFile.exists()) {
return getCartonLog(easyCheckerFile, timerCheckerFile);
} else if (easyCheckerFile.exists()) {
return getEasyFileCartonLog(easyCheckerFile);
} else if (timerCheckerFile.exists()) {
return getTimerFileCartonLog(timerCheckerFile);
} else {
return res;
}
}
/**
* 初始化监控任务主要是替换EventQueue以及SwingWorker执行任务的线程池
*
*/
public static void initThreadMonitoring () {
String mainClass = System.getProperty("sun.java.command");
//判断一下,如果是以Designer4Debug启动,就不注册代码,不然会覆盖掉SwingExplorer,导致其无法使用
if (!StringUtils.equals(mainClass, DEBUG_MAIN_CLASS_NAME)) {
EventDispatchThreadHangMonitor.initMonitoring();
AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool());
}
}
/**
* 判断是否有指定日期的卡顿日志没有就返回false
*/
public static boolean isCartonExists(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String format = simpleDateFormat.format(date);
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH) + 1;
int year = calendar.get(Calendar.YEAR);
File file = new File(StableUtils.pathJoin(JOURNAL_FILE_PATH, String.valueOf(year), "month-" + month, format));
return file.exists();
}
public static boolean isCartonExists() {
return isCartonExists(new Date());
}
private void initSwitchChecker() {
if (easyChecker) {
EventDispatchThreadHangMonitor.INSTANCE.setEasyWitch(true);
CartonThreadExecutorPool.getTimerThreadExecutorPool().setEasyWitch(true);
}
if (checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.initTimer();
CartonThreadExecutorPool.getTimerThreadExecutorPool().initTimer();
EventDispatchThreadHangMonitor.INSTANCE.setTimerWitch(true);
}
if (easyChecker || checkerTimerSwitch) {
EventDispatchThreadHangMonitor.INSTANCE.startFilterModalWindow();
}
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isAttr()) {
checkerTimerSwitch = reader.getAttrAsBoolean("checkerTimerSwitch", false);
easyChecker = reader.getAttrAsBoolean("easyChecker", false);
}
try {
initSwitchChecker();
} catch (Throwable t) {
FineLoggerFactory.getLogger().error("read checker attr fail", t);
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(XML_TAG);
writer.attr("checkerTimerSwitch", checkerTimerSwitch);
writer.attr("easyChecker", easyChecker);
writer.end();
}
}

180
designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java

@ -0,0 +1,180 @@
package com.fr.design.cell;
import com.fr.base.CellBorderSourceFlag;
import com.fr.base.CellBorderStyle;
import com.fr.base.Style;
import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase;
import com.fr.general.IOUtils;
import com.fr.report.cell.TemplateCellElement;
import javax.swing.JPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/3
*/
public class CellRectangleStylePreviewPane extends JPanel {
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png");
private final float transparentBackgroundWidth;
private final float transparentBackgroundHeight;
private static final int ROW_COUNT = 2;
private static final int COLUMN_COUNT = 2;
private final TemplateCellElement[][] cellElementGrid = new TemplateCellElement[ROW_COUNT][COLUMN_COUNT];
private final int[][] borderSourceFlags = new int[ROW_COUNT][COLUMN_COUNT];
private final CellStylePreviewPane[][] cellStylePreviewPaneGrid = new CellStylePreviewPane[ROW_COUNT][COLUMN_COUNT];
public CellRectangleStylePreviewPane(boolean supportInnerBorder) {
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null);
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null);
setLayout(new GridLayout(2, 2));
setOpaque(false);
setBackground(null);
for (int r = 0; r < ROW_COUNT; r++) {
for (int c = 0; c < COLUMN_COUNT; c++) {
CellStylePreviewPane pane = new CellStylePreviewPane(c, r, COLUMN_COUNT, ROW_COUNT, false, false);
TemplateCellElement cellElement = DefaultThemedTemplateCellElementCase.createInstance(c, r);
int flags = CellBorderSourceFlag.INVALID_BORDER_SOURCE;
if (supportInnerBorder) {
flags = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER;
if (r != 0) {
flags |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER;
}
if (r != ROW_COUNT - 1) {
flags |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER;
}
if (c != 0) {
flags |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER;
}
if (c != COLUMN_COUNT - 1) {
flags |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER;
}
}
pane.setStyle(cellElement.getStyle());
add(pane);
cellElementGrid[r][c] = cellElement;
borderSourceFlags[r][c] = flags;
cellStylePreviewPaneGrid[r][c] = pane;
}
}
}
public void setPlainText(String text) {
cellStylePreviewPaneGrid[0][1].setPaintText(text);
cellStylePreviewPaneGrid[1][1].setPaintText(text);
repaint();
}
public void setStyle(Style style, CellBorderStyle borderStyle) {
for (int i = 0; i < ROW_COUNT; i++) {
for (int j = 0; j < COLUMN_COUNT; j++) {
CellStylePreviewPane pane = cellStylePreviewPaneGrid[i][j];
TemplateCellElement cellElement = cellElementGrid[i][j];
int flag = borderSourceFlags[i][j];
cellElement.setStyle(CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, flag));
pane.setStyle(cellElement.getStyle());
}
}
repaint();
}
@Override
public void setPreferredSize(Dimension preferredSize) {
super.setPreferredSize(preferredSize);
int hw = preferredSize.width / 2;
int hh = preferredSize.height / 2;
cellStylePreviewPaneGrid[0][0].setPreferredSize(new Dimension(hw, hh));
cellStylePreviewPaneGrid[0][1].setPreferredSize(new Dimension(hw, hh));
cellStylePreviewPaneGrid[1][0].setPreferredSize(new Dimension(hw, hh));
cellStylePreviewPaneGrid[1][1].setPreferredSize(new Dimension(hw, hh));
}
@Override
public Dimension getPreferredSize() {
Dimension d00 = cellStylePreviewPaneGrid[0][0].getPreferredSize();
Dimension d01 = cellStylePreviewPaneGrid[0][1].getPreferredSize();
Dimension d10 = cellStylePreviewPaneGrid[1][0].getPreferredSize();
Dimension d11 = cellStylePreviewPaneGrid[1][1].getPreferredSize();
int width = Math.max(d00.width + d01.width, d10.width + d11.width);
int height = Math.max(d00.height + d10.height, d01.height + d11.height);
return new Dimension(width, height);
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.clearRect(0, 0, getWidth(), getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
paintTransparentBackground((Graphics2D) g, cellElementGrid[0][0].getStyle());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
super.paint(g);
}
@Override
public Rectangle getBounds() {
return super.getBounds();
}
private void paintTransparentBackground(Graphics2D g2d, Style style) {
float alpha = computeTransparentBackgroundAlpha(style);
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth;
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight;
float maxScale = Math.max(scaleWidth, scaleHeight);
if (maxScale <= 1) {
scaleWidth = scaleHeight = 1;
} else {
scaleHeight = scaleWidth = maxScale;
}
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null);
g2d.setComposite(oldComposite);
}
private float computeTextColorBrightness(Style style) {
Color fontColor = style.getFRFont().getForeground();
return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F;
}
private float computeTransparentBackgroundAlpha(Style style) {
float textBrightness = computeTextColorBrightness(style);
float alpha = 1.0F;
if (textBrightness < 50) {
alpha = 0.2F;
} else if (textBrightness < 160){
alpha = 0.5F;
}
return alpha;
}
}

152
designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java

@ -1,18 +1,27 @@
package com.fr.design.cell;
import com.fr.base.BaseUtils;
import com.fr.base.GraphHelper;
import com.fr.base.NameStyle;
import com.fr.base.ScreenResolution;
import com.fr.base.Style;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.stable.Constants;
import com.fr.stable.unit.PT;
import javax.swing.JPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.List;
/**
* @author Starryi
@ -21,44 +30,69 @@ import java.awt.image.BufferedImage;
*/
public class CellStylePreviewPane extends JPanel {
public static final int MINIMUM_HEIGHT = 40;
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png");
private final float transparentBackgroundWidth;
private final float transparentBackgroundHeight;
private String paintText = "Report";
private Style style = Style.DEFAULT_STYLE;
public CellStylePreviewPane() {
private final int column;
private final int row;
private final int columnSpan;
private final int rowSpan;
private final boolean autoClearCanvas;
private final boolean paintingMosaic;
public CellStylePreviewPane(int column, int row, int columnSpan, int rowSpan, boolean autoClearCanvas, boolean paintingMosaic) {
this.column = column;
this.row = row;
this.columnSpan = columnSpan;
this.rowSpan = rowSpan;
this.autoClearCanvas = autoClearCanvas;
this.paintingMosaic = paintingMosaic;
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null);
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null);
setPreferredSize(new Dimension(0, 0));
}
public void setPaintText(String paintText) {
this.paintText = paintText;
repaint();
}
public void setStyle(Style style) {
this.style = style;
if (style instanceof NameStyle) {
paintText = ((NameStyle) style).getName();
}
repaint();
}
public void setStyle(NameStyle style) {
paintText = style.getName();
setStyle(style.getRealStyle());
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g.clearRect(0, 0, getWidth(), getHeight());
if (autoClearCanvas) {
g2d.clearRect(0, 0, getWidth(), getHeight());
}
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
paintTransparentBackground(g2d, style);
if (paintingMosaic) {
paintTransparentBackground(g2d, style);
}
paintCellStyle(g2d, style);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
private void paintTransparentBackground(Graphics2D g2d, Style style) {
Color fontColor = style.getFRFont().getForeground();
float g = fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F * fontColor.getBlue() * 0.114F;
float alpha = 1.0F;
if (g < 50) {
alpha = 0.2F;
} else if (g < 160){
alpha = 0.5F;
}
float alpha = computeTransparentBackgroundAlpha(style);
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth;
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight;
@ -76,6 +110,23 @@ public class CellStylePreviewPane extends JPanel {
g2d.setComposite(oldComposite);
}
private float computeTextColorBrightness(Style style) {
Color fontColor = style.getFRFont().getForeground();
return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F;
}
private float computeTransparentBackgroundAlpha(Style style) {
float textBrightness = computeTextColorBrightness(style);
float alpha = 1.0F;
if (textBrightness < 50) {
alpha = 0.2F;
} else if (textBrightness < 160){
alpha = 0.5F;
}
return alpha;
}
private void paintCellStyle(Graphics2D g2d, Style style) {
int resolution = ScreenResolution.getScreenResolution();
@ -92,11 +143,78 @@ public class CellStylePreviewPane extends JPanel {
Style.paintContent(g2d, paintText, style, width, height, resolution);
Style.paintBorder(g2d, style, width, height);
paintCellBorder(g2d, style);
}
protected void paintCellBorder(Graphics2D g2d, Style style) {
float adjustLeft = 0;
float adjustTop = 0;
float adjustRight = 0;
float adjustBottom = 0;
if (column == 0) {
adjustLeft = computeHalfSize4StyledBorder(style.getBorderLeft());
}
if (row == 0) {
adjustTop = computeHalfSize4StyledBorder(style.getBorderTop());
}
if (column == columnSpan - 1) {
adjustRight = -computeHalfSize4StyledBorder(style.getBorderRight());
}
if (row == rowSpan - 1) {
adjustBottom = -computeHalfSize4StyledBorder(style.getBorderBottom());
}
g2d.translate(adjustLeft, adjustTop);
Style.paintBorder(g2d, style, getWidth() - adjustLeft + adjustRight, getHeight() - adjustTop + adjustBottom);
g2d.translate(-adjustLeft, -adjustTop);
}
private float computeHalfSize4StyledBorder(int border) {
float size = GraphHelper.getLineStyleSize(border) / 2.0F;
if (border == Constants.LINE_DOUBLE) {
size += GraphHelper.getLineStyleSize(Constants.LINE_THIN) / 2.0F;
} else if (border == Constants.LINE_DOUBLE_DOT) {
size += GraphHelper.getLineStyleSize(Constants.LINE_DOT) / 2.0F;
}
return size;
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
int width = size.width;
int height = size.height;
if (height != 0) {
// 使用者设置了一个高度
return size;
} else if (width == 0) {
// 使用者未设置任何尺寸
return new Dimension(width, MINIMUM_HEIGHT);
} else {
// 使用者设置了宽度,但未设置高度
return getAutoWrapContentPreferredSize(width, height);
}
}
private Dimension getAutoWrapContentPreferredSize(int width, int height) {
int resolution = ScreenResolution.getScreenResolution();
// 计算文本区域高度
final FRFont frFont = style.getFRFont();
final Font rfont = frFont.applyResolutionNP(resolution);
final FontMetrics metrics = GraphHelper.getFontMetrics(rfont);
final int textLineHeight = metrics.getHeight();
final double textLineSpacing = PT.pt2pix(style.getLineSpacing(), resolution);
List<?> textLineList = BaseUtils.getLineTextList(paintText, style, rfont, height, width, resolution);
double textLinesHeight = textLineList.size() * textLineHeight + Math.max(0, textLineList.size() - 1) * textLineSpacing;
height = (int) Math.max(MINIMUM_HEIGHT, textLinesHeight);
return new Dimension(width, height);
}
}

148
designer-base/src/main/java/com/fr/design/components/loading/LoadingPane.java

@ -0,0 +1,148 @@
package com.fr.design.components.loading;
import javax.swing.JComponent;
import javax.swing.Timer;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/4/12
*/
public class LoadingPane extends JComponent implements ActionListener {
private AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
private volatile boolean mIsRunning;
private volatile boolean mIsFadingOut;
private Timer mTimer;
private int mAngle;
private int mFadeCount;
private int mFadeLimit = 15;
private int lines = 12;
private int maxAngle = 360;
private int angleAdd = 30;
public LoadingPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// do nothing
}
});
setLayout(getCoverLayout());
setBackground(null);
setOpaque(false);
}
protected LayoutManager getCoverLayout() {
return new LayoutManager() {
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return parent.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
};
}
@Override
public void paint(Graphics g) {
int w = this.getWidth();
int h = this.getHeight();
super.paint(g);
if (!mIsRunning) {
return;
}
Graphics2D g2 = (Graphics2D) g.create();
float fade = (float) mFadeCount / (float) mFadeLimit;
Composite urComposite = g2.getComposite();
g2.setComposite(composite);
g2.fillRect(0, 0, w, h);
g2.setComposite(urComposite);
int s = Math.min(w, h) / 50;
int cx = w / 2;
int cy = h / 2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.setPaint(Color.BLACK);
g2.rotate(Math.PI * mAngle / 180, cx, cy);
for (int i = 0; i < lines; i++) {
float scale = (11.0f - (float) i) / 11.0f;
g2.drawLine(cx + s, cy, cx + s * 2, cy);
g2.rotate(-Math.PI / 6, cx, cy);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, scale * fade));
}
g2.dispose();
}
@Override
public void actionPerformed(ActionEvent e) {
if (mIsRunning) {
repaint();
mAngle += angleAdd;
if (mAngle >= maxAngle) {
mAngle = 0;
}
if (mIsFadingOut) {
if (--mFadeCount == 0) {
mIsRunning = false;
mTimer.stop();
}
} else if (mFadeCount < mFadeLimit) {
mFadeCount++;
}
}
}
public void start() {
if (mIsRunning) {
return;
}
mIsRunning = true;
mIsFadingOut = false;
mFadeCount = 0;
int fps = 24;
int tick = 1000 / fps;
mTimer = new Timer(tick, this);
mTimer.start();
}
public void stop() {
mIsRunning = false;
mIsFadingOut = true;
}
}

21
designer-base/src/main/java/com/fr/design/components/notification/NotificationAction.java

@ -0,0 +1,21 @@
package com.fr.design.components.notification;
/**
* created by Harrison on 2022/05/24
**/
public interface NotificationAction {
/**
* 行为名
*
* @return 名称
*/
String name();
/**
* 行为动作
*
* @param args 参数
*/
void run(Object... args);
}

391
designer-base/src/main/java/com/fr/design/components/notification/NotificationDialog.java

@ -0,0 +1,391 @@
package com.fr.design.components.notification;
import com.fr.base.function.ThrowableRunnable;
import com.fr.base.svg.IconUtils;
import com.fr.design.components.page.PageControlModel;
import com.fr.design.components.page.PageControlPanel;
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.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.utils.LinkStrUtils;
import com.fr.env.detect.base.EnvDetectorConfig;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Desktop;
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.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* 右下角的提醒 <a href="https://kms.fineres.com/pages/viewpage.action?pageId=388333688">异常提醒</a>
* 相关使用方式见 <a href="https://kms.fineres.com/pages/viewpage.action?pageId=415212013">提醒组件</a>
*
* created by Harrison on 2022/05/24
**/
public class NotificationDialog extends JDialog {
/**
* 通知框的内部高度
*/
private static final int CONTENT_INNER_HEIGHT = 60;
/**
* 通知框如果出现滚动条后的内部宽度
*/
private static final int CONTENT_SCROLL_WIDTH = 280;
private static final int CONTENT_WIDTH = 300;
private static final int CONTENT_HEIGHT = 100;
/**
* 通知框的外部宽高
*/
private static final Dimension CONTENT_SIZE = new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT);
private static final Dimension BUTTON_DIMENSION = new Dimension(68, 20);
/**
* 标记 LABEL 没有作用
*/
private static final UILabel SIGN_LABEL = new UILabel("#");
/**
* 确认一个 LABEL 的宽高
*/
private static final Dimension SIGN_LABEL_DIMENSION = SIGN_LABEL.getPreferredSize();
private NotificationDialogProperties properties;
/* 数据 model */
private List<NotificationModel> notificationModels;
private PageControlModel pageControlModel;
private JPanel body;
private JPanel headerPanel;
private JPanel contentPanel;
private JPanel tailPanel;
public NotificationDialog(NotificationDialogProperties properties, List<NotificationModel> notificationModels) {
super(properties.getOwner());
setTitle(properties.getTitle());
this.properties = properties;
this.notificationModels = notificationModels;
this.pageControlModel = new PageControlModel(0, this.notificationModels.size());
initComponents();
}
public void initComponents() {
//UI 配置
configProperties();
this.body = FRGUIPaneFactory.createBorderLayout_L_Pane();
body.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
//首行
layoutHeaderPanel();
//消息内容
layoutContentPanel();
//查看详情
layoutTailPanel();
add(body);
Dimension dimension = body.getPreferredSize();
setSize(dimension.width, dimension.height);
Container parent = getParent();
setLocation((parent.getWidth() - dimension.width - 30 + parent.getX()),
parent.getY() + parent.getHeight() - dimension.height - 30);
}
public void open() {
setVisible(true);
}
private void configProperties() {
setModal(properties.isModal());
setFocusable(false);
setAutoRequestFocus(false);
setResizable(false);
}
protected JPanel createHeaderPanel() {
return null;
}
/**
* 内容
*
* @return 内容面板
*/
protected JPanel createContentPanel() {
JPanel contentPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
contentPanel.setBorder(BorderFactory.createEmptyBorder(8, 10, 8, 10));
contentPanel.setName("contentPanel");
NotificationModel model = getCurrentModel();
UILabel icon = new UILabel(getIconForType(model.getType()));
icon.setPreferredSize(new Dimension(16, 16));
JPanel iconPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
iconPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 10, 8));
iconPanel.add(icon, BorderLayout.NORTH);
contentPanel.add(iconPanel, BorderLayout.WEST);
JPanel centerPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 5));
NotificationMessage[] messages = model.getMessages();
List<? extends JComponent> messageComponents = Arrays.stream(messages)
.map((messageModel) -> {
if (messageModel.getType() == NotificationMessage.Type.LINK) {
NotificationMessage.LinkMessage linkMessage = (NotificationMessage.LinkMessage) messageModel;
return new MessageWithLink(linkMessage.format(), ThrowableRunnable.toRunnable(() -> {
Desktop.getDesktop().browse(URI.create(linkMessage.getLink()));
}));
}
return new UILabel(LinkStrUtils.generateHtmlTag(messageModel.format()));
})
.collect(Collectors.toList());
// 当高度 大于 60 时,就会出现滚动条。
// 当出现滚动条时,需要将内部的宽度限制为 280, 否则会展示不出来
Function<Double, Integer> calStandardWidth = height -> height > CONTENT_INNER_HEIGHT ? CONTENT_SCROLL_WIDTH : CONTENT_WIDTH;
int widthUnit = messageComponents.stream()
.map((component) -> {
Dimension preferredSize = component.getPreferredSize();
double width = preferredSize.getWidth();
double widthFactor = Math.ceil(width / CONTENT_WIDTH);
// 这里的高度是没有限制宽度的,如果限制宽度,高度会变更,所以这里需要加上宽度的影响
return preferredSize.getHeight() + widthFactor * SIGN_LABEL_DIMENSION.getHeight();
})
.reduce(Double::sum)
.map(calStandardWidth)
.orElse(CONTENT_WIDTH);
messageComponents = messageComponents.stream()
.peek((component) -> {
Dimension preferredSize = component.getPreferredSize();
double componentWidth = preferredSize.getWidth();
double componentHeight = preferredSize.getHeight();
double heightFactor = Math.ceil(componentHeight / SIGN_LABEL_DIMENSION.getHeight());
double widthFactor = Math.ceil(componentWidth / widthUnit);
int realHeight = (int)Math.ceil(heightFactor + widthFactor - 1) * (int)(Math.ceil(SIGN_LABEL_DIMENSION.getHeight()));
component.setPreferredSize(new Dimension(widthUnit, realHeight));
})
.collect(Collectors.toList());
// 竖向排列
JPanel messageSummaryPanel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, VerticalFlowLayout.TOP, 0, 0);
messageComponents.forEach(messageSummaryPanel::add);
JScrollPane jScrollPane = new JScrollPane(messageSummaryPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jScrollPane.setBorder(BorderFactory.createEmptyBorder());
centerPanel.add(jScrollPane, BorderLayout.CENTER);
centerPanel.setPreferredSize(CONTENT_SIZE);
contentPanel.add(centerPanel, BorderLayout.CENTER);
return contentPanel;
}
/**
* 行动
*
* UI布局
* /翻页/不再提醒/提醒行为/我知道了
*
* @return 行动面板
*/
protected JPanel createTailPanel() {
JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
tailPanel.setName("tailPanel");
// 翻页按钮效果
PageControlPanel pageControlPanel = new PageControlPanel(pageControlModel);
pageControlPanel.actions(new Runnable() {
@Override
public void run() {
pageControlModel = pageControlPanel.performPrevious();
refresh();
}
}, new Runnable() {
@Override
public void run() {
pageControlModel = pageControlPanel.performNext();
refresh();
}
});
tailPanel.add(pageControlPanel, BorderLayout.WEST);
// 行为效果
JPanel actionsPanel = FRGUIPaneFactory.createBorderLayout_M_Pane();
{
actionsPanel.setBorder(BorderFactory.createEmptyBorder());
actionsPanel.setName("actionsPanel");
UILabel notReminder = new UILabel();
notReminder.setText(Toolkit.i18nText("Fine-Design_Basic_Not_Reminder"));
notReminder.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// 配置处理
EnvDetectorConfig.getInstance().setEnabled(false);
// 点击事件
destroy();
}
});
Color color = new Color(65, 155, 249);
notReminder.setForeground(color);
actionsPanel.add(notReminder, BorderLayout.WEST);
JPanel buttonPanel = FRGUIPaneFactory.createBorderLayout_M_Pane();
buttonPanel.setBorder(BorderFactory.createEmptyBorder());
// real-action
NotificationModel currentModel = getCurrentModel();
NotificationAction action = currentModel.getAction();
if (action != null) {
UIButton actionButton = new UIButton(action.name());
actionButton.setPreferredSize(BUTTON_DIMENSION);
actionButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
action.run();
}
});
buttonPanel.add(actionButton, BorderLayout.WEST);
}
UIButton knowButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Know"));
knowButton.setPreferredSize(BUTTON_DIMENSION);
knowButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (pageControlModel.isLast()) {
destroy();
return;
}
pageControlModel = pageControlPanel.performNext();
refresh();
}
});
buttonPanel.add(knowButton, BorderLayout.EAST);
actionsPanel.add(buttonPanel, BorderLayout.EAST);
}
tailPanel.add(actionsPanel, BorderLayout.EAST);
return tailPanel;
}
private void refresh() {
layoutContentPanel();
layoutTailPanel();
this.repaint();
}
private void layoutHeaderPanel() {
this.headerPanel = layoutPanel(this.headerPanel, this::createHeaderPanel, BorderLayout.NORTH);
}
private void layoutTailPanel() {
this.tailPanel = layoutPanel(this.tailPanel, this::createTailPanel, BorderLayout.SOUTH);
}
private void layoutContentPanel() {
this.contentPanel = layoutPanel(this.contentPanel, this::createContentPanel, BorderLayout.CENTER);
}
private JPanel layoutPanel(JPanel oldPanel, Supplier<JPanel> supplier, Object constraints){
if (oldPanel != null) {
this.body.remove(oldPanel);
}
JPanel newPanel = supplier.get();
if (newPanel != null) {
this.body.add(newPanel, constraints);
}
return newPanel;
}
private NotificationModel getCurrentModel() {
int index = pageControlModel.getIndex();
return notificationModels.get(index);
}
protected Icon getIconForType(NotificationType type) {
String iconPath;
switch (type) {
case ERROR:
iconPath = "/com/fr/design/standard/reminder/reminder_error.svg";
break;
case INFO:
iconPath = "/com/fr/design/standard/reminder/reminder_success.svg";
break;
case WARNING:
iconPath = "/com/fr/design/standard/reminder/reminder_warning.svg";
break;
default:
return null;
}
return IconUtils.readIcon(iconPath);
}
private void destroy() {
setVisible(false);
dispose();
}
@Override
public void dispose() {
super.dispose();
// todo
}
}

39
designer-base/src/main/java/com/fr/design/components/notification/NotificationDialogProperties.java

@ -0,0 +1,39 @@
package com.fr.design.components.notification;
import java.awt.Frame;
/**
* 通知会话的属性
*
* created by Harrison on 2022/05/24
**/
public class NotificationDialogProperties {
private Frame owner;
private String title;
private boolean modal;
public NotificationDialogProperties(Frame owner, String title) {
this.owner = owner;
this.title = title;
this.modal = false;
}
public void setModal(boolean modal) {
this.modal = modal;
}
public Frame getOwner() {
return owner;
}
public String getTitle() {
return title;
}
public boolean isModal() {
return modal;
}
}

88
designer-base/src/main/java/com/fr/design/components/notification/NotificationMessage.java

@ -0,0 +1,88 @@
package com.fr.design.components.notification;
import com.fr.design.utils.LinkStrUtils;
/**
* created by Harrison on 2022/05/24
**/
public interface NotificationMessage {
/**
* 格式化
*
* @return 通知信息
*/
String format();
/**
* 类型
*
* @return 类型
*/
Type getType();
enum Type {
/**
* 简单型
*/
SIMPLE,
/**
* 链接
*/
LINK
}
class SimpleMessage implements NotificationMessage {
private String text;
public SimpleMessage(String text) {
this.text = text;
}
@Override
public String format() {
return text;
}
@Override
public Type getType() {
return Type.SIMPLE;
}
}
class LinkMessage implements NotificationMessage {
private String text;
private String link;
public LinkMessage(String text, String link) {
this.text = text;
this.link = link;
}
public String getText() {
return text;
}
public String getLink() {
return link;
}
@Override
public String format() {
return LinkStrUtils.generateHtmlTag(text);
}
@Override
public Type getType() {
return Type.LINK;
}
}
}

39
designer-base/src/main/java/com/fr/design/components/notification/NotificationModel.java

@ -0,0 +1,39 @@
package com.fr.design.components.notification;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class NotificationModel {
private final NotificationType type;
private final NotificationMessage[] messages;
@Nullable
private final NotificationAction action;
public NotificationModel(NotificationType type, @Nullable NotificationAction action, List<NotificationMessage> messages) {
this(type, action, messages.toArray(new NotificationMessage[0]));
}
public NotificationModel(NotificationType type, @Nullable NotificationAction action, NotificationMessage... messages) {
this.type = type;
this.messages = messages;
this.action = action;
}
public NotificationType getType() {
return type;
}
public NotificationMessage[] getMessages() {
return messages == null ? new NotificationMessage[0] : messages;
}
public @Nullable NotificationAction getAction() {
return action;
}
}

16
designer-base/src/main/java/com/fr/design/components/notification/NotificationType.java

@ -0,0 +1,16 @@
package com.fr.design.components.notification;
/**
* 提醒类型
* 决定图标种类
*
* created by Harrison on 2022/05/27
**/
public enum NotificationType {
INFO,
ERROR,
WARNING
}

78
designer-base/src/main/java/com/fr/design/components/page/PageControlModel.java

@ -0,0 +1,78 @@
package com.fr.design.components.page;
/**
* created by Harrison on 2022/05/26
**/
public class PageControlModel {
/**
* 当前索引
*
* = (页数-1)
*/
private int index;
/**
* 总页数
*/
private int summary;
public PageControlModel(int index, int summary) {
this.index = index;
this.summary = summary;
}
public PageControlModel() {
}
public PageControlModel previous() {
this.index--;
return this;
}
public PageControlModel next() {
this.index++;
return this;
}
/**
* 页数
* index+1
*
* @return 页数
*/
public int getNumber() {
return index + 1;
}
public boolean isFirst() {
return getNumber() == 1;
}
public boolean isLast() {
return getNumber() == getSummary();
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getSummary() {
return summary;
}
public void setSummary(int summary) {
this.summary = summary;
}
public String toContent() {
return getNumber() + "/" + this.summary;
}
}

151
designer-base/src/main/java/com/fr/design/components/page/PageControlPanel.java

@ -0,0 +1,151 @@
package com.fr.design.components.page;
import com.fr.base.svg.IconUtils;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.function.Function;
/**
* 翻页组件
* 相关使用方式见 <a href="https://kms.fineres.com/pages/viewpage.action?pageId=415212013">翻页组件</a>
*
* created by Harrison on 2022/05/26
**/
public class PageControlPanel extends JPanel {
private static final long serialVersionUID = 8140501834691131305L;
private static final Dimension PAGE_CONTROL_BUTTON_DIMENSION = new Dimension(20, 20);
private UIButton previous;
private Runnable previousAction;
private UILabel content;
private PageControlModel model;
private UIButton next;
private Runnable nextAction;
public PageControlPanel(PageControlModel model) {
this.model = model;
setBorder(BorderFactory.createEmptyBorder());
setLayout(new BorderLayout(6, 0));
this.previous = new UIButton();
previous.setPreferredSize(PAGE_CONTROL_BUTTON_DIMENSION);
previous.setIcon(IconUtils.readIcon("/com/fr/design/standard/arrow/arrow_enable_left.svg"));
previous.setDisabledIcon(IconUtils.readIcon("/com/fr/design/standard/arrow/arrow_disable_left.svg"));
previous.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
performAction(previousAction);
}
});
this.add(previous, BorderLayout.WEST);
this.content = new UILabel(model.toContent());
this.add(content, BorderLayout.CENTER);
next = new UIButton();
next.setPreferredSize(PAGE_CONTROL_BUTTON_DIMENSION);
next.setIcon(IconUtils.readIcon("/com/fr/design/standard/arrow/arrow_enable_right.svg"));
next.setDisabledIcon(IconUtils.readIcon("/com/fr/design/standard/arrow/arrow_disable_right.svg"));
next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
performAction(nextAction);
}
});
this.add(next, BorderLayout.EAST);
refresh();
}
public PageControlModel performPrevious() {
update(PageControlModel::previous);
return this.model;
}
public PageControlModel performNext() {
update(PageControlModel::next);
return this.model;
}
public PageControlModel getModel() {
return this.model;
}
public void update(PageControlModel model) {
this.model.setIndex(model.getIndex());
this.model.setSummary(model.getSummary());
refresh();
}
public void update(Function<PageControlModel, PageControlModel> updateAction) {
PageControlModel newModel = updateAction.apply(this.model);
update(newModel);
refresh();
}
public void refresh() {
this.content.setText(this.model.toContent());
this.content.repaint();
this.previous.setEnabled(true);
this.next.setEnabled(true);
if (model.getNumber() == 1) {
// 禁用上一个
disableButton(this.previous);
// 禁用next
if (model.getNumber() == model.getSummary()) {
disableButton(this.next);
}
return;
}
// 禁用next
if (model.getNumber() == model.getSummary()) {
disableButton(this.next);
}
}
private void enable(UIButton button) {
button.setEnabled(true);
}
private void disableButton(UIButton button) {
button.setEnabled(false);
}
private void performAction(Runnable action) {
if (action != null) {
action.run();
refresh();
}
}
public void actions(Runnable previousAction, Runnable nextAction) {
this.previousAction = previousAction;
this.nextAction = nextAction;
}
}

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

@ -0,0 +1,184 @@
package com.fr.design.components.table;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.ColorUtils;
import com.fr.third.org.apache.commons.lang3.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
/**
* 表头
* 内容
*
* 适用于需要一个表格的 Panel
*
* created by Harrison on 2022/05/26
**/
public class TablePanel extends JPanel {
private static final Color DEFAULT_HEADER_COLOR = new Color(232, 232, 233);
private static final Color DEFAULT_ODD_ROW_COLOR = new Color(245, 245, 247);
private static final Color DEFAULT_EVEN_ROW_COLOR = Color.WHITE;
private JPanel headerPanel;
private JPanel[] headerItemPanels;
private JPanel contentPanel;
private JPanel[][] cellPanels;
public TablePanel(int row, int column) {
setLayout(FRGUIPaneFactory.createBorderLayout());
/* header 部分 */
this.headerPanel = new JPanel();
headerPanel.setLayout(FRGUIPaneFactory.createNColumnGridLayout(column));
headerPanel.setName("header-panel");
headerPanel.setPreferredSize(new Dimension(640, 24));
// border
headerPanel.setBorder(BorderFactory.createLineBorder(new Color(218, 218, 221)));
syncHeaderColor(headerPanel);
headerItemPanels = new JPanel[column];
for (int i = 0; i < column; i++) {
JPanel headerItemWrapper = FRGUIPaneFactory.createBorderLayout_S_Pane();
syncHeaderColor(headerItemWrapper);
headerItemWrapper.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
JPanel headerItemPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
headerItemPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
headerItemPanels[i] = headerItemPanel;
UILabel label = new UILabel();
syncHeaderColor(label);
headerItemPanel.add(new UILabel(), BorderLayout.CENTER);
headerItemWrapper.add(headerItemPanel, BorderLayout.WEST);
if (i != column - 1) {
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
separator.setBackground(new Color(218, 218, 221));
headerItemWrapper.add(separator, BorderLayout.EAST);
}
headerPanel.add(headerItemWrapper);
}
/* content 部分 */
contentPanel = new JPanel();
contentPanel.setLayout(new GridLayout(row, 1));
contentPanel.setBorder(BorderFactory.createLineBorder(new Color(218, 218, 221)));
cellPanels = new JPanel[row][column];
for (int i = 0; i < row; i++) {
JPanel rowPanel = new JPanel();
// 获取行号
Color rowColor = getRowColorByRowNumber(i + 1);
rowPanel.setBackground(rowColor);
rowPanel.setLayout(FRGUIPaneFactory.createNColumnGridLayout(column));
rowPanel.setName("row-" + i);
rowPanel.setBorder(BorderFactory.createEmptyBorder());
rowPanel.setPreferredSize(new Dimension(640, 24));
for (int j = 0; j < column; j++) {
JPanel rowItemPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
rowItemPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
rowItemPanel.setName("rowItemPanel-"+ i + "-" + j);
final UILabel empty = new UILabel();
empty.setPreferredSize(new Dimension(210, 24));
rowItemPanel.setBackground(rowPanel.getBackground());
rowItemPanel.add(empty, BorderLayout.CENTER);
rowPanel.add(rowItemPanel);
cellPanels[i][j] = rowItemPanel;
}
contentPanel.add(rowPanel);
}
add(headerPanel, BorderLayout.NORTH);
add(contentPanel, BorderLayout.SOUTH);
}
/**
* 获取行的颜色
*
* @param row 行号
* @return 颜色
*/
private Color getRowColorByRowNumber(int row) {
Color rowColor;
if (row % 2 != 0) {
rowColor = DEFAULT_EVEN_ROW_COLOR;
} else {
rowColor = DEFAULT_ODD_ROW_COLOR;
}
return rowColor;
}
public void updateHeaders(String[] headers) {
for (int i = 0; i < headers.length; i++) {
String header = headers[i];
UILabel headerContent = new UILabel(header);
JPanel headerItemPanel = headerItemPanels[i];
if (ArrayUtils.getLength(headerItemPanel.getComponents()) == 1) {
headerItemPanel.remove(0);
}
headerItemPanel.add(headerContent);
syncHeaderColor(headerItemPanel);
}
}
public void updateCell(int row, int column, Component component) {
int x = row - 1;
int y = column - 1;
syncCellColor(row, component);
JPanel cellPanel = this.cellPanels[x][y];
if (ArrayUtils.getLength(cellPanel.getComponents()) == 1) {
cellPanel.remove(0);
}
cellPanel.add(component);
}
public void updateCell(int row, int column, String value) {
UILabel cellContent = new UILabel(value);
syncCellColor(row, cellContent);
this.updateCell(row, column, cellContent);
}
private void syncHeaderColor(Component component) {
ColorUtils.syncBackground(component, DEFAULT_HEADER_COLOR);
}
private void syncCellColor(int row, Component component) {
Color rowColor = getRowColorByRowNumber(row);
ColorUtils.syncBackground(component, rowColor);
component.setBackground(rowColor);
}
}

105
designer-base/src/main/java/com/fr/design/components/tooltip/ModernToolTip.java

@ -0,0 +1,105 @@
package com.fr.design.components.tooltip;
import com.fr.base.GraphHelper;
import com.fr.design.gui.itooltip.UIToolTip;
import com.fr.log.FineLoggerFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JToolTip;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ToolTipUI;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.Vector;
/**
* 现代化的 UIToolTip
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=416850313">设计文档</a>
*
* created by Harrison on 2022/07/09
**/
public class ModernToolTip extends UIToolTip {
public ModernToolTip() {
super();
setUI(new ModernToolTipUI());
}
private class ModernToolTipUI extends ToolTipUI {
private String[] strs;
private Icon icon;
private boolean needPaint;
public void paint(Graphics g, JComponent c) {
if (!needPaint) {
return;
}
FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont());
Dimension size = c.getSize();
int width = size.width;
int height = size.height;
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(51, 51, 52, (int) Math.round(0.7 * 255)));
g2.fillRoundRect(0, 0, width, height, 4, 4);
g2.setColor(Color.WHITE);
if (strs != null) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT);
for (int i = 0; i < strs.length; i++) {
g2.drawString(strs[i], icon.getIconWidth() + 6, (metrics.getHeight()) * (i + 1));
}
}
}
@Override
public Dimension getPreferredSize(JComponent c) {
FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont());
String tipText = ((JToolTip) c).getTipText();
icon = ((UIToolTip)c).getIcon();
needPaint = true;
if (tipText == null) {
if(icon.getIconWidth() == -1) {
needPaint = false;
}
tipText = " ";
}
BufferedReader br = new BufferedReader(new StringReader(tipText));
String line;
int maxWidth = 0;
Vector<String> v = new Vector<String>();
try {
while ((line = br.readLine()) != null) {
int width = SwingUtilities.computeStringWidth(metrics, line);
maxWidth = (maxWidth < width) ? width : maxWidth;
v.addElement(line);
}
} catch (IOException ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
int lines = v.size();
if (lines < 1) {
strs = null;
lines = 1;
} else {
strs = new String[lines];
int i = 0;
for (Enumeration<String> e = v.elements(); e.hasMoreElements(); i++) {
strs[i] = e.nextElement();
}
}
int height = metrics.getHeight() * lines;
return new Dimension(maxWidth + icon.getIconWidth() + 10, Math.max(height, icon.getIconHeight()) + 6);
}
}
}

52
designer-base/src/main/java/com/fr/design/config/DesignerProperties.java

@ -0,0 +1,52 @@
package com.fr.design.config;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Properties;
public class DesignerProperties {
private static DesignerProperties holder = null;
private boolean supportLoginEntry = true;
public DesignerProperties() {
String filePath = StableUtils.pathJoin(StableUtils.getInstallHome(), "/config/config.properties");
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(filePath));
Properties ps = new Properties();
ps.load(is);
this.initProperties(ps);
} catch (FileNotFoundException e) {
// ignore
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
} finally {
IOUtils.close(is);
}
}
public static DesignerProperties getInstance() {
if (holder == null) {
holder = new DesignerProperties();
}
return holder;
}
private void initProperties(Properties ps) {
String supportLoginEntry = ps.getProperty("supportLoginEntry");
if (StringUtils.isNotEmpty(supportLoginEntry)) {
this.supportLoginEntry = Boolean.valueOf(supportLoginEntry);
}
}
public boolean isSupportLoginEntry() {
return supportLoginEntry;
}
}

24
designer-base/src/main/java/com/fr/design/constants/DesignerColor.java

@ -0,0 +1,24 @@
package com.fr.design.constants;
import java.awt.Color;
/**
* <a href="https://www.figma.com/file/G2f40rv7cY8zpDDYbt6pY2/%E8%AE%BE%E8%AE%A1%E5%99%A811.0%E8%A7%84%E8%8C%83%E6%95%B4%E7%90%86">设计器规范</a>
* 将相关的逻辑抽象过来
* 如果后面更改的话 可以统一修改
* 如果换版本可以换成 v2 这种类推
*
* created by Harrison on 2022/05/26
**/
public interface DesignerColor {
interface Button {
interface Primary {
Color PRESSED = new Color(29, 122, 220);
Color HOVER = new Color(84, 165, 249);
Color NORMAL = new Color(65, 155, 249);
}
}
}

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

@ -15,7 +15,12 @@ public enum DesignerLaunchStatus implements Event<Null> {
* 初始化环境完成
*/
WORKSPACE_INIT_COMPLETE,
/**
* 设计器模块初始化开始
*/
DESIGNER_INIT_STARTED,
/**
* 设计器模块启动完成
*/

5
designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java

@ -0,0 +1,5 @@
package com.fr.design.constants;
public class TableDataConstants {
public static final String SEPARATOR = "_";
}

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

@ -4,14 +4,13 @@
package com.fr.design.constants;
import com.fr.base.svg.IconUtils;
import com.fr.base.svg.SVGIcon;
import com.fr.base.svg.SVGLoader;
import com.fr.general.IOUtils;
import com.fr.stable.Constants;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.border.Border;
import java.awt.BasicStroke;
import java.awt.Color;
@ -150,6 +149,7 @@ public interface UIConstants {
public static final Color LIST_ITEM_SPLIT_LINE = new Color(0xf0f0f3);
public static final Color DESIGNER_LOGIN_BACKGROUND = new Color(0xf1ad14);
public static final Color DESIGNER_LOGIN_BACKGROUND_ONCLICK = new Color(0xd89600);
public static final Color CHECK_BOX_TIP_FONT_COLOR = new Color(51, 51, 52, (int)Math.round(0.5 * 255));
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");
@ -160,16 +160,16 @@ public interface UIConstants {
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");
public static final BufferedImage DRAG_UP_NORMAL = IOUtils.readImage("com/fr/design/images/control/upnor.png");
public static final BufferedImage DRAG_UP_PRESS = IOUtils.readImage("com/fr/design/images/control/uppre.png");
public static final BufferedImage DRAG_DOWN_NORMAL = IOUtils.readImage("com/fr/design/images/control/downnor.png");
public static final BufferedImage DRAG_DOWN_PRESS = IOUtils.readImage("com/fr/design/images/control/downpre.png");
public static final BufferedImage DRAG_RIGHT_NORMAL = IOUtils.readImage("com/fr/design/images/control/rightnor.png");
public static final BufferedImage DRAG_RIGHT_PRESS = IOUtils.readImage("com/fr/design/images/control/rightpre.png");
public static final BufferedImage DRAG_LEFT_NORMAL = IOUtils.readImage("com/fr/design/images/control/leftnor.png");
public static final BufferedImage DRAG_LEFT_PRESS = IOUtils.readImage("com/fr/design/images/control/leftpre.png");
public static final Image DRAG_UP_NORMAL = SVGLoader.load("/com/fr/design/standard/triangle.arrow/up_normal.svg");
public static final Image DRAG_UP_PRESS = SVGLoader.load("/com/fr/design/standard/triangle.arrow/up_hover.svg");
public static final Image DRAG_DOWN_NORMAL = SVGLoader.load("/com/fr/design/standard/triangle.arrow/down_normal.svg");
public static final Image DRAG_DOWN_PRESS = SVGLoader.load("/com/fr/design/standard/triangle.arrow/down_hover.svg");
public static final Image DRAG_RIGHT_NORMAL = SVGLoader.load("/com/fr/design/standard/drag/right_normal.svg");
public static final Image DRAG_RIGHT_PRESS = SVGLoader.load("/com/fr/design/standard/drag/right_pressed.svg");
public static final Image DRAG_LEFT_NORMAL = SVGLoader.load("/com/fr/design/standard/drag/left_normal.svg");
public static final Image DRAG_LEFT_PRESS = SVGLoader.load("/com/fr/design/standard/drag/left_pressed.svg");
public static final BufferedImage DRAG_DOT = IOUtils.readImage("com/fr/design/images/control/dot.png");
public static final BufferedImage DRAG_LINE = IOUtils.readImage("com/fr/design/images/control/dot-line.png");
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");
@ -186,20 +186,22 @@ public interface UIConstants {
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 = IOUtils.readIcon("com/fr/design/images/buttonicon/editn.png");
public static final Icon EDIT_PRESSED_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/editp.png");
public static final Icon HIDE_NORMAL_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/hiden.png");
public static final Icon HIDE_PRESSED_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/hidep.png");
public static final Icon VIEW_NORMAL_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/viewn.png");
public static final Icon VIEW_PRESSED_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/viewp.png");
public static final Icon RUN_BIG_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/run24.png");
public static final Icon RUN_SMALL_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/runs.png");
public static final Icon PAGE_BIG_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/pageb24.png");
public static final Icon WRITE_BIG_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/writeb24.png");
public static final Icon ANA_BIG_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/anab24.png");
public static final Icon PAGE_SMALL_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/pages.png");
public static final Icon WRITE_SMALL_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/writes.png");
public static final Icon ANA_SMALL_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/anas.png");
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 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 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");
public static final Icon RUN_BIG_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/run24.svg");
public static final Icon RUN_SMALL_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/runs.svg");
public static final Icon PAGE_BIG_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/pageb24.svg");
public static final Icon WRITE_BIG_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/writeb24.svg");
public static final Icon ANA_BIG_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/anab24.svg");
public static final Icon PAGE_SMALL_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/pages.svg");
public static final Icon WRITE_SMALL_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/writes.svg");
public static final Icon ANA_SMALL_ICON = IconUtils.readIcon("/com/fr/design/standard/preview/anas.svg");
public static final Icon REFRESH_ICON = IOUtils.readIcon("com/fr/design/images/buttonicon/refresh.png");
public static final Icon FONT_ICON = IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png");
public static final Icon AUTO_FONT_ICON = IOUtils.readIcon("/com/fr/design/images/gui/color/autoForeground.png");

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

@ -2,9 +2,9 @@ package com.fr.design.data;
import com.fr.base.BaseUtils;
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.api.StoreProcedureAssist;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.design.DesignModelAdapter;
import com.fr.design.actions.UpdateAction;
import com.fr.design.data.datapane.TableDataCreatorProducer;
@ -13,7 +13,7 @@ import com.fr.design.data.datapane.TableDataSourceOP;
import com.fr.design.data.datapane.TableDataTree;
import com.fr.design.data.tabledata.ResponseDataSourceChange;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper;
import com.fr.design.data.tabledata.wrapper.MultiResultTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import com.fr.design.dialog.BasicDialog;
@ -36,8 +36,6 @@ import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
@ -55,8 +53,10 @@ import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Coder: zack
@ -83,6 +83,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
protected String[] allDSNames;
protected ConnectionTableAction connectionTableAction;
protected ToolBarDef toolbarDef;
protected TableDataTreePaneListener listener = null;
private String type = "";
@ -114,7 +115,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
*/
@Override
public Icon getViewIcon() {
return BaseUtils.readIcon(IconPathConstants.DS_ICON_PATH);
return IconUtils.readIcon(IconPathConstants.DS_ICON_PATH);
}
/**
@ -142,6 +143,17 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
public abstract void dgEdit(final AbstractTableDataPane<?> uPanel, String originalName, boolean isUpdate);
public void showEditPane(final AbstractTableDataPane<?> tableDataPane, String originalName, TableDataTreePaneListener listener) {
this.listener = listener;
dgEdit(tableDataPane, originalName);
}
public interface TableDataTreePaneListener {
void doOk();
void doCancel();
}
protected void doPropertyChange(BasicDialog dg, BasicPane.NamePane nPanel, final String oldName) {
type = dg.getTitle();
nPanel.setShowText(StringUtils.BLANK);
@ -172,7 +184,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
private boolean isIncludeUnderline(String name) {
return ComparatorUtils.equals(name.indexOf(StoreProcedureAssist.GROUP_MARKER), -1) ? false : true;
return ComparatorUtils.equals(name.indexOf(MultiResultTableData.GROUP_MARKER), -1) ? false : true;
}
public abstract void addDataPane(final AbstractTableDataPane<?> uPanel, String paneName);
@ -366,15 +378,9 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
}
protected boolean isDsNameRepeaded(String name) {
if (allDSNames == null) {
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
}
for (int i = 0; i < allDSNames.length; i++) {
if (ComparatorUtils.equals(name, allDSNames[i])) {
return true;
}
}
return false;
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
Set<String> allDSNamesWithoutPermissions = DesignTableDataManager.getAllDSNamesWithoutPermissions(tc.getBook());
return allDSNamesWithoutPermissions.contains(name);
}
protected KeyAdapter getTableTreeNodeListener(final UpdateAction editAction, final UpdateAction previewTableDataAction, final UpdateAction removeAction, final TableDataSourceOP op, final TableDataTree dataTree) {
@ -419,7 +425,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
public PreviewTableDataAction(TableDataTree dataTree) {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"));
this.setMnemonic('p');
this.setSmallIcon("/com/fr/design/images/m_file/preview");
this.setSmallIcon("/com/fr/design/standard/previewdateset/preview");
this.dataTree = dataTree;
}
@ -431,16 +437,16 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
data = selectedNO.getObject();
}
try {
if (((TableDataWrapper) Objects.requireNonNull(data)).getTableData() instanceof StoreProcedure) {
((StoreProcedure) (((TableDataWrapper) data).getTableData())).resetDataModelList();
if (data instanceof StoreProcedureDataWrapper) {
StoreProcedureDataWrapper oldSdw = ((StoreProcedureDataWrapper) data);
StoreProcedureDataWrapper newSdw = new StoreProcedureDataWrapper((StoreProcedure) oldSdw.getTableData(), oldSdw.getStoreprocedureName(), oldSdw.getTableDataName());
newSdw.previewData(StoreProcedureDataWrapper.PREVIEW_ONE);
if (((TableDataWrapper) Objects.requireNonNull(data)).getTableData() instanceof MultiResultTableData) {
((MultiResultTableData<?>) (((TableDataWrapper) data).getTableData())).resetDataModelList();
if (data instanceof MultiResultTableDataWrapper) {
MultiResultTableDataWrapper oldSdw = ((MultiResultTableDataWrapper) data);
MultiResultTableDataWrapper newSdw = new MultiResultTableDataWrapper((MultiResultTableData<?>) oldSdw.getTableData(), oldSdw.getMultiResultTableDataName(), oldSdw.getTableDataName());
newSdw.previewData(MultiResultTableDataWrapper.PREVIEW_ONE);
} else {
StoreProcedure storeProcedure = (StoreProcedure) ((TableDataWrapper) data).getTableData();
StoreProcedureDataWrapper storeProcedureDataWrapper = new StoreProcedureDataWrapper(storeProcedure, StringUtils.EMPTY, StringUtils.EMPTY);
storeProcedureDataWrapper.previewData(StoreProcedureDataWrapper.PREVIEW_ALL);
MultiResultTableData<?> tableData = (MultiResultTableData<?>) ((TableDataWrapper) data).getTableData();
MultiResultTableDataWrapper storeProcedureDataWrapper = new MultiResultTableDataWrapper(tableData, StringUtils.EMPTY, StringUtils.EMPTY);
storeProcedureDataWrapper.previewData(MultiResultTableDataWrapper.PREVIEW_ALL);
}
} else {
((TableDataWrapper) data).previewData();
@ -458,7 +464,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
public ConnectionTableAction() {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Server_Define_Data_Connection"));
this.setMnemonic('D');
this.setSmallIcon("/com/fr/design/images/m_web/connection");
this.setSmallIcon("/com/fr/design/standard/connection", false);
}
@Override

7
designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java

@ -1,6 +1,7 @@
package com.fr.design.data;
import com.fr.data.TableDataSource;
import com.fr.design.constants.TableDataConstants;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.stable.StringUtils;
@ -11,8 +12,6 @@ import com.fr.stable.StringUtils;
* Created by hades on 2020/4/27
*/
public abstract class BasicTableDataUtils {
private static final String SEPARATOR = "-";
private static final int LEN = 2;
@ -38,10 +37,10 @@ public abstract class BasicTableDataUtils {
public static String getTableDataName(boolean isCover, TableDataSource tds, String tdName, String srcName, boolean isDsNameRepeaded) {
if (isCover) {
return srcName + SEPARATOR + tdName;
return srcName + TableDataConstants.SEPARATOR + tdName;
}
if (tds.getTableData(tdName) != null || isDsNameRepeaded) {//如果有同名的就拼上来源名称
tdName = srcName + SEPARATOR + tdName;
tdName = srcName + TableDataConstants.SEPARATOR + tdName;
}
int i = 0;
while (tds.getTableData(tdName) != null) {

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

@ -3,19 +3,22 @@ package com.fr.design.data;
import com.fr.base.StoreProcedureParameter;
import com.fr.base.TableData;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.TableDataSourceTailor;
import com.fr.data.core.DataCoreXmlUtils;
import com.fr.data.impl.EmbeddedTableData;
import com.fr.data.impl.NameDataModel;
import com.fr.data.impl.storeproc.ProcedureDataModel;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.data.impl.storeproc.StoreProcedureConstants;
import com.fr.data.impl.storeproc.StoreProcedureHelper;
import com.fr.data.operator.DataOperator;
import com.fr.design.DesignModelAdapter;
import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.tabledata.wrapper.MultiResultTableDataNameWrapper;
import com.fr.design.data.tabledata.wrapper.MultiResultTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.ServerTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper;
import com.fr.design.data.tabledata.wrapper.StoreProcedureNameWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataFactory;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
@ -45,6 +48,7 @@ import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -188,7 +192,7 @@ public abstract class DesignTableDataManager {
public static void addDsChangeListener(ChangeListener l) {
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String key = StringUtils.EMPTY;
if (template != null) {
if (JTemplate.isValid(template)) {
key = template.getPath();
}
List<ChangeListener> dsListeners = dsListenersMap.get(key);
@ -292,6 +296,27 @@ public abstract class DesignTableDataManager {
return list.toArray(new String[0]);
}
/**
* 获取所有的数据集名称,无论模板是不是有数据集的权限
*/
public static Set<String> getAllDSNamesWithoutPermissions(TableDataSource source) {
Set<String> names = new HashSet<>();
Map<String, TableDataWrapper> resMap = new HashMap<>();
// 模板数据集
addTemplateData(resMap, source);
// 存储过程
addStoreProcedureData(resMap);
for (Map.Entry<String, TableDataWrapper> entry : resMap.entrySet()) {
names.add(entry.getKey());
}
//服务器数据集
Map<String, TableData> tableDatas = TableDataConfig.getInstance().getTableDatas();
for (Map.Entry<String, TableData> entry : tableDatas.entrySet()) {
names.add(entry.getKey());
}
return names;
}
/**
* 不根据过滤设置返回当前模板数据集服务器数据集存储过程本身是有顺序的
*/
@ -308,35 +333,57 @@ public abstract class DesignTableDataManager {
return resMap;
}
/**
* 不根据过滤设置返回当前模板数据集是有顺序的
*/
public static java.util.Map<String, TableDataWrapper> getTemplateDataSet(TableDataSource source) {
java.util.Map<String, TableDataWrapper> resMap = new java.util.LinkedHashMap<String, TableDataWrapper>();
// 模板数据集
addTemplateData(resMap, source);
return resMap;
}
public static java.util.Map<String, TableDataWrapper> getAllDataSetIncludingProcedure(java.util.Map<String, TableDataWrapper> resMap) {
java.util.LinkedHashMap<String, TableDataWrapper> dsMap = new java.util.LinkedHashMap<String, TableDataWrapper>();
Iterator<Entry<String, TableDataWrapper>> entryIt = resMap.entrySet().iterator();
while (entryIt.hasNext()) {
String key = entryIt.next().getKey();
for (Entry<String, TableDataWrapper> entry : resMap.entrySet()) {
String key = entry.getKey();
TableDataWrapper tableDataWrapper = resMap.get(key);
if (tableDataWrapper.getTableData() instanceof StoreProcedure) {
StoreProcedure storeProcedure = (StoreProcedure) tableDataWrapper.getTableData();
boolean hasSchemaOrResult = false;
StoreProcedureParameter[] parameters = StoreProcedure.getSortPara(storeProcedure.getParameters());
if (tableDataWrapper.getTableData() instanceof MultiResultTableData) {
MultiResultTableData<?> tableData = (MultiResultTableData<?>) tableDataWrapper.getTableData();
String name = tableDataWrapper.getTableDataName();
List<String> resultNames = storeProcedure.getResultNames();
TableDataWrapper tdw = new StoreProcedureNameWrapper(name + "_Table", storeProcedure);
for (StoreProcedureParameter parameter : parameters) {
if (parameter.getSchema() != StoreProcedureConstants.IN) {
String parameterName = name + "_" + parameter.getName();
TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false);
dsMap.put(parameterName, newTwd);
hasSchemaOrResult = true;
List<String> resultNames = tableData.getResultNames();
TableDataWrapper tdw = new MultiResultTableDataNameWrapper(name + "_Table", tableData);
boolean hasSchemaOrResult = false;
// 存储过程的特殊处理,还有其它名称
if (tableData instanceof StoreProcedure) {
StoreProcedure storeProcedure = (StoreProcedure) tableData;
StoreProcedureParameter[] parameters = StoreProcedureHelper.getSortPara(storeProcedure.getParameters());
for (StoreProcedureParameter parameter : parameters) {
if (parameter.getSchema() != StoreProcedureConstants.IN) {
String parameterName = name + "_" + parameter.getName();
TableDataWrapper newTwd = new MultiResultTableDataWrapper(storeProcedure, name, parameterName, false);
dsMap.put(parameterName, newTwd);
hasSchemaOrResult = true;
}
}
}
} /*else {
// TODO getDataModelList是空的
for (String n : tableData.getResultNames()) {
String dmName = name + "_" + n;
dsMap.put(n, new MultiResultTableDataWrapper(tableData, name, dmName, false));
}
}*/
if (!resultNames.isEmpty()) {
hasSchemaOrResult = true;
for (int i = 0; i < resultNames.size(); i++) {
String parameterName = name + "_" + resultNames.get(i);
TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false);
dsMap.put(parameterName, newTwd);
for (String resultName : resultNames) {
String dmName = name + "_" + resultName;
TableDataWrapper newTwd = new MultiResultTableDataWrapper(tableData, name, dmName, false);
dsMap.put(dmName, newTwd);
}
}
@ -418,7 +465,7 @@ public abstract class DesignTableDataManager {
if (globalDsCache.containsKey(name)) {
resMap.put(name, globalDsCache.get(name));
} else {
TableDataWrapper tdw = new StoreProcedureNameWrapper(name, storeProcedure);
TableDataWrapper tdw = new MultiResultTableDataNameWrapper(name, storeProcedure);
resMap.put(name, tdw);
globalDsCache.put(name, tdw);
}
@ -588,29 +635,39 @@ public abstract class DesignTableDataManager {
* 所以用该方法不会对一个已经计算了的存储过程重复计算.和分页预览时处理机制一样这样对有多个返回数据集的存储过程来说很有必要
*
* @param needLoadingBar 是否需要进度条
* @param storeProcedure 存储过程
* @param tableData 存储过程
* @return 数据
*/
public static ProcedureDataModel[] createLazyDataModel(StoreProcedure storeProcedure, boolean needLoadingBar) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLPrintWriter writer = XMLPrintWriter.create(out);
// 把storeProcedure写成xml文件到out
DataCoreXmlUtils.writeXMLStoreProcedure(writer, storeProcedure, null);
if (storeProcedure.getDataModelSize() > 0 && !storeProcedure.isFirstExpand()) {
return storeProcedure.creatLazyDataModel();
}
ParameterProvider[] inParameters = DataOperator.getInstance().getStoreProcedureParameters(storeProcedure);
public static NameDataModel[] createLazyDataModel(MultiResultTableData<?> tableData, boolean needLoadingBar) throws Exception {
Map<String, Object> parameterMap = new HashMap<>();
if (inParameters.length > 0 && !ComparatorUtils.equals(threadLocal.get(), NO_PARAMETER)) {// 检查Parameter.
showParaWindow(parameterMap, inParameters);
if (tableData instanceof StoreProcedure) {
StoreProcedure storeProcedure = (StoreProcedure) tableData;
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLPrintWriter writer = XMLPrintWriter.create(out);
// 把storeProcedure写成xml文件到out
DataCoreXmlUtils.writeXMLStoreProcedure(writer, storeProcedure, null);
if (storeProcedure.getDataModelList().size() > 0 && !storeProcedure.isFirstExpand()) {
// 存储过程有些特殊处理
// 这个就简单直接获取暂存列表吧
return storeProcedure.getDataModelList().toArray(new ProcedureDataModel[0]);
}
ParameterProvider[] inParameters = DataOperator.getInstance().getStoreProcedureParameters(storeProcedure);
if (inParameters.length > 0 && !ComparatorUtils.equals(threadLocal.get(), NO_PARAMETER)) {// 检查Parameter.
showParaWindow(parameterMap, inParameters);
}
storeProcedure.setFirstExpand(false);
} else {
ParameterProvider[] parameters = DataOperator.getInstance().getTableDataParameters(tableData);
if (parameters.length > 0) {
showParaWindow(parameterMap, parameters);
}
}
storeProcedure.setFirstExpand(false);
if (needLoadingBar) {
StoreProcedureDataWrapper.loadingBar.start();
MultiResultTableDataWrapper.loadingBar.start();
}
return DataOperator.getInstance().previewProcedureDataModel(storeProcedure, parameterMap, 0);
return DataOperator.getInstance().previewMultiResultTableData(tableData, parameterMap, 0);
}
private static void showParaWindow(final Map<String, Object> parameterMap, ParameterProvider[] inParameters) {
@ -626,4 +683,14 @@ public abstract class DesignTableDataManager {
public static void setThreadLocal(String value) {
threadLocal.set(value);
}
}
/**
* 根据数据集名称判断是否为服务器数据集或服务器存储过程
*
* @param tableDataName 数据集名称
* @return
*/
public static boolean isGlobalTableData(String tableDataName) {
return globalDsCache.containsKey(tableDataName);
}
}

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

@ -0,0 +1,93 @@
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;
}
}

6
designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java

@ -11,11 +11,11 @@ import com.fr.esd.event.DSMapping;
import com.fr.esd.event.DsNameTarget;
import com.fr.esd.event.StrategyEventsNotifier;
import com.fr.esd.event.xml.XMLSavedHook;
import com.fr.file.FILE;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -46,7 +46,9 @@ public class StrategyConfigAttrUtils {
}
//新建模版此时不存在,不需要注册钩子
if (attr.getXmlSavedHook() == null && WorkContext.getWorkResource().exist(jTemplate.getPath())) {
//不处理外部路径,保存到设计器才处理
String path = jTemplate.getPath();
if (attr.getXmlSavedHook() == null && !Paths.get(path).isAbsolute() && WorkContext.getWorkResource().exist(path)) {
attr.setXmlSavedHook(new StrategyConfigsAttrSavedHook(jTemplate.getPath(), attr));
}
return attr;

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

@ -1,12 +1,12 @@
package com.fr.design.data.datapane;
import com.fr.base.TableData;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.data.core.DataCoreUtils;
import com.fr.data.core.db.DBUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.core.db.dialect.Dialect;
import com.fr.data.core.db.dialect.DialectFactory;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData;
import com.fr.data.operator.DataOperator;
import com.fr.design.DesignerEnvManager;
@ -19,7 +19,7 @@ import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.tabledata.Prepare4DataSourceChange;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.icombobox.FilterableComboBoxModel;
import com.fr.design.gui.icombobox.SearchPreTaskTreeComboBox;
import com.fr.design.gui.icombobox.TableSearchTreeComboBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIComboBoxEditor;
import com.fr.design.gui.icombobox.UIComboBoxRenderer;
@ -40,11 +40,6 @@ import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.util.Collections;
import java.util.concurrent.CancellationException;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@ -58,21 +53,20 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.CancellationException;
/**
* @author zhou
@ -97,41 +91,12 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
/**
* 表名
*/
protected SearchPreTaskTreeComboBox tableNameComboBox;
private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("ChoosePane"));
protected TableSearchTreeComboBox tableNameComboBox;
private SwingWorker populateWorker;
private SwingWorker<List<String>, Void> initWorker;
private PopupMenuListener popupMenuListener = new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
@Override
public Void call() throws Exception {
calculateTableDataNames();
return null;
}
});
tableNameComboBox.setPreSearchTask(task);
SERVICE.submit(task);
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// Do nothing
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// Do nothing
}
};
private PopupMenuListener listener = new PopupMenuListener() {
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
@ -181,7 +146,7 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
schemaBox = new StringUIComboBox();
schemaBox.setEditor(new ComboBoxEditor());
tableNameComboBox = new SearchPreTaskTreeComboBox(new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer, false);
tableNameComboBox = new TableSearchTreeComboBox(this, new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer);
tableNameComboBox.setEditable(true);
tableNameComboBox.setRenderer(listCellRenderer);
registerDSChangeListener();
@ -198,7 +163,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
});
schemaBox.addPopupMenuListener(listener);
addFocusListener();
this.tableNameComboBox.addPopupMenuListener(popupMenuListener);
}
protected void addDSBoxListener() {
@ -355,7 +319,7 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1);
}
protected com.fr.data.impl.Connection getConnection() {
public Connection getConnection() {
String selectedDSName = this.getDSName();
if (StringUtils.isEmpty(selectedDSName)) {
return null; // peter:选中了当前的零长度的节点,直接返回.
@ -455,56 +419,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
return "choosepane";
}
protected void calculateTableDataNames() {
JTree tree = tableNameComboBox.getTree();
if (tree == null) {
return;
}
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot();
rootTreeNode.removeAllChildren();
String selectedDSName = this.getDSName();
com.fr.data.impl.Connection selectedDatabase = this.getConnection();
if (selectedDatabase == null) {
return;
}
try {
String schema = StringUtils.isEmpty(this.schemaBox.getSelectedItem()) ? null : this.schemaBox.getSelectedItem();
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (sqlTableArray.length > 0) {
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"));
rootTreeNode.add(tableTreeNode);
for (int i = 0; i < sqlTableArray.length; i++) {
ExpandMutableTreeNode tableChildTreeNode = new ExpandMutableTreeNode(sqlTableArray[i]);
tableTreeNode.add(tableChildTreeNode);
}
}
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (sqlViewArray.length > 0) {
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"));
rootTreeNode.add(viewTreeNode);
for (int i = 0; i < sqlViewArray.length; i++) {
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(sqlViewArray[i]);
viewTreeNode.add(viewChildTreeNode);
}
}
((DefaultTreeModel) tree.getModel()).reload();
// daniel 展开所有tree
TreeNode root = (TreeNode) tree.getModel().getRoot();
TreePath parent = new TreePath(root);
TreeNode node = (TreeNode) parent.getLastPathComponent();
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
tree.expandPath(path);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE);
}
}
/**
* 创建选中的数据集数据
*
@ -558,22 +472,23 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
return tableData;
}
protected String getDSName() {
public String getDSName() {
return this.dsNameComboBox.getSelectedItem();
}
public String getSchema() {
return this.schemaBox.getSelectedItem();
}
protected void failedToFindTable() {
// Do nothing
}
protected String getTableName() {
String tableName = "";
Object obj = this.tableNameComboBox.getSelectedItemObject();
Object obj = this.tableNameComboBox.getSelectedItem();
if (obj == null) {
obj = this.tableNameComboBox.getSelectedItem();
if (obj == null) {
obj = this.tableNameComboBox.getEditor().getItem();
}
obj = this.tableNameComboBox.getEditor().getItem();
}
if (obj instanceof TreePath) {
Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject();

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

@ -83,7 +83,7 @@ public class ChoosePaneSupportFormula extends ChoosePane {
*
* @return
*/
protected String getDSName() {
public String getDSName() {
String selectedDSName = null;
String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem());
// 没有选中的列表项 那么看看是不是手输值

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

@ -15,6 +15,7 @@ import com.fr.esd.util.ESDUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.third.org.quartz.CronExpression;
import javax.swing.AbstractAction;
import javax.swing.JPanel;
@ -25,9 +26,11 @@ import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URI;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Date;
/**
* @author rinoux
@ -36,7 +39,6 @@ import java.util.List;
*/
public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html";
private UIRadioButton selectAutoUpdate;
private UIRadioButton selectBySchema;
private UICheckBox shouldEvolve;
@ -131,7 +133,6 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
ob = StrategyConfigHelper.createStrategyConfig(true, false, true);
}
this.strategyConfig = ob;
this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.valueOf(ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE));
this.schemaTime.setText(StringUtils.join(",", ob.getUpdateSchema().toArray(new String[0])));
this.shouldEvolve.setSelected(ob.shouldEvolve());
@ -177,11 +178,18 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
if (ESDUtils.checkUpdateTimeSchema(text)) {
if (ESDUtils.isCronExpression(text)) {
schemaTimes.add(text);
if (checkCornTimeInterval(text)) {
schemaTimes.add(text);
} else {
this.schemaTimeCheckTips.setText(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Interval_Too_Short"));
this.schemaTimeCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Update schema time interval is to short.");
}
} else {
Collections.addAll(schemaTimes, text.split(","));
}
} else {
this.schemaTimeCheckTips.setText(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format"));
this.schemaTimeCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Update schema time format error.");
}
@ -191,8 +199,15 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
String interval = this.updateInterval.getText();
if (checkUpdateInterval(interval)) {
long intervalMillis = StringUtils.isEmpty(interval) ? 0 : (long) (Double.parseDouble(interval) * CacheConstants.MILLIS_OF_MINUTE);
config.setUpdateInterval(intervalMillis);
if (intervalMillis >= CacheConstants.MILLIS_OF_MINUTE) {
config.setUpdateInterval(intervalMillis);
} else {
this.updateIntervalCheckTips.setText(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Interval_Too_Short"));
this.updateIntervalCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Update schema time interval is to short.");
}
} else {
this.updateIntervalCheckTips.setText(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format"));
this.updateIntervalCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Error update interval format.");
}
@ -220,6 +235,19 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
}
private boolean checkCornTimeInterval (String cronText) {
// 判断后两次更新时间间隔,如果小于1分钟就返回false
try {
CronExpression cron = new CronExpression(cronText);
Date next1 = cron.getNextValidTimeAfter(new Date());
Date next2 = cron.getNextValidTimeAfter(next1);
return next2.getTime() - next1.getTime() >= CacheConstants.MILLIS_OF_MINUTE;
} catch (ParseException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
protected String title4PopupWindow() {
return InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Strategy_Config_Title");
}

73
designer-base/src/main/java/com/fr/design/data/datapane/SummaryMethodComboBox.java

@ -0,0 +1,73 @@
package com.fr.design.data.datapane;
import com.fr.data.util.function.AbstractDataFunction;
import com.fr.data.util.function.AverageFunction;
import com.fr.data.util.function.CountFunction;
import com.fr.data.util.function.MaxFunction;
import com.fr.data.util.function.MinFunction;
import com.fr.data.util.function.NoneFunction;
import com.fr.data.util.function.SumFunction;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.i18n.Toolkit;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.chart.base.FirstFunction;
/**
* 图表数据汇总方式下拉框
*
* 支持首个最后一个求和平均最大值最小值个数
*
*/
public class SummaryMethodComboBox extends UIComboBox {
public static final String[] CALCULATE_ARRAY = {Toolkit.i18nText("Fine-Design_Chart_Data_Function_First"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Last"),
Toolkit.i18nText("Fine-Design_Chart_Data_Function_Sum"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Average"),
Toolkit.i18nText("Fine-Design_Chart_Data_Function_Max"), Toolkit.i18nText("Fine-Design_Chart_Data_Function_Min"),
Toolkit.i18nText("Fine-Design_Chart_Data_Function_Count")};
public static final Class[] CLASS_ARRAY = {FirstFunction.class, NoneFunction.class, SumFunction.class, AverageFunction.class,
MaxFunction.class, MinFunction.class, CountFunction.class};
public SummaryMethodComboBox() {
super(CALCULATE_ARRAY);
setSelectedIndex(2);
}
public void reset() {
this.setSelectedItem(Toolkit.i18nText("Fine-Design_Chart_Data_Function_Sum"));
}
/**
* 更新公式选择.
*/
public void populateBean(AbstractDataFunction function) {
if (function != null) {
for (int i = 0; i < CLASS_ARRAY.length; i++) {
if (this.getModel() != null && this.getModel().getSize() > i
&& ComparatorUtils.equals(function.getClass(), CLASS_ARRAY[i])) {
setSelectedIndex(i);
break;
}
}
}
}
/**
* 返回当前选择的公式
*/
public AbstractDataFunction updateBean() {
try {
int selectIndex = getSelectedIndex();
if (selectIndex >= 0 && selectIndex < CLASS_ARRAY.length) {
return (AbstractDataFunction) CLASS_ARRAY[selectIndex].newInstance();
}
} catch (InstantiationException e) {
FineLoggerFactory.getLogger().error("Function Error");
return null;
} catch (IllegalAccessException e) {
FineLoggerFactory.getLogger().error("Function Error");
return null;
}
return null;
}
}

28
designer-base/src/main/java/com/fr/design/data/datapane/TableDataCreatorProducer.java

@ -33,33 +33,33 @@ public class TableDataCreatorProducer {
public TableDataNameObjectCreator[] createReportTableDataCreator() {
TableDataNameObjectCreator dataBase = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Database_Query"),
"ds",
"/com/fr/design/images/data/database.png", DBTableData.class, DBTableDataPane.class);
"/com/fr/design/standard/database_normal.svg", DBTableData.class, DBTableDataPane.class);
TableDataNameObjectCreator ds_Class = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Class"),
"Class",
"/com/fr/design/images/data/source/classTableData.png", ClassTableData.class, ClassTableDataPane.class);
"/com/fr/design/standard/class_table_data_normal.svg", ClassTableData.class, ClassTableDataPane.class);
TableDataNameObjectCreator table = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Embedded"),
"Embedded",
"/com/fr/design/images/data/dataTable.png", EmbeddedTableData.class, EmbeddedTableDataPane.class);
"/com/fr/design/standard/data_table_normal.svg", EmbeddedTableData.class, EmbeddedTableDataPane.class);
TableDataNameObjectCreator multiTable = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Relation"),
"Multi",
"/com/fr/design/images/data/multi.png", ConditionTableData.class, MultiTDTableDataPane.class) {
"/com/fr/design/standard/multi_normal.svg", ConditionTableData.class, MultiTDTableDataPane.class) {
public boolean isNeedParameterWhenPopulateJControlPane() {
return true;
}
};
TableDataNameObjectCreator fileTable = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_File"),
"File",
"/com/fr/design/images/data/file.png", FileTableData.class, FileTableDataSmallHeightPane.class);
"/com/fr/design/standard/file_normal.svg", FileTableData.class, FileTableDataSmallHeightPane.class);
TableDataNameObjectCreator treeTable = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Tree"),
"Tree",
"/com/fr/design/images/data/tree.png", RecursionTableData.class, TreeTableDataPane.class) {
"/com/fr/design/standard/tree_normal.svg", RecursionTableData.class, TreeTableDataPane.class) {
public boolean isNeedParameterWhenPopulateJControlPane() {
return true;
}
};
TableDataNameObjectCreator storeProcedure = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Stored_Procedure"),
"Proc",
"/com/fr/design/images/data/store_procedure.png",
"/com/fr/design/standard/store_procedure_normal.svg",
StoreProcedure.class, ProcedureDataPane.class) {
@Override
public boolean shouldInsertSeparator() {
@ -72,33 +72,33 @@ public class TableDataCreatorProducer {
public TableDataNameObjectCreator[] createServerTableDataCreator() {
TableDataNameObjectCreator dataBase = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Database_Query"),
"/com/fr/design/images/data/dock/serverdatabase.png", DBTableData.class,
"/com/fr/design/standard/server_database_normal.svg", DBTableData.class,
DBTableDataPane.class);
TableDataNameObjectCreator ds_Class = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Class"),
"/com/fr/design/images/data/dock/serverclasstabledata.png", ClassTableData.class,
"/com/fr/design/standard/class_table_data_normal.svg", ClassTableData.class,
ClassTableDataPane.class);
TableDataNameObjectCreator table = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Embedded"),
"/com/fr/design/images/data/dock/serverdatatable.png", EmbeddedTableData.class,
"/com/fr/design/standard/data_table_normal.svg", EmbeddedTableData.class,
EmbeddedTableDataPane.class);
TableDataNameObjectCreator fileTable = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_File"),
"/com/fr/design/images/data/file.png", FileTableData.class,
"/com/fr/design/standard/file_normal.svg", FileTableData.class,
FileTableDataSmallPane.class);
TableDataNameObjectCreator treeTable = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Tree"),
"/com/fr/design/images/data/tree.png",
"/com/fr/design/standard/tree_normal.svg",
RecursionTableData.class, GlobalTreeTableDataPane.class) {
public boolean isNeedParameterWhenPopulateJControlPane() {
return true;
}
};
TableDataNameObjectCreator multiTable = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Relation"),
"/com/fr/design/images/data/multi.png",
"/com/fr/design/standard/multi_normal.svg",
ConditionTableData.class, GlobalMultiTDTableDataPane.class) {
public boolean isNeedParameterWhenPopulateJControlPane() {
return true;
}
};
TableDataNameObjectCreator storeProcedure = new TableDataNameObjectCreator(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Type_Stored_Procedure"),
"/com/fr/design/images/data/store_procedure.png",
"/com/fr/design/standard/store_procedure_normal.svg",
StoreProcedure.class, ProcedureDataPane.class) {
@Override
public boolean shouldInsertSeparator() {

12
designer-base/src/main/java/com/fr/design/data/datapane/TableDataNameObjectCreator.java

@ -1,6 +1,8 @@
package com.fr.design.data.datapane;
import com.fr.base.BaseUtils;
import com.fr.base.svg.IconUtils;
import com.fr.base.svg.SVGLoader;
import com.fr.data.impl.DBTableData;
import com.fr.design.actions.tabledata.TableDataAction;
import com.fr.design.beans.BasicBeanPane;
@ -39,7 +41,7 @@ public class TableDataNameObjectCreator extends NameObjectCreator {
public TableDataNameObjectCreator(TableDataAction action) {
super(action.getDisplayName(), action.getIconPath(), action.getTableDataClass(), action.getUpdateTableDataPaneClass());
this.iconPath = action.getIconPath();
menuImage = BaseUtils.readImage(iconPath);
menuImage = SVGLoader.load(iconPath);
isNeedInsertSeparator = action.isNeedInsertSeparator();
prefix = action.getPrefix();
}
@ -54,7 +56,7 @@ public class TableDataNameObjectCreator extends NameObjectCreator {
super(menuName, iconPath, clazz, updatePane);
if (iconPath != null) {
this.iconPath = iconPath;
menuImage = BaseUtils.readImage(iconPath);
menuImage = SVGLoader.load(iconPath);
}
}
@ -62,7 +64,7 @@ public class TableDataNameObjectCreator extends NameObjectCreator {
super(menuName, iconPath, clazz, updatePane);
if (iconPath != null) {
this.iconPath = iconPath;
menuImage = BaseUtils.readImage(iconPath);
menuImage = SVGLoader.load(iconPath);
}
this.prefix = prefix;
}
@ -71,7 +73,7 @@ public class TableDataNameObjectCreator extends NameObjectCreator {
super(menuName, iconPath, clazz, clazz4Init, updatePane);
if (iconPath != null) {
this.iconPath = iconPath;
menuImage = BaseUtils.readImage(iconPath);
menuImage = SVGLoader.load(iconPath);
}
}
@ -79,7 +81,7 @@ public class TableDataNameObjectCreator extends NameObjectCreator {
super(menuName, iconPath, clazz, clazz4Init, updatePane);
if (iconPath != null) {
this.iconPath = iconPath;
menuImage = BaseUtils.readImage(iconPath);
menuImage = SVGLoader.load(iconPath);
}
this.prefix = prefix;
}

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

@ -3,13 +3,11 @@ package com.fr.design.data.datapane;
import com.fr.base.TableData;
import com.fr.base.TableDataBean;
import com.fr.config.RemoteConfigEvent;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.api.StoreProcedureAssist;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.NameInspector;
import com.fr.design.gui.controlpane.JListControlPane;
import com.fr.design.gui.controlpane.NameableCreator;
import com.fr.design.gui.ilist.ListModelElement;
@ -18,25 +16,28 @@ import com.fr.event.EventDispatcher;
import com.fr.file.ProcedureConfig;
import com.fr.file.TableDataConfig;
import com.fr.file.TableDataOperator;
import com.fr.file.TableDataOperatorImpl;
import com.fr.general.ComparatorUtils;
import com.fr.general.NameObject;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
import com.fr.rpc.RPCInvokerExceptionInfo;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable;
import com.fr.stable.StringUtils;
import com.fr.stable.core.PropertyChangeAdapter;
import com.fr.third.org.apache.commons.collections4.MapUtils;
import com.fr.workspace.WorkContext;
import javax.swing.*;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* TableDataList Pane.
@ -52,15 +53,12 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
@Override
public void propertyChange() {
isNamePermitted = true;
String tempName = getEditingName();
if (ComparatorUtils.equals(tempName, selectedName)) {
//说明双击之后又取消了,啥也不用做
if (!checkName()) {
isNamePermitted = false;
return;
}
Set<String> allDSNames = DesignTableDataManager.getGlobalDataSet().keySet();
String[] allListNames = nameableList.getAllNames();
allListNames[editingIndex] = StringUtils.EMPTY;
String tempName = getEditingName();
Object editingType = getEditingType();
if (!BasicTableDataUtils.checkName(tempName)) {
@ -70,35 +68,36 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
return;
}
if (StringUtils.isEmpty(tempName)) {
if (editingType instanceof MultiResultTableData<?> && isIncludeUnderline(tempName)) {
isNamePermitted = false;
nameableList.stopEditing();
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this),
Toolkit.i18nText("Fine-Design_Basic_Table_Data_Empty_Name_Tips"),
Toolkit.i18nText("Fine-Design_Report_Alert"),
JOptionPane.WARNING_MESSAGE);
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Multi_Result_Table_Data_Name_Tips"));
setIllegalIndex(editingIndex);
return;
}
boolean isRepeated = isNameRepeated(new Collection[]{allDSNames, Arrays.asList(allListNames)}, tempName);
if (isRepeated) {
isNamePermitted = false;
nameableList.stopEditing();
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Table_Data_Duplicate_Name_Tips", tempName));
setIllegalIndex(editingIndex);
} else if (editingType instanceof StoreProcedure && isIncludeUnderline(tempName)) {
isNamePermitted = false;
nameableList.stopEditing();
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataPaneListPane.this), Toolkit.i18nText("Fine-Design_Basic_Stored_Procedure_Name_Tips"));
setIllegalIndex(editingIndex);
}
if (nameableList.getSelectedValue() instanceof ListModelElement) {
rename(selectedName, isRepeated ? NameInspector.ILLEGAL_NAME_HOLDER : tempName);
rename(selectedName, tempName);
}
}
});
}
@Override
public String getEmptyNameTip() {
return Toolkit.i18nText("Fine-Design_Basic_Table_Data_Empty_Name_Tips");
}
@Override
public String getDuplicatedNameTip() {
return Toolkit.i18nText("Fine-Design_Basic_Table_Data_Duplicate_Name_Tips", getEditingName());
}
@Override
public Collection getExtraItemsToCheckNameRepeat() {
return DesignTableDataManager.getGlobalDataSet().keySet();
}
@Override
public void rename(String oldName, String newName) {
//如果a改成了b,b又被改成了c,就认为是a改成了c
@ -137,7 +136,7 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
}
private boolean isIncludeUnderline(String name) {
return name.contains(StoreProcedureAssist.GROUP_MARKER);
return name.contains(MultiResultTableData.GROUP_MARKER);
}
/**
@ -249,15 +248,30 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
tableDataBeans.add(new TableDataBean(nameObject.getName(), oldName, (TableData) nameObject.getObject()));
}
try {
WorkContext.getCurrent().get(TableDataOperator.class).saveTableData(tableDataBeans);
WorkContext.getCurrent().get(TableDataOperator.class, new ExceptionHandler() {
@Override
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) {
// 走老的方式
return saveByOldWay(tableDataBeans);
}
}).saveTableData(new ArrayList<>(tableDataConfig.getTableDatas().keySet()), tableDataBeans);
if (!WorkContext.getCurrent().isLocal()) {
EventDispatcher.fire(RemoteConfigEvent.EDIT, TableDataConfig.class.getSimpleName());
EventDispatcher.fire(RemoteConfigEvent.EDIT, TableDataConfig.getInstance().getNameSpace());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean saveByOldWay(List<TableDataBean> tableDataBean) {
try {
return TableDataOperatorImpl.getInstance().saveTableData(tableDataBean);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return false;
}
}
@Override
public void update(TableDataSource tds) {
tds.clearAllTableData();

75
designer-base/src/main/java/com/fr/design/data/datapane/TableDataSourceOP.java

@ -2,20 +2,25 @@ package com.fr.design.data.datapane;
import com.fr.base.StoreProcedureParameter;
import com.fr.base.TableData;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.data.impl.storeproc.StoreProcedureConstants;
import com.fr.data.impl.storeproc.StoreProcedureHelper;
import com.fr.design.DesignModelAdapter;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper;
import com.fr.design.data.tabledata.wrapper.StoreProcedureNameWrapper;
import com.fr.design.data.tabledata.wrapper.MultiResultTableDataNameWrapper;
import com.fr.design.data.tabledata.wrapper.MultiResultTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.gui.itree.refreshabletree.UserObjectOP;
import com.fr.general.NameObject;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
@ -155,9 +160,9 @@ public class TableDataSourceOP implements UserObjectOP<TableDataWrapper> {
list.add(initStoreProcedureNode(storeProcedureMap));
for (int i = 0; i < getNodeArrayFromMap(storeProcedureMap).length; i++) {
ExpandMutableTreeNode tmpNode = getNodeArrayFromMap(storeProcedureMap)[i];
if (((NameObject) tmpNode.getUserObject()).getObject() instanceof StoreProcedureNameWrapper) {
TableData tableData = ((StoreProcedureNameWrapper) (((NameObject) tmpNode.getUserObject()).getObject())).getStoreProcedure();
setStoreProcedureTree(tableData, tmpNode);
if (((NameObject) tmpNode.getUserObject()).getObject() instanceof MultiResultTableDataNameWrapper) {
TableData tableData = ((MultiResultTableDataNameWrapper) (((NameObject) tmpNode.getUserObject()).getObject())).getTableData();
setStoreProcedureTree((MultiResultTableData<?>) tableData, tmpNode);
serverlist.add(tmpNode);
}
}
@ -176,8 +181,8 @@ public class TableDataSourceOP implements UserObjectOP<TableDataWrapper> {
for (int i = 0; i < getNodeArrayFromMap(dataMap).length; i++) {
ExpandMutableTreeNode tmpNode = getNodeArrayFromMap(dataMap)[i];
TableData tableData = ((TableDataWrapper) (((NameObject) tmpNode.getUserObject()).getObject())).getTableData();
if (tableData instanceof StoreProcedure) {
setStoreProcedureTree(tableData, tmpNode);
if (tableData instanceof MultiResultTableData<?>) {
setStoreProcedureTree((MultiResultTableData<?>) tableData, tmpNode);
dataList.add(tmpNode);
} else {
dataList.add(tmpNode);
@ -185,31 +190,49 @@ public class TableDataSourceOP implements UserObjectOP<TableDataWrapper> {
}
}
protected void setStoreProcedureTree(TableData tableData, ExpandMutableTreeNode tmpNode) {
protected void setStoreProcedureTree(MultiResultTableData<?> tableData, ExpandMutableTreeNode tmpNode) {
ArrayList<String> nodeName = new ArrayList<>();
StoreProcedure storeProcedure = (StoreProcedure) tableData;
String name = ((NameObject) tmpNode.getUserObject()).getName();
StoreProcedureParameter[] parameters = StoreProcedure.getSortPara(storeProcedure.getParameters());
List<String> resultNames = storeProcedure.getResultNames();
List<String> resultNames = tableData.getResultNames();
boolean hasChild = false;
tmpNode.remove(0);
TableDataWrapper tdw = new StoreProcedureNameWrapper(name + "_Table1", storeProcedure);
TableDataWrapper tdw = new MultiResultTableDataNameWrapper(name + "_Table1", tableData);
ExpandMutableTreeNode childNode = new ExpandMutableTreeNode(new NameObject("Table", tdw));
childNode.add(new ExpandMutableTreeNode());
tmpNode.add(childNode);
for (StoreProcedureParameter parameter : parameters) {
if (parameter.getSchema() != StoreProcedureConstants.IN) {
if (!nodeName.contains(parameter.getName())) {
nodeName.add(parameter.getName());
hasChild = true;
String parameterName = name + "_" + parameter.getName();
TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false);
ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(parameter.getName(), newTwd));
newChildNode.add(new ExpandMutableTreeNode());
tmpNode.add(newChildNode);
if (tableData instanceof StoreProcedure) {
StoreProcedure storeProcedure = (StoreProcedure) tableData;
StoreProcedureParameter[] parameters = StoreProcedureHelper.getSortPara(storeProcedure.getParameters());
for (StoreProcedureParameter parameter : parameters) {
if (parameter.getSchema() != StoreProcedureConstants.IN) {
if (!nodeName.contains(parameter.getName())) {
nodeName.add(parameter.getName());
hasChild = true;
String parameterName = name + "_" + parameter.getName();
TableDataWrapper newTwd = new MultiResultTableDataWrapper(tableData, name, parameterName, false);
ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(parameter.getName(), newTwd));
newChildNode.add(new ExpandMutableTreeNode());
tmpNode.add(newChildNode);
}
}
}
}
} /*else {
if (tableData.getDataModelList().size() > 1) {
for (NameDataModel nameDataModel : tableData.getDataModelList()) {
if (!nodeName.contains(nameDataModel.getName())) {
nodeName.add(nameDataModel.getName());
hasChild = true;
String parameterName = name + "_" + nameDataModel.getName();
TableDataWrapper newTwd = new MultiResultTableDataWrapper(tableData, name, parameterName, false);
ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(nameDataModel.getName(), newTwd));
newChildNode.add(new ExpandMutableTreeNode());
tmpNode.add(newChildNode);
}
}
}
}*/
if (!resultNames.isEmpty()) {
for (String resultName : resultNames) {
@ -217,7 +240,7 @@ public class TableDataSourceOP implements UserObjectOP<TableDataWrapper> {
nodeName.add(resultName);
hasChild = true;
String parameterName = name + "_" + resultName;
TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false);
TableDataWrapper newTwd = new MultiResultTableDataWrapper(tableData, name, parameterName, false);
ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(resultName, newTwd));
newChildNode.add(new ExpandMutableTreeNode());
tmpNode.add(newChildNode);

254
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java

@ -1,7 +1,9 @@
package com.fr.design.data.datapane;
import com.fr.base.BaseUtils;
import com.fr.base.svg.IconUtils;
import com.fr.data.MultiResultTableData;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.gui.itree.refreshabletree.UserObjectRefreshJTree;
@ -17,6 +19,10 @@ import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* TableData Tree
@ -24,6 +30,10 @@ import java.awt.Component;
public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
private static final long serialVersionUID = 1L;
private static final String TABLE_DATA_NODE = "tableData";
private static final String COLUMN_NODE = "column";
/**
* Constructor.
*/
@ -44,7 +54,7 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
Object userObj = treeNode.getUserObject();
if (userObj instanceof String) {
// p:这个是column field.
this.setIcon(BaseUtils.readIcon("com/fr/design/images/data/field.png"));
this.setIcon(IconUtils.readIcon("/com/fr/design/standard/field"));
this.setText((String) userObj);
} else if (userObj instanceof NameObject) {
NameObject nameObject = (NameObject) userObj;
@ -55,14 +65,14 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
} else if (nameObject.getObject() instanceof Integer) {
int num = (Integer) nameObject.getObject();
if (num == TableDataSourceOP.SERVER_TABLE_DATA) {
this.setIcon(BaseUtils.readIcon(IconPathConstants.STD_SHOW_ICON_PATH));
this.setIcon(IconUtils.readIcon(IconPathConstants.STD_SHOW_ICON_PATH));
} else if (num == TableDataSourceOP.STORE_PRECEDURE_DATA) {
this.setIcon(BaseUtils.readIcon(IconPathConstants.SP_SHOW_ICON_PATH));
this.setIcon(IconUtils.readIcon(IconPathConstants.SP_SHOW_ICON_PATH));
} else {
this.setIcon(BaseUtils.readIcon(IconPathConstants.DS_QUERY_ICON_PATH));
this.setIcon(IconUtils.readIcon(IconPathConstants.DS_QUERY_ICON_PATH));
}
} else {
this.setIcon(BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png"));
this.setIcon(IconUtils.readIcon("/com/fr/design/images/data/store_procedure.png"));
}
} else if (userObj == PENDING) {
this.setIcon(null);
@ -84,12 +94,13 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
this.tableDataTreeCellRenderer = tableDataTreeCellRenderer;
}
@Override
protected void refreshTreeNode(ExpandMutableTreeNode eTreeNode, String childName) {
if (interceptRefresh(eTreeNode)) {
return;
}
boolean refreshall = childName.isEmpty();
ExpandMutableTreeNode[] new_nodes = loadChildTreeNodes(eTreeNode);
ExpandMutableTreeNode[] newNodes = loadChildTreeNodes(eTreeNode);
java.util.List<DefaultMutableTreeNode> childTreeNodeList = new java.util.ArrayList<DefaultMutableTreeNode>();
for (int i = 0, len = eTreeNode.getChildCount(); i < len; i++) {
@ -102,30 +113,30 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
eTreeNode.removeAllChildren();
for (int ci = 0; ci < new_nodes.length; ci++) {
Object cUserObject = new_nodes[ci].getUserObject();
for (int ci = 0; ci < newNodes.length; ci++) {
Object cUserObject = newNodes[ci].getUserObject();
ExpandMutableTreeNode cTreeNode = null;
for (int ni = 0, nlen = childTreeNodeList.size(); ni < nlen; ni++) {
cTreeNode = (ExpandMutableTreeNode) childTreeNodeList.get(ni);
if (ComparatorUtils.equals(cTreeNode.getUserObject(), cUserObject)) {
if (!refreshall && !ComparatorUtils.equals(childName, ((NameObject) cUserObject).getName())) {
new_nodes[ci] = cTreeNode;
newNodes[ci] = cTreeNode;
break;
}
new_nodes[ci].setExpanded(cTreeNode.isExpanded());
newNodes[ci].setExpanded(cTreeNode.isExpanded());
// REPORT-41299 如果建立的是错误的数据集(没有Child的情况)且这个错误数据集处于isExpanded状态,会在后面的if语句中调用getFirstChild()产生异常,因此这里判断一下
if (cTreeNode.isExpanded() && cTreeNode.getChildCount() == 0) {
new_nodes[ci].setExpanded(false);
if (cTreeNode.getChildCount() == 0) {
newNodes[ci].setExpanded(false);
break;
}
if (cTreeNode.getFirstChild() instanceof ExpandMutableTreeNode && cTreeNode.isExpanded()) {
checkChildNodes(cTreeNode, new_nodes[ci]);
checkChildNodes(cTreeNode, newNodes[ci]);
}
break;
}
}
eTreeNode.add(new_nodes[ci]);
eTreeNode.add(newNodes[ci]);
}
}
@ -140,9 +151,7 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
for (int k = 0; k < nodes.length; k++) {
newChild.add(nodes[k]);
}
if (newChild.getChildCount() > 1 && ((ExpandMutableTreeNode) newChild.getFirstChild()).getUserObject() == PENDING) {
newChild.remove(0);
}
removePending(newChild);
if (ComparatorUtils.equals(oldChild.getUserObject(), newChild.getUserObject())) {
newChild.setExpanded(oldChild.isExpanded());
}
@ -150,9 +159,100 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
}
}
private void removePending(ExpandMutableTreeNode treeNode) {
if (treeNode.getChildCount() > 1 && ((ExpandMutableTreeNode) treeNode.getFirstChild()).getUserObject() == PENDING) {
treeNode.remove(0);
}
}
@Override
public void refresh4TreeSearch() {
ExpandMutableTreeNode root = (ExpandMutableTreeNode) this.getModel().getRoot();
refreshTreeNode4TreeSearch(root);
((DefaultTreeModel) this.getModel()).reload(root);
root.expandCurrentTreeNode(this);
}
/**
* 主要是处理节点是否应该添加为搜索结果以及节点是否需要展开
*
* @param root
*/
private void refreshTreeNode4TreeSearch(ExpandMutableTreeNode root) {
if (interceptRefresh(root)) {
return;
}
// 获取数据集子节点
ExpandMutableTreeNode[] dsTreeNodes = loadChildTreeNodes(root);
root.removeAllChildren();
for (ExpandMutableTreeNode dsTreeNode : dsTreeNodes) {
if (TableDataTreeSearchManager.getInstance().nodeNameMatches(dsTreeNode.getUserObject().toString())) {
// 加载数据列节点
loadAndAddChildTreeChild(dsTreeNode);
// 处理子节点的展开
dealWithNodeExpand(dsTreeNode);
// 添加数据集子节点
root.add(dsTreeNode);
}
}
}
/**
* 加载所有子节点并添加到父节点中
*
* @param treeNode
* @return
*/
private ExpandMutableTreeNode loadAndAddChildTreeChild(ExpandMutableTreeNode treeNode) {
if (isTreeNodeStoreProcedure(treeNode)) {
// 如果是存储过程,则再加载一次其子表节点,这里比较坑的就是存储过程不能使用loadChildTreeNodes
int tableChildCounts = treeNode.getChildCount();
ExpandMutableTreeNode[] childs = new ExpandMutableTreeNode[tableChildCounts];
for (int i = 0; i < tableChildCounts; i++) {
ExpandMutableTreeNode tableChild = (ExpandMutableTreeNode) treeNode.getChildAt(i);
loadAndAddChildTreeChild(tableChild);
childs[i] = tableChild;
removePending(tableChild);
}
treeNode.addChildTreeNodes(childs);
} else {
ExpandMutableTreeNode[] expandMutableTreeNodes = loadChildTreeNodes(treeNode);
treeNode.addChildTreeNodes(expandMutableTreeNodes);
}
removePending(treeNode);
return treeNode;
}
/**
* 处理节点的展开如果此节点是存储过程还会处理其子表节点的展开
* 只针对数据集节点
*
* @param treeNode
* @return
*/
public ExpandMutableTreeNode dealWithNodeExpand(ExpandMutableTreeNode treeNode) {
String tableDataName = treeNode.getUserObject().toString();
// 主要还是处理存储过程
if (isTreeNodeStoreProcedure(treeNode)) {
int childCount = treeNode.getChildCount();
for (int i = 0; i < childCount; i++) {
ExpandMutableTreeNode child = (ExpandMutableTreeNode) treeNode.getChildAt(i);
String nodeName = tableDataName + "_" + child.getUserObject().toString();
if (TableDataTreeSearchManager.getInstance().nodeCanExpand(nodeName)) {
child.setExpanded(true);
}
}
}
if (TableDataTreeSearchManager.getInstance().nodeCanExpand(treeNode.getUserObject().toString())) {
treeNode.setExpanded(true);
}
return treeNode;
}
/*
* p:获得选中的NameObject = name + tabledata.
*/
@Override
public NameObject getSelectedNameObject() {
TreePath selectedTreePath = this.getSelectionPath();
if (selectedTreePath == null) {
@ -182,6 +282,108 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
}
/**
* 获得选中的数据集节点的NameObject的数组只会返回数据集节点的NameObject
* 当多选了数据集或数据列时也只返回选中的数据集
*/
public NameObject[] getSelectedTableDataNameObjects() {
Map<String, List<ExpandMutableTreeNode>> tableDataNodesAndColumnNodes = getSelectedTableDataNodesAndColumnNodes();
List<ExpandMutableTreeNode> tableDataNodes = tableDataNodesAndColumnNodes.get(TABLE_DATA_NODE);
if (tableDataNodes == null) {
return new NameObject[0];
}
return tableDataNodes.stream().map(node -> (NameObject) node.getUserObject()).toArray(NameObject[]::new);
}
/**
* 获取选中的数据集节点和列名节点
* 其中存储过程的子表节点不计入数据集节点中仅存储过程节点本身计入数据集节点
* @return
*/
private Map<String, List<ExpandMutableTreeNode>> getSelectedTableDataNodesAndColumnNodes() {
TreePath[] selectedTreePaths = this.getSelectionPaths();
if (selectedTreePaths == null) {
return new HashMap<>();
}
Map<String, List<ExpandMutableTreeNode>> resultMap = new HashMap<>();
List<ExpandMutableTreeNode> tableDataNodes = new ArrayList<>();
List<ExpandMutableTreeNode> columnNodes = new ArrayList<>();
resultMap.put(TABLE_DATA_NODE, tableDataNodes);
resultMap.put(COLUMN_NODE, columnNodes);
for (TreePath selectedTreePath : selectedTreePaths) {
if (selectedTreePath == null) {
continue;
}
ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent();
if (isTableDataNodes(selectedTreeNode)) {
// 数据集节点
tableDataNodes.add(selectedTreeNode);
} else {
// 列名节点
columnNodes.add(selectedTreeNode);
}
}
return resultMap;
}
/**
* 获取选中的数据集数量选中数据列则不计入
*
* @return
*/
public int getSelectedTableDataCounts() {
return getSelectedTableDataNameObjects().length;
}
/**
* 是否存在单独选了数据列节点但没选其对应数据集的情况
* @return
*/
public boolean hasSelectedIndependentColumns() {
Map<String, List<ExpandMutableTreeNode>> tableDataNodesAndColumnNodes = getSelectedTableDataNodesAndColumnNodes();
List<ExpandMutableTreeNode> tableDataNodes = tableDataNodesAndColumnNodes.get(TABLE_DATA_NODE);
List<ExpandMutableTreeNode> columnNodes = tableDataNodesAndColumnNodes.get(COLUMN_NODE);
if (columnNodes == null || columnNodes.size() == 0) {
// 未选中数据列
return false;
}
if (tableDataNodes == null || tableDataNodes.size() == 0) {
// 选中数据列而未选中数据集
return true;
}
boolean result = false;
for (ExpandMutableTreeNode columnNode : columnNodes) {
ExpandMutableTreeNode tableDataNode = getBelongedTableDataNodes(columnNode);
if (!tableDataNodes.contains(tableDataNode)) {
result = true;
}
}
return result;
}
/**
* 获取一个节点归属的数据集层级父节点
* @param treeNode
* @return
*/
private ExpandMutableTreeNode getBelongedTableDataNodes(ExpandMutableTreeNode treeNode) {
if (isTableDataNodes(treeNode)) {
return treeNode;
}
return getBelongedTableDataNodes((ExpandMutableTreeNode) treeNode.getParent());
}
private boolean isTableDataNodes(ExpandMutableTreeNode treeNode) {
if (treeNode == null) {
return false;
}
Object userObject = treeNode.getUserObject();
if (userObject instanceof NameObject && ((NameObject) userObject).getObject() instanceof TableDataWrapper) {
return true;
}
return false;
}
public TableDataWrapper[] getSelectedDatas() {
TreePath[] selectedTreePaths = this.getSelectionPaths();
if (selectedTreePaths == null || selectedTreePaths.length == 0) {
@ -247,4 +449,20 @@ public class TableDataTree extends UserObjectRefreshJTree<TableDataSourceOP> {
treeModel.reload(root);
}
/**
* 判断此节点是否为存储过程
*
* @param treeNode
* @return
*/
public boolean isTreeNodeStoreProcedure(ExpandMutableTreeNode treeNode) {
Object userObject = treeNode.getUserObject();
if (userObject instanceof NameObject) {
NameObject nameObject = (NameObject) userObject;
TableDataWrapper tableDataWrapper = (TableDataWrapper) nameObject.getObject();
return tableDataWrapper.getTableData() instanceof MultiResultTableData<?>;
}
return false;
}
}

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

@ -1,6 +1,7 @@
package com.fr.design.data.datapane;
import com.fr.base.TableData;
import com.fr.data.MultiResultTableData;
import com.fr.data.TableDataSource;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.TableDataSourceDependent;
@ -13,30 +14,41 @@ import com.fr.design.data.BasicTableDataTreePane;
import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.StrategyConfigAttrUtils;
import com.fr.design.data.datapane.auth.TableDataAuthHelper;
import com.fr.design.data.datapane.management.clip.TableDataTreeClipboard;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.pane.TableDataSearchRemindPane;
import com.fr.design.data.datapane.management.search.pane.TreeSearchToolbarPane;
import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode;
import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.TableDataPaneProcessor;
import com.fr.design.gui.ibutton.UIHeadGroup;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.CheckBoxListWithPartialSelect;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.i18n.Toolkit;
import com.fr.design.icon.IconPathConstants;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.LineSeparator;
import com.fr.design.menu.MenuDef;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.esd.core.strategy.config.StrategyConfig;
import com.fr.esd.core.strategy.config.StrategyConfigHelper;
import com.fr.esd.event.DSMapping;
@ -45,7 +57,6 @@ import com.fr.esd.event.StrategyEventsNotifier;
import com.fr.esd.query.StrategicTableData;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext;
import com.fr.general.IOUtils;
import com.fr.general.NameObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContext;
@ -53,6 +64,7 @@ import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.stable.StringUtils;
import com.fr.stable.core.PropertyChangeAdapter;
import com.fr.workspace.WorkContext;
import org.jetbrains.annotations.NotNull;
@ -60,7 +72,6 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
@ -68,12 +79,17 @@ import javax.swing.ToolTipManager;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.dnd.DnDConstants;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@ -103,15 +119,37 @@ public class TableDataTreePane extends BasicTableDataTreePane {
return singleton;
}
/**
* 获取不必每次都refreshDockingView的数据集树面板
* 不会主动替换DesignModelAdapter需要保证使用时没有跨模板动作谨慎使用
*
* @param tc
* @return
*/
public synchronized static BasicTableDataTreePane getInstanceWithoutRefreshEverytime(DesignModelAdapter<?, ?> tc) {
TableDataPaneProcessor treePaneProcessor = ExtraDesignClassManager.getInstance().getSingle(TableDataPaneProcessor.XML_TAG);
if (treePaneProcessor != null) {
return treePaneProcessor.createTableDataTreePane(tc);
}
return singleton.tc == null ? getInstance(tc) : singleton;
}
private TableDataSourceOP op;
private TableDataTree tableDataTree;
private UIPopupMenu popupMenu;
private EditAction editAction;
private RemoveAction removeAction;
private CopyAction copyAction;
private PasteAction pasteAction;
private EsdOnAction esdAction;
private EsdOffAction esdOffAction;
private SwitchAction switchAction;
private PreviewTableDataAction previewTableDataAction;
private JPanel serverDatasetAuthTipJPanel = new JPanel();
private TableDataSearchRemindPane remindPane;
private TreeSearchToolbarPane toolbarPane;
private TableDataTreePane() {
initPane();
}
@ -120,76 +158,150 @@ public class TableDataTreePane extends BasicTableDataTreePane {
this.setLayout(new BorderLayout(4, 0));
this.setBorder(null);
//TableDataTree
tableDataTree = new TableDataTree();
initTableDataTree();
toolbarPane = initToolBarPane();
JPanel treePane = initTreePane();
dealWithTableDataTree();
this.add(toolbarPane, BorderLayout.NORTH);
this.add(treePane, BorderLayout.CENTER);
checkButtonEnabled();
}
/**
* 处理TableDataTree的监听等
*/
private void dealWithTableDataTree() {
// tooltip
ToolTipManager.sharedInstance().registerComponent(tableDataTree);
ToolTipManager.sharedInstance().setDismissDelay(3000);
ToolTipManager.sharedInstance().setInitialDelay(0);
// 右键菜单
popupMenu = new UIPopupMenu();
popupMenu.add(editAction.createMenuItem());
popupMenu.add(previewTableDataAction.createMenuItem());
popupMenu.addSeparator();
popupMenu.add(copyAction.createMenuItem());
popupMenu.add(pasteAction.createMenuItem());
popupMenu.add(removeAction.createMenuItem());
popupMenu.addSeparator();
// 监听
tableDataTree.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// 服务器暂不支持右键菜单
if (SwingUtilities.isRightMouseButton(e) && op.getDataMode() != TableDataSourceOP.SERVER_TABLE_DATA) {
GUICoreUtils.showPopupMenu(popupMenu, e.getComponent(), e.getX(), e.getY());
}
checkButtonEnabled();
}
});
tableDataTree.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//F2重命名先屏蔽了, 有bug没时间弄
if (e.getKeyCode() == KeyEvent.VK_F2) {
return;
}
super.keyPressed(e);
checkButtonEnabled();
}
@Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
checkButtonEnabled();
}
});
// TreeCellEditor
tableDataTree.setEditable(true);
TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this);
treeCellEditor.addCellEditorListener(treeCellEditor);
tableDataTree.setCellEditor(treeCellEditor);
new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY);
}
/**
* 工具栏面板
*
* @return
*/
private TreeSearchToolbarPane initToolBarPane() {
// toolbar
addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add"));
addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH);
addMenuDef.setIconPath("/com/fr/design/standard/addpopup/addPopup");
createAddMenuDef();
// 创建插件监听
createPluginListener();
editAction = new EditAction();
copyAction = new CopyAction();
pasteAction = new PasteAction();
removeAction = new RemoveAction();
previewTableDataAction = new PreviewTableDataAction(tableDataTree);
connectionTableAction = new ConnectionTableAction();
esdAction = new EsdOnAction();
esdOffAction = new EsdOffAction();
switchAction = new SwitchAction();
toolbarDef = new ToolBarDef();
toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction);
toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction, switchAction);
UIToolbar toolBar = ToolBarDef.createJToolBar();
toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR));
toolBar.setBorderPainted(true);
toolbarDef.updateToolBar(toolBar);
JPanel toolbarPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
toolbarPane.add(toolBar, BorderLayout.CENTER);
this.add(toolbarPane, BorderLayout.NORTH);
TreeSearchToolbarPane searchLayerdPane = new TreeSearchToolbarPane(toolBar);
searchLayerdPane.setPreferredSize(new Dimension(this.getWidth(), 23));
UIScrollPane scrollPane = new UIScrollPane(tableDataTree);
scrollPane.setBorder(null);
return searchLayerdPane;
}
/**
* 数据集树面板
*
* @return
*/
private JPanel initTreePane() {
JPanel treePane = new JPanel(new BorderLayout(0, 6));
// north
JPanel northPane = new JPanel(FRGUIPaneFactory.createBorderLayout());
initServerDatasetAuthTipJPanel();
initButtonGroup();
JPanel jPanel = new JPanel(new BorderLayout(0, 0));
JPanel buttonPane = new JPanel(FRGUIPaneFactory.createBorderLayout());
buttonPane.add(buttonGroup, BorderLayout.CENTER);
buttonPane.add(serverDatasetAuthTipJPanel, BorderLayout.SOUTH);
jPanel.add(buttonPane, BorderLayout.NORTH);
jPanel.add(scrollPane, BorderLayout.CENTER);
this.add(jPanel, BorderLayout.CENTER);
tableDataTree.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
checkButtonEnabled();
}
});
tableDataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, tableDataTree));
// TreeCellEditor
tableDataTree.setEditable(true);
TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this);
treeCellEditor.addCellEditorListener(treeCellEditor);
tableDataTree.setCellEditor(treeCellEditor);
new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY);
checkButtonEnabled();
northPane.add(buttonGroup, BorderLayout.CENTER);
northPane.add(serverDatasetAuthTipJPanel, BorderLayout.SOUTH);
// center
remindPane = new TableDataSearchRemindPane(getDataTree());
treePane.add(northPane, BorderLayout.NORTH);
treePane.add(remindPane, BorderLayout.CENTER);
return treePane;
}
/**
* 初始化 TableDataTree
*/
private void initTableDataTree() {
tableDataTree = new TableDataTree();
}
private void initServerDatasetAuthTipJPanel() {
String[] lineTips = Toolkit.i18nText("Fine-Design_Server_Dataset_Auth_Tip").split("\n");
String datasetAuthTip = Toolkit.i18nText("Fine-Design_Server_Dataset_Auth_Tip");
List<String> lineTips = new ArrayList(Arrays.asList(datasetAuthTip.split("\n")));
if (datasetAuthTip.endsWith("\n")) {
lineTips.add(StringUtils.EMPTY);
}
serverDatasetAuthTipJPanel = new JPanel();
serverDatasetAuthTipJPanel.setLayout(new GridLayout(lineTips.length, 1));
for (int i = 0; i < lineTips.length; i++) {
String lineTip = lineTips[i];
serverDatasetAuthTipJPanel.setLayout(new GridLayout(lineTips.size(), 1));
for (int i = 0; i < lineTips.size(); i++) {
String lineTip = lineTips.get(i);
List<JLabel> jLabels = new ArrayList<>();
jLabels.add(new JLabel(lineTip));
if (i == (lineTips.length - 1)) {
JLabel lineJLabel = new JLabel(lineTip);
lineJLabel.setForeground(Color.lightGray);
jLabels.add(lineJLabel);
if (i == (lineTips.size() - 1)) {
JLabel jLabel = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Alphafine_No_Remind"));
jLabel.setForeground(Color.lightGray);
jLabel.setForeground(Color.blue);
jLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@ -292,6 +404,10 @@ public class TableDataTreePane extends BasicTableDataTreePane {
*/
@Override
public void dgEdit(final AbstractTableDataPane<?> tableDataPane, String originalName, boolean isUpdate) {
// 编辑时如果正在搜索,跳回原树
if (TableDataTreeSearchManager.getInstance().isInSearchMode()) {
TableDataTreeSearchManager.getInstance().outOfSearchMode();
}
tableDataPane.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() {
public void fireDoneAction() {
if (tableDataTree.getSelectionPath() == null) {
@ -353,20 +469,59 @@ public class TableDataTreePane extends BasicTableDataTreePane {
//单独编辑数据集关闭,修改缓存配置状态,刷新下一键开启/关闭按钮
checkButtonEnabled();
if (listener != null) {
listener.doOk();
}
}
@Override
public void doCancel() {
super.doCancel();
if (listener != null) {
listener.doCancel();
}
}
});
tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() {
@Override
public void propertyChange() {
doPropertyChange(dg, tdNamePanel, oldName);
checkNameChange(tableDataPane, dg, tdNamePanel, oldName);
}
});
dg.setVisible(true);
// 有些数据集(DBTableData)面板的初始化过程中是包含了SwingWorker处理(查询数据连接、查表等)的
// 如果这里直接setVisible,可能阻塞SwingWorker的done方法,导致面板渲染出现问题
SwingUtilities.invokeLater(() -> {
dg.setVisible(true);
});
}
private void checkNameChange(AbstractTableDataPane<?> tableDataPane, BasicDialog dg, BasicPane.NamePane nPanel, final String oldName) {
nPanel.setShowText(StringUtils.BLANK);
dg.setButtonEnabled(true);
String tempName = nPanel.getObjectName();
if (StringUtils.isBlank(tempName)) {
nPanel.setShowText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Table_Data_Empty_Name_Tips"));
dg.setButtonEnabled(false);
} else if (!ComparatorUtils.equals(oldName, tempName) && isDsNameRepeaded(tempName)) {
nPanel.setShowText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Table_Data_Duplicate_Name_Tips", tempName));
dg.setButtonEnabled(false);
} else if (oldName.length() >= PROCEDURE_NAME_INDEX && tableDataPane.updateBean() instanceof MultiResultTableData) {
if (isIncludeUnderline(tempName)) {
nPanel.setShowText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Multi_Result_Table_Data_Name_Tips"));
dg.setButtonEnabled(false);
}
} else if (!BasicTableDataUtils.checkName(tempName)) {
dg.setButtonEnabled(false);
} else {
nPanel.setShowText(StringUtils.BLANK);
dg.setButtonEnabled(true);
}
}
private boolean isIncludeUnderline(String name) {
return !ComparatorUtils.equals(name.indexOf(MultiResultTableData.GROUP_MARKER), -1);
}
@Override
@ -456,6 +611,17 @@ public class TableDataTreePane extends BasicTableDataTreePane {
((TableDataSourceDependent) td).setTableDataSource(tds);
}
String tdName = nPanel.getObjectName();
//处理缓存策略配置
if (uPanel instanceof DBTableDataPane) {
StrategyConfig editingConfig = ((DBTableDataPane) uPanel).updateStrategyConfig();
if (editingConfig != null) {
editingConfig.setDsName(tdName);
StrategyConfigAttrUtils.addStrategyConfig(editingConfig);
}
((DBTableData) td).setDsName(tdName);
}
tds.putTableData(tdName, td);
Map<String, String> map = new HashMap<String, String>();
if (!ComparatorUtils.equals(paneName, tdName)) {
@ -467,6 +633,7 @@ public class TableDataTreePane extends BasicTableDataTreePane {
int[] rows = tableDataTree.getSelectionRows();
tableDataTree.refreshChildByName(tdName);
tableDataTree.setSelectionRows(rows);
FineLoggerFactory.getLogger().info("add table data succeeded for {}", tdName);
}
@Override
@ -486,11 +653,61 @@ public class TableDataTreePane extends BasicTableDataTreePane {
this.createAddMenuDef();
}
/**
* 感觉这里把一堆Action和Op之类的送到抽象类里去检查很奇怪抽象类本身定义的Action只有add和connection
* 另外因为改动了数据集树节点的选中逻辑所以这边改成自己类内部实现
* 不直接改抽象类是怕影响到部分插件兼容
*/
private void checkButtonEnabled() {
super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, tableDataTree);
// 检查添加与定义数据连接操作
this.checkAddAndConnectionEnabled();
// 检查编辑、预览、复制、粘贴、删除等基本操作
this.checkBasicButtonEnabled();
// 检查esd相关操作
this.checkESDComponentsEnabled();
}
private void checkAddAndConnectionEnabled() {
connectionTableAction.setEnabled(WorkContext.getCurrent() != null && WorkContext.getCurrent().isRoot());
addMenuDef.setEnabled(!(op == null || op.interceptButtonEnabled() || op.getDataMode() == SERVER_TABLE_DATA));
}
private void checkBasicButtonEnabled() {
// 设置下各个button的基本状态,避免代码重复
editAction.setEnabled(false);
copyAction.setEnabled(false);
pasteAction.setEnabled(false);
removeAction.setEnabled(false);
previewTableDataAction.setEnabled(false);
if (op == null || op.interceptButtonEnabled()) {
// 保持false状态
return;
}
// 获取选中的数据集数量
int selectioncount = getDataTree().getSelectedTableDataCounts();
if (op.getDataMode() == SERVER_TABLE_DATA) {
// 服务器数据集下,选中数据集数量为1时,可以预览
if (selectioncount == 1 && !getDataTree().hasSelectedIndependentColumns()) {
previewTableDataAction.setEnabled(true);
}
// 其它保持false状态
return;
}
// 模板数据集时,粘贴可用
pasteAction.setEnabled(true);
if (selectioncount == 0 || getDataTree().hasSelectedIndependentColumns()) {
// 未选中数据集,或存在单独选中的数据列时,其它保持false状态
return;
}
if (selectioncount == 1) {
// 仅选中单个数据集时,才可以编译、预览
editAction.setEnabled(true);
previewTableDataAction.setEnabled(true);
}
removeAction.setEnabled(true);
copyAction.setEnabled(true);
}
private void checkESDComponentsEnabled() {
if (buttonGroup.getSelectedIndex() == 1) {
@ -579,6 +796,9 @@ public class TableDataTreePane extends BasicTableDataTreePane {
if (op != null) {
op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]);
addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA);
if (TableDataTreeSearchManager.getInstance().isInSearchMode()) {
TableDataTreeSearchManager.getInstance().outOfSearchMode();
}
refreshDockingView();
}
@ -674,8 +894,8 @@ public class TableDataTreePane extends BasicTableDataTreePane {
}
@Override
public Icon getIcon() {
return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_on.png");
public String getIconResource() {
return "/com/fr/design/standard/batchesdon/batch_esd_on";
}
@Override
@ -721,8 +941,8 @@ public class TableDataTreePane extends BasicTableDataTreePane {
}
@Override
public Icon getIcon() {
return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_off.png");
public String getIconResource() {
return "/com/fr/design/standard/batchesdoff/batch_esd_off";
}
@Override
@ -743,14 +963,14 @@ public class TableDataTreePane extends BasicTableDataTreePane {
public abstract String getName();
public abstract Icon getIcon();
public abstract String getIconResource();
public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper);
public AbstractESDAction() {
this.setName(getName());
this.setMnemonic('R');
this.setSmallIcon(getIcon());
this.setSmallIcon(getIconResource());
}
@Override
@ -816,7 +1036,7 @@ public class TableDataTreePane extends BasicTableDataTreePane {
public EditAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit"));
this.setMnemonic('E');
this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH));
this.setSmallIcon("/com/fr/design/standard/editdataset/edit");
}
@Override
@ -833,8 +1053,46 @@ public class TableDataTreePane extends BasicTableDataTreePane {
AbstractTableDataPane<?> tableDataPane = wrapper.creatTableDataPane();
//下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name
dgEdit(tableDataPane, dsName, false);
if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) {
// 先打开一个Loading面板
TableDataLoadingPane loadingPane = new TableDataLoadingPane();
BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.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);
dgEdit(tableDataPane, dsName, false);
} 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 {
// 无需检查权限时,直接打开数据库查询编辑面板
//下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name
dgEdit(tableDataPane, dsName, false);
}
}
}
@ -843,39 +1101,140 @@ public class TableDataTreePane extends BasicTableDataTreePane {
public RemoveAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove"));
this.setMnemonic('R');
this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH));
this.setSmallIcon("/com/fr/design/standard/remove/remove");
}
@Override
public void actionPerformed(ActionEvent e) {
NameObject selectedNO = tableDataTree.getSelectedNameObject();
if (selectedNO == null) {
NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects();
if (selectedNameObjects == null || selectedNameObjects.length == 0) {
FineLoggerFactory.getLogger().error("Table Data to remove is null or not selected");
return;
}
// 可以半选的CheckBoxList
CheckBoxListWithPartialSelect tableDataCheckBoxPane = new CheckBoxListWithPartialSelect(selectedNameObjects);
UIScrollPane scrollPane = new UIScrollPane(tableDataCheckBoxPane);
UILabel tips = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Select_Source_To_Remove"));
BasicPane basicPane = new BasicPane() {
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Remove");
}
};
basicPane.setLayout(new BorderLayout());
basicPane.add(tips, BorderLayout.NORTH);
basicPane.add(scrollPane, BorderLayout.CENTER);
BasicDialog basicDialog = basicPane.showSmallWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() {
@Override
public void doOk() {
List selectedValues = tableDataCheckBoxPane.getSelectedObjects();
// 删除时如果正在搜索,跳回原树
if (TableDataTreeSearchManager.getInstance().isInSearchMode()) {
TableDataTreeSearchManager.getInstance().outOfSearchMode();
}
for (Object toRemove : selectedValues) {
try {
doRemove((String) toRemove);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "remove table data failed for {}", toRemove);
}
}
}
int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + ":" + selectedNO.getName() + "?",
Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (returnVal == JOptionPane.OK_OPTION) {
// richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧
op.removeAction(selectedNO.getName());
tableDataTree.refresh();
// Richie:默认最后一行获得焦点.
tableDataTree.requestFocus();
tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1);
fireDSChanged();
checkButtonEnabled();
@Override
public void doCancel() {
super.doCancel();
}
});
basicDialog.setVisible(true);
}
//删掉缓存配置
StrategyConfigAttrUtils.removeStrategyConfig(selectedNO.getName());
private void doRemove(String toRemove) throws Exception {
// richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧
op.removeAction(toRemove);
tableDataTree.refresh();
// Richie:默认最后一行获得焦点.
tableDataTree.requestFocus();
tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1);
fireDSChanged();
checkButtonEnabled();
//删掉缓存配置
StrategyConfigAttrUtils.removeStrategyConfig(toRemove);
// 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样
// 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效
// 这里额外发出一次数据集修改事件
StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(toRemove)));
DesignTableDataManager.removeSelectedColumnNames(toRemove);
DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(toRemove);
FineLoggerFactory.getLogger().info("remove table data succeeded for {}", toRemove);
}
}
private class CopyAction extends UpdateAction {
public CopyAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Copy"));
this.setMnemonic('C');
this.setSmallIcon("/com/fr/design/standard/copy/copy");
}
@Override
public void actionPerformed(ActionEvent e) {
NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects();
Map<String, AbstractTableDataWrapper> dataWrapperMap = TableDataTreeClipboard.getInstance().transferNameObjectArray2Map(selectedNameObjects);
TableDataTreeClipboard.getInstance().addToClip(dataWrapperMap);
}
}
// 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样
// 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效
// 这里额外发出一次数据集修改事件
StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName())));
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName());
private class PasteAction extends UpdateAction {
public PasteAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Action_Paste_Name"));
this.setMnemonic('P');
this.setSmallIcon("/com/fr/design/images/m_edit/paste");
}
@Override
public void actionPerformed(ActionEvent e) {
// 粘贴时如果正在搜索,跳回原树
if (TableDataTreeSearchManager.getInstance().isInSearchMode()) {
TableDataTreeSearchManager.getInstance().outOfSearchMode();
}
Map<String, AbstractTableDataWrapper> dataWrapperMap = TableDataTreeClipboard.getInstance().takeFromClip();
for (Map.Entry<String, AbstractTableDataWrapper> dataWrapperEntry : dataWrapperMap.entrySet()) {
// 处理数据集名称
String dsName = getNoRepeatedDsName4Paste(dataWrapperEntry.getKey());
AbstractTableDataWrapper wrapper = dataWrapperEntry.getValue();
AbstractTableDataPane<?> tableDataPane = TableDataFollowingPasteUtils.generateTableDataPaneWhenPaste(wrapper);
if (tableDataPane != null) {
addDataPane(tableDataPane, dsName);
}
}
}
}
public String getNoRepeatedDsName4Paste(String oldName) {
while (isDsNameRepeaded(oldName)) {
oldName = oldName + Toolkit.i18nText("Fine-Design_Table_Data_Copy_Of_Table_Data");
}
return oldName;
}
private class SwitchAction extends UpdateAction {
public SwitchAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Search"));
this.setMnemonic('S');
this.setSmallIcon("/com/fr/design/standard/search", false);
}
@Override
public void actionPerformed(ActionEvent e) {
// 交换层级
toolbarPane.switchPane(TreeSearchToolbarPane.SEARCH_PANE);
TableDataTreeSearchManager.getInstance().switchToSearch(TableDataSearchMode.match(buttonGroup.getSelectedIndex()), DesignTableDataManager.getEditingTableDataSource());
}
}

57
designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java

@ -0,0 +1,57 @@
package com.fr.design.data.datapane.auth;
import com.fr.base.TableData;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.NameDatabaseConnection;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import java.util.Collection;
import java.util.Collections;
/**
* 数据连接权限相关的工具类
* @author Yvan
*/
public class TableDataAuthHelper {
/**
* 编辑数据集时是否需要检查权限
* @param tableData
* @return
*/
public static boolean needCheckAuthWhenEdit(TableData tableData) {
// 远程设计下,编辑DBTableData时需要判断权限
return !WorkContext.getCurrent().isLocal() && tableData instanceof DBTableData;
}
/**
* 获取无权限数据连接集合
* 远程下需要调用RPC为耗时操作谨慎使用
* @return
*/
public static Collection<String> getNoAuthConnections() {
// 获取无权限连接集合
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections();
return noAuthConnections == null ? Collections.emptyList() : noAuthConnections;
}
/**
* 通过数据集获取其数据连接的名称
*
* 注意
* 1. Connection接口本身是不提供名称的只有我们内部为了使用方便将其包装成了NameDataBaseConnection
* 如果不是NameDataBaseConnection类型则无名称因此这里只能用判断类型的方式获取名称
* 2. 仅支持DBTableData获取连接名
* @return
*/
public static String getConnectionNameByDBTableData(DBTableData tableData) {
Connection database = tableData.getDatabase();
if (database instanceof NameDatabaseConnection) {
return ((NameDatabaseConnection) database).getName();
}
return StringUtils.EMPTY;
}
}

145
designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java

@ -0,0 +1,145 @@
package com.fr.design.data.datapane.connect;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.pool.DBCPConnectionPoolAttr;
import com.fr.design.dialog.BasicPane;
import com.fr.design.editor.editor.IntegerEditor;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.stable.StringUtils;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
/**
* @author xiqiu
* @date 2021/11/22
* @description
*/
public class AdvancePane extends BasicPane {
private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor();
private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor();
private SpecialUITextField DBCP_VALIDATION_QUERY = new SpecialUITextField();
public AdvancePane() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
DBCP_VALIDATION_QUERY.addFocusListener(new JTextFieldHintListener(DBCP_VALIDATION_QUERY));
double p = TableLayout.PREFERRED;
DBCP_VALIDATION_QUERY.setColumns(20);
double[] rowSizeDbcp = {p, p, p, p};
double[] columnDbcp = {190, p};
Component[][] comps = {
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT}
};
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSizeDbcp, columnDbcp, 11, 11);
jPanel.add(contextPane, BorderLayout.CENTER);
this.add(jPanel);
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr();
if (dbcpAttr == null) {
dbcpAttr = new DBCPConnectionPoolAttr();
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive());
this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait());
this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery());
this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0);
}
public void update(JDBCDatabaseConnection jdbcDatabase) {
DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr();
if (dbcpAttr == null) {
dbcpAttr = new DBCPConnectionPoolAttr();
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue());
dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue());
dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText());
dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true);
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Advanced_Setup");
}
private class JTextFieldHintListener implements FocusListener {
private SpecialUITextField textField;
public JTextFieldHintListener(SpecialUITextField jTextField) {
this.textField = jTextField;
}
@Override
public void focusGained(FocusEvent e) {
//获取焦点时,清空提示内容
String temp = textField.getText();
textField.setForeground(Color.BLACK);
textField.setTextOrigin(temp);
}
@Override
public void focusLost(FocusEvent e) {
//失去焦点时,没有输入内容,显示提示内容
String temp = textField.getTextOrigin();
textField.setText(temp);
}
}
private class SpecialUITextField extends UITextField {
@Override
public String getText() {
String text = super.getText();
if (isUseless(text)) {
return StringUtils.EMPTY;
}
return text;
}
@Override
public void setText(String text) {
if (isUseless(text)) {
this.setForeground(Color.GRAY);
super.setText(Toolkit.i18nText("Fine-Design_Dbcp_Default_Query"));
} else {
this.setForeground(Color.BLACK);
super.setText(text);
}
}
public String getTextOrigin() {
return super.getText();
}
public void setTextOrigin(String text) {
super.setText(text);
}
private boolean isUseless(String text) {
return text == null || text.isEmpty() || Toolkit.i18nText("Fine-Design_Dbcp_Default_Query").equals(text);
}
}
}

44
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java

@ -10,11 +10,10 @@ import com.fr.design.editlock.EditLockUtils;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UILockButton;
import com.fr.file.ConnectionConfig;
import com.fr.general.ComparatorUtils;
import com.fr.report.LockItem;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import com.fr.report.LockItem;
import javax.swing.SwingUtilities;
import java.awt.Dimension;
@ -96,6 +95,7 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
continue;
}
Connection connection = mgr.getConnection(conName);
// nameList依赖items方法初始化,父类ItemEditableComboBoxPanel里异步执行item方法
filterConnection(connection, conName, nameList);
}
@ -138,20 +138,34 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
if (connection instanceof NameDatabaseConnection) {
this.setSelectedItem(((NameDatabaseConnection) connection).getName());
} else {
String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection();
if (StringUtils.isNotBlank(s)) {
for (int i = 0; i < this.getConnectionSize(); i++) {
String t = this.getConnection(i);
if (ComparatorUtils.equals(s, t)) {
this.setSelectedItem(s);
break;
}
}
}
// alex:如果这个ComboBox还是没有选中,那么选中第一个
if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) {
this.setSelectedItem(this.getConnection(0));
setRecentConnection();
}
}
/**
* 下拉框选项设置成最近选择的connection如果最近选择不存在则选择列表中的第一个
*/
protected void setRecentConnection() {
String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection();
if (StringUtils.isNotBlank(s)) {
// 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白
// 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置
if (nameList.contains(s)) {
this.setSelectedItem(s);
}
}
// alex:如果这个ComboBox还是没有选中,那么选中第一个
if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) {
this.setSelectedItem(this.getConnection(0));
}
}
/**
* 是否无选中状态空白item也视为无选中
* @return
*/
protected boolean isSelectedItemEmpty() {
String selectedItem = this.getSelectedItem();
return selectedItem == null || StringUtils.equals(selectedItem, EMPTY.toString());
}
}

12
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListDialogActionAdapter.java

@ -2,11 +2,15 @@ package com.fr.design.data.datapane.connect;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.editlock.EditLockUtils;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.file.ConnectionConfig;
import com.fr.report.LockItem;
import javax.swing.JOptionPane;
/**
* @author hades
* @version 11.0
@ -32,7 +36,13 @@ public class ConnectionListDialogActionAdapter extends DialogActionAdapter {
connectionListDialog.setDoOKSucceed(false);
return;
}
connectionManagerPane.update(connectionConfig);
try {
connectionManagerPane.update(connectionConfig);
} catch (Exception e) {
connectionListDialog.setDoOKSucceed(false);
FineJOptionPane.showMessageDialog(connectionManagerPane, e.getMessage(), Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.ERROR_MESSAGE);
return;
}
DesignerContext.getDesignerBean("databasename").refreshBeanElement();
// 关闭定义数据连接页面,为其解锁
EditLockUtils.unlock(LockItem.CONNECTION);

281
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -1,39 +1,53 @@
package com.fr.design.data.datapane.connect;
import com.fr.config.RemoteConfigEvent;
import com.fr.data.driver.DriverClassNotFoundException;
import com.fr.data.impl.Connection;
import com.fr.data.impl.ConnectionBean;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.metric.utils.DatabaseConnectionMetricHandler;
import com.fr.data.operator.DataOperator;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.data.MapCompareUtils;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.fun.ConnectionProvider;
import com.fr.design.gui.controlpane.JListControlPane;
import com.fr.design.gui.controlpane.NameObjectCreator;
import com.fr.design.gui.controlpane.NameableCreator;
import com.fr.design.gui.ilist.ListModelElement;
import com.fr.design.i18n.Toolkit;
import com.fr.event.EventDispatcher;
import com.fr.file.ConnectionConfig;
import com.fr.general.ComparatorUtils;
import com.fr.file.ConnectionOperator;
import com.fr.general.NameObject;
import com.fr.license.database.DBTypes;
import com.fr.license.database.DataBaseTypePointManager;
import com.fr.license.exception.DataBaseNotSupportedException;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable;
import com.fr.stable.StringUtils;
import com.fr.stable.core.PropertyChangeAdapter;
import com.fr.third.org.apache.commons.collections4.MapUtils;
import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerFacade;
import com.fr.workspace.WorkContext;
import com.fr.file.ConnectionOperator;
import com.fr.workspace.server.database.DataBaseTypeOperator;
import org.jetbrains.annotations.NotNull;
import javax.swing.SwingWorker;
import java.awt.Window;
import javax.swing.*;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
/**
* Connection List Pane.
@ -41,39 +55,57 @@ import java.util.Set;
public class ConnectionListPane extends JListControlPane implements ConnectionShowPane {
public static final String TITLE_NAME = Toolkit.i18nText("Fine-Design_Basic_Server_Define_Data_Connection");
private boolean isNamePermitted = true;
private HashMap<String, String> renameMap = new HashMap<String, String>();
private final HashMap<String, String> renameMap = new HashMap<>();
private final Map<String, Connection> populatedConnectionsSnapshot = new LinkedHashMap<>();
private static List<String> supportedDatabaseTypes = new ArrayList<>();
public ConnectionListPane() {
renameMap.clear();
this.addEditingListener(new PropertyChangeAdapter() {
public void propertyChange() {
isNamePermitted = true;
String[] allListNames = nameableList.getAllNames();
allListNames[nameableList.getSelectedIndex()] = StringUtils.EMPTY;
String tempName = getEditingName();
if (StringUtils.isEmpty(tempName)) {
nameableList.stopEditing();
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ConnectionListPane.this), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connection_Empty_Name"));
setIllegalIndex(editingIndex);
if (!checkName()) {
isNamePermitted = false;
return;
}
if (!ComparatorUtils.equals(tempName, selectedName)
&& isNameRepeated(new List[]{Arrays.asList(allListNames)}, tempName)) {
isNamePermitted = false;
nameableList.stopEditing();
String message = Toolkit.i18nText("Fine-Design_Basic_Connection_Duplicate_Name", tempName);
FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ConnectionListPane.this), message);
setIllegalIndex(editingIndex);
}
if (isNamePermitted && !ComparatorUtils.equals(tempName, selectedName)) {
rename(selectedName, tempName);
}
rename(selectedName, getEditingName());
}
});
getSupportedTypes();
}
/**
* 获取本地远程环境lic中未受限制的数据库类型信息
*/
private static void getSupportedTypes() {
SwingWorker<List<String>, Void> getSupportedTypesWorker = new SwingWorker<List<String>, Void>() {
@Override
protected List<String> doInBackground() {
return WorkContext.getCurrent().get(DataBaseTypeOperator.class).getSupportedDatabaseTypes();
}
@Override
protected void done() {
try {
supportedDatabaseTypes = get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
};
getSupportedTypesWorker.execute();
}
@Override
public String getEmptyNameTip() {
return Toolkit.i18nText("Fine-Design_Basic_Connection_Empty_Name");
}
@Override
public String getDuplicatedNameTip() {
return Toolkit.i18nText("Fine-Design_Basic_Connection_Duplicate_Name", getEditingName());
}
protected void rename(String oldName, String newName) {
//如果a改成了b,b又被改成了c,就认为是a改成了c
@ -115,21 +147,31 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
/**
* 创建菜单项
* <p>
* 方法中获取limitDatabaseType使用了远程rpc调用可能会比较耗时
*
* @return 菜单项
*/
public NameableCreator[] createNameableCreators() {
NameableCreator[] creators = new NameableCreator[]{new NameObjectCreator(
NameObjectCreator jdbc = new NameObjectCreator(
"JDBC",
"/com/fr/design/images/data/source/jdbcTableData.png",
JDBCDatabaseConnection.class,
DatabaseConnectionPane.JDBC.class
), new NameObjectCreator(
);
NameObjectCreator jndi = new NameObjectCreator(
"JNDI",
"/com/fr/design/images/data/source/jdbcTableData.png",
JNDIDatabaseConnection.class,
DatabaseConnectionPane.JNDI.class
)};
);
NameableCreator[] creators;
if (WorkContext.getCurrent().get(DataBaseTypeOperator.class).limitDatabaseType()) {
// 不支持JNDI,屏蔽接口
creators = new NameableCreator[]{jdbc};
} else {
creators = new NameableCreator[]{jdbc, jndi};
}
Set<ConnectionProvider> pluginCreators = ExtraDesignClassManager.getInstance().getArray(ConnectionProvider.XML_TAG);
for (ConnectionProvider provider : pluginCreators) {
NameObjectCreator creator = new NameObjectCreator(
@ -156,39 +198,177 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
*/
public void populate(ConnectionConfig connectionConfig) {
List<NameObject> nameObjectList = new ArrayList<NameObject>();
populatedConnectionsSnapshot.clear();
for (Map.Entry<String, Connection> entry : connectionConfig.getConnections().entrySet()) {
nameObjectList.add(new NameObject(entry.getKey(), entry.getValue()));
try {
populatedConnectionsSnapshot.put(entry.getKey(), (Connection) entry.getValue().clone());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
this.populate(nameObjectList.toArray(new NameObject[nameObjectList.size()]));
}
/**
* Update.
*/
public void update(ConnectionConfig connectionConfig) {
public void update(ConnectionConfig connectionConfig) throws Exception {
// Nameable[]居然不能强转成NameObject[],一定要这么写...
Nameable[] res = this.update();
List<ConnectionBean> connectionBeans = new ArrayList<>();
Map<String, String> map = MapUtils.invertMap(getRenameMap());
for (int i = 0; i < res.length; i++) {
NameObject nameObject = (NameObject) res[i];
String oldName = map.get(nameObject.getName());
if (oldName == null) {
oldName = StringUtils.EMPTY;
Map<String, Connection> updatedMap = new LinkedHashMap<>();
Arrays.stream(res).map(n -> (NameObject) n).forEach(no -> updatedMap.put(no.getName(), (Connection) no.getObject()));
List<String> removedConnNames = new ArrayList<>();
List<ConnectionBean> addedOrUpdatedConnections = new ArrayList<>();
MapCompareUtils.contrastMapEntries(populatedConnectionsSnapshot, updatedMap, (entryEventKind, s, connection) -> {
switch (entryEventKind) {
case REMOVED:
removedConnNames.add(s);
break;
case ADDED:
case UPDATED:
addedOrUpdatedConnections.add(new ConnectionBean(s, StringUtils.EMPTY, connection));
if (connection instanceof JDBCDatabaseConnection) {
DatabaseConnectionMetricHandler.handleSaveConnection((JDBCDatabaseConnection) connection, null);
}
default:
break;
}
}, new MapCompareUtils.UpdateRule<String, Connection>() {
@Override
public boolean needUpdate(Connection origin, Connection connection) {
return needUpdate0(origin, connection);
}
/**
* 是否需要更新处理
* 1. Connection本身equals为false代表字段修改
* 2. 非内置的Connection即插件提供的Connection
* todo 原本一个equals方法就可以搞定但是插件里面没有实现equals结果导致不能正确判断只能主代码里做兼容很恶心先记个todo以后看有没有办法改掉
* @param origin
* @param connection
* @return
*/
private boolean needUpdate0(Connection origin, Connection connection) {
return !connection.equals(origin) || !isEmbedConnection(connection);
}
/**
* 是否是主工程里内置的Connection
* @return
*/
private boolean isEmbedConnection(Connection connection) {
return connection instanceof JDBCDatabaseConnection || connection instanceof JNDIDatabaseConnection;
}
});
this.validateDatabaseType(addedOrUpdatedConnections);
this.validateConnections(addedOrUpdatedConnections);
this.alterConnections(removedConnNames, addedOrUpdatedConnections);
}
/**
* 校验是否支持所有新增和修改数据连接的数据库类型
*/
public void validateDatabaseType(@NotNull List<ConnectionBean> addedOrUpdatedConnections) {
Set<String> notSupportedConnections = new HashSet<>();
if (!addedOrUpdatedConnections.isEmpty()) {
for (ConnectionBean bean : addedOrUpdatedConnections) {
Connection connection = bean.getConnection();
// 仅校验jdbc连接,其他插件数据连接不进行校验
if (connection instanceof JDBCDatabaseConnection) {
DBTypes dataBaseTypePoint = DataBaseTypePointManager.getInstance().getDataBaseTypePoint(connection.getDriver(), connection.feature());
if (connectionIsNotSupported(connection, dataBaseTypePoint)) {
notSupportedConnections.addAll(dataBaseTypePoint.getDataBaseType());
}
}
}
}
if (!notSupportedConnections.isEmpty()) {
throw new DataBaseNotSupportedException(notSupportedConnections, supportedDatabaseTypes);
}
}
/**
* 校验当前数据连接是否被限制
*/
private static boolean connectionIsNotSupported(Connection connection, DBTypes dataBaseTypePoint) {
return !validateFRDemo(connection.getDriver(), connection.feature()) &&
(dataBaseTypePoint != null && !supportedDatabaseTypes.containsAll(dataBaseTypePoint.getDataBaseType()));
}
/**
* 校验当前是否为FRDemo不对其进行限制
*/
private static boolean validateFRDemo(String driver, String url) {
if (DBTypes.Sqlite.getDriver().equals(driver) && url.contains(DBTypes.Sqlite.getUrlKey())) {
// 产品:对sqlite类型只允许示例连接FRDemo
String databaseName = url.substring(url.lastIndexOf("/") + 1);
return StringUtils.equals("FRDemo.db", databaseName);
}
return false;
}
private void validateConnections(List<ConnectionBean> addedOrUpdatedConnections) throws Exception {
for (ConnectionBean connectionBean : addedOrUpdatedConnections) {
Connection connection = connectionBean.getConnection();
try {
DataOperator.getInstance().validateConnectionSettings(connection);
} catch (DriverClassNotFoundException e) {
FineLoggerFactory.getLogger().info(e.getMessage());
} catch (Exception e) {
throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", connectionBean.getName()) + ", " + e.getMessage(), e.getCause());
}
connectionBeans.add(new ConnectionBean(nameObject.getName(), oldName, (Connection) nameObject.getObject()));
}
}
private void alterConnections(List<String> removedConnNames, List<ConnectionBean> addedOrUpdatedConnections) {
try {
WorkContext.getCurrent().get(ConnectionOperator.class).saveConnection(connectionBeans);
WorkContext.getCurrent().get(ConnectionOperator.class, exceptionInfo -> saveByOldWay(removedConnNames, addedOrUpdatedConnections))
.saveConnection(removedConnNames, addedOrUpdatedConnections);
// hades:远程环境时,由于时直接RPC调用远程修改,因此设计器本地配置需要失效
if (!WorkContext.getCurrent().isLocal()) {
EventDispatcher.fire(RemoteConfigEvent.EDIT, ConnectionConfig.class.getSimpleName());
EventDispatcher.fire(RemoteConfigEvent.EDIT, ConnectionConfig.getInstance().getNameSpace());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean saveByOldWay(List<String> removedConnNames, List<ConnectionBean> addedOrUpdatedConnections) {
final int remaining = ConnectionConfig.getInstance().getRemainingCon(removedConnNames.size(), addedOrUpdatedConnections.size());
try {
return Configurations.modify(new WorkerFacade(ConnectionConfig.class) {
@Override
public void run() {
removedConnNames.forEach(n -> ConnectionConfig.getInstance().removeConnection(n));
int innerRemaining = remaining;
for (ConnectionBean cb : addedOrUpdatedConnections) {
if (innerRemaining > 0) {
ConnectionConfig.getInstance().addConnectionWithoutCheck(cb.getName(), cb.getConnection());
innerRemaining--;
} else {
break;
}
}
}
});
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
public static void showDialog(Window parent) {
final ConnectionConfig connectionConfig = ConnectionConfig.getInstance();
final ConnectionManagerPane connectionManagerPane = new ConnectionManagerPane() {
@ -197,14 +377,23 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
ConnectionConfig cloned = connectionConfig.mirror();
populate(cloned);
}
@Override
protected void renameConnection(String oldName, String newName) {
connectionConfig.renameConnection(oldName, newName);
}
};
final BasicDialog connectionListDialog = connectionManagerPane.showLargeWindow(parent, null);
connectionListDialog.addDialogActionListener(new ConnectionListDialogActionAdapter(connectionManagerPane, connectionListDialog, connectionConfig));
connectionListDialog.setVisible(true);
}
@Override
public void onCopyItem() {
super.onCopyItem();
ListModelElement selectedValue = getSelectedValue();
// identity 需要重置
if (selectedValue != null && selectedValue.wrapper != null) {
Object temp = ((NameObject) selectedValue.wrapper).getObject();
if (temp instanceof JDBCDatabaseConnection) {
JDBCDatabaseConnection object = (JDBCDatabaseConnection) temp;
object.setIdentity(UUID.randomUUID().toString());
}
}
}
}

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

@ -4,9 +4,8 @@ import com.fr.design.gui.frpane.LoadingBasicPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.ConnectionConfig;
import javax.swing.*;
import java.awt.*;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.HashMap;
public class ConnectionManagerPane extends LoadingBasicPane implements ConnectionShowPane {
@ -39,7 +38,7 @@ public class ConnectionManagerPane extends LoadingBasicPane implements Connectio
this.connectionListPane.populate(datasourceManager);
}
public void update(ConnectionConfig datasourceManager) {
public void update(ConnectionConfig datasourceManager) throws Exception {
this.connectionListPane.update(datasourceManager);
}

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

@ -7,7 +7,7 @@ import com.fr.file.ConnectionConfig;
* 数据链接显示面板
*/
public interface ConnectionShowPane {
void update(ConnectionConfig connectionConfig);
void update(ConnectionConfig connectionConfig) throws Exception;
void populate(ConnectionConfig connectionConfig);

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

@ -1,26 +1,32 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.BaseUtils;
import com.fr.base.svg.IconUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.AbstractDatabaseConnection;
import com.fr.data.impl.Connection;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.TableViewList;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.GeneralContext;
import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@ -45,7 +51,39 @@ public class ConnectionTableProcedurePane extends BasicPane {
private java.util.List<DoubleClickSelectedNodeOnTreeListener> listeners = new java.util.ArrayList<DoubleClickSelectedNodeOnTreeListener>();
public ConnectionTableProcedurePane() {
init(null);
}
/**
* 传入父容器
* @param parent
*/
public ConnectionTableProcedurePane(SwitchableTableDataPane parent) {
init(parent);
}
private void init(SwitchableTableDataPane parent) {
this.setLayout(new BorderLayout(4, 4));
// 初始化数据连接下拉框
initConnectionComboBox(parent);
// 初始化中间的面板
JPanel centerPane = initCenterPane();
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
}
private JPanel initCenterPane() {
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
// 搜索面板
centerPane.add(createSearchPane(), BorderLayout.NORTH);
// 数据库表视图面板
centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER);
return centerPane;
}
private void initConnectionComboBox(SwitchableTableDataPane parent) {
connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) {
@Override
@ -60,10 +98,34 @@ public class ConnectionTableProcedurePane extends BasicPane {
search(true);
}
}
@Override
protected void afterRefreshItems() {
// 刷新完成后,如果未选中(在nameList初始化完成之前可能会出现),则尝试再次设置
if (isSelectedItemEmpty()) {
setRecentConnection();
}
// 获取数据连接之后,让父容器切换面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
@Override
protected void refreshItemsError() {
// 获取数据连接出现错误时,也让父容器从Loading面板切换至内容面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
};
connectionComboBox.addComboBoxActionListener(filter);
}
private JPanel createTableViewBorderPane() {
tableViewList = new TableViewList();
ToolTipManager.sharedInstance().registerComponent(tableViewList);
connectionComboBox.addComboBoxActionListener(filter);
tableViewList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() >= 2) {
@ -80,23 +142,50 @@ public class ConnectionTableProcedurePane extends BasicPane {
}
}
});
JPanel filterPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER);
JPanel checkBoxgroupPane = createCheckBoxgroupPane();
if (checkBoxgroupPane != null) {
filterPane.add(createCheckBoxgroupPane(), BorderLayout.NORTH);
tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH);
}
return tableViewBorderPane;
}
/**
* 创建搜索Panel用于搜索表或视图
* @return
*/
private JPanel createSearchPane() {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel searchPane = new JPanel(new BorderLayout(10, 0));
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
searchPane.setBackground(Color.WHITE);
searchField = new UITextField();
searchPane.add(searchField, BorderLayout.CENTER);
searchField.setBorderPainted(false);
searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search"));
searchField.getDocument().addDocumentListener(searchListener);
filterPane.add(searchPane, BorderLayout.CENTER);
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(tableViewListPane, BorderLayout.CENTER);
this.add(filterPane, BorderLayout.SOUTH);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
searchField.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
super.mouseEntered(e);
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.CHECKBOX_HOVER_SELECTED));
}
@Override
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
}
});
// 搜索图标
UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search"));
searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
searchPane.add(searchField, BorderLayout.CENTER);
searchPane.add(searchLabel, BorderLayout.EAST);
panel.add(searchPane, BorderLayout.CENTER);
return panel;
}
protected void filter(Connection connection, String conName, List<String> nameList) {
@ -224,4 +313,4 @@ public class ConnectionTableProcedurePane extends BasicPane {
*/
public void actionPerformed(TableProcedure target);
}
}
}

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

@ -20,6 +20,7 @@ import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
@ -45,13 +46,8 @@ public class DBCPAttrPane extends BasicPane {
private static final int EMPTY_FETCHSIZE = -2;
// carl:DBCP的一些属性
private IntegerEditor DBCP_INITIAL_SIZE = new IntegerEditor();
private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor();
private IntegerEditor DBCP_MAX_IDLE = new IntegerEditor();
private IntegerEditor DBCP_MIN_IDLE = new IntegerEditor();
private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor();
private UITextField DBCP_VALIDATION_QUERY = new UITextField();
private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
private UIComboBox DBCP_TESTONRETURN = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
private UIComboBox DBCP_TESTWHILEIDLE = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
@ -75,25 +71,19 @@ public class DBCPAttrPane extends BasicPane {
defaultPane = this;
// JPanel northFlowPane
northFlowPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_ConnectionPool_Attr"));
northFlowPane.setPreferredSize(new Dimension(630, 320));
northFlowPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_ConnectionPool_Attr"));
northFlowPane.setPreferredSize(new Dimension(630, 330));
defaultPane.add(northFlowPane, BorderLayout.NORTH);
DBCP_VALIDATION_QUERY.setColumns(15);
// ContextPane
double f = TableLayout.FILL;
// double p = TableLayout.PREFERRED;
double[] rowSize = {f, f, f, f, f, f, f, f, f, f, f, f};
double[] rowSize = {f, f, f, f, f, f, f};
double[] columnSize = {f, f};
Component[][] comps = {
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Initial_Size") + ":", SwingConstants.RIGHT), DBCP_INITIAL_SIZE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Idle") + ":", SwingConstants.RIGHT), DBCP_MAX_IDLE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Min_Idle") + ":", SwingConstants.RIGHT), DBCP_MIN_IDLE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Return") + ":", SwingConstants.RIGHT), DBCP_TESTONRETURN},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_While_Idle") + ":", SwingConstants.RIGHT), DBCP_TESTWHILEIDLE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Evictionruns_millis") + ":", SwingConstants.RIGHT),
@ -102,8 +92,13 @@ public class DBCPAttrPane extends BasicPane {
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Mix_Evictable_Idle_Time_Millis") + ":", SwingConstants.RIGHT),
DBCP_MINEVICTABLEIDLETIMEMILLIS}};
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 4);
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 10);
northFlowPane.add(contextPane);
JPanel boxFlowInnerContainer = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 5, 5);
UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Dbcp_Warning"));
uiLabel.setForeground(Color.RED);
boxFlowInnerContainer.add(uiLabel);
northFlowPane.add(boxFlowInnerContainer);
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
@ -113,12 +108,7 @@ public class DBCPAttrPane extends BasicPane {
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
this.DBCP_INITIAL_SIZE.setValue(dbcpAttr.getInitialSize());
this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive());
this.DBCP_MAX_IDLE.setValue(dbcpAttr.getMaxIdle());
this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait());
this.DBCP_MIN_IDLE.setValue(dbcpAttr.getMinIdle());
this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery());
this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0);
this.DBCP_TESTONRETURN.setSelectedIndex(dbcpAttr.isTestOnReturn() ? 1 : 0);
this.DBCP_TESTWHILEIDLE.setSelectedIndex(dbcpAttr.isTestWhileIdle() ? 1 : 0);
this.DBCP_MINEVICTABLEIDLETIMEMILLIS.setValue(dbcpAttr.getMinEvictableIdleTimeMillis() / TIME_MULTIPLE);
@ -141,12 +131,7 @@ public class DBCPAttrPane extends BasicPane {
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
dbcpAttr.setInitialSize(this.DBCP_INITIAL_SIZE.getValue().intValue());
dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue());
dbcpAttr.setMaxIdle(this.DBCP_MAX_IDLE.getValue().intValue());
dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue());
dbcpAttr.setMinIdle(this.DBCP_MIN_IDLE.getValue().intValue());
dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText());
dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true);
dbcpAttr.setTestOnReturn(this.DBCP_TESTONRETURN.getSelectedIndex() == 0 ? false : true);
dbcpAttr.setTestWhileIdle(this.DBCP_TESTWHILEIDLE.getSelectedIndex() == 0 ? false : true);
dbcpAttr.setMinEvictableIdleTimeMillis(((Number) this.DBCP_MINEVICTABLEIDLETIMEMILLIS.getValue()).intValue() * TIME_MULTIPLE);

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

@ -3,10 +3,12 @@
*/
package com.fr.design.data.datapane.connect;
import com.fr.data.driver.util.JarFileParseUtil;
import com.fr.data.impl.Connection;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.operator.DataOperatorProvider;
import com.fr.data.security.ssl.impl.NormalSsl;
import com.fr.data.solution.ExceptionSolutionSelector;
import com.fr.data.solution.entity.DriverPage;
import com.fr.data.solution.processor.ClassNotFoundExceptionSolutionProcessor;
@ -14,11 +16,11 @@ import com.fr.data.solution.processor.SolutionProcessor;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.scrollruler.ModLineBorder;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
@ -31,9 +33,12 @@ import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
@ -53,6 +58,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.URI;
import java.util.concurrent.ExecutionException;
@ -60,6 +66,8 @@ import java.util.concurrent.ExecutionException;
* Database Connection pane.
*/
public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connection> extends BasicBeanPane<com.fr.data.impl.Connection> {
private static int MAX_MAIN_PANEL_HEIGHT = 410;
private static int MAX_MAIN_PANEL_WIDTH = 675;
private UILabel message;
private UIButton okButton;
@ -89,120 +97,7 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
public void actionPerformed(ActionEvent evt) {
// Try the java connection.
final SwingWorker<Void, Void> connectionThread = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
Connection database = DatabaseConnectionPane.this.updateBean();
// 返回连接结果
DriverPage.updateCache();
final Exception[] exception = new Exception[1];
WorkContext.getCurrent().get(DataOperatorProvider.class, new ExceptionHandler() {
@Override
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) {
// 正常调用发生的异常也会被捕获,因此需要对异常类型进行判断,如果是NoSuchMethodException 就要去调用 testConnection
// 如果不是 NoSuchMethodException 保存下异常上下文
// 两种情况下异常都需要抛出
if (exceptionInfo.getException() instanceof NoSuchMethodException) {
if (!WorkContext.getCurrent().get(DataOperatorProvider.class).testConnection(database)) {
exception[0] = new Exception(Toolkit.i18nText("Fine-Design_Description_Of_Test_Connection"));
}
} else {
exception[0] = exceptionInfo.getException();
}
return null;
}
}).testConnectionWithException(database);
if (exception[0] != null) {
throw exception[0];
}
return null;
}
@Override
protected void done() {
try {
get();
dialog.setSize(new Dimension(380, 125));
okButton.setEnabled(true);
uiLabel.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
message.setText(Toolkit.i18nText("Fine-Design_Basic_Datasource_Connection_Successfully"));
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (ExecutionException e) {
dialog.setSize(new Dimension(380, 142));
midPane.setVisible(true);
hiddenPanel.setVisible(false);
okButton.setEnabled(true);
uiLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
message.setText(Toolkit.i18nText("Fine-Design_Basic_Connection_Failed"));
Connection database = DatabaseConnectionPane.this.updateBean();
SolutionProcessor select = ExceptionSolutionSelector.get().select(e, database);
if (select instanceof ClassNotFoundExceptionSolutionProcessor) {
JPanel gridJpanel = new JPanel();
gridJpanel.setLayout(new GridLayout(5, 1, 0, 5));
UILabel driverTips = new UILabel();
driverTips.setText(Toolkit.i18nText("Fine_Designer_Not_Found_Driver"));
gridJpanel.add(driverTips);
UILabel deatail = new UILabel();
String content = Toolkit.i18nText("Fine_Designer_Not_Found") + " " + select.getResultException().getDetailMessage() + " " + Toolkit.i18nText("Fine_Designer_Driver");
deatail.setText(content);
deatail.setToolTipText(content);
gridJpanel.add(deatail);
String solution = select.getResultException().getSolution();
UILabel redirect = new UILabel();
if (solution != null) {
redirect.setText(Toolkit.i18nText("Fine_Designer_Download_Driver"));
redirect.setForeground(Color.BLUE);
redirect.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
Desktop.getDesktop().browse(new URI(solution));
} catch (Exception clickException) {
FineLoggerFactory.getLogger().warn("can not open browser with {}", solution);
}
}
@Override
public void mouseEntered(MouseEvent e) {
redirect.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
redirect.setCursor(Cursor.getDefaultCursor());
}
});
} else {
redirect.setText(Toolkit.i18nText("Fine_Designer_Not_Found_Driver_No_Solution"));
}
gridJpanel.add(redirect);
hiddenPanel.add(gridJpanel);
gridJpanel.setBackground(Color.WHITE);
} else {
JPanel borderPanel = new JPanel();
borderPanel.setLayout(new BorderLayout());
JTextArea jta = new JTextArea();
JScrollPane jsp = new JScrollPane(jta);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jta.append(select.getResultException().getDetailMessage() + "\n");
jta.append(select.getResultException().getSolution());
jta.setCaretPosition(0);
jta.setEditable(false);
jta.getCaret().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
jta.getCaret().setVisible(true);
}
});
borderPanel.add(jsp, BorderLayout.CENTER);
hiddenPanel.add(borderPanel);
}
okButton.setEnabled(true);
}
}
};
final SwingWorker<Void, Void> connectionThread = new TestConnectionWorker();
midPane.setVisible(false);
hiddenPanel.setVisible(false);
initDialogPane();
@ -305,6 +200,19 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
protected abstract E updateSubDatabaseConnectionBean();
protected JPanel getAdvancePane() {
throw new UnsupportedOperationException();
}
protected SslPane getSslPane() {
throw new UnsupportedOperationException();
}
protected SshPane getSshPane() {
throw new UnsupportedOperationException();
}
protected void initComponents() {
message = new UILabel();
uiLabel = new UILabel();
@ -318,7 +226,8 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel northPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
this.add(northPane, BorderLayout.NORTH);
UIScrollPane uiScrollPane = new UIScrollPane(northPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.add(uiScrollPane, BorderLayout.CENTER);
// 按钮.
JPanel testPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane();
@ -330,15 +239,12 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
// Center
mainPanel = mainPanel();
northPane.add(mainPanel, BorderLayout.CENTER);
JPanel advancedPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
advancedPanel.setBorder(BorderFactory.createTitledBorder(
new ModLineBorder(ModLineBorder.TOP),
Toolkit.i18nText("Fine-Design_Basic_Advanced")
));
JPanel advancedPanel = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Advanced"));
if (mainPanel instanceof JDBCDefPane) {
ActionLabel actionLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Basic_Advanced_Setup"));
northPane.add(mainPanel, BorderLayout.CENTER);
ActionLabel actionLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Advanced_More_Settings"));
actionLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
JDialog wDialog = createJDialog();
if (wDialog != null) {
@ -349,10 +255,25 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
JPanel actionLabelPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionLabelPanel.setBorder(BorderFactory.createEmptyBorder(2, 4, 4, 20));
actionLabelPanel.add(actionLabel, BorderLayout.WEST);
JPanel advancePane = getAdvancePane();
if (advancePane != null) {
advancedPanel.add(advancePane);
}
advancedPanel.add(actionLabelPanel);
northPane.add(getSshPane());
northPane.add(getSslPane());
} else {
//非jdbc配置布局保持不变
advancedPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, 60));
if (mainPanel.getPreferredSize().height > MAX_MAIN_PANEL_HEIGHT || mainPanel.getPreferredSize().width > MAX_MAIN_PANEL_WIDTH) {
UIScrollPane jp = new
UIScrollPane(mainPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jp.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT));
northPane.add(jp, BorderLayout.CENTER);
} else {
mainPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT));
northPane.add(mainPanel, BorderLayout.CENTER);
}
// ChartSet
String[] defaultEncode = new String[]{Toolkit.i18nText("Fine-Design_Encode_Auto")};
charSetComboBox = new UIComboBox(ArrayUtils.addAll(defaultEncode, EncodeConstants.ENCODING_ARRAY));
@ -406,6 +327,13 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
public static class JDBC extends DatabaseConnectionPane<JDBCDatabaseConnection> {
private static JDBCDefPane jdbcDefPane = new JDBCDefPane();
private static DBCPAttrPane dbcpAttrPane = new DBCPAttrPane();
private static AdvancePane advancePane = new AdvancePane();
private static SslPane sslPane = new SslPane();
private static SshPane sshPane = new SshPane();
static {
jdbcDefPane.addLinkPane(sslPane);
}
@Override
protected JPanel mainPanel() {
@ -425,15 +353,40 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
protected void populateSubDatabaseConnectionBean(JDBCDatabaseConnection ob) {
jdbcDefPane.populate(ob);
dbcpAttrPane.populate(jdbcDefPane.getJDBCDatabase());
advancePane.populate(jdbcDefPane.getJDBCDatabase());
sshPane.populate(jdbcDefPane.getJDBCDatabase());
sslPane.populate(jdbcDefPane.getJDBCDatabase());
}
@Override
protected JDBCDatabaseConnection updateSubDatabaseConnectionBean() {
JDBCDatabaseConnection jdbcDatabaseConnection = jdbcDefPane.update();
dbcpAttrPane.update(jdbcDatabaseConnection);
advancePane.update(jdbcDatabaseConnection);
sshPane.update(jdbcDatabaseConnection);
if (sslPane.isVisible()) {
sslPane.update(jdbcDatabaseConnection);
} else {
jdbcDatabaseConnection.setSsl(new NormalSsl());
}
return jdbcDatabaseConnection;
}
@Override
protected JPanel getAdvancePane() {
return advancePane;
}
@Override
protected SslPane getSslPane() {
return sslPane;
}
@Override
protected SshPane getSshPane() {
return sshPane;
}
@Override
protected String title4PopupWindow() {
return "JDBC";
@ -468,4 +421,191 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
return "JNDI";
}
}
private class TestConnectionWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
Connection database = DatabaseConnectionPane.this.updateBean();
// 返回连接结果
DriverPage.updateCache();
final Exception[] exception = new Exception[1];
WorkContext.getCurrent().get(DataOperatorProvider.class, new ExceptionHandler() {
@Override
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) {
// 正常调用发生的异常也会被捕获,因此需要对异常类型进行判断,如果是NoSuchMethodException 就要去调用 testConnection
// 如果不是 NoSuchMethodException 保存下异常上下文
// 两种情况下异常都需要抛出
if (exceptionInfo.getException() instanceof NoSuchMethodException) {
if (!WorkContext.getCurrent().get(DataOperatorProvider.class).testConnection(database)) {
exception[0] = new Exception(Toolkit.i18nText("Fine-Design_Description_Of_Test_Connection"));
}
} else {
exception[0] = exceptionInfo.getException();
}
return null;
}
}).testConnectionWithException(database);
if (exception[0] != null) {
throw exception[0];
}
return null;
}
@Override
protected void done() {
try {
get();
dialog.setSize(new Dimension(380, 125));
okButton.setEnabled(true);
uiLabel.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
message.setText(Toolkit.i18nText("Fine-Design_Basic_Datasource_Connection_Successfully"));
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (ExecutionException e) {
dealWithException(e);
}
}
private void dealWithException(ExecutionException e) {
dialog.setSize(new Dimension(380, 142));
midPane.setVisible(true);
hiddenPanel.setVisible(false);
okButton.setEnabled(true);
uiLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
message.setText(Toolkit.i18nText("Fine-Design_Basic_Connection_Failed"));
Connection database = DatabaseConnectionPane.this.updateBean();
SolutionProcessor select = ExceptionSolutionSelector.get().select(e, database);
String detail = select.getResultException().getDetailMessage();
String solution = select.getResultException().getSolution();
if (select instanceof ClassNotFoundExceptionSolutionProcessor) {
showClassNotFoundUI(select.getResultException().getDetailMessage(), select.getResultException().getSolution());
} else {
showExceptionMessageUI(detail, solution);
}
okButton.setEnabled(true);
}
private void showClassNotFoundUI(String detailMessage, String solution) {
JPanel gridJpanel = new JPanel();
gridJpanel.setLayout(new GridLayout(5, 1, 0, 5));
UILabel driverTips = new UILabel();
driverTips.setText(Toolkit.i18nText("Fine_Designer_Not_Found_Driver"));
gridJpanel.add(driverTips);
UILabel deatail = new UILabel();
String content = Toolkit.i18nText("Fine_Designer_Not_Found") + " " + detailMessage+ " " + Toolkit.i18nText("Fine_Designer_Driver");
deatail.setText(content);
deatail.setToolTipText(content);
gridJpanel.add(deatail);
UILabel redirect = new UILabel();
if (solution != null) {
redirect.setText(Toolkit.i18nText("Fine_Designer_Download_Driver"));
redirect.setForeground(Color.BLUE);
redirect.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
Desktop.getDesktop().browse(new URI(solution));
} catch (Exception clickException) {
FineLoggerFactory.getLogger().warn("can not open browser with {}", solution);
}
}
@Override
public void mouseEntered(MouseEvent e) {
redirect.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
redirect.setCursor(Cursor.getDefaultCursor());
}
});
} else {
redirect.setText(Toolkit.i18nText("Fine_Designer_Not_Found_Driver_No_Solution"));
}
gridJpanel.add(redirect);
hiddenPanel.add(gridJpanel);
gridJpanel.setBackground(Color.WHITE);
}
private void showExceptionMessageUI(String detail, String solution) {
JPanel borderPanel = new JPanel();
borderPanel.setLayout(new BorderLayout());
JTextArea jta = new JTextArea();
JScrollPane jsp = new JScrollPane(jta);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
Connection con = DatabaseConnectionPane.this.updateBean();
if(con instanceof JDBCDatabaseConnection && WorkContext.getCurrent().isLocal()) {
String driverPath = JarFileParseUtil.getDriverClassPath((JDBCDatabaseConnection) con);
jta.append(Toolkit.i18nText("Fine_Designer_Current_Driver_Path") + ":" + driverPath + "\n");
JPanel testDriverPanel = generateTestDriverPanel((JDBCDatabaseConnection) con, driverPath);
borderPanel.add(testDriverPanel, BorderLayout.NORTH);
}
jta.append(detail + "\n");
jta.append(solution);
jta.setCaretPosition(0);
jta.setEditable(false);
jta.getCaret().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
jta.getCaret().setVisible(true);
}
});
borderPanel.add(jsp, BorderLayout.CENTER);
hiddenPanel.add(borderPanel);
}
private JPanel generateTestDriverPanel(JDBCDatabaseConnection con, String driverPath) {
JPanel xBorderPanel = new JPanel();
xBorderPanel.setLayout(new BorderLayout());
UILabel driverTestTip = new UILabel();
JLabel testResult = new JLabel();
driverTestTip.setForeground(Color.BLUE);
driverTestTip.setVisible(true);
testResult.setVisible(false);
testResult.setHorizontalAlignment(SwingConstants.CENTER);
driverTestTip.setText(Toolkit.i18nText("Fine_Designer_Driver_Path_Test"));
xBorderPanel.add(driverTestTip, BorderLayout.WEST);
xBorderPanel.add(testResult, BorderLayout.CENTER);
driverTestTip.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
driverTestTip.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
@Override
public void mouseExited(MouseEvent e) {
driverTestTip.setCursor(Cursor.getDefaultCursor());
}
@Override
public void mouseClicked(MouseEvent e) {
try {
String path;
if(driverPath.endsWith(JarFileParseUtil.JAR_MARKER)) {
path = new File(driverPath).getParent();
} else {
path = driverPath;
}
if(JarFileParseUtil.hasDuplicateDriver(con.getDriver(), path)) {
testResult.setForeground(Color.RED);
testResult.setText(Toolkit.i18nText("Fine_Designer_Driver_Conflict"));
} else {
testResult.setForeground(Color.BLACK);
testResult.setText(Toolkit.i18nText("Fine_Designer_Driver_No_Conflict"));
}
testResult.setVisible(true);
} catch (Exception clickException) {
FineLoggerFactory.getLogger().warn(clickException, "can not test driver conflict");
}
}
});
return xBorderPanel;
}
}
}

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

@ -127,10 +127,12 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1);
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1);
}
afterRefreshItems();
} catch (Exception e) {
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
refreshItemsError();
}
}
@ -160,6 +162,20 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
*/
protected abstract java.util.Iterator<String> items();
/**
* 刷新ComboBox.items之后
*/
protected void afterRefreshItems() {
// 空实现,供子类重写
}
/**
* 刷新ComboBox.items时出现异常
*/
protected void refreshItemsError() {
// 空实现,供子类重写
}
/*
* 弹出对话框编辑Items
*/

280
designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java

@ -1,10 +1,15 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.GraphHelper;
import com.fr.data.driver.DriverLoader;
import com.fr.data.driver.config.DriverLoaderConfig;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.solution.entity.DriverClasses;
import com.fr.design.border.UITitledBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIComboBoxUI;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ipasswordfield.UIPasswordFieldWithFixedLength;
@ -21,13 +26,18 @@ import com.fr.general.ComparatorUtils;
import com.fr.stable.ArrayUtils;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StringUtils;
import com.fr.third.guava.collect.HashBiMap;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
@ -45,6 +55,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -59,6 +70,7 @@ public class JDBCDefPane extends JPanel {
// 编码转换.
private String originalCharSet = null;
private static Map<String, DriverURLName[]> jdbcMap = new HashMap<String, DriverURLName[]>();
private JPanel linkPanel;
static {
jdbcMap.put(OTHER_DB, new DriverURLName[]{new DriverURLName("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:"),
@ -101,8 +113,55 @@ public class JDBCDefPane extends JPanel {
private JDBCDatabaseConnection jdbcDatabase;
private boolean needRefresh = true;
private UIComboBox driverManageBox;
private ActionLabel driverManageLabel;
private UIComboBox driverLoaderBox;
ActionListener driverManageListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean selectSelfDefine = isSelfDefine();
driverManageLabel.setVisible(selectSelfDefine);
driverLoaderBox.setVisible(selectSelfDefine);
driverComboBox.setVisible(!selectSelfDefine);
odbcTipsLink.setVisible(driverComboBox.isVisible() && ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem()));
}
};
ActionListener dbtypeActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
urlTextField.setText(StringUtils.EMPTY);
driverComboBox.removeAllItems();
driverManageBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Default"));
if (driverLoaderBox.getItemCount() > 0) {
driverLoaderBox.setSelectedIndex(0);
}
if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), StringUtils.EMPTY)) {
driverComboBox.setSelectedItem(StringUtils.EMPTY);
return;
}
DriverURLName[] dus = jdbcMap.get(dbtypeComboBox.getSelectedItem());
for (int i = 0, len = dus.length; i < len; i++) {
driverComboBox.addItem(dus[i].getDriver());
if (i == 0) {
driverComboBox.setSelectedItem(dus[i].getDriver());
urlTextField.setText(dus[i].getURL());
}
}
// 更改数据库类型后 数据库名称置空和之前逻辑保持一致
if (needRefresh) {
jdbcDatabase.setDatabase(StringUtils.EMPTY);
}
changePane(dbtypeComboBox.getSelectedItem());
JDBCConnectionDef.getInstance().setConnection((String) dbtypeComboBox.getSelectedItem(), jdbcDatabase);
DatabaseConnectionPane.JDBC.getAdvancedAttrPane().populate(jdbcDatabase);
}
};
private HashBiMap<String, String> nameAndRepresent;
public JDBCDefPane() {
initMap();
this.setBorder(UITitledBorder.createBorderWithTitle("JDBC" + ":"));
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout());
JPanel innerthis = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
@ -115,7 +174,15 @@ public class JDBCDefPane extends JPanel {
}
dbtypeComboBox.addActionListener(dbtypeActionListener);
dbtypeComboBox.setMaximumRowCount(10);
driverLoaderBox = new SpecialUIComboBox();
refreshDriverLoader();
driverLoaderBox.setPreferredSize(new Dimension(200, driverLoaderBox.getPreferredSize().height));
driverLoaderBox.setEditable(false);
driverManageBox = new UIComboBox();
refreshDriverManage(true);
driverManageBox.setEditable(false);
driverManageBox.addActionListener(driverManageListener);
driverLoaderBox.setVisible(isSelfDefine());
driverComboBox = new UIComboBox();
driverComboBox.setEditable(true);
driverComboBox.addActionListener(driverListener);
@ -130,7 +197,9 @@ public class JDBCDefPane extends JPanel {
userNameTextField = new UITextField(15);
userNameTextField.setName(USER_NAME);
passwordTextField = new UIPasswordFieldWithFixedLength(15);
dbtypeButton = new UIButton(".");
dbtypeButton = new UIButton();
dbtypeButton.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
dbtypeButton.setPreferredSize(new Dimension(20, 20));
dbtypeButton.setToolTipText(Toolkit.i18nText("Fine-Design_Basic_Click_Get_Default_URL"));
dbtypeButton.addActionListener(dbtypeButtonActionListener);
@ -163,9 +232,33 @@ public class JDBCDefPane extends JPanel {
BrowseUtils.browser(url);
}
});
driverManageLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Driver_Manage_Add_Driver")) {
@Override
public void paintComponent(Graphics _gfx) {
super.paintComponent(_gfx);
_gfx.setColor(Color.blue);
_gfx.drawLine(0, this.getHeight() - 1, GraphHelper.getWidth(this.getText()), this.getHeight() - 1);
}
};
driverManageLabel.setPreferredSize(new Dimension(GraphHelper.getWidth(Toolkit.i18nText("Fine-Design_Driver_Manage_Add_Driver")), driverManageLabel.getPreferredSize().height));
driverManageLabel.setVisible(isSelfDefine());
driverManageLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
String url = CloudCenter.getInstance().acquireUrlByKind("driver.add.help");
BrowseUtils.browser(url);
}
});
odbcTipsPane.add(driverManageLabel);
odbcTipsPane.add(odbcTipsLink);
JPanel driverComboBoxAndTips = new JPanel(new BorderLayout());
driverComboBoxAndTips.add(driverComboBox, BorderLayout.WEST);
JPanel normalFlowInnerContainer_s_pane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 5, 0);
normalFlowInnerContainer_s_pane.add(driverManageBox);
normalFlowInnerContainer_s_pane.add(driverComboBox);
normalFlowInnerContainer_s_pane.add(driverLoaderBox);
driverComboBoxAndTips.add(normalFlowInnerContainer_s_pane, BorderLayout.WEST);
driverComboBoxAndTips.add(odbcTipsPane, BorderLayout.CENTER);
JPanel hostPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
@ -225,7 +318,71 @@ public class JDBCDefPane extends JPanel {
innerthis.add(centerPanel);
}
private void refreshDriverLoader() {
Set<String> representSet = nameAndRepresent.values();
driverLoaderBox.clearBoxItems();
for (String represent : representSet) {
driverLoaderBox.addItem(represent);
}
}
private String getRepresent(String driverClass, String driverName) {
return driverClass + "(" + driverName + ")";
}
private boolean isSelfDefine() {
return ComparatorUtils.equals(Toolkit.i18nText("Fine-Design_Driver_Manage_Self_Define"), driverManageBox.getSelectedItem());
}
private void refreshDriverManage(boolean addSelfDefine) {
driverManageBox.clearBoxItems();
driverManageBox.addItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Default"));
if (addSelfDefine) {
driverManageBox.addItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Self_Define"));
}
}
private void initMap() {
Map<String, DriverLoader> driverLoaders = DriverLoaderConfig.getInstance().getDriverLoaders();
nameAndRepresent = getDriverLoaderAndRepresent(driverLoaders);
}
private HashBiMap<String, String> getDriverLoaderAndRepresent(Map<String, DriverLoader> driverLoaders) {
HashBiMap<String, String> driverHashBiMap = HashBiMap.create();
if (WorkContext.getCurrent().isWarDeploy()) {
return driverHashBiMap;
}
// name 是唯一的,name+driver自然也是唯一的
for (DriverLoader driverLoader : driverLoaders.values()) {
driverHashBiMap.put(driverLoader.getName(), getRepresent(driverLoader.getDriverClass(), driverLoader.getName()));
}
return driverHashBiMap;
}
protected JDBCDatabaseConnection getJDBCDatabase() {
return this.jdbcDatabase;
}
private void changePane(Object dbType) {
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] columnSize = {p, f, 22};
if (ComparatorUtils.equals(dbType, OTHER_DB) || ComparatorUtils.equals(dbType, "Access") || ComparatorUtils.equals(dbType, "SQLite")) {
if (this.centerPanel.getComponentCount() != partComponents.length * 2) {
centerPanel.removeAll();
TableLayoutHelper.addComponent2ResultPane(partComponents, new double[]{p, p, p, p, p}, columnSize, centerPanel);
}
} else if (this.centerPanel.getComponentCount() != allComponents.length * 2) {
centerPanel.removeAll();
TableLayoutHelper.addComponent2ResultPane(allComponents, new double[]{p, p, p, p, p, p, p, p}, columnSize, centerPanel);
}
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
// 单例对象,重新打开的时候并不会新建,但是由于driverloaderbox里面需要是动态内容,因此需要进行刷新动作
initMap();
refreshDriverLoader();
needRefresh = false;
if (jdbcDatabase == null) {
jdbcDatabase = new JDBCDatabaseConnection();
@ -255,7 +412,24 @@ public class JDBCDefPane extends JPanel {
this.dbtypeComboBox.setSelectedItem(OTHER_DB);
}
}
this.driverComboBox.setSelectedItem(jdbcDatabase.getDriver());
// jdbcDatabase.getDriverSource() 只会是空或者是有值,但是为了保险起见,还是应该做个处理
String driverSource = jdbcDatabase.getDriverSource();
if (driverSource == null) {
driverSource = StringUtils.EMPTY;
}
if (driverSource.isEmpty()) {
refreshDriverManage(!nameAndRepresent.isEmpty());
this.driverManageBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Default"));
this.driverComboBox.setSelectedItem(jdbcDatabase.getDriver());
} else {
refreshDriverManage(true);
this.driverManageBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Driver_Manage_Self_Define"));
String represent = getRepresent(jdbcDatabase.getDriver(), jdbcDatabase.getDriverSource());
if (!nameAndRepresent.containsValue(represent)) {
this.driverLoaderBox.addItem(represent);
}
this.driverLoaderBox.setSelectedItem(represent);
}
this.urlTextField.setText(jdbcDatabase.getURL());
this.userNameTextField.setText(jdbcDatabase.getUser());
this.passwordTextField.setText(jdbcDatabase.getPassword());
@ -268,31 +442,10 @@ public class JDBCDefPane extends JPanel {
needRefresh = false;
}
protected JDBCDatabaseConnection getJDBCDatabase() {
return this.jdbcDatabase;
}
private void changePane(Object dbType) {
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] columnSize = {p, f, 22};
if (ComparatorUtils.equals(dbType, OTHER_DB) || ComparatorUtils.equals(dbType, "Access") || ComparatorUtils.equals(dbType, "SQLite")) {
if (this.centerPanel.getComponentCount() != partComponents.length * 2) {
centerPanel.removeAll();
TableLayoutHelper.addComponent2ResultPane(partComponents, new double[]{p, p, p, p, p}, columnSize, centerPanel);
}
} else if (this.centerPanel.getComponentCount() != allComponents.length * 2) {
centerPanel.removeAll();
TableLayoutHelper.addComponent2ResultPane(allComponents, new double[]{p, p, p, p, p, p, p, p}, columnSize, centerPanel);
}
}
public JDBCDatabaseConnection update() {
if (jdbcDatabase == null) {
jdbcDatabase = new JDBCDatabaseConnection();
}
Object driveItem = this.driverComboBox.getSelectedItem();
jdbcDatabase.setDriver(driveItem == null ? null : driveItem.toString().trim());
jdbcDatabase.setURL(this.urlTextField.getText().trim());
jdbcDatabase.setUser(this.userNameTextField.getText().trim());
jdbcDatabase.setPassword(new String(this.passwordTextField.getPassword()).trim());
@ -304,43 +457,42 @@ public class JDBCDefPane extends JPanel {
jdbcDatabase.setNewCharsetName(EncodeConstants.ENCODING_GBK);
jdbcDatabase.setOriginalCharsetName(((String) this.charSetComboBox.getSelectedItem()));
}
return jdbcDatabase;
}
ActionListener dbtypeActionListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
urlTextField.setText(StringUtils.EMPTY);
driverComboBox.removeAllItems();
if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), StringUtils.EMPTY)) {
driverComboBox.setSelectedItem(StringUtils.EMPTY);
return;
}
DriverURLName[] dus = jdbcMap.get(dbtypeComboBox.getSelectedItem());
for (int i = 0, len = dus.length; i < len; i++) {
driverComboBox.addItem(dus[i].getDriver());
if (i == 0) {
driverComboBox.setSelectedItem(dus[i].getDriver());
urlTextField.setText(dus[i].getURL());
String driverLoader = (String) this.driverLoaderBox.getSelectedItem();
if (driverLoader == null) {
driverLoader = StringUtils.EMPTY;
}
if (isSelfDefine()) {
String[] split = driverLoader.split("\\(");
if (split.length > 1) {
String name = split[1];
if (name.length() > 0) {
jdbcDatabase.setDriverSource(name.substring(0, name.length() - 1));
} else {
jdbcDatabase.setDriverSource(StringUtils.EMPTY);
}
} else {
jdbcDatabase.setDriverSource(StringUtils.EMPTY);
}
// 更改数据库类型后 数据库名称置空和之前逻辑保持一致
if (needRefresh) {
jdbcDatabase.setDatabase(StringUtils.EMPTY);
}
changePane(dbtypeComboBox.getSelectedItem());
JDBCConnectionDef.getInstance().setConnection((String) dbtypeComboBox.getSelectedItem(), jdbcDatabase);
DatabaseConnectionPane.JDBC.getAdvancedAttrPane().populate(jdbcDatabase);
jdbcDatabase.setDriver(split[0]);
} else {
Object driveItem = this.driverComboBox.getSelectedItem();
jdbcDatabase.setDriver(driveItem == null ? null : driveItem.toString().trim());
jdbcDatabase.setDriverSource(StringUtils.EMPTY);
}
};
return jdbcDatabase;
}
ActionListener driverListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
linkPanel.setVisible(DriverClasses.MYSQL.toString().equalsIgnoreCase((String) dbtypeComboBox.getSelectedItem())
&& driverComboBox.getSelectedItem() != null
&& ComparatorUtils.equals(DriverClasses.MYSQL.getDriverClass(), driverComboBox.getSelectedItem().toString().trim()));
odbcTipsLink.setVisible(driverComboBox.getSelectedItem() != null
&& ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem().toString().trim())); // 选择的如果是ODBC就显示提示
if (driverComboBox.getSelectedItem() == null || ComparatorUtils.equals(driverComboBox.getSelectedItem(), StringUtils.EMPTY)) {
return;
}
odbcTipsLink.setVisible(ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem())); // 选择的如果是ODBC就显示提示
Iterator<Entry<String, DriverURLName[]>> jdbc = jdbcMap.entrySet().iterator();
while (jdbc.hasNext()) {
Entry<String, DriverURLName[]> entry = jdbc.next();
@ -353,7 +505,6 @@ public class JDBCDefPane extends JPanel {
}
}
}
};
ActionListener dbtypeButtonActionListener = new ActionListener() {
@ -579,4 +730,25 @@ public class JDBCDefPane extends JPanel {
private String driver;
private String url;
}
private static class SpecialUIComboBox extends UIComboBox {
@Override
public ComboBoxUI getUIComboBoxUI() {
return new SpecialUIComboBoxUI();
}
}
private static class SpecialUIComboBoxUI extends UIComboBoxUI {
@Override
public ComboPopup createPopup() {
return createHorizontalNeverUIComboPopUp();
}
}
public void addLinkPane(JPanel panel) {
linkPanel = panel;
}
}

301
designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java

@ -0,0 +1,301 @@
package com.fr.design.data.datapane.connect;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.security.ssh.BaseSsh;
import com.fr.data.security.ssh.Ssh;
import com.fr.data.security.ssh.SshException;
import com.fr.data.security.ssh.SshType;
import com.fr.data.security.ssh.impl.KeyVerifySsh;
import com.fr.data.security.ssh.impl.NormalSsh;
import com.fr.data.security.ssl.SslUtils;
import com.fr.design.border.UITitledBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.editor.editor.NotNegativeIntegerEditor;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ipasswordfield.UIPasswordFieldWithFixedLength;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.stable.StringUtils;
import com.fr.third.guava.collect.HashBiMap;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
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.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.fr.design.i18n.Toolkit.i18nText;
/**
* @author xiqiu
* @date 2021/12/23
* @description
*/
public class SshPane extends BasicPane {
private static HashBiMap<String, SshType> typeMap;
static {
typeMap = HashBiMap.create();
typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Password"), SshType.NORMAL);
typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Ssh_Public_Key"), SshType.KEY);
}
private UICheckBox usingSsh = new UICheckBox(i18nText("Fine-Design_Basic_Ssh_Using"));
private NotNegativeIntegerEditor port = new NotNegativeIntegerEditor(20);
private UITextField ip = new UITextField(20);
private UIComboBox type = new UIComboBox();
private UITextField user = new UITextField(20);
private JPasswordField password = new UIPasswordFieldWithFixedLength(20);
private JPasswordField secret = new UIPasswordFieldWithFixedLength(20);
private KeyFileUITextField keyPath = new KeyFileUITextField(18);
private JPanel contextPane;
private Component[][] passwordComps;
private Component[][] keyComps;
private double p = TableLayout.PREFERRED;
private double f = TableLayout.FILL;
private JPanel jPanel;
private UIButton fileChooserButton = new UIButton();
private double[] columnSize = new double[]{195, p};
public SshPane() {
fileChooserButton.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings")));
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout());
typeMap.keySet().forEach(key -> type.addItem(key));
type.setSelectedItem(typeMap.inverse().get(SshType.KEY));
jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
fileChooserButton.setPreferredSize(new Dimension(20, 20));
type.setEditable(false);
type.setSelectedItem(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key"));
JPanel filePanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPath, fileChooserButton}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compIp = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Host") + ":", SwingConstants.RIGHT), ip};
Component[] compPort = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Port") + ":", SwingConstants.RIGHT), port};
Component[] compUserName = {new UILabel(Toolkit.i18nText("Fine-Design_Report_UserName") + ":", SwingConstants.RIGHT), user};
Component[] compMethod = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Verify_Method") + ":", SwingConstants.RIGHT), type};
Component[] compPassword = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Password") + ":", SwingConstants.RIGHT), password};
Component[] compKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key") + ":", SwingConstants.RIGHT), filePanel};
Component[] comSecret = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Secret") + ":", SwingConstants.RIGHT), secret};
passwordComps = new Component[][]{
compIp,
compPort,
compUserName,
compMethod,
compPassword
};
keyComps = new Component[][]{
compIp,
compPort,
compUserName,
compMethod,
compKey,
comSecret
};
usingSsh.setSelected(true);
contextPane = TableLayoutHelper.createGapTableLayoutPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, 11, 11);
jPanel.add(usingSsh, BorderLayout.NORTH);
jPanel.add(contextPane, BorderLayout.CENTER);
this.add(jPanel);
usingSsh.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changePane();
}
});
type.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changePaneForType();
}
});
fileChooserButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(SslUtils.PREFIX, new ChooseFileFilter(true), SslUtils.CERTIFICATES);
int type = fileChooser.showOpenDialog(SshPane.this, StringUtils.EMPTY);
if (type == FILEChooserPane.OK_OPTION) {
final FILE file = fileChooser.getSelectedFILE();
if (file == null) {
keyPath.setText(StringUtils.EMPTY);
} else {
keyPath.setText(file.getPath());
}
}
fileChooser.removeAllFilter();
fileChooser.removeTopPath();
}
});
}
private void changePane() {
contextPane.setVisible(usingSsh.isSelected());
}
private void changePaneForType() {
contextPane.removeAll();
switch (typeMap.get(type.getSelectedItem())) {
case NORMAL:
TableLayoutHelper.addComponent2ResultPane(passwordComps, new double[]{p, p, p, p, p}, columnSize, contextPane);
break;
case KEY:
TableLayoutHelper.addComponent2ResultPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, contextPane);
break;
default:
throw new SshException("un support ssh type");
}
jPanel.revalidate();
jPanel.repaint();
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings");
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
if (jdbcDatabase.getSsh() == null) {
jdbcDatabase.setSsh(new NormalSsh());
}
Ssh ssh = jdbcDatabase.getSsh();
switch (ssh.getSshType()) {
case KEY:
type.setSelectedItem(typeMap.inverse().get(ssh.getSshType()));
KeyVerifySsh keyVerifySsh = (KeyVerifySsh) ssh;
keyPath.setText(keyVerifySsh.getPrivateKeyPath());
secret.setText(keyVerifySsh.getSecret());
password.setText(StringUtils.EMPTY);
setCommonConfig(keyVerifySsh);
break;
case NORMAL:
type.setSelectedItem(typeMap.inverse().get(ssh.getSshType()));
NormalSsh normalSsh = (NormalSsh) ssh;
password.setText(normalSsh.getSecret());
keyPath.setText(StringUtils.EMPTY);
secret.setText(StringUtils.EMPTY);
setCommonConfig(normalSsh);
break;
default:
throw new SshException("un support ssh type");
}
usingSsh.setSelected(ssh.isUsingSsh());
changePane();
}
private void setCommonConfig(BaseSsh baseSsh) {
ip.setText(baseSsh.getIp());
port.setValue(baseSsh.getPort());
user.setText(baseSsh.getUser());
}
public void update(JDBCDatabaseConnection jdbcDatabase) {
Ssh ssh;
switch (typeMap.get(type.getSelectedItem())) {
case NORMAL:
NormalSsh normalSsh = new NormalSsh();
normalSsh.setSecret(new String(password.getPassword()).trim());
getCommonConfig(normalSsh);
ssh = normalSsh;
break;
case KEY:
KeyVerifySsh keyVerifySsh = new KeyVerifySsh();
keyVerifySsh.setPrivateKeyPath(keyPath.getText().trim());
keyVerifySsh.setSecret(new String(secret.getPassword()).trim());
getCommonConfig(keyVerifySsh);
ssh = keyVerifySsh;
break;
default:
throw new SshException("un support ssh type");
}
jdbcDatabase.setSsh(ssh);
}
private void getCommonConfig(BaseSsh baseSsh) {
baseSsh.setUsingSsh(usingSsh.isSelected());
baseSsh.setIp(ip.getText().trim());
baseSsh.setPort(port.getValue());
baseSsh.setUser(user.getText().trim());
}
public static class KeyFileUITextField extends UITextField {
private static final Pattern ERROR_START = Pattern.compile("^([/\\\\.]+).*");
private static final Pattern MUTI_DOT = Pattern.compile("\\.+");
private static final String UPPER = "..";
public KeyFileUITextField(int columns) {
this();
this.setColumns(columns);
}
public KeyFileUITextField() {
super();
this.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
String text = KeyFileUITextField.this.getTextOrigin();
if (!StringUtils.isEmpty(text)) {
if (text.contains(UPPER)) {
text = MUTI_DOT.matcher(text).replaceAll(".");
KeyFileUITextField.this.setTextOrigin(text);
}
Matcher matcher = ERROR_START.matcher(text);
if (matcher.matches()) {
text = text.substring(matcher.group(1).length());
KeyFileUITextField.this.setTextOrigin(text);
}
}
}
});
}
public String getTextOrigin() {
return super.getText();
}
public void setTextOrigin(String text) {
super.setText(text);
}
@Override
public String getText() {
// 获取的时候,不为空,给他加上前缀就好了,否则还是空
if (!StringUtils.isEmpty(super.getText())) {
return SslUtils.PREFIX + super.getText();
}
return StringUtils.EMPTY;
}
@Override
public void setText(String text) {
// 设置的时候,不为空,说明文件指定了(文件需要是resource下),替换掉前缀
if (!StringUtils.isEmpty(text) && text.startsWith(SslUtils.PREFIX)) {
super.setText(text.replaceFirst(SslUtils.PREFIX, ""));
} else {
super.setText(text);
}
}
}
}

165
designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java

@ -0,0 +1,165 @@
package com.fr.design.data.datapane.connect;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.security.ssl.Ssl;
import com.fr.data.security.ssl.SslException;
import com.fr.data.security.ssl.SslType;
import com.fr.data.security.ssl.SslUtils;
import com.fr.data.security.ssl.impl.NormalSsl;
import com.fr.design.border.UITitledBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.datapane.connect.SshPane.KeyFileUITextField;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.stable.StringUtils;
import javax.swing.ImageIcon;
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 static com.fr.design.i18n.Toolkit.i18nText;
/**
* @author xiqiu
* @date 2022/1/4
* @description
*/
public class SslPane extends BasicPane {
UICheckBox usingSsl = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Using"));
private KeyFileUITextField keyPathCa = new KeyFileUITextField(18);
private UIButton fileChooserButtonCa = new UIButton();
private KeyFileUITextField keyPathClientCert = new KeyFileUITextField(18);
private UIButton fileChooserButtonClientCert = new UIButton();
private KeyFileUITextField keyPathClientKey = new KeyFileUITextField(18);
private UIButton fileChooserButtonClientKey = new UIButton();
private UICheckBox verifyCa = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Verify_Ca"));
// private UITextField cipher = new UITextField(20);
private JPanel jPanel;
private Component[][] usingComps;
private double p = TableLayout.PREFERRED;
private double f = TableLayout.FILL;
private JPanel contextPane;
private double[] columnSize = new double[]{195, p};
public SslPane() {
fileChooserButtonCa.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
fileChooserButtonClientCert.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
fileChooserButtonClientKey.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings")));
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout());
jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
Dimension dimension = new Dimension(20, 20);
fileChooserButtonCa.setPreferredSize(dimension);
fileChooserButtonClientCert.setPreferredSize(dimension);
fileChooserButtonClientKey.setPreferredSize(dimension);
JPanel filePanelCa = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathCa, fileChooserButtonCa}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compCa = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Ca") + ":", SwingConstants.RIGHT), filePanelCa};
Component[] compVerifyCa = {null, verifyCa};
JPanel filePanelClientKey = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathClientKey, fileChooserButtonClientKey}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compClientKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Key") + ":", SwingConstants.RIGHT), filePanelClientKey};
JPanel filePanelClientCert = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathClientCert, fileChooserButtonClientCert}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compClientCert = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Cert") + ":", SwingConstants.RIGHT), filePanelClientCert};
// Component[] comCipher = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Cipher") + ":", SwingConstants.RIGHT), cipher};
usingComps = new Component[][]{
compCa,
compVerifyCa,
compClientKey,
compClientCert
// comCipher
};
usingSsl.setSelected(true);
contextPane = TableLayoutHelper.createGapTableLayoutPane(usingComps, new double[]{p, p, p, p}, columnSize, 11, 11);
jPanel.add(usingSsl, BorderLayout.NORTH);
jPanel.add(contextPane, BorderLayout.CENTER);
this.add(jPanel);
usingSsl.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changePane();
}
});
fileChooserButtonCa.addActionListener(new TextFieldActionListener(keyPathCa));
fileChooserButtonClientCert.addActionListener(new TextFieldActionListener(keyPathClientCert));
fileChooserButtonClientKey.addActionListener(new TextFieldActionListener(keyPathClientKey));
}
private void changePane() {
contextPane.setVisible(usingSsl.isSelected());
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings");
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
Ssl ssl = jdbcDatabase.getSsl();
if (ssl == null) {
ssl = new NormalSsl();
jdbcDatabase.setSsl(ssl);
}
if (ssl.getSslType() == SslType.NORMAL) {
NormalSsl normalSsl = (NormalSsl) ssl;
keyPathCa.setText(normalSsl.getCaCertificate());
keyPathClientCert.setText(normalSsl.getClientCertificate());
keyPathClientKey.setText(normalSsl.getClientPrivateKey());
verifyCa.setSelected(normalSsl.isVerifyCa());
// cipher.setText(normalSsl.getCipher());
} else {
throw new SslException("un support ssl type");
}
usingSsl.setSelected(ssl.isUsingSsl());
changePane();
}
public void update(JDBCDatabaseConnection jdbcDatabase) {
NormalSsl normalSsl = new NormalSsl();
// normalSsl.setCipher(cipher.getText().trim());
normalSsl.setVerifyCa(verifyCa.isSelected());
normalSsl.setCaCertificate(keyPathCa.getText().trim());
normalSsl.setClientCertificate(keyPathClientCert.getText().trim());
normalSsl.setClientPrivateKey(keyPathClientKey.getText().trim());
normalSsl.setUsingSsl(usingSsl.isSelected());
jdbcDatabase.setSsl(normalSsl);
}
private class TextFieldActionListener implements ActionListener {
private UITextField textField;
public TextFieldActionListener(UITextField textField) {
this.textField = textField;
}
@Override
public void actionPerformed(ActionEvent e) {
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(SslUtils.PREFIX, new ChooseFileFilter(true), SslUtils.CERTIFICATES);
int type = fileChooser.showOpenDialog(SslPane.this, StringUtils.EMPTY);
if (type == FILEChooserPane.OK_OPTION) {
final FILE file = fileChooser.getSelectedFILE();
if (file == null) {
textField.setText(StringUtils.EMPTY);
} else {
textField.setText(file.getPath());
}
}
fileChooser.removeAllFilter();
fileChooser.removeTopPath();
}
}
}

74
designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java

@ -0,0 +1,74 @@
package com.fr.design.data.datapane.management.clip;
import com.fr.base.TableData;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import com.fr.general.NameObject;
import java.util.HashMap;
import java.util.Map;
/**
* 用于数据集的复制粘贴
*
* @author Yvan
*/
public class TableDataTreeClipboard {
/**
* 数据集名称 - 数据集Wrapper
*/
private Map<String, AbstractTableDataWrapper> clip = new HashMap<>();
private static class Holder {
private static final TableDataTreeClipboard INSTANCE = new TableDataTreeClipboard();
}
private TableDataTreeClipboard() {
}
public static TableDataTreeClipboard getInstance() {
return Holder.INSTANCE;
}
/**
* 添加选中的数据集数据到剪切板覆盖原本剪切板内数据
*
* @param copyMap
* @return
*/
public void addToClip(Map<String, AbstractTableDataWrapper> copyMap) {
this.clip = copyMap;
}
public Map<String, AbstractTableDataWrapper> transferNameObjectArray2Map(NameObject[] selectedNameObjects) {
Map<String, AbstractTableDataWrapper> resultMap = new HashMap<>();
if (selectedNameObjects == null) {
return resultMap;
}
for (NameObject selectedNameObject : selectedNameObjects) {
TableData cloned = TableDataFollowingPasteUtils.cloneTableData(((AbstractTableDataWrapper) selectedNameObject.getObject()).getTableData());
if (cloned != null) {
resultMap.put(selectedNameObject.getName(), new TemplateTableDataWrapper(cloned));
}
}
return resultMap;
}
/**
* 取出剪切板内的所有数据集数据剪切板不清空
*
* @return
*/
public Map<String, AbstractTableDataWrapper> takeFromClip() {
return clip;
}
/**
* 清空剪切板
*/
public void reset() {
clip.clear();
}
}

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

Loading…
Cancel
Save