Browse Source

Merge pull request #8414 in DESIGN/design from feature/x to release/11.0

* commit '1412900fd05acf53c7b8d48658db029876703359': (63 commits)
  REPORT-69108 【迭代】【数据集管理优化】搜索过程中更新关键字,概率卡死 【问题原因】为输入框add的keyListener比remove的次数多,所以会累积性的重复添加监听,导致多次搜索后会多次触发,直到卡死 【改动思路】 1. 修改下remove和add的逻辑,只在初始化输入框时add一次;之前在这里remove那是刚写迭代的时候代码里需要把输入框清空,当时清空后逻辑有问题,所以就add+remove,后面那边清空的逻辑改好了,这里忘改回来了 2. 将计数提前,否则取数失败的任务不会计数 【review建议】无
  REPORT-68706 新增公式中excel不存在的公式勾选导出保留公式导出后显示有问题
  REPORT-66457 原数据集管理优化 【问题原因】跟产品确定了在搜索过程中做数据集的编辑、删除、粘贴时,需要中断搜索,展示原数据集树 【改动思路】编辑、删除、粘贴处添加跳出搜索的逻辑 【review建议】无
  REPORT-68727 【迭代】【数据集管理优化】搜索数据列未加载的数据集,该数据集未被搜索 【问题原因】测试用sleep来模拟取数慢,在取列名的时候会造成一些奇怪的错误 【改动思路】1.因为计算列名里做了异常处理,所以跟产品沟通后确定逻辑为列名为空时,就不展示整个数据集节点了;2.产品让把最大搜索时间的限制去掉 【review建议】无
  REPORT-68740 【迭代】【数据集管理优化】数据集+数据列(不包含数据集),操作按钮未对应灰化 改一下方法名
  REPORT-68740 【迭代】【数据集管理优化】数据集+数据列(不包含数据集),操作按钮未对应灰化 【问题原因】之前做的是,只取选中的有效数据集,然后做复制、粘贴、删除等操作 【改动思路】1. 应产品要求改成同时选中数据集+独立数据列时,复制粘贴删除等操作置灰;2. 将UI相关的代码移到TableDataTree里,TableDataTreeSearchManager那边仅保留搜索结果集用来判断节点是否应该展示以及节点是否应该展开 【review建议】无
  REPORT-68930 【迭代】【数据集管理优化】搜索过程交互提示样式和产品文档不一致 【问题原因】Label文字颜色没设置 【改动思路】改成灰色 【review建议】无
  REPORT-68726 删掉多余import
  REPORT-68726 【迭代】【数据集管理优化】多张模板切换触发搜索,设计器概率卡住 【问题原因】之前的定时器每次搜索都会开始计时,然后新建线程池+线程,在搜索完后停止计时将线程池shutDownNow,是为了不让前一次的搜索计时影响后一次的搜索,但是漏了切换回工具栏的时候停止计时,且每次新建线程池太重了 【改动思路】1.补充切换回工具栏的停止计时逻辑;2.用判断task对象的方式来判断前一次与后一次,保证只有一个线程创建 【review建议】无
  REPORT-68585 修复表格返回大屏编辑器时设计器闪烁的bug
  REPORT-68405 【迭代】【数据集管理优化】显示检索完成了,但是结果为空,实际有结果 【问题原因】1.状态跳转时,结果集被重置了,所以显示无结果;2.之前没搞明白的count减到0过快的原因搞清楚了,是因为预加载任务回调忘了重写done方法了 【改动思路】1.将重置放到搜索开始前;2.预加载任务回调处理;3.部分代码质量问题 【review建议】无
  REPORT-68803 【迭代】【数据集管理优化】复制单元格,已存在同名数据集,数据集不需要跟随复制 【问题原因】rt 【改动思路】修改为存在同名时,不跟随复制 【review建议】无
  REPORT-68392【迭代】【超链设置优化】超链数量=1,编辑/排序,会修改单元格样式 REPORT-68335【迭代】【超链设置优化】超链列表数量n->1时,单元格样式会变化 1、添加判断:判断下当前触发的事件类型
  KERNEL-10626 直接在2.0上支持fvs多开
  REPORT-68355 【迭代】【数据集管理优化】搜索关键字匹配数据列,数据列所在数据集没有展开 【问题原因】之前把切换回工具栏的调用放在TableDataTreePane的refreshDockingView里又因为TableDataTreePane的每一次getInstance都会去调用一次refreshDockingView,搜索任务过程中会经常调用到TableDataTreePane.getInstance,所以造成了搜索状态上的紊乱 【改动思路】1. 扩展TreeSearchStatus,新增Not_In_Search_Mode,视为非搜索模式,其它的状态(搜索中,搜索中止,搜索完成等)统统视为搜索模式 2. 在需要退出搜索模式的地方(切换数据集Tab和新打开一个模板),加上退出的逻辑;不把逻辑放到refreshDockingView里 3. 部分代码质量问题 【review建议】上面改动的第二点,分布在需要退出的场景里,会显得比较松散,但是我没找到一个好的地方可以统一搞。有思路的可以帮忙提供下,感谢~
  REPORT-66457 原数据集管理优化 1. 补充test 2. 删掉监听逻辑,不考虑搜索中的数据集变更问题 3. 删掉测试日志代码
  REPORT-66457 原数据集管理优化 【问题原因】rt 【改动方案】rt 【review建议】详见开发文档:https://kms.fineres.com/pages/viewpage.action?pageId=340985192
  REPORT-67311 jxbrowser 7.15升级到7.22
  REPORT-68117 && REPORT-68112 1、设计器页面,构建树的显示和点开后不一致 2、控件值和数据字典均设置联动,联动异常
  REPORT-65492 新增一个千分比格式
  ...
bugfix/11.0
superman 2 years ago
parent
commit
e9023e3bd2
  1. 8
      build.gradle
  2. 13
      designer-base/src/main/java/com/fr/design/DesignModelAdapter.java
  3. 35
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  4. 4
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  5. 11
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  6. 243
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTree.java
  7. 354
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  8. 12
      designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java
  9. 5
      designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java
  10. 68
      designer-base/src/main/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboard.java
  11. 238
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/TableDataTreeSearchManager.java
  12. 12
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchCallback.java
  13. 37
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchResult.java
  14. 10
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchTask.java
  15. 54
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchCallBack.java
  16. 105
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchResult.java
  17. 146
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchTask.java
  18. 23
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchCallBack.java
  19. 40
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchResult.java
  20. 44
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchTask.java
  21. 22
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeEvent.java
  22. 11
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeListener.java
  23. 213
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java
  24. 199
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java
  25. 38
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataSearchMode.java
  26. 148
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataTreeSearcher.java
  27. 28
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearchStatus.java
  28. 27
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearcher.java
  29. 82
      designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java
  30. 159
      designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java
  31. 109
      designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java
  32. 4
      designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java
  33. 23
      designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java
  34. 22
      designer-base/src/main/java/com/fr/design/formula/FormulaPane.java
  35. 34
      designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java
  36. 12
      designer-base/src/main/java/com/fr/design/gui/controlpane/UIListControlPane.java
  37. 26
      designer-base/src/main/java/com/fr/design/gui/frpane/JTreeControlPane.java
  38. 158
      designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java
  39. 40
      designer-base/src/main/java/com/fr/design/gui/frpane/tree/layer/config/LayerDataControlPane.java
  40. 7
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java
  41. 5
      designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java
  42. 5823
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java
  43. 26
      designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java
  44. 7
      designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java
  45. 26
      designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java
  46. 21
      designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java
  47. 12
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  48. 4
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java
  49. 10
      designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java
  50. 27
      designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java
  51. 2
      designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java
  52. 5
      designer-base/src/main/java/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java
  53. 45
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java
  54. 131
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java
  55. 12
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java
  56. 23
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java
  57. 91
      designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java
  58. 23
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java
  59. 46
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java
  60. 31
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java
  61. 157
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java
  62. 49
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java
  63. 36
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java
  64. 25
      designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java
  65. 31
      designer-base/src/main/java/com/fr/design/upm/UpmFinder.java
  66. 27
      designer-base/src/main/java/com/fr/env/utils/WorkspaceUtils.java
  67. 111
      designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java
  68. 34
      designer-base/src/main/java/com/fr/file/FILEChooserPane.java
  69. 2
      designer-base/src/main/java/com/fr/start/BaseDesigner.java
  70. 14
      designer-base/src/main/java/com/fr/start/event/LazyStartupEvent.java
  71. 8
      designer-base/src/main/resources/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex
  72. 9
      designer-base/src/main/resources/com/fr/design/images/data/back_normal.svg
  73. 10
      designer-base/src/main/resources/com/fr/design/images/data/clear_normal.svg
  74. 9
      designer-base/src/main/resources/com/fr/design/images/data/search_normal.svg
  75. 43
      designer-base/src/test/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboardTest.java
  76. 201
      designer-base/src/test/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtilsTest.java
  77. 139
      designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java
  78. 50
      designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableAdvice.java
  79. 15
      designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableHelper.java
  80. 11
      designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java
  81. 29
      designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java
  82. 19
      designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java
  83. 37
      designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java
  84. 1
      designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java
  85. 1
      designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java
  86. 2
      designer-chart/src/main/java/com/fr/design/module/ChartHyperlinkGroup.java
  87. 7
      designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java
  88. 7
      designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java
  89. 28
      designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java
  90. 15
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java
  91. 39
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java
  92. 4
      designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java
  93. 12
      designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java
  94. 35
      designer-realize/src/main/java/com/fr/design/cell/clipboard/FloatElementsClip.java
  95. 8
      designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java
  96. 5
      designer-realize/src/main/java/com/fr/design/mainframe/WorkBookModelAdapter.java
  97. 171
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java
  98. 11
      designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java
  99. 21
      designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java
  100. 33
      designer-realize/src/main/java/com/fr/design/mainframe/form/FormReportComponentComposite.java
  101. Some files were not shown because too many files have changed in this diff Show More

8
build.gradle

@ -67,10 +67,10 @@ allprojects {
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-mac-v7:7.22'
implementation 'com.fr.third:jxbrowser-win64-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'

13
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;
@ -283,9 +284,9 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
TableData tableData = this.getBook().getTableData(name);
ParameterProvider[] parameterProviders = DataOperator.getInstance().getTableDataParameters(tableData);
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);
}
@ -353,9 +354,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 +379,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);
}

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

@ -214,6 +214,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private boolean useOptimizedUPM4Adapter;
private boolean propertiesUsable;
/**
* DesignerEnvManager.
*/
@ -442,12 +444,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
*
@ -676,6 +701,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.useOptimizedUPM4Adapter = useOptimizedUPM4Adapter;
}
public boolean isPropertiesUsable() {
return this.propertiesUsable;
}
public void setPropertiesUsable(boolean propertiesUsable) {
this.propertiesUsable = propertiesUsable;
}
/**
* 知否自动备份
*
@ -1900,6 +1933,7 @@ 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));
}
@ -2178,6 +2212,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writer.attr("layoutTemplateStyle", this.getLayoutTemplateStyle());
writer.attr("showServerDatasetAuthTip", this.isShowServerDatasetAuthTip());
writer.attr("useOptimizedUPM4Adapter", this.isUseOptimizedUPM4Adapter());
writer.attr("propertiesUsable", this.isPropertiesUsable());
writer.end();
}

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

@ -378,9 +378,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
}
protected boolean isDsNameRepeaded(String name) {
if (allDSNames == null) {
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
}
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
for (int i = 0; i < allDSNames.length; i++) {
if (ComparatorUtils.equals(name, allDSNames[i])) {
return true;

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

@ -308,6 +308,17 @@ 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();

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

@ -1,7 +1,10 @@
package com.fr.design.data.datapane;
import com.fr.base.BaseUtils;
import com.fr.data.impl.storeproc.StoreProcedure;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
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 +20,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 +31,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.
*/
@ -84,12 +95,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 +114,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 +152,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 +160,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 +283,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 AbstractTableDataWrapper) {
return true;
}
return false;
}
public TableDataWrapper[] getSelectedDatas() {
TreePath[] selectedTreePaths = this.getSelectionPaths();
if (selectedTreePaths == null || selectedTreePaths.length == 0) {
@ -247,4 +450,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 StoreProcedure;
}
return false;
}
}

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

@ -13,6 +13,11 @@ 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.management.clip.TableDataTreeClipboard;
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.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
@ -20,12 +25,14 @@ 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.ilist.CheckBoxList;
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;
@ -37,6 +44,7 @@ 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;
@ -61,7 +69,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;
@ -69,9 +76,12 @@ 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;
@ -107,13 +117,20 @@ public class TableDataTreePane extends BasicTableDataTreePane {
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();
}
@ -122,13 +139,76 @@ 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);
createAddMenuDef();
@ -136,49 +216,54 @@ public class TableDataTreePane extends BasicTableDataTreePane {
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));
return searchLayerdPane;
}
UIScrollPane scrollPane = new UIScrollPane(tableDataTree);
scrollPane.setBorder(null);
/**
* 数据集树面板
*
* @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() {
@ -300,6 +385,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) {
@ -471,6 +560,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)) {
@ -501,11 +601,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) {
@ -594,6 +744,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();
}
@ -863,34 +1016,125 @@ public class TableDataTreePane extends BasicTableDataTreePane {
@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 checkBoxList = new CheckBoxList(selectedNameObjects, CheckBoxList.SelectedState.ALL, Toolkit.i18nText("Fine-Design_Basic_Remove_All_Selected"));
UIScrollPane scrollPane = new UIScrollPane(checkBoxList);
BasicPane basicPane = new BasicPane() {
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Remove");
}
};
basicPane.setLayout(new BorderLayout());
basicPane.add(scrollPane, BorderLayout.CENTER);
BasicDialog basicDialog = basicPane.showSmallWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() {
@Override
public void doOk() {
Object[] selectedValues = checkBoxList.getSelectedValues();
// 删除时如果正在搜索,跳回原树
if (TableDataTreeSearchManager.getInstance().isInSearchMode()) {
TableDataTreeSearchManager.getInstance().outOfSearchMode();
}
for (Object toRemove : selectedValues) {
doRemove((NameObject) 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);
}
private void doRemove(NameObject selectedNO) {
// richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧
op.removeAction(selectedNO.getName());
tableDataTree.refresh();
// Richie:默认最后一行获得焦点.
tableDataTree.requestFocus();
tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1);
fireDSChanged();
checkButtonEnabled();
//删掉缓存配置
StrategyConfigAttrUtils.removeStrategyConfig(selectedNO.getName());
// 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样
// 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效
// 这里额外发出一次数据集修改事件
StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName())));
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName());
}
}
private class CopyAction extends UpdateAction {
public CopyAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Copy"));
this.setMnemonic('C');
this.setSmallIcon("/com/fr/design/images/m_edit/copy");
}
//删掉缓存配置
StrategyConfigAttrUtils.removeStrategyConfig(selectedNO.getName());
@Override
public void actionPerformed(ActionEvent e) {
NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects();
Map<String, AbstractTableDataWrapper> dataWrapperMap = TableDataTreeClipboard.getInstance().transferNameObjectArray2Map(selectedNameObjects);
TableDataTreeClipboard.getInstance().addToClip(dataWrapperMap);
}
}
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");
}
// 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样
// 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效
// 这里额外发出一次数据集修改事件
StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName())));
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName());
@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 = wrapper.creatTableDataPane();
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/images/data/search");
}
@Override
public void actionPerformed(ActionEvent e) {
// 交换层级
toolbarPane.switchPane(TreeSearchToolbarPane.SEARCH_PANE);
TableDataTreeSearchManager.getInstance().switchToSearch(TableDataSearchMode.match(buttonGroup.getSelectedIndex()), DesignTableDataManager.getEditingTableDataSource());
}
}

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

@ -7,6 +7,7 @@ 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;
@ -25,7 +26,6 @@ import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.third.guava.collect.HashBiMap;
import javax.swing.ImageIcon;
@ -131,7 +131,7 @@ public class SshPane extends BasicPane {
fileChooserButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true));
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();
@ -142,6 +142,7 @@ public class SshPane extends BasicPane {
}
}
fileChooser.removeAllFilter();
fileChooser.removeTopPath();
}
});
}
@ -241,7 +242,6 @@ public class SshPane extends BasicPane {
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 PREFIX = ProjectConstants.RESOURCES_NAME + "/";
private static final String UPPER = "..";
public KeyFileUITextField(int columns) {
@ -283,7 +283,7 @@ public class SshPane extends BasicPane {
public String getText() {
// 获取的时候,不为空,给他加上前缀就好了,否则还是空
if (!StringUtils.isEmpty(super.getText())) {
return PREFIX + super.getText();
return SslUtils.PREFIX + super.getText();
}
return StringUtils.EMPTY;
}
@ -291,8 +291,8 @@ public class SshPane extends BasicPane {
@Override
public void setText(String text) {
// 设置的时候,不为空,说明文件指定了(文件需要是resource下),替换掉前缀
if (!StringUtils.isEmpty(text) && text.startsWith(PREFIX)) {
super.setText(text.replaceFirst(PREFIX, ""));
if (!StringUtils.isEmpty(text) && text.startsWith(SslUtils.PREFIX)) {
super.setText(text.replaceFirst(SslUtils.PREFIX, ""));
} else {
super.setText(text);
}

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

@ -4,6 +4,7 @@ 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;
@ -21,7 +22,6 @@ import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
@ -148,7 +148,7 @@ public class SslPane extends BasicPane {
@Override
public void actionPerformed(ActionEvent e) {
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true));
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();
@ -159,6 +159,7 @@ public class SslPane extends BasicPane {
}
}
fileChooser.removeAllFilter();
fileChooser.removeTopPath();
}
}
}

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

@ -0,0 +1,68 @@
package com.fr.design.data.datapane.management.clip;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
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) {
resultMap.put(selectedNameObject.getName(), (AbstractTableDataWrapper) selectedNameObject.getObject());
}
return resultMap;
}
/**
* 取出剪切板内的所有数据集数据剪切板不清空
*
* @return
*/
public Map<String, AbstractTableDataWrapper> takeFromClip() {
return clip;
}
/**
* 清空剪切板
*/
public void reset() {
clip.clear();
}
}

238
designer-base/src/main/java/com/fr/design/data/datapane/management/search/TableDataTreeSearchManager.java

@ -0,0 +1,238 @@
package com.fr.design.data.datapane.management.search;
import com.fr.data.TableDataSource;
import com.fr.design.DesignModelAdapter;
import com.fr.design.data.datapane.TableDataTree;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeEvent;
import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeListener;
import com.fr.design.data.datapane.management.search.searcher.TableDataSearchMode;
import com.fr.design.data.datapane.management.search.searcher.TableDataTreeSearcher;
import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus;
import com.fr.design.data.datapane.management.search.view.TreeSearchRendererHelper;
import com.fr.stable.StringUtils;
import javax.swing.SwingUtilities;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 数据集树搜索管理器
*
* @author Yvan
*/
public class TableDataTreeSearchManager {
/**
* 数据集树搜索器
*/
private TableDataTreeSearcher treeSearcher;
/**
* 搜索任务的状态
*/
private TreeSearchStatus treeSearchStatus;
/**
* 缓存上次搜索文本避免重复搜索
*/
private String lastSearchText;
/**
* 存储与复原 原本数据集树的UI
*/
private TreeSearchRendererHelper rendererHelper;
/**
* 取数计数器
*/
private AtomicInteger count;
/**
* 搜索状态变化监听
*/
private List<TreeSearchStatusChangeListener> listeners = new ArrayList<>();
private TableDataTreeSearchManager() {
init();
}
private void init() {
this.treeSearchStatus = TreeSearchStatus.NOT_IN_SEARCH_MODE;
}
private static class Holder {
private static final TableDataTreeSearchManager INSTANCE = new TableDataTreeSearchManager();
}
public static TableDataTreeSearchManager getInstance() {
return Holder.INSTANCE;
}
public TreeSearchStatus getTreeSearchStatus() {
return treeSearchStatus;
}
public void setTreeSearchStatus(TreeSearchStatus treeSearchStatus) {
this.treeSearchStatus = treeSearchStatus;
// 每次设置搜索状态,都触发下监听,让页面跟随变化
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (TreeSearchStatusChangeListener listener : listeners) {
listener.updateTreeSearchChange(new TreeSearchStatusChangeEvent(treeSearchStatus));
}
}
});
}
public void registerTreeSearchStatusChangeListener(TreeSearchStatusChangeListener listener) {
listeners.add(listener);
}
/**
* 工具栏处切换到搜索面板
*
* @param searchMode
* @param tableDataSource
*/
public void switchToSearch(TableDataSearchMode searchMode, TableDataSource tableDataSource) {
setTreeSearchStatus(TreeSearchStatus.SEARCH_NOT_BEGIN);
rendererHelper = new TreeSearchRendererHelper();
rendererHelper.save(getCurrentTableDataTree());
treeSearcher = new TableDataTreeSearcher();
treeSearcher.beforeSearch(searchMode, tableDataSource);
}
/**
* 获取当前的tableDataTree
*
* @return
*/
private TableDataTree getCurrentTableDataTree() {
DesignModelAdapter<?, ?> currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter();
TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstance(currentModelAdapter);
return tableDataTreePane.getDataTree();
}
public boolean isMatchSetsEmpty() {
return treeSearcher.isMatchSetsEmpty();
}
/**
* 开始搜索
*
* @param searchText
*/
public void startSearch(String searchText) {
if (isRepeatSearch(searchText) || StringUtils.isEmpty(searchText)) {
return;
}
setTreeSearchStatus(TreeSearchStatus.SEARCHING);
rendererHelper.replaceTreeRenderer(getCurrentTableDataTree(), searchText);
count = new AtomicInteger(treeSearcher.getAllWrappersSize());
treeSearcher.startSearch(searchText);
}
/**
* 计数-1
*/
public void decreaseCount() {
if (count == null) {
return;
}
int cunrrentCount = count.decrementAndGet();
// 减到0后判断状态
if (cunrrentCount == 0 && getTreeSearchStatus() == TreeSearchStatus.SEARCHING) {
completeSearch();
}
}
private boolean isRepeatSearch(String searchText) {
if (StringUtils.isEmpty(lastSearchText)) {
lastSearchText = searchText;
return false;
}
return StringUtils.equals(lastSearchText, searchText);
}
/**
* 刷新树更新搜索的结果
*/
public void updateTableDataTree() {
getCurrentTableDataTree().refresh4TreeSearch();
}
/**
* 中断搜索
*/
public void stopSearch() {
setTreeSearchStatus(TreeSearchStatus.SEARCH_STOPPED);
count = null;
treeSearcher.stopSearch();
}
/**
* 搜索完成
*/
public void completeSearch() {
setTreeSearchStatus(TreeSearchStatus.SEARCH_COMPLETED);
count = null;
treeSearcher.completeSearch();
}
/**
* 切换回工具栏恢复数据集树UI
*/
public void restoreToolBarAndTreePane() {
setTreeSearchStatus(TreeSearchStatus.NOT_IN_SEARCH_MODE);
if (treeSearcher != null) {
treeSearcher.afterSearch();
}
lastSearchText = null;
if (rendererHelper != null) {
rendererHelper.restore(getCurrentTableDataTree());
}
}
/**
* 恢复数据集树UI
*/
public void restoreTreePane() {
setTreeSearchStatus(TreeSearchStatus.SEARCH_NOT_BEGIN);
lastSearchText = null;
if (rendererHelper != null) {
rendererHelper.restore(getCurrentTableDataTree());
}
}
/**
* 节点是否应该添加到搜索结果树的根节点中
* 只针对数据集节点
*
* @param treeNodeName 数据集节点名称
* @return
*/
public boolean nodeNameMatches(String treeNodeName) {
return treeSearcher.nodeMatches(treeNodeName);
}
/**
* 节点是否应该展开
*
* @param treeNodeName 节点名称
* @return
*/
public boolean nodeCanExpand(String treeNodeName) {
return treeSearcher.nodeCanExpand(treeNodeName);
}
public boolean isInSearchMode() {
return getTreeSearchStatus() != TreeSearchStatus.NOT_IN_SEARCH_MODE;
}
public void outOfSearchMode() {
restoreToolBarAndTreePane();
}
}

12
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchCallback.java

@ -0,0 +1,12 @@
package com.fr.design.data.datapane.management.search.control;
/**
* 搜索任务回调
*
* @author Yvan
*/
public interface TreeSearchCallback {
void done(TreeSearchResult treeSearchResult);
}

37
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchResult.java

@ -0,0 +1,37 @@
package com.fr.design.data.datapane.management.search.control;
import java.util.List;
/**
* @author Yvan
*/
public interface TreeSearchResult {
/**
* 任务结果是否成功
*
* @return
*/
boolean isSuccess();
/**
* 数据集名称匹配或者列名匹配时需要将数据集名称添加到匹配结果集中
*
* @return
*/
List<String> getAddToMatch();
/**
* 数据集有列名匹配时需要添加到展开结果集中
*
* @return
*/
List<String> getAddToExpand();
/**
* 数据集完成计算后需要添加到完成结果集中
*
* @return
*/
List<String> getAddToCalculated();
}

10
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/TreeSearchTask.java

@ -0,0 +1,10 @@
package com.fr.design.data.datapane.management.search.control;
/**
* @author Yvan
*/
public interface TreeSearchTask extends Runnable {
@Override
void run();
}

54
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchCallBack.java

@ -0,0 +1,54 @@
package com.fr.design.data.datapane.management.search.control.common;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.control.TreeSearchCallback;
import com.fr.design.data.datapane.management.search.control.TreeSearchResult;
import com.fr.design.data.datapane.management.search.searcher.TableDataTreeSearcher;
import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus;
import javax.swing.SwingUtilities;
/**
* @author Yvan
*/
public class TableDataSearchCallBack implements TreeSearchCallback {
protected TableDataTreeSearcher treeSearcher;
public TableDataSearchCallBack(TableDataTreeSearcher treeSearcher) {
this.treeSearcher = treeSearcher;
}
@Override
public void done(TreeSearchResult treeSearchResult) {
if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() != TreeSearchStatus.SEARCHING) {
return;
}
// 搜索计数
TableDataTreeSearchManager.getInstance().decreaseCount();
if (treeSearchResult.isSuccess()) {
// 添加结果
addToTreeSearcher(treeSearchResult);
// 处理UI
updateTableDataTree();
}
}
protected void updateTableDataTree() {
SwingUtilities.invokeLater(() -> {
if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() != TreeSearchStatus.SEARCHING) {
return;
}
TableDataTreeSearchManager.getInstance().updateTableDataTree();
});
}
protected void addToTreeSearcher(TreeSearchResult treeSearchResult) {
// 添加到已计算结果集
treeSearcher.addToCalculatedSets(treeSearchResult.getAddToCalculated());
// 添加到匹配结果集
treeSearcher.addToMatchSets(treeSearchResult.getAddToMatch());
// 添加到展开结果集
treeSearcher.addToCanExpandSets(treeSearchResult.getAddToExpand());
}
}

105
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchResult.java

@ -0,0 +1,105 @@
package com.fr.design.data.datapane.management.search.control.common;
import com.fr.design.data.datapane.management.search.control.TreeSearchResult;
import java.util.ArrayList;
import java.util.List;
/**
* @author Yvan
*/
public class TableDataSearchResult implements TreeSearchResult {
private boolean success;
private List<String> addToMatch;
private List<String> addToExpand;
private List<String> addToCalculated;
protected TableDataSearchResult(Builder builder) {
this.success = builder.success;
this.addToMatch = builder.addToMatch;
this.addToExpand = builder.addToExpand;
this.addToCalculated = builder.addToCalculated;
}
public void setSuccess(boolean success) {
this.success = success;
}
public void setAddToMatch(List<String> addToMatch) {
this.addToMatch = addToMatch;
}
public void setAddToExpand(List<String> addToExpand) {
this.addToExpand = addToExpand;
}
public void setAddToCalculated(List<String> addToCalculated) {
this.addToCalculated = addToCalculated;
}
@Override
public boolean isSuccess() {
return this.success;
}
@Override
public List<String> getAddToMatch() {
return this.addToMatch;
}
@Override
public List<String> getAddToExpand() {
return this.addToExpand;
}
@Override
public List<String> getAddToCalculated() {
return this.addToCalculated;
}
public static class Builder {
private boolean success;
private List<String> addToMatch;
private List<String> addToExpand;
private List<String> addToCalculated;
public Builder() {
this.success = false;
this.addToMatch = new ArrayList<>();
this.addToExpand = new ArrayList<>();
this.addToCalculated = new ArrayList<>();
}
public Builder buildSuccess(boolean success) {
this.success = success;
return this;
}
public Builder buildAddToMatch(List<String> addToMatch) {
this.addToMatch = addToMatch;
return this;
}
public Builder buildAddToExpand(List<String> addToExpand) {
this.addToExpand = addToExpand;
return this;
}
public Builder buildAddToCalculated(List<String> addToCalculated) {
this.addToCalculated = addToCalculated;
return this;
}
public TableDataSearchResult build() {
return new TableDataSearchResult(this);
}
}
}

146
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/common/TableDataSearchTask.java

@ -0,0 +1,146 @@
package com.fr.design.data.datapane.management.search.control.common;
import com.fr.design.data.datapane.management.search.control.TreeSearchCallback;
import com.fr.design.data.datapane.management.search.control.TreeSearchResult;
import com.fr.design.data.datapane.management.search.control.TreeSearchTask;
import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author Yvan
*/
public class TableDataSearchTask implements TreeSearchTask {
/**
* 用户搜索的文本
*/
private String searchText;
private TableDataWrapper tableDataWrapper;
private TreeSearchCallback callback;
public TableDataSearchTask(String searchText, TableDataWrapper tableDataWrapper, TreeSearchCallback callback) {
this.searchText = searchText;
this.tableDataWrapper = tableDataWrapper;
this.callback = callback;
}
@Override
public void run() {
TreeSearchResult result;
try {
if (isTableDataStoreProcedure(tableDataWrapper)) {
result = dealWithStoreProcedureTableDataWrapper((StoreProcedureDataWrapper) tableDataWrapper);
} else {
result = dealWithCommonTableDataWrapper(tableDataWrapper);
}
} catch (Throwable e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
result = dealWithErrorTableDataWrapper(tableDataWrapper);
}
callback.done(result);
}
/**
* 处理错误情况
*
* @param tableDataWrapper
*/
private TreeSearchResult dealWithErrorTableDataWrapper(TableDataWrapper tableDataWrapper) {
return new TableDataSearchResult.Builder().buildSuccess(false).build();
}
/**
* 处理普通数据集的搜索与匹配
*
* @param tableDataWrapper
*/
private TreeSearchResult dealWithCommonTableDataWrapper(TableDataWrapper tableDataWrapper) {
String tableDataName = tableDataWrapper.getTableDataName();
boolean isTableDataNameMatch = isMatchSearch(tableDataName, searchText);
List<String> columnNameList = tableDataWrapper.calculateColumnNameList();
// 没取到列名的话,代表取数那边出错了,就不添加数据集了
if (columnNameList.size() == 0) {
return new TableDataSearchResult.Builder().buildSuccess(false).build();
}
boolean isColumnMatch = columnNameList.stream().anyMatch(columnName -> isMatchSearch(columnName, searchText));
return new TableDataSearchResult.Builder()
.buildSuccess(true)
.buildAddToMatch(isTableDataNameMatch || isColumnMatch ? Arrays.asList(tableDataName) : new ArrayList<>())
.buildAddToExpand(isColumnMatch ? Arrays.asList(tableDataName) : new ArrayList<>())
.buildAddToCalculated(Arrays.asList(tableDataName))
.build();
}
/**
* 处理存储过程的搜索与匹配
*
* @param procedureDataWrapper
*/
private TreeSearchResult dealWithStoreProcedureTableDataWrapper(StoreProcedureDataWrapper procedureDataWrapper) {
// 存储过程数据集名称,例如 Proc1_Table1
String tableDataName = procedureDataWrapper.getTableDataName();
// 存储过程名称,例如 Proc1
String storeProcedureName = procedureDataWrapper.getStoreprocedureName();
// 存储过程子表名称,例如 Table1
String tableName = tableDataName.replaceFirst(storeProcedureName, StringUtils.EMPTY).replaceFirst("_", StringUtils.EMPTY);
boolean isStoreProcedureNameMatch = isMatchSearch(storeProcedureName, searchText);
boolean isTableNameMatch = isMatchSearch(tableName, searchText);
// 再处理子表的columns
List<String> columnNameList = tableDataWrapper.calculateColumnNameList();
boolean isColumnMatch = columnNameList.stream().anyMatch(columnName -> isMatchSearch(columnName, searchText));
Set<String> addToMatch = new HashSet<>();
Set<String> addToExpand = new HashSet<>();
Set<String> addToCalculated = new HashSet<>();
if (isStoreProcedureNameMatch) {
addToMatch.add(storeProcedureName);
}
if (isTableNameMatch) {
addToMatch.add(storeProcedureName);
addToExpand.add(storeProcedureName);
}
if (isColumnMatch) {
addToMatch.add(storeProcedureName);
addToExpand.add(storeProcedureName);
// 这里有重名风险,所以要添加 “Proc1_Table1”,在结果树展示的时候再去处理
addToExpand.add(tableDataName);
}
addToCalculated.add(tableDataName);
return new TableDataSearchResult.Builder()
.buildSuccess(true)
.buildAddToMatch(new ArrayList<>(addToMatch))
.buildAddToExpand(new ArrayList<>(addToExpand))
.buildAddToCalculated(new ArrayList<>(addToCalculated))
.build();
}
/**
* 判断TableDataWrapper内的TableData是否为存储过程
*
* @param tableDataWrapper
* @return
*/
private boolean isTableDataStoreProcedure(TableDataWrapper tableDataWrapper) {
return tableDataWrapper instanceof StoreProcedureDataWrapper;
}
/**
* 判断是否匹配搜索文本不区分大小写
*
* @param str
* @return
*/
private boolean isMatchSearch(String str, String searchText) {
return str.toUpperCase().contains(searchText.toUpperCase());
}
}

23
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchCallBack.java

@ -0,0 +1,23 @@
package com.fr.design.data.datapane.management.search.control.pre;
import com.fr.design.data.datapane.management.search.control.TreeSearchResult;
import com.fr.design.data.datapane.management.search.control.common.TableDataSearchCallBack;
import com.fr.design.data.datapane.management.search.searcher.TableDataTreeSearcher;
/**
* 预取数任务回调
*
* @author Yvan
*/
public class TableDataPreSearchCallBack extends TableDataSearchCallBack {
public TableDataPreSearchCallBack(TableDataTreeSearcher treeSearcher) {
super(treeSearcher);
}
@Override
public void done(TreeSearchResult treeSearchResult) {
// do nothing
}
}

40
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchResult.java

@ -0,0 +1,40 @@
package com.fr.design.data.datapane.management.search.control.pre;
import com.fr.design.data.datapane.management.search.control.TreeSearchResult;
import java.util.ArrayList;
import java.util.List;
/**
* 预取数任务结果不需要回调因此空实现即可
*
* @author Yvan
*/
public class TableDataPreSearchResult implements TreeSearchResult {
private boolean success;
public TableDataPreSearchResult(boolean success) {
this.success = success;
}
@Override
public boolean isSuccess() {
return this.success;
}
@Override
public List<String> getAddToMatch() {
return new ArrayList<>();
}
@Override
public List<String> getAddToExpand() {
return new ArrayList<>();
}
@Override
public List<String> getAddToCalculated() {
return new ArrayList<>();
}
}

44
designer-base/src/main/java/com/fr/design/data/datapane/management/search/control/pre/TableDataPreSearchTask.java

@ -0,0 +1,44 @@
package com.fr.design.data.datapane.management.search.control.pre;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.control.TreeSearchTask;
import com.fr.design.data.datapane.management.search.control.common.TableDataSearchResult;
import com.fr.design.data.datapane.management.search.control.TreeSearchCallback;
import com.fr.design.data.datapane.management.search.control.TreeSearchResult;
import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.log.FineLoggerFactory;
/**
* 预取数任务
*
* @author Yvan
*/
public class TableDataPreSearchTask implements TreeSearchTask {
private TreeSearchCallback callback;
private TableDataWrapper tableDataWrapper;
public TableDataPreSearchTask(TreeSearchCallback callback, TableDataWrapper tableDataWrapper) {
this.callback = callback;
this.tableDataWrapper = tableDataWrapper;
}
@Override
public void run() {
TreeSearchResult result;
try {
tableDataWrapper.calculateColumnNameList();
result = new TableDataSearchResult.Builder()
.buildSuccess(true)
.build();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "calculate table data {} failed", tableDataWrapper.getTableDataName());
result = new TableDataSearchResult.Builder()
.buildSuccess(false)
.build();
}
callback.done(result);
}
}

22
designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeEvent.java

@ -0,0 +1,22 @@
package com.fr.design.data.datapane.management.search.event;
import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus;
import java.util.EventObject;
/**
* @author Yvan
*/
public class TreeSearchStatusChangeEvent extends EventObject {
private TreeSearchStatus status;
public TreeSearchStatusChangeEvent(Object source) {
super(source);
this.status = (TreeSearchStatus) source;
}
public TreeSearchStatus getTreeSearchStatus() {
return status;
}
}

11
designer-base/src/main/java/com/fr/design/data/datapane/management/search/event/TreeSearchStatusChangeListener.java

@ -0,0 +1,11 @@
package com.fr.design.data.datapane.management.search.event;
import java.util.EventListener;
/**
* @author Yvan
*/
public interface TreeSearchStatusChangeListener extends EventListener {
void updateTreeSearchChange(TreeSearchStatusChangeEvent event);
}

213
designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java

@ -0,0 +1,213 @@
package com.fr.design.data.datapane.management.search.pane;
import com.fr.base.svg.IconUtils;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.datapane.TableDataTree;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeEvent;
import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeListener;
import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
* @author Yvan
*/
public class TableDataSearchRemindPane extends JPanel implements TreeSearchStatusChangeListener {
private RemindPane remindPane;
private TreePane treePane;
public TableDataSearchRemindPane(TableDataTree tableDataTree) {
this.setLayout(new BorderLayout());
remindPane = new RemindPane();
treePane = new TreePane(tableDataTree);
// 初始状态
this.add(remindPane, BorderLayout.NORTH);
this.add(treePane, BorderLayout.CENTER);
TableDataTreeSearchManager.getInstance().registerTreeSearchStatusChangeListener(this);
}
/**
* 根据搜索状态变化来调整自身面板的显示
*
* @param event
*/
@Override
public void updateTreeSearchChange(TreeSearchStatusChangeEvent event) {
TreeSearchStatus status = event.getTreeSearchStatus();
if (status == TreeSearchStatus.SEARCH_NOT_BEGIN || status == TreeSearchStatus.NOT_IN_SEARCH_MODE) {
remindPane.onNotBegin();
treePane.onNotBegin();
} else if (status == TreeSearchStatus.SEARCHING) {
remindPane.onInSearching();
treePane.onInSearching();
} else if (status == TreeSearchStatus.SEARCH_STOPPED) {
remindPane.onStoppedSearching();
treePane.onStoppedSearching();
} else {
boolean matchSetsEmpty = TableDataTreeSearchManager.getInstance().isMatchSetsEmpty();
// 代表是否搜索出结果
remindPane.onDoneSearching(matchSetsEmpty);
treePane.onDoneSearching(matchSetsEmpty);
}
this.revalidate();
}
private interface TreeSearchStatusChange {
void onNotBegin();
void onInSearching();
void onStoppedSearching();
void onDoneSearching(boolean matchSetsEmpty);
}
private class TreePane extends JPanel implements TreeSearchStatusChange {
private UIScrollPane scrollPane;
private JPanel notFoundPane;
private CardLayout cardLayout;
private static final String SCROLL_PANE = "scrollPane";
private static final String NOT_FOUND_PANE = "notFoundPane";
public TreePane(TableDataTree tableDataTree) {
init(tableDataTree);
}
private void init(TableDataTree tableDataTree) {
scrollPane = new UIScrollPane(tableDataTree);
scrollPane.setBorder(null);
notFoundPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5);
UILabel emptyPicLabel = new UILabel();
emptyPicLabel.setIcon(IconUtils.readIcon("com/fr/base/images/share/no_match_icon.png"));
emptyPicLabel.setHorizontalAlignment(SwingConstants.CENTER);
emptyPicLabel.setPreferredSize(new Dimension(240, 100));
UILabel textLabel = new UILabel(Toolkit.i18nText("Fine-Design_Tree_Search_Not_Match"), SwingConstants.CENTER);
textLabel.setForeground(Color.gray);
textLabel.setHorizontalAlignment(SwingConstants.CENTER);
textLabel.setPreferredSize(new Dimension(240, 20));
notFoundPane.add(emptyPicLabel);
notFoundPane.add(textLabel);
notFoundPane.setBorder(BorderFactory.createEmptyBorder(80, 0, 0, 0));
cardLayout = new CardLayout();
this.setLayout(cardLayout);
this.add(scrollPane, SCROLL_PANE);
this.add(notFoundPane, NOT_FOUND_PANE);
cardLayout.show(this, SCROLL_PANE);
}
@Override
public void onNotBegin() {
switchPane(SCROLL_PANE);
}
@Override
public void onInSearching() {
switchPane(SCROLL_PANE);
}
@Override
public void onStoppedSearching() {
switchPane(SCROLL_PANE);
}
@Override
public void onDoneSearching(boolean matchSetsEmpty) {
if (matchSetsEmpty) {
switchPane(NOT_FOUND_PANE);
}
}
private void switchPane(String paneName) {
cardLayout.show(this, paneName);
}
}
private static class RemindPane extends JPanel implements TreeSearchStatusChange {
private static final String IN_SEARCHING = Toolkit.i18nText("Fine-Design_Tree_Search_In_Searching");
private static final String STOP_SEARCHING = Toolkit.i18nText("Fine-Design_Tree_Search_Stop_Search");
private static final String SEARCHING_STOPPED = Toolkit.i18nText("Fine-Design_Tree_Search_Search_Stopped");
private static final String DONE_SEARCHING = Toolkit.i18nText("Fine-Design_Tree_Search_Search_Completed");
private UILabel textLabel;
private UILabel stopLabel;
private MouseListener stopSearch;
public RemindPane() {
init();
}
private void init() {
this.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0));
// 初始情况下为Not_Begin
textLabel = new UILabel();
textLabel.setForeground(Color.gray);
stopLabel = new UILabel();
stopLabel.setForeground(UIConstants.NORMAL_BLUE);
stopSearch = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
TableDataTreeSearchManager.getInstance().stopSearch();
}
};
stopLabel.addMouseListener(stopSearch);
this.add(textLabel);
this.add(stopLabel);
onNotBegin();
}
@Override
public void onNotBegin() {
this.setVisible(false);
}
@Override
public void onInSearching() {
this.textLabel.setText(IN_SEARCHING);
this.stopLabel.setText(STOP_SEARCHING);
this.stopLabel.setVisible(true);
this.setVisible(true);
}
@Override
public void onStoppedSearching() {
this.textLabel.setText(SEARCHING_STOPPED);
this.stopLabel.setVisible(false);
this.setVisible(true);
}
@Override
public void onDoneSearching(boolean matchSetsEmpty) {
this.textLabel.setText(DONE_SEARCHING);
this.stopLabel.setVisible(false);
this.setVisible(true);
}
}
}

199
designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java

@ -0,0 +1,199 @@
package com.fr.design.data.datapane.management.search.pane;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignModelAdapter;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeEvent;
import com.fr.design.data.datapane.management.search.event.TreeSearchStatusChangeListener;
import com.fr.design.data.datapane.management.search.searcher.TreeSearchStatus;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Panel;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* @author Yvan
*/
public class TreeSearchToolbarPane extends Panel implements TreeSearchStatusChangeListener {
public static final String TOOLBAR_PANE = "toolbarPane";
public static final String SEARCH_PANE = "searchPane";
/**
* 工具栏
*/
private UIToolbar toolbar;
/**
* 工具栏面板
*/
private JPanel toolbarPane;
/**
* 搜索面板
*/
private JPanel searchPane;
/**
* 搜索输入框
*/
private UITextField searchTextField;
/**
* 内容面板
*/
private JPanel contentPane;
/**
* 卡片布局管理器
*/
private CardLayout cardLayout;
private final KeyAdapter enterPressed = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
TableDataTreeSearchManager.getInstance().startSearch(searchTextField.getText());
}
}
};
public TreeSearchToolbarPane(UIToolbar toolbar) {
this.toolbar = toolbar;
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initToolbarPane();
initSearchPane();
initContentPane();
add(contentPane, BorderLayout.CENTER);
setPreferredSize(new Dimension(240, 30));
TableDataTreeSearchManager.getInstance().registerTreeSearchStatusChangeListener(this);
}
private void initContentPane() {
cardLayout = new CardLayout();
contentPane = new JPanel(cardLayout);
contentPane.add(searchPane, SEARCH_PANE);
contentPane.add(toolbarPane, TOOLBAR_PANE);
cardLayout.show(contentPane, TOOLBAR_PANE);
}
private void initSearchPane() {
searchPane = new JPanel(FRGUIPaneFactory.createBorderLayout());
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
searchPane.setBackground(Color.WHITE);
// 左侧搜索图标
UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search"));
searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
searchLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// do nothing
}
});
// 中间输入框
searchTextField = new UITextField();
searchTextField.setBorderPainted(false);
searchTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Tree_Search_Press_Enter_For_Search"));
searchTextField.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.NORMAL_BLUE));
searchPane.repaint();
}
@Override
public void focusLost(FocusEvent e) {
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
searchPane.repaint();
}
});
this.searchTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
}
@Override
public void removeUpdate(DocumentEvent e) {
dealWithTextChange();
}
@Override
public void changedUpdate(DocumentEvent e) {
}
});
this.searchTextField.addKeyListener(enterPressed);
// 右侧返回图标
UILabel returnLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/clear"));
returnLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Tree_Search_Return"));
returnLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
returnLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
searchTextField.setText(StringUtils.EMPTY);
TableDataTreeSearchManager.getInstance().outOfSearchMode();
switchPane(TOOLBAR_PANE);
}
});
searchPane.add(searchLabel, BorderLayout.WEST);
searchPane.add(searchTextField, BorderLayout.CENTER);
searchPane.add(returnLabel, BorderLayout.EAST);
}
private void dealWithTextChange() {
if (StringUtils.isEmpty(searchTextField.getText()) && TableDataTreeSearchManager.getInstance().isInSearchMode()) {
// 如果是搜索模式下,看作是用户删除输入框文字,仅复原TableDataTreePane
TableDataTreeSearchManager.getInstance().restoreTreePane();
TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).refreshDockingView();
}
}
private void initToolbarPane() {
toolbarPane = new JPanel();
toolbarPane.setLayout(FRGUIPaneFactory.createBorderLayout());
toolbarPane.add(toolbar, BorderLayout.CENTER);
}
/**
* 交换当前面板层级
*/
public void switchPane(String name) {
cardLayout.show(contentPane, name);
}
public void setPlaceHolder(String placeHolder) {
this.searchTextField.setPlaceholder(placeHolder);
}
/**
* 根据搜索状态变化来调整自身面板的显示
*
* @param event
*/
@Override
public void updateTreeSearchChange(TreeSearchStatusChangeEvent event) {
TreeSearchStatus treeSearchStatus = event.getTreeSearchStatus();
switchPane(treeSearchStatus == TreeSearchStatus.NOT_IN_SEARCH_MODE ? TOOLBAR_PANE : SEARCH_PANE);
}
}

38
designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataSearchMode.java

@ -0,0 +1,38 @@
package com.fr.design.data.datapane.management.search.searcher;
/**
* 搜索模式
*
* @author Yvan
*/
public enum TableDataSearchMode {
/**
* 搜索模板数据集
*/
TEMPLATE_TABLE_DATA(0),
/**
* 搜索服务器数据集
*/
SERVER_TABLE_DATA(1);
private final int mode;
TableDataSearchMode(int mode) {
this.mode = mode;
}
public int getMode() {
return mode;
}
public static TableDataSearchMode match(int mode) {
for (TableDataSearchMode searchMode : TableDataSearchMode.values()) {
if (searchMode.getMode() == mode) {
return searchMode;
}
}
return TEMPLATE_TABLE_DATA;
}
}

148
designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TableDataTreeSearcher.java

@ -0,0 +1,148 @@
package com.fr.design.data.datapane.management.search.searcher;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.data.TableDataSource;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.datapane.management.search.control.common.TableDataSearchCallBack;
import com.fr.design.data.datapane.management.search.control.common.TableDataSearchTask;
import com.fr.design.data.datapane.management.search.control.pre.TableDataPreSearchCallBack;
import com.fr.design.data.datapane.management.search.control.pre.TableDataPreSearchTask;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Yvan
*/
public class TableDataTreeSearcher implements TreeSearcher {
private ExecutorService executorService;
private Map<String, TableDataWrapper> allWrappers = new ConcurrentHashMap<>();
private final Set<String> calculatedSets = new HashSet<>();
private final Set<String> notCalculatedSets = new HashSet<>();
private final Set<String> matchSets = new HashSet<>();
private final Set<String> canExpandSets = new HashSet<>();
public TableDataTreeSearcher() {
}
public boolean isMatchSetsEmpty() {
return matchSets.isEmpty();
}
public int getAllWrappersSize() {
return allWrappers.size();
}
public synchronized void addToCalculatedSets(List<String> tableDataNames) {
for (String tableDataName : tableDataNames) {
TableDataWrapper tableDataWrapper = allWrappers.get(tableDataName);
if (tableDataWrapper == null) {
return;
}
calculatedSets.add(tableDataName);
}
}
public synchronized void addToMatchSets(List<String> matchNodeNames) {
matchSets.addAll(matchNodeNames);
}
public synchronized void addToCanExpandSets(List<String> canExpandNodeNames) {
canExpandSets.addAll(canExpandNodeNames);
}
/**
* 正式搜索前预加载一下数据集列名
*
* @param searchMode
* @param tableDataSource
*/
public void beforeSearch(TableDataSearchMode searchMode, TableDataSource tableDataSource) {
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new NamedThreadFactory(TableDataTreeSearcher.class));
collectTableDataWrappers(searchMode, tableDataSource);
preCalculateColumns();
}
/**
* 预先对数据集进行取列名的操作提升用户搜索体验
*/
private void preCalculateColumns() {
for (String notCalculatedSet : notCalculatedSets) {
TableDataWrapper tableDataWrapper = allWrappers.get(notCalculatedSet);
if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() == TreeSearchStatus.SEARCH_NOT_BEGIN) {
executorService.execute(new TableDataPreSearchTask(new TableDataPreSearchCallBack(this), tableDataWrapper));
}
}
}
/**
* 收集下此次搜索需要进行取数的TableDataWrapper
*
* @param searchSubject
* @param tableDataSource
*/
private void collectTableDataWrappers(TableDataSearchMode searchSubject, TableDataSource tableDataSource) {
Map<String, TableDataWrapper> dataSet = searchSubject == TableDataSearchMode.TEMPLATE_TABLE_DATA ?
DesignTableDataManager.getTemplateDataSet(tableDataSource) :
DesignTableDataManager.getGlobalDataSet();
// 转化一下存储过程
Map<String, TableDataWrapper> setIncludingProcedure = DesignTableDataManager.getAllDataSetIncludingProcedure(dataSet);
notCalculatedSets.addAll(setIncludingProcedure.keySet());
allWrappers.putAll(setIncludingProcedure);
}
@Override
public void startSearch(String searchText) {
reset();
for (String notCalculatedSet : notCalculatedSets) {
TableDataWrapper tableDataWrapper = allWrappers.get(notCalculatedSet);
if (TableDataTreeSearchManager.getInstance().getTreeSearchStatus() == TreeSearchStatus.SEARCHING) {
executorService.execute(new TableDataSearchTask(searchText, tableDataWrapper, new TableDataSearchCallBack(this)));
}
}
}
@Override
public void stopSearch() {
}
@Override
public void completeSearch() {
}
private void reset() {
matchSets.clear();
canExpandSets.clear();
calculatedSets.clear();
notCalculatedSets.addAll(allWrappers.keySet());
}
public void afterSearch() {
allWrappers.clear();
executorService.shutdownNow();
}
public boolean nodeMatches(String dsName) {
return matchSets.contains(dsName);
}
public boolean nodeCanExpand(String dsName) {
return canExpandSets.contains(dsName);
}
}

28
designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearchStatus.java

@ -0,0 +1,28 @@
package com.fr.design.data.datapane.management.search.searcher;
/**
* @author Yvan
*/
public enum TreeSearchStatus {
/**
* 非搜索模式
*/
NOT_IN_SEARCH_MODE,
/**
* 搜索未开始
*/
SEARCH_NOT_BEGIN,
/**
* 搜索中
*/
SEARCHING,
/**
* 搜索已停止
*/
SEARCH_STOPPED,
/**
* 搜索已完成
*/
SEARCH_COMPLETED;
}

27
designer-base/src/main/java/com/fr/design/data/datapane/management/search/searcher/TreeSearcher.java

@ -0,0 +1,27 @@
package com.fr.design.data.datapane.management.search.searcher;
/**
* 用于搜索RefreshableJTree数据的搜索器
*
* @author Yvan
*/
public interface TreeSearcher {
/**
* 开始搜索
*
* @param text
*/
void startSearch(String text);
/**
* 停止搜索
*/
void stopSearch();
/**
* 搜索完成
*/
void completeSearch();
}

82
designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java

@ -0,0 +1,82 @@
package com.fr.design.data.datapane.management.search.view;
import com.fr.design.data.datapane.TableDataTree;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
import java.awt.Component;
import java.util.regex.Pattern;
/**
* @author Yvan
*/
public class TreeSearchRendererHelper {
/**
* 缓存下原来的渲染器
*/
private TreeCellRenderer originTreeCellRenderer;
public TreeSearchRendererHelper() {
}
public TreeCellRenderer getOriginTreeCellRenderer() {
return originTreeCellRenderer;
}
public void setOriginTreeCellRenderer(TreeCellRenderer originTreeCellRenderer) {
this.originTreeCellRenderer = originTreeCellRenderer;
}
public void replaceTreeRenderer(TableDataTree tableDataTree, String searchText) {
tableDataTree.setCellRenderer(getNewTreeCellRenderer(searchText));
}
public void save(TableDataTree tableDataTree) {
if (getOriginTreeCellRenderer() == null) {
setOriginTreeCellRenderer(tableDataTree.getTableDataTreeCellRenderer());
}
}
public void restore(TableDataTree tableDataTree) {
if (getOriginTreeCellRenderer() != null) {
tableDataTree.setCellRenderer(getOriginTreeCellRenderer());
}
}
/**
* 获取新树渲染器也就是搜索结果树的TreeCellRenderer主要是为了文本高亮
*
* @param searchText
* @return
*/
private TreeCellRenderer getNewTreeCellRenderer(String searchText) {
return new DefaultTreeCellRenderer() {
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component treeCellRendererComponent = getOriginTreeCellRenderer().getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if (treeCellRendererComponent instanceof DefaultTreeCellRenderer) {
DefaultTreeCellRenderer defaultTreeCellRenderer = (DefaultTreeCellRenderer) treeCellRendererComponent;
String text = defaultTreeCellRenderer.getText();
defaultTreeCellRenderer.setText(getHighlightText(text, searchText));
}
return treeCellRendererComponent;
}
};
}
private String getHighlightText(String text, String textToHighlight) {
String highLightTemplate = "<font color=\"blue\">$1</font>";
if (textToHighlight.length() == 0) {
return text;
}
try {
text = text.replaceAll("(?i)(" + Pattern.quote(textToHighlight) + ")", highLightTemplate);
} catch (Exception e) {
return text;
}
text = "<html>" + text + "</html>";
return text;
}
}

159
designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java

@ -0,0 +1,159 @@
package com.fr.design.data.tabledata.paste;
import com.fr.base.TableData;
import com.fr.data.TableDataSource;
import com.fr.design.DesignModelAdapter;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
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.form.data.DataBinding;
import com.fr.form.data.DataTableConfig;
import com.fr.form.ui.DataControl;
import com.fr.form.ui.DictionaryContainer;
import com.fr.form.ui.Widget;
import com.fr.form.ui.concept.data.ValueInitializer;
import com.fr.report.cell.tabledata.ElementUsedTableDataProvider;
import com.fr.stable.StringUtils;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 数据集跟随复制粘贴的工具类
*
* @author Yvan
*/
public class TableDataFollowingPasteUtils {
/**
* 粘贴所有Map中的tabledata到当前模板
*
* @param tableDataWrapperMap
*/
public static void paste(Map<String, TableData> tableDataWrapperMap) {
if (tableDataWrapperMap == null) {
return;
}
// 获取当前的TableDataTreePane
DesignModelAdapter<?, ?> currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter();
TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstance(currentModelAdapter);
// 粘贴(添加)数据集
for (Map.Entry<String, TableData> dataWrapperEntry : tableDataWrapperMap.entrySet()) {
String dsName = dataWrapperEntry.getKey();
// 处理名称重复情况
if (isDsNameRepeated(dsName)) {
continue;
}
AbstractTableDataWrapper tableDataWrapper = new TemplateTableDataWrapper(dataWrapperEntry.getValue(), dsName);
AbstractTableDataPane<?> tableDataPane = tableDataWrapper.creatTableDataPane();
tableDataTreePane.addDataPane(tableDataPane, dsName);
}
}
private static boolean isDsNameRepeated(String dsName) {
DesignModelAdapter<?, ?> currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter();
String[] allDSNames = DesignTableDataManager.getAllDSNames(currentModelAdapter.getBook());
return Arrays.stream(allDSNames).anyMatch(name -> StringUtils.equals(name, dsName));
}
/**
* 处理 ElementUsedTableDataProvider从中获取数据集名称 - 数据集Wrapper 的Map
*
* @param providers
* @return
*/
public static Map<String, TableData> transferProvider2TableDataMap(ElementUsedTableDataProvider... providers) {
if (providers == null) {
return new HashMap<>();
}
// 获取当前的所有模板数据集
Map<String, TableDataWrapper> templateTableData = getCurrentTemplateTableDataWrapper();
Map<String, TableData> resultMap = new HashMap<>();
for (ElementUsedTableDataProvider tableDataProvider : providers) {
Set<String> usedTableDataNames = tableDataProvider.getElementUsedTableDataNames();
for (String usedTableDataName : usedTableDataNames) {
if (templateTableData.containsKey(usedTableDataName)) {
resultMap.put(usedTableDataName, templateTableData.get(usedTableDataName).getTableData());
}
}
}
return resultMap;
}
/**
* 提取控件内使用的数据集转化成Map返回
*
* @param widgets
* @return
*/
public static Map<String, TableData> transferWidgetArray2TableDataMap(Widget... widgets) {
if (widgets == null) {
return new HashMap<>();
}
// 获取当前的所有模板数据集
Map<String, TableDataWrapper> templateTableData = getCurrentTemplateTableDataWrapper();
Map<String, TableData> resultMap = new HashMap<>();
for (Widget widget : widgets) {
collectTableDataInDictionary(templateTableData, resultMap, widget);
collectTableDataInWidgetValue(templateTableData, resultMap, widget);
}
return resultMap;
}
/**
* 收集控件值中的TableData
*
* @param templateTableData
* @param resultMap
* @param widget
*/
private static void collectTableDataInWidgetValue(Map<String, TableDataWrapper> templateTableData, Map<String, TableData> resultMap, Widget widget) {
if (widget instanceof DataControl && ((DataControl) widget).getWidgetValue() != null) {
ValueInitializer widgetValue = ((DataControl) widget).getWidgetValue();
Object value = widgetValue.getValue();
if (value instanceof DataBinding) {
String dataSourceName = ((DataBinding) value).getDataSourceName();
if (templateTableData.containsKey(dataSourceName)) {
resultMap.put(dataSourceName, templateTableData.get(dataSourceName).getTableData());
}
}
if (value instanceof DataTableConfig) {
String tableDataName = ((DataTableConfig) value).getTableDataName();
if (templateTableData.containsKey(tableDataName)) {
resultMap.put(tableDataName, templateTableData.get(tableDataName).getTableData());
}
}
}
}
/**
* 收集控件-数据字典中的TableData
*
* @param templateTableData
* @param resultMap
* @param widget
*/
private static void collectTableDataInDictionary(Map<String, TableDataWrapper> templateTableData, Map<String, TableData> resultMap, Widget widget) {
if (widget instanceof DictionaryContainer) {
Set<String> usedTableDataSets = ((DictionaryContainer) widget).getUsedTableDataSets();
for (String usedTableDataSet : usedTableDataSets) {
if (templateTableData.containsKey(usedTableDataSet)) {
resultMap.put(usedTableDataSet, templateTableData.get(usedTableDataSet).getTableData());
}
}
}
}
private static Map<String, TableDataWrapper> getCurrentTemplateTableDataWrapper() {
TableDataSource tableDataSource = DesignTableDataManager.getEditingTableDataSource();
List<Map<String, TableDataWrapper>> editingDataSet = DesignTableDataManager.getEditingDataSet(tableDataSource);
return editingDataSet.get(0);
}
}

109
designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java

@ -63,26 +63,27 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName) {
this(component, storeProcedure, storeprocedureName, dsName, true);
}
/**
* @param: component loadingBar的父弹框如果不设置父弹框的话可能出现loadingBar隐藏在一个弹框后的情况
* @param: storeProcedure 存储过程
* @param: storeprocedureName 存储过程的名字(某些情况下可以为空)
* @param: dsName 存储过程一个返回数据集的名字
* @param: needLoad 是否要加载
* @param component loadingBar的父弹框如果不设置父弹框的话可能出现loadingBar隐藏在一个弹框后的情况
* @param storeProcedure 存储过程
* @param storeprocedureName 存储过程的名字(某些情况下可以为空)
* @param dsName 存储过程一个返回数据集的名字
* @param needLoad 是否要加载
**/
public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName, boolean needLoad) {
this.dsName = dsName;
this.storeProcedure = storeProcedure;
this.storeProcedure.setCalculating(false);
this.storeprocedureName = storeprocedureName;
if (needLoad) {
setWorker();
}
if (component == null) {
component = new JFrame();
}
if (needLoad) {
setWorker(component);
}
loadingBar = new AutoProgressBar(component, Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) {
@Override
public void doMonitorCanceled() {
getWorker().cancel(true);
}
@ -93,16 +94,17 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
* 数据集执行结果返回的所有字段
*
* @return 数据集执行结果返回的所有字段
*
*
* @date 2014-12-3-下午7:43:17
*
*/
* @date 2014-12-3-下午7:43:17
*/
@Override
public List<String> calculateColumnNameList() {
if (columnNameList != null) {
return columnNameList;
}
if (!createStore(false)) {
try {
createStore(false);
} catch (Exception e) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Engine_No_TableData"));
return new ArrayList<String>();
}
@ -114,11 +116,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
* 生成子节点
*
* @return 节点数组
*
*
* @date 2014-12-3-下午7:06:47
*
*/
* @date 2014-12-3-下午7:06:47
*/
@Override
public ExpandMutableTreeNode[] load() {
List<String> namelist;
if (storeProcedure.isCalculating()) {
@ -134,23 +134,16 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
return res;
}
private boolean createStore(boolean needLoadingBar) {
try {
dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar);
if (dataModels == null || dataModels.length == 0) {
return false;
}
for (int i = 0; i < dataModels.length; i++) {
if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModels[i].getName())) {
procedureDataModel = dataModels[i];
private void createStore(boolean needLoadingBar) throws Exception {
dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar);
if (dataModels != null && dataModels.length != 0) {
for (ProcedureDataModel dataModel : dataModels) {
if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModel.getName())) {
procedureDataModel = dataModel;
break;
}
}
return true;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
@Override
@ -159,17 +152,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
}
/**
* 预览数据
*
* @param previewModel 预览模式, 全部还是一个
*
*
* @date 2014-12-3-下午7:05:50
*
*/
* 预览数据
*
* @param previewModel 预览模式, 全部还是一个
* @date 2014-12-3-下午7:05:50
*/
public void previewData(final int previewModel) {
this.previewModel = previewModel;
connectionBar = new AutoProgressBar(new JFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Now_Create_Connection"), "", 0, 100) {
@Override
public void doMonitorCanceled() {
connectionBar.close();
worker.cancel(true);
@ -178,8 +169,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
worker.execute();
}
private void setWorker() {
private void setWorker(final Component parent) {
worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
loadingBar.close();
PreviewTablePane.resetPreviewTable();
@ -195,6 +187,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
return null;
}
@Override
public void done() {
try {
get();
@ -206,13 +199,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
case StoreProcedureDataWrapper.PREVIEW_ONE:
previewData();
break;
default:
break;
}
} catch (Exception e) {
loadingBar.close();
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage());
FineJOptionPane.showMessageDialog(parent, e.getMessage());
}
loadingBar.close();
}
}
};
@ -227,10 +222,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
/**
* 预览返回的一个数据集
*
*
* @date 2014-12-3-下午7:42:53
*
*/
* @date 2014-12-3-下午7:42:53
*/
@Override
public void previewData() {
previewData(-1, -1);
}
@ -240,13 +234,11 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
/**
* 预览返回的一个数据集带有显示值和实际值的标记结果
*
* @param keyIndex 实际值
* @param valueIndex 显示值
*
*
* @date 2014-12-3-下午7:42:27
*
*/
* @param keyIndex 实际值
* @param valueIndex 显示值
* @date 2014-12-3-下午7:42:27
*/
@Override
public void previewData(final int keyIndex, final int valueIndex) {
PreviewTablePane.previewStoreData(procedureDataModel, keyIndex, valueIndex);
}
@ -257,7 +249,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
*/
public void previewAllTable() {
if (procedureDataModel == null) {
if (!createStore(true)) {
try {
createStore(true);
} catch (Exception e) {
return;
}
}
@ -269,6 +263,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
return dsName;
}
@Override
public TableData getTableData() {
return storeProcedure;
}
@ -282,10 +277,12 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
*
* @return 是否异常
*/
@Override
public boolean isUnusual() {
return false;
}
@Override
public boolean equals(Object obj) {
return obj instanceof StoreProcedureDataWrapper
&& ComparatorUtils.equals(this.dsName, ((StoreProcedureDataWrapper) obj).getTableDataName())

4
designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java vendored

@ -1,8 +1,6 @@
package com.fr.design.env;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.stable.CoreConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
@ -10,8 +8,8 @@ import com.fr.stable.project.ProjectConstants;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import com.fr.workspace.engine.exception.MainVersionNotMatchException;
import java.io.File;
import java.util.Properties;

23
designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java

@ -1,6 +1,6 @@
package com.fr.design.extra;
import com.fr.base.FRContext;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.PluginResourceLoader;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.dialog.UIDialog;
@ -15,12 +15,12 @@ import com.fr.general.IOUtils;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.PluginStoreConfig;
import com.fr.plugin.PluginStoreConstants;
import com.fr.stable.CommonUtils;
import com.fr.stable.EnvChangedListener;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
@ -44,15 +44,15 @@ public class WebViewDlgHelper {
private static final String LATEST = "latest";
private static final String SHOP_SCRIPTS = "shop_scripts";
private static final int VERSION_8 = 8;
private static String installHome = FRContext.getCommonOperator().getWebRootPath();
private static String installHome = PluginStoreConstants.getLocalInstallHome();
private static final String MAIN_JS_PATH = "/scripts/plugin.html";
private static final String ENV_VERSION = "ENV_VERSION";
static {
GeneralContext.addEnvChangedListener(new EnvChangedListener() {
@Override
public void envChanged() {
installHome = FRContext.getCommonOperator().getWebRootPath();
installHome = PluginStoreConstants.getLocalInstallHome();
PluginResourceLoader.INSTANCE.checkOldShopFile();
}
});
}
@ -74,8 +74,11 @@ public class WebViewDlgHelper {
}
return;
}
String jar_version = PluginStoreConstants.getProps(ENV_VERSION, StringUtils.EMPTY);
if (ComparatorUtils.equals(jar_version, ProductConstants.VERSION)) {
// 检测更新前先刷新一下版本号
PluginStoreConstants.refreshProps();
String jarVersion = PluginStoreConfig.getInstance().getEnvVersion();
if (ComparatorUtils.equals(jarVersion, ProductConstants.VERSION)) {
updateShopScripts(SHOP_SCRIPTS);
showPluginDlg();
} else {
@ -133,7 +136,7 @@ public class WebViewDlgHelper {
*
* @param filePath 待删除文件路径
*/
private static void deleteExtraFile(String filePath){
private static void deleteExtraFile(String filePath) {
CommonIOUtils.deleteFile(new File(filePath));
}
@ -259,7 +262,7 @@ public class WebViewDlgHelper {
try {
if (get()) {
File scriptZip = new File(StableUtils.pathJoin(PluginConstants.DOWNLOAD_PATH, PluginConstants.TEMP_FILE));
if(scriptZip.exists()){
if (scriptZip.exists()) {
IOUtils.unzip(scriptZip, installHome);
CommonUtils.deleteFile(scriptZip);
}
@ -283,7 +286,7 @@ public class WebViewDlgHelper {
protected Void doInBackground() throws Exception {
String url = CloudCenter.getInstance().acquireUrlByKind("shop.plugin.update");
if (url != null) {
String text = HttpToolbox.get(url + "?" + PluginUtils.FR_VERSION + "=" + ProductConstants.VERSION + "&version=" + PluginStoreConstants.getProps("VERSION"));
String text = HttpToolbox.get(url + "?" + PluginUtils.FR_VERSION + "=" + ProductConstants.VERSION + "&version=" + PluginStoreConfig.getInstance().getVersion());
JSONObject resultJSONObject = new JSONObject(text);
String isLatest = resultJSONObject.optString("result");
if (!ComparatorUtils.equals(isLatest, LATEST)) {

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

@ -14,6 +14,7 @@ import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.DialogActionListener;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.autocomplete.AutoCompleteExtraRefreshComponent;
@ -63,6 +64,7 @@ import com.fr.stable.script.Node;
import com.fr.stable.script.Tiny;
import com.fr.stable.script.TinyHunter;
import java.awt.Window;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
@ -736,6 +738,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Formula_Definition");
}
public BasicDialog showLargeWindow(Window window, DialogActionListener l) {
BasicDialog basicDialog = super.showWindowWithCustomSize(window, l, new Dimension(900, 600));
basicDialog.setMinimumSize(new Dimension(900, 600));
basicDialog.setResizable(true);
return basicDialog;
}
/**
* Populate
*/
@ -1102,6 +1111,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initGroupTypeModel() {
functionTypeListModel.addElement(FunctionConstants.COMMON);
functionTypeListModel.addElement(FunctionConstants.NEW);
for (int i = 0; i < FunctionConstants.EMBFUNCTIONS.length; i++) {
functionTypeListModel.addElement(FunctionConstants.EMBFUNCTIONS[i]);
}
@ -1186,9 +1196,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
descriptionTextArea = new UITextArea();
descriptionTextArea.setPreferredSize(new Dimension(350, 200));
UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea);
desScrollPane.setBorder(null);
this.add(this.createNamePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Formula_Description") + ":", desScrollPane), BorderLayout.EAST);
descriptionTextArea.setBackground(Color.white);
descriptionTextArea.setLineWrap(true);
descriptionTextArea.setWrapStyleWord(true);
@ -1256,12 +1263,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initVariablesTree() {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
// vairable.
variablesTree = new JTree();
UIScrollPane variablesTreePane = new UIScrollPane(variablesTree);
variablesTreePane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
this.add(this.createNamePane(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables") + ":", variablesTreePane), BorderLayout.CENTER);
panel.add(this.createNamePane(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables") + ":", variablesTreePane), BorderLayout.WEST);
variablesTree.setRootVisible(false);
variablesTree.setShowsRootHandles(true);
variablesTree.addMouseListener(applyTextMouseListener);
@ -1269,7 +1277,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
initDescriptionTextArea();
UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea);
desScrollPane.setBorder(null);
panel.add(this.createNamePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Formula_Description") + ":", desScrollPane), BorderLayout.CENTER);
initVariablesTreeSelectionListener();
this.add(panel,BorderLayout.CENTER);
}
private void initComponents() {

34
designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java

@ -5,10 +5,19 @@ import com.fr.function.AVERAGE;
import com.fr.function.CHAR;
import com.fr.function.COUNT;
import com.fr.function.DATE;
import com.fr.function.ENBYSTRNUM;
import com.fr.function.ENDOFMONTH;
import com.fr.function.GCD;
import com.fr.function.GETCHARNUM;
import com.fr.function.ISWORKDAY;
import com.fr.function.LCM;
import com.fr.function.MAX;
import com.fr.function.MIDCHAR;
import com.fr.function.MIN;
import com.fr.function.NUMTOZH;
import com.fr.function.RANGE;
import com.fr.function.SUM;
import com.fr.function.TEXTGETNUM;
import com.fr.function.TIME;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralUtils;
@ -36,6 +45,7 @@ import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -46,6 +56,8 @@ public final class FunctionConstants {
public static NameAndFunctionList COMMON = getCommonFunctionList();
public static NameAndTypeAndFunctionList[] EMBFUNCTIONS = getEmbededFunctionListArray();
public static FunctionGroup ALL = getAllFunctionGroup();
public static List<String> abandonFormulas = Arrays.asList("CIRCULAR", "CROSSLAYERTOTAL", "HIERARCHY", "LAYERTOTAL");
public static NameAndFunctionList NEW = getNewFunctionList();
static {
loadEmbededFunctions();
@ -54,7 +66,8 @@ public final class FunctionConstants {
/**
* Don't let anyone instantiate this class.
*/
private FunctionConstants() {}
private FunctionConstants() {
}
private static void loadEmbededFunctions() {
String pkgName = "com.fr.function";
@ -88,7 +101,10 @@ public final class FunctionConstants {
Class<?> cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6));
if (StableUtils.classInstanceOf(cls, iface)) {
Function inst;
inst = (Function)cls.newInstance();
inst = (Function) cls.newInstance();
if (abandonFormulas.contains(inst.getClass().getSimpleName())) {
continue;
}
for (NameAndTypeAndFunctionList EMBFUNCTION : EMBFUNCTIONS) {
if (EMBFUNCTION.test(inst)) {
break;
@ -270,6 +286,13 @@ public final class FunctionConstants {
});
}
private static NameAndFunctionList getNewFunctionList() {
return new NameAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_New"), new Function[]{
new ENDOFMONTH(), new NUMTOZH(), new MIDCHAR(), new ISWORKDAY(), new ENBYSTRNUM(), new TEXTGETNUM(),
new GETCHARNUM(), new GCD(), new LCM()
});
}
private static NameAndTypeAndFunctionList[] getEmbededFunctionListArray() {
return new NameAndTypeAndFunctionList[] {
new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Math_&_Trig"), Function.MATH),
@ -300,11 +323,12 @@ public final class FunctionConstants {
Collections.addAll(all, CUSTOM.getDescriptions());
//hugh:自定义函数分组
Set<Mutable> containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING);
if(!containers.isEmpty()){
for(Mutable container : containers){
Collections.addAll(all,createFunctionGroup(((FunctionDefContainer)container)).getDescriptions());
if (!containers.isEmpty()) {
for (Mutable container : containers) {
Collections.addAll(all, createFunctionGroup(((FunctionDefContainer) container)).getDescriptions());
}
}
all = all.stream().filter(n -> !abandonFormulas.contains(n.getName())).collect(Collectors.toList());
Collections.sort(all, new Comparator<NameAndDescription>() {
@Override

12
designer-base/src/main/java/com/fr/design/gui/controlpane/UIListControlPane.java

@ -34,6 +34,9 @@ public abstract class UIListControlPane extends UIControlPane implements ListCon
private CommonShortCutHandlers commonHandlers;
private ListControlPaneHelper helper;
// 目前被触发的事件
private ListDataEvent currentEvent;
public UIListControlPane() {
super();
@ -96,7 +99,9 @@ public abstract class UIListControlPane extends UIControlPane implements ListCon
nameableList.getModel().addListDataListener(new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent e) {
setCurrentEvent(e);
saveSettings();
setCurrentEvent(null);
}
@Override
@ -321,4 +326,11 @@ public abstract class UIListControlPane extends UIControlPane implements ListCon
}
public ListDataEvent getCurrentEvent() {
return currentEvent;
}
public void setCurrentEvent(ListDataEvent currentEvent) {
this.currentEvent = currentEvent;
}
}

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

@ -42,14 +42,10 @@ public class JTreeControlPane extends ControlPane {
private JTree tree;
private DefaultTreeModel defaultTreeModel;
boolean isEditor = false;
private UICheckBox isPerformanceFirst;
public JTreeControlPane(NameableCreator[] creators, BasicBeanPane updatePane, boolean isEditor) {
public JTreeControlPane(NameableCreator[] creators, BasicBeanPane updatePane) {
this.initComponents(creators, updatePane);
this.isEditor = isEditor;
}
private void initComponents(NameableCreator[] creators, BasicBeanPane updatePane) {
@ -120,11 +116,7 @@ public class JTreeControlPane extends ControlPane {
if (obj instanceof TreeNodeAttr[]) {
treeNodeAttr = ((TreeNodeAttr[]) obj);
isPerformanceFirst.setSelected(false);
} else if (obj instanceof TreeEditor) {
TreeEditor treeEditor = (TreeEditor) obj;
treeNodeAttr = treeEditor.getTreeNodeAttr();
isPerformanceFirst.setSelected(treeEditor.isPerformanceFirst());
} else if (obj instanceof TreeNodeWrapper) {
}else if (obj instanceof TreeNodeWrapper) {
treeNodeAttr = ((TreeNodeWrapper) obj).getTreeNodeAttrs();
isPerformanceFirst.setSelected(((TreeNodeWrapper) obj).isPerformanceFirst());
}
@ -146,18 +138,8 @@ public class JTreeControlPane extends ControlPane {
}
public NameObject update() {
if (isEditor) {
TreeEditor treeEditor = new TreeEditor();
treeEditor.setTreeNodeAttr(updateTreeNodeAttr());
treeEditor.setPerformanceFirst(isPerformanceFirst.isSelected());
return new NameObject("tree", treeEditor);
} else {
TreeNodeWrapper treeNodeWrapper = new TreeNodeWrapper(isPerformanceFirst.isSelected(), updateTreeNodeAttr());
return new NameObject("tree", treeNodeWrapper);
}
TreeNodeWrapper treeNodeWrapper = new TreeNodeWrapper(isPerformanceFirst.isSelected(), updateTreeNodeAttr());
return new NameObject("tree", treeNodeWrapper);
}
public TreeNodeAttr[] updateTreeNodeAttr() {

158
designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java

@ -26,12 +26,18 @@ import java.awt.event.ItemListener;
import java.util.Arrays;
public class TreeSettingPane extends BasicPane implements DataCreatorUI {
/**
* 普通分层构建方式
*/
private JTreeControlPane controlPane;
/**
* 自动构建方式
*/
private JTreeAutoBuildPane autoBuildPane;
/**
* 新的分层构建方式
* 急速分层构建方式
*/
private LayerDataControlPane layerDataControlPane;
@ -43,15 +49,15 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
private static final long serialVersionUID = 1762889323082827111L;
private String[] buildWay = new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DataTable_Build"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Auto_Build"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Build")};
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Auto_Build"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Build")};
public TreeSettingPane(boolean isEditor) {
this.initComponents(isEditor);
public TreeSettingPane() {
this.initComponents();
}
private void initComponents(boolean isEditor) {
private void initComponents() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel buildWayPanel= FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane();
JPanel buildWayPanel = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane();
buildWayPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
UILabel buildWayLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Build_Way") + " :");
buildWayPanel.add(buildWayLabel);
@ -65,8 +71,8 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
});
buildWayPanel.add(buildBox);
controlPane = new JTreeControlPane(new NameableCreator[] { treeNode },
new TreeDataCardPane(), isEditor);
controlPane = new JTreeControlPane(new NameableCreator[]{treeNode},
new TreeDataCardPane());
autoBuildPane = new JTreeAutoBuildPane();
layerDataControlPane = new LayerDataControlPane();
this.add(buildWayPanel, BorderLayout.NORTH);
@ -108,87 +114,14 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
}
NameableCreator treeNode = new NameObjectCreator(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradation"),
"/com/fr/design/images/data/source/jdbcTableData.png",
TreeNodeAttr.class);
/**
*
* @param treeEditor
*/
public void populate(TreeEditor treeEditor) {
boolean isAutoBuild = treeEditor.isAutoBuild();
TreeAttr treeAttr = treeEditor.getTreeAttr();
if (treeAttr != null) {
NameObject no = new NameObject("name", treeEditor);
controlPane.populate(no);
}
if (isAutoBuild) {
buildBox.setSelectedIndex(1);
TableDataDictionary dictionary = treeEditor.getDictionary();
autoBuildPane.populate(dictionary);
} else if (treeEditor.isFastLayerBuild()) {
buildBox.setSelectedIndex(0);
java.util.List<LayerConfig> layerConfigList = treeEditor.getLayerConfigs();
LayerConfig[] layerConfigs = new LayerConfig[layerConfigList.size()];
int i = 0;
for (LayerConfig layerConfig : layerConfigList) {
layerConfigs[i++] = layerConfig;
}
this.layerDataControlPane.populate(new NameObject("Tree Layer Data", layerConfigs));
} else {
buildBox.setSelectedIndex(2);
}
}
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradation"),
"/com/fr/design/images/data/source/jdbcTableData.png",
TreeNodeAttr.class);
/**
* 视图树的update
* @return
*/
public TreeEditor updateTreeEditor() {
// NameObject no = this.controlPane.update();
// if (no != null) {
// return ((TreeEditor) no.getObject());
// }
//
// return null;
TreeEditor te = new TreeEditor();
if (buildBox.getSelectedIndex() == 1) {
TableDataDictionary dictionary = this.autoBuildPane.update();
te.setAutoBuild(true);
te.setFastLayerBuild(false);
te.setDictionary(dictionary);
te.setNodeOrDict(dictionary);
} else if (buildBox.getSelectedIndex() == 2) {
te.setAutoBuild(false);
te.setFastLayerBuild(false);
NameObject no = this.controlPane.update();
if (no != null) {
TreeEditor editor = (TreeEditor) no.getObject();
te.setAllowBlank(editor.isAllowBlank());
te.setEnabled(editor.isEnabled());
te.setDirectEdit(editor.isDirectEdit());
te.setErrorMessage(editor.getErrorMessage());
te.setWidgetName(editor.getWidgetName());
te.setVisible(editor.isVisible());
te.setWaterMark(editor.getWaterMark());
te.setRemoveRepeat(editor.isRemoveRepeat());
te.setTreeAttr(editor.getTreeAttr());
te.setTreeNodeAttr(editor.getTreeNodeAttr());
te.setNodeOrDict(editor.getTreeNodeAttr());
te.setPerformanceFirst(editor.isPerformanceFirst());
}
} else {
LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject();
te.setAutoBuild(false);
te.setFastLayerBuild(true);
te.setLayerConfigs(Arrays.asList(configs));
}
return te;
}
/**
* 树节点属性的update
*
* @return
*/
public Object updateTreeNodeAttrs() {
@ -207,64 +140,19 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
}
/**
* 下拉树的update
* @return
*/
public TreeComboBoxEditor updateTreeComboBox() {
TreeComboBoxEditor tcb = new TreeComboBoxEditor();
if (buildBox.getSelectedIndex() == 1) {
TableDataDictionary dictionary = this.autoBuildPane.update();
tcb.setAutoBuild(true);
tcb.setFastLayerBuild(false);
tcb.setDictionary(dictionary);
tcb.setNodeOrDict(dictionary);
} else if (buildBox.getSelectedIndex() == 2) {
tcb.setAutoBuild(false);
tcb.setFastLayerBuild(false);
NameObject no = this.controlPane.update();
if (no != null) {
if (no.getObject() instanceof TreeComboBoxEditor) {
return (TreeComboBoxEditor) no.getObject();
}
TreeEditor editor = (TreeEditor) no.getObject();
tcb.setAllowBlank(editor.isAllowBlank());
tcb.setEnabled(editor.isEnabled());
tcb.setDirectEdit(editor.isDirectEdit());
tcb.setErrorMessage(editor.getErrorMessage());
tcb.setWidgetName(editor.getWidgetName());
tcb.setVisible(editor.isVisible());
tcb.setWaterMark(editor.getWaterMark());
tcb.setRemoveRepeat(editor.isRemoveRepeat());
tcb.setTreeAttr(editor.getTreeAttr());
tcb.setTreeNodeAttr(editor.getTreeNodeAttr());
tcb.setNodeOrDict(editor.getTreeNodeAttr());
tcb.setPerformanceFirst(editor.isPerformanceFirst());
}
}else {
LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject();
tcb.setAutoBuild(false);
tcb.setFastLayerBuild(true);
tcb.setLayerConfigs(Arrays.asList(configs));
}
return tcb;
}
/**
*
* @param nodeOrDict
*/
public void populate(Object nodeOrDict) {
if(nodeOrDict instanceof TreeNodeAttr[] || nodeOrDict instanceof TreeNodeWrapper) {
if (nodeOrDict instanceof TreeNodeAttr[] || nodeOrDict instanceof TreeNodeWrapper) {
buildBox.setSelectedIndex(2);
NameObject no = new NameObject("name", nodeOrDict);
controlPane.populate(no);
} else if(nodeOrDict instanceof TableDataDictionary) {
} else if (nodeOrDict instanceof TableDataDictionary) {
buildBox.setSelectedIndex(1);
autoBuildPane.populate((TableDataDictionary)nodeOrDict);
} else if (nodeOrDict instanceof NameObject) {
autoBuildPane.populate((TableDataDictionary) nodeOrDict);
} else if (nodeOrDict instanceof LayerConfig[]) {
buildBox.setSelectedIndex(0);
layerDataControlPane.populate((NameObject) nodeOrDict);
layerDataControlPane.populate((LayerConfig[]) nodeOrDict);
}
}
}

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

@ -179,7 +179,7 @@ public class LayerDataControlPane extends ControlPane {
public void actionPerformed(ActionEvent e) {
// TODO remove tree node
int val = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?",
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val != JOptionPane.OK_OPTION) {
return;
}
@ -193,36 +193,32 @@ public class LayerDataControlPane extends ControlPane {
}
}
public void populate(NameObject nameObject) {
public void populate(LayerConfig[] layerConfigs) {
// 重新添加tree节点的时候需要remove掉原来的所有子节点
((DefaultMutableTreeNode) defaultTreeModel.getRoot()).removeAllChildren();
if (BEAN_NAME.equals(nameObject.getName())) {
Object obj = nameObject.getObject();
LayerConfig[] layerConfigs = null;
if (obj instanceof LayerConfig[]) {
layerConfigs = ((LayerConfig[]) obj);
}
if (layerConfigs == null) {
return;
}
int count = layerConfigs == null ? 0 : layerConfigs.length;
//将树的层次一层一层的加上去
DefaultMutableTreeNode node4root = (DefaultMutableTreeNode) defaultTreeModel.getRoot();
for (int i = 0; i < count; i++) {
int count = layerConfigs.length;
//将树的层次一层一层的加上去
DefaultMutableTreeNode node4root = (DefaultMutableTreeNode) defaultTreeModel.getRoot();
for (int i = 0; i < count; i++) {
DefaultMutableTreeNode node4add = new DefaultMutableTreeNode(
DefaultMutableTreeNode node4add = new DefaultMutableTreeNode(
new NameObject(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Gradation") + (i + 1), layerConfigs[i].clone()));
node4root.add(node4add);
node4root = node4add;
}
defaultTreeModel.reload();
expandAll(tree, true);
tree.setSelectionRow(0);
node4root.add(node4add);
node4root = node4add;
}
defaultTreeModel.reload();
expandAll(tree, true);
tree.setSelectionRow(0);
}
public NameObject update() {
public LayerConfig[] update() {
return new NameObject(BEAN_NAME, updateLayerDatas());
return updateLayerDatas();
}
private LayerConfig[] updateLayerDatas() {

7
designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java

@ -154,6 +154,13 @@ public abstract class RefreshableJTree extends CheckBoxTree {
refresh((ExpandMutableTreeNode) this.getModel().getRoot(), childName);
}
/**
* 刷新树用于搜索结果的展示
*/
public void refresh4TreeSearch() {
}
/*
* 刷新expandRoot节点下所有已打开的节点的UserObject,并打开isExpanded为true的TreeNode
*/

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

@ -58,8 +58,9 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
private static final Integer[] TYPES = new Integer[]{
FormatContents.NULL, FormatContents.NUMBER,
FormatContents.CURRENCY, FormatContents.PERCENT,
FormatContents.SCIENTIFIC, FormatContents.DATE,
FormatContents.TIME, FormatContents.TEXT};
FormatContents.THOUSANDTHS, FormatContents.SCIENTIFIC,
FormatContents.DATE, FormatContents.TIME,
FormatContents.TEXT};
private static final Integer[] DATE_TYPES = new Integer[]{FormatContents.NULL, FormatContents.DATE, FormatContents.TIME};

5823
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java

File diff suppressed because it is too large Load Diff

26
designer-base/src/main/java/com/fr/design/login/socketio/LoginAuthServer.java

@ -1,5 +1,6 @@
package com.fr.design.login.socketio;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.DesignerEnvManager;
import com.fr.design.login.DesignerLoginType;
import com.fr.design.login.bean.BBSAccountLogin;
@ -11,7 +12,11 @@ import com.fr.third.socketio.Configuration;
import com.fr.third.socketio.SocketIOClient;
import com.fr.third.socketio.SocketIOServer;
import com.fr.third.socketio.listener.DataListener;
import java.net.URLDecoder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Lanlan
@ -19,9 +24,11 @@ import java.net.URLDecoder;
* Created by Lanlan on 2021/6/3
*/
public class LoginAuthServer {
private AtomicBoolean started = new AtomicBoolean(false);
private SocketIOServer server;
private static final String HOSTNAME = "localhost";
private static final int PORT = 41925;
@ -47,6 +54,23 @@ public class LoginAuthServer {
}
public void start() {
// 只运行一次,不在乎成不成功
if (started.compareAndSet(false, true)) {
asyncStart();
}
}
public void asyncStart() {
ExecutorService asyncService = Executors.newSingleThreadExecutor(new NamedThreadFactory(LoginAuthServer.class.getName(), true));
asyncService.submit(this::compatibleStart);
asyncService.shutdown();
}
@Deprecated
public void compatibleStart() {
try {
server.start();
} catch (Exception e) {

7
designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java

@ -10,7 +10,7 @@ import javax.swing.JComponent;
* Date: 13-7-15
* Time: 上午10:28
*/
public interface BaseJForm<T> extends JTemplateProvider<T> {
public interface BaseJForm<T> extends JTemplateProvider<T>, JDashboard {
String XML_TAG = "JForm";
int FORM_TAB = 0;
@ -58,4 +58,9 @@ public interface BaseJForm<T> extends JTemplateProvider<T> {
* @param ecContainer ElementCase所在container
*/
void tabChanged(int index, FormElementCaseContainerProvider ecContainer);
@Override
default void switchToDashBoardEditor() {
tabChanged(FORM_TAB);
}
}

26
designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java

@ -220,7 +220,7 @@ public class CenterRegionContainerPane extends JPanel {
*
* @param plus 工具条中相关信息
*/
protected void resetToolkitByPlus(ToolBarMenuDockPlus plus, ToolBarMenuDock ad) {
protected void resetToolkitByPlus(ToolBarMenuDockPlus plus, ToolBarMenuDock ad, ToolKitConfigStrategy strategy) {
resetCombineUpTooBar(ad.resetUpToolBar(plus), plus);
@ -230,28 +230,40 @@ public class CenterRegionContainerPane extends JPanel {
// 颜色,字体那些按钮的工具栏
toolbarPane.add(toolbarComponent = ad.resetToolBar(toolbarComponent, plus), BorderLayout.CENTER);
if (plus.hasToolBarPane()) {
if (strategy.hasToolBarPane(plus)) {
this.add(toolbarPane, BorderLayout.NORTH);
} else {
this.remove(toolbarPane);
}
if (strategy.hasTemplateTabPane(plus)) {
eastCenterPane.add(templateTabPane, BorderLayout.CENTER);
} else {
eastCenterPane.remove(templateTabPane);
}
if (strategy.hasCombineUp(plus)) {
eastCenterPane.add(combineUp, BorderLayout.NORTH);
} else {
eastCenterPane.remove(combineUp);
}
resetByDesignMode();
}
private void resetByDesignMode() {
if (DesignModeContext.isDuchampMode()) {
eastPane.remove(largeToolbar);
eastCenterPane.remove(templateTabPane);
centerTemplateCardPane.refresh(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate());
//移除新建模板按钮
templateTabPane.remove(newWorkBookPane);
} else {
eastPane.add(largeToolbar, BorderLayout.WEST);
eastCenterPane.add(templateTabPane, BorderLayout.CENTER);
}
templateTabPane.add(newWorkBookPane, BorderLayout.WEST);
}
}
JComponent getToolbarComponent() {
return this.toolbarComponent;

21
designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java

@ -0,0 +1,21 @@
package com.fr.design.mainframe;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
public class DefaultToolKitConfig implements ToolKitConfigStrategy {
@Override
public boolean hasTemplateTabPane(ToolBarMenuDockPlus plus) {
return !DesignModeContext.isDuchampMode();
}
@Override
public boolean hasCombineUp(ToolBarMenuDockPlus plus) {
return plus.hasToolBarPane();
}
@Override
public boolean hasToolBarPane(ToolBarMenuDockPlus plus) {
return plus.hasToolBarPane();
}
}

12
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java

@ -4,6 +4,7 @@
package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.base.OptimizeUtil;
import com.fr.design.DesignModelAdapter;
import com.fr.design.DesignerEnvManager;
import com.fr.design.ExtraDesignClassManager;
@ -42,6 +43,7 @@ import com.fr.design.lock.LockInfoDialog;
import com.fr.event.EventDispatcher;
import com.fr.exception.DecryptTemplateException;
import com.fr.exception.TplLockedException;
import com.fr.exit.ConfigToPropMigrator;
import com.fr.exit.DesignerExiter;
import com.fr.file.FILE;
import com.fr.file.FILEFactory;
@ -614,6 +616,10 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
* @param plus 工具条中相关信息
*/
public void resetToolkitByPlus(ToolBarMenuDockPlus plus) {
resetToolkitByPlus(plus, new DefaultToolKitConfig());
}
public void resetToolkitByPlus(ToolBarMenuDockPlus plus, ToolKitConfigStrategy strategy) {
if (plus == null) {
plus = ToolBarMenuDock.NULLAVOID;
@ -621,7 +627,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
NorthRegionContainerPane.getInstance().resetToolkitByPlus(plus, ad);
CenterRegionContainerPane.getInstance().resetToolkitByPlus(plus, ad);
CenterRegionContainerPane.getInstance().resetToolkitByPlus(plus, ad, strategy);
this.checkToolbarMenuEnable();
this.validate();
@ -1071,6 +1077,10 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
DesignerEnvManager.getEnvManager().setLastEastRegionContainerWidth(
EastRegionContainerPane.getInstance().getContainerWidth());
OptimizeUtil.open(() -> {
ConfigToPropMigrator.getInstance().execute();
});
DesignerEnvManager.getEnvManager().saveXMLFile();
}

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

@ -11,6 +11,7 @@ import com.fr.design.actions.UpdateAction;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.data.datapane.management.search.TableDataTreeSearchManager;
import com.fr.design.data.tabledata.ResponseDataSourceChange;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.FileOperations;
@ -244,6 +245,9 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
DesignModelAdapter.setCurrentModelAdapter(jt.getModel());
fireDSChanged();
if (TableDataTreeSearchManager.getInstance().isInSearchMode()) {
TableDataTreeSearchManager.getInstance().outOfSearchMode();
}
TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter());
HistoryTemplateListPane.getInstance().setCurrentEditingTemplate(jt);
//处理自动新建的模板

10
designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java

@ -0,0 +1,10 @@
package com.fr.design.mainframe;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/3/1
*/
public interface JDashboard {
void switchToDashBoardEditor();
}

27
designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java

@ -0,0 +1,27 @@
package com.fr.design.mainframe;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
public interface ToolKitConfigStrategy {
/**
* 展示tabpane
* @param plus
* @return
*/
boolean hasTemplateTabPane(ToolBarMenuDockPlus plus);
/**
* 展示模板操作按钮复制粘贴保存等
* @param plus
* @return
*/
boolean hasCombineUp(ToolBarMenuDockPlus plus);
/**
* 展示工具栏pane
* @param plus
* @return
*/
boolean hasToolBarPane(ToolBarMenuDockPlus plus);
}

2
designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java

@ -23,7 +23,7 @@ public class AccessibleTreeModelEditor extends UneditableAccessibleEditor {
@Override
protected void showEditorPane() {
if (treeSettingPane == null) {
treeSettingPane = new TreeSettingPane(false);
treeSettingPane = new TreeSettingPane();
}
BasicDialog dlg = treeSettingPane.showWindow(SwingUtilities.getWindowAncestor(this));
treeSettingPane.populate(getValue());

5
designer-base/src/main/java/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java

@ -6,8 +6,7 @@ import com.fr.data.impl.TreeNodeWrapper;
import com.fr.design.Exception.ValidationException;
import com.fr.design.designer.properties.Decoder;
import com.fr.design.designer.properties.Encoder;
import com.fr.general.NameObject;
import com.fr.form.ui.tree.LayerConfig;
import com.fr.stable.StringUtils;
public class TreeModelWrapper implements Encoder, Decoder {
@ -22,7 +21,7 @@ public class TreeModelWrapper implements Encoder, Decoder {
} else if (v instanceof TreeNodeWrapper) {
TreeNodeAttr[] treeNodeAttrs = ((TreeNodeWrapper) v).getTreeNodeAttrs();
return TemplateUtils.render(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Total_N_Grade"), new String[]{"N"}, new String[]{treeNodeAttrs.length + ""});
} else if (v instanceof NameObject) {
} else if (v instanceof LayerConfig[]) {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DataTable_Build");
} else {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Auto_Build");

45
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java

@ -0,0 +1,45 @@
package com.fr.design.record.analyzer;
import com.fr.design.record.analyzer.advice.TimeAdvice;
import com.fr.design.record.analyzer.advice.TrackAdvice;
import com.fr.record.analyzer.AnalyzerConfiguration;
import com.fr.record.analyzer.AnalyzerUnit;
import com.fr.record.analyzer.Assistant;
import com.fr.record.analyzer.Metrics;
import com.fr.record.analyzer.Track;
import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory;
import com.fr.stable.ArrayUtils;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.description.type.TypeDescription;
import com.fr.third.net.bytebuddy.dynamic.DynamicType;
import com.fr.third.net.bytebuddy.matcher.ElementMatchers;
import com.fr.third.net.bytebuddy.utility.JavaModule;
/**
* created by Harrison on 2022/03/08
**/
public class DesignerAnalyzer {
private static final AnalyzerUnit ANALYZER = new AnalyzerUnit();
public static synchronized void init(AnalyzerAssemblyFactory factory, AnalyzerConfiguration... configurations) {
AnalyzerAssemblyFactory redefineFactory = factory.prepare(DesignerAssemblyFactory.getInstance());
AnalyzerConfiguration defaultConfiguration = AnalyzerConfiguration.create(new Assistant() {
@Override
public DynamicType.Builder<?> supply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
return builder
.visit(Advice.to(TimeAdvice.class).on(ElementMatchers.isAnnotatedWith(Metrics.class)))
.visit(Advice.to(TrackAdvice.class).on(ElementMatchers.isAnnotatedWith(Track.class)));
}
});
AnalyzerConfiguration[] allConfigurations = ArrayUtils.add(configurations, defaultConfiguration);
// 准备监听
ANALYZER.setAgentListener(new DesignerAnalyzerListener());
ANALYZER.init(redefineFactory, allConfigurations);
}
}

131
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java

@ -0,0 +1,131 @@
package com.fr.design.record.analyzer;
import com.fr.base.OptimizeUtil;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.record.analyzer.advice.DBMonitorAdvice;
import com.fr.design.record.analyzer.advice.FaultToleranceAdvice;
import com.fr.design.record.analyzer.advice.FocusAdvice;
import com.fr.design.record.analyzer.advice.MonitorAdvice;
import com.fr.design.record.analyzer.advice.PerformancePointAdvice;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.intelli.metrics.Compute;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.PerformancePoint;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.record.analyzer.AnalyzerConfiguration;
import com.fr.record.analyzer.AnalyzerKey;
import com.fr.record.analyzer.DBMetrics;
import com.fr.record.analyzer.FineAnalyzer;
import com.fr.record.analyzer.advice.AnalyzerAdviceKey;
import com.fr.record.analyzer.advice.FineAdviceAssistant;
import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory;
import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory;
import com.fr.stable.collections.CollectionUtils;
import com.fr.third.net.bytebuddy.matcher.ElementMatchers;
import com.fr.tolerance.FaultTolerance;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* created by Harrison on 2022/03/04
**/
public class DesignerAnalyzerActivator extends Activator implements Prepare {
@Override
public void start() {
OptimizeUtil.open(() -> {
AnalyzerAssemblyFactory basicFactory = createBasicFactory();
// 兼容逻辑
List<AnalyzerConfiguration> backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY);
if (!CollectionUtils.isEmpty(backwardsConfigurations)) {
// 直接初始化,不添加默认值,防止和下面的冲突
FineAnalyzer.initDirectly(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0]));
}
// 等页面完全打开后,再进行 retransform, 别影响了启动速度
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true));
try {
// 加入 retransform 部分的逻辑
List<FineAdviceAssistant> adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY);
if (!CollectionUtils.isEmpty(adviceConfigurations)) {
AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations);
es.submit(() -> {
DesignerAnalyzer.init(basicFactory, configurations);
});
}
} finally {
es.shutdown();
}
}
});
});
}
@NotNull
private AnalyzerConfiguration[] convertConfigurations(List<FineAdviceAssistant> list) {
return list.stream()
.map(AnalyzerConfiguration::create)
.toArray(AnalyzerConfiguration[]::new);
}
@Override
public void stop() {
}
@Override
public void prepare() {
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(Focus.class),
FocusAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(Compute.class),
MonitorAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(DBMetrics.class),
DBMonitorAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(PerformancePoint.class),
PerformancePointAdvice.class
));
addMutable(AnalyzerAdviceKey.KEY, FineAdviceAssistant.create(
ElementMatchers.isAnnotatedWith(FaultTolerance.class),
FaultToleranceAdvice.class
));
}
private AnalyzerAssemblyFactory createBasicFactory() {
AnalyzerAssemblyFactory factory = findSingleton(AnalyzerAssemblyFactory.class);
FineAnalyzerAssemblyFactory basicFactory = new FineAnalyzerAssemblyFactory();
basicFactory.prepare(factory);
return basicFactory;
}
}

12
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerAdvice.java

@ -0,0 +1,12 @@
package com.fr.design.record.analyzer;
import com.fr.record.analyzer.advice.AnalyzerAdvice;
/**
* 仅作为标志
* 没有方法
*
* created by Harrison on 2022/03/04
**/
public interface DesignerAnalyzerAdvice extends AnalyzerAdvice {
}

23
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerListener.java

@ -0,0 +1,23 @@
package com.fr.design.record.analyzer;
import com.fr.log.FineLoggerFactory;
import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder;
import com.fr.third.net.bytebuddy.description.type.TypeDescription;
import com.fr.third.net.bytebuddy.dynamic.DynamicType;
import com.fr.third.net.bytebuddy.utility.JavaModule;
/**
* created by Harrison on 2022/03/08
**/
public class DesignerAnalyzerListener extends AgentBuilder.Listener.Adapter {
@Override
public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) {
FineLoggerFactory.getLogger().debug("Designer-Analyzer transform successfully:{}", typeDescription);
}
@Override
public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) {
FineLoggerFactory.getLogger().error("Designer-Analyzer transform error:" + typeName);
}
}

91
designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java

@ -0,0 +1,91 @@
package com.fr.design.record.analyzer;
import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory;
import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder;
import java.util.List;
import java.util.Map;
/**
* 装配 Agent 为后置启动
* <p>必须在一个线程中处理 retransform 的事务否则会阻塞整个的线程导致效果不佳</p>
*
* created by Harrison on 2022/03/07
**/
public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory<Void> {
/**
* 每次执行 1 class retransform
*/
private static final int FIXED_SIZE = 1;
/**
* 单位 ms
* 每次间隔 500 ms, 执行一次
*/
private static final int DELAY_INTERVAL = 500;
private final AgentBuilder.RedefinitionStrategy.BatchAllocator batchAllocator = AgentBuilder.RedefinitionStrategy.BatchAllocator.ForFixedSize.ofSize(FIXED_SIZE);
private final AgentBuilder.RedefinitionStrategy.Listener redefinitionListener = new DelayListener(DELAY_INTERVAL);
public static DesignerAssemblyFactory getInstance() {
return DesignerAssemblyFactoryHolder.INSTANCE;
}
private static class DesignerAssemblyFactoryHolder {
private static final DesignerAssemblyFactory INSTANCE = new DesignerAssemblyFactory();
}
@Override
public AnalyzerAssemblyFactory<Void> prepare(Void material) {
return this;
}
@Override
public AgentBuilder assembly(AgentBuilder raw) {
return raw.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
// 每次只 transform 一部分否则会导致 UI 变慢
.with(batchAllocator)
.with(redefinitionListener)
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE);
}
private class DelayListener implements AgentBuilder.RedefinitionStrategy.Listener {
/**
* 单位 ms
*/
private final int interval;
public DelayListener(int interval) {
this.interval = interval;
}
/**
* 执行完后等待一段时间再执行
*/
@Override
public void onBatch(int index, List<Class<?>> batch, List<Class<?>> types) {
try {
Thread.sleep(interval);
} catch (Exception ignore) {
}
}
@Override
public Iterable<? extends List<Class<?>>> onError(int index, List<Class<?>> batch, Throwable throwable, List<Class<?>> types) {
return null;
}
@Override
public void onComplete(int amount, List<Class<?>> types, Map<List<Class<?>>, Throwable> failures) {
}
}
}

23
designer-base/src/main/java/com/fr/design/record/analyzer/advice/DBMonitorAdvice.java

@ -0,0 +1,23 @@
package com.fr.design.record.analyzer.advice;
import com.fr.design.record.analyzer.DesignerAnalyzerAdvice;
import com.fr.general.data.DataModel;
import com.fr.measure.DBMeterFactory;
import com.fr.measure.metric.DBMetric;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
/**
* created by Harrison on 2022/03/07
**/
public class DBMonitorAdvice implements DesignerAnalyzerAdvice {
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args) {
if (args.length > 1 && args[1] instanceof DataModel) {
DBMetric meter = ((DataModel) args[1]).getMetric();
DBMeterFactory.getMeter().record(meter);
}
}
}

46
designer-base/src/main/java/com/fr/design/record/analyzer/advice/FaultToleranceAdvice.java

@ -0,0 +1,46 @@
package com.fr.design.record.analyzer.advice;
import com.fr.design.record.analyzer.DesignerAnalyzerAdvice;
import com.fr.record.analyzer.advice.AdviceContext;
import com.fr.record.analyzer.advice.DefaultAdviceCallable;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import com.fr.tolerance.FaultTolerance;
import com.fr.tolerance.FaultToleranceFactory;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
/**
* created by Harrison on 2022/03/07
**/
public class FaultToleranceAdvice implements DesignerAnalyzerAdvice {
@Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
public static boolean onMethodEnter(@Advice.Local("context") AdviceContext adviceContext) throws Exception {
adviceContext = AdviceContext
.builder()
.onAdviceCall()
.build();
// 如果是切面调用,则忽视当前方法
return adviceContext.isOnAdviceCall();
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self,
@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result,
@Advice.Local("context")AdviceContext adviceContext) throws Exception {
// 如果是切面调用,则忽视不继续 exit
if (adviceContext != null && adviceContext.isOnAdviceCall()) {
return;
}
FaultTolerance faultTolerance = method.getAnnotation(FaultTolerance.class);
Callable<Object> callable = new DefaultAdviceCallable<>(self, method, args);
result = FaultToleranceFactory.getInstance().getScene(faultTolerance.scene()).getProcessor().execute(self, callable, args);
}
}

31
designer-base/src/main/java/com/fr/design/record/analyzer/advice/FocusAdvice.java

@ -0,0 +1,31 @@
package com.fr.design.record.analyzer.advice;
import com.fr.design.record.analyzer.DesignerAnalyzerAdvice;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.FocusPoint;
import com.fr.intelli.record.FocusPolicy;
import com.fr.log.counter.DefaultLimitedMetric;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import java.lang.reflect.Method;
/**
* created by Harrison on 2022/03/07
**/
public class FocusAdvice implements DesignerAnalyzerAdvice {
private static final String FOCUS_POINT_ID_PREFIX = "function_";
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.Origin Method method,
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception {
if (FocusPolicy.IGNORE == result) {
return;
}
Focus focus = method.getAnnotation(Focus.class);
String id = FOCUS_POINT_ID_PREFIX + focus.id();
DefaultLimitedMetric.INSTANCE.submit(FocusPoint.create(id, focus.text(), focus.source()), id);
}
}

157
designer-base/src/main/java/com/fr/design/record/analyzer/advice/MonitorAdvice.java

@ -0,0 +1,157 @@
package com.fr.design.record.analyzer.advice;
import com.fr.design.record.analyzer.DesignerAnalyzerAdvice;
import com.fr.general.GeneralUtils;
import com.fr.intelli.measure.Estimator;
import com.fr.intelli.metrics.Compute;
import com.fr.intelli.metrics.SupervisoryConfig;
import com.fr.intelli.record.Measurable;
import com.fr.intelli.record.MeasureObject;
import com.fr.intelli.record.MeasureUnit;
import com.fr.intelli.record.MetricRegistry;
import com.fr.log.FineLoggerFactory;
import com.fr.measure.DBMeterFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.web.Session;
import com.fr.stable.web.SessionProvider;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import com.fr.web.core.SessionPoolManager;
import com.fr.web.session.SessionLocalManager;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* created by Harrison on 2022/03/07
**/
public class MonitorAdvice implements DesignerAnalyzerAdvice {
private static final Pattern P = Pattern.compile("-?\\d+");
private static final int MIN_ERROR_CODE = 10000000;
@Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Local("startTime") Long startTime,
@Advice.Local("registeredSession") Boolean registeredSession) {
startTime = (System.currentTimeMillis());
registeredSession = (findSessionAnnotation(method, args));
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self,
@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e,
@Advice.Local("startTime") Long startTime,
@Advice.Local("registeredSession") Boolean registeredSession) throws Exception {
String error = StringUtils.EMPTY;
try {
if (e != null) {
try {
error = getErrorContent(e);
} catch (Exception ignore) {
}
}
} finally {
try {
if (self instanceof Measurable) {
long consume = System.currentTimeMillis() - startTime;
Compute once = method.getAnnotation(Compute.class);
Measurable measurable = (Measurable) self;
MeasureObject measureObject = MeasureObject.create();
recordMemory(once, measurable, measureObject);
recordSQL(once, measureObject);
measureObject.consume(consume);
measureObject.error(error);
String id = UUID.randomUUID().toString();
List<Object> newArgs = new ArrayList<>(Arrays.asList(args));
newArgs.add(id);
recordSQLDetail(id);
if (measurable instanceof Estimator) {
measurable.asyncDurable(measureObject, newArgs.toArray());
} else {
Object message = null;
try {
message = measurable.durableEntity(measureObject, newArgs.toArray());
} catch (Throwable throwable) {
FineLoggerFactory.getLogger().error(throwable.getMessage(), throwable);
}
if (message != null) {
MetricRegistry.getMetric().submit(message);
}
}
}
} catch (Exception ignore) {
//埋点信息入库失败应该不能影响业务流程
} finally {
if (registeredSession) {
// 如果上面记录了,这里就要释放
SessionLocalManager.releaseSession();
}
}
}
}
public static String getErrorContent(Exception e) {
int errorCode = GeneralUtils.objectToNumber(
extractCodeFromString(e.getMessage())
).intValue();
// 提取字符串中的第一个数字,最小的错误码为10000000
return e.getClass().getName() + ":" + (errorCode >= MIN_ERROR_CODE ? errorCode : StringUtils.EMPTY);
}
public static String extractCodeFromString(String errorMsg) {
Matcher m = P.matcher(errorMsg);
if (m.find()) {
return m.group();
}
return StringUtils.EMPTY;
}
public static void recordSQLDetail(String uuid) {
DBMeterFactory.getMeter().submit(uuid);
}
public static void recordSQL(Compute once, MeasureObject measureObject) {
if (SupervisoryConfig.getInstance().isEnableMeasureSql() && once.computeSql()) {
measureObject.sqlTime(SessionLocalManager.getSqlTime());
measureObject.sql(SessionLocalManager.getSql());
}
}
public static void recordMemory(Compute once, Measurable measurable, MeasureObject measureObject) {
if (SupervisoryConfig.getInstance().isEnableMeasureMemory() && once.computeMemory()) {
MeasureUnit unit = measurable.measureUnit();
measureObject.memory(unit.measureMemory());
}
}
public static boolean findSessionAnnotation(Method method, Object[] args) {
Annotation[][] all = method.getParameterAnnotations();
int len = ArrayUtils.getLength(args);
for (int i = 0; i < len; i++) {
Annotation[] current = all[i];
for (Annotation annotation : current) {
if (annotation.annotationType().equals(Session.class)) {
SessionLocalManager.setSession(
SessionPoolManager.getSessionIDInfor(GeneralUtils.objectToString(args[i]), SessionProvider.class));
return true;
}
}
}
return false;
}
}

49
designer-base/src/main/java/com/fr/design/record/analyzer/advice/PerformancePointAdvice.java

@ -0,0 +1,49 @@
package com.fr.design.record.analyzer.advice;
import com.fr.design.record.analyzer.DesignerAnalyzerAdvice;
import com.fr.intelli.record.ConsumePoint;
import com.fr.intelli.record.MetricRegistry;
import com.fr.intelli.record.PerformancePoint;
import com.fr.intelli.record.PerformancePointRecord;
import com.fr.stable.StringUtils;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* created by Harrison on 2022/03/07
**/
public class PerformancePointAdvice implements DesignerAnalyzerAdvice {
@Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Local("startTime") Long startTime) {
startTime = (System.currentTimeMillis());
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self,
@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Local("startTime") Long startTime) {
PerformancePoint point = method.getAnnotation(PerformancePoint.class);
String id = point.id();
long endTime = System.currentTimeMillis();
long consume = endTime - startTime;
if (self instanceof PerformancePointRecord) {
PerformancePointRecord measurable = (PerformancePointRecord) self;
List<Object> newArgs = new ArrayList<Object>(Arrays.asList(args));
ConsumePoint consumePoint = ConsumePoint.create(id, startTime, endTime, consume, point.source());
MetricRegistry.getMetric().submit(measurable.recordPoint(consumePoint, newArgs.toArray()));
} else {
if (StringUtils.isNotEmpty(id)) {
MetricRegistry.getMetric().submit(ConsumePoint.create(id, consume, point.source()));
}
}
}
}

36
designer-base/src/main/java/com/fr/design/record/analyzer/advice/TimeAdvice.java

@ -0,0 +1,36 @@
package com.fr.design.record.analyzer.advice;
import com.fr.design.record.analyzer.DesignerAnalyzerAdvice;
import com.fr.log.FineLoggerFactory;
import com.fr.record.analyzer.Metrics;
import com.fr.third.net.bytebuddy.asm.Advice;
import java.lang.reflect.Method;
/**
* created by Harrison on 2022/03/08
**/
public class TimeAdvice implements DesignerAnalyzerAdvice {
@Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Local("startTime") Long startTime) {
startTime = (System.currentTimeMillis());
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.Origin Method method,
@Advice.Local("startTime") Long startTime) {
Metrics metrics = method.getAnnotation(Metrics.class);
Object prefix;
String description = metrics.description();
if ("".equals(description)) {
prefix = method.getDeclaringClass().getName() + "#" + method.getName();
} else {
prefix = description;
}
FineLoggerFactory.getLogger().info("{} took {} ms.", prefix, System.currentTimeMillis() - startTime);
}
}

25
designer-base/src/main/java/com/fr/design/record/analyzer/advice/TrackAdvice.java

@ -0,0 +1,25 @@
package com.fr.design.record.analyzer.advice;
import com.fr.intelli.record.MetricRegistry;
import com.fr.third.javax.persistence.Entity;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import java.util.List;
/**
* created by Harrison on 2022/03/08
**/
public class TrackAdvice {
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) {
if (result != null) {
Class clazz = result.getClass();
if (clazz.getAnnotation(Entity.class) != null || result instanceof List) {
MetricRegistry.getMetric().submit(result);
}
}
}
}

31
designer-base/src/main/java/com/fr/design/upm/UpmFinder.java

@ -1,6 +1,6 @@
package com.fr.design.upm;
import com.fr.base.FRContext;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.BaseResourceLoader;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.dialog.UIDialog;
@ -12,8 +12,11 @@ import com.fr.design.update.ui.dialog.UpdateMainDialog;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.general.CommonIOUtils;
import com.fr.general.GeneralContext;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.PluginStoreConstants;
import com.fr.stable.StableUtils;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
@ -33,7 +36,7 @@ public class UpmFinder {
private static final String MAIN_RESOURCE_PATH = UPM_DIR + "/plugin_design.html";
private static final String JXBROWSER = "com.teamdev.jxbrowser.browser.Browser";
public static String installHome = FRContext.getCommonOperator().getWebRootPath();
public static String installHome = PluginStoreConstants.getLocalInstallHome();
private static UIDialog dialog = null;
@ -41,7 +44,8 @@ public class UpmFinder {
EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener<Workspace>() {
@Override
public void on(Event event, Workspace param) {
installHome = FRContext.getCommonOperator().getWebRootPath();
installHome = PluginStoreConstants.getLocalInstallHome();
UpmResourceLoader.INSTANCE.checkOldShopFile();
}
});
}
@ -75,24 +79,24 @@ public class UpmFinder {
}
private static void showUpmPane() {
if (!checkUPMResourcesExist()){
if (!checkUPMResourcesExist()) {
// upm下载
int val = FineJOptionPane.showConfirmDialog(null, Toolkit.i18nText("Fine-Design_Basic_Plugin_Shop_Need_Install"),
Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
if (val == JOptionPane.OK_OPTION){
if (val == JOptionPane.OK_OPTION) {
try {
UpmResourceLoader.INSTANCE.download();
UpmResourceLoader.INSTANCE.install();
installUpmResource();
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Basic_Plugin_Shop_Installed"),
Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e){
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(null, Toolkit.i18nText("Fine-Design_Updater_Download_Failed"),
Toolkit.i18nText("Fine-Design_Basic_Message"), JOptionPane.INFORMATION_MESSAGE);
}
}
}
else {
} else {
UpmShowPane upmPane = new UpmShowPane();
if (dialog == null) {
dialog = new UpmShowDialog(DesignerContext.getDesignerFrame(), upmPane);
@ -102,6 +106,15 @@ public class UpmFinder {
}
}
private static void installUpmResource() {
String installHome = PluginStoreConstants.getLocalInstallHome();
File scriptZip = new File(BaseResourceLoader.SCRIPT_DOWNLOAD_PATH);
if (scriptZip.exists()) {
IOUtils.unzip(scriptZip, installHome);
CommonIOUtils.deleteFile(scriptZip);
}
}
private static void showUpdatePane() {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Update_Info_Plugin_Message"));
if (!GeneralContext.getLocale().equals(Locale.JAPANESE) && !GeneralContext.getLocale().equals(Locale.JAPAN)

27
designer-base/src/main/java/com/fr/env/utils/WorkspaceUtils.java vendored

@ -0,0 +1,27 @@
package com.fr.env.utils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.LocalDesignerWorkspaceInfo;
import com.fr.stable.StringUtils;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/3/10
*/
public class WorkspaceUtils {
private static final String SPECIFY_WORKSPACE = "fr.designer.workspace";
public static DesignerWorkspaceInfo getWorkspaceInfo() {
String workspacePath;
String current = DesignerEnvManager.getEnvManager().getCurEnvName();
if (StringUtils.isNotEmpty(workspacePath = System.getProperty(SPECIFY_WORKSPACE))) {
return LocalDesignerWorkspaceInfo.create(StringUtils.EMPTY, workspacePath);
} else {
return DesignerEnvManager.getEnvManager().getWorkspaceInfo(current);
}
}
}

111
designer-base/src/main/java/com/fr/exit/ConfigToPropMigrator.java

@ -0,0 +1,111 @@
package com.fr.exit;
import com.fr.config.dao.PropertiesConstants;
import com.fr.design.DesignerEnvManager;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.CommonUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
/**
* 设计器关闭前的配置缓存一份到Properties
*
* @author hades
* @version 11.0
* Created by hades on 2022/3/1
*/
public class ConfigToPropMigrator {
private static final String SELECT_FOR_ENTITY = "select id, value from fine_conf_entity";
private static final String SELECT_FOR_CLASSNAME = "select id, classname from fine_conf_classname";
private static final String SELECT_FOR_XML_ENTITY = "select id, value from fine_conf_xmlentity";
private static final ConfigToPropMigrator INSTANCE = new ConfigToPropMigrator();
public static ConfigToPropMigrator getInstance() {
return INSTANCE;
}
public void execute() {
if (WorkContext.getCurrent().isLocal()) {
String url = "jdbc:hsqldb:file://" + WorkContext.getCurrent().getPath() + "/" + ProjectConstants.EMBED_DB_DIRECTORY + "/finedb/db;hsqldb.tx=mvcc";
try {
Class.forName("com.fr.third.org.hsqldb.jdbcDriver");
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return ;
}
initDirectory();
try (Connection c = DriverManager.getConnection(url);
FileOutputStream entityOut = new FileOutputStream(PropertiesConstants.ENTITY_PROP_PATH);
FileOutputStream classHelperOut = new FileOutputStream(PropertiesConstants.CLASS_NAME_PROP_PATH);
FileOutputStream xmlEntityOut = new FileOutputStream(PropertiesConstants.XML_ENTITY_PROP_PATH)) {
processClassOrEntity(c, new Properties(), SELECT_FOR_ENTITY, entityOut);
processClassOrEntity(c, new Properties(), SELECT_FOR_CLASSNAME, classHelperOut);
processXmlEntity(c, new Properties(), xmlEntityOut);
DesignerEnvManager.getEnvManager().setPropertiesUsable(true);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
deletePropertiesCache();
}
}
}
private void initDirectory() {
File directory = new File(StableUtils.pathJoin(WorkContext.getCurrent().getPath(), ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.PROPERTIES_CACHE_FOR_CONFIG));
if (!directory.exists()) {
directory.mkdir();
}
}
private void processClassOrEntity(Connection c, Properties map, String sql, FileOutputStream outputStream) throws SQLException, IOException {
PreparedStatement query = c.prepareStatement(sql);
ResultSet resultSet = query.executeQuery();
while (resultSet.next()) {
String id = resultSet.getString(1);
String value = resultSet.getString(2);
if (id != null && value != null) {
map.setProperty(id, value);
}
}
map.store(outputStream, null);
}
private void processXmlEntity(Connection c, Properties map, FileOutputStream outputStream) throws SQLException, IOException {
PreparedStatement query = c.prepareStatement(SELECT_FOR_XML_ENTITY);
ResultSet resultSet = query.executeQuery();
while (resultSet.next()) {
String id = resultSet.getString(1);
Blob value = resultSet.getBlob(2);
byte[] bytes = value.getBytes(1L, (int) value.length());
map.setProperty(id, new String(bytes));
}
map.store(outputStream, null);
}
public void deletePropertiesCache() {
CommonUtils.deleteFile(new File(PropertiesConstants.ENTITY_PROP_PATH));
CommonUtils.deleteFile(new File(PropertiesConstants.XML_ENTITY_PROP_PATH));
CommonUtils.deleteFile(new File(PropertiesConstants.CLASS_NAME_PROP_PATH));
}
}

34
designer-base/src/main/java/com/fr/file/FILEChooserPane.java

@ -202,10 +202,11 @@ public class FILEChooserPane extends BasicPane {
return INSTANCE;
}
public static FILEChooserPane getInstanceWithDesignatePath(String path, FILEFilter filter) {
public static FILEChooserPane getInstanceWithDesignatePath(String path, FILEFilter filter, String topPath) {
INSTANCE.showLoc = false;
INSTANCE.showEnv = false;
INSTANCE.showWebReport = false;
INSTANCE.setTopPath(topPath);
INSTANCE.setDesignateModel(path);
INSTANCE.removeAllFilter();
INSTANCE.addChooseFILEFilter(filter, 0);
@ -633,6 +634,9 @@ public class FILEChooserPane extends BasicPane {
this.filterList.clear();
}
public void removeTopPath() {
this.setTopPath(StringUtils.EMPTY);
}
/**
* 设置filter,刷新右侧subFileList中的items
@ -1045,9 +1049,14 @@ public class FILEChooserPane extends BasicPane {
if (placesList == null) {
return;
}
setPlaceListModel(new DesignateRemotePlaceListModel(path));
}
private void setTopPath(String path) {
this.locationBtnPane.setTopPath(path);
}
private void setMultiPlaceListModel() {
if (placesList == null) {
@ -1385,6 +1394,8 @@ public class FILEChooserPane extends BasicPane {
private List<UIButton> buttonList = new ArrayList<>();
private int pathIndex = 0;
private int maxPathIndex = 0;
// 对顶层目录进行的限制
private String topPath;
public LocationButtonPane() {
this.setLayout(FRGUIPaneFactory.createBoxFlowLayout());
@ -1430,6 +1441,10 @@ public class FILEChooserPane extends BasicPane {
});
}
public void setTopPath(String path) {
this.topPath = path;
}
public void highLightButton(FILE dir) {
for (int i = 0; i < this.buttonList.size(); i++) {
this.buttonList.get(i).setForeground(null);
@ -1471,6 +1486,7 @@ public class FILEChooserPane extends BasicPane {
}
Matcher matcher = SEPARATOR_PATTERN.matcher(path);
int node_start = 0;
boolean needTopPath = !StringUtils.isEmpty(topPath);
while (matcher.find()) {
int start = matcher.start();
String btn_text = path.substring(node_start, start);
@ -1478,11 +1494,14 @@ public class FILEChooserPane extends BasicPane {
if (StringUtils.isBlank(btn_text) && isWebAppNamePath) {
btn_text = webAppName;
}
node_start = matcher.end();
if (needTopPath && topPath.equals(btn_text)) {
needTopPath = false;
}
this.buttonList.add(createBlankButton((new SetDirectoryAction(btn_text + '/',
// alex:dir.prefix不和btn_path一起参与pathJoin,因为btn_path是否以/打头在unix,linux
// OS中意义很不一样
FILEFactory.createFolder(dir.prefix() + StableUtils.pathJoin(btn_path, "/"))))));
node_start = matcher.end();
FILEFactory.createFolder(dir.prefix() + StableUtils.pathJoin(btn_path, "/")), !needTopPath))));
}
maxPathIndex = calculateMaxPathIndex();
@ -1583,6 +1602,7 @@ public class FILEChooserPane extends BasicPane {
private class SetDirectoryAction extends UpdateAction {
private FILE dir;
private boolean response = true;
public SetDirectoryAction(String name) {
this.setName(name);
@ -1594,9 +1614,15 @@ public class FILEChooserPane extends BasicPane {
this.dir = file;
}
public SetDirectoryAction(String name, FILE file, boolean response) {
this.setName(name);
this.dir = file;
this.response = response;
}
@Override
public void actionPerformed(ActionEvent evt) {
if (dir != null) {
if (dir != null && response) {
setSelectedDirectory(dir);
}
}

2
designer-base/src/main/java/com/fr/start/BaseDesigner.java

@ -32,6 +32,7 @@ import com.fr.process.engine.core.CarryMessageEvent;
import com.fr.process.engine.core.FineProcessContext;
import com.fr.stable.OperatingSystem;
import com.fr.start.event.LazyStartupEvent;
import com.fr.workspace.base.WorkspaceStatus;
import java.awt.Window;
import java.io.File;
@ -86,6 +87,7 @@ public abstract class BaseDesigner extends ToolBarMenuDock {
eventPipe.fire(new CarryMessageEvent(ReportState.STOP.getValue()));
}
EventDispatcher.fire(WorkspaceStatus.Prepared);
EventDispatcher.asyncFire(LazyStartupEvent.INSTANCE);
collectUserInformation();
}
});

14
designer-base/src/main/java/com/fr/start/event/LazyStartupEvent.java

@ -0,0 +1,14 @@
package com.fr.start.event;
import com.fr.event.Event;
import com.fr.event.Null;
/**
* @author hades
* @version 11.0
* Created by hades on 2022/3/7
*/
public enum LazyStartupEvent implements Event<Null> {
INSTANCE
}

8
designer-base/src/main/resources/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex

@ -584,7 +584,13 @@ FunctionNames = "ABS"|
"QUERY"|
"query"|
"WEBIMAGE"|
"webimage"
"webimage"|
"ACCSUM"|
"accsum"|
"COUNTIFS"|
"countifs"|
"SUMIFS"|
"sumifs"
%state MLC

9
designer-base/src/main/resources/com/fr/design/images/data/back_normal.svg

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_返回_normal</title>
<g id="icon_返回_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M6.57897109,8 L11.8084387,3.05563189 C12.0638538,2.81414149 12.0638538,2.4226082 11.8084387,2.1811178 C11.5530236,1.9396274 11.1389139,1.9396274 10.8834988,2.1811178 L5.19156131,7.56274296 C4.93614623,7.80423335 4.93614623,8.19576665 5.19156131,8.43725704 L10.8834988,13.8188822 C11.1389139,14.0603726 11.5530236,14.0603726 11.8084387,13.8188822 C12.0638538,13.5773918 12.0638538,13.1858585 11.8084387,12.9443681 L6.57897109,8 Z"
id="Rectangle-135" fill="#333334" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 861 B

10
designer-base/src/main/resources/com/fr/design/images/data/clear_normal.svg

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_关闭_normal</title>
<g id="icon_关闭_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M7.89949494,0.899494937 C8.28609426,0.899494937 8.59949494,1.21820884 8.59949494,1.59375711 L8.59849494,7.19949494 L14.2052328,7.19949494 C14.5567106,7.19949494 14.8471855,7.46057376 14.8931571,7.80394288 L14.8994949,7.89949494 C14.8994949,8.28609426 14.580781,8.59949494 14.2052328,8.59949494 L8.59849494,8.59849494 L8.59949494,14.2052328 C8.59949494,14.5567106 8.33841611,14.8471855 7.99504699,14.8931571 L7.89949494,14.8994949 C7.51289561,14.8994949 7.19949494,14.580781 7.19949494,14.2052328 L7.19949494,8.59849494 L1.59375711,8.59949494 C1.24227924,8.59949494 0.951804388,8.33841611 0.905832732,7.99504699 L0.899494937,7.89949494 C0.899494937,7.51289561 1.21820884,7.19949494 1.59375711,7.19949494 L7.19949494,7.19949494 L7.19949494,1.59375711 C7.19949494,1.24227924 7.46057376,0.951804388 7.80394288,0.905832732 L7.89949494,0.899494937 Z"
id="Combined-Shape" fill="#333334"
transform="translate(7.899495, 7.899495) rotate(45.000000) translate(-7.899495, -7.899495) "></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

9
designer-base/src/main/resources/com/fr/design/images/data/search_normal.svg

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_搜索_normal</title>
<g id="icon_搜索_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M6.5,1 C9.53756612,1 12,3.46243388 12,6.5 C12,7.75769341 11.577854,8.91678934 10.8675261,9.84332369 L14.7880061,13.764409 C15.0706646,14.0470675 15.0706646,14.5053476 14.7880061,14.7880061 C14.5053476,15.0706646 14.0470675,15.0706646 13.764409,14.7880061 L9.84332369,10.8675261 C8.91678934,11.577854 7.75769341,12 6.5,12 C3.46243388,12 1,9.53756612 1,6.5 C1,3.46243388 3.46243388,1 6.5,1 Z M6.5,2 C4.01471863,2 2,4.01471863 2,6.5 C2,8.98528137 4.01471863,11 6.5,11 C8.98528137,11 11,8.98528137 11,6.5 C11,4.01471863 8.98528137,2 6.5,2 Z"
id="Combined-Shape" fill="#333334" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 970 B

43
designer-base/src/test/java/com/fr/design/data/datapane/management/clip/TableDataTreeClipboardTest.java

@ -0,0 +1,43 @@
package com.fr.design.data.datapane.management.clip;
import com.fr.data.impl.EmbeddedTableData;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import junit.framework.TestCase;
import org.junit.Assert;
import java.util.HashMap;
import java.util.Map;
/**
* @author Yvan
*/
public class TableDataTreeClipboardTest extends TestCase {
public void testAddAndTake() {
Map<String, AbstractTableDataWrapper> testMap = new HashMap<>();
testMap.put("ds1", new TemplateTableDataWrapper(new EmbeddedTableData()));
testMap.put("ds2", new TemplateTableDataWrapper(new EmbeddedTableData()));
Map<String, AbstractTableDataWrapper> anotherTestMap = new HashMap<>();
anotherTestMap.put("ds3", new TemplateTableDataWrapper(new EmbeddedTableData()));
Map<String, AbstractTableDataWrapper> clip;
TableDataTreeClipboard.getInstance().addToClip(testMap);
clip = TableDataTreeClipboard.getInstance().takeFromClip();
Assert.assertEquals(2, clip.size());
Assert.assertTrue(clip.containsKey("ds1"));
Assert.assertTrue(clip.containsKey("ds2"));
// 验证多次取出
clip = TableDataTreeClipboard.getInstance().takeFromClip();
Assert.assertEquals(2, clip.size());
Assert.assertTrue(clip.containsKey("ds1"));
Assert.assertTrue(clip.containsKey("ds2"));
TableDataTreeClipboard.getInstance().addToClip(anotherTestMap);
clip = TableDataTreeClipboard.getInstance().takeFromClip();
Assert.assertEquals(1, clip.size());
Assert.assertTrue(clip.containsKey("ds3"));
}
}

201
designer-base/src/test/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtilsTest.java

@ -0,0 +1,201 @@
package com.fr.design.data.tabledata.paste;
import com.fr.base.TableData;
import com.fr.data.Dictionary;
import com.fr.data.TableDataSource;
import com.fr.data.impl.EmbeddedTableData;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import com.fr.form.data.DataBinding;
import com.fr.form.data.DataTableConfig;
import com.fr.form.ui.AbstractDataControl;
import com.fr.form.ui.DictionaryContainer;
import com.fr.form.ui.Widget;
import com.fr.form.ui.WidgetValue;
import com.fr.report.cell.tabledata.ElementUsedTableDataProvider;
import com.fr.script.Calculator;
import com.fr.stable.script.CalculatorProvider;
import com.fr.stable.script.NameSpace;
import com.fr.web.core.TemplateSessionIDInfo;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Yvan
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({DesignTableDataManager.class})
public class TableDataFollowingPasteUtilsTest extends TestCase {
@Before
public void beforeTest() {
Map<String, TableDataWrapper> templateDataMap = new LinkedHashMap<String, TableDataWrapper>();
Map<String, TableDataWrapper> serverDataMap = new LinkedHashMap<String, TableDataWrapper>();
Map<String, TableDataWrapper> storeProcedureMap = new LinkedHashMap<String, TableDataWrapper>();
templateDataMap.put("ds1", new TemplateTableDataWrapper(new EmbeddedTableData()));
templateDataMap.put("ds2", new TemplateTableDataWrapper(new EmbeddedTableData()));
templateDataMap.put("ds3", new TemplateTableDataWrapper(new EmbeddedTableData()));
templateDataMap.put("ds4", new TemplateTableDataWrapper(new EmbeddedTableData()));
templateDataMap.put("ds5", new TemplateTableDataWrapper(new EmbeddedTableData()));
List<Map<String, TableDataWrapper>> list = new ArrayList<Map<String, TableDataWrapper>>();
list.add(templateDataMap);
list.add(serverDataMap);
list.add(storeProcedureMap);
TableDataSource tableDataSource = EasyMock.mock(TableDataSource.class);
PowerMock.mockStatic(DesignTableDataManager.class);
EasyMock.expect(DesignTableDataManager.getEditingTableDataSource()).andReturn(tableDataSource).anyTimes();
EasyMock.expect(DesignTableDataManager.getEditingDataSet(tableDataSource)).andReturn(list).anyTimes();
PowerMock.replayAll();
}
public void testTransferProvider2TableDataMap() {
ElementUsedTableDataProvider[] providers = generateElementUsedTableDataProvider();
Map<String, TableData> tableDataMap = TableDataFollowingPasteUtils.transferProvider2TableDataMap(providers);
Assert.assertEquals(2, tableDataMap.size());
Assert.assertTrue(tableDataMap.containsKey("ds1"));
Assert.assertTrue(tableDataMap.containsKey("ds2"));
}
private ElementUsedTableDataProvider[] generateElementUsedTableDataProvider() {
ElementUsedTableDataProvider elementUsedTableDataProvider1 = new ElementUsedTableDataProvider() {
@Override
public Set<String> getElementUsedTableDataNames() {
Set<String> set = new HashSet<>();
set.add("ds1");
return set;
}
};
ElementUsedTableDataProvider elementUsedTableDataProvider2 = new ElementUsedTableDataProvider() {
@Override
public Set<String> getElementUsedTableDataNames() {
Set<String> set = new HashSet<>();
set.add("ds2");
return set;
}
};
return new ElementUsedTableDataProvider[]{elementUsedTableDataProvider1, elementUsedTableDataProvider2};
}
public void testTransferWidgetArray2TableDataMap() {
Widget[] widgets = generateWidgetArray();
Map<String, TableData> tableDataMap = TableDataFollowingPasteUtils.transferWidgetArray2TableDataMap(widgets);
Assert.assertEquals(3, tableDataMap.size());
Assert.assertTrue(tableDataMap.containsKey("ds3"));
Assert.assertTrue(tableDataMap.containsKey("ds4"));
Assert.assertTrue(tableDataMap.containsKey("ds5"));
}
private Widget[] generateWidgetArray() {
Set<String> set = new HashSet<>();
set.add("ds3");
MockWidget widget1 = EasyMock.mock(MockWidget.class);
EasyMock.expect(widget1.getUsedTableDataSets()).andReturn(set).anyTimes();
EasyMock.replay(widget1);
DataBinding dataBinding = new DataBinding("ds4", "");
WidgetValue widgetValue2 = new WidgetValue();
widgetValue2.setValue(dataBinding);
AbstractDataControl widget2 = EasyMock.mock(AbstractDataControl.class);
EasyMock.expect(widget2.getWidgetValue()).andReturn(widgetValue2).anyTimes();
EasyMock.replay(widget2);
DataTableConfig dataTableConfig = EasyMock.mock(DataTableConfig.class);
EasyMock.expect(dataTableConfig.getTableDataName()).andReturn("ds5").anyTimes();
WidgetValue widgetValue3 = new WidgetValue();
widgetValue3.setValue(dataTableConfig);
AbstractDataControl widget3 = EasyMock.mock(AbstractDataControl.class);
EasyMock.expect(widget3.getWidgetValue()).andReturn(widgetValue3).anyTimes();
EasyMock.replay(dataTableConfig, widget3);
Widget[] widgets = new Widget[3];
widgets[0] = widget1;
widgets[1] = widget2;
widgets[2] = widget3;
return widgets;
}
private class MockWidget extends Widget implements DictionaryContainer {
@Override
public String[] supportedEvents() {
return new String[0];
}
@Override
public void setDictionary(Dictionary model) {
}
@Override
public Dictionary getDictionary() {
return null;
}
@Override
public Object getViewValue(Object value, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req) {
return null;
}
@Override
public Object getModuleValue(Object text, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req) {
return null;
}
@Override
public Object getViewValue(Object value, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req, NameSpace dependenceNameSpace) {
return null;
}
@Override
public Object getModuleValue(Object text, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req, NameSpace dependenceNameSpace) {
return null;
}
@Override
public boolean isValueAllInDictionary(Object value, Calculator c, TemplateSessionIDInfo sessionIDInfor, HttpServletRequest req, NameSpace dependenceNameSpace) {
return false;
}
@Override
public String getXType() {
return null;
}
@Override
public boolean isEditor() {
return false;
}
@Override
public void setDependenceMap(Map dependenceMap) {
}
@Override
public Map getDependenceMap() {
return null;
}
@Override
public String[] dependence(CalculatorProvider calculatorProvider) {
return new String[0];
}
}
}

139
designer-base/src/test/java/com/fr/design/record/analyzer/BytebuddyRedefineTest.java

@ -0,0 +1,139 @@
package com.fr.design.record.analyzer;
import com.fr.third.net.bytebuddy.ByteBuddy;
import com.fr.third.net.bytebuddy.agent.ByteBuddyAgent;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import com.fr.third.net.bytebuddy.matcher.ElementMatchers;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
/**
* 测试一下通过 redefine 去处理代码时
* 相应的 advice 应该怎么写
*/
public class BytebuddyRedefineTest {
/**
* 测试一下是否可以直接抛出异常
*/
@Test
public void testThrowException() {
try {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(TestClass.class)
.visit(Advice.to(TestThrowExceptionAdvice.class).on(ElementMatchers.named("testPrint")))
.make()
.load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
TestClass testClass = new TestClass();
testClass.testPrint();
} catch (Throwable throwable) {
Assert.assertNotNull("expected throw exception", throwable);
}
}
/**
* 测试是否可以直接传值
*/
@Test
public void testTransferValue() {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(TestClass.class)
.visit(Advice.to(TestTransferValueAdvice.class).on(ElementMatchers.named("testPrint")))
.make()
.load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
TestClass testClass = new TestClass();
String print = testClass.testPrint();
Assert.assertEquals(10, TestTransferValueAdvice.intField);
Assert.assertEquals("[test]stringField", TestTransferValueAdvice.stringField);
Assert.assertEquals("[test]objectField", TestTransferValueAdvice.objectField);
}
/**
* 测试是否可以改变返回值
*/
@Test
public void testModifyReturn() {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(TestClass.class)
.visit(Advice.to(TestModifyReturnAdvice.class).on(ElementMatchers.named("testPrint")))
.make()
.load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
TestClass testClass = new TestClass();
String print = testClass.testPrint();
Assert.assertEquals("[test]Modify Return Value", print);
}
@Test
public void testCallable() throws Exception {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(TestClass.class)
.visit(Advice.to(TestCallableAdvice.class).on(ElementMatchers.named("testPrint")))
.make()
.load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
TestClass testClass = new TestClass();
String print = testClass.testPrint();
Assert.assertEquals("[test]Callable", print);
}
@Test
public void testCallablePerformance() throws Exception {
// 千
int loop = 1000;
StopWatch stopWatch = new StopWatch();
stopWatch.start();
TestClass rawClass = new TestClass();
for (int i = 0; i < loop; i++) {
rawClass.testPrint();
}
System.out.printf("raw class run %s cost %s ms \n", loop, stopWatch.getTime(TimeUnit.MILLISECONDS));
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(TestClass.class)
.visit(Advice.to(TestCallableAdvice.class).on(ElementMatchers.named("testPrint")))
.make()
.load(TestClass.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
stopWatch.reset();
stopWatch.start();
TestClass retransformClass = new TestClass();
for (int i = 0; i < loop; i++) {
retransformClass.testPrint();
}
System.out.printf("retransformClass class run %s cost %s ms \n", loop, stopWatch.getTime(TimeUnit.MILLISECONDS));
Assert.assertEquals("[test]Callable", retransformClass.testPrint());
}
}

50
designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableAdvice.java

@ -0,0 +1,50 @@
package com.fr.design.record.analyzer;
import com.fr.record.analyzer.advice.AdviceCallable;
import com.fr.record.analyzer.advice.AdviceContext;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import com.fr.tolerance.FaultTolerance;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
/**
* created by Harrison on 2022/03/09
**/
public class TestCallableAdvice {
@Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
public static boolean onMethodEnter(@Advice.Local("context")AdviceContext adviceContext) {
adviceContext = AdviceContext
.builder()
.onAdviceCall()
.build();
// 如果是切面调用,则忽视当前方法
return adviceContext.isOnAdviceCall();
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self,
@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result,
@Advice.Local("context") AdviceContext adviceContext) throws Exception {
// 如果是切面调用,则忽视不继续 exit
if (adviceContext != null && adviceContext.isOnAdviceCall()) {
return;
}
FaultTolerance faultTolerance = method.getAnnotation(FaultTolerance.class);
Callable<Object> callable = new AdviceCallable<Object>() {
@Override
public Object call() throws Exception {
return method.invoke(self, args);
}
};
result = TestCallableHelper.test(callable);
}
}

15
designer-base/src/test/java/com/fr/design/record/analyzer/TestCallableHelper.java

@ -0,0 +1,15 @@
package com.fr.design.record.analyzer;
import java.util.concurrent.Callable;
/**
* created by Harrison on 2022/03/09
**/
public class TestCallableHelper {
public static String test(Callable<Object> callable) throws Exception {
callable.call();
return "[test]Callable";
}
}

11
designer-base/src/test/java/com/fr/design/record/analyzer/TestClass.java

@ -0,0 +1,11 @@
package com.fr.design.record.analyzer;
/**
* created by Harrison on 2022/03/04
**/
public class TestClass {
public String testPrint() {
return "";
}
}

29
designer-base/src/test/java/com/fr/design/record/analyzer/TestModifyReturnAdvice.java

@ -0,0 +1,29 @@
package com.fr.design.record.analyzer;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import java.lang.reflect.Method;
/**
* created by Harrison on 2022/03/07
**/
public class TestModifyReturnAdvice {
@Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class)
public static int onMethodEnter() throws Exception {
return 0;
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.This(optional = true, typing = Assigner.Typing.DYNAMIC) Object self,
@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] args,
@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object result) throws Exception {
result = "[test]Modify Return Value";
}
}

19
designer-base/src/test/java/com/fr/design/record/analyzer/TestThrowExceptionAdvice.java

@ -0,0 +1,19 @@
package com.fr.design.record.analyzer;
import com.fr.third.net.bytebuddy.asm.Advice;
import com.fr.third.net.bytebuddy.implementation.bytecode.assign.Assigner;
import java.lang.reflect.Method;
/**
* created by Harrison on 2022/03/07
**/
public class TestThrowExceptionAdvice {
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.Origin Method method,
@Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments,
@Advice.Thrown(typing = Assigner.Typing.DYNAMIC) Exception e) throws Exception {
throw new RuntimeException("[test] throw exception in advice");
}
}

37
designer-base/src/test/java/com/fr/design/record/analyzer/TestTransferValueAdvice.java

@ -0,0 +1,37 @@
package com.fr.design.record.analyzer;
import com.fr.third.net.bytebuddy.asm.Advice;
/**
* created by Harrison on 2022/03/07
**/
public class TestTransferValueAdvice {
public static int intField;
public static String stringField;
public static Object objectField;
@Advice.OnMethodEnter
public static void onMethodEnter(@Advice.Local("int") int intField,
@Advice.Local("string") String stringField,
@Advice.Local("Object") Object objectField) {
intField = 10;
stringField = "[test]stringField";
objectField = "[test]objectField";
}
@Advice.OnMethodExit(onThrowable = Exception.class)
public static void onMethodExit(@Advice.Local("int") int intField,
@Advice.Local("string") String stringField,
@Advice.Local("Object") Object objectField) throws Exception {
TestTransferValueAdvice.intField = intField;
TestTransferValueAdvice.stringField = stringField;
TestTransferValueAdvice.objectField = objectField;
}
}

1
designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/report/CategoryPlotMoreCateReportDataContentPane.java

@ -190,7 +190,6 @@ public class CategoryPlotMoreCateReportDataContentPane extends CategoryPlotRepor
Plot plot = collection.getSelectedChart().getPlot();
if (definition instanceof NormalReportDataDefinition) {
NormalReportDataDefinition reportDefinition = (NormalReportDataDefinition) definition;
reportDefinition.clearMoreCate();
updateMoreCate(reportDefinition, plot);
collection.updateAxisCategoryStyles();

1
designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/data/table/CategoryPlotMoreCateTableDataContentPane.java

@ -257,5 +257,4 @@ public class CategoryPlotMoreCateTableDataContentPane extends CategoryPlotTableD
}
}
}
}

2
designer-chart/src/main/java/com/fr/design/module/ChartHyperlinkGroup.java

@ -59,7 +59,7 @@ public class ChartHyperlinkGroup extends BaseHyperlinkGroup {
return false;
}
if (template.isJWorkBook() || DesignModeContext.isDuchampMode()) {
if (template.isJWorkBook()) {
// 如果是普通报表单元格,那么没有 FormHyperlink 选项
FormHyperlinkProvider formHyperlink = StableFactory.getMarkedInstanceObjectFromClass(FormHyperlinkProvider.XML_TAG, FormHyperlinkProvider.class);
//返回true表示可用,返回false表示不可用

7
designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java

@ -3,6 +3,7 @@ package com.fr.design.designer.beans.models;
import com.fr.common.inputevent.InputEventBaseOnOS;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.base.clipboard.ClipboardFilter;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.events.DesignerEvent;
@ -187,6 +188,8 @@ public class SelectionModel {
} else {
//已选
selectedPaste();
// 粘贴剪切板控件中的数据集
pasteTableDataFromWidget(pasteSelection);
}
} else {
Toolkit.getDefaultToolkit().beep();
@ -194,6 +197,10 @@ public class SelectionModel {
return false;
}
private void pasteTableDataFromWidget(FormSelection pasteSelection) {
TableDataFollowingPasteUtils.paste(pasteSelection.getSelectionUsedTablaData());
}
public FormSelection getSelection() {
return selection;
}

7
designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java

@ -2,6 +2,7 @@ package com.fr.design.mainframe;
import com.fr.base.Parameter;
import com.fr.base.TableData;
import com.fr.base.param.ParameterSource;
import com.fr.data.TableDataSource;
import com.fr.design.DesignModelAdapter;
import com.fr.design.file.HistoryTemplateListPane;
@ -14,8 +15,8 @@ import com.fr.script.Calculator;
import com.fr.stable.EmbParaFilter;
import com.fr.stable.ParameterProvider;
import com.fr.stable.js.WidgetName;
import com.fr.util.ParameterApplyHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -55,7 +56,7 @@ public class FormModelAdapter extends DesignModelAdapter<Form, BaseJForm<Form>>
Map<String, ParameterProvider> map = new HashMap<>();
addGlobalParameters(map);
updateTableDataParameters(oldName, tdName, tableData, map, parameterProvider -> !EmbParaFilter.isFRLayerTypePara(parameterProvider));
ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters());
ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters(), null, ParameterSource.DEFAULT_SOURCE);
parameters = map.values().toArray(new Parameter[0]);
jTemplate.populateParameter();
}
@ -158,7 +159,7 @@ public class FormModelAdapter extends DesignModelAdapter<Form, BaseJForm<Form>>
addTableDataParameters(map, parameterProvider -> !EmbParaFilter.isFRLayerTypePara(parameterProvider));
ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters());
ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters(), null, ParameterSource.DEFAULT_SOURCE);
return map.values().toArray(new Parameter[0]);
}

28
designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java

@ -1,5 +1,7 @@
package com.fr.design.mainframe;
import com.fr.base.TableData;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter;
@ -7,12 +9,10 @@ import com.fr.design.designer.beans.location.Direction;
import com.fr.design.designer.creator.XComponent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XElementCase;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.creator.XWTitleLayout;
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
import com.fr.design.designer.creator.cardlayout.XWCardTagLayout;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
@ -22,11 +22,12 @@ import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.ui.Widget;
import com.fr.log.FineLoggerFactory;
import java.awt.Component;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
public class FormSelection {
@ -35,6 +36,7 @@ public class FormSelection {
private ArrayList<Rectangle> recs = new ArrayList<Rectangle>();
// 选中的组件外层嵌套的tab块 head->tail 由内向外
private LinkedList<XCreator> tabList = new LinkedList<>();
private Map<String, TableData> selectionUsedTablaData = new HashMap<>();
public FormSelection() {
selection = new ArrayList<XCreator>();
@ -362,8 +364,13 @@ public class FormSelection {
public void cut2ClipBoard(FormSelection clipBoard) {
clipBoard.reset();
clipBoard.selection.addAll(selection);
for (XCreator creator : selection) {
try {
// 剪切时,添加剪切组件的数据集到usedTablaDataMap中
clipBoard.addUsedTablaData((Widget) creator.toData().clone());
} catch (CloneNotSupportedException e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
removeCreatorFromContainer(creator);
}
reset();
@ -382,15 +389,26 @@ public class FormSelection {
continue;
}
try {
XCreator creator = XCreatorUtils.createXCreator((Widget) root.toData().clone());
Widget clone = (Widget) root.toData().clone();
XCreator creator = XCreatorUtils.createXCreator(clone);
creator.setBounds(root.getBounds());
clipBoard.selection.add(creator);
// 复制时,添加剪切组件的数据集到usedTablaDataMap中
clipBoard.addUsedTablaData(clone);
} catch (CloneNotSupportedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
public void addUsedTablaData(Widget... widget) {
this.selectionUsedTablaData.putAll(TableDataFollowingPasteUtils.transferWidgetArray2TableDataMap(widget));
}
public Map<String, TableData> getSelectionUsedTablaData() {
return selectionUsedTablaData;
}
public LinkedList<XCreator> getTabList() {
return tabList;
}

15
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/MiniComponentShopDialog.java

@ -1,15 +1,13 @@
package com.fr.design.mainframe.share.ui.online.mini;
import com.fr.base.ScreenResolution;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.stable.Constants;
import com.fr.stable.unit.FU;
import com.fr.stable.unit.UNIT;
import javax.swing.JFrame;
import java.awt.Container;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
@ -36,10 +34,11 @@ public class MiniComponentShopDialog {
final JFrame frame = new JFrame();
final MiniComponentShopPane shopPane = new MiniComponentShopPane();
final UNIT width = FU.getInstance(900 * Constants.FU_PER_OLD_PIX);
final UNIT height = FU.getInstance(600 * Constants.FU_PER_OLD_PIX);
int resolution = ScreenResolution.getScreenResolution();
frame.setSize(width.toPixI(resolution), height.toPixI(resolution));
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle rect =ge.getMaximumWindowBounds();
int width = (int) (rect.width * 0.8);
int height = (int) (rect.height * 0.9);
frame.setSize(width, height);
frame.setTitle(Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Window_Title"));
frame.add(shopPane);
frame.setResizable(false);

39
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/mini/bridge/NativeProductBridge.java

@ -254,9 +254,9 @@ public class NativeProductBridge {
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Component_Tip"),
"",
FineJOptionPane.YES_NO_OPTION
FineJOptionPane.OK_CANCEL_OPTION
);
allowedDownload = result == JOptionPane.YES_OPTION;
allowedDownload = result == JOptionPane.OK_OPTION;
}
if (allowedDownload) {
fireStartEvent(null);
@ -353,33 +353,14 @@ public class NativeProductBridge {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
boolean allowedDownload;
OnlineShareWidget[] childrenWidgets = OnlineShopUtils.getPackageWidgets(widget, false);
boolean isCompatibleWithCurrentEnv = true;
for (OnlineShareWidget children: childrenWidgets) {
if (!children.isCompatibleWithCurrentEnv()) {
isCompatibleWithCurrentEnv = false;
break;
}
}
int result;
if (!isCompatibleWithCurrentEnv) {
result = FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Incompatible_Components_Package_Tip", childrenCount),
"",
FineJOptionPane.YES_NO_OPTION
);
} else {
result = FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Components_Package_Tip", childrenCount),
"",
FineJOptionPane.YES_NO_OPTION
);
}
allowedDownload = result == JOptionPane.YES_OPTION;
if (allowedDownload) {
OnlineShareWidget[] childrenWidgets = OnlineShopUtils.getPackageWidgets(widget, true);
int result = FineJOptionPane.showConfirmDialog(
MiniComponentShopDialog.getInstance().getContentPane(),
Toolkit.i18nText("Fine-Design_Share_Online_Mini_Shop_Download_Components_Package_Tip", childrenWidgets.length),
"",
FineJOptionPane.OK_CANCEL_OPTION
);
if (result == JOptionPane.OK_OPTION) {
fireStartEvent(null);
action.install();
} else {

4
designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java

@ -76,7 +76,7 @@ public class TreeEditorDefinePane extends CustomWritableRepeatEditorPane<TreeEdi
@Override
protected void populateSubCustomWritableRepeatEditorBean(TreeEditor e) {
accessibleTreeModelEditor.setValue(e.getNodeOrDict());
accessibleTreeModelEditor.setValue(e.getBuildModelConfig());
formWidgetValuePane.populate(e);
treeRootPane.populate(e.getTreeAttr());
mutiSelect.setSelected(e.isMultipleSelection());
@ -95,7 +95,7 @@ public class TreeEditorDefinePane extends CustomWritableRepeatEditorPane<TreeEdi
editor.setAjax(loadAsync.isSelected());
editor.setSelectLeafOnly(returnLeaf.isSelected());
editor.setReturnFullPath(returnPath.isSelected());
editor.setNodeOrDict(accessibleTreeModelEditor.getValue());
editor.setBuildModelConfig(accessibleTreeModelEditor.getValue());
return editor;
}

12
designer-realize/src/main/java/com/fr/design/cell/clipboard/CellElementsClip.java

@ -3,7 +3,9 @@
*/
package com.fr.design.cell.clipboard;
import com.fr.base.TableData;
import com.fr.design.base.clipboard.ClipboardHelper;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.grid.selection.CellSelection;
import com.fr.log.FineLoggerFactory;
import com.fr.report.cell.CellElement;
@ -17,6 +19,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* The clip of CellElement.
@ -27,6 +30,7 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
private FU[] columnWidth;
private FU[] rowHeight;
private TemplateCellElement[] clips;
private Map<String, TableData> elementUsedTableDatas;
public CellElementsClip(int columnSpan, int rowSpan, FU[] columnWidth, FU[] rowHeight, TemplateCellElement[] clips) {
this.columnSpan = columnSpan;
@ -34,12 +38,14 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
this.columnWidth = columnWidth;
this.rowHeight = rowHeight;
this.clips = clips;
this.elementUsedTableDatas = TableDataFollowingPasteUtils.transferProvider2TableDataMap(clips);
}
public CellElementsClip(int columnSpan, int rowSpan, TemplateCellElement[] clips) {
this.columnSpan = columnSpan;
this.rowSpan = rowSpan;
this.clips = clips;
this.elementUsedTableDatas = TableDataFollowingPasteUtils.transferProvider2TableDataMap(clips);
}
public int getColumnSpan() {
@ -136,6 +142,8 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
if (this.columnWidth != null && this.rowHeight != null) {
pasteWidthAndHeight(ec, column, row, columnSpan, rowSpan);
}
// 粘贴数据集
TableDataFollowingPasteUtils.paste(elementUsedTableDatas);
return new CellSelection(column, row, columnSpan, rowSpan);
}
@ -163,6 +171,8 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
}
ec.addCellElement(cellElement);
// 跟随粘贴数据集
TableDataFollowingPasteUtils.paste(elementUsedTableDatas);
}
}
@ -182,4 +192,4 @@ public class CellElementsClip implements Cloneable, java.io.Serializable {
return cloned;
}
}
}

35
designer-realize/src/main/java/com/fr/design/cell/clipboard/FloatElementsClip.java

@ -3,7 +3,9 @@
*/
package com.fr.design.cell.clipboard;
import com.fr.base.TableData;
import com.fr.design.cell.FloatElementsProvider;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.general.ComparatorUtils;
import com.fr.grid.selection.FloatSelection;
import com.fr.log.FineLoggerFactory;
@ -14,21 +16,25 @@ import com.fr.stable.unit.FU;
import com.fr.stable.unit.OLDPIX;
import java.util.Iterator;
import java.util.Map;
/**
* The clip of Float Element.
*/
public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatElementsProvider {
public class FloatElementsClip implements Cloneable, java.io.Serializable, FloatElementsProvider {
private FloatElement floatEl;
public FloatElementsClip(FloatElement floatEl) {
this.floatEl = floatEl;
}
/**
* 悬浮元素的粘贴
*
* @param ec 单元格
private Map<String, TableData> elementUsedTableDatas;
public FloatElementsClip(FloatElement floatEl) {
this.floatEl = floatEl;
this.elementUsedTableDatas = TableDataFollowingPasteUtils.transferProvider2TableDataMap(floatEl);
}
/**
* 悬浮元素的粘贴
*
* @param ec 单元格
* @return 粘贴的悬浮元素
*/
public FloatSelection pasteAt(TemplateElementCase ec) {
@ -46,7 +52,7 @@ public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatE
while (ec.getFloatElement(ret.getName()) != null) {
ret.setName(ret.getName() + "-Copy");
}
while (true) {
if (isContainSameBoundFloatElement(ec, ret)) {
ret.setTopDistance(FU.getInstance(ret.getTopDistance().toFU() + new OLDPIX(50).toFU()));
@ -55,11 +61,12 @@ public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatE
break;
}
}
ec.addFloatElement(ret);
// 跟随粘贴数据集
TableDataFollowingPasteUtils.paste(elementUsedTableDatas);
return new FloatSelection(ret.getName());
}
}
/**
* Contain same location and bounds FloatElement.
@ -100,4 +107,4 @@ public class FloatElementsClip implements Cloneable, java.io.Serializable,FloatE
return cloned;
}
}
}

8
designer-realize/src/main/java/com/fr/design/mainframe/HyperlinkGroupPaneActionImpl.java

@ -18,6 +18,7 @@ import com.fr.report.cell.FloatElement;
import com.fr.report.elementcase.TemplateElementCase;
import com.fr.stable.Constants;
import javax.swing.event.ListDataEvent;
import java.awt.Color;
/**
@ -86,7 +87,12 @@ public class HyperlinkGroupPaneActionImpl implements HyperlinkGroupPaneActionPro
frFont = frFont.applyForeground(AdjustWorkBookDefaultStyleUtils.adjustCellElementFontForeground(Color.black));
frFont = frFont.applyUnderline(Constants.LINE_NONE);
}
editCellElement.setStyle(elementStyle.deriveFRFont(frFont));
// 首次添加超链接,将文字样式默认改为蓝色下划线
if (updateNameHyperlinks.size() == 1 && hyperlinkGroupPane.getCurrentEvent() != null && hyperlinkGroupPane.getCurrentEvent().getType() == ListDataEvent.INTERVAL_ADDED) {
editCellElement.setStyle(elementStyle.deriveFRFont(frFont));
}
try {
editCellElement.setNameHyperlinkGroup((NameJavaScriptGroup) updateNameHyperlinks.clone());
} catch (CloneNotSupportedException e) {

5
designer-realize/src/main/java/com/fr/design/mainframe/WorkBookModelAdapter.java

@ -2,6 +2,7 @@ package com.fr.design.mainframe;
import com.fr.base.Parameter;
import com.fr.base.TableData;
import com.fr.base.param.ParameterSource;
import com.fr.data.TableDataSource;
import com.fr.design.DesignModelAdapter;
import com.fr.design.bridge.DesignToolbarProvider;
@ -17,8 +18,8 @@ import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.stable.bridge.StableFactory;
import com.fr.stable.js.WidgetName;
import com.fr.util.ParameterApplyHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@ -139,7 +140,7 @@ public class WorkBookModelAdapter extends DesignModelAdapter<WorkBook, JWorkBook
// 添加模板参数
ReportParameterAttr parameterAttr = this.getBook().getReportParameterAttr();
if (parameterAttr != null) {
ParameterApplyHelper.addPara2Map(map, parameterAttr.getParameters());
ParameterApplyHelper.addPara2Map(map, parameterAttr.getParameters(), null, ParameterSource.TEMPLATE_SOURCE);
}
}

171
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java

@ -12,8 +12,10 @@ 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.ilable.UILabel;
import com.fr.design.gui.ispinner.UISpinner;
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.design.layout.VerticalFlowLayout;
@ -58,6 +60,8 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
private static final int HEAD_HEIGTH = 24;
private static final int COMBO_WIDTH = 154;
private static final int BUTTON_GROUP_WIDTH = 140;
private static final double f = TableLayout.FILL;
private static final double p = TableLayout.PREFERRED;
// normal
private UIButtonGroup autoshrik;
@ -67,8 +71,20 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
private UIComboBox showContent;
//内容提示
private UIButtonGroup tooltipButtonGroup;
private CardLayout tooltipLayout;
private JPanel tooltipPane;
private UITextField tooltipTextField;
//文本超出时隐藏
private UICheckBox textOverflowCheckBox;
private UIComboBox showPartComboBox;
private CardLayout showPartLayout;
private JPanel showPartPane;
private UISpinner showCharNums;
private UIComboBox textOverflowTypeComboBox;
private UITextField fileNameTextField;
// 分页
@ -214,17 +230,16 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
private JPanel seniorUpPane() {
JPanel pane = new JPanel(new BorderLayout());
// TODO: 方法之间的耦合还比较严重。现在必须先执行 createShowContentPane,再执行 createSeniorCheckPane。否则出现 npe。
pane.add(createTextOverflowPane(), BorderLayout.SOUTH);
pane.add(createShowContentPane(), BorderLayout.CENTER);
pane.add(createSeniorCheckPane(), BorderLayout.NORTH);
return pane;
}
private JPanel createShowContentPane() {
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = {p, p, p};
double[] rowSize = {p, p, p, p};
double[] colSize = {f, COMBO_WIDTH};
int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}};
int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}};
JPanel fileNamePane = createNormal();
fileNamePane.setBorder(BorderFactory.createEmptyBorder(0,12,0,0));
@ -233,21 +248,96 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
UIComponentUtils.setLineWrap(showContentLabel);
UILabel toolTipLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip"));
JPanel toolTipTextFieldWrapper = new JPanel(new BorderLayout());
toolTipTextFieldWrapper.add(tooltipTextField, BorderLayout.NORTH);
tooltipLayout = new CardLayout();
tooltipPane = new JPanel(tooltipLayout);
tooltipPane.add(new JPanel(), "none");
tooltipPane.add(tooltipTextField, "content");
tooltipPane.setPreferredSize(new Dimension(0, 0));
tooltipButtonGroup = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_Custom"), Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_CellValue")});
tooltipButtonGroup.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (tooltipButtonGroup.getSelectedIndex() == 0) {
tooltipPane.setPreferredSize(new Dimension(154, 20));
tooltipLayout.show(tooltipPane, "content");
} else {
tooltipLayout.show(tooltipPane, "none");
tooltipPane.setPreferredSize(new Dimension(0, 0));
}
}
});
Component[][] components = new Component[][]{
new Component[]{showContentLabel, UIComponentUtils.wrapWithBorderLayoutPane(showContent)},
new Component[]{fileNamePane, null}, // 选择"用下载连接显示二进制内容"时,会显示这一行的面板
new Component[]{toolTipLabel, toolTipTextFieldWrapper}
new Component[]{toolTipLabel, tooltipButtonGroup}, // “自定义”or"单元格值"
new Component[]{null, tooltipPane} // 选择“自定义”时显示这一行
};
JPanel showContentPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, colSize, rowCount, LayoutConstants.VGAP_LARGE, LayoutConstants.VGAP_MEDIUM);
showContentPane.setBorder(BorderFactory.createEmptyBorder(6, 0, 12, 0));
showContentPane.setBorder(BorderFactory.createEmptyBorder(6, 0, 6, 0));
return showContentPane;
}
private JPanel createTextOverflowPane() {
showPartLayout = new CardLayout();
showPartPane = new JPanel(showPartLayout);
showCharNums = new UISpinner(0, Integer.MAX_VALUE, 1, 10);
JPanel showPartNumPane = new JPanel(new BorderLayout(4, 0));
showPartNumPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Nums")), BorderLayout.WEST);
showPartNumPane.add(showCharNums, BorderLayout.CENTER);
showPartPane.add(new JPanel(), "none");
showPartPane.add(showPartNumPane, "content");
showPartComboBox = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_CharNum"), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_CellWidth")});
showPartComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (showPartComboBox.getSelectedIndex() == 0) {
showPartPane.setPreferredSize(new Dimension(70, 20));
showPartLayout.show(showPartPane, "content");
} else {
showPartLayout.show(showPartPane, "none");
showPartPane.setPreferredSize(new Dimension(0, 0));
}
}
});
textOverflowTypeComboBox = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Ellipsis"), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_NoneSymbol")});
UILabel showPartLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_ShowPart") + ":");
UILabel hideTypeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideType") + ":");
Component[][] textOverflowComponents = new Component[][]{
new Component[]{showPartLabel, showPartComboBox, showPartPane},
new Component[]{hideTypeLabel, textOverflowTypeComboBox, null}
};
JPanel textOverflowComPane = TableLayoutHelper.createTableLayoutPane(textOverflowComponents, new double[]{p, p}, new double[]{p, f, p});
textOverflowComPane.setVisible(false);
textOverflowCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideWhenOverflow"));
textOverflowCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
textOverflowComPane.setVisible(e.getStateChange() == ItemEvent.SELECTED);
if (e.getStateChange() == ItemEvent.SELECTED) {
if (showPartComboBox.getSelectedIndex() == 0) {
showPartPane.setPreferredSize(new Dimension(70, 20));
showPartLayout.show(showPartPane, "content");
} else {
showPartLayout.show(showPartPane, "none");
showPartPane.setPreferredSize(new Dimension(0, 0));
}
noAutoRadioButton.setSelected(true);
}
}
});
JPanel dynamicPaneWrapper = FRGUIPaneFactory.createBorderLayout_S_Pane();
dynamicPaneWrapper.add(textOverflowComPane);
JPanel textOverflowPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
textOverflowPane.add(textOverflowCheckBox, BorderLayout.NORTH);
textOverflowPane.add(dynamicPaneWrapper, BorderLayout.CENTER);
textOverflowPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
return textOverflowPane;
}
private JPanel createSeniorCheckPane() {
previewCellContent.setBorder(UIConstants.CELL_ATTR_ZEROBORDER);
printAndExportContent.setBorder(UIConstants.CELL_ATTR_ZEROBORDER);
@ -371,6 +461,11 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
insertRowPolicyButtonGroup.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_InsertRow_Policy"));
valueEditor.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_InsertRow_Policy"));
pageFixedRowDataCheckBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_Page_Fixed_Row_Cell"));
tooltipButtonGroup.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_Button_Group"));
textOverflowCheckBox.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideWhenOverflow"));
showPartComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_ShowPart"));
showCharNums.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Nums"));
textOverflowTypeComboBox.setGlobalName(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideType"));
}
@ -429,7 +524,40 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
} else {
showContent.setSelectedItem(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Default"));
}
tooltipTextField.setText(cellGUIAttr.getTooltipText());
if (cellGUIAttr.isCustomTooltip()) {
tooltipButtonGroup.setSelectedIndex(0);
tooltipTextField.setText(cellGUIAttr.getTooltipText());
} else {
tooltipButtonGroup.setSelectedIndex(1);
}
if (tooltipButtonGroup.getSelectedIndex() == 0) {
tooltipPane.setPreferredSize(new Dimension(100, 20));
tooltipLayout.show(tooltipPane, "content");
} else {
tooltipLayout.show(tooltipPane, "none");
tooltipPane.setPreferredSize(new Dimension(0, 0));
}
tooltipPane.setVisible(true);
if (cellGUIAttr.isHideTextWhenOverflow()) {
textOverflowCheckBox.setSelected(true);
if (cellGUIAttr.isShowCharNum()) {
showPartComboBox.setSelectedIndex(0);
showCharNums.setValue(cellGUIAttr.getShowCharNums());
} else {
showPartComboBox.setSelectedIndex(1);
}
showPartPane.setVisible(true);
if (cellGUIAttr.isTextOverflowEllipsis()) {
textOverflowTypeComboBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Ellipsis"));
} else {
textOverflowTypeComboBox.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_NoneSymbol"));
}
} else {
showPartComboBox.setSelectedIndex(cellGUIAttr.isShowCharNum() ? 0 : 1);
showCharNums.setValue(cellGUIAttr.getShowCharNums());
textOverflowTypeComboBox.setSelectedIndex(cellGUIAttr.isTextOverflowEllipsis() ? 0 : 1);
textOverflowCheckBox.setSelected(false);
}
CellPageAttr cellPageAttr = cellElement.getCellPageAttr(); // 分页
if (cellPageAttr == null) {
cellPageAttr = new CellPageAttr();
@ -521,7 +649,18 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
cellGUIAttr.setFileName(fileNameTextField.getText());
}
}
if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip_Button_Group"))) {
cellGUIAttr.setCustomTooltip(tooltipButtonGroup.getSelectedIndex() == 0);
if (tooltipButtonGroup.getSelectedIndex() == 0) {
if (tooltipTextField.getText() == null || tooltipTextField.getText().trim().length() <= 0) {
cellGUIAttr.setTooltipText(fieldName);
} else {
cellGUIAttr.setTooltipText(tooltipTextField.getText());
}
} else if (tooltipButtonGroup.getSelectedIndex() == 1) {
cellGUIAttr.setTooltipText("=$$$");
}
}
if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_CellWrite_ToolTip"))) {
if (tooltipTextField.getText() == null || tooltipTextField.getText().trim().length() <= 0) {
cellGUIAttr.setTooltipText(fieldName);
@ -529,6 +668,18 @@ public class CellOtherSetPane extends AbstractCellAttrPane {
cellGUIAttr.setTooltipText(tooltipTextField.getText());
}
}
if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideWhenOverflow"))) {
cellGUIAttr.setHideTextWhenOverflow(textOverflowCheckBox.isSelected());
}
if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_ShowPart"))) {
cellGUIAttr.setShowCharNum(showPartComboBox.getSelectedIndex() == 0);
}
if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_Nums"))) {
cellGUIAttr.setShowCharNums((int) showCharNums.getValue());
}
if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_CellWrite_TextOverflow_HideType"))) {
cellGUIAttr.setTextOverflowEllipsis(textOverflowTypeComboBox.getSelectedIndex() == 0);
}
// 如果与默认的CellGUIAttr相同,就不用保存这个属性了
if (ComparatorUtils.equals(cellGUIAttr, CellGUIAttr.DEFAULT_CELLGUIATTR)) {
cellElement.setCellGUIAttr(cellNullGUIAttr);

11
designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java

@ -30,6 +30,7 @@ import com.fr.design.selection.SelectableElement;
import com.fr.design.selection.Selectedable;
import com.fr.design.selection.SelectionListener;
import com.fr.form.FormElementCaseProvider;
import com.fr.form.fit.common.LightTool;
import com.fr.form.main.Form;
import com.fr.grid.Grid;
import com.fr.grid.selection.CellSelection;
@ -69,8 +70,12 @@ public class FormElementCaseDesigner
}
public FormElementCaseDesigner(T sheet, Form form) {
this(sheet, form.getFormMobileAttr().isMobileOnly(), LightTool.containNewFormFlag(form));
}
public FormElementCaseDesigner(T sheet, boolean isMobileOnly, boolean isNewForm) {
super(sheet);
elementCasePane = initElementCasePane(sheet, form);
elementCasePane = initElementCasePane(sheet, isMobileOnly, isNewForm);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
elementCasePane.setSelection(getDefaultSelectElement());
this.add(elementCasePane, BorderLayout.CENTER);
@ -84,8 +89,8 @@ public class FormElementCaseDesigner
}
protected FormElementCasePaneDelegate initElementCasePane(T sheet, Form form){
return new FormElementCasePaneDelegate((FormElementCase) sheet, form);
protected FormElementCasePaneDelegate initElementCasePane(T sheet, boolean isMobileOnly, boolean isNewForm){
return new FormElementCasePaneDelegate((FormElementCase) sheet, isMobileOnly, isNewForm);
}
@Override

21
designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCasePaneDelegate.java

@ -9,6 +9,7 @@ import com.fr.design.actions.form.FormECFrozenAction;
import com.fr.design.designer.creator.XElementCase;
import com.fr.design.event.TargetModifiedEvent;
import com.fr.design.event.TargetModifiedListener;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fit.NewUIModeCellElementPainter;
import com.fr.design.fit.common.FormDesignerUtil;
import com.fr.design.gui.frpane.HyperlinkGroupPane;
@ -40,13 +41,16 @@ import java.awt.Rectangle;
*/
public class FormElementCasePaneDelegate extends ElementCasePane<FormElementCase>{
public FormElementCasePaneDelegate(FormElementCase sheet, Form form) {
this(sheet, form.getFormMobileAttr().isMobileOnly(), LightTool.containNewFormFlag(form));
}
public FormElementCasePaneDelegate(FormElementCase sheet, boolean isMobileOnly, boolean isNewForm) {
super(sheet);
this.getGrid().setPaginateLineShowType(form.getFormMobileAttr().isMobileOnly()
this.getGrid().setPaginateLineShowType(isMobileOnly
? Grid.SINGLE_HORIZONTAL_PAGINATE_LINE
: Grid.NO_PAGINATE_LINE);
if (LightTool.containNewFormFlag(form)){
if (isNewForm){
this.getGrid().setCellElementPainter(new NewUIModeCellElementPainter());
}
this.addSelectionChangeListener(new SelectionListener() {
@ -68,8 +72,17 @@ public class FormElementCasePaneDelegate extends ElementCasePane<FormElementCase
}
private Rectangle getBoundsLineRect(TemplateElementCase elementCase) {
FormDesigner designer = WidgetPropertyPane.getInstance().getEditingFormDesigner();
final Rectangle rectangle = new Rectangle();
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (!(template instanceof JForm)) {
return rectangle;
}
FormDesigner designer = ((JForm) template).getFormDesign();
if (designer == null) {
return rectangle;
}
XElementCase xElementCase = FormDesignerUtil.getXelementCase(designer.getRootComponent(), (FormElementCase) elementCase);
if (xElementCase != null) {
rectangle.setBounds(xElementCase.getBounds());

33
designer-realize/src/main/java/com/fr/design/mainframe/form/FormReportComponentComposite.java

@ -2,7 +2,6 @@ package com.fr.design.mainframe.form;
import com.fr.base.DynamicUnitList;
import com.fr.base.ScreenResolution;
import com.fr.common.inputevent.InputEventBaseOnOS;
import com.fr.design.cell.bar.DynamicScrollBar;
import com.fr.design.event.TargetModifiedEvent;
import com.fr.design.event.TargetModifiedListener;
@ -11,9 +10,11 @@ import com.fr.design.mainframe.BaseJForm;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerUIModeConfig;
import com.fr.design.mainframe.ElementCasePane;
import com.fr.design.mainframe.JDashboard;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.JFormSliderPane;
import com.fr.design.mainframe.ReportComponent;
import com.fr.design.mainframe.ReportComponentCompositeMouseWheelHandler;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.JTemplateProvider;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.form.FormElementCaseContainerProvider;
import com.fr.form.FormElementCaseProvider;
@ -24,11 +25,11 @@ import com.fr.report.worksheet.FormElementCase;
import com.fr.stable.AssistUtils;
import com.fr.stable.Constants;
import javax.swing.*;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.*;
import java.awt.BorderLayout;
/**
* 整个FormElementCase编辑区域 包括滚动条中间的grid或者聚合块下面的sheetTab
@ -40,19 +41,19 @@ public class FormReportComponentComposite extends JComponent implements TargetMo
private static final int MIN = 10;
private static final int DIR = 10;
private static final double MIN_TIME = 0.4;
public FormElementCaseDesigner elementCaseDesigner;
private BaseJForm jForm;
public final FormElementCaseDesigner elementCaseDesigner;
private final JTemplateProvider jTemplate;
private FormTabPane sheetNameTab;
private final FormTabPane sheetNameTab;
private JPanel hbarContainer;
private JFormSliderPane jSliderContainer;
public FormReportComponentComposite(BaseJForm jform, FormElementCaseDesigner elementCaseDesign, FormElementCaseContainerProvider ecContainer) {
this.jForm = jform;
public FormReportComponentComposite(JTemplateProvider jTemplate, JDashboard jDashboard, FormElementCaseDesigner<?,?,?> elementCaseDesign, String ecContainerName) {
this.jTemplate = jTemplate;
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.elementCaseDesigner = elementCaseDesign;
this.add(elementCaseDesigner, BorderLayout.CENTER);
sheetNameTab = new FormTabPane(ecContainer, jform);
sheetNameTab = new FormTabPane(ecContainerName, jDashboard);
this.add(createSouthControlPane(), BorderLayout.SOUTH);
jSliderContainer.addValueChangeListener(showValSpinnerChangeListener);
this.elementCaseDesigner.elementCasePane.getGrid().addMouseWheelListener(new FormReportComponentCompositeMouseWheelHandler(this));
@ -60,6 +61,10 @@ public class FormReportComponentComposite extends JComponent implements TargetMo
this.jSliderContainer.setShowValue((ScreenResolution.getScreenResolution() * HUND) / Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION);
}
public FormReportComponentComposite(BaseJForm jform, FormElementCaseDesigner elementCaseDesign, FormElementCaseContainerProvider ecContainer) {
this(jform, jform, elementCaseDesign, ecContainer.getElementCaseContainerName());
}
ChangeListener showValSpinnerChangeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
@ -167,7 +172,7 @@ public class FormReportComponentComposite extends JComponent implements TargetMo
}
public void setComposite() {
DesignerContext.getDesignerFrame().resetToolkitByPlus((ToolBarMenuDockPlus) jForm);
DesignerContext.getDesignerFrame().resetToolkitByPlus((ToolBarMenuDockPlus) jTemplate);
this.validate();
this.repaint(40);
}
@ -182,7 +187,7 @@ public class FormReportComponentComposite extends JComponent implements TargetMo
* 模板更新
*/
public void fireTargetModified() {
jForm.fireTargetModified();
jTemplate.fireTargetModified();
}
public JFormSliderPane getSliderContainer() {

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

Loading…
Cancel
Save