Browse Source

恢复代码到删除前一个节点

research/11.0
ju 3 years ago
parent
commit
a694af0ccf
  1. 1
      build.gradle
  2. 94
      designer-base/src/main/java/com/fr/design/DesignModelAdapter.java
  3. 47
      designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java
  4. 49
      designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java
  5. 154
      designer-base/src/main/java/com/fr/design/data/DesignerStrategyConfigUtils.java
  6. 225
      designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java
  7. 766
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  8. 504
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  9. 12
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java
  10. 22
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  11. 1
      designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java
  12. 41
      designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java
  13. 40
      designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java
  14. 1
      designer-base/src/main/java/com/fr/file/FILEChooserPane.java
  15. 60
      designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java
  16. 97
      designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java
  17. 116
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java
  18. 221
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java
  19. 55
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java
  20. 64
      designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java
  21. 25
      designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java
  22. 25
      designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java
  23. 71
      designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java
  24. 22
      designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java
  25. 61
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java
  26. 223
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java
  27. 79
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java
  28. 204
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java
  29. 130
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java
  30. 70
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java
  31. 110
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java
  32. 86
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java
  33. 70
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java
  34. 72
      designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java
  35. 55
      designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java
  36. 79
      designer-base/src/main/java/com/fr/nx/app/designer/utils/DesignerCptxFileUtils.java
  37. 2
      designer-base/src/main/resources/com/fr/design/images/bbs/bbs_normal.svg
  38. 8
      designer-base/src/main/resources/com/fr/design/images/buttonicon/prewidget_normal.svg
  39. 7
      designer-base/src/main/resources/com/fr/design/images/buttonicon/widget/files_up_normal.svg
  40. 16
      designer-base/src/main/resources/com/fr/design/images/control/addPopup_disabled.svg
  41. 14
      designer-base/src/main/resources/com/fr/design/images/control/addPopup_normal.svg
  42. BIN
      designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png
  43. BIN
      designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png
  44. 8
      designer-base/src/main/resources/com/fr/design/images/control/edit_disabled.svg
  45. 8
      designer-base/src/main/resources/com/fr/design/images/control/edit_normal.svg
  46. 11
      designer-base/src/main/resources/com/fr/design/images/control/remove_disabled.svg
  47. 9
      designer-base/src/main/resources/com/fr/design/images/control/remove_normal.svg
  48. 11
      designer-base/src/main/resources/com/fr/design/images/m_file/preview_disabled.svg
  49. 9
      designer-base/src/main/resources/com/fr/design/images/m_file/preview_normal.svg
  50. 239
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java
  51. 85
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java
  52. 32
      designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java
  53. 27
      designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java
  54. 35
      designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java
  55. 124
      designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java
  56. 58
      designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java
  57. 11
      designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java
  58. 83
      designer-form/src/main/java/com/fr/design/actions/FormFitAttrAction.java
  59. 115
      designer-form/src/main/java/com/fr/design/actions/NewFormMobileAttrAction.java
  60. 2
      designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java
  61. 3
      designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java
  62. 6
      designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java
  63. 4
      designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java
  64. 124
      designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java
  65. 36
      designer-form/src/main/java/com/fr/design/fit/FitStateCompatible.java
  66. 133
      designer-form/src/main/java/com/fr/design/fit/JFormType.java
  67. 285
      designer-form/src/main/java/com/fr/design/fit/NewJForm.java
  68. 27
      designer-form/src/main/java/com/fr/design/fit/PX.java
  69. 32
      designer-form/src/main/java/com/fr/design/fit/PXReportLengthUNIT.java
  70. 91
      designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java
  71. 161
      designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java
  72. 27
      designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteLayoutExtendDefinePane.java
  73. 246
      designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java
  74. 107
      designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java
  75. 303
      designer-form/src/main/java/com/fr/design/fit/attrpane/RootDesignExtendDefinePane.java
  76. 225
      designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java
  77. 1266
      designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java
  78. 45
      designer-form/src/main/java/com/fr/design/fit/common/FormDesignerUtil.java
  79. 177
      designer-form/src/main/java/com/fr/design/fit/common/LayoutTool.java
  80. 2030
      designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java
  81. 835
      designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java
  82. 214
      designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java
  83. 303
      designer-form/src/main/java/com/fr/design/fit/menupane/BrowserFitAttrPane.java
  84. 76
      designer-form/src/main/java/com/fr/design/fit/menupane/FitPreviewPane.java
  85. 80
      designer-form/src/main/java/com/fr/design/fit/menupane/FitRadioGroup.java
  86. 17
      designer-form/src/main/java/com/fr/design/fit/menupane/FontRadioGroup.java
  87. 58
      designer-form/src/main/java/com/fr/design/fit/menupane/FormFitAttrPane.java
  88. 287
      designer-form/src/main/java/com/fr/design/fit/toolbar/SwitchAction.java
  89. 4
      designer-form/src/main/java/com/fr/design/mainframe/CoverReportPane.java
  90. 16
      designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java
  91. 28
      designer-form/src/main/java/com/fr/design/mainframe/FormArea.java
  92. 3
      designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java
  93. 23
      designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java
  94. 53
      designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java
  95. 54
      designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java
  96. BIN
      designer-form/src/main/resources/com/fr/design/form/images/developer_preview.png
  97. BIN
      designer-form/src/main/resources/com/fr/design/form/images/developer_preview24.png
  98. BIN
      designer-form/src/main/resources/com/fr/design/form/images/icon_form_tab.png
  99. BIN
      designer-form/src/main/resources/com/fr/design/form/images/icon_switch.png
  100. BIN
      designer-form/src/main/resources/com/fr/design/form/images/icon_switch_disable.png
  101. Some files were not shown because too many files have changed in this diff Show More

1
build.gradle

@ -73,6 +73,7 @@ allprojects {
implementation 'com.fr.decision:fine-decision:' + frVersion
implementation 'com.fr.schedule:fine-schedule:' + frVersion
implementation 'com.fr.report:engine-report:' + frDevVersion
implementation 'com.fr.report:engine-x:' + frDevVersion
implementation 'com.fr.report:engine-chart:' + frDevVersion
implementation 'com.fr.report:engine-i18n:' + frDevVersion
implementation 'com.fr.design:design-i18n:' + frDevVersion

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

@ -1,11 +1,8 @@
package com.fr.design;
import com.fr.base.Parameter;
import com.fr.base.ParameterConfig;
import com.fr.base.TableData;
import com.fr.base.io.BaseBook;
import com.fr.data.TableDataSource;
import com.fr.data.operator.DataOperator;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.mainframe.JTemplate;
@ -14,14 +11,9 @@ import com.fr.form.ui.DataControl;
import com.fr.form.ui.MultiFileEditor;
import com.fr.form.ui.Widget;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -48,7 +40,7 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
/**
* 全部的参数包括全局参数模板参数和数据集参数
*/
protected Parameter[] parameters;
private Parameter[] parameters;
/**
* 数据集参数
@ -60,12 +52,6 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
*/
private Parameter[] templateParameters;
/**
* 数据集参数缓存 更新时刷新
*/
protected Map<String, ParameterProvider[]> tableDataParametersMap = new HashMap<>();
public DesignModelAdapter(S jTemplate) {
this.jTemplate = jTemplate;
@ -255,79 +241,6 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
}
protected void addTableDataParameters(Map<String, ParameterProvider> map, Filter<ParameterProvider> filter) {
Iterator<String> it = this.getBook().getTableDataNameIterator();
try {
// 清空下缓存
tableDataParametersMap.clear();
while (it.hasNext()) {
String name = it.next();
TableData tableData = this.getBook().getTableData(name);
ParameterProvider[] parameterProviders = DataOperator.getInstance().getTableDataParameters(tableData);
if (filter != null) {
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter);
} else {
ParameterApplyHelper.addPara2Map(map, parameterProviders);
}
tableDataParametersMap.put(name, parameterProviders);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
protected void updateTableDataParameters(String oldName,
String tdName,
TableData tableData,
Map<String, ParameterProvider> map,
Filter<ParameterProvider> filter) {
ParameterProvider[] providers = null;
if (!ComparatorUtils.equals(oldName, tdName)) {
// 更新下缓存名称 替换下数据集名称
providers = tableDataParametersMap.remove(oldName);
if (providers != null) {
tableDataParametersMap.put(tdName, providers);
}
}
try {
for (Map.Entry<String, ParameterProvider[]> entry : tableDataParametersMap.entrySet()) {
ParameterProvider[] parameterProviders;
if (ComparatorUtils.equals(entry.getKey(), tdName)) {
parameterProviders = DataOperator.getInstance().getTableDataParameters(tableData);
// 用来更新缓存
providers = parameterProviders;
} else {
parameterProviders = entry.getValue();
}
if (filter != null) {
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter);
} else {
ParameterApplyHelper.addPara2Map(map, parameterProviders);
}
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (providers != null) {
// 更新缓存
tableDataParametersMap.put(tdName, providers);
}
}
protected void addGlobalParameters(Map<String, ParameterProvider> map) {
// 添加全局参数
Parameter[] glbParas = ParameterConfig.getInstance().getGlobalParameters();
ParameterApplyHelper.addPara2Map(map, glbParas);
}
/**
* 环境改变.
*/
@ -338,11 +251,6 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
*/
public abstract void parameterChanged();
/**
* 数据集参数改变
*/
public abstract void tableDataParametersChanged(String oldName, String tdName, TableData tableData);
/**
* 控件配置改变.
*/

47
designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java

@ -0,0 +1,47 @@
package com.fr.design.actions.file;
import com.fr.base.BaseUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.menu.MenuKeySet;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.transform.ui.BatchTransformPane;
import javax.swing.KeyStroke;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
/**
* Created by kerry on 2019-12-10
*/
public class BatchCompileAction extends UpdateAction {
public BatchCompileAction() {
this.setMenuKeySet(COMPILE);
this.setName(getMenuKeySet().getMenuKeySetName() + "...");
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/batch_transform.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
BatchTransformPane batchTransformPane = new BatchTransformPane();
Dialog dialog = batchTransformPane.showDialog();
dialog.setVisible(true);
}
private static final MenuKeySet COMPILE = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'C';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
}

49
designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java

@ -0,0 +1,49 @@
package com.fr.design.actions.server;
import com.fr.base.BaseUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.menu.MenuKeySet;
import com.fr.design.utils.DesignUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.web.URLConstants;
import com.fr.stable.StableUtils;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
/**
* @author Maksim
* Created in 2020/11/5 11:44 上午
*/
public class LocalAnalyzerAction extends UpdateAction {
public LocalAnalyzerAction() {
this.setMenuKeySet(ANALYZER);
this.setName(getMenuKeySet().getMenuKeySetName());
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/analyzer.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
String path = StableUtils.pathJoin("/url", URLConstants.ANALYZE_VIEW);
DesignUtils.visitEnvServerByParameters(path, new String[]{}, new String[]{});
}
private static final MenuKeySet ANALYZER = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'R';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Analyzer_Menu_Name");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
}

154
designer-base/src/main/java/com/fr/design/data/DesignerStrategyConfigUtils.java

@ -0,0 +1,154 @@
package com.fr.design.data;
import com.fr.base.io.IOFile;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.JTemplate;
import com.fr.esd.core.strategy.config.StrategyConfig;
import com.fr.esd.core.strategy.config.StrategyConfigHelper;
import com.fr.esd.core.strategy.persistence.StrategyConfigsAttr;
import com.fr.esd.event.DSMapping;
import com.fr.esd.event.DsNameTarget;
import com.fr.esd.event.StrategyEventsNotifier;
import com.fr.esd.event.xml.XMLSavedHook;
import com.fr.file.FILE;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author rinoux
* @version 10.0
* Created by rinoux on 2020/10/28
*/
public class DesignerStrategyConfigUtils {
/**
* 获取当前编辑模版的数据集缓存配置属性
*
* @return
*/
private static StrategyConfigsAttr getStrategyConfigsAttr() {
StrategyConfigsAttr attr;
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (jTemplate != null) {
IOFile ioFile = (IOFile) jTemplate.getTarget();
attr = ioFile.getAttrMark(StrategyConfigsAttr.ATTR_MARK);
if (attr == null) {
attr = new StrategyConfigsAttr();
ioFile.addAttrMark(attr);
}
//新建模版此时不存在,不需要注册钩子
if (attr.getXmlSavedHook() == null && WorkContext.getWorkResource().exist(jTemplate.getPath())) {
attr.setXmlSavedHook(new StrategyConfigsAttrSavedHook(jTemplate.getPath(), attr));
}
return attr;
} else {
throw new IllegalStateException("[ESD]No editing template found.");
}
}
/**
* 当前编辑的模版是否被批量开启
*
* @return
*/
public static boolean isEditingTemplateRecommended() {
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (jTemplate != null) {
FILE file = jTemplate.getEditingFILE();
if (file != null) {
String path = file.getPath();
return StrategyConfigHelper.recommended(path);
}
}
return false;
}
/**
* 获取模版数据集配置
*
* @param dsName
* @return
*/
public static StrategyConfig getStrategyConfig(String dsName) {
return getStrategyConfigsAttr().getStrategyConfig(dsName);
}
/**
* 移除模版数据集配置
*
* @param dsName
* @return
*/
public static StrategyConfig removeStrategyConfig(String dsName) {
return getStrategyConfigsAttr().removeStrategyConfig(dsName);
}
/**
* 添加模版数据集配置
*
* @param strategyConfig
*/
public static void addStrategyConfig(StrategyConfig strategyConfig) {
getStrategyConfigsAttr().addStrategyConfig(strategyConfig);
}
private static class StrategyConfigsAttrSavedHook implements XMLSavedHook<StrategyConfigsAttr> {
private static final long serialVersionUID = -8843201977112289321L;
private final String tplPath;
private final Map<String, StrategyConfig> origStrategyConfigs;
public StrategyConfigsAttrSavedHook(String tplPath, StrategyConfigsAttr raw) {
this.tplPath = tplPath;
this.origStrategyConfigs = new HashMap<>();
this.initOrigStrategyConfigs(raw);
}
private void initOrigStrategyConfigs(StrategyConfigsAttr raw) {
origStrategyConfigs.clear();
raw.getStrategyConfigs().forEach((k, v) -> {
try {
origStrategyConfigs.put(k, v.clone());
} catch (CloneNotSupportedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
});
}
@Override
public void doAfterSaved(StrategyConfigsAttr saved) {
FineLoggerFactory.getLogger().info("[ESD]Write StrategyConfigsAttr done, now check change.");
Set<String> dsNames = new HashSet<>();
dsNames.addAll(origStrategyConfigs.keySet());
dsNames.addAll(saved.getStrategyConfigs().keySet());
if (StringUtils.isNotEmpty(tplPath)) {
dsNames.forEach(dsName -> {
if (StringUtils.isNotEmpty(dsName)) {
StrategyEventsNotifier.compareAndFireConfigEvents(origStrategyConfigs.get(dsName), saved.getStrategyConfig(dsName), new DSMapping(tplPath, new DsNameTarget(dsName)));
}
});
}
initOrigStrategyConfigs(saved);
}
}
}

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

@ -0,0 +1,225 @@
package com.fr.design.data.datapane;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.esd.common.CacheConstants;
import com.fr.esd.core.strategy.config.StrategyConfig;
import com.fr.esd.core.strategy.config.StrategyConfigHelper;
import com.fr.esd.util.ESDUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import javax.swing.AbstractAction;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author rinoux
* @version 10.0
* Created by rinoux on 2020/7/22
*/
public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
private UIRadioButton selectAutoUpdate;
private UIRadioButton selectBySchema;
private UICheckBox shouldEvolve;
private UILabel updateIntervalCheckTips;
private UITextField updateInterval;
private UITextField schemaTime;
private ActionLabel actionLabel;
private UILabel schemaTimeCheckTips;
private final boolean global;
private StrategyConfig strategyConfig;
private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html";
public ESDStrategyConfigPane(boolean global) {
this.global = global;
init();
}
private void init() {
setLayout(FRGUIPaneFactory.createM_BorderLayout());
this.selectAutoUpdate = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Every_Interval"));
this.updateInterval = new UITextField(4);
this.shouldEvolve = new UICheckBox(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Auto_Evolved_Strategy"), false);
this.shouldEvolve.setEnabled(false);
this.updateIntervalCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Interval_Format"));
this.updateIntervalCheckTips.setForeground(Color.RED);
this.updateIntervalCheckTips.setVisible(false);
this.selectBySchema = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron"));
this.schemaTime = new UITextField(10);
this.schemaTimeCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format"));
this.schemaTimeCheckTips.setVisible(false);
this.schemaTimeCheckTips.setForeground(Color.RED);
this.selectAutoUpdate.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent e) {
ESDStrategyConfigPane.this.selectBySchema.setSelected(!ESDStrategyConfigPane.this.selectAutoUpdate.isSelected());
ESDStrategyConfigPane.this.schemaTime.setEnabled(false);
ESDStrategyConfigPane.this.updateInterval.setEnabled(true);
ESDStrategyConfigPane.this.shouldEvolve.setEnabled(true);
}
});
this.selectBySchema.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent e) {
ESDStrategyConfigPane.this.selectAutoUpdate.setSelected(!ESDStrategyConfigPane.this.selectBySchema.isSelected());
ESDStrategyConfigPane.this.schemaTime.setEnabled(true);
ESDStrategyConfigPane.this.updateInterval.setEnabled(false);
ESDStrategyConfigPane.this.shouldEvolve.setEnabled(false);
}
});
JPanel pane = FRGUIPaneFactory.createVerticalTitledBorderPane(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Update_Strategy"));
add(pane, BorderLayout.NORTH);
JPanel row1 = GUICoreUtils.createFlowPane(new Component[]{
this.selectAutoUpdate,
this.updateInterval,
new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Minute_Update_Cache")),
this.shouldEvolve,
this.updateIntervalCheckTips
}, 0, 5);
pane.add(row1);
ActionLabel actionLabel = new ActionLabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron_Help"));
actionLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
Desktop.getDesktop().browse(new URI(CRON_HELP_URL));
} catch (Exception exp) {
FineLoggerFactory.getLogger().error(exp.getMessage(), e);
}
}
});
JPanel row2 = GUICoreUtils.createFlowPane(new Component[]{
this.selectBySchema,
this.schemaTime,
actionLabel,
this.schemaTimeCheckTips
}, 0, 5);
pane.add(row2);
}
public void populateBean(StrategyConfig ob) {
if (ob == null && !global) {
ob = StrategyConfigHelper.createStrategyConfig(true, false, true);
}
this.strategyConfig = ob;
this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.valueOf(ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE));
this.schemaTime.setText(StringUtils.join(",", ob.getUpdateSchema().toArray(new String[0])));
this.shouldEvolve.setSelected(ob.shouldEvolve());
this.selectBySchema.setSelected(ob.isScheduleBySchema());
this.selectAutoUpdate.setSelected(!ob.isScheduleBySchema());
if (global) {
//使用全局配置,禁用面板编辑
disablePane();
} else {
setSchemaEnable(!this.selectAutoUpdate.isSelected());
}
}
private void disablePane() {
this.selectAutoUpdate.setEnabled(false);
this.updateInterval.setEnabled(false);
this.shouldEvolve.setEnabled(false);
this.selectBySchema.setEnabled(false);
this.schemaTime.setEnabled(false);
}
private void setSchemaEnable(boolean enable) {
this.updateInterval.setEnabled(!enable);
this.shouldEvolve.setEnabled(!enable);
this.schemaTime.setEnabled(enable);
}
public StrategyConfig updateBean() {
StrategyConfig config = null;
if (!this.global) {
try {
//这里是new的config
config = this.strategyConfig.clone();
if (this.selectBySchema.isSelected()) {
List<String> schemaTimes = new ArrayList<>();
String text = this.schemaTime.getText();
if (ESDUtils.checkUpdateTimeSchema(text)) {
if (ESDUtils.isCronExpression(text)) {
schemaTimes.add(text);
} else {
Collections.addAll(schemaTimes, text.split(","));
}
} else {
this.schemaTimeCheckTips.setVisible(true);
throw new IllegalArgumentException("update schema time format error.");
}
config.setScheduleBySchema(true);
config.setUpdateSchema(schemaTimes);
} else {
String interval = this.updateInterval.getText();
if (checkUpdateInterval(interval)) {
long intervalMillis = StringUtils.isEmpty(interval) ? 0 : (long) (Double.parseDouble(interval) * CacheConstants.MILLIS_OF_MINUTE);
config.setUpdateInterval(intervalMillis);
} else {
this.updateIntervalCheckTips.setVisible(true);
throw new IllegalArgumentException("Error update interval format.");
}
config.setShouldEvolve(this.shouldEvolve.isSelected());
config.setScheduleBySchema(false);
}
} catch (CloneNotSupportedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
return config;
}
private boolean checkUpdateInterval(String intervalValue) {
try {
return !StringUtils.isEmpty(intervalValue) && !(Double.parseDouble(intervalValue) <= 0);
} catch (NumberFormatException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
protected String title4PopupWindow() {
return InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Strategy_Config_Title");
}
}

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

@ -1,8 +1,8 @@
package com.fr.design.data.datapane;
import com.fr.base.BaseUtils;
import com.fr.base.TableData;
import com.fr.data.TableDataSource;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.TableDataSourceDependent;
import com.fr.design.DesignModelAdapter;
import com.fr.design.ExtraDesignClassManager;
@ -11,52 +11,67 @@ import com.fr.design.constants.UIConstants;
import com.fr.design.data.BasicTableDataTreePane;
import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.DesignerStrategyConfigUtils;
import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
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.itextfield.UITextField;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.i18n.Toolkit;
import com.fr.design.icon.IconPathConstants;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.LineSeparator;
import com.fr.design.menu.MenuDef;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef;
import com.fr.esd.core.strategy.config.StrategyConfig;
import com.fr.esd.core.strategy.config.StrategyConfigHelper;
import com.fr.esd.event.DSMapping;
import com.fr.esd.event.DsNameTarget;
import com.fr.esd.event.StrategyEventsNotifier;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext;
import com.fr.general.IOUtils;
import com.fr.general.NameObject;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.core.PropertyChangeAdapter;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.ToolTipManager;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.dnd.DnDConstants;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
public class TableDataTreePane extends BasicTableDataTreePane {
private static TableDataTreePane singleton = new TableDataTreePane();
private static final TableDataTreePane singleton = new TableDataTreePane();
public static final int PLUGIN_LISTENER_PRIORITY = 1;
@ -78,31 +93,42 @@ public class TableDataTreePane extends BasicTableDataTreePane {
}
private TableDataSourceOP op;
private TableDataTree dataTree;
private TableDataTree tableDataTree;
private EditAction editAction;
private RemoveAction removeAction;
private EsdOnAction esdAction;
private EsdOffAction esdOffAction;
private PreviewTableDataAction previewTableDataAction;
private TableDataTreePane() {
initPane();
}
private void initPane() {
this.setLayout(new BorderLayout(4, 0));
this.setBorder(null);
dataTree = new TableDataTree();
ToolTipManager.sharedInstance().registerComponent(dataTree);
//TableDataTree
tableDataTree = new TableDataTree();
ToolTipManager.sharedInstance().registerComponent(tableDataTree);
ToolTipManager.sharedInstance().setDismissDelay(3000);
ToolTipManager.sharedInstance().setInitialDelay(0);
addMenuDef = new MenuDef(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Action_Add"));
addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH);
addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add"));
addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH);
createAddMenuDef();
// 创建插件监听
createPluginListener();
editAction = new EditAction();
removeAction = new RemoveAction();
previewTableDataAction = new PreviewTableDataAction(dataTree);
previewTableDataAction = new PreviewTableDataAction(tableDataTree);
connectionTableAction = new ConnectionTableAction();
esdAction = new EsdOnAction();
esdOffAction = new EsdOffAction();
ToolBarDef toolbarDef = new ToolBarDef();
toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction);
toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction);
UIToolbar toolBar = ToolBarDef.createJToolBar();
toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR));
toolBar.setBorderPainted(true);
@ -112,115 +138,152 @@ public class TableDataTreePane extends BasicTableDataTreePane {
toolbarPane.add(toolBar, BorderLayout.CENTER);
this.add(toolbarPane, BorderLayout.NORTH);
UIScrollPane scrollPane = new UIScrollPane(dataTree);
UIScrollPane scrollPane = new UIScrollPane(tableDataTree);
scrollPane.setBorder(null);
initbuttonGroup();
initButtonGroup();
JPanel jPanel = new JPanel(new BorderLayout(0, 0));
JPanel buttonPane = new JPanel(new GridLayout());
buttonPane.add(buttonGroup, BorderLayout.CENTER);
jPanel.add(buttonPane, BorderLayout.NORTH);
jPanel.add(scrollPane, BorderLayout.CENTER);
this.add(jPanel, BorderLayout.CENTER);
dataTree.addMouseListener(new MouseAdapter() {
tableDataTree.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
checkButtonEnabled();
}
});
dataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, dataTree));
tableDataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, tableDataTree));
// TreeCellEditor
dataTree.setEditable(true);
TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), dataTree, this);
tableDataTree.setEditable(true);
TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this);
treeCellEditor.addCellEditorListener(treeCellEditor);
dataTree.setCellEditor(treeCellEditor);
new TableDataTreeDragSource(dataTree, DnDConstants.ACTION_COPY);
tableDataTree.setCellEditor(treeCellEditor);
new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY);
checkButtonEnabled();
}
private void createPluginListener() {
//菜单栏监听
GeneralContext.listenPluginRunningChanged(new PluginEventListener(PLUGIN_LISTENER_PRIORITY) {
@Override
public void on(PluginEvent event) {
addMenuDef.clearShortCuts();
createAddMenuDef();
}
}, new PluginFilter() {
@Override
public boolean accept(PluginContext context) {
return context.contain(PluginModule.ExtraDesign);
}
});
}
protected void checkButtonEnabled() {
super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, dataTree);
}
/**
* 刷新
*/
@Override
public void refreshDockingView() {
populate(new TableDataSourceOP(tc));
this.checkButtonEnabled();
}
protected void initbuttonGroup() {
// Icon[] iconArray = {BaseUtils.readIcon("/com/fr/design/images/data/datasource.png"), BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png")};
final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA};
String[] textArray = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")};
buttonGroup = new UIHeadGroup(textArray) {
public void tabChanged(int index) {
if (op != null) {
op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]);
addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA ? true : false);
refreshDockingView();
}
@Override
public final void createAddMenuDef() {
TableDataNameObjectCreator[] creators = TableDataCreatorProducer.getInstance().createReportTableDataCreator();
for (final TableDataNameObjectCreator creator : creators) {
if (creator.shouldInsertSeparator()) {
addMenuDef.addShortCut(new LineSeparator());
}
};
buttonGroup.setNeedLeftRightOutLine(false);
addMenuDef.addShortCut(new AddAction() {
@Override
protected String getTDName() {
return creator.menuName();
}
@Override
protected Icon getTDIcon() {
return creator.menuIcon();
}
@Override
protected String getNamePrefix() {
return creator.getPrefix();
}
@Override
protected TemplateTableDataWrapper getTableDataInstance() {
TableData tableData = (TableData) creator.createObject();
//新建的DBTableData单独换为DBTableData
if (tableData instanceof DBTableData) {
tableData = new DBTableData();
String dsName = createDsName(creator.getPrefix());
((DBTableData) tableData).setDsName(dsName);
} else {
// TODO: 2020/11/10 后期支持其它数据集,这里转化可以不用侵入修改TableDataCreatorProducer
}
return new TemplateTableDataWrapper(tableData);
}
});
}
}
/**
* 编辑面板
*
* @param uPanel 面板
* @param originalName 原始名字
* @param tableDataPane 面板
* @param originalName 原始名字
*/
public void dgEdit(final AbstractTableDataPane<?> uPanel, String originalName, boolean isUpdate) {
uPanel.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() {
@Override
public void dgEdit(final AbstractTableDataPane<?> tableDataPane, String originalName, boolean isUpdate) {
tableDataPane.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() {
public void fireDoneAction() {
if (dataTree.getSelectionPath() == null) {
dataTree.refresh();
if (tableDataTree.getSelectionPath() == null) {
tableDataTree.refresh();
} else {
Object object = dataTree.getSelectionPath().getLastPathComponent();
int[] rows = dataTree.getSelectionRows();
dataTree.refreshChildByName(object.toString());
dataTree.setSelectionRows(rows);
Object object = tableDataTree.getSelectionPath().getLastPathComponent();
int[] rows = tableDataTree.getSelectionRows();
tableDataTree.refreshChildByName(object.toString());
tableDataTree.setSelectionRows(rows);
}
}
});
final BasicPane.NamePane nPanel = uPanel.asNamePane();
nPanel.setObjectName(originalName);
final NamePane tdNamePanel = tableDataPane.asNamePane();
tdNamePanel.setObjectName(originalName);
final String oldName = originalName;
final BasicDialog dg;
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
dg = nPanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() {
final BasicDialog dg = tdNamePanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() {
@Override
public void doOk() {
DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER);
tc.renameTableData(oldName, nPanel.getObjectName(), false);
tc.renameTableData(oldName, tdNamePanel.getObjectName(), false);
TableDataSource tds = tc.getBook();
TableData td = uPanel.updateBean();
TableData td = tableDataPane.updateBean();
if (td instanceof TableDataSourceDependent) {
((TableDataSourceDependent) td).setTableDataSource(tds);
}
String tdName = nPanel.getObjectName();
String tdName = tdNamePanel.getObjectName();
//模版还没保存的时候不知道后缀,不能设置到策略配置里面
if (tableDataPane instanceof DBTableDataPane) {
StrategyConfig editingConfig = ((DBTableDataPane) tableDataPane).updateStrategyConfig();
if (editingConfig != null) {
editingConfig.setDsName(tdName);
if (!ComparatorUtils.equals(oldName, tdName)) {
//重命名
DesignerStrategyConfigUtils.removeStrategyConfig(oldName);
}
DesignerStrategyConfigUtils.addStrategyConfig(editingConfig);
}
((DBTableData) td).setDsName(tdName);
}
//服务器数据集不会走这里,入口不一样
/*if (tableDataPane instanceof ServerDBTableDataPane) {
StrategyConfig editingConfig = ((ServerDBTableDataPane) tableDataPane).updateStrategyConfig();
if (editingConfig != null) {
editingConfig.setDsName(tdName);
if (!ComparatorUtils.equals(oldName, tdName)) {
//重命名
DesignerStrategyConfigUtils.removeServerStrategyConfig(oldName);
}
DesignerStrategyConfigUtils.addServerStrategyConfig(editingConfig);
}
}*/
tds.putTableData(tdName, td);
Map<String, String> map = new HashMap<String, String>();
if (!ComparatorUtils.equals(oldName, tdName)) {
@ -228,82 +291,35 @@ public class TableDataTreePane extends BasicTableDataTreePane {
}
fireDSChanged(map);
tc.fireTargetModified();
tc.tableDataParametersChanged(oldName, tdName, td);
int[] rows = dataTree.getSelectionRows();
dataTree.refreshChildByName(tdName);
dataTree.setSelectionRows(rows);
tc.parameterChanged();
int[] rows = tableDataTree.getSelectionRows();
tableDataTree.refreshChildByName(tdName);
tableDataTree.setSelectionRows(rows);
//单独编辑数据集关闭,修改缓存配置状态,刷新下一键开启/关闭按钮
checkButtonEnabled();
}
@Override
public void doCancel() {
super.doCancel();
}
});
nPanel.addPropertyChangeListener(new PropertyChangeAdapter() {
tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() {
@Override
public void propertyChange() {
doPropertyChange(dg, nPanel, oldName);
doPropertyChange(dg, tdNamePanel, oldName);
}
});
dg.setVisible(true);
}
private class EditAction extends UpdateAction {
public EditAction() {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Edit"));
this.setMnemonic('E');
this.setSmallIcon("/com/fr/design/images/control/edit");
}
public void actionPerformed(ActionEvent e) {
final NameObject selectedNO = dataTree.getSelectedNameObject();
if (selectedNO == null) {
return;
}
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
dgEdit(((AbstractTableDataWrapper) selectedNO.getObject()).creatTableDataPane(), selectedNO.getName(), false);
}
}
private class RemoveAction extends UpdateAction {
public RemoveAction() {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"));
this.setMnemonic('R');
this.setSmallIcon("/com/fr/design/images/control/remove");
}
@Override
public void actionPerformed(ActionEvent e) {
NameObject selectedNO = dataTree.getSelectedNameObject();
if (selectedNO == null) {
return;
}
int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + ":" + selectedNO.getName() + "?",
com.fr.design.i18n.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());
dataTree.refresh();
// Richie:默认最后一行获得焦点.
dataTree.requestFocus();
dataTree.setSelectionRow(dataTree.getRowCount() - 1);
fireDSChanged();
checkButtonEnabled();
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
}
}
}
private void populate(TableDataSourceOP op) {
this.op = op;
dataTree.populate(op);
checkButtonEnabled();
}
/**
* @return
*/
public TableDataTree getDataTree() {
return dataTree;
@Override
public void removeTableData(String sourceName) {
TableDataSource tds = this.tc.getBook();
tds.removeTableData(sourceName);
this.tableDataTree.refresh();
}
/**
@ -312,6 +328,7 @@ public class TableDataTreePane extends BasicTableDataTreePane {
* @param srcName 数据集来源(比如报表块就是报表块的名称)
* @param tableDataSource 数据集
*/
@Override
public Map<String, String> addTableData(String srcName, TableDataSource tableDataSource, boolean isCover) {
Map<String, String> tdNameMap = new HashMap<>();
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
@ -330,29 +347,55 @@ public class TableDataTreePane extends BasicTableDataTreePane {
}
}
tc.parameterChanged();
dataTree.refresh();
tableDataTree.refresh();
return Collections.unmodifiableMap(tdNameMap);
}
/**
* 合并数据集
*
* @param srcName 数据集来源(比如报表块就是报表块的名称)
* @param tableDataSource 数据集
*/
@Override
public void removeTableData(String sourceName) {
public Map<String, String> addTableData(String srcName, TableDataSource tableDataSource) {
Map<String, String> tdNameMap = new HashMap<>();
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER);
TableDataSource tds = tc.getBook();
tds.removeTableData(sourceName);
dataTree.refresh();
Iterator<String> tdIterator = tableDataSource.getTableDataNameIterator();
while (tdIterator.hasNext()) {
String tdName = tdIterator.next();
String oldName = tdName;
TableData td = tableDataSource.getTableData(tdName);
if (tds.getTableData(tdName) != null || isDsNameRepeaded(tdName)) {
//如果有同名的就拼上来源名称
tdName = srcName + tdName;
}
int i = 0;
while (tds.getTableData(tdName) != null) {
i++;//如果拼上名字后依然已经存在就加编号
tdName += i;
}
tds.putTableData(tdName, td);
if (!ComparatorUtils.equals(oldName, tdName)) {
tdNameMap.put(oldName, tdName);
}
}
tc.parameterChanged();
tableDataTree.refresh();
return Collections.unmodifiableMap(tdNameMap);
}
@Override
public void addDataPane(final AbstractTableDataPane<?> uPanel, String paneName) {
final NamePane nPanel = uPanel.asNamePane();
nPanel.setObjectName(paneName);
final String oldName = paneName;
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER);
tc.renameTableData(oldName, nPanel.getObjectName(), false);
tc.renameTableData(paneName, nPanel.getObjectName(), false);
TableDataSource tds = tc.getBook();
TableData td = uPanel.updateBean();
if (td instanceof TableDataSourceDependent) {
@ -361,14 +404,409 @@ public class TableDataTreePane extends BasicTableDataTreePane {
String tdName = nPanel.getObjectName();
tds.putTableData(tdName, td);
Map<String, String> map = new HashMap<String, String>();
if (!ComparatorUtils.equals(oldName, tdName)) {
map.put(oldName, tdName);
if (!ComparatorUtils.equals(paneName, tdName)) {
map.put(paneName, tdName);
}
fireDSChanged(map);
tc.fireTargetModified();
tc.tableDataParametersChanged(oldName, tdName, td);
int[] rows = dataTree.getSelectionRows();
dataTree.refreshChildByName(tdName);
dataTree.setSelectionRows(rows);
tc.parameterChanged();
int[] rows = tableDataTree.getSelectionRows();
tableDataTree.refreshChildByName(tdName);
tableDataTree.setSelectionRows(rows);
}
@Override
public TableDataTree getDataTree() {
return this.tableDataTree;
}
private void populate(TableDataSourceOP op) {
this.op = op;
tableDataTree.populate(op);
checkButtonEnabled();
}
private void resetAddMenuDef() {
this.addMenuDef.clearShortCuts();
this.createAddMenuDef();
}
private void checkButtonEnabled() {
super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, tableDataTree);
this.checkESDComponentsEnabled();
}
private void checkESDComponentsEnabled() {
if (buttonGroup.getSelectedIndex() == 1) {
//切换到服务器数据集的tab,禁用
esdAction.setEnabled(false);
esdOffAction.setEnabled(false);
return;
}
new SwingWorker<ButtonStatus, Void>() {
@Override
protected ButtonStatus doInBackground() throws Exception {
ButtonStatus btnStatus = new ButtonStatus();
Map<DBTableData, ESDStatus> statusMap = checkCanBeEsdBatchEnableStatus();
if (statusMap.size() == 0) {
//没有db数据集
return btnStatus;
} else {
int canTurnOnCount = 0;
int canTurnOffCount = 0;
for (ESDStatus status : statusMap.values()) {
switch (status) {
case GLOBAL_ON:
case GLOBAL_OFF:
case SINGLE_OFF:
canTurnOnCount++;
break;
case SINGLE_ON:
canTurnOffCount++;
break;
default:
break;
}
}
btnStatus.setOnStatus(canTurnOnCount > 0);
btnStatus.setOffStatus(canTurnOffCount > 0);
}
return btnStatus;
}
@Override
protected void done() {
try {
ButtonStatus buttonStatus = get();
esdAction.setEnabled(buttonStatus.isOnStatus());
esdOffAction.setEnabled(buttonStatus.isOffStatus());
} catch (InterruptedException | ExecutionException e) {
FineLoggerFactory.getLogger().error("get esd status of ds error for " + e.getMessage(), e);
}
}
}.execute();
}
private static class ButtonStatus {
private boolean onStatus = false;
private boolean offStatus = false;
public boolean isOnStatus() {
return onStatus;
}
public void setOnStatus(boolean onStatus) {
this.onStatus = onStatus;
}
public boolean isOffStatus() {
return offStatus;
}
public void setOffStatus(boolean offStatus) {
this.offStatus = offStatus;
}
}
//模版数据集
private void initButtonGroup() {
final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA};
String[] textArray = {Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")};
buttonGroup = new UIHeadGroup(textArray) {
public void tabChanged(int index) {
if (op != null) {
op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]);
addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA);
refreshDockingView();
}
}
};
buttonGroup.setNeedLeftRightOutLine(false);
}
private TableDataWrapper findTableDataWrapper(TreePath treePath) {
if (treePath != null) {
ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) treePath.getLastPathComponent();
Object selectedUserObject = selectedTreeNode.getUserObject();
NameObject nameObject = null;
if (selectedUserObject instanceof NameObject) {
nameObject = (NameObject) selectedUserObject;
} else {
selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent();
selectedUserObject = selectedTreeNode.getUserObject();
if (selectedUserObject instanceof NameObject) {
nameObject = (NameObject) selectedUserObject;
}
}
if (nameObject != null && nameObject.getObject() instanceof TableDataWrapper) {
return (TableDataWrapper) nameObject.getObject();
}
}
return null;
}
private String getTplPath() {
return HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getPath();
}
enum ESDStatus {
GLOBAL_ON,
GLOBAL_OFF,
SINGLE_ON,
SINGLE_OFF;
}
private Map<DBTableData, ESDStatus> checkCanBeEsdBatchEnableStatus() {
//<数据集, 是否可以被单独开启>
Map<DBTableData, ESDStatus> result = new HashMap<>();
for (int i = 0; i < tableDataTree.getRowCount(); i++) {
TreePath treePath = tableDataTree.getPathForRow(i);
TableDataWrapper wrapper = findTableDataWrapper(treePath);
if (wrapper.getTableData() instanceof DBTableData) {
DBTableData td = (DBTableData) wrapper.getTableData();
StrategyConfig config = DesignerStrategyConfigUtils.getStrategyConfig(wrapper.getTableDataName());
if (config == null) {
result.put(td, td.isShare() ? ESDStatus.SINGLE_ON : ESDStatus.SINGLE_OFF);
} else {
if (config.isUseGlobal()) {
if (StrategyConfigHelper.recommended(getTplPath())) {
result.put(td, ESDStatus.GLOBAL_ON);
} else {
result.put(td, ESDStatus.GLOBAL_OFF);
}
} else {
if (config.enabled()) {
result.put(td, ESDStatus.SINGLE_ON);
} else {
result.put(td, ESDStatus.SINGLE_OFF);
}
}
}
}
}
return result;
}
private class EsdOnAction extends AbstractESDAction {
@Override
public String getName() {
return Toolkit.i18nText("Fine-Design_ESD_Batch_Enable");
}
@Override
public Icon getIcon() {
return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_on.png");
}
@Override
public void doWithTableDataWrapper(TableDataWrapper wrapper) {
String dsName = wrapper.getTableDataName();
if (wrapper.getTableData() instanceof DBTableData) {
StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName);
strategyConfig.setEnable(true);
strategyConfig.setUseGlobal(false);
DesignerStrategyConfigUtils.addStrategyConfig(strategyConfig);
DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified();
}
}
}
private @NotNull StrategyConfig getOrCreateStrategyConfig(String dsName) {
StrategyConfig config = DesignerStrategyConfigUtils.getStrategyConfig(dsName);
if (config == null) {
config = StrategyConfigHelper.createStrategyConfig(true);
config.setDsName(dsName);
}
return config;
}
private String createDsName(String prefix) {
int count = 1;
allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook());
while (isDsNameRepeaded(prefix + count)) {
count++;
}
return prefix + count;
}
private class EsdOffAction extends AbstractESDAction {
@Override
public String getName() {
return Toolkit.i18nText("Fine-Design_ESD_Batch_Disable");
}
@Override
public Icon getIcon() {
return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_off.png");
}
@Override
public void doWithTableDataWrapper(TableDataWrapper wrapper) {
String dsName = wrapper.getTableDataName();
if (wrapper.getTableData() instanceof DBTableData) {
((DBTableData) wrapper.getTableData()).setShare(false);
StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName);
strategyConfig.setEnable(false);
strategyConfig.setUseGlobal(false);
DesignerStrategyConfigUtils.addStrategyConfig(strategyConfig);
DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified();
}
}
}
private abstract class AbstractESDAction extends UpdateAction {
public abstract String getName();
public abstract Icon getIcon();
public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper);
public AbstractESDAction() {
this.setName(getName());
this.setMnemonic('R');
this.setSmallIcon(getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
List<TableDataWrapper> tableDataWrapperList = new ArrayList<>();
for (int i = 0; i < tableDataTree.getRowCount(); i++) {
TreePath treePath = tableDataTree.getPathForRow(i);
TableDataWrapper wrapper = findTableDataWrapper(treePath);
if (wrapper != null) {
tableDataWrapperList.add(wrapper);
}
}
if (tableDataWrapperList.isEmpty()) {
return;
}
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
for (TableDataWrapper tableDataWrapper : tableDataWrapperList) {
doWithTableDataWrapper(tableDataWrapper);
}
return null;
}
@Override
protected void done() {
refreshDockingView();
}
}.execute();
}
}
/**
* 新建数据集
* <p>
* 抽象化支持不同类型数据集创建
*/
private abstract class AddAction extends UpdateAction {
protected abstract String getTDName();
protected abstract Icon getTDIcon();
protected abstract String getNamePrefix();
protected abstract TemplateTableDataWrapper getTableDataInstance();
public AddAction() {
this.setName(this.getTDName());
this.setSmallIcon(this.getTDIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
dgEdit(getTableDataInstance().creatTableDataPane(), createDsName(getNamePrefix()), false);
}
}
private class EditAction extends UpdateAction {
public EditAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit"));
this.setMnemonic('E');
this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH));
}
@Override
public void actionPerformed(ActionEvent e) {
final NameObject selectedNO = tableDataTree.getSelectedNameObject();
if (selectedNO == null) {
return;
}
String dsName = selectedNO.getName();
DesignTableDataManager.removeSelectedColumnNames(dsName);
AbstractTableDataWrapper wrapper = (AbstractTableDataWrapper) selectedNO.getObject();
AbstractTableDataPane<?> tableDataPane = wrapper.creatTableDataPane();
//下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name
dgEdit(tableDataPane, dsName, false);
}
}
private class RemoveAction extends UpdateAction {
public RemoveAction() {
this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove"));
this.setMnemonic('R');
this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH));
}
@Override
public void actionPerformed(ActionEvent e) {
NameObject selectedNO = tableDataTree.getSelectedNameObject();
if (selectedNO == null) {
return;
}
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();
//删掉缓存配置
DesignerStrategyConfigUtils.removeStrategyConfig(selectedNO.getName());
// 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样
// 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效
// 这里额外发出一次数据集修改事件
StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName())));
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
}
}
}
}

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

@ -1,6 +1,5 @@
package com.fr.design.data.tabledata.tabledatapane;
import com.fr.base.BaseUtils;
import com.fr.base.Parameter;
import com.fr.base.ParameterHelper;
import com.fr.data.core.db.TableProcedure;
@ -13,15 +12,19 @@ import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.UpdateAction;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.DesignerStrategyConfigUtils;
import com.fr.design.data.datapane.ESDStrategyConfigPane;
import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane;
import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener;
import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.datapane.sqlpane.SQLEditPane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.DBTableDataMenuHandler;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itableeditorpane.ParameterTableModel;
import com.fr.design.gui.itableeditorpane.UITableEditAction;
@ -29,18 +32,27 @@ import com.fr.design.gui.itableeditorpane.UITableEditorPane;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants;
import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef;
import com.fr.design.utils.ParameterUtils;
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;
import com.fr.esd.event.DsNameTarget;
import com.fr.esd.event.StrategyEventsNotifier;
import com.fr.esd.event.xml.XMLSavedHook;
import com.fr.general.ComparatorUtils;
import com.fr.general.IOUtils;
import com.fr.general.sql.SqlUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.script.Calculator;
import com.fr.stable.ArrayUtils;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.Box;
@ -55,6 +67,7 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
@ -62,25 +75,39 @@ import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
/**
* @author rinoux
* @version 10.0
* Created by rinoux on 2020/7/22
*/
public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
private static final int BOTTOM = 6;
private static final String PREVIEW_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview");
private static final String REFRESH_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh");
private static final String PREVIEW_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Preview");
private static final String REFRESH_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Refresh");
private ConnectionTableProcedurePane connectionTableProcedurePane;
private UITableEditorPane<ParameterProvider> editorPane;
private DBTableDataMenuHandler dbTableDataMenuHandler;
private SQLEditPane sqlTextPane;
private UICheckBox isShareCheckBox;
private MaxMemRowCountPanel maxPanel;
private String pageQuery = null;
UIComboBox configFromList;
UICheckBox esdEnabled;
private UIButton esdSettingsBtn;
private UILabel barErrorTips;
private String pageQuery;
private DBTableData dbTableData;
StrategyConfig strategyConfig;
public DBTableDataPane() {
init();
initMainSplitPane();
}
private void init() {
this.setLayout(new BorderLayout(4, 4));
setLayout(new BorderLayout(4, 4));
sqlTextPane = new SQLEditPane();
sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
this.sqlTextPane = new SQLEditPane();
this.sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
ParameterTableModel model = new ParameterTableModel() {
@Override
@ -88,25 +115,27 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
return ArrayUtils.add(super.createDBTableAction(), new RefreshAction());
}
};
editorPane = new UITableEditorPane<ParameterProvider>(model);
editorPane = new UITableEditorPane<>(model);
// 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table
connectionTableProcedurePane = new ConnectionTableProcedurePane() {
this.connectionTableProcedurePane = new ConnectionTableProcedurePane() {
@Override
protected void filter(Connection connection, String conName, List<String> nameList) {
connection.addConnection(nameList, conName, new Class[]{JDBCDatabaseConnection.class, JNDIDatabaseConnection.class});
connection.addConnection(nameList, conName, new Class[]{
JDBCDatabaseConnection.class,
JNDIDatabaseConnection.class
});
}
@Override
protected void addKeyMonitor() {
searchField.addKeyListener(new KeyListener() {
this.searchField.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
//do nothing
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
@ -115,39 +144,39 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
}
}
@Override
public void keyReleased(KeyEvent e) {
//do nothing
}
});
}
};
connectionTableProcedurePane.addDoubleClickListener(new DoubleClickSelectedNodeOnTreeListener() {
this.connectionTableProcedurePane.addDoubleClickListener(new ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener() {
@Override
public void actionPerformed(TableProcedure target) {
Document document = sqlTextPane.getDocument();
Document document = DBTableDataPane.this.sqlTextPane.getDocument();
try {
document.insertString(sqlTextPane.getCaretPosition(), target.toString(), null);
document.insertString(DBTableDataPane.this.sqlTextPane.getCaretPosition(), target.toString(), null);
} catch (BadLocationException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
// 这里开始作色,本来可以给sqlTextPane添加DocumentListener来实现的,
// 后来发现insertString的时候,锁定了JTextPane,不能调用setXXX来作色,先这样了.
// sqlTextPane.syntaxTexts();
sqlTextPane.requestFocus();
DBTableDataPane.this.sqlTextPane.requestFocus();
}
});
sqlTextPane.addFocusListener(new FocusListener() {
this.sqlTextPane.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// do nothing
barErrorTips.setVisible(false);
}
@Override
public void focusLost(FocusEvent e) {
if (isPreviewOrRefreshButton(e)) {
checkParameter();
if (DBTableDataPane.this.isPreviewOrRefreshButton(e)) {
DBTableDataPane.this.checkParameter();
}
}
});
@ -163,105 +192,189 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
northPane.add(editToolBar, BorderLayout.CENTER);
northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM, 0));
RTextScrollPane sqlTextScrollPane = new RTextScrollPane(sqlTextPane);
RTextScrollPane sqlTextScrollPane = new RTextScrollPane(this.sqlTextPane);
sqlTextScrollPane.setLineNumbersEnabled(true);
sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
sqlTextScrollPane.setPreferredSize(new Dimension(680, 600));
JPanel paraMeanPane = new JPanel(new BorderLayout());
paraMeanPane.setPreferredSize(new Dimension(680, 90));
UILabel paraMean = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Param_DES"));
UILabel paraMean = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Datasource_Param_DES"));
paraMeanPane.add(paraMean, BorderLayout.CENTER);
box.add(northPane);
box.add(sqlTextScrollPane);
box.add(paraMeanPane);
box.add(editorPane);
box.add(this.editorPane);
JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4));
sqlSplitPane.add(box, BorderLayout.CENTER);
box.setMinimumSize(new Dimension(300, 400));
// 防止数据连接名过长时影响 split pane 分割效果
// 本界面中给MaxMemRowCountPanel留的空间太小,造成MaxMemRowCountPanel显示异常,这边减小一点最小宽度,拉长MaxMemRowCountPanel
connectionTableProcedurePane.setMinimumSize(new Dimension(230, 400));
connectionTableProcedurePane.setMaximumSize(new Dimension(500, 400));
// 使用SplitPane
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, connectionTableProcedurePane, sqlSplitPane);
this.connectionTableProcedurePane.setMinimumSize(new Dimension(230, 400));
this.connectionTableProcedurePane.setMaximumSize(new Dimension(500, 400));
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.connectionTableProcedurePane, sqlSplitPane);
mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor()));
mainSplitPane.setOneTouchExpandable(true);
this.add(mainSplitPane, BorderLayout.CENTER);
}
public DBTableDataPane() {
init();
initMainSplitPane();
add(mainSplitPane, BorderLayout.CENTER);
}
private boolean isPreviewOrRefreshButton(FocusEvent e) {
if (e.getOppositeComponent() != null) {
String name = e.getOppositeComponent().getName();
return ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON);
return (ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON));
}
return false;
}
@Override
protected String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query");
return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query");
}
private void refresh() {
private void refreshParameters() {
String[] paramTexts = new String[2];
paramTexts[0] = SqlUtils.tryPureSqlText(sqlTextPane.getText());
paramTexts[1] = SqlUtils.tryPureSqlText(pageQuery);
List<ParameterProvider> existParameterList = editorPane.update();
Parameter[] ps = existParameterList == null ? new Parameter[0] : existParameterList.toArray(new Parameter[0]);
editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps));
paramTexts[0] = SqlUtils.tryPureSqlText(this.sqlTextPane.getText());
paramTexts[1] = SqlUtils.tryPureSqlText(this.pageQuery);
List<ParameterProvider> existParameterList = this.editorPane.update();
Parameter[] ps = (existParameterList == null) ? new Parameter[0] : existParameterList.toArray(new Parameter[0]);
this.editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps));
}
private JToolBar createToolBar() {
// p:工具栏.
ToolBarDef toolBarDef = new ToolBarDef();
toolBarDef.addShortCut(new PreviewAction());
toolBarDef.addShortCut(SeparatorDef.DEFAULT);
toolBarDef.addShortCut(new EditPageQueryAction());
dbTableDataMenuHandler = ExtraDesignClassManager.getInstance().getSingle(DBTableDataMenuHandler.MARK_STRING);
if (dbTableDataMenuHandler != null) {
this.dbTableDataMenuHandler = ExtraDesignClassManager.getInstance().getSingle("DBTableDataMenuHandler");
if (this.dbTableDataMenuHandler != null) {
toolBarDef.addShortCut(SeparatorDef.DEFAULT);
toolBarDef.addShortCut(dbTableDataMenuHandler.createQueryAction());
toolBarDef.addShortCut(this.dbTableDataMenuHandler.createQueryAction());
}
isShareCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Is_Share_DBTableData"));
isShareCheckBox.setBackground(Color.WHITE);
maxPanel = new MaxMemRowCountPanel();
maxPanel.setBorder(null);
UILabel esdSettingsLabel = new UILabel(Toolkit.i18nText("Fine-Design_ESD_Cache_Settings"));
this.configFromList = new UIComboBox(ConfigFrom.values());
this.esdEnabled = new UICheckBox(Toolkit.i18nText("Fine-Design_ESD_Enable_Cache"));
this.barErrorTips = new UILabel();
this.barErrorTips.setForeground(Color.RED);
this.barErrorTips.setVisible(false);
esdSettingsBtn = new UIButton(Toolkit.i18nText("Fine-Design_ESD_Strategy_Config"));
esdSettingsBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final boolean global = (DBTableDataPane.this.configFromList.getSelectedIndex() == DBTableDataPane.ConfigFrom.GLOBAL.getIndex());
final ESDStrategyConfigPane strategyConfigPane = new ESDStrategyConfigPane(global);
StrategyConfig populateStrategyConfig = null;
if (global) {
populateStrategyConfig = StrategyConfigHelper.getGlobalStrategyConfig();
} else {
populateStrategyConfig = strategyConfig;
}
//显示对应的配置
strategyConfigPane.populateBean(populateStrategyConfig);
BasicDialog dlg = strategyConfigPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
super.doOk();
if (!global) {
//点击策略配置面板的确定,重新设置策略配置
strategyConfig = strategyConfigPane.updateBean();
}
}
});
dlg.setAlwaysOnTop(true);
dlg.setVisible(true);
}
});
this.configFromList.setSelectedIndex(DBTableDataPane.ConfigFrom.GLOBAL.getIndex());
this.configFromList.addActionListener(e -> setEsdEnabled());
UIToolbar editToolBar = ToolBarDef.createJToolBar();
toolBarDef.updateToolBar(editToolBar);
editToolBar.add(isShareCheckBox);
editToolBar.add(maxPanel);
editToolBar.add(esdSettingsLabel);
editToolBar.add(this.configFromList);
editToolBar.add(this.esdEnabled);
editToolBar.add(this.esdSettingsBtn);
editToolBar.add(this.barErrorTips);
return editToolBar;
}
/* private void showBarError(String errorTips) {
this.barErrorTips.setText(errorTips);
this.barErrorTips.setVisible(true);
}
private boolean checkQuery(String errorTips) {
if (StringUtils.isEmpty(this.sqlTextPane.getText())) {
showBarError(errorTips);
return false;
}
return true;
}*/
/**
* 设置是否开启
*/
protected void setEsdEnabled() {
boolean useIndividualConfig = configFromList.getSelectedIndex() == ConfigFrom.INDIVIDUAL.getIndex();
if (useIndividualConfig) {
if (this.strategyConfig == null) {
//新建的数据集,选择单独时,可用但是不勾选
this.esdEnabled.setSelected(false);
this.esdEnabled.setEnabled(true);
} else {
this.esdEnabled.setSelected(!this.strategyConfig.isUseGlobal() && this.strategyConfig.enabled());
this.esdEnabled.setEnabled(true);
}
} else {
this.esdEnabled.setSelected(DesignerStrategyConfigUtils.isEditingTemplateRecommended());
this.esdEnabled.setEnabled(false);
}
}
public StrategyConfig updateStrategyConfig() {
return this.strategyConfig;
}
private void checkParameter() {
String[] paramTexts = new String[2];
paramTexts[0] = sqlTextPane.getText();
paramTexts[1] = pageQuery;
paramTexts[0] = this.sqlTextPane.getText();
paramTexts[1] = this.pageQuery;
Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false);
if (parameters.length < 1 && editorPane.update().size() < 1) {
if (parameters.length < 1 && this.editorPane.update().size() < 1) {
return;
}
boolean isIn = true;
List<ParameterProvider> list = editorPane.update();
List<String> name = new ArrayList<String>();
for (int i = 0; i < list.size(); i++) {
name.add(list.get(i).getName());
List<ParameterProvider> list = this.editorPane.update();
List<String> name = new ArrayList<>();
for (ParameterProvider parameter : list) {
name.add(parameter.getName());
}
for (int i = 0; i < parameters.length; i++) {
if (!name.contains(parameters[i].getName())) {
for (Parameter parameter : parameters) {
if (!name.contains(parameter.getName())) {
isIn = false;
break;
}
@ -269,115 +382,175 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
if (list.size() == parameters.length && isIn) {
return;
}
// bug:34175 删了是否刷新对话框, 均直接刷新
refresh();
refreshParameters();
}
@Override
public void populateBean(DBTableData dbtabledata) {
this.dbTableData = dbtabledata;
if (dbTableDataMenuHandler != null) {
dbTableDataMenuHandler.populate(dbtabledata);
public void populateBean(DBTableData dbTableData) {
this.dbTableData = dbTableData;
if (this.dbTableDataMenuHandler != null) {
this.dbTableDataMenuHandler.populate(dbTableData);
}
ParameterProvider[] parameters = null;
Calculator c = Calculator.createCalculator();
parameters = dbtabledata.getParameters(c);
editorPane.populate(parameters);
ParameterProvider[] parameters = dbTableData.getParameters(c);
this.editorPane.populate(parameters);
com.fr.data.impl.Connection db = null;
String query = null;
boolean isShare = false;
int maxMemeryRow = -1;
db = dbtabledata.getDatabase();
query = dbtabledata.getQuery();
isShare = dbtabledata.isShare();
maxMemeryRow = dbtabledata.getMaxMemRowCount();
this.pageQuery = dbtabledata.getPageQuerySql();
Connection db = dbTableData.getDatabase();
String query = dbTableData.getQuery();
this.pageQuery = dbTableData.getPageQuerySql();
this.connectionTableProcedurePane.setSelectedDatabaseConnection(db);
this.sqlTextPane.setText(query);
this.sqlTextPane.requestFocus();
this.sqlTextPane.moveCaretPosition(this.sqlTextPane.getCaretPosition());
isShareCheckBox.setSelected(isShare);
maxPanel.setValue(maxMemeryRow);
//查找映射的配置
this.strategyConfig = mapStrategyConfig(dbTableData);
boolean shouldEnable = false;
ConfigFrom from = ConfigFrom.GLOBAL;
if (this.strategyConfig != null) {
if (this.strategyConfig.enabled()) {
shouldEnable = true;
}
if (!this.strategyConfig.isUseGlobal()) {
from = ConfigFrom.INDIVIDUAL;
}
}
this.esdEnabled.setSelected(shouldEnable);
this.configFromList.setSelectedIndex(from.getIndex());
}
@Override
protected StrategyConfig mapStrategyConfig(DBTableData dbTableData) {
//获取配置,如果是模版数据集,dbTableData实例应该是DBTableData,如果是服务器数据集是DBTableData
StrategyConfig strategyConfig = null;
if (dbTableData != null) {
//设置保存数据集的事件检查钩子
String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath();
//新建模版此时不存在,不需要注册钩子
if (dbTableData.getXmlSavedHook() == null && WorkContext.getWorkResource().exist(tplPath)) {
dbTableData.setXmlSavedHook(new DBTableDataSavedHook(tplPath, dbTableData));
}
//获取当前的缓存配置,没有就创建一份
String dsName = this.dbTableData.getDsName();
strategyConfig = DesignerStrategyConfigUtils.getStrategyConfig(dsName);
if (strategyConfig == null && dbTableData.isShare()) {
strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true);
}
}
return strategyConfig;
}
public DBTableData updateBean() {
updateDBTableData();
//这边只修改enable和useGlobal
boolean global = DBTableDataPane.this.configFromList.getSelectedIndex() == DBTableDataPane.ConfigFrom.GLOBAL.getIndex();
boolean enable = DBTableDataPane.this.esdEnabled.isSelected();
//未开启缓存的,如果选择了单独配置,需要创建配置
if (this.strategyConfig == null && !global) {
this.strategyConfig = StrategyConfig.createDefault();
}
//设置配置来源和开启状态
if (this.strategyConfig != null) {
this.strategyConfig.setEnable(enable);
this.strategyConfig.setUseGlobal(global);
}
return this.dbTableData;
}
private void updateDBTableData() {
String dbName = this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName();
if (StringUtils.isBlank(dbName) || StringUtils.isBlank(this.sqlTextPane.getText())) {
try {
throw new Exception(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + ".");
} catch (Exception ignore) {
// JOptionPane.showMessageDialog(DBTableDataPane.this,
// com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + ".");
throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + ".");
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
// 保存前 刷新下参数列表 保证获取到最新的参数
refresh();
List<ParameterProvider> parameterList = editorPane.update();
Parameter[] parameters = parameterList.toArray(new Parameter[parameterList.size()]);
refreshParameters();
List<ParameterProvider> parameterList = this.editorPane.update();
ParameterProvider[] parameters = parameterList.toArray(new ParameterProvider[0]);
dbTableData.setDatabase(new NameDatabaseConnection(dbName));
// p:必须先设置Parameters数组,因为setQuery里面会自动设置的
dbTableData.setParameters(parameters);
dbTableData.setQuery(this.sqlTextPane.getText());
dbTableData.setQuery(this.sqlTextPane.getText().trim());
dbTableData.setShare(isShareCheckBox.isSelected());
dbTableData.setMaxMemRowCount(maxPanel.getValue());
dbTableData.setPageQuerySql(this.pageQuery);
if (dbTableDataMenuHandler != null) {
dbTableDataMenuHandler.update();
if (this.dbTableDataMenuHandler != null) {
this.dbTableDataMenuHandler.update();
}
return dbTableData;
}
protected class RefreshAction extends UITableEditAction {
public RefreshAction() {
this.setName(REFRESH_BUTTON);
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png"));
setName(REFRESH_BUTTON);
setSmallIcon(IOUtils.readIcon("/com/fr/design/images/control/refresh.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
refresh();
DBTableDataPane.this.refreshParameters();
}
@Override
public void checkEnabled() {
// do nothing
}
}
private class PreviewAction extends UpdateAction {
private class PreviewAction
extends UpdateAction {
public PreviewAction() {
this.setName(PREVIEW_BUTTON);
this.setMnemonic('P');
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png"));
setName(PREVIEW_BUTTON);
setMnemonic('P');
setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_file/preview.png"));
}
@Override
public void actionPerformed(ActionEvent evt) {
checkParameter();
DBTableDataPane.this.checkParameter();
PreviewTablePane.previewTableData(DBTableDataPane.this.updateBean());
}
}
private class EditPageQueryAction extends UpdateAction {
public EditPageQueryAction() {
this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Page_Query"));
this.setName(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Page_Query"));
this.setMnemonic('L');
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/text.png"));
this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_file/text.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
final QueryPane pane = new QueryPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL"));
final QueryPane pane = new QueryPane(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL"));
pane.populate(pageQuery);
BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame());
dialog.addDialogActionListener(new DialogActionAdapter() {
@ -391,9 +564,9 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
}
}
private class QueryPane extends BasicPane {
private static class QueryPane extends BasicPane {
private SQLEditPane pageQueryPane;
private String title;
private final String title;
public QueryPane(String title) {
this.title = title;
@ -410,21 +583,96 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
if (StringUtils.isBlank(text)) {
return;
}
pageQueryPane.setText(text);
this.pageQueryPane.setText(text);
}
public String update() {
String text = pageQueryPane.getText();
String text = this.pageQueryPane.getText();
if (StringUtils.isBlank(text)) {
return null;
} else {
return text;
}
return text;
}
@Override
protected String title4PopupWindow() {
return title;
return this.title;
}
}
enum ConfigFrom {
GLOBAL(0, Toolkit.i18nText("Fine-Design_ESD_Use_Global_Settings")),
INDIVIDUAL(1, Toolkit.i18nText("Fine-Design_ESD_Use_Individual_Settings"));
int index;
String displayText;
ConfigFrom(int index, String displayText) {
this.index = index;
this.displayText = displayText;
}
static int parse(StrategyConfig config) {
return (config == null || config.isUseGlobal()) ? ConfigFrom.GLOBAL.getIndex() : ConfigFrom.INDIVIDUAL.getIndex();
}
public int getIndex() {
return this.index;
}
public String getDisplayText() {
return this.displayText;
}
public String toString() {
return getDisplayText();
}
}
private static class DBTableDataSavedHook implements XMLSavedHook<DBTableData> {
private static final long serialVersionUID = 4925391747683335372L;
private final String tplPath;
private String origName;
private String origConnection;
private String origQuery;
public DBTableDataSavedHook(String tplPath, DBTableData origDBTableData) {
this.tplPath = tplPath;
this.origName = origDBTableData.getDsName();
this.origConnection = origDBTableData.getDatabase().toString();
this.origQuery = origDBTableData.getQuery();
}
@Override
public void doAfterSaved(DBTableData saved) {
String dsName = saved.getDsName();
String conn = saved.getDatabase().toString();
String query = saved.getQuery();
//检查数据集名称、数据链接和sql是否修改,如果修改需要触发缓存监听事件
if (!dsName.equals(origName) || !conn.equals(origConnection) || !query.equals(origQuery)) {
if (StringUtils.isNotEmpty(tplPath) && StringUtils.isNotEmpty(origName)) {
//新建数据集的origName为null,不用触发
StrategyEventsNotifier.modifyDataSet(new DSMapping(tplPath, new DsNameTarget(origName)));
}
}
this.origName = dsName;
this.origConnection = conn;
this.origQuery = query;
}
}
}

12
designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java

@ -48,6 +48,9 @@ public class FileTreeIcon {
public static final Icon MODERN_CHT_FILE_IMAGE_ICON =
BaseUtils.readIcon("/com/fr/design/images/gui/modern_style_cht_file_icon_16x16.png");
public static final Icon CPTX_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon.png");
public static final Icon CPTX_LOCKED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon_locked.png");
public static final LockIcon FOLDER_LOCK_ICON =
new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/fold.png"));
public static final LockIcon FILE_LOCK_ICON =
@ -108,6 +111,7 @@ public class FileTreeIcon {
public final static int CPT_FILE = 11; //.cpt
public final static int FRM_FILE = 12; //.form .frm
public final static int CHT_FILE = 13; //.chart .cht
public final static int CPTX_FILE = 14; //.cptx
public static Icon getIcon(File file) {
return FileTreeIcon.getIcon(file, false);
@ -252,6 +256,12 @@ public class FileTreeIcon {
} else {
return FileTreeIcon.MODERN_CPT_FILE_IMAGE_ICON;
}
} else if (fileType == CPTX_FILE) {
if (isLocked) {
return FileTreeIcon.CPTX_LOCKED_ICON;
} else {
return FileTreeIcon.CPTX_ICON;
}
} else if (fileType == FRM_FILE) { //form frm
if (isLocked) {
return FileTreeIcon.FRM_FILE_LOCK_ICON;
@ -314,6 +324,8 @@ public class FileTreeIcon {
return BMP_FILE;
} else if (fileName.endsWith(".cpt")) {
return CPT_FILE;
} else if (fileName.endsWith(".cptx")) {
return CPTX_FILE;
} else if (fileName.endsWith(".frm") || fileName.endsWith(".form")) {
return FRM_FILE;
} else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")) {

22
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -3,6 +3,7 @@ package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.base.FRContext;
import com.fr.base.Parameter;
import com.fr.base.extension.FileExtension;
import com.fr.base.io.BaseBook;
import com.fr.base.iofile.attr.DesignBanCopyAttrMark;
import com.fr.base.iofile.attr.TemplateIdAttrMark;
@ -14,6 +15,7 @@ import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.TableDataSourceAction;
import com.fr.design.actions.edit.RedoAction;
import com.fr.design.actions.edit.UndoAction;
import com.fr.design.actions.file.BatchCompileAction;
import com.fr.design.actions.file.SaveAsTemplateAction;
import com.fr.design.actions.file.SaveTemplateAction;
import com.fr.design.actions.file.WebPreviewUtils;
@ -60,6 +62,8 @@ import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.context.PluginRuntime;
import com.fr.nx.app.designer.toolbar.CompileAction;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
import com.fr.plugin.observer.PluginEvent;
@ -781,10 +785,12 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
protected boolean saveToNewFile(String oldName) {
boolean result = false;
String path = this.editingFILE.getPath();
Set<ReportSupportedFileUIProvider> providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG);
for (ReportSupportedFileUIProvider provider : providers) {
result = result || provider.saveToNewFile(this.editingFILE.getPath(), this);
result = result || provider.saveToNewFile(path, this);
}
result = result || saveToNewFile4Cptx(path);
if (!result) {
result = result || this.saveFile();
//更换最近打开
@ -794,6 +800,14 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return result;
}
private boolean saveToNewFile4Cptx(String targetPath) {
if (FileExtension.CPTX.matchExtension(targetPath)) {
TemplateTransformer.TO_CPTX.transform(this);
return true;
}
return false;
}
protected void mkNewFile(FILE file) {
try {
file.mkfile();
@ -887,7 +901,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
} else if (DesignerMode.isAuthorityEditing()) {
return new ShortCut[]{new SaveTemplateAction(this), new UndoAction(this), new RedoAction(this)};
} else {
return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new UndoAction(this), new RedoAction(this)};
return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new BatchCompileAction(), new UndoAction(this), new RedoAction(this)};
}
}
@ -1323,8 +1337,10 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
* @return 按钮组
*/
public UIButton[] createExtraButtons() {
UIButton[] uiButtons = new UIButton[] {
(UIButton) new CompileAction().createToolBarComponent()
};
Set<DesignerFrameUpButtonProvider> providers = ExtraDesignClassManager.getInstance().getArray(DesignerFrameUpButtonProvider.XML_TAG);
UIButton[] uiButtons = new UIButton[0];
for (DesignerFrameUpButtonProvider provider : providers) {
uiButtons = ArrayUtils.addAll(uiButtons, provider.getUpButtons(getMenuState()));
}

1
designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe.vcs.common;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.DesignerEnvManager;
import com.fr.design.file.HistoryTemplateListCache;

41
designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java

@ -0,0 +1,41 @@
package com.fr.design.preview;
import com.fr.design.fun.impl.AbstractPreviewProvider;
import com.fr.general.web.ParameterConstants;
import com.fr.locale.InterProviderFactory;
import java.util.HashMap;
import java.util.Map;
import static com.fr.nx.app.web.v9.PagePlusActor.TYPE;
public class PagePlusPreview extends AbstractPreviewProvider {
private static final int CODE = 100;
@Override
public String nameForPopupItem() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Page-Plus");
}
@Override
public String iconPathForPopupItem() {
return "com/fr/design/images/buttonicon/pages.png";
}
@Override
public String iconPathForLarge() {
return "com/fr/design/images/buttonicon/pageb24.png";
}
@Override
public int previewTypeCode() {
return CODE;
}
@Override
public Map<String, Object> parametersForPreview() {
Map<String, Object> map = new HashMap<String, Object>();
map.put(ParameterConstants.OP, TYPE);
return map;
}
}

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

@ -0,0 +1,40 @@
package com.fr.design.preview;
import com.fr.base.io.IOFile;
import com.fr.design.fun.impl.AbstractPreviewProvider;
import java.util.HashMap;
import java.util.Map;
/**
* Created by loy on 2017/7/7.
*/
public class WriteEnhancePreview extends AbstractPreviewProvider {
@Override
public String nameForPopupItem() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Enhance_Preview");
}
@Override
public String iconPathForPopupItem() {
return "com/fr/design/images/buttonicon/writes.png";
}
@Override
public String iconPathForLarge() {
return "com/fr/design/images/buttonicon/writeb24.png";
}
@Override
public int previewTypeCode() {
return IOFile.WRITE_ENHANCE_PREVIEW_TYPE;
}
@Override
public Map<String, Object> parametersForPreview() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("op", "write_plus");
return map;
}
}

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

@ -770,6 +770,7 @@ public class FILEChooserPane extends BasicPane {
// ben:filefilter设置初值为cpt过滤
this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));
this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));
// richer:form文件 daniel 改成三个字
this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.FRM, appName + Toolkit.i18nText("Fine-Design_Report_Template_File")));

60
designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java

@ -0,0 +1,60 @@
package com.fr.nx.app.designer.cptx.io;
import com.fr.common.annotations.Negative;
import com.fr.file.FILE;
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils;
import com.fr.nx.cptx.io.handle.impl.AbstractCptxIOProvider;
import com.fr.nx.cptx.pack.util.CompiledReportInputStream;
import com.fr.nx.cptx.pack.util.CompiledReportOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 用于设计器保存编译后的结果并缓存可web预览模版
* 没有可观的内存实现内存实现方式复杂赶发布先提供简单的内存实现方式
*
* @author: Maksim
* @Date: Created in 2020/4/10
* @Description: 用于cptx写操作的Provider
*/
@Negative(until = "2020-05-10")
public class DesignReadWritableProvider extends AbstractCptxIOProvider {
/**
* 原文件
*/
private final FILE file;
/**
* 编译文件夹
*/
private final String compileDir;
private CompiledReportOutputStream outputStream;
public DesignReadWritableProvider(FILE file) {
this.file = file;
this.compileDir = DesignerCptxFileUtils.generateCompileDir(file);
}
@Override
public InputStream open() throws Exception {
if (outputStream == null) {
throw new IOException("can not read cptx template before compile");
}
return new CompiledReportInputStream(outputStream.toByteArray());
}
/**
* 对于写操作用到的只有这个方法以流形式来操作
*
* @return 保存的目标输出流
* @throws Exception e
*/
@Override
public OutputStream createTemp() throws Exception {
outputStream = new CompiledReportOutputStream(file.asOutputStream(), compileDir);
return outputStream;
}
}

97
designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java

@ -0,0 +1,97 @@
package com.fr.nx.app.designer.monitor;
import com.fr.design.mainframe.errorinfo.ErrorInfo;
import com.fr.intelli.record.MetricRegistry;
import com.fr.json.JSON;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.message.ErrorMessage;
import com.fr.nx.app.designer.toolbar.TransformResult;
/**
* Created by loy on 2021/1/18.
*
* <p>设计器埋点记录相关
*/
public class DesignerMetricRecorder {
private static final String ATTR_TEMPLATE_ID = "templateid";
private static final String ATTR_USERNAME = "username";
private static final String ATTR_UUID = "uuid";
private static final String ATTR_ACTIVE_KEY = "activekey";
private static final String ATTR_TEST_LOG = "testlog";
private static final String ATTR_REPORT_CONTENT = "reportcontent";
private static final String ATTR_ERROR_STACK = "errorstack";
private static final String IDENTIFICATION = "view_plus";
private DesignerMetricRecorder() {
}
/**
* 模板转换失败的埋点
*/
public static void submitFailedTransform(TransformResult result, String templateID, String name, Exception e) {
if (isPressureTesting()) {
return;
}
saveAsJSON(result, templateID, name, e);
}
/**
* 记录在设计器的错误信息收集中
*/
private static void saveToErrorInfo(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) {
JSONObject jo = JSONFactory.createJSON(JSON.OBJECT);
jo.put(ATTR_USERNAME, IDENTIFICATION);
jo.put(ATTR_UUID, IDENTIFICATION);
jo.put(ATTR_ACTIVE_KEY, IDENTIFICATION);
jo.put(ATTR_TEMPLATE_ID, templateID);
jo.put(ATTR_REPORT_CONTENT, name);
if (result == TransformResult.FAILED) {
jo.put(ATTR_TEST_LOG, e);
jo.put(ATTR_ERROR_STACK, e.getMessage());
} else {
jo.put(ATTR_TEST_LOG, unsupportMessage);
}
new ErrorInfo().saveFileToCache(jo);
}
/**
* 记录在fine_record_error表中
*/
private static void saveToErrorMessage(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) {
String errorMessage = unsupportMessage;
if (result == TransformResult.FAILED) {
errorMessage = e.getStackTrace()[0].toString();
}
ErrorMessage message = ErrorMessage.build(e == null ? errorMessage : e.getMessage(), errorMessage);
message.setTname(name);
message.setDisplayName(name);
MetricRegistry.getMetric().submit(message);
}
private static void saveAsJSON(TransformResult result, String templateID, String name, Exception e) {
saveToErrorInfo(result, templateID, name, e, null);
saveToErrorMessage(result, templateID, name, e, null);
}
/**
* 预编译中不支持的功能的埋点
*/
public static void submitUnSupportTransform(TransformResult result, String templateID, String name, String unsupportMessage) {
if (isPressureTesting()) {
return;
}
saveToErrorInfo(result, templateID, name, null, unsupportMessage);
saveToErrorMessage(result, templateID, name, null, unsupportMessage);
}
/**
* 埋点对压测性能的影响控制参数
*
* @return 是否压测
*/
public static boolean isPressureTesting() {
return Boolean.parseBoolean(System.getProperty("monitorDebug"));
}
}

116
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java

@ -0,0 +1,116 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.extension.FileExtension;
import com.fr.design.actions.UpdateAction;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.MenuKeySet;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.general.IOUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.utils.CompileTransformUtil;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog;
import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.OK_OPTION;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
/**
* Created by kerry on 2019-10-14
*/
public class CompileAction extends UpdateAction {
public static final Icon TRANS_ICON = IOUtils.readIcon("/com/fr/nx/app/designer/transform.png");
private static final MenuKeySet COMPILE_ATTR = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'C';
}
@Override
public String getMenuName() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip");
}
@Override
public KeyStroke getKeyStroke() {
return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER);
}
};
public CompileAction() {
initMenuStyle();
}
private void initMenuStyle() {
this.setMenuKeySet(COMPILE_ATTR);
this.setName(getMenuKeySet().getMenuKeySetName());
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(TRANS_ICON);
this.setAccelerator(getMenuKeySet().getKeyStroke());
}
@Override
public void actionPerformed(ActionEvent e) {
JTemplate jtemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate();
if (jtemplate == null || jtemplate.getEditingFILE() == null) {
return;
}
FILE currentTemplate = jtemplate.getEditingFILE();
if(currentTemplate instanceof FileNodeFILE){
transformAndDisplay(jtemplate);
}else {
//模板不在报表环境下,提示保存
int selVal = showConfirmDialog(
DesignerContext.getDesignerFrame(),
InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Preview_Message"),
InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Transformer_Tips"),
OK_CANCEL_OPTION,
WARNING_MESSAGE);
if (OK_OPTION == selVal) {
//保存成功才会执行编译
if (jtemplate.saveAsTemplate2Env()) {
transformAndDisplay(jtemplate);
}
}
}
}
//编译模板并展示
private void transformAndDisplay(JTemplate jtemplate){
String path = jtemplate.getEditingFILE().getPath();
TemplateTransformer transformer = TemplateTransformer.parse(path);
FILE targetFile = CompileTransformUtil.getTargetFile(jtemplate, transformer);
TransformResult result = transformer.transform(jtemplate, targetFile);
jtemplate.fireJTemplateSaved();
result.display();
}
@Override
public boolean isEnabled() {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
String path = jt.getEditingFILE().getPath();
return FileExtension.CPTX.matchExtension(path) || FileExtension.CPT.matchExtension(path);
}
@Override
public JComponent createToolBarComponent() {
UIButton transBtn = (UIButton) super.createToolBarComponent();
transBtn.set4ToolbarButton();
transBtn.setToolTipText(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip"));
return transBtn;
}
}

221
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java

@ -0,0 +1,221 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.extension.FileExtension;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MutilTempalteTabPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.monitor.DesignerMetricRecorder;
import com.fr.nx.compile.CompileStatus;
import com.fr.nx.compile.ReportCompiler;
import com.fr.nx.compile.adapter.LegacyWorkBookAdapter;
import com.fr.nx.compile.util.ReportCompileUtils;
import com.fr.nx.cptx.CptxIOManager;
import com.fr.nx.cptx.cache.CptxTemplatePool;
import com.fr.nx.cptx.entry.CptxTemplate;
import com.fr.nx.cptx.io.handle.CptxTemplateHandle;
import com.fr.nx.app.designer.cptx.io.DesignReadWritableProvider;
import com.fr.nx.cptx.monitor.CompileMonitorHandler;
import com.fr.nx.cptx.utils.CptxFileUtils;
import com.fr.nx.data.layer.LayerItem;
import com.fr.nx.data.layer.LayerProps;
import com.fr.nx.template.compile.CompiledReport;
import com.fr.stable.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.io.OutputStream;
import static com.fr.base.extension.FileExtension.ALL;
import static com.fr.base.extension.FileExtension.CPT;
import static com.fr.base.extension.FileExtension.CPTX;
/**
* 模板转换器, 可以把cptx模板转为cpt, 或者cpt模板转为cptx.
* 以后可以扩展支持frm frmx互相转换
*/
public enum TemplateTransformer {
TO_CPTX(CPT) {
@Override
public TransformResult transform(JTemplate jtemplate, FILE file) {
WorkBook workbook = (WorkBook) jtemplate.getTarget();
TransformResultInfo resultInfo = compileCPTX(workbook, file);
if (needDoAfterTransformed(resultInfo.getResult())) {
doAfterTransformed(file, jtemplate);
}
return resultInfo.getResult();
}
},
TO_CPT(CPTX) {
@Override
public TransformResult transform(JTemplate jtemplate, FILE file) {
WorkBook workbook = (WorkBook) jtemplate.getTarget();
try {
workbook.export(file.asOutputStream());
doAfterTransformed(file, jtemplate);
return TransformResult.SUCCESS;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return TransformResult.FAILED;
}
}
},
OTHER(ALL);
private FileExtension extension;
TemplateTransformer(FileExtension extension) {
this.extension = extension;
}
public TransformResult transform(JTemplate jtemplate) {
return transform(jtemplate, jtemplate.getEditingFILE());
}
public TransformResult transform(JTemplate jtemplate, FILE newFile) {
return TransformResult.UNSUPPORT;
}
public static TemplateTransformer parse(String path) {
for (TemplateTransformer transformer : values()) {
if (transformer.extension.matchExtension(path)) {
return transformer;
}
}
return OTHER;
}
private static boolean needDoAfterTransformed(TransformResult result) {
return ComparatorUtils.equals(TransformResult.SUCCESS, result)
|| ComparatorUtils.equals(TransformResult.UNSUPPORT, result);
}
private static void doAfterTransformed(FILE file, JTemplate jtemplate) {
JTemplate<?, ?> jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (ComparatorUtils.equals(file.getPath(), jt.getPath())) {
HistoryTemplateListCache.getInstance().closeSelectedReport(jt);
DesignerContext.getDesignerFrame().openTemplate(file);
return;
}
MutilTempalteTabPane.getInstance().setIsCloseCurrent(true);
MutilTempalteTabPane.getInstance().closeFormat(jt);
MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt);
DesignerContext.getDesignerFrame().openTemplate(file);
}
public static FILE createOutputFile(String oldPath, String oldSuffix, String newSuffix) {
String newPath = generateNewPath(oldPath, oldSuffix, newSuffix);
return new FileNodeFILE(new FileNode(newPath, false));
}
private static String generateNewPath(String oldPath, String oldSuffix, String newSuffix) {
if (StringUtils.isEmpty(oldPath) || StringUtils.isEmpty(oldSuffix) || StringUtils.isEmpty(newSuffix)) {
return oldPath;
}
if (oldPath.endsWith(oldSuffix)) {
return StringUtils.cutStringEndWith(oldPath, oldSuffix) + newSuffix;
}
return oldPath;
}
/**
* 编译和保存
*
* @param workbook work
* @param file file
* @return 编译保存结果
*/
@NotNull
public static TransformResultInfo compileCPTX(WorkBook workbook, FILE file) {
//对于非工作目录的cptx,修改无需执行编译
if(!(file instanceof FileNodeFILE)){
try {
OutputStream outputStream = file.asOutputStream();
workbook.export(outputStream);
return TransformResultInfo.generateResult(TransformResult.SUCCESS).saved(true);
}catch (Exception e){
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return TransformResultInfo.generateResult(TransformResult.FAILED).saved(false);
}
}
boolean saved;
CompiledReport report = null;
CompileStatus compileStatus = CompileStatus.SUCCEED;
if (workbook == null || file == null) {
return TransformResultInfo
.generateResult(TransformResult.FAILED, "work and file must not be null")
.saved(false);
}
String failMessage = null;
// 编译
ReportCompiler compiler;
try {
compiler = new ReportCompiler(new LegacyWorkBookAdapter(workbook));
long startTime = System.currentTimeMillis();
compiler.compile();
report = compiler.getCompiledReport();
// 折叠树埋点
LayerProps props = ReportCompileUtils.getLayerProps(report);
LayerItem[] items;
if (props != null && (items = props.getLayerItems()) != null) {
CompileMonitorHandler.submitTreeCompileFocusPoint(
startTime, file.getPath(), items.length,
props.getExpandLayer(), true
);
}
compileStatus = compiler.getStatus();
failMessage = compiler.getFailMessage();
long endTime = System.currentTimeMillis();
CompileMonitorHandler.submitCompileMessage(startTime, endTime, file.getPath(), "");
if (compileStatus != CompileStatus.SUCCEED) {
DesignerMetricRecorder.submitUnSupportTransform(
TransformResult.UNSUPPORT,
workbook.getTemplateID(),
file.getName(),
compileStatus == CompileStatus.FAILED_UNSUPPORT ? failMessage : null
);
}
} catch (Exception exception) {
String templateID = workbook.getTemplateID();
String fileName = file.getName();
DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, templateID, fileName, exception);
FineLoggerFactory.getLogger().error(exception.getMessage(), exception);
}
// 构建编译结果,当前的 cptx template 是未经反序列化钩子处理过的 cptx 模版对象,不能直接用于模版预览
CptxTemplate template = CptxIOManager.createCptxTemplate(workbook, report, compileStatus, failMessage);
// 保存
DesignReadWritableProvider cptx = new DesignReadWritableProvider(file);
CptxTemplateHandle handle = CptxIOManager.create(template, cptx);
try {
saved = handle.save();
} catch (Exception exception) {
// 存储cptx格式报错或者失败
FineLoggerFactory.getLogger().error(exception.getMessage(), exception);
DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, workbook.getTemplateID(), file.getName(), exception);
return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(false);
}
// 读取可 web 预览模版并缓存
try {
// todo 是否考虑异步
String timestampedPath = CptxFileUtils.getTimestampedPath(file.getPath());
CptxTemplate previewCptxTemplate = CptxIOManager.open(cptx).getTemplate();
CptxTemplatePool.getInstance().addCptxTemplate(timestampedPath, previewCptxTemplate);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (report == null) {
// 编译报错或者失败
return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(saved);
}
return TransformResultInfo.generateResult(TransformResult.parse(compileStatus), failMessage).saved(saved);
}
}

55
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java

@ -0,0 +1,55 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.compile.CompileStatus;
import javax.swing.JOptionPane;
public enum TransformResult {
SUCCESS(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Success")) {
@Override
public void display() {
// 转换成功后, 刷新下目录树
TemplateTreePane.getInstance().refresh();
super.display();
}
},
FAILED(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Failed")),
UNSUPPORT(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Unsupport")){
@Override
public void display() {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), TransformResult.SUCCESS.toString());
}
};
private String msg;
private TransformResult(String msg) {
this.msg = msg;
}
// 展示结果
public void display() {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), this.toString());
}
@Override
public String toString() {
return this.msg;
}
public static TransformResult parse(CompileStatus status) {
switch (status) {
case SUCCEED:
return TransformResult.SUCCESS;
case FAILED_UNSUPPORT:
return TransformResult.UNSUPPORT;
default:
return TransformResult.FAILED;
}
}
}

64
designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java

@ -0,0 +1,64 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.locale.InterProviderFactory;
import com.fr.stable.StringUtils;
/**
* Created by kerry on 2020-01-15
*/
public class TransformResultInfo {
private boolean saved;
private TransformResult result;
private final String transformLog;
public static TransformResultInfo generateResult(TransformResult result, String transformLog) {
return new TransformResultInfo(result, transformLog);
}
public static TransformResultInfo generateResult(TransformResult result) {
return new TransformResultInfo(result, StringUtils.EMPTY);
}
private TransformResultInfo(TransformResult result, String transformLog) {
this.result = result;
this.transformLog = transformLog;
this.saved = false;
}
public boolean isSaved() {
return saved;
}
public void setSaved(boolean saved) {
this.saved = saved;
}
public TransformResultInfo saved(boolean saved) {
setSaved(saved);
return this;
}
public TransformResult getResult() {
return result;
}
public void setResult(TransformResult result) {
this.result = result;
}
public String getTransformLog() {
switch (this.result) {
case FAILED:
return transformLog + "\n"
+ InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip");
case SUCCESS:
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip");
case UNSUPPORT:
return transformLog + "\n"
+ InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip");
}
return transformLog;
}
}

25
designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java

@ -0,0 +1,25 @@
package com.fr.nx.app.designer.transform;
/**
* Created by kerry on 2019-12-10
*/
public class BatchTransformProgress {
private double progress = 0.0D;
private int total = 0;
private int complete = 0;
public BatchTransformProgress(int total) {
this.total = total;
}
public double getProgress() {
return this.progress;
}
public void updateProgress() {
this.complete++;
this.progress = this.complete * 1D / this.total;
}
}

25
designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java

@ -0,0 +1,25 @@
package com.fr.nx.app.designer.transform;
import com.fr.file.filetree.FileNode;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-02-14
*/
public class BatchTransformUtil {
private BatchTransformUtil() {
}
public static FileNode[] filterTransformedFile(FileNode[] fileNodes, List<FileNode> transformedList){
List<FileNode> list = new ArrayList<FileNode>();
for (FileNode fileNode : fileNodes) {
if (!transformedList.contains(fileNode)) {
list.add(fileNode);
}
}
return list.toArray(new FileNode[list.size()]);
}
}

71
designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java

@ -0,0 +1,71 @@
package com.fr.nx.app.designer.transform;
import com.fr.design.utils.concurrent.ThreadFactoryBuilder;
import com.fr.file.filetree.FileNode;
import com.fr.plugin.context.PluginContexts;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.nx.app.designer.utils.CompileTransformUtil;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
/**
* Created by kerry on 2019-12-10
*/
public class BatchTransformer {
private BatchTransformProgress progress = new BatchTransformProgress(0);
private Map<FileNode, TransformResultInfo> transformResults = new ConcurrentHashMap<FileNode, TransformResultInfo>();
private UpdateCallBack updateCallBack;
private static final int MAXPOOLSIZE = 5;
private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s";
private ExecutorService threadPoolExecutor =
PluginContexts.currentContext().newFixedThreadPool(MAXPOOLSIZE,
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build());
public BatchTransformer(UpdateCallBack updateCallBack) {
this.updateCallBack = updateCallBack;
}
public void batchTransform(List<FileNode> fileNodes) {
//先清理下
transformResults.clear();
progress = new BatchTransformProgress(fileNodes.size());
for (FileNode fileNode : fileNodes) {
transform(fileNode);
}
}
private void transform(final FileNode fileNode) {
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
TransformResultInfo transformResult = CompileTransformUtil.compileFile(fileNode);
transformResults.put(fileNode, transformResult);
updateTransformProgress();
}
});
}
private synchronized void updateTransformProgress() {
progress.updateProgress();
updateCallBack.updateProgress(progress.getProgress());
}
public void shutDown() {
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdownNow();
}
threadPoolExecutor = PluginContexts.currentContext().newFixedThreadPool(MAXPOOLSIZE,
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build());
updateCallBack.shutDown();
}
public Map<FileNode, TransformResultInfo> getResults() {
return transformResults;
}
}

22
designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java

@ -0,0 +1,22 @@
package com.fr.nx.app.designer.transform;
/**
* Created by kerry on 2019-12-10
*/
public interface UpdateCallBack {
/**
* 更新进度
* @param progress 进度
*/
void updateProgress(double progress);
/**
* 进度中断
*/
void shutDown();
/**
* 进度重置
*/
void reset();
}

61
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java

@ -0,0 +1,61 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.locale.InterProviderFactory;
import javax.swing.JDialog;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* Created by kerry on 2019-12-19
*/
public class BatchTransformDialog extends JDialog implements ActionListener {
private UIButton closeBtn;
public BatchTransformDialog(Frame parent, JPanel contentPane) {
super(parent, true);
this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"));
this.setResizable(false);
JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
this.setContentPane(defaultPane);
closeBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Close"));
closeBtn.addActionListener(this);
JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
buttonPanel.add(closeBtn);
defaultPane.add(contentPane, BorderLayout.CENTER);
defaultPane.add(buttonPanel, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dialogExit();
}
});
this.getRootPane().setDefaultButton(closeBtn);
this.setSize(new Dimension(900, 600));
GUICoreUtils.centerWindow(this);
}
@Override
public void actionPerformed(ActionEvent e) {
dialogExit();
}
private void dialogExit() {
this.dispose();
}
}

223
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java

@ -0,0 +1,223 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.extension.FileExtension;
import com.fr.design.dialog.BasicPane;
import com.fr.design.file.NodeAuthProcessor;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itree.filetree.FileNodeComparator;
import com.fr.design.gui.itree.filetree.FileNodeConstants;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.file.filetree.FileNode;
import com.fr.file.filetree.IOFileNodeFilter;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.tree.DefaultTreeModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Created by kerry on 2019-12-10
*/
public class BatchTransformPane extends BasicPane {
private UITextField searchField;
private TransformFileTree tree;
private Dialog showDialog;
private TransformPreparePane preparePane;
private TransformResultPane resultPane;
public BatchTransformPane() {
DesignerFrame designerFrame = DesignerContext.getDesignerFrame();
this.showDialog = new BatchTransformDialog(designerFrame, this);
initPane();
}
private void initPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initNorthPane();
initSouthPane();
}
private void initNorthPane() {
UILabel northTip = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Tip"));
northTip.setForeground(Color.decode("#8F8F92"));
northTip.setBorder(BorderFactory.createEmptyBorder(0, 550, 10, 10));
this.add(northTip, BorderLayout.NORTH);
}
private void initSouthPane() {
preparePane = new TransformPreparePane(this.showDialog, this);
tree = new TransformFileTree(preparePane);
this.add(preparePane, BorderLayout.CENTER);
initLeftPane();
initRightPane();
}
private void initLeftPane() {
IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{FileExtension.CPT.getSuffix()});
tree.setDigIn(true);
tree.setFileNodeFilter(filter);
UIScrollPane scrollPane = new UIScrollPane(tree);
scrollPane.setPreferredSize(new Dimension(320, 442));
scrollPane.setBorder(BorderFactory.createEmptyBorder(12, 0, 0, 0));
tree.refreshEnv();
JPanel selectPane = FRGUIPaneFactory.createTitledBorderPaneCenter(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Select_Template"));
JPanel searchPane = initSearchPane();
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.add(searchPane, BorderLayout.NORTH);
jPanel.add(scrollPane, BorderLayout.WEST);
jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
selectPane.add(jPanel);
selectPane.setPreferredSize(new Dimension(330, 501));
this.add(selectPane, BorderLayout.WEST);
}
private void initRightPane() {
resultPane = new TransformResultPane();
this.add(resultPane, BorderLayout.EAST);
}
private JPanel initSearchPane() {
JPanel jPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane();
jPanel.setBorder(BorderFactory.createEmptyBorder());
searchField = new UITextField();
searchField.requestFocus();
searchField.addKeyListener(keyFieldKeyListener);
searchField.setPreferredSize(new Dimension(261, 20));
jPanel.add(searchField);
UIButton searchBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Search"));
searchBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
search();
}
});
searchBtn.setPreferredSize(new Dimension(44, 20));
jPanel.add(searchBtn);
return jPanel;
}
private KeyAdapter keyFieldKeyListener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
search();
e.consume();
}
}
};
private void search() {
//重新构建TreeModel
filter(searchField.getText());
ExpandMutableTreeNode rootNode = (ExpandMutableTreeNode) tree.getModel().getRoot();
((DefaultTreeModel) tree.getModel()).reload(rootNode);
// 展开所有isExpanded为true的TreeNode
rootNode.expandCurrentTreeNode(tree);
}
public void filter(String filterString) {
NodeAuthProcessor.getInstance().refresh();
DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel();
ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot();
NodeAuthProcessor.getInstance().fixTreeNodeAuth(rootTreeNode);
filter(rootTreeNode, filterString);
defaultTreeModel.reload(rootTreeNode);
}
private void filter(ExpandMutableTreeNode rootTreeNode, String filterString) {
rootTreeNode.removeAllChildren();
FileNode[] fns;
fns = listFileNodes(rootTreeNode);
ExpandMutableTreeNode[] subTreeNodes = NodeAuthProcessor.getInstance().parser2TreeNodeArray(fns);
for (ExpandMutableTreeNode node : subTreeNodes) {
filter(node, filterString);
if (node.getChildCount() > 0 || (node.getChildCount() == 0 && node.toString().contains(filterString))) {
node.setExpanded(true);
rootTreeNode.add(node);
}
}
}
private FileNode[] listFileNodes(ExpandMutableTreeNode rootTreeNode) {
if (rootTreeNode == null) {
return new FileNode[0];
}
Object object = rootTreeNode.getUserObject();
if (!(object instanceof FileNode)) {
return new FileNode[0];
}
FileNode[] fileNodes = null;
try {
fileNodes = tree.listFile(((FileNode) object).getEnvPath());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (fileNodes == null) {
fileNodes = new FileNode[0];
}
Arrays.sort(fileNodes, new FileNodeComparator(FileNodeConstants.getSupportFileTypes()));
return fileNodes;
}
public void resetFilePaths(Map<FileNode, TransformResultInfo> resultMap) {
this.tree.resetSelectedPaths();
Iterator<FileNode> iterator = resultMap.keySet().iterator();
List<FileNode> list = new ArrayList<FileNode>();
while (iterator.hasNext()){
FileNode node = iterator.next();
list.add(node);
}
this.tree.addTransformedList(list);
this.tree.refresh();
resultPane.populate(resultMap);
}
public void removeSelectedNode(FileNode fileNode) {
String path = fileNode.getEnvPath();
this.tree.removeSelectedPath(path);
}
@Override
protected String title4PopupWindow() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform");
}
public Dialog showDialog() {
return this.showDialog;
}
}

79
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java

@ -0,0 +1,79 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.BaseUtils;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ilist.UIList;
import com.fr.design.gui.itree.filetree.FileTreeIcon;
import com.fr.file.filetree.FileNode;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
* Created by kerry on 2020-01-13
*/
public class PrepareTransformFileList extends UIList {
private TransformPreparePane transformingPane;
private static final int DELETE_RANGE = 20;
public PrepareTransformFileList(final TransformPreparePane transformingPane) {
super();
this.transformingPane = transformingPane;
this.setBackground(UIConstants.TREE_BACKGROUND);
this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
DefaultListModel listModel = new DefaultListModel();
this.setModel(listModel);
this.setCellRenderer(new UIListControlCellRenderer() {
@Override
protected Icon getLeftLabelIcon(Object value) {
if (value instanceof FileNode) {
return FileTreeIcon.getIcon((FileNode) value);
}
return null;
}
@Override
protected Icon getRightLabelIcon(Object value) {
return BaseUtils.readIcon("/com/fr/nx/app/designer/transform/tab_close.png");
}
});
this.addMouseListener(getListMouseListener());
}
private MouseListener getListMouseListener() {
return new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent evt) {
JList list = (JList) evt.getSource();
int selectedIndex = list.getSelectedIndex();
Rectangle rectangle = list.getCellBounds(selectedIndex, selectedIndex);
if (SwingUtilities.isLeftMouseButton(evt)
&& pointInSelected(rectangle, evt.getX(), evt.getY())) {
Object value = PrepareTransformFileList.this.getSelectedValue();
if (value != null) {
transformingPane.removeSelectedNode((FileNode) value);
}
}
}
};
}
private boolean pointInSelected(Rectangle rectangle, int x, int y) {
if (rectangle == null) {
return false;
}
return x >= rectangle.x + rectangle.width - DELETE_RANGE &&
x <= rectangle.x + rectangle.width &&
y >= rectangle.y && y <= rectangle.y + rectangle.height;
}
}

204
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java

@ -0,0 +1,204 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.FRContext;
import com.fr.base.extension.FileExtension;
import com.fr.design.gui.itree.checkboxtree.CheckBoxTree;
import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeCellRenderer;
import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeSelectionModel;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.remote.ui.tree.FileAuthorityTree;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.nx.app.designer.transform.BatchTransformUtil;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Created by kerry on 2020-01-13
*/
public class TransformFileTree extends FileAuthorityTree {
private TransformPreparePane preparePane;
private static final float CHECKBOX_ENABLE_OPACITY = 0.4f;
private List<FileNode> transformedList = new ArrayList<FileNode>();
public TransformFileTree(TransformPreparePane preparePane) {
this.preparePane = preparePane;
}
public void addTransformedList(List<FileNode> removeList) {
this.transformedList.addAll(removeList);
}
@Override
protected CheckBoxTree.Handler createHandler() {
return new CheckBoxTree.Handler(this) {
@Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
TreePath treePath = this.getTreePathForMouseEvent(e);
if (treePath == null) {
return;
}
CheckBoxTreeSelectionModel selectionModel = _tree.getCheckBoxTreeSelectionModel();
boolean selected = selectionModel.isPathSelected(treePath, selectionModel.isDigIn());
ExpandMutableTreeNode lastPathComponent = (ExpandMutableTreeNode) treePath.getLastPathComponent();
List<FileNode> selectedFileNodes = filterBatchFileNode(lastPathComponent);
preparePane.removeTransformNode(selectedFileNodes);
if (selected) {
preparePane.addTransformNode(selectedFileNodes);
}
}
};
}
private List<FileNode> filterBatchFileNode(ExpandMutableTreeNode treeNode) {
List<FileNode> fileNodeList = new ArrayList<>();
int childCount = treeNode.getChildCount();
if (childCount > 0) {
loadPendingChildTreeNode(treeNode);
int expandChildCount = treeNode.getChildCount();
for (int i = 0; i < expandChildCount; i++) {
fileNodeList.addAll(filterBatchFileNode((ExpandMutableTreeNode) treeNode.getChildAt(i)));
}
} else {
FileNode fileNode = (FileNode) treeNode.getUserObject();
boolean locked = fileNodeLocked(treeNode);
if (!fileNode.isDirectory() && !locked) {
fileNodeList.add((FileNode) treeNode.getUserObject());
}
}
return fileNodeList;
}
private boolean fileNodeLocked(ExpandMutableTreeNode treeNode) {
Object userObj = treeNode.getUserObject();
if (userObj instanceof FileNode) {
FileNode node = (FileNode) userObj;
String lock = node.getLock();
if (lock != null && !node.getUserID().equals(lock)) {
return true;
}
}
return false;
}
public void resetSelectedPaths() {
CheckBoxTreeSelectionModel selectionModel = this.getCheckBoxTreeSelectionModel();
selectionModel.clearSelection();
}
@Override
public void selectCheckBoxPaths(String[] paths) {
if (paths == null || paths.length == 0) {
return;
}
DefaultTreeModel model = (DefaultTreeModel) this.getModel();
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot();
List<TreePath> res = new ArrayList<>();
for (String path : paths) {
TreePath treePath = getSelectedPath(treeNode, path);
if (treePath != null) {
res.add(treePath);
}
}
// 勾选中这些结点
this.getCheckBoxTreeSelectionModel().setSelectionPaths(res.toArray(new TreePath[0]));
}
private TreePath getSelectedPath(ExpandMutableTreeNode treeNode, String path) {
//可以只在选中的path中选择
for (int i = 0, len = treeNode.getChildCount(); i < len; i++) {
ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i);
if (childTreeNode.getChildCount() > 0) {
loadPendingChildTreeNode(childTreeNode);
TreePath treePath = getSelectedPath(childTreeNode, path);
if (treePath != null) {
return treePath;
}
}
if (!(childTreeNode.getUserObject() instanceof FileNode)) {
continue;
}
FileNode fileNode = (FileNode) childTreeNode.getUserObject();
if (ComparatorUtils.equals(path, fileNode.getEnvPath())) {
DefaultTreeModel model = (DefaultTreeModel) this.getModel();
return new TreePath(model.getPathToRoot(childTreeNode));
}
}
return null;
}
public void removeSelectedPath(String path) {
if (path == null) {
return;
}
DefaultTreeModel model = (DefaultTreeModel) this.getModel();
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot();
TreePath selectedPath = getSelectedPath(treeNode, path);
if (selectedPath != null) {
this.getCheckBoxTreeSelectionModel().removeSelectionPath(selectedPath);
}
}
@Override
public FileNode[] listFile(String path) {
// 支持插件扩展, 先从env的filter拿, 再从插件拿
Set<FileExtension> supportTypes = new HashSet<FileExtension>();
for (String temp : this.filter.getSupportedTypes()) {
supportTypes.add(FileExtension.parse(temp));
}
FileNode[] fileNodes = FRContext.getFileNodes().list(
path,
supportTypes.toArray(new FileExtension[supportTypes.size()])
);
return BatchTransformUtil.filterTransformedFile(fileNodes, transformedList);
}
@Override
public boolean isCheckBoxEnabled(TreePath path) {
ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) path.getLastPathComponent();
return !fileNodeLocked(treeNode);
}
@Override
protected CheckBoxTreeCellRenderer createCellRenderer(TreeCellRenderer renderer) {
final CheckBoxTreeCellRenderer checkBoxTreeCellRenderer = new CheckBoxTreeCellRenderer(renderer) {
@Override
public void paint(Graphics g) {
if (!_checkBox.isEnabled()) {
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, CHECKBOX_ENABLE_OPACITY);
((Graphics2D) g).setComposite(composite);
}
super.paint(g);
}
};
addPropertyChangeListener(CELL_RENDERER_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
checkBoxTreeCellRenderer.setActualTreeRenderer((TreeCellRenderer) evt.getNewValue());
}
});
return checkBoxTreeCellRenderer;
}
}

130
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java

@ -0,0 +1,130 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.filetree.FileNode;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.nx.app.designer.transform.BatchTransformer;
import com.fr.nx.app.designer.transform.UpdateCallBack;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by kerry on 2020-01-13
*/
public class TransformPreparePane extends JPanel {
private static final String INITIAL_DISPLAY_TEXT = "0";
private PrepareTransformFileList fileList;
private List<FileNode> selectedFileNodes;
private UpdateProgressDialog dialog;
private BatchTransformer transformer;
private UpdateCallBack updateProgressPane;
private Dialog parentDialog;
private UILabel transCountLabel;
private BatchTransformPane batchTransformPane;
private UIButton startTransform;
public TransformPreparePane(Dialog parentDialog, BatchTransformPane batchTransformPane) {
this.batchTransformPane = batchTransformPane;
this.parentDialog = parentDialog;
this.setLayout(FRGUIPaneFactory.createBorderLayout());
updateProgressPane = new UpdateProgressPane(this);
transformer = new BatchTransformer(updateProgressPane);
fileList = new PrepareTransformFileList(this);
selectedFileNodes = new ArrayList<>();
initPane();
}
private void initPane() {
JPanel transformPane = FRGUIPaneFactory.createTitledBorderPaneCenter(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Template_To_Transform"));
transformPane.setPreferredSize(new Dimension(270, 501));
startTransform = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Start"));
startTransform.setEnabled(false);
addStartTransformListener(startTransform);
transCountLabel = new UILabel(INITIAL_DISPLAY_TEXT);
JPanel northPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
northPane.add(startTransform);
northPane.add(Box.createHorizontalStrut(160));
northPane.add(transCountLabel);
transformPane.add(northPane, BorderLayout.NORTH);
UIScrollPane scrollPane = new UIScrollPane(fileList);
scrollPane.setPreferredSize(new Dimension(260, 442));
scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
transformPane.add(scrollPane, BorderLayout.CENTER);
this.add(transformPane, BorderLayout.CENTER);
}
private void addStartTransformListener(UIButton startTransform) {
startTransform.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//开始转换
transformer.batchTransform(selectedFileNodes);
displayProgressPane();
}
private void displayProgressPane() {
dialog = new UpdateProgressDialog(transformer, parentDialog, (JPanel) updateProgressPane);
dialog.setVisible(true);
}
});
}
public void addTransformNode(List<FileNode> fileNodeList) {
selectedFileNodes.addAll(fileNodeList);
buildFileList();
}
public void removeTransformNode(List<FileNode> fileNodeList) {
selectedFileNodes.removeAll(fileNodeList);
buildFileList();
}
public void removeSelectedNode(FileNode fileNode) {
selectedFileNodes.remove(fileNode);
buildFileList();
this.batchTransformPane.removeSelectedNode(fileNode);
}
private void buildFileList() {
DefaultListModel listModel = new DefaultListModel();
int count = selectedFileNodes.size();
for (int i = count - 1; i >= 0; i--) {
listModel.addElement(selectedFileNodes.get(i));
}
this.fileList.setModel(listModel);
startTransform.setEnabled(selectedFileNodes.size() > 0);
transCountLabel.setText(String.valueOf(selectedFileNodes.size()));
}
public void complete() {
dialog.dialogExit();
updateProgressPane.reset();
Map<FileNode, TransformResultInfo> resultMap = transformer.getResults();
resetFileNodeList();
this.batchTransformPane.resetFilePaths(resultMap);
}
private void resetFileNodeList(){
this.selectedFileNodes.clear();
buildFileList();
}
}

70
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java

@ -0,0 +1,70 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.BaseUtils;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ilist.UIList;
import com.fr.design.gui.itree.filetree.FileTreeIcon;
import com.fr.file.filetree.FileNode;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ListSelectionModel;
import java.util.Iterator;
import java.util.Map;
/**
* Created by kerry on 2020-01-13
*/
public class TransformResultList extends UIList {
private Map<FileNode, TransformResultInfo> resultMap;
private static final Icon FAILED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_failed.png");
private static final Icon SUCCESS_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_success.png");
private static final Icon UNSUPPORT_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_unsupport.png");
public TransformResultList() {
super();
this.setBackground(UIConstants.TREE_BACKGROUND);
this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
DefaultListModel listModel = new DefaultListModel();
this.setModel(listModel);
this.setCellRenderer(new UIListControlCellRenderer() {
@Override
protected Icon getLeftLabelIcon(Object value) {
if (value instanceof FileNode) {
return FileTreeIcon.getIcon((FileNode) value);
}
return null;
}
@Override
protected Icon getRightLabelIcon(Object value) {
if (value != null) {
TransformResultInfo resultInfo = resultMap.get(value);
switch (resultInfo.getResult()) {
case FAILED:
return FAILED_ICON;
case SUCCESS:
return SUCCESS_ICON;
case UNSUPPORT:
return UNSUPPORT_ICON;
}
}
return null;
}
});
}
public void populate(Map<FileNode, TransformResultInfo> resultMap) {
this.resultMap = resultMap;
DefaultListModel listModel = new DefaultListModel();
Iterator<Map.Entry<FileNode, TransformResultInfo>> iterator = resultMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<FileNode, TransformResultInfo> entry = iterator.next();
FileNode key = entry.getKey();
listModel.addElement(key);
}
this.setModel(listModel);
}
}

110
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java

@ -0,0 +1,110 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextarea.UITextArea;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.toolbar.TransformResult;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.Iterator;
import java.util.Map;
/**
* Created by kerry on 2020-01-10
*/
public class TransformResultPane extends JPanel {
private TransformResultList resultList;
private UITextArea resultInfo;
private Map<FileNode, TransformResultInfo> resultMap;
private UILabel successTip;
public TransformResultPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initPane();
}
private void initPane() {
JPanel resultPane = FRGUIPaneFactory.createTitledBorderPaneCenter(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Result"));
JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
resultList = new TransformResultList();
addValueChangeListener();
UIScrollPane scrollPane = new UIScrollPane(resultList);
scrollPane.setPreferredSize(new Dimension(260, 260));
scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
successTip = new UILabel("");
successTip.setBorder(BorderFactory.createEmptyBorder(5, 150, 5, 10));
northPane.add(successTip, BorderLayout.NORTH);
northPane.add(scrollPane, BorderLayout.CENTER);
resultPane.add(northPane);
JPanel resultInfoPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
resultInfoPane.setPreferredSize(new Dimension(270, 165));
resultInfoPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
UILabel transformLogLabel = new UILabel(
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Logs"));
transformLogLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
resultInfoPane.add(transformLogLabel, BorderLayout.NORTH);
resultInfo = new UITextArea();
resultInfo.setBackground(Color.white);
resultInfo.setLineWrap(true);
resultInfo.setWrapStyleWord(true);
resultInfo.setEditable(false);
UIScrollPane resultScrollPane = new UIScrollPane(resultInfo);
resultInfoPane.add(resultScrollPane, BorderLayout.CENTER);
this.add(resultPane, BorderLayout.NORTH);
this.add(resultInfoPane, BorderLayout.CENTER);
}
private void addValueChangeListener() {
resultList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
FileNode selectedValue = (FileNode) resultList.getSelectedValue();
if (resultInfo != null && selectedValue != null) {
TransformResultInfo result = resultMap.get(selectedValue);
resultInfo.setText(result.getTransformLog());
}
}
});
}
public void populate(Map<FileNode, TransformResultInfo> resultMap) {
int count = getSuccessCount(resultMap);
String tip = InterProviderFactory.getProvider().getLocText(
"Fine-Plugin_Engine_Transform_Result_Tip", String.valueOf(count));
successTip.setText(tip);
this.resultMap = resultMap;
resultList.populate(resultMap);
if (resultList.getModel().getSize() > 0) {
resultList.setSelectedIndex(0);
FileNode firstResult = (FileNode) resultList.getModel().getElementAt(0);
resultInfo.setText(resultMap.get(firstResult).getTransformLog());
}
}
private int getSuccessCount(Map<FileNode, TransformResultInfo> resultMap) {
int count = 0;
Iterator<Map.Entry<FileNode, TransformResultInfo>> iterator = resultMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<FileNode, TransformResultInfo> entry = iterator.next();
TransformResultInfo resultInfo = entry.getValue();
if (ComparatorUtils.equals(TransformResult.SUCCESS, resultInfo.getResult())) {
count++;
}
}
return count;
}
}

86
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java

@ -0,0 +1,86 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.stable.StringUtils;
import sun.swing.DefaultLookup;
import javax.swing.Icon;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
/**
* Created by kerry on 2020-01-14
*/
public class UIListControlCellRenderer extends JPanel implements ListCellRenderer {
private UILabel content;
private UILabel controlLabel;
private Color initialLabelForeground;
public UIListControlCellRenderer() {
initPane();
}
private void initPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
content = new UILabel();
initialLabelForeground = content.getForeground();
controlLabel = new UILabel();
controlLabel.setPreferredSize(new Dimension(16, 20));
this.add(content, BorderLayout.CENTER);
this.add(controlLabel, BorderLayout.EAST);
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setComponentOrientation(list.getComponentOrientation());
Color bg = null;
Color fg = null;
JList.DropLocation dropLocation = list.getDropLocation();
if (dropLocation != null
&& !dropLocation.isInsert()
&& dropLocation.getIndex() == index) {
bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground");
fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground");
isSelected = true;
}
if (isSelected) {
setBackground(bg == null ? list.getSelectionBackground() : bg);
setForeground(fg == null ? list.getSelectionForeground() : fg);
content.setForeground(Color.WHITE);
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
content.setForeground(initialLabelForeground);
}
content.setText((value == null) ? StringUtils.EMPTY : value.toString());
Icon leftLabelIcon = getLeftLabelIcon(value);
if (leftLabelIcon != null) {
content.setIcon(leftLabelIcon);
}
Icon rightLabelIcon = getRightLabelIcon(value);
if (rightLabelIcon != null) {
controlLabel.setIcon(rightLabelIcon);
}
return this;
}
protected Icon getLeftLabelIcon(Object value) {
return null;
}
protected Icon getRightLabelIcon(Object value) {
return null;
}
}

70
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java

@ -0,0 +1,70 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.transform.BatchTransformer;
import javax.swing.JDialog;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* Created by kerry on 2019-12-19
*/
public class UpdateProgressDialog extends JDialog implements ActionListener {
private UIButton pauseBtn;
private BatchTransformer transformer;
public UpdateProgressDialog(BatchTransformer transformer, Dialog parent, JPanel contentPane) {
super(parent, true);
this.transformer = transformer;
initPane(contentPane);
}
private void initPane(JPanel contentPane) {
this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Format_Transform"));
this.setResizable(false);
JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
this.setContentPane(defaultPane);
pauseBtn = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend"));
pauseBtn.addActionListener(this);
JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
buttonPanel.add(pauseBtn);
defaultPane.add(contentPane, BorderLayout.CENTER);
defaultPane.add(buttonPanel, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
transformer.shutDown();
dialogExit();
}
});
this.getRootPane().setDefaultButton(pauseBtn);
this.setSize(new Dimension(262, 122));
GUICoreUtils.centerWindow(this);
}
@Override
public void actionPerformed(ActionEvent e) {
transformer.shutDown();
dialogExit();
}
public void dialogExit() {
this.dispose();
}
}

72
designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java

@ -0,0 +1,72 @@
package com.fr.nx.app.designer.transform.ui;
import com.fr.base.BaseUtils;
import com.fr.decision.update.data.UpdateConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.ComparatorUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.nx.app.designer.transform.UpdateCallBack;
import com.sun.java.swing.plaf.motif.MotifProgressBarUI;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import java.awt.BorderLayout;
import java.awt.Dimension;
/**
* Created by kerry on 2019-12-11
*/
public class UpdateProgressPane extends BasicPane implements UpdateCallBack {
private TransformPreparePane contentPane;
private JProgressBar progressBar;
public UpdateProgressPane(TransformPreparePane contentPane) {
this.contentPane = contentPane;
initPane();
}
private void initPane() {
this.setPreferredSize(new Dimension(262, 60));
UILabel icon = new UILabel(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transforming.png"));
icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
this.add(icon, BorderLayout.WEST);
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel title = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transforming"));
title.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));
centerPane.add(title, BorderLayout.NORTH);
progressBar = new JProgressBar();
progressBar.setUI(new MotifProgressBarUI());
progressBar.setForeground(UpdateConstants.BAR_COLOR);
centerPane.add(progressBar, BorderLayout.CENTER);
this.add(centerPane, BorderLayout.CENTER);
}
@Override
public void updateProgress(double progress) {
progressBar.setValue((int) (progress * 100));
if (ComparatorUtils.equals(progress, 1D)) {
contentPane.complete();
}
}
@Override
public void shutDown() {
contentPane.complete();
}
@Override
public void reset() {
progressBar.setValue(0);
}
@Override
protected String title4PopupWindow() {
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend");
}
}

55
designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java

@ -0,0 +1,55 @@
package com.fr.nx.app.designer.utils;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import com.fr.nx.app.designer.toolbar.TransformResult;
import com.fr.nx.app.designer.toolbar.TransformResultInfo;
import com.fr.workspace.WorkContext;
import java.io.InputStream;
import static com.fr.base.extension.FileExtension.CPT;
import static com.fr.base.extension.FileExtension.CPTX;
/**
* Created by kerry on 2019-12-04
*/
public class CompileTransformUtil {
public static TransformResultInfo compileFile(FileNode fileNode) {
long start = System.currentTimeMillis();
InputStream in = WorkContext.getWorkResource().openStream(fileNode.getEnvPath());
WorkBook workBook = new WorkBook();
TransformResultInfo result = null;
try {
workBook.readStream(in);
FILE file = TemplateTransformer.createOutputFile(fileNode.getEnvPath(), CPT.getSuffix(), CPTX.getSuffix());
result = TemplateTransformer.compileCPTX(workBook, file);
} catch (Exception ignore) {
result = TransformResultInfo.generateResult(TransformResult.FAILED);
}
long end = System.currentTimeMillis();
FineLoggerFactory.getLogger().debug(fileNode.getName() + " compile cost : " + (end - start) +" ms ");
return result;
}
public static FILE getTargetFile(JTemplate jTemplate, TemplateTransformer transformer) {
FILE file = null;
if (ComparatorUtils.equals(TemplateTransformer.TO_CPTX, transformer)) {
file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(),
CPT.getSuffix(), CPTX.getSuffix());
} else if (ComparatorUtils.equals(TemplateTransformer.TO_CPT, transformer)) {
file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(),
CPTX.getSuffix(), CPT.getSuffix());
}
return file;
}
}

79
designer-base/src/main/java/com/fr/nx/app/designer/utils/DesignerCptxFileUtils.java

@ -0,0 +1,79 @@
package com.fr.nx.app.designer.utils;
import com.fr.file.FILE;
import com.fr.general.CommonIOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.nx.marshal.impl.xml.DefaultXMLObjectUnmarshaler;
import com.fr.nx.marshal.util.MarshalUtil;
import com.fr.nx.cptx.entry.metadata.CptxMetadata;
import com.fr.nx.cptx.io.handle.impl.OriginCptProvider;
import com.fr.nx.cptx.marshal.util.CptxMarshalUtil;
import com.fr.nx.cptx.utils.CptxFileUtils;
import com.fr.stable.EncodeConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.xml.XMLableReader;
import com.fr.workspace.WorkContext;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by loy on 2021/1/18.
*
* <p>用于设计器的cptx的一些工具类
* <p>
*/
public class DesignerCptxFileUtils {
/**
* 根据file来获取cptx中的cpt
* @param file
* @return
*/
public static WorkBook getWorkBook(final FILE file){
try (InputStream input = file.asInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
CommonIOUtils.copyBinaryTo(input, outputStream);
OriginCptProvider provider = new OriginCptProvider(outputStream.toByteArray());
return CptxFileUtils.getWorkBook(provider);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
/**
* 获取模板的元数据
* @param file
* @return
*/
public static CptxMetadata getMetadata(FILE file){
try {
String metadataPath = StableUtils.pathJoin(generateCompileDir(file), CptxMarshalUtil.NAME_METADATA);
if(!WorkContext.getWorkResource().exist(metadataPath)){
return null;
}
InputStream metadataInput = WorkContext.getWorkResource().openStream(metadataPath);
XMLableReader reader = XMLableReader.createXMLableReader(
new InputStreamReader(metadataInput, EncodeConstants.ENCODING_UTF_8));
CptxMetadata metadata = (CptxMetadata) new DefaultXMLObjectUnmarshaler().unmarshal(
MarshalUtil.createMarshalableExtra(CptxMetadata.class), reader);
return metadata;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
/**
* 根据文件获取编译后的文件夹绝对路径比如原文件位于reportlets/test/merge.cptx转化后为evn://assets/engine/test/merge文件夹
* @param file
* @return
*/
public static String generateCompileDir(FILE file){
String filePath = file.getPath();
return CptxFileUtils.generateCompileDir(filePath);
}
}

2
designer-base/src/main/resources/com/fr/design/images/bbs/bbs_normal.svg

@ -4,4 +4,4 @@
<g id="icon/社区/首页_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M2.41421356,7 L3,7 L3,14 L6,14 L6,10 L10,10 L10,14 L13,14 L13,7 L13.5857864,7 L8,1.41421356 L2.41421356,7 Z M0.341421356,7.65857864 L8,0 L15.6585786,7.65857864 C15.7366835,7.7366835 15.7366835,7.8633165 15.6585786,7.94142136 C15.6210714,7.97892863 15.5702006,8 15.5171573,8 L14,8 L14,15 L9,15 L9,11 L7,11 L7,15 L2,15 L2,8 L0.482842712,8 C0.372385763,8 0.282842712,7.91045695 0.282842712,7.8 C0.282842712,7.7469567 0.303914081,7.69608592 0.341421356,7.65857864 Z" id="Rectangle-148" fill="#333334" fill-rule="nonzero"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 889 B

After

Width:  |  Height:  |  Size: 888 B

8
designer-base/src/main/resources/com/fr/design/images/buttonicon/prewidget_normal.svg

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="30px" height="20px" viewBox="0 0 30 20" 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="M16.0758389,11.7597783 L17.7397914,13.4242307 L14.4118864,16.7516357 L11.4999696,17.9996 L12.747934,15.0876832 L16.0758389,11.7597783 Z M17,3 C17.5522847,3 18,3.44771525 18,4 L18.0005048,10.107534 C17.6771796,10.0020594 17.3340722,9.9742129 17.0003341,10.0239839 L17,4 L5,4 L5,15 L11.697,15 L11.268,16 L5,16 C4.44771525,16 4,15.5522847 4,15 L4,4 C4,3.44771525 4.44771525,3 5,3 L17,3 Z M18,14.577 L18,15 C18,15.5522847 17.5522847,16 17,16 L16.576,16 L18,14.577 Z M18.1553795,11.3442402 C18.6148663,11.803727 18.6148663,12.5487057 18.1553795,13.0081926 L16.491427,11.3442402 C16.9509139,10.8852533 17.6958926,10.8852533 18.1553795,11.3442402 Z M15,10 L15,11.42 L13.42,13 L9,13 L9,10 L15,10 Z M8,10 L8,12 L6,12 L6,10 L8,10 Z M14,11 L10,11 L10,12 L14,12 L14,11 Z M15,6 L15,9 L9,9 L9,6 L15,6 Z M8,6 L8,8 L6,8 L6,6 L8,6 Z M14,7 L10,7 L10,8 L14,8 L14,7 Z" id="Combined-Shape" fill="#333334" fill-rule="nonzero"></path>
<path d="M23.3414214,10.3414214 L27,14 L27,14 L23.3414214,17.6585786 C23.2633165,17.7366835 23.1366835,17.7366835 23.0585786,17.6585786 C23.0210714,17.6210714 23,17.5702006 23,17.5171573 L23,10.4828427 C23,10.3723858 23.0895431,10.2828427 23.2,10.2828427 C23.2530433,10.2828427 23.3039141,10.3039141 23.3414214,10.3414214 Z" id="Rectangle-2" fill="#333334"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

7
designer-base/src/main/resources/com/fr/design/images/buttonicon/widget/files_up_normal.svg

@ -0,0 +1,7 @@
<?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="M11,-1.28785871e-13 L15,4.001 L15,14 L4,14 L4,3 L2,3 L2,15 L11,15 L11,14 L12,14 L12,16 L1,16 L1,2 L4,2 L4,-1.35780276e-13 L11,-1.28785871e-13 Z M10.586,1 L5,1 L5,13 L14,13 L13.999,4.415 L11,4.415 L10.999,4.405 L11,4.415 L10.586,4.415 L10.586,1 Z M13,10 L13,11 L6,11 L6,10 L13,10 Z M13,8 L13,9 L6,9 L6,8 L13,8 Z M13,6 L13,7 L6,7 L6,6 L13,6 Z" id="形状结合" fill="#333334"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 758 B

16
designer-base/src/main/resources/com/fr/design/images/control/addPopup_disabled.svg

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="16px" viewBox="0 0 24 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.3">
<g id="工具栏/导入数据集" transform="translate(-8.000000, -6.000000)">
<g id="编组" transform="translate(8.000000, 6.000000)">
<g fill="#333334" id="Combined-Shape">
<path d="M8,2 C8.38659932,2 8.7,2.32097101 8.7,2.69703907 L8.7,7.3 L13.3029609,7.3 C13.6558446,7.3 13.9474813,7.56107882 13.9936369,7.90444795 L14,8 C14,8.38659932 13.679029,8.7 13.3029609,8.7 L8.7,8.699 L8.7,13.3029609 C8.7,13.6558446 8.43892118,13.9474813 8.09555205,13.9936369 L8,14 C7.61340068,14 7.3,13.679029 7.3,13.3029609 L7.3,8.699 L2.69703907,8.7 C2.34415536,8.7 2.05251868,8.43892118 2.00636315,8.09555205 L2,8 C2,7.61340068 2.32097101,7.3 2.69703907,7.3 L7.3,7.3 L7.3,2.69703907 C7.3,2.34415536 7.56107882,2.05251868 7.90444795,2.00636315 L8,2 Z"></path>
</g>
<g transform="translate(16.000000, 4.000000)" fill="#8F8F92" id="Rectangle-6">
<path d="M2,0.997030139 C2,0.446385598 2.31387329,0.313873291 2.70591205,0.705912054 L6,4 L2.70591205,7.29408795 C2.31604759,7.68395241 2,7.54696369 2,7.00296986 L2,0.997030139 Z" transform="translate(4.000000, 4.000000) rotate(90.000000) translate(-4.000000, -4.000000) "></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

14
designer-base/src/main/resources/com/fr/design/images/control/addPopup_normal.svg

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="16px" viewBox="0 0 24 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组备份</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组备份">
<g id="Combined-Shape" fill="#333334">
<path d="M8,2 C8.38659932,2 8.7,2.32097101 8.7,2.69703907 L8.7,7.3 L13.3029609,7.3 C13.6558446,7.3 13.9474813,7.56107882 13.9936369,7.90444795 L14,8 C14,8.38659932 13.679029,8.7 13.3029609,8.7 L8.7,8.699 L8.7,13.3029609 C8.7,13.6558446 8.43892118,13.9474813 8.09555205,13.9936369 L8,14 C7.61340068,14 7.3,13.679029 7.3,13.3029609 L7.3,8.699 L2.69703907,8.7 C2.34415536,8.7 2.05251868,8.43892118 2.00636315,8.09555205 L2,8 C2,7.61340068 2.32097101,7.3 2.69703907,7.3 L7.3,7.3 L7.3,2.69703907 C7.3,2.34415536 7.56107882,2.05251868 7.90444795,2.00636315 L8,2 Z"></path>
</g>
<g id="Rectangle-6" transform="translate(16.000000, 4.000000)" fill="#8F8F92">
<path d="M2,0.997030139 C2,0.446385598 2.31387329,0.313873291 2.70591205,0.705912054 L6,4 L2.70591205,7.29408795 C2.31604759,7.68395241 2,7.54696369 2,7.00296986 L2,0.997030139 Z" transform="translate(4.000000, 4.000000) rotate(90.000000) translate(-4.000000, -4.000000) "></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

8
designer-base/src/main/resources/com/fr/design/images/control/edit_disabled.svg

@ -0,0 +1,8 @@
<?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_编辑_disable</title>
<g id="icon_编辑_disable" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.299107143">
<path d="M9.95422984,2.34704298 L13.4897637,5.88257688 L6.18790578,13.1844348 L0.884604926,14.9522018 L2.65237188,9.64890094 L9.95422984,2.34704298 Z M13.4897637,1.6399362 L14.1968705,2.34704298 C14.9368113,3.08698374 14.9757555,4.2624679 14.3137033,5.04825533 L14.1968705,5.1754701 L10.6613366,1.6399362 C11.4423852,0.858887612 12.7087152,0.858887612 13.4897637,1.6399362 Z" id="形状结合" fill="#333334"></path>
<rect id="矩形" fill="#333334" x="7" y="14" width="7" height="1"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 864 B

8
designer-base/src/main/resources/com/fr/design/images/control/edit_normal.svg

@ -0,0 +1,8 @@
<?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="M9.95422984,2.34704298 L13.4897637,5.88257688 L6.18790578,13.1844348 L0.884604926,14.9522018 L2.65237188,9.64890094 L9.95422984,2.34704298 Z M13.4897637,1.6399362 L14.1968705,2.34704298 C14.9368113,3.08698374 14.9757555,4.2624679 14.3137033,5.04825533 L14.1968705,5.1754701 L10.6613366,1.6399362 C11.4423852,0.858887612 12.7087152,0.858887612 13.4897637,1.6399362 Z" id="形状结合" fill="#333334"></path>
<rect id="矩形" fill="#333334" x="7" y="14" width="7" height="1"></rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 840 B

11
designer-base/src/main/resources/com/fr/design/images/control/remove_disabled.svg

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_删除_normal</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.3">
<g id="工具栏/导入数据集" transform="translate(-78.000000, -7.000000)" fill="#333334">
<g id="icon_删除_normal" transform="translate(77.000000, 6.000000)">
<path d="M11,1 L11,3 L15,3 L15,4 L13,4 L13,15 L3,15 L3,4 L1,4 L1,3 L5,3 L5,1 L11,1 Z M12,4 L4,4 L4,14 L12,14 L12,4 Z M7,6 L7,12 L6,12 L6,6 L7,6 Z M10,6 L10,12 L9,12 L9,6 L10,6 Z M10,2 L6,2 L6,3 L10,3 L10,2 Z" id="Combined-Shape"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 804 B

9
designer-base/src/main/resources/com/fr/design/images/control/remove_normal.svg

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_删除_normal备份</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Combined-Shape" transform="translate(-1.000000, -1.000000)" fill="#333334">
<path d="M11,1 L11,3 L15,3 L15,4 L13,4 L13,15 L3,15 L3,4 L1,4 L1,3 L5,3 L5,1 L11,1 Z M12,4 L4,4 L4,14 L12,14 L12,4 Z M7,6 L7,12 L6,12 L6,6 L7,6 Z M10,6 L10,12 L9,12 L9,6 L10,6 Z M10,2 L6,2 L6,3 L10,3 L10,2 Z"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 660 B

11
designer-base/src/main/resources/com/fr/design/images/m_file/preview_disabled.svg

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="14px" viewBox="0 0 12 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_报表web属性_打印预览_normal</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.3">
<g id="工具栏/导入数据集" transform="translate(-116.000000, -7.000000)" fill="#333334">
<g id="icon_报表web属性_打印预览_normal" transform="translate(114.000000, 6.000000)">
<path d="M9.5,7 C11.432875,7 13,8.567125 13,10.5 C13,11.1075915 12.845147,11.679042 12.5727578,12.1770349 C12.6203353,12.2075319 12.6650188,12.2450114 12.7069,12.287 L13.7129,13.293 C14.1039,13.684 14.1039,14.316 13.7129,14.707 C13.5179,14.902 13.2619,15 13.0059,15 C12.7499,15 12.4939,14.902 12.2989,14.707 L11.2929,13.701 C11.251507,13.6597129 11.2144961,13.6157024 11.1818672,13.5695439 C10.6844106,13.8436886 10.110446,14 9.5,14 C7.567125,14 6,12.432875 6,10.5 C6,8.567125 7.567125,7 9.5,7 Z M10,1 L14,5 L14,8 L13,8 L13,6 L9,6 L9,2 L3,2 L3,14 L7,14 L7,15 L2,15 L2,1 L10,1 Z M9.5,8 C10.8783333,8 12,9.12166667 12,10.5 C12,11.8783333 10.8783333,13 9.5,13 C8.12166667,13 7,11.8783333 7,10.5 C7,9.12166667 8.12166667,8 9.5,8 Z M12.587,5 L10,2.414 L10,5 L12.587,5 Z" id="Combined-Shape"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

9
designer-base/src/main/resources/com/fr/design/images/m_file/preview_normal.svg

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="14px" viewBox="0 0 12 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>icon_报表web属性_打印预览_normal备份</title>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Combined-Shape" transform="translate(-2.000000, -1.000000)" fill="#333334">
<path d="M9.5,7 C11.432875,7 13,8.567125 13,10.5 C13,11.1075915 12.845147,11.679042 12.5727578,12.1770349 C12.6203353,12.2075319 12.6650188,12.2450114 12.7069,12.287 L13.7129,13.293 C14.1039,13.684 14.1039,14.316 13.7129,14.707 C13.5179,14.902 13.2619,15 13.0059,15 C12.7499,15 12.4939,14.902 12.2989,14.707 L11.2929,13.701 C11.251507,13.6597129 11.2144961,13.6157024 11.1818672,13.5695439 C10.6844106,13.8436886 10.110446,14 9.5,14 C7.567125,14 6,12.432875 6,10.5 C6,8.567125 7.567125,7 9.5,7 Z M10,1 L14,5 L14,8 L13,8 L13,6 L9,6 L9,2 L3,2 L3,14 L7,14 L7,15 L2,15 L2,1 L10,1 Z M9.5,8 C10.8783333,8 12,9.12166667 12,10.5 C12,11.8783333 10.8783333,13 9.5,13 C8.12166667,13 7,11.8783333 7,10.5 C7,9.12166667 8.12166667,8 9.5,8 Z M12.587,5 L10,2.414 L10,5 L12.587,5 Z"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

239
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java

@ -0,0 +1,239 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.Parameter;
import com.fr.base.chart.BaseChartCollection;
import com.fr.base.io.XMLEncryptKey;
import com.fr.base.io.XMLEncryptUtils;
import com.fr.base.iofile.IOFileAttrMarkManager;
import com.fr.base.parameter.ParameterUI;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.config.dao.DaoContext;
import com.fr.config.dao.impl.LocalClassHelperDao;
import com.fr.config.dao.impl.LocalEntityDao;
import com.fr.config.dao.impl.LocalXmlEntityDao;
import com.fr.file.MemFILE;
import com.fr.form.DefaultFormOperator;
import com.fr.form.FormOperator;
import com.fr.form.main.ExtraFormClassManager;
import com.fr.form.main.Form;
import com.fr.form.main.FormHyperlink;
import com.fr.form.main.parameter.FormParameterUI;
import com.fr.form.parameter.FormSubmitButton;
import com.fr.form.plugin.DefaultSwitcherImpl;
import com.fr.general.xml.GeneralXMLTools;
import com.fr.io.EncryptUtils;
import com.fr.js.FormHyperlinkProvider;
import com.fr.main.impl.WorkBook;
import com.fr.nx.calculable.Calculable;
import com.fr.nx.calculable.type.ConstantCalculable;
import com.fr.nx.cell.CellKey;
import com.fr.nx.cell.CellTemplate;
import com.fr.nx.cptx.cache.CptxTemplatePool;
import com.fr.nx.cptx.entry.CptxTemplate;
import com.fr.nx.cptx.resource.ImageResourceRef;
import com.fr.page.BaseSinglePagePrintable;
import com.fr.page.BaseSingleReportCache;
import com.fr.page.ClippedChartPage;
import com.fr.page.ClippedECPage;
import com.fr.page.ClippedPageProvider;
import com.fr.page.PDF2Painter;
import com.fr.page.PageGeneratorProvider;
import com.fr.page.PagePainter;
import com.fr.page.PagePainterProvider;
import com.fr.page.PageSetChainProvider;
import com.fr.page.PageSetProvider;
import com.fr.page.PageXmlOperator;
import com.fr.page.PageXmlProvider;
import com.fr.page.PaperSettingProvider;
import com.fr.page.ReportPage;
import com.fr.page.ReportPageAttrProvider;
import com.fr.page.ReportPageProvider;
import com.fr.page.SheetPage;
import com.fr.page.SinglePagePrintable;
import com.fr.page.SingleReportCache;
import com.fr.page.generator.PaginateReportPageGenerator;
import com.fr.page.generator.PolyReportPageGenerator;
import com.fr.page.generator.SheetPageGenerator;
import com.fr.page.pageset.ArrayPageSet;
import com.fr.page.pageset.PageSetChain;
import com.fr.page.stable.PaperSetting;
import com.fr.page.stable.ReportPageAttr;
import com.fr.plugin.attr.CalculatorAttrMark;
import com.fr.runtime.FineRuntime;
import com.fr.stable.EssentialUtils;
import com.fr.stable.bridge.BridgeMark;
import com.fr.stable.bridge.StableFactory;
import com.fr.stable.fun.WidgetSwitcher;
import com.fr.stable.module.Module;
import com.fr.stable.plugin.ExtraFormClassManagerProvider;
import com.fr.transaction.Configurations;
import com.fr.transaction.LocalConfigurationHelper;
import com.fr.xml.ReportXMLUtils;
import org.easymock.EasyMock;
import org.easymock.IArgumentMatcher;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import java.io.InputStream;
@RunWith(PowerMockRunner.class)
@PrepareForTest({CptxTemplatePool.class, XMLEncryptUtils.class})
@SuppressStaticInitializationFor({"com.fr.nx.cptx.cache.CptxTemplatePool", "com.fr.base.io.XMLEncryptUtils"})
@PowerMockIgnore({"com.sun.tools.attach.*", "sun.tools.attach.*"})
public class TemplateTransformerDebugTest {
@BeforeClass
public static void beforeClass() {
System.setProperty("apple.awt.UIElement", "true");
StableFactory.registerXMLDescription(ReportPageAttrProvider.XML_TAG, new ReportPageAttr());
StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG, ReportPage.class);
StableFactory.registerMarkedClass(PaperSettingProvider.XML_TAG, PaperSetting.class);
StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG_4_SHEET, SheetPage.class);
StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG, PagePainter.class);
StableFactory.registerMarkedClass(PageSetChainProvider.XML_TAG, PageSetChain.class);
StableFactory.registerMarkedClass(PageXmlProvider.XML_TAG, PageXmlOperator.class);
StableFactory.registerMarkedClass(BaseSinglePagePrintable.XML_TAG, SinglePagePrintable.class);
StableFactory.registerMarkedClass(BaseSingleReportCache.XML_TAG, SingleReportCache.class);
StableFactory.registerMarkedClass(PageSetProvider.XML_TAG_4_ARRAY, ArrayPageSet.class);
StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_EC, ClippedECPage.class);
StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_CHART, ClippedChartPage.class);
StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_PAGE, PaginateReportPageGenerator.class);
StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_POLY, PolyReportPageGenerator.class);
StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_SHEET, SheetPageGenerator.class);
StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG_4_PDF, PDF2Painter.class);
StableFactory.registerMarkedClass(BridgeMark.SUBMIT_BUTTON, FormSubmitButton.class);
StableFactory.registerMarkedClass(FormOperator.MARK_STRING, DefaultFormOperator.class);
StableFactory.registerMarkedClass(Module.FORM_MODULE, Form.class);
StableFactory.registerMarkedClass(ParameterUI.FORM_XML_TAG, FormParameterUI.class);
StableFactory.registerMarkedClass(FormHyperlinkProvider.XML_TAG, FormHyperlink.class);
StableFactory.registerMarkedObject(WidgetSwitcher.XML_TAG, new DefaultSwitcherImpl());
StableFactory.registerMarkedClass(ExtraFormClassManagerProvider.XML_TAG, ExtraFormClassManager.class);
StableFactory.registerXMLDescription(BaseChartCollection.XML_TAG, new ChartCollection());
StableFactory.registerXMLDescription(Parameter.XML_TAG, new Parameter());
FineRuntime.start();
GeneralXMLTools.Object_Tokenizer = new ReportXMLUtils.ReportObjectTokenizer();
GeneralXMLTools.Object_XML_Writer_Finder = new ReportXMLUtils.ReportObjectXMLWriterFinder();
DaoContext.setEntityDao(new LocalEntityDao());
DaoContext.setClassHelperDao(new LocalClassHelperDao());
DaoContext.setXmlEntityDao(new LocalXmlEntityDao());
Configurations.setHelper(new LocalConfigurationHelper());
IOFileAttrMarkManager.register(new CalculatorAttrMark());
}
@Before
public void before() {
Whitebox.setInternalState(XMLEncryptUtils.class, "KEY", new XMLEncryptKey());
}
@Test
public void testUnsupportedCompile() {
WorkBook workbook = readCpt("read-write-expand-order.cpt");
CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class);
PowerMock.mockStatic(CptxTemplatePool.class);
EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes();
PowerMock.replay(CptxTemplatePool.class);
pool.addCptxTemplate(EasyMock.anyString(), matchUnsupportedWebPreviewCptxTemplate());
EasyMock.expectLastCall().once();
EasyMock.replay(pool);
TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-expand-order.cpt"));
EasyMock.verify(pool);
PowerMock.verify(CptxTemplatePool.class);
}
@Test
public void testImageRefCompile() {
WorkBook workbook = readCpt("read-write-image-ref.cpt");
CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class);
PowerMock.mockStatic(CptxTemplatePool.class);
EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes();
PowerMock.replay(CptxTemplatePool.class);
pool.addCptxTemplate(EasyMock.anyString(), matchImageRefWebPreviewCptxTemplate());
EasyMock.expectLastCall().once();
EasyMock.replay(pool);
TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-image-ref.cpt"));
EasyMock.verify(pool);
PowerMock.verify(CptxTemplatePool.class);
}
private CptxTemplate matchImageRefWebPreviewCptxTemplate() {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
if (argument instanceof CptxTemplate) {
CptxTemplate cptxTemplate = (CptxTemplate) argument;
Assert.assertNotNull(cptxTemplate.getTemplate());
Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult());
Assert.assertEquals(1, cptxTemplate.getTemplate().getCompileResult().getCellBlocks().length);
Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure());
Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells());
CellTemplate cellTemplate = cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells().get(CellKey.fromString("A2"));
Assert.assertNotNull(cellTemplate);
Calculable calculable = cellTemplate.getCalculable();
ConstantCalculable constantCalculable = calculable.unWrap(ConstantCalculable.KEY);
Assert.assertNotNull(constantCalculable);
Assert.assertTrue(constantCalculable.get() instanceof ImageResourceRef);
return true;
}
return false;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("cptx template should be previewed on the web side but not.");
}
});
return null;
}
private CptxTemplate matchUnsupportedWebPreviewCptxTemplate() {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object argument) {
if (argument instanceof CptxTemplate) {
CptxTemplate cptxTemplate = (CptxTemplate) argument;
Assert.assertEquals("unsupported feature: sort after expand",
cptxTemplate.getMetadata().getFailMessage());
return true;
}
return false;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("should find unsupported error message but not");
}
});
return null;
}
private static WorkBook readCpt(String subPath) {
InputStream is = TemplateTransformerDebugTest.class.getClassLoader().getResourceAsStream("cpt/" + subPath);
WorkBook wb = new WorkBook();
try {
wb.readStream(EncryptUtils.decodeInputStream(is));
} catch (Exception e) {
throw new RuntimeException(e);
}
return wb;
}
}

85
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java

@ -0,0 +1,85 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.base.FRContext;
import com.fr.base.operator.common.CommonOperator;
import com.fr.file.FILE;
import com.fr.file.filetree.FileNodes;
import com.fr.invoke.Reflect;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static com.fr.nx.app.designer.toolbar.TemplateTransformer.OTHER;
import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPT;
import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPTX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@RunWith(PowerMockRunner.class)
@PrepareForTest({FRContext.class})
@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*", "com.fr.license.*"})
public class TemplateTransformerTest {
@Test
public void testParse() {
assertEquals(TO_CPTX, TemplateTransformer.parse("/sdf/abc.cpt"));
assertEquals(TO_CPT, TemplateTransformer.parse("/sdf/abc.cptx"));
assertEquals(OTHER, TemplateTransformer.parse("/sdf/abc.frm"));
assertEquals(OTHER, TemplateTransformer.parse(null));
assertEquals(OTHER, TemplateTransformer.parse("abc"));
}
@Test
public void testCompileFailed() {
TransformResultInfo result = TemplateTransformer.compileCPTX(null, null);
assertEquals(result.getResult(), TransformResult.FAILED);
}
@Test
public void testGenerateNewPath() {
assertEquals(generateNewPath("/abc/dd.cpt", ".cpt", ".cptx"), "/abc/dd.cptx");
assertEquals(generateNewPath("/abc/dd.cptx", ".cpt", ".cptx"), "/abc/dd.cptx");
assertEquals(generateNewPath("/abc/dd.cptx", ".cptx", ".cpt"), "/abc/dd.cpt");
assertEquals(generateNewPath("/abc/dd.frm", ".cpt", ".cptx"), "/abc/dd.frm");
assertNull(generateNewPath(null, null, null));
assertEquals(generateNewPath("abc", null, null), "abc");
}
private String generateNewPath(String oldPath, String oldSuffix, String newSuffix) {
return Reflect.on(TemplateTransformer.class).call("generateNewPath", oldPath, oldSuffix, newSuffix).get();
}
@Test
public void testCreateOutputFile() {
CommonOperator commonOperator = EasyMock.mock(CommonOperator.class);
FileNodes fileNodes = EasyMock.mock(FileNodes.class);
EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes();
PowerMock.mockStatic(FRContext.class);
EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes();
EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes();
EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes();
EasyMock.replay(commonOperator, fileNodes);
PowerMock.replayAll();
FILE file1 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cpt", ".cptx");
FILE file2 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cptx", ".cpt");
assertEquals("WorkBook1.cptx", file1.getPath());
assertEquals("WorkBook1.cpt", file2.getPath());
}
@Test
public void testNeedDoAfterTransformed() {
Assert.assertTrue(needDoAfterTransformed(TransformResult.SUCCESS));
Assert.assertTrue(needDoAfterTransformed(TransformResult.UNSUPPORT));
Assert.assertFalse(needDoAfterTransformed(TransformResult.FAILED));
}
private boolean needDoAfterTransformed(TransformResult result) {
return Reflect.on(TemplateTransformer.class).call("needDoAfterTransformed", result).get();
}
}

32
designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java

@ -0,0 +1,32 @@
package com.fr.nx.app.designer.toolbar;
import com.fr.locale.InterProviderFactory;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by kerry on 2020-01-15
*/
public class TransformResultInfoTest {
@Test
public void testGetTransformLog() {
TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed");
Assert.assertEquals("failed\n" +
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"),
resultInfo1.getTransformLog());
TransformResultInfo resultInfo2 = TransformResultInfo.generateResult(TransformResult.SUCCESS);
Assert.assertEquals(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"),
resultInfo2.getTransformLog());
TransformResultInfo resultInfo3 = TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "unsupport");
Assert.assertEquals("unsupport\n" +
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"),
resultInfo3.getTransformLog());
}
@Test
public void testSaved() {
TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed").saved(false);
Assert.assertFalse(resultInfo1.isSaved());
}
}

27
designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java

@ -0,0 +1,27 @@
package com.fr.nx.app.designer.transform;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by kerry on 2020-01-15
*/
public class BatchTransformProgressTest {
@Test
public void testGetProgress(){
BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100);
Assert.assertEquals(0.0D, batchTransformProgress.getProgress(), 0.0D);
}
@Test
public void testUpdateProgress(){
BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100);
for (int i = 0; i < 80; i++) {
batchTransformProgress.updateProgress();
}
Assert.assertEquals(0.8D, batchTransformProgress.getProgress(), 0.0D);
batchTransformProgress.updateProgress();
Assert.assertEquals(0.81D, batchTransformProgress.getProgress(), 0.0D);
}
}

35
designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java

@ -0,0 +1,35 @@
package com.fr.nx.app.designer.transform;
import com.fr.file.filetree.FileNode;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-02-14
*/
public class BatchTransformUtilTest {
@Test
public void testFilterTransformedFile(){
FileNode[] fileNodes = new FileNode[]{
new FileNode("test1", false), new FileNode("test2", false)
};
List<FileNode> transformedFileNodes = new ArrayList<FileNode>();
FileNode[] result1 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(2, result1.length);
transformedFileNodes.add( new FileNode("test1", false));
FileNode[] result2 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(1, result2.length);
transformedFileNodes.add( new FileNode("test2", false));
FileNode[] result3 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(0, result3.length);
transformedFileNodes.add( new FileNode("test3", false));
FileNode[] result4 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes);
Assert.assertEquals(0, result4.length);
}
}

124
designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java

@ -0,0 +1,124 @@
package com.fr.nx.app.designer.transform;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
/**
* Created by kerry on 2020-01-15
*/
// FIXME @kerry 打包失败,暂时先注释
//@RunWith(value = PowerMockRunner.class)
//@PrepareForTest({CompileTransformUtil.class, PluginContexts.class})
//@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"})
public class BatchTransformerTest {
private static final int MAXPOOLSIZE = 5;
private static final int COREPOOLSIZE = 3;
private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s";
@Before
public void setUp() {
// FineRuntime.start();
// ExecutorService threadPoolExecutor = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE,
// 0L, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>(),
// new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build());
// PowerMock.mockStatic(PluginContexts.class);
// PluginContext pluginContext = EasyMock.mock(PluginContext.class);
// EasyMock.expect(pluginContext.newFixedThreadPool(
// EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class)))
// .andReturn(threadPoolExecutor).anyTimes();
// EasyMock.expect(PluginContexts.currentContext()).andReturn(pluginContext).anyTimes();
//
// PowerMock.mockStatic(CompileTransformUtil.class);
// TransformResultInfo resultInfo = TransformResultInfo.generateResult(TransformResult.SUCCESS);
// EasyMock.expect(CompileTransformUtil.compileFile(EasyMock.anyObject(FileNode.class)))
// .andReturn(resultInfo).anyTimes();
// EasyMock.replay(pluginContext);
// PowerMock.replayAll();
}
@Test
public void testBatchTransform() {
// final CountDownLatch countDownLatch = new CountDownLatch(2);
// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch));
// List<FileNode> nodeList = new ArrayList<>();
// FileNode test1 = new FileNode("path1", false);
// FileNode test2 = new FileNode("path2", false);
// nodeList.add(test1);
// nodeList.add(test2);
// transformer.batchTransform(nodeList);
// try {
// countDownLatch.await(5, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// Assert.fail();
// }
// Map<FileNode, TransformResultInfo> transformResults = transformer.getResults();
// Assert.assertEquals(2, transformResults.size());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test1).getResult());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test2).getResult());
}
@Test
public void testTransform() {
// final CountDownLatch countDownLatch = new CountDownLatch(1);
// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch));
// FileNode test = new FileNode("path", false);
// Reflect.on(transformer).call("transform", test);
// try {
// countDownLatch.await(5, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// Assert.fail();
// }
// Map<FileNode, TransformResultInfo> transformResults = transformer.getResults();
// Assert.assertEquals(1, transformResults.size());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult());
}
@Test
public void testShutDown() {
// final CountDownLatch countDownLatch = new CountDownLatch(1);
// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch));
// List<FileNode> nodeList = new ArrayList<>();
// FileNode test = new FileNode("path", false);
// nodeList.add(test);
// transformer.batchTransform(nodeList);
// transformer.shutDown();
// try {
// countDownLatch.await(3, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// Assert.fail();
// }
// Map<FileNode, TransformResultInfo> transformResults = transformer.getResults();
// Assert.assertEquals(1, transformResults.size());
// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult());
}
private class MockUpdateCallBack implements UpdateCallBack {
private CountDownLatch countDownLatch;
public MockUpdateCallBack(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void updateProgress(double progress) {
countDownLatch.countDown();
}
@Override
public void shutDown() {
}
@Override
public void reset() {
}
}
}

58
designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java

@ -0,0 +1,58 @@
package com.fr.nx.app.designer.utils;
import com.fr.base.FRContext;
import com.fr.base.operator.common.CommonOperator;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.filetree.FileNodes;
import com.fr.nx.app.designer.toolbar.TemplateTransformer;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* Created by kerry on 2019-12-04
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({FRContext.class})
@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"})
public class CompileTransformUtilTest {
@Test
public void testGetTargetFile() {
CommonOperator commonOperator = EasyMock.mock(CommonOperator.class);
FileNodes fileNodes = EasyMock.mock(FileNodes.class);
EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes();
PowerMock.mockStatic(FRContext.class);
EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes();
EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes();
EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes();
EasyMock.replay(commonOperator, fileNodes);
PowerMock.replayAll();
JTemplate jTemplate1 = EasyMock.mock(JTemplate.class);
FILE file1 = EasyMock.mock(FILE.class);
EasyMock.expect(jTemplate1.getEditingFILE()).andReturn(file1).anyTimes();
EasyMock.expect(file1.getPath()).andReturn("WorkBook1.cpt").anyTimes();
EasyMock.replay(jTemplate1, file1);
FILE targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPTX);
Assert.assertEquals("WorkBook1.cptx", targetFile.getPath());
targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPT);
Assert.assertEquals("WorkBook1.cpt", targetFile.getPath());
JTemplate jTemplate2 = EasyMock.mock(JTemplate.class);
FILE file2 = EasyMock.mock(FILE.class);
EasyMock.expect(jTemplate2.getEditingFILE()).andReturn(file2).anyTimes();
EasyMock.expect(file2.getPath()).andReturn("WorkBook1.cpt").anyTimes();
EasyMock.replay(jTemplate2, file2);
targetFile = CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPTX);
Assert.assertEquals("WorkBook1.cptx", targetFile.getPath());
targetFile =CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPT);
Assert.assertEquals("WorkBook1.cpt", targetFile.getPath());
}
}

11
designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java

@ -47,7 +47,6 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -464,15 +463,9 @@ public class VanChartTooltipContentPane extends BasicBeanPane<AttrTooltipContent
private void refreshTableFieldParams(Map<String, String> params) {
List<String> tableFieldNames = VanChartRichEditorPane.getFieldNames();
List<String> defaultParams = Arrays.asList(getRichTextFieldNames());
if (tableFieldNames == null || params == null) {
return;
}
for (String fieldName : tableFieldNames) {
// 富文本默认参数和数据集字段重名时,显示默认参数
if (!defaultParams.contains(fieldName)) {
if (tableFieldNames != null && params != null) {
for (String fieldName : tableFieldNames) {
params.put(fieldName, "${" + fieldName + "_" + fieldName.hashCode() + "}");
}
}

83
designer-form/src/main/java/com/fr/design/actions/FormFitAttrAction.java

@ -0,0 +1,83 @@
package com.fr.design.actions;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.UIDialog;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.fit.NewJForm;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.MenuKeySet;
import com.fr.report.fit.FitProvider;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
/**
* Created by Administrator on 2015/7/6 0006.
*/
public class FormFitAttrAction extends JTemplateAction {
private static final MenuKeySet REPORT_FIT_ATTR_ELEMENTCASE = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'T';
}
@Override
public String getMenuName() {
return DesignerUIModeConfig.getInstance().newUIMode() ?
com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_PC_Adaptive_Attr") :
com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_PC_Element_Case_Fit_Attr");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
public FormFitAttrAction(JTemplate jTemplate) {
super(jTemplate);
initMenuStyle();
}
private void initMenuStyle() {
this.setMenuKeySet(REPORT_FIT_ATTR_ELEMENTCASE);
this.setName(getMenuKeySet().getMenuKeySetName() + "...");
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(DesignerUIModeConfig.getInstance().newUIMode() ?
"/com/fr/design/images/reportfit/fit.png":
"/com/fr/design/images/reportfit/fit");
}
/**
* Action触发事件
*
* @param e 事件
*/
@Override
public void actionPerformed(ActionEvent e) {
final JTemplate jwb = getEditingComponent();
if (jwb == null || !(jwb instanceof NewJForm)) {
return;
}
final FitProvider wbTpl = (FitProvider) jwb.getTarget();
ReportFitAttr fitAttr = wbTpl.getReportFitAttr();
NewJForm newJForm = (NewJForm) jwb;
BasicBeanPane attrPane = newJForm.getJFormType().obtainAttrPane(newJForm);
showFitDialog(fitAttr, jwb, wbTpl, attrPane);
}
private void showFitDialog(ReportFitAttr fitAttr, final JTemplate jwb, final FitProvider wbTpl, final BasicBeanPane<ReportFitAttr> attrPane) {
attrPane.populateBean(fitAttr);
UIDialog dialog = attrPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
wbTpl.setReportFitAttr(attrPane.updateBean());
jwb.fireTargetModified();
}
});
dialog.setVisible(true);
}
}

115
designer-form/src/main/java/com/fr/design/actions/NewFormMobileAttrAction.java

@ -0,0 +1,115 @@
package com.fr.design.actions;
import com.fr.base.iofile.attr.MobileOnlyTemplateAttrMark;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteBodyLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.fit.NewJForm;
import com.fr.design.fit.common.AdaptiveSwitchUtil;
import com.fr.design.fit.common.TemplateTool;
import com.fr.design.form.mobile.FormMobileAttrPane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.FormArea;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.file.FILE;
import com.fr.form.main.Form;
import com.fr.form.main.mobile.FormMobileAttr;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.stable.StringUtils;
import java.awt.event.ActionEvent;
/**
* Created by fanglei on 2016/11/14.
*/
@EnableMetrics
public class NewFormMobileAttrAction extends FormMobileAttrAction {
public NewFormMobileAttrAction(JForm jf) {
super(jf);
}
/**
* 执行动作
*
* @return 是否执行成功
*/
@Override
public void actionPerformed(ActionEvent e) {
final JForm jf = getEditingComponent();
if (jf == null) {
return;
}
final Form formTpl = jf.getTarget();
FormMobileAttr mobileAttr = formTpl.getFormMobileAttr();
final FormMobileAttrPane mobileAttrPane = new FormMobileAttrPane();
mobileAttrPane.populateBean(mobileAttr);
final boolean oldMobileOnly = mobileAttr.isMobileOnly();
final boolean oldAdaptive = mobileAttr.isAdaptivePropertyAutoMatch();
BasicDialog dialog = mobileAttrPane.showWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
FormMobileAttr formMobileAttr = mobileAttrPane.updateBean();
if (formMobileAttr.isMobileOnly() && jf.getTarget().getAttrMark(MobileOnlyTemplateAttrMark.XML_TAG) == null) {
// 如果是老模板,选择手机专属之后需要另存为
FILE editingFILE = jf.getEditingFILE();
if (editingFILE != null && editingFILE.exists()) {
String fileName = editingFILE.getName().substring(0, editingFILE.getName().length() - jf.suffix().length()) + "_mobile";
if (!jf.saveAsTemplate(true, fileName)) {
return;
}
}
// 放到后面。如果提前 return 了,则仍然处于未设置状态,不要添加
jf.getTarget().addAttrMark(new MobileOnlyTemplateAttrMark());
}
// 设置移动端属性并刷新界面
formTpl.setFormMobileAttr(formMobileAttr); // 会调整 body 的自适应布局,放到最后
boolean changeSize = (!oldMobileOnly && formMobileAttr.isMobileOnly()) || (oldMobileOnly && !formMobileAttr.isMobileOnly());
if (changeSize) {
((FormArea)jf.getFormDesign().getParent()).onMobileAttrModified();
}
//改变布局为自适应布局,只在移动端属性设置保存后改变一次
boolean changeLayout = !oldAdaptive && formMobileAttr.isAdaptivePropertyAutoMatch();
if (changeLayout) {
jf.getFormDesign().getSelectionModel().setSelectedCreator(jf.getFormDesign().getRootComponent());
doChangeBodyLayout();
WidgetPropertyPane.getInstance().refreshDockingView();
}
jf.fireTargetModified();
FILE editingFILE = jf.getEditingFILE();
if(editingFILE != null && editingFILE.exists()){
JForm jForm = getEditingComponent();
TemplateTool.saveForm(jForm);
if (jForm instanceof NewJForm) {
AdaptiveSwitchUtil.switch2OldUI();
}
}else {
AdaptiveSwitchUtil.switch2OldUIMode();
NewJForm mobileJForm = new NewJForm(jf.getTarget(), jf.getEditingFILE());
//设置临时的id,和新建的模板区分
mobileJForm.getTarget().setTemplateID(StringUtils.EMPTY);
TemplateTool.resetTabPaneEditingTemplate(mobileJForm);
TemplateTool.activeAndResizeTemplate(mobileJForm);
}
}
});
dialog.setVisible(true);
}
private void doChangeBodyLayout(){
FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner();
XLayoutContainer rootLayout = formDesigner.getRootComponent();
if (rootLayout.getComponentCount() == 1 && rootLayout.getXCreator(0).acceptType(XWAbsoluteBodyLayout.class)) {
rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(0);
}
((XWFitLayout)formDesigner.getRootComponent()).switch2FitBodyLayout(rootLayout);
}
}

2
designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java

@ -54,7 +54,7 @@ public interface LayoutAdapter {
* @return 是否添加成功成功返回true否则false
*/
boolean addBean(XCreator creator, int x, int y, boolean accept);
/**
* 返回该布局管理适配器的Painter为容器提供放置位置的标识
*/

3
designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java

@ -267,6 +267,9 @@ public class XChartEditor extends XBorderStyleWidgetCreator {
if (editingMouseListener.stopEditing()) {
if (this != (XCreator) designer.getRootComponent()) {
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);
if (isEditing) {
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_SETTINGS);
}
editingMouseListener.startEditing(this, isEditing ? adapter.getDesignerEditor() : null, adapter);
if (isEditing) {
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_SETTINGS);

6
designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java

@ -14,6 +14,7 @@ import com.fr.design.designer.beans.location.Direction;
import com.fr.design.designer.beans.models.SelectionModel;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
import com.fr.design.designer.properties.mobile.MobileBooKMarkUsePropertyUI;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.form.layout.FRAbsoluteLayout;
import com.fr.design.form.util.FormDesignerUtils;
import com.fr.design.form.util.XCreatorConstants;
@ -30,7 +31,6 @@ import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
import com.fr.form.ui.container.WLayout;
import com.fr.general.FRScreen;
import com.fr.general.IOUtils;
import com.fr.share.ShareConstants;
@ -111,7 +111,7 @@ public class XWAbsoluteLayout extends XLayoutContainer {
private void initPercent(WAbsoluteLayout widget) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension scrnsize = toolkit.getScreenSize();
double screenValue = FRScreen.getDesignScreenByDimension(scrnsize).getValue();
double screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(scrnsize).getValue();
if (!AssistUtils.equals(screenValue, FormArea.DEFAULT_SLIDER)) {
this.setContainerPercent(screenValue / FormArea.DEFAULT_SLIDER);
}
@ -247,7 +247,7 @@ public class XWAbsoluteLayout extends XLayoutContainer {
*/
@Override
public void updateChildBound(int minHeight) {
double prevContainerPercent = FRScreen.getDesignScreenByDimension(toData().getDesigningResolution()).getValue() / FormArea.DEFAULT_SLIDER;
double prevContainerPercent = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(toData().getDesigningResolution()).getValue() / FormArea.DEFAULT_SLIDER;
if (toData().getCompState() == 0 && !AssistUtils.equals(containerPercent, prevContainerPercent)) {
for (int i = 0; i < this.getComponentCount(); i++) {
XCreator creator = getXCreator(i);

4
designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java

@ -6,6 +6,7 @@ import com.fr.design.designer.beans.location.Direction;
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
import com.fr.design.designer.properties.mobile.BodyMobilePropertyUI;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.form.layout.FRFitLayout;
import com.fr.design.fun.WidgetPropertyUIProvider;
import com.fr.design.mainframe.FormArea;
@ -20,7 +21,6 @@ import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WLayout;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRLogger;
import com.fr.general.FRScreen;
import com.fr.stable.ArrayUtils;
import com.fr.stable.AssistUtils;
import javax.swing.JOptionPane;
@ -72,7 +72,7 @@ public class XWFitLayout extends XLayoutContainer {
private void initPercent(){
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension scrnsize = toolkit.getScreenSize();
double screenValue = FRScreen.getDesignScreenByDimension(scrnsize).getValue();
double screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(scrnsize).getValue();
if (!AssistUtils.equals(FormArea.DEFAULT_SLIDER, screenValue)) {
this.setContainerPercent(screenValue / FormArea.DEFAULT_SLIDER);
}

124
designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java

@ -0,0 +1,124 @@
package com.fr.design.fit;
import com.fr.base.ScreenResolution;
import com.fr.design.fun.ReportLengthUNITProvider;
import com.fr.design.unit.UnitConvertUtil;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRScreen;
import com.fr.stable.Constants;
import java.awt.Dimension;
/**
* Created by kerry on 2020-06-05
*/
public class DesignerUIModeConfig {
private DesignerUIMode mode = DesignerUIMode.NEW_UI_MODE;
private static class DesignerUIModeConfigHolder {
private static final DesignerUIModeConfig designerUIModeConfig = new DesignerUIModeConfig();
}
private DesignerUIModeConfig() {
}
public static DesignerUIModeConfig getInstance() {
return DesignerUIModeConfigHolder.designerUIModeConfig;
}
/**
* 判断是否是新ui模式
*
* @return boolean
*/
public boolean newUIMode() {
return ComparatorUtils.equals(DesignerUIMode.NEW_UI_MODE, mode);
}
/**
* 设置新ui模式
*/
public void setNewUIMode() {
this.mode = DesignerUIMode.NEW_UI_MODE;
}
/**
* 设置老ui模式
*/
public void setOldUIMode() {
this.mode = DesignerUIMode.OLD_UI_MODE;
}
/**
* 解析不同模式下的尺寸单位
*
* @param unitType 尺寸类型
* @return ReportLengthUNITProvider对象
*/
public ReportLengthUNITProvider parseLengthUNIT(int unitType) {
return mode.parseLengthUNIT(unitType);
}
/**
* 获取不同模式下的屏幕分辨率
*
* @return 分辨率
*/
public int getScreenResolution() {
return mode.getScreenResolution();
}
/**
* 根据屏幕尺寸获取设计时的FRScreen
*
* @param screen 屏幕尺寸
* @return FRScreen
*/
public FRScreen getDesignScreenByDimension(Dimension screen) {
return mode.getDesignScreenByDimension(screen);
}
private enum DesignerUIMode {
OLD_UI_MODE {
@Override
protected ReportLengthUNITProvider parseLengthUNIT(int unitType) {
return UnitConvertUtil.parseLengthUNIT(unitType);
}
@Override
protected FRScreen getDesignScreenByDimension(Dimension screen) {
return FRScreen.getDesignScreenByDimension(screen);
}
@Override
protected int getScreenResolution() {
return ScreenResolution.getScreenResolution();
}
},
NEW_UI_MODE {
@Override
protected ReportLengthUNITProvider parseLengthUNIT(int unitType) {
return new PXReportLengthUNIT();
}
@Override
protected FRScreen getDesignScreenByDimension(Dimension screen) {
return FRScreen.p1440;
}
@Override
protected int getScreenResolution() {
return Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION;
}
};
protected abstract ReportLengthUNITProvider parseLengthUNIT(int unitType);
protected abstract FRScreen getDesignScreenByDimension(Dimension screen);
protected abstract int getScreenResolution();
}
}

36
designer-form/src/main/java/com/fr/design/fit/FitStateCompatible.java

@ -0,0 +1,36 @@
package com.fr.design.fit;
/**
* Created by kerry on 2020-04-27
*/
public enum FitStateCompatible {
DOUBLE_FIT(2, 0),
HOR_FIT(1, 1),
NO_FIT(3, 2);
private final int newType;
private final int oldType;
FitStateCompatible(int oldType, int newType) {
this.oldType = oldType;
this.newType = newType;
}
public static int getNewTypeFromOld(int oldValue) {
for (FitStateCompatible compatible : values()) {
if (compatible.oldType == oldValue) {
return compatible.newType;
}
}
return DOUBLE_FIT.newType;
}
public static int getOldTypeFromNew(int newValue) {
for (FitStateCompatible compatible : values()) {
if (compatible.newType == newValue) {
return compatible.oldType;
}
}
return DOUBLE_FIT.oldType;
}
}

133
designer-form/src/main/java/com/fr/design/fit/JFormType.java

@ -0,0 +1,133 @@
package com.fr.design.fit;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.fit.common.AdaptiveSwitchUtil;
import com.fr.form.fit.NewFormMarkAttr;
import com.fr.form.fit.config.FormFitConfig;
import com.fr.design.fit.menupane.FormFitAttrPane;
import com.fr.design.fun.PreviewProvider;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.preview.FormAdaptivePreview;
import com.fr.design.preview.FormPreview;
import com.fr.design.report.fit.menupane.ReportFitAttrPane;
import com.fr.form.main.Form;
import com.fr.report.fit.ReportFitAttr;
public enum JFormType {
OLD_TYPE(0, new FormPreview()) {
@Override
public void switchUI() {
AdaptiveSwitchUtil.switch2OldUI();
}
@Override
public void switchUIMode() {
AdaptiveSwitchUtil.switch2OldUIMode();
}
@Override
public ReportFitAttr obtainFitAttr() {
return FormFitConfig.getInstance().getOldFitAttr();
}
@Override
public void updateFitAttr(ReportFitAttr attr) {
FormFitConfig.getInstance().setOldFitAttr(attr);
}
@Override
public BasicBeanPane obtainAttrPane(NewJForm newJForm) {
return new ReportFitAttrPane();
}
},
NEW_TYPE(1, new FormAdaptivePreview()) {
@Override
public void switchUI() {
AdaptiveSwitchUtil.switch2NewUI();
}
@Override
public void switchUIMode() {
AdaptiveSwitchUtil.switch2NewUIMode();
}
@Override
public ReportFitAttr obtainFitAttr() {
return FormFitConfig.getInstance().getNewFitAttr();
}
@Override
public void updateFitAttr(ReportFitAttr attr) {
FormFitConfig.getInstance().setNewFitAttr(attr);
}
@Override
public BasicBeanPane obtainAttrPane(NewJForm newJForm) {
return new FormFitAttrPane(newJForm);
}
};
private int type;
private boolean newType;
private PreviewProvider previewType;
JFormType(int type, PreviewProvider previewType) {
this.type = type;
this.newType = (type == 1);
this.previewType = previewType;
}
public int getType() {
return type;
}
public boolean isNewType() {
return newType;
}
public PreviewProvider getPreviewType() {
return previewType;
}
public abstract void switchUI();
public abstract void switchUIMode();
public abstract ReportFitAttr obtainFitAttr();
public abstract void updateFitAttr(ReportFitAttr attr);
public abstract BasicBeanPane obtainAttrPane(NewJForm newJForm);
/**
* @Description: 更新模板的标志位
* @param jTemplate
* @return:
* @Author: Henry.Wang
* @date: 2020/12/17 16:17
*/
public void updateJFromTemplateType(JTemplate jTemplate) {
if (jTemplate instanceof NewJForm) {
NewJForm newJForm = (NewJForm) jTemplate;
Form form = newJForm.getTarget();
NewFormMarkAttr newFormMarkAttr = form.getAttrMark(NewFormMarkAttr.XML_TAG);
if (newFormMarkAttr == null) {
newFormMarkAttr = new NewFormMarkAttr(this.getType());
form.addAttrMark(newFormMarkAttr);
}
newFormMarkAttr.setType(this.getType());
newJForm.setJFormType(this);
}
}
/**
* @Description: 更新预览方式
* @param jTemplate
* @return:
* @Author: Henry.Wang
* @date: 2020/12/17 16:17
*/
public void updatePreviewType(JTemplate jTemplate) {
jTemplate.setPreviewType(this.getPreviewType());
}
}

285
designer-form/src/main/java/com/fr/design/fit/NewJForm.java

@ -0,0 +1,285 @@
package com.fr.design.fit;
import com.fr.base.DynamicUnitList;
import com.fr.design.actions.TemplateParameterAction;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.adapters.layout.FRFitLayoutAdapter;
import com.fr.design.designer.beans.events.DesignerEditListener;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.*;
import com.fr.design.fit.common.AdaptiveSwitchUtil;
import com.fr.design.fit.common.LayoutTool;
import com.fr.form.fit.NewFormMarkAttr;
import com.fr.design.fit.common.TemplateTool;
import com.fr.design.actions.FormFitAttrAction;
import com.fr.design.actions.NewFormMobileAttrAction;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.preview.DeveloperPreview;
import com.fr.design.preview.FormAdaptivePreview;
import com.fr.design.fit.toolbar.SwitchAction;
import com.fr.design.fun.PreviewProvider;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.menu.ShortCut;
import com.fr.design.preview.FormPreview;
import com.fr.design.preview.MobilePreview;
import com.fr.design.utils.ComponentUtils;
import com.fr.file.FILE;
import com.fr.form.FormElementCaseProvider;
import com.fr.form.main.Form;
import com.fr.form.main.mobile.FormMobileAttr;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.stable.ArrayUtils;
import javax.swing.JComponent;
import java.awt.Dimension;
import java.awt.Rectangle;
/**
* Created by kerry on 2020-05-31
*/
public class NewJForm extends JForm {
private static final int FUZZY_EDGE = 10;
private static final int TITLE_HEIGHT = 36;
private JFormType jFormType;
public NewJForm() {
super();
init();
changePaneSize();
}
public NewJForm(Form form, FILE file) {
super(form, file);
if (DesignerUIModeConfig.getInstance().newUIMode()) {
init();
}
changePaneSize();
}
/**
* @Description:改变body的大小主要针对新模式下打开老模板出现截断的情况
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/9/13 23:23
*/
private void changePaneSize() {
if (mobileForm())
return;
NewFormMarkAttr newFormMarkAttr = this.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG);
if (newFormMarkAttr.isNotSetOriginSize()) {
newFormMarkAttr.setBodyHeight(LayoutTool.getBodyHeight(this));
newFormMarkAttr.setBodyWidth(LayoutTool.getBodyWidth(this));
return;
}
//这种是针对body为绝对布局时,可能出现截断的情况
if (LayoutTool.absoluteLayoutForm(this)) {
int bodyHeight = newFormMarkAttr.getBodyHeight();
int bodyWidth = newFormMarkAttr.getBodyWidth();
Rectangle rectangle = LayoutTool.getAbsoluteBodySize(this);
if (!isNewJFrom() && (rectangle.width != bodyWidth || rectangle.height != bodyHeight)) {
TemplateTool.onlyChangeAbsoluteBodySize(bodyHeight, bodyWidth, this);
} else if(isNewJFrom()){
if (rectangle.width > bodyWidth && rectangle.height > bodyHeight) {
TemplateTool.onlyChangeAbsoluteBodySize(rectangle.height, rectangle.width, this);
} else if (rectangle.width > bodyWidth) {
TemplateTool.onlyChangeAbsoluteBodySize(bodyHeight, rectangle.width, this);
} else if (rectangle.height > bodyHeight) {
TemplateTool.onlyChangeAbsoluteBodySize(rectangle.height, bodyWidth, this);
}
}
} else if (AdaptiveSwitchUtil.isSwitchJFromIng()) {
//这种是针对body中有绝对画布块,导致截断的情况
double scale = LayoutTool.getContainerPercent();
if (isNewJFrom()) {
LayoutTool.scaleAbsoluteBlockComponentsBounds(this.getFormDesign().getRootComponent(), 1 / scale);
} else {
LayoutTool.scaleAbsoluteBlockComponentsBounds(this.getFormDesign().getRootComponent(), scale);
}
}
}
public JFormType getJFormType() {
return this.jFormType;
}
public void setJFormType(JFormType jFormType) {
this.jFormType = jFormType;
}
/**
* 模板菜单
*
* @return 返回菜单
*/
@Override
public ShortCut[] shortcut4TemplateMenu() {
if (this.index == FORM_TAB) {
return ArrayUtils.addAll(new ShortCut[]{new TemplateParameterAction(this), new NewFormMobileAttrAction(this), new FormFitAttrAction(this)}, new ShortCut[0]);
} else {
return ArrayUtils.addAll(new ShortCut[]{new TemplateParameterAction(this), new NewFormMobileAttrAction(this), new FormFitAttrAction(this)}, this.getElementCaseDesign().shortcut4TemplateMenu());
}
}
private void init() {
this.getFormDesign().addDesignerEditListener(new DesignerEditListener() {
private Rectangle oldRec;
@Override
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getAffectedCreator() == null) {
return;
}
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) {
XComponent affectedCreator = evt.getAffectedCreator();
if (isElementCase((JComponent) affectedCreator)) {
processAbsorbingEffect((XWTitleLayout) affectedCreator);
}
}
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) {
XComponent affectedCreator = evt.getAffectedCreator();
oldRec = new Rectangle(affectedCreator.getBounds());
}
}
private boolean isElementCase(JComponent component) {
return component.getComponents().length > 0 && component.getComponent(0) instanceof XElementCase;
}
private void processAbsorbingEffect(XWTitleLayout xwTitleLayout) {
NewJForm.this.getFormDesign().repaint();
Dimension bound = new Dimension(xwTitleLayout.getSize());
ElementCaseEditor elementCaseEditor = (ElementCaseEditor) xwTitleLayout.toData().getBodyBoundsWidget().getWidget();
FormElementCaseProvider elementCase = elementCaseEditor.getElementCase();
if (oldRec.width != bound.width) {
processColumnAbsorbingEffect(xwTitleLayout, elementCase.getColumnWidthList_DEC(), bound);
oldRec.width = bound.width;
}
if (oldRec.height != bound.height) {
processRowAbsorbingEffect(xwTitleLayout, elementCase.getRowHeightList_DEC(), bound);
oldRec.height = bound.height;
}
NewJForm.this.getFormDesign().refreshDesignerUI();
}
private boolean hasTitle(XWTitleLayout xwTitleLayout) {
return xwTitleLayout.getComponentCount() > 1;
}
private void processColumnAbsorbingEffect(XWTitleLayout xwTitleLayout, DynamicUnitList columnUnitList, Dimension bound) {
int temp = 0;
int resolution = DesignerUIModeConfig.getInstance().getScreenResolution();;
int difference = 0;
int i = 0;
while (true) {
if (i < columnUnitList.size()) {
temp += columnUnitList.get(i++).toPixI(resolution);
} else {
//在处理吸附效果时,columnUnitList数组长度可能比实际显示的列数少,所以用默认值来补充
temp += columnUnitList.getDefaultUnit().toPixI(resolution);
}
if (bound.width - temp < 0) {
break;
}
if (bound.width - temp < FUZZY_EDGE) {
difference = bound.width - temp;
bound.width = temp;
break;
}
}
fixLayout(xwTitleLayout, bound, difference, 0);
}
private void processRowAbsorbingEffect(XWTitleLayout xwTitleLayout, DynamicUnitList rowUnitList, Dimension bound) {
int temp = hasTitle(xwTitleLayout) ? TITLE_HEIGHT : 0;
int resolution =DesignerUIModeConfig.getInstance().getScreenResolution();
int difference = 0;
int i = 0;
while (true) {
if (i < rowUnitList.size()) {
temp += rowUnitList.get(i++).toPixI(resolution);
} else {
//在处理吸附效果时,rowUnitList数组长度可能比实际显示的行数少,所以用默认值来补充
temp += rowUnitList.getDefaultUnit().toPixI(resolution);
}
if (bound.height - temp < 0) {
break;
}
if (bound.height - temp < FUZZY_EDGE) {
difference = bound.height - temp;
bound.height = temp;
break;
}
}
fixLayout(xwTitleLayout, bound, difference, 1);
}
private void fixLayout(XWTitleLayout xwTitleLayout, Dimension bound, int difference, int row) {
Rectangle backupBounds = getBound(xwTitleLayout);
xwTitleLayout.setSize(bound);
FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner();
LayoutAdapter adapter = AdapterBus.searchLayoutAdapter(formDesigner, xwTitleLayout);
if (adapter instanceof FRFitLayoutAdapter) {
FRFitLayoutAdapter layoutAdapter = (FRFitLayoutAdapter) adapter;
layoutAdapter.setEdit(true);
layoutAdapter.calculateBounds(backupBounds, xwTitleLayout.getBounds(), xwTitleLayout, row, difference);
}
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xwTitleLayout);
if (parent != null && parent.toData() != null) {
parent.toData().setBounds(xwTitleLayout.toData(), xwTitleLayout.getBounds());
}
}
});
}
public Rectangle getBound(XWTitleLayout creator) {
Rectangle bounds = new Rectangle(creator.getBounds());
if (creator.getParent() == null) {
return bounds;
}
Rectangle rec = ComponentUtils.getRelativeBounds(creator.getParent());
bounds.x += rec.x;
bounds.y += rec.y;
return bounds;
}
@Override
public PreviewProvider[] supportPreview() {
if (isNewJFrom()) {
return new PreviewProvider[]{new FormAdaptivePreview(), new DeveloperPreview(), new MobilePreview()};
}
return new PreviewProvider[]{new FormPreview(), new MobilePreview()};
}
public boolean mobileForm() {
FormMobileAttr mobileAttr = this.getTarget().getFormMobileAttr();
if (mobileAttr.isMobileOnly() && mobileAttr.isAdaptivePropertyAutoMatch()) {
return true;
}
return false;
}
private SwitchAction switchAction;
public UIButton[] createExtraButtons() {
UIButton[] extraButtons = super.createExtraButtons();
switchAction = new SwitchAction();
return ArrayUtils.addAll(extraButtons, new UIButton[]{switchAction.getToolBarButton()});
}
public boolean isNewJFrom() {
return jFormType == null || jFormType.isNewType();
}
}

27
designer-form/src/main/java/com/fr/design/fit/PX.java

@ -0,0 +1,27 @@
package com.fr.design.fit;
import com.fr.stable.Constants;
import com.fr.stable.unit.LEN_UNIT;
public class PX extends LEN_UNIT {
private static final long FU_SCALE = 36576L;
public PX(float var1) {
super(var1);
}
public boolean equals(Object var1) {
return var1 instanceof PX && super.equals(var1);
}
protected long getMoreFUScale() {
int dpi = DesignerUIModeConfig.getInstance().getScreenResolution();
return FU_SCALE / dpi;
}
public static double toPixWithResolution(double value, int resolution) {
return value * resolution / Constants.FR_PAINT_RESOLUTION;
}
}

32
designer-form/src/main/java/com/fr/design/fit/PXReportLengthUNIT.java

@ -0,0 +1,32 @@
package com.fr.design.fit;
import com.fr.design.fun.impl.AbstractReportLengthUNITProvider;
import com.fr.stable.unit.UNIT;
/**
* Created by kerry on 2020-04-09
*/
public class PXReportLengthUNIT extends AbstractReportLengthUNITProvider {
public static final short UNIT_TYPE = 4;
@Override
public String unitText() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Px");
}
@Override
public int unitType() {
return UNIT_TYPE;
}
@Override
public float unit2Value4Scale(UNIT value) {
int resolution = DesignerUIModeConfig.getInstance().getScreenResolution();
return value.toPixF(resolution);
}
@Override
public UNIT float2UNIT(float value) {
return new PX(value);
}
}

91
designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java

@ -0,0 +1,91 @@
package com.fr.design.fit.attrpane;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.designer.creator.CRPropertyDescriptor;
import com.fr.design.designer.creator.PropertyGroupPane;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XElementCase;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.widget.accessibles.AccessibleElementCaseToolBarEditor;
import com.fr.design.widget.ui.designer.component.PaddingBoundPane;
import com.fr.design.widget.ui.designer.layout.WTitleLayoutDefinePane;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.form.web.FormToolBarManager;
import com.fr.general.ComparatorUtils;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-04-09
*/
public class ElementEditorExtendDefinePane extends WTitleLayoutDefinePane<ElementCaseEditor> {
private PaddingBoundPane paddingBoundPane;
private AccessibleElementCaseToolBarEditor elementCaseToolBarEditor;
private PropertyGroupPane extraPropertyGroupPane;
private PcFitExpandablePane pcFitExpandablePane;
private static final String FIT_STATE_PC = "fitStateInPC";
public ElementEditorExtendDefinePane(XCreator xCreator) {
super(xCreator);
}
protected JPanel createCenterPane() {
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
paddingBoundPane = new PaddingBoundPane();
elementCaseToolBarEditor = new AccessibleElementCaseToolBarEditor();
Component[][] components = new Component[][]{
new Component[]{paddingBoundPane, null},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_EC_Toolbar")), elementCaseToolBarEditor},
};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1);
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0));
CRPropertyDescriptor[] extraTableEditor = removeOldFitEditor(((XElementCase) creator).getExtraTableEditor());
extraPropertyGroupPane = new PropertyGroupPane(extraTableEditor, creator);
centerPane.add(panel, BorderLayout.NORTH);
if (extraTableEditor.length > 0) {
centerPane.add(extraPropertyGroupPane, BorderLayout.CENTER);
}
pcFitExpandablePane = new PcFitExpandablePane(this);
centerPane.add(pcFitExpandablePane, BorderLayout.SOUTH);
return centerPane;
}
private CRPropertyDescriptor[] removeOldFitEditor(CRPropertyDescriptor[] extraTableEditor) {
List<CRPropertyDescriptor> list = new ArrayList<CRPropertyDescriptor>();
for (CRPropertyDescriptor crPropertyDescriptor : extraTableEditor) {
if (!ComparatorUtils.equals(FIT_STATE_PC, crPropertyDescriptor.getName())) {
list.add(crPropertyDescriptor);
}
}
return list.toArray(new CRPropertyDescriptor[list.size()]);
}
protected ElementCaseEditor updateSubBean() {
ElementCaseEditor elementCaseEditor = (ElementCaseEditor) creator.toData();
if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate"))) {
paddingBoundPane.update(elementCaseEditor);
}
elementCaseEditor.setToolBars((FormToolBarManager[]) elementCaseToolBarEditor.getValue());
ReportFitAttr fitAttr = pcFitExpandablePane.update();
elementCaseEditor.setReportFitAttr(fitAttr);
return elementCaseEditor;
}
protected void populateSubBean(ElementCaseEditor ob) {
paddingBoundPane.populate(ob);
elementCaseToolBarEditor.setValue(ob.getToolBars());
extraPropertyGroupPane.populate(ob);
pcFitExpandablePane.populate(ob.getReportFitAttr());
}
}

161
designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java

@ -0,0 +1,161 @@
package com.fr.design.fit.attrpane;
import com.fr.base.io.IOFile;
import com.fr.base.iofile.attr.WatermarkAttr;
import com.fr.design.data.DataCreatorUI;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.properties.items.FRLayoutTypeItems;
import com.fr.design.designer.properties.items.Item;
import com.fr.design.foldablepane.UIExpandablePane;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.mainframe.widget.accessibles.AccessibleBodyWatermarkEditor;
import com.fr.design.mainframe.widget.accessibles.AccessibleWLayoutBorderStyleEditor;
import com.fr.design.utils.gui.UIComponentUtils;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.design.widget.ui.designer.layout.FRAbsoluteLayoutDefinePane;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.form.ui.container.WAbsoluteBodyLayout;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WBodyLayoutType;
import com.fr.report.core.ReportUtils;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
/**
* Created by kerry on 2020-04-22
*/
public class FRAbsoluteBodyLayoutExtendDefinePane extends FRAbsoluteLayoutDefinePane {
private static final int MAX_LABEL_WIDTH = 80;
private AccessibleWLayoutBorderStyleEditor borderStyleEditor;
private AccessibleBodyWatermarkEditor watermarkEditor;
private UIComboBox layoutCombox;
private WBodyLayoutType layoutType = WBodyLayoutType.ABSOLUTE;
public FRAbsoluteBodyLayoutExtendDefinePane(XCreator xCreator) {
super(xCreator);
}
public void initComponent() {
initCenterPane();
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
borderStyleEditor = new AccessibleWLayoutBorderStyleEditor();
watermarkEditor = new AccessibleBodyWatermarkEditor();
JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane(
new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style")), borderStyleEditor},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), watermarkEditor}
}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W3, IntervalConstants.INTERVAL_L1);
JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
borderPane.add(jPanel, BorderLayout.CENTER);
UIExpandablePane advancedPane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, borderPane);
centerPane.add(advancedPane, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.NORTH);
}
private void initCenterPane(){
this.setLayout(FRGUIPaneFactory.createBorderLayout());
initUIComboBox();
JPanel thirdPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel jPanel = createThirdPane();
jPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
thirdPane.add(jPanel, BorderLayout.CENTER);
UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout"), 280, 20, thirdPane);
this.add(layoutExpandablePane, BorderLayout.CENTER);
}
public JPanel createThirdPane() {
initLayoutComboBox();
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
double p = TableLayout.PREFERRED;
double f = TableLayout.FILL;
double[] rowSize = {p};
double[] colSize = {p, f};
UILabel layoutTypeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type"));
JPanel northPane = TableLayoutHelper.createGapTableLayoutPane(
new Component[][]{
new Component[]{layoutTypeLabel, UIComponentUtils.wrapWithBorderLayoutPane(layoutCombox)}},
rowSize, colSize, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1);
jPanel.add(northPane, BorderLayout.NORTH);
return jPanel;
}
public void initLayoutComboBox() {
Item[] items = FRLayoutTypeItems.ITEMS;
DefaultComboBoxModel model = new DefaultComboBoxModel();
for (Item item : items) {
model.addElement(item);
}
layoutCombox = new UIComboBox(model);
layoutCombox.setSelectedIndex(1);
}
@Override
public String title4PopupWindow() {
return "absoluteBodyLayout";
}
public void populateSubPane(WAbsoluteLayout ob) {
layoutCombox.setSelectedIndex(1);
borderStyleEditor.setValue(ob.getBorderStyle());
watermarkEditor.setValue(ReportUtils.getWatermarkAttrFromTemplate(getCurrentIOFile()));
}
public WAbsoluteBodyLayout updateSubPane() {
WAbsoluteBodyLayout layout = (WAbsoluteBodyLayout) creator.toData();
Item item = (Item) layoutCombox.getSelectedItem();
Object value = item.getValue();
int state = 0;
if (value instanceof Integer) {
state = (Integer) value;
}
if (layoutType == WBodyLayoutType.ABSOLUTE) {
((XWFitLayout) creator.getBackupParent()).toData().resetStyle();
if (state == WBodyLayoutType.FIT.getTypeValue()) {
XWFitLayout xwFitLayout = ((XWFitLayout)creator.getBackupParent());
xwFitLayout.switch2FitBodyLayout(creator);
copyLayoutAttr(layout, xwFitLayout.toData());
}
}
layout.setBorderStyle((LayoutBorderStyle) borderStyleEditor.getValue());
updateWatermark();
return layout;
}
private void updateWatermark() {
WatermarkAttr watermark = (WatermarkAttr) watermarkEditor.getValue();
if (watermark != null) {
IOFile ioFile = getCurrentIOFile();
ioFile.addAttrMark(watermark);
}
}
private IOFile getCurrentIOFile() {
return WidgetPropertyPane.getInstance().getEditingFormDesigner().getTarget();
}
@Override
public DataCreatorUI dataUI() {
return null;
}
}

27
designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteLayoutExtendDefinePane.java

@ -0,0 +1,27 @@
package com.fr.design.fit.attrpane;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.widget.ui.designer.layout.AbstractFRLayoutDefinePane;
import com.fr.form.ui.container.WAbsoluteLayout;
/**
* Created by kerry on 2020-04-22
*/
public class FRAbsoluteLayoutExtendDefinePane extends AbstractFRLayoutDefinePane<WAbsoluteLayout> {
public FRAbsoluteLayoutExtendDefinePane(XCreator xCreator) {
super(xCreator);
this.setLayout(FRGUIPaneFactory.createBorderLayout());
}
@Override
public void populateBean(WAbsoluteLayout ob) {
}
@Override
public WAbsoluteLayout updateBean() {
WAbsoluteLayout wAbsoluteLayout = (WAbsoluteLayout) creator.toData();
return wAbsoluteLayout;
}
}

246
designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java

@ -0,0 +1,246 @@
package com.fr.design.fit.attrpane;
import com.fr.base.io.IOFile;
import com.fr.base.iofile.attr.WatermarkAttr;
import com.fr.design.data.DataCreatorUI;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteBodyLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWScaleLayout;
import com.fr.design.designer.properties.items.FRLayoutTypeItems;
import com.fr.design.designer.properties.items.Item;
import com.fr.design.foldablepane.UIExpandablePane;
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.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelectionUtils;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.mainframe.widget.accessibles.AccessibleBodyWatermarkEditor;
import com.fr.design.mainframe.widget.accessibles.AccessibleWLayoutBorderStyleEditor;
import com.fr.design.utils.gui.UIComponentUtils;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.design.widget.ui.designer.component.PaddingBoundPane;
import com.fr.design.widget.ui.designer.layout.AbstractFRLayoutDefinePane;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteBodyLayout;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WBodyLayoutType;
import com.fr.form.ui.container.WFitLayout;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.report.core.ReportUtils;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
/**
* Created by kerry on 2020-04-22
*/
public class FRFitLayoutExtendDefinePane extends AbstractFRLayoutDefinePane<WFitLayout> {
private static final int ADAPT_LABEL_MAX_WIDTH = 80;
private XWFitLayout xWFitLayout;
private WFitLayout wFitLayout;
private UIComboBox layoutComboBox;
private UISpinner componentIntervel;
private PaddingBoundPane paddingBound;
private AccessibleWLayoutBorderStyleEditor stylePane;
private AccessibleBodyWatermarkEditor watermarkEditor;
public FRFitLayoutExtendDefinePane(XCreator xCreator) {
super(xCreator);
this.xWFitLayout = (XWFitLayout) xCreator;
wFitLayout = xWFitLayout.toData();
initComponent();
}
public void initComponent() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel advancePane = createAdvancePane();
UIExpandablePane advanceExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, advancePane);
this.add(advanceExpandablePane, BorderLayout.NORTH);
UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout"), 280, 20, createLayoutPane());
this.add(layoutExpandablePane, BorderLayout.CENTER);
}
public JPanel createAdvancePane() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
stylePane = new AccessibleWLayoutBorderStyleEditor();
watermarkEditor = new AccessibleBodyWatermarkEditor();
paddingBound = new PaddingBoundPane();
JPanel jp2 = TableLayoutHelper.createGapTableLayoutPane(
new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style")), stylePane},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), watermarkEditor}
}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W3, IntervalConstants.INTERVAL_L1);
jp2.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
jPanel.add(paddingBound, BorderLayout.CENTER);
jPanel.add(jp2, BorderLayout.NORTH);
return jPanel;
}
public JPanel createLayoutPane() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
layoutComboBox = initUIComboBox(FRLayoutTypeItems.ITEMS);
componentIntervel = new UISpinner(0, Integer.MAX_VALUE, 1, 0);
JPanel componentIntervelPane = UIComponentUtils.wrapWithBorderLayoutPane(componentIntervel);
UILabel intervalLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Component_Interval"));
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = {p, p};
double[] columnSize = {p, f};
int[][] rowCount = {{1, 1}, {1, 1}};
Component[][] components = new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")), layoutComboBox},
new Component[]{intervalLabel, componentIntervelPane}
};
JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1);
centerPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0));
jPanel.add(centerPane, BorderLayout.CENTER);
return jPanel;
}
public UIComboBox initUIComboBox(Item[] items) {
DefaultComboBoxModel model = new DefaultComboBoxModel();
for (Item item : items) {
model.addElement(item);
}
return new UIComboBox(model);
}
@Override
public String title4PopupWindow() {
return "fitLayout";
}
@Override
public void populateBean(WFitLayout ob) {
FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner();
XLayoutContainer rootLayout = selectedBodyLayout(formDesigner);
if (rootLayout != formDesigner.getRootComponent()
&& formDesigner.getSelectionModel().getSelection().getSelectedCreator() == formDesigner.getRootComponent()) {
formDesigner.getSelectionModel().setSelectedCreators(
FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{selectedBodyLayout(formDesigner).toData()}));
}
paddingBound.populate(ob);
layoutComboBox.setSelectedIndex(ob.getBodyLayoutType().getTypeValue());
componentIntervel.setValue(ob.getCompInterval());
stylePane.setValue(ob.getBorderStyle());
watermarkEditor.setValue(ReportUtils.getWatermarkAttrFromTemplate(getCurrentIOFile()));
}
private XLayoutContainer selectedBodyLayout(FormDesigner formDesigner) {
XLayoutContainer rootLayout = formDesigner.getRootComponent();
if (rootLayout.getComponentCount() == 1 && rootLayout.getXCreator(0).acceptType(XWAbsoluteBodyLayout.class)) {
rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(0);
}
return rootLayout;
}
@Override
public WFitLayout updateBean() {
WFitLayout layout = (WFitLayout) creator.toData();
if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate"))) {
paddingBound.update(layout);
}
LayoutBorderStyle borderStyle = (LayoutBorderStyle) stylePane.getValue();
if (borderStyle != null) {
layout.setBorderStyle(borderStyle);
}
updateWatermark();
Item item = (Item) layoutComboBox.getSelectedItem();
Object value = item.getValue();
int state = 0;
if (value instanceof Integer) {
state = (Integer) value;
}
//todo 验证下
layout.setLayoutType(WBodyLayoutType.parse(state));
try {
if (state == WBodyLayoutType.ABSOLUTE.getTypeValue()) {
WAbsoluteBodyLayout wAbsoluteBodyLayout = new WAbsoluteBodyLayout("body");
wAbsoluteBodyLayout.setCompState(WAbsoluteLayout.STATE_FIXED);
Component[] components = xWFitLayout.getComponents();
xWFitLayout.removeAll();
layout.resetStyle();
XWAbsoluteBodyLayout xwAbsoluteBodyLayout = xWFitLayout.getBackupParent() == null ? new XWAbsoluteBodyLayout(wAbsoluteBodyLayout, new Dimension(0, 0)) : (XWAbsoluteBodyLayout) xWFitLayout.getBackupParent();
xWFitLayout.getLayoutAdapter().addBean(xwAbsoluteBodyLayout, 0, 0);
for (Component component : components) {
XCreator xCreator = (XCreator) component;
//部分控件被ScaleLayout包裹着,绝对布局里面要放出来
if (xCreator.acceptType(XWScaleLayout.class)) {
if (xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator()) {
component = xCreator.getComponent(0);
component.setBounds(xCreator.getBounds());
}
}
xwAbsoluteBodyLayout.add(component);
}
copyLayoutAttr(wFitLayout, wAbsoluteBodyLayout);
xWFitLayout.setBackupParent(xwAbsoluteBodyLayout);
FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner();
formDesigner.getSelectionModel().setSelectedCreators(
FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{wAbsoluteBodyLayout}));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
int intervelValue = (int) componentIntervel.getValue();
if (xWFitLayout.canAddInterval(intervelValue)) {
// 设置完间隔后,要同步处理界面组件,容器刷新后显示出对应效果
setLayoutGap(intervelValue);
}
return layout;
}
private void updateWatermark() {
WatermarkAttr watermark = (WatermarkAttr) watermarkEditor.getValue();
if (watermark != null) {
IOFile ioFile = getCurrentIOFile();
ioFile.addAttrMark(watermark);
}
}
private IOFile getCurrentIOFile() {
return WidgetPropertyPane.getInstance().getEditingFormDesigner().getTarget();
}
private void setLayoutGap(int value) {
int interval = wFitLayout.getCompInterval();
if (value != interval) {
xWFitLayout.moveContainerMargin();
xWFitLayout.moveCompInterval(xWFitLayout.getAcualInterval());
wFitLayout.setCompInterval(value);
xWFitLayout.addCompInterval(xWFitLayout.getAcualInterval());
}
}
@Override
public DataCreatorUI dataUI() {
return null;
}
}

107
designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java

@ -0,0 +1,107 @@
package com.fr.design.fit.attrpane;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.fit.FitStateCompatible;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.widget.DataModify;
import com.fr.report.fit.FitAttrState;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* Created by kerry on 2020-04-22
*/
public class PcFitExpandablePane extends JPanel {
UIComboBox comboBox = new UIComboBox(
new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Double_Fit"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Hor_Fit"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit")});
UILabel tipLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit_Tip"));
public PcFitExpandablePane(DataModify attrPane) {
init(attrPane);
}
public void init(final DataModify attrPane) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel pcFitPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
final JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
borderPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
tipLabel.setForeground(Color.gray);
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
tipLabel.setText(ScaleTipType.getScaleTip(comboBox.getSelectedIndex()).getTip());
}
});
Component[][] components = new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Content_Display_Type")), comboBox},
new Component[]{tipLabel, null},
};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_W0);
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0));
borderPane.add(panel, BorderLayout.CENTER);
borderPane.add(tipLabel, BorderLayout.SOUTH);
pcFitPane.add(borderPane, BorderLayout.CENTER);
this.add(pcFitPane, BorderLayout.CENTER);
}
public ReportFitAttr update() {
ReportFitAttr fitAttr = getReportFitAttr();
fitAttr.setFitStateInPC(FitStateCompatible.getOldTypeFromNew(comboBox.getSelectedIndex()));
return fitAttr;
}
public void populate(ReportFitAttr fitAttr) {
if (fitAttr == null) {
fitAttr = getReportFitAttr();
}
int selectIndex = FitStateCompatible.getNewTypeFromOld(fitAttr.fitStateInPC());
comboBox.setSelectedIndex(selectIndex);
tipLabel.setText(ScaleTipType.getScaleTip(selectIndex).getTip());
}
private ReportFitAttr getReportFitAttr() {
ReportFitAttr fitAttr = new ReportFitAttr();
fitAttr.setFitStateInPC(FitAttrState.NOT_FIT.getState());
return fitAttr;
}
private enum ScaleTipType {
EC_DOUBLE_FIT(0, com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Double_Fit_Tip")),
EC_HOR_FIT(1, com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Hor_Fit_Tip")),
EC_NO_FIT(2, com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit_Tip"));
private int index;
private String tip;
ScaleTipType(int index, String tip) {
this.index = index;
this.tip = tip;
}
public String getTip() {
return tip;
}
public static ScaleTipType getScaleTip(int selectIndex) {
for (ScaleTipType tipType : values()) {
if (selectIndex == tipType.index) {
return tipType;
}
}
return EC_NO_FIT;
}
}
}

303
designer-form/src/main/java/com/fr/design/fit/attrpane/RootDesignExtendDefinePane.java

@ -0,0 +1,303 @@
package com.fr.design.fit.attrpane;
import com.fr.base.BaseUtils;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.data.DataCreatorUI;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.designer.creator.CRPropertyDescriptor;
import com.fr.design.designer.creator.PropertyGroupPane;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.properties.PropertyTab;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.fit.common.TemplateTool;
import com.fr.design.foldablepane.UIExpandablePane;
import com.fr.design.fun.ParameterExpandablePaneUIProvider;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.icheckbox.UICheckBox;
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.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.widget.accessibles.AccessibleBackgroundEditor;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.design.utils.gui.UIComponentUtils;
import com.fr.design.widget.ui.designer.AbstractDataModify;
import com.fr.design.widget.ui.designer.component.UIBoundSpinner;
import com.fr.form.ui.container.WParameterLayout;
import com.fr.general.Background;
import com.fr.report.stable.FormConstants;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Rectangle;
import java.util.Set;
public class RootDesignExtendDefinePane extends AbstractDataModify<WParameterLayout> {
private XWParameterLayout root;
private UISpinner designerWidth;
private UISpinner paraHeight;
private UICheckBox displayReport;
private UICheckBox useParamsTemplate;
private AccessibleBackgroundEditor background;
private UIButtonGroup hAlignmentPane;
private UITextField labelNameTextField;
//是否是新设计模式下决策报表
private boolean newForm;
private PropertyGroupPane extraPropertyGroupPane;
public RootDesignExtendDefinePane(XCreator xCreator) {
super(xCreator);
newForm = TemplateTool.getCurrentEditingNewJForm() != null && DesignerUIModeConfig.getInstance().newUIMode();
this.root = (XWParameterLayout) xCreator;
initComponent();
}
public void initComponent() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
if (newForm) {
paraHeight = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, 0);
} else {
designerWidth = new UIBoundSpinner(1, Integer.MAX_VALUE, 1);
}
JPanel advancePane = createAdvancePane();
UIExpandablePane advanceExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, advancePane);
this.add(advanceExpandablePane, BorderLayout.NORTH);
JPanel layoutPane = createBoundsPane();
UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Size"), 280, 20, layoutPane);
this.add(layoutExpandablePane, BorderLayout.CENTER);
this.addExtraUIExpandablePaneFromPlugin();
}
private void addExtraUIExpandablePaneFromPlugin() {
Set<ParameterExpandablePaneUIProvider> pluginCreators = ExtraDesignClassManager.getInstance().getArray(ParameterExpandablePaneUIProvider.XML_TAG);
JPanel panel = FRGUIPaneFactory.createYBoxEmptyBorderPane();
for (ParameterExpandablePaneUIProvider provider : pluginCreators) {
UIExpandablePane uiExpandablePane = provider.createUIExpandablePane();
PropertyTab propertyTab = provider.addToWhichPropertyTab();
if (uiExpandablePane != null && propertyTab == PropertyTab.ATTR) {
panel.add(uiExpandablePane);
}
}
this.add(panel, BorderLayout.SOUTH);
}
public JPanel createBoundsPane() {
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = {p};
double[] columnSize = {p, f};
int[][] rowCount = {{1, 1}};
Component[] component = newForm ? new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Design_Height")), paraHeight} :
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Desin_Width")), designerWidth};
Component[][] components = new Component[][]{component};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1);
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
jPanel.add(panel);
return jPanel;
}
public JPanel createAdvancePane() {
if (newForm) {
return getNewFormAdvancePane();
} else {
return getTemplateAdvancePane();
}
}
/**
* @Description: 获取的非新决策报表AdvancePane
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/11/05 15:36
*/
private JPanel getTemplateAdvancePane() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
labelNameTextField = new UITextField();
displayReport = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Display_Nothing_Before_Query"));
UIComponentUtils.setLineWrap(displayReport);
useParamsTemplate = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Use_Params_Template"));
background = new AccessibleBackgroundEditor();
Icon[] hAlignmentIconArray = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"),
BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"),
BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png"),};
Integer[] hAlignment = new Integer[]{FormConstants.LEFTPOSITION, FormConstants.CENTERPOSITION, FormConstants.RIGHTPOSITION};
hAlignmentPane = new UIButtonGroup<Integer>(hAlignmentIconArray, hAlignment);
hAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left")
, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right")});
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = {p, p, p, p, p};
double[] columnSize = {p, f};
int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}};
Component[][] components = new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_Background")), background},
new Component[]{displayReport, null},
new Component[]{useParamsTemplate, null},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Display_Position")), hAlignmentPane}
};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1);
panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0));
CRPropertyDescriptor[] extraTableEditor = new CRPropertyDescriptor[0];
extraTableEditor = root.getExtraTableEditor();
extraPropertyGroupPane = new PropertyGroupPane(extraTableEditor, root);
jPanel.add(panel, BorderLayout.NORTH);
jPanel.add(extraPropertyGroupPane, BorderLayout.CENTER);
return jPanel;
}
/**
* @Description: 获取新决策报表的AdvancePane
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/11/05 15:36
*/
private JPanel getNewFormAdvancePane() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
labelNameTextField = new UITextField();
displayReport = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Display_Nothing_Before_Query"));
UIComponentUtils.setLineWrap(displayReport);
useParamsTemplate = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Use_Params_Template"));
background = new AccessibleBackgroundEditor();
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = {p, p, p, p};
double[] columnSize = {p, f};
int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}};
Component[][] components = new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_Background")), background},
new Component[]{displayReport, null},
new Component[]{useParamsTemplate, null}
};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1);
panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0));
jPanel.add(panel, BorderLayout.NORTH);
return jPanel;
}
@Override
public String title4PopupWindow() {
return "parameter";
}
@Override
public void populateBean(WParameterLayout ob) {
labelNameTextField.setText(ob.getLabelName());
background.setValue(ob.getBackground());
displayReport.setSelected(ob.isDelayDisplayContent());
useParamsTemplate.setSelected(ob.isUseParamsTemplate());
if (newForm) {
FormDesigner designer = TemplateTool.getCurrentEditingNewJForm().getFormDesign();
paraHeight.setValue(designer.getParaHeight());
} else {
designerWidth.setValue(ob.getDesignWidth());
hAlignmentPane.setSelectedItem(ob.getPosition());
if (extraPropertyGroupPane != null) {
extraPropertyGroupPane.populate(ob);
}
}
}
@Override
public WParameterLayout updateBean() {
if (newForm) {
return updateNewFormBean();
} else {
return updateTemplateBean();
}
}
/**
* @Description: 更新非新决策报表的bean
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/11/05 15:36
*/
private WParameterLayout updateTemplateBean() {
WParameterLayout wParameterLayout = (WParameterLayout) creator.toData();
wParameterLayout.setLabelName(labelNameTextField.getText());
if (isCompsOutOfDesignerWidth((int) designerWidth.getValue())) {
designerWidth.setValue(wParameterLayout.getDesignWidth());
} else {
wParameterLayout.setDesignWidth((int) designerWidth.getValue());
}
wParameterLayout.setDelayDisplayContent(displayReport.isSelected());
wParameterLayout.setUseParamsTemplate(useParamsTemplate.isSelected());
JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected());
wParameterLayout.setBackground((Background) background.getValue());
wParameterLayout.setPosition((Integer) hAlignmentPane.getSelectedItem());
return wParameterLayout;
}
/**
* @Description: 更新新决策报表的bean
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/11/05 15:36
*/
private WParameterLayout updateNewFormBean() {
WParameterLayout wParameterLayout = (WParameterLayout) creator.toData();
wParameterLayout.setLabelName(labelNameTextField.getText());
wParameterLayout.setDelayDisplayContent(displayReport.isSelected());
wParameterLayout.setUseParamsTemplate(useParamsTemplate.isSelected());
JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected());
wParameterLayout.setBackground((Background) background.getValue());
//设置参数模板面板的高度
int height = (int) paraHeight.getTextField().getValue();
FormDesigner designer = TemplateTool.getCurrentEditingNewJForm().getFormDesign();
FormSelection selection = designer.getSelectionModel().getSelection();
XCreator creator = designer.getParaComponent();
Rectangle rectangle = creator.getBounds();
Rectangle newRectangle = new Rectangle(rectangle.x, rectangle.y, rectangle.width, height);
creator.setBounds(newRectangle);
if (paraHeight.getValue() != newRectangle.height)
paraHeight.setValue(newRectangle.height);
designer.setParaHeight(newRectangle.height);
designer.getArea().doLayout();
LayoutUtils.layoutContainer(creator);
selection.fixCreator(designer);
designer.repaint();
return wParameterLayout;
}
private boolean isCompsOutOfDesignerWidth(int designerWidth) {
for (int i = 0; i < root.getComponentCount(); i++) {
Component comp = root.getComponent(i);
if (comp.getX() + comp.getWidth() > designerWidth) {
return true;
}
}
return false;
}
@Override
public DataCreatorUI dataUI() {
return null;
}
}

225
designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java

@ -0,0 +1,225 @@
package com.fr.design.fit.common;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.fit.NewJForm;
import com.fr.design.fit.attrpane.ElementEditorExtendDefinePane;
import com.fr.design.fit.attrpane.FRAbsoluteBodyLayoutExtendDefinePane;
import com.fr.design.fit.attrpane.FRAbsoluteLayoutExtendDefinePane;
import com.fr.design.fit.attrpane.FRFitLayoutExtendDefinePane;
import com.fr.design.fit.attrpane.RootDesignExtendDefinePane;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.JTemplateFactory;
import com.fr.design.parameter.RootDesignDefinePane;
import com.fr.design.preview.FormAdaptivePreview;
import com.fr.design.preview.FormPreview;
import com.fr.design.widget.Appearance;
import com.fr.design.widget.FormWidgetDefinePaneFactoryBase;
import com.fr.design.widget.ui.designer.layout.ElementEditorDefinePane;
import com.fr.design.widget.ui.designer.layout.FRAbsoluteBodyLayoutDefinePane;
import com.fr.design.widget.ui.designer.layout.FRAbsoluteLayoutDefinePane;
import com.fr.design.widget.ui.designer.layout.FRFitLayoutDefinePane;
import com.fr.file.FILE;
import com.fr.file.MemFILE;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteBodyLayout;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WParameterLayout;
import com.fr.form.ui.widget.CRBoundsWidget;
import com.fr.log.FineLoggerFactory;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.SwingUtilities;
/**
* Created by kerry on 2020-06-02
*/
public class AdaptiveSwitchUtil {
private static int switchJFromIng = 0;
private AdaptiveSwitchUtil() {
}
public static void switch2NewUI() {
switch2NewUIMode();
reload();
}
public static void switch2NewUIMode() {
DesignerUIModeConfig.getInstance().setNewUIMode();
FormWidgetDefinePaneFactoryBase.registerDefinePane(ElementCaseEditor.class,
new Appearance(ElementEditorExtendDefinePane.class, "elementCaseEditor"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WFitLayout.class,
new Appearance(FRFitLayoutExtendDefinePane.class, "wFitLayout"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteBodyLayout.class,
new Appearance(FRAbsoluteBodyLayoutExtendDefinePane.class, "wAbsoluteBodyLayout"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteLayout.class,
new Appearance(FRAbsoluteLayoutExtendDefinePane.class, "wAbsoluteLayout"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WParameterLayout.class,
new Appearance(RootDesignExtendDefinePane.class, "wParameterLayout"));
}
public static void switch2OldUI() {
switch2OldUIMode();
reload();
}
public static void switch2OldUIMode() {
DesignerUIModeConfig.getInstance().setOldUIMode();
FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteLayout.class,
new Appearance(FRAbsoluteLayoutDefinePane.class, "wAbsoluteLayout"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(ElementCaseEditor.class,
new Appearance(ElementEditorDefinePane.class, "elementCaseEditor"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteBodyLayout.class,
new Appearance(FRAbsoluteBodyLayoutDefinePane.class, "wAbsoluteBodyLayout"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WFitLayout.class,
new Appearance(FRFitLayoutDefinePane.class, "wFitLayout"));
FormWidgetDefinePaneFactoryBase.registerDefinePane(WParameterLayout.class,
new Appearance(RootDesignDefinePane.class, "wParameterLayout"));
}
public static void reload() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
synchronized (AdaptiveSwitchUtil.class) {
try {
if (DesignerContext.getDesignerFrame() == null) {
return;
}
JTemplate<?, ?> old = TemplateTool.getCurrentEditingTemplate();
if (old == null || !(old instanceof JForm)) {
return;
}
JTemplate<?, ?> template = createNewJTemplate(old);
if (template != null) {
DesignTableDataManager.closeTemplate(old);
TemplateTool.resetTabPaneEditingTemplate(template);
TemplateTool.activeAndResizeTemplate(template);
setPreviewType();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
} finally {
switchJFromIng = 0;
}
}
}
});
}
/**
* @Description: 设置预览方式
* @return: 新创建的模板
* @Author: Henry.Wang
* @date: 2020/10/13 14:08
*/
private static void setPreviewType() {
JTemplate jTemplate = TemplateTool.getCurrentEditingTemplate();
if (jTemplate != null) {
if (DesignerUIModeConfig.getInstance().newUIMode()) {
jTemplate.setPreviewType(new FormAdaptivePreview());
} else {
jTemplate.setPreviewType(new FormPreview());
}
}
}
/**
* @Description: 创建模板
* @param old 以前的模板
* @return: 新创建的模板
* @Author: Henry.Wang
* @date: 2020/9/6 14:08
*/
public static JTemplate<?, ?> createNewJTemplate(JTemplate<?, ?> old) {
JTemplate<?, ?> template;
template = createNewJTemplateInternal(old);
if (template instanceof NewJForm) {
NewJForm jForm = ((NewJForm) template);
//如果是从旧的设计模板转化为新的设计模式,并且不是全局配置的模板。则更新新模板的Pc端自适应属性
if (DesignerUIModeConfig.getInstance().newUIMode() && jForm.getTarget().getReportFitAttr() != null && isSwitchJFromIng()) {
jForm.getTarget().setReportFitAttr(shiftReportFitAttr(old, jForm.getTarget().getReportFitAttr().isFitFont()));
}
TemplateTool.saveForm(jForm);
}
return template;
}
/**
* @Description: 创建模板核心方法
* @param old 以前的方法
* @return: 新创建的模板
* @Author: Henry.Wang
* @date: 2020/9/6 14:09
*/
private static JTemplate<?, ?> createNewJTemplateInternal(JTemplate<?, ?> old) {
FILE file = old.getEditingFILE();
if ((file instanceof MemFILE) || !old.isSaved()) {
if (old instanceof NewJForm) {
TemplateTool.resetAbsoluteBodySize((NewJForm) old);
}
TemplateTool.saveForm(old);
}
return JTemplateFactory.createJTemplate(old.getEditingFILE());
}
/**
* @Description: 老模板切换到新模板的属性配置转换
* 1绝对布局-适应区域--双向自适应
* 2自适应布局-双向自适应--双向自适应
* 3自适应布局-横向自适应--横向自适应
* 4绝对布局-固定大小--不自适应
*
* @param old
* @param fitFont 字体是否自适应
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:01
*/
private static ReportFitAttr shiftReportFitAttr(JTemplate old, boolean fitFont) {
if (old instanceof JForm && DesignerUIModeConfig.getInstance().newUIMode()) {
JForm jForm = (JForm) old;
try {
int layoutType = LayoutTool.getFormLayoutType(jForm);
int compState = -1;
//自适应布局
if (layoutType == 0) {
compState = ((WFitLayout) jForm.getFormDesign().getRootComponent().toData()).getCompState();
if (compState == WFitLayout.STATE_FULL) {
return new ReportFitAttr(2, fitFont);
} else if (compState == WFitLayout.STATE_ORIGIN) {
return new ReportFitAttr(1, fitFont);
}
} else if (layoutType == 1) {//绝对布局
Widget widget = ((CRBoundsWidget) jForm.getFormDesign().getRootComponent().toData().getWidget(0)).getWidget();
if (widget instanceof WAbsoluteLayout) {
compState = ((WAbsoluteLayout) widget).getCompState();
}
if (compState == WAbsoluteLayout.STATE_FIT) {
return new ReportFitAttr(2, fitFont);
} else if (compState == WAbsoluteLayout.STATE_FIXED) {
return new ReportFitAttr(3, fitFont);
}
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
return null;
}
public static void setSwitchJFromIng(int switchJFromIng) {
AdaptiveSwitchUtil.switchJFromIng = switchJFromIng;
}
public static boolean isSwitchJFromIng() {
return switchJFromIng == 1;
}
}

1266
designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java

File diff suppressed because it is too large Load Diff

45
designer-form/src/main/java/com/fr/design/fit/common/FormDesignerUtil.java

@ -0,0 +1,45 @@
package com.fr.design.fit.common;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XElementCase;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.form.FormElementCaseProvider;
import com.fr.form.ui.ElementCaseEditor;
import java.util.Iterator;
import java.util.List;
/**
* Created by kerry on 2020-06-12
*/
public class FormDesignerUtil {
private FormDesignerUtil(){
}
public static XElementCase getXelementCase(XLayoutContainer rootContainer, FormElementCaseProvider elementCaseProvider) {
for (int i = 0; i < rootContainer.getComponentCount(); i++) {
XCreator creator = rootContainer.getXCreator(i);
if (creator instanceof XElementCase && elementCaseProvider == ((ElementCaseEditor) creator.toData()).getElementCase()) {
return (XElementCase) creator;
}
if (creator instanceof XLayoutContainer) {
XElementCase temp = getXelementCase((XLayoutContainer) creator, elementCaseProvider);
if (temp != null) {
return temp;
}
}
}
return null;
}
public static void removeDeletedEC(List currentECList, List waitToProcessECList) {
Iterator iterator = waitToProcessECList.iterator();
while (iterator.hasNext()) {
Object editor = iterator.next();
if (!currentECList.contains(editor)) {
iterator.remove();
}
}
}
}

177
designer-form/src/main/java/com/fr/design/fit/common/LayoutTool.java

@ -0,0 +1,177 @@
package com.fr.design.fit.common;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteBodyLayout;
import com.fr.design.designer.creator.XWAbsoluteLayout;
import com.fr.design.designer.creator.cardlayout.XWCardLayout;
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
import com.fr.design.fit.NewJForm;
import com.fr.design.mainframe.FormArea;
import com.fr.design.mainframe.JForm;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.ui.container.WAbsoluteBodyLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WLayout;
import com.fr.form.ui.widget.CRBoundsWidget;
import com.fr.general.FRScreen;
import com.fr.log.FineLoggerFactory;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Toolkit;
/**
* @description:布局工具类
* @author: Henry.Wang
* @create: 2020/09/03 14:18
*/
public class LayoutTool {
/**
* @Description: 获取布局类型
* @param jForm
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:31
*/
public static int getFormLayoutType(JForm jForm) {
JForm tempJForm = jForm;
if (tempJForm == null)
tempJForm = TemplateTool.getCurrentEditingNewJForm();
if (tempJForm == null || tempJForm.getFormDesign().getRootComponent() == null)
return -1;
return ((WFitLayout) tempJForm.getFormDesign().getRootComponent().toData()).getBodyLayoutType().getTypeValue();
}
/**
* @Description: 是否为绝对布局
* @param jForm
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:31
*/
public static boolean absoluteLayoutForm(NewJForm jForm) {
if (getFormLayoutType(jForm) == 1)
return true;
return false;
}
/**
* @Description: 如果为绝对布局则获取XWAbsoluteBodyLayout否则返回null
* @param jForm
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:26
*/
public static XWAbsoluteBodyLayout getXWAbsoluteBodyLayout(NewJForm jForm) {
NewJForm tempJForm = jForm;
if (tempJForm == null)
tempJForm = TemplateTool.getCurrentEditingNewJForm();
if (tempJForm != null) {
if (absoluteLayoutForm(tempJForm)) {
XLayoutContainer xLayoutContainer = tempJForm.getFormDesign().getRootComponent();
if (xLayoutContainer != null && xLayoutContainer.getComponentCount() > 0) {
Component component = xLayoutContainer.getComponent(0);
if (component instanceof XWAbsoluteBodyLayout) {
return (XWAbsoluteBodyLayout) component;
}
}
}
}
return null;
}
/**
* @Description: 通过子组件的位置获取绝对布局body的尺寸为什么不直接调用getRootComponent().toData().getContentHeight()因为在截断的情况下就不不一致了
* @param newJForm
* @return:
* @Author: Henry.Wang
* @date: 2020/9/11 15:24
*/
public static Rectangle getAbsoluteBodySize(NewJForm newJForm) {
int width = 0;
int height = 0;
XWAbsoluteBodyLayout xwAbsoluteBodyLayout = LayoutTool.getXWAbsoluteBodyLayout(newJForm);
if (xwAbsoluteBodyLayout != null) {
WAbsoluteBodyLayout wAbsoluteBodyLayout = xwAbsoluteBodyLayout.toData();
if (wAbsoluteBodyLayout.getWidgetCount() > 0) {
for (int i = 0; i < wAbsoluteBodyLayout.getWidgetCount(); i++) {
Rectangle rectangle = ((CRBoundsWidget) wAbsoluteBodyLayout.getWidget(i)).getBounds();
if (rectangle.x + rectangle.width > width)
width = rectangle.x + rectangle.width;
if (rectangle.y + rectangle.height > height)
height = rectangle.y + rectangle.height;
}
}
}
return new Rectangle(0, 0, width, height);
}
public static int getBodyHeight(NewJForm newJForm) {
return newJForm.getFormDesign().getRootComponent().toData().getContentHeight();
}
public static int getBodyWidth(NewJForm newJForm) {
return newJForm.getFormDesign().getRootComponent().toData().getContentWidth();
}
/**
* @Description: 对绝对画布块里的组件进行缩放
* @param xCreator
* @param scale 缩放比例
* @return:
* @Author: Henry.Wang
* @date: 2020/10/26 20:39
*/
public static void scaleAbsoluteBlockComponentsBounds(XCreator xCreator, Double scale) {
try {
Component[] components = xCreator.getComponents();
for (Component component : components) {
if (component instanceof XWCardMainBorderLayout) {
XWCardLayout xwCardLayout = ((XWCardMainBorderLayout)component).getCardPart();
for (Component tabComponent : xwCardLayout.getComponents()) {
scaleAbsoluteBlockComponentsBounds((XCreator) tabComponent, scale);
scaleAbsoluteBlockComponentsBoundsInternal((XCreator) tabComponent, scale);
}
} else if (component instanceof XWAbsoluteLayout) {
scaleAbsoluteBlockComponentsBounds((XCreator) component, scale);
scaleAbsoluteBlockComponentsBoundsInternal((XCreator) component, scale);
}
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
}
public static void scaleAbsoluteBlockComponentsBoundsInternal(XCreator parentXCreator, Double scale) {
if (parentXCreator instanceof XWAbsoluteLayout) {
XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) parentXCreator;
Component[] absoluteComponents = xwAbsoluteLayout.getComponents();
for (Component absoluteComponent : absoluteComponents) {
XCreator xCreator = (XCreator) absoluteComponent;
Rectangle bounds = new Rectangle(absoluteComponent.getBounds());
Rectangle newBounds = new Rectangle((int) (bounds.x * scale), (int) (bounds.y * scale), (int) (bounds.width * scale), (int) (bounds.height * scale));
WLayout wAbsoluteLayout = xwAbsoluteLayout.toData();
wAbsoluteLayout.setBounds(xCreator.toData(), newBounds);
xCreator.setBounds(newBounds);
LayoutUtils.layoutContainer(xCreator);
}
}
}
/**
* @Description: 获取老预览时的缩放比例
* @return:
* @Author: Henry.Wang
* @date: 2020/10/26 20:39
*/
public static double getContainerPercent(){
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
double screenValue = FRScreen.getFRScreenByDimension(screen).getValue();
return screenValue / FormArea.DEFAULT_SLIDER;
}
}

2030
designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java

File diff suppressed because it is too large Load Diff

835
designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java

@ -0,0 +1,835 @@
/*
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
*/
package com.fr.design.fit.common;
import com.fr.base.AutoChangeLineAndDrawManager;
import com.fr.base.BaseFormula;
import com.fr.base.BaseUtils;
import com.fr.base.GraphHelper;
import com.fr.base.ImageProvider;
import com.fr.base.Painter;
import com.fr.base.Style;
import com.fr.base.Utils;
import com.fr.base.background.ColorBackground;
import com.fr.base.chart.BaseChartCollection;
import com.fr.base.chart.result.WebChartIDInfo;
import com.fr.code.BarcodeImpl;
import com.fr.code.bar.BarcodeException;
import com.fr.code.bar.core.BarCodeUtils;
import com.fr.code.bar.core.BarcodeAttr;
import com.fr.data.DataUtils;
import com.fr.data.PresentationType;
import com.fr.data.condition.ListCondition;
import com.fr.file.ResultChangeWhenExport;
import com.fr.form.ui.Widget;
import com.fr.general.Background;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRFont;
import com.fr.general.ImageWithSuffix;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.ExtraClassManager;
import com.fr.report.cell.CellElement;
import com.fr.report.cell.FloatElement;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.cell.cellattr.CellExpandAttr;
import com.fr.report.cell.cellattr.CellGUIAttr;
import com.fr.report.cell.cellattr.core.CellUtils;
import com.fr.report.cell.cellattr.core.ResultSubReport;
import com.fr.report.cell.cellattr.core.group.DSColumn;
import com.fr.report.core.Html2ImageUtils;
import com.fr.report.core.ReportUtils;
import com.fr.script.Calculator;
import com.fr.stable.Constants;
import com.fr.stable.CoreConstants;
import com.fr.stable.StringUtils;
import com.fr.stable.bridge.ObjectHolder;
import com.fr.stable.fun.AutoChangeLineAndDrawProcess;
import com.fr.stable.fun.FontProcessor;
import com.fr.stable.html.Tag;
import com.fr.stable.unit.FU;
import com.fr.stable.unit.PT;
import com.fr.stable.unit.UNIT;
import com.fr.stable.web.Repository;
import javax.swing.ImageIcon;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.font.TextAttribute;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
/**
* The util for paint.
*/
public class PaintUtils {
// Add by Denny
public static final int CELL_MARK_SIZE = 6;
public static final Color CELL_HIGHT_LIGHT_MARK_COLOR = new Color(255, 0, 55);
public static final Color CELL_PRESENT_MARK_COLOR = new Color(0, 255, 200);
public static final Color CELL_PAGINATION_MARK_COLOR = new Color(55, 255, 0);
public static final Color CELL_RESULT_MARK_COLOR = new Color(200, 0, 255);
public static final Color CELL_CONDITION_FILTER_MARK_COLOR = new Color(255, 200, 0);
public static final Color CELL_PARAMETER_FILTER_MARK_CONLR = new Color(0, 55, 255);
public static final Color CELL_DIRECTION_MARK_COLOR = Color.gray;
private static final int UNIT_SIZE = 4;
//原值是15,矩形线条会缺失,加1px绘制没问题。这地方有水印,但是貌似不是水印影响,未找到线条被挡住的原因
private static final int WIDGET_WIDTH = 16;
private static final int WIDGET_HEIGHT = 16;
// Suppresses default constructor, ensuring non-instantiability.
private PaintUtils() {
}
// font attributes map cache
private static Hashtable fontAttributeMapCache = new Hashtable();
/*
* 用于在Grid里面画CellElement的Content + Background
*
* 不画Border,是因为在Grid里面先画所有单元格的Content + Background,再画所有单元格的Border(peter认为这可以提高速度)
*/
public static void paintGridCellContent(Graphics2D g2d, TemplateCellElement cell, int width, int height, int resolution) {
int cell_mark_size = CELL_MARK_SIZE;
// denny_Grid
// 左上角: 条件高亮, 形态
int leftUpCount = 0;
int rightUpCount = 0;
int leftDownCount = 0;
GraphHelper.applyRenderingHints(g2d);
if (paintHighlightGroupMarkWhenExsit(g2d, cell, leftUpCount)) {
leftUpCount++;
}
if (paintPresentMarkWhenExsit(g2d, cell, leftUpCount)) {
leftUpCount++;
}
if (paintPaginationMarkWhenExsit(g2d, cell, width, rightUpCount)) {
rightUpCount++;
}
paintWidgetMarkWhenExsit(g2d, cell, width, height);
paintExpandMarkWhenExsit(g2d, cell);
Object value = cell.getValue();
if (value == null) {// 先判断是否是空.
return;
}
if (paintResultMarkWhenExsit(g2d, value, width, rightUpCount)) {
rightUpCount++;
}
if (paintDSColumnParametermarkWhenExsit(g2d, value, height, leftDownCount)) {
leftDownCount++;
}
if (paintDSColumnConditionmarkWhenExsit(g2d, value, height, leftDownCount)) {
leftDownCount++;
}
// 画value,但因为是在Grid里面画,所以画Formula.content
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getContent();
}
if (value instanceof ImageWithSuffix) {
value = ((ImageWithSuffix) value).getFineImage();
}
if (value instanceof BaseChartCollection) {
value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height);
}
// Carl:当是子报表时,在格子里画一个子报表的图
/*
* alex:TODO 此处在Grid里面画ChartCollection和SubReport都只画一个图表,这种做法,很不雅
*/
if (value instanceof ResultSubReport) {
value = BaseUtils.readImage("/com/fr/base/images/report/painter/subReport.png");
GraphHelper.paintImage(g2d, width, height, (Image) value, Constants.IMAGE_CENTER,
BaseUtils.getAlignment4Horizontal(cell.getStyle(), value), cell.getStyle().getVerticalAlignment(),
width > 16 ? 16 : width, height > 16 ? 16 : height);
} else {
renderContent(g2d, value, cell.getStyle(), width, height, resolution);
}
}
private static void renderContent(Graphics2D g2d, Object value, Style style, int width, int height, int resolution) {
if (value != null && width != 0 && height != 0) {
if (style == null) {
style = Style.DEFAULT_STYLE.deriveImageLayout(1);
}
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getResult();
}
if (value instanceof Painter) {
((Painter)value).paint(g2d, width, height, resolution, style);
} else if (value instanceof ImageProvider) {
Style.paintImageContent(g2d, ((ImageProvider) value).getImage(), style, width, height, resolution);
} else if (value instanceof Image) {
Style.paintImageContent(g2d, (Image) value, style, width, height, resolution);
} else {
String var6 = Style.valueToText(value, style.getFormat());
NewFormStyle.paintCellStyleString2(g2d, width, height, var6, style, resolution);
}
}
}
private static boolean paintHighlightGroupMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) {
if (cell.getHighlightGroup() != null && cell.getHighlightGroup().size() > 0) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_HIGHT_LIGHT_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0, 0);
polyline.lineTo(0, CELL_MARK_SIZE);
polyline.lineTo(CELL_MARK_SIZE, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
return false;
}
private static boolean paintPresentMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) {
if (cell.getPresent() != null) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_PRESENT_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0 + left_up_count * CELL_MARK_SIZE, 0);
polyline.lineTo(0 + left_up_count * CELL_MARK_SIZE, 6);
polyline.lineTo(CELL_MARK_SIZE + left_up_count * CELL_MARK_SIZE, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
return false;
}
private static boolean paintPaginationMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int ringt_up_count) {
// 右上角: 标记是否有分页
if (isRightTopMarker(cell)) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_PAGINATION_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, 0);
polyline.lineTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, CELL_MARK_SIZE);
polyline.lineTo(width - 1 - (ringt_up_count + 1) * CELL_MARK_SIZE, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
return false;
}
private static boolean isRightTopMarker(TemplateCellElement cell) {
return cell.getCellPageAttr() != null && (cell.getCellPageAttr().isPageAfterColumn()
|| cell.getCellPageAttr().isPageBeforeColumn()
|| cell.getCellPageAttr().isPageAfterRow()
|| cell.getCellPageAttr().isPageBeforeRow());
}
private static boolean paintResultMarkWhenExsit(Graphics2D g2d, Object value, int width, int ringt_up_count) {
//右上角标记是否自定义显示
if (value instanceof DSColumn && ((DSColumn) value).getResult() != null) {
if (!ComparatorUtils.equals(((DSColumn) value).getResult(), "$$$")) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_RESULT_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(width - ringt_up_count * CELL_MARK_SIZE - 1, 0);
polyline.lineTo(width - ringt_up_count * CELL_MARK_SIZE - 1, CELL_MARK_SIZE);
polyline.lineTo(width - (ringt_up_count + 1) * CELL_MARK_SIZE - 1, 0);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
}
return false;
}
private static void paintWidgetMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int height) {
// 右下角:是否填报, 设置为4时,三角太小了,不知何故,设置为6
if (cell.getWidget() != null) {
Widget widget = cell.getWidget();
Image img = ((ImageIcon) ReportUtils.createWidgetIcon(widget.getClass())).getImage();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.67f));
g2d.drawImage(img, width - 15, height - 15, WIDGET_WIDTH, WIDGET_HEIGHT, null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
}
}
private static void paintExpandMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell) {
CellExpandAttr cellExpandAttr = cell.getCellExpandAttr();
if (cellExpandAttr != null) {
if (cellExpandAttr.getDirection() == Constants.TOP_TO_BOTTOM) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_DIRECTION_MARK_COLOR);
GraphHelper.drawLine(g2d, 2, 0, 2, 5);
GraphHelper.drawLine(g2d, 2, 5, 0, 2);
GraphHelper.drawLine(g2d, 2, 5, 4, 2);
g2d.setPaint(oldPaint);
} else if (cellExpandAttr.getDirection() == Constants.LEFT_TO_RIGHT) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_DIRECTION_MARK_COLOR);
GraphHelper.drawLine(g2d, 0, 2, 5, 2);
GraphHelper.drawLine(g2d, 5, 2, 2, 0);
GraphHelper.drawLine(g2d, 5, 2, 2, 4);
g2d.setPaint(oldPaint);
}
}
}
private static boolean paintDSColumnConditionmarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) {
// 左下角:数据列(DSColumn)相关:比如条件过滤
if (value instanceof DSColumn && ((DSColumn) value).getCondition() != null) {
if (((DSColumn) value).getCondition() instanceof ListCondition &&
((ListCondition) ((DSColumn) value).getCondition()).getJoinConditionCount() == 0) {
// do nothing
} else {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_CONDITION_FILTER_MARK_COLOR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1);
polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1);
polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
}
return false;
}
private static boolean paintDSColumnParametermarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) {
// 左下角:动态注入参数
if (value instanceof DSColumn && ((DSColumn) value).getParameters() != null) {
if (((DSColumn) value).getParameters().length > 0) {
Paint oldPaint = g2d.getPaint();
g2d.setPaint(CELL_PARAMETER_FILTER_MARK_CONLR);
GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1);
polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1);
polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE);
GraphHelper.fill(g2d, polyline);
g2d.setPaint(oldPaint);
return true;
}
}
return false;
}
/*
* 画悬浮元素
*
* 仅根据宽度 + 高度画
*/
//b:此方法在grid和tohtml的时候都被调用,所以对formula会有冲突,暂时这么改,应该考虑分开的,也可以根据result来判断,但是那么写好像不妥
public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, int width, int height, int resolution) {
Style.paintBackground(g2d, flotEl.getStyle(), width, height);
Object value = flotEl.getValue();
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getContent();
}
if (value instanceof BaseChartCollection) {
value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height);
}
//图片需要切割一下
if (value instanceof Image) {
value = CellUtils.value2ImageWithBackground(value, resolution, flotEl.getStyle(), width, height);
}
Style.paintContent(g2d, value, flotEl.getStyle(), width, height, resolution);
Style.paintBorder(g2d, flotEl.getStyle(), width, height);
}
/*
* 画悬浮元素flotEl
*
* 也就是画三个东西:背景 + 内容 + 边框
*/
public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, Rectangle paintRectangle, Rectangle clipRectangle, int resolution) {
// 画悬浮元素的背景
Style.paintBackground(g2d, flotEl.getStyle(), paintRectangle, clipRectangle);
Object value = flotEl.getValue();
if (value instanceof ResultChangeWhenExport) {
value = ((ResultChangeWhenExport) value).changeThis();
}
// 画悬浮元素的内容
Style.paintContent(g2d, value, resolution, flotEl.getStyle(), paintRectangle, clipRectangle);
// 画悬浮元素的边框
Style.paintBorder(g2d, flotEl.getStyle(), paintRectangle, clipRectangle);
}
public static void paintHTMLContent(Graphics2D g2d, String value, int resolution, Style style, Rectangle paintRectangle, Rectangle clipRectangle) {
Style.paintContent(g2d, createHTMLContentBufferedImage(value, paintRectangle, 0, 0, style), resolution, style, paintRectangle, clipRectangle);
}
public static void paintTag(Painter painter, Repository repo, int width, int height, Style style, Tag tag) {
painter.paintTag(repo, width, height, style, tag);
}
/**
* 如果用户希望以HTML方式展示String这个时候先value变成图片
*
* @param value
* @param paintRectangle 绘制范围
* @param x x坐标
* @param y y坐标
* @param style 当前格子样式
* @return BufferedImage 返回图片.
*/
public static BufferedImage createHTMLContentBufferedImage(String value, Rectangle paintRectangle, int x, int y, Style style) {
return Html2ImageUtils.createHTMLContentBufferedImage(value, paintRectangle, x, y, style);
}
/**
* see <code>BaseUtils.getLineTextList</code>, 等于BaseUtils.getLineTextList().size()
* Denny: 为了提高速度和性能才单独拿出来的
* TODO: 重构
*
* @param text 文本
* @param style 样式
* @param paintWidth 单元格宽度
* @return paintWidth 单位为PT
*/
public static int getLineTextCount(String text, Style style, UNIT paintWidth) {
if (style.getRotation() != 0) {
return 1;
}
if (style.getTextStyle() != Style.TEXTSTYLE_WRAPTEXT) {
return dealNotWrapTextCount(text.toCharArray());
} else {// 自动换行
return dealWrapTextCount(text, style, paintWidth);
}
}
private static int dealNotWrapTextCount(char[] text_chars) {
boolean remain_chars = false;
int count = 0;
for (int t = 0; t < text_chars.length; t++) {
if (text_chars[t] == '\\') {// 判断是否是 "\n"
if (t + 1 < text_chars.length && text_chars[t + 1] == 'n') {
// 是"\n"字符串,但不是换行符.
t++;
count++;
if (remain_chars) {
remain_chars = false;
}
} else {
if (!remain_chars) {
remain_chars = true;
}
}
} else if (text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n')) {
count++;
if (remain_chars) {
remain_chars = false;
}
} else {
if (!remain_chars) {
remain_chars = true;
}
}
}
// 最后一个
if (remain_chars) {
count++;
}
return count;
}
// 自动换行
//neil:style里面, 默认值padding right = 2时, 默认不生效, 这边算行高时也不要计算入内
//临时处理, 去掉左边框线, 因为浏览器计算时需要考虑左边框线宽度, 但这边还是存在问题的
//同样需要考虑的是导出和web端展示, padding计算方式也不一致.
private static int dealWrapTextCount(String text, Style style, UNIT unitWidth) {
AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess();
if (process != null) {
return process.getAutoChangeLineCount(text, new ObjectHolder(style), unitWidth);
}
int count = 0;
char[] text_chars = text.toCharArray();
FontMetrics fontMetrics = getFontMetrics(style);
double paintWidth = unitWidth.toPixD(Constants.FR_PAINT_RESOLUTION);
double width = paintWidth - style.getPaddingLeft() - (style.getPaddingRight() == Style.DEFAULT_PADDING ? 0 : style.getPaddingRight()) - style.getBorderLeftWidth();
boolean remain_lineText = false;
int lineTextWidth = 0;
int wordWidth = 0;
for (int t = 0, len = text_chars.length; t < len; t++) {
if (t != 0 && BaseUtils.isNumOrLetter(text_chars[t]) && BaseUtils.isNumOrLetter(text_chars[t - 1])) {
if (wordWidth + fontMetrics.charWidth(text_chars[t]) > width) {
if (lineTextWidth > 0) {
count++;
remain_lineText = false;
lineTextWidth = 0;
}
count++;
wordWidth = 0;
}
wordWidth += fontMetrics.charWidth(text_chars[t]);
} else if (isSwitchLine(text_chars, t) || isLN(text_chars, t)) {// 判断是否是 "\n"
if (isLN(text_chars, t)) {
t++;// 忽略'n'字符.// 是"\n"字符串,但不是换行符,依然需要换行.
}
if (lineTextWidth + wordWidth > width && remain_lineText) {
count += 2;
} else {
count++;
}
remain_lineText = false;
lineTextWidth = 0;
wordWidth = 0;
} else {
if (text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == '\\') {// 判断是否是转义字符'\'
t++;// _denny: 增加了转义字符'\\'用来表示\,使"\n"可以输入
}
if (lineTextWidth + wordWidth > width && remain_lineText) {
count++;
lineTextWidth = isPunctuationAtLineHead(t, text_chars) ? dealLineWidthWithPunctuation(t, text_chars, fontMetrics) : 0;
}
remain_lineText = true;
lineTextWidth += wordWidth;
wordWidth = fontMetrics.charWidth(text_chars[t]);
}
}
if (lineTextWidth + wordWidth > width && remain_lineText) {
count += 2;
} else {
count++;
}
return count;
}
/**
* 标点符号是否在换行后的行首
*/
private static boolean isPunctuationAtLineHead(int t, char[] text_chars) {
if (t > 1 && BaseUtils.isPunctuation(text_chars[t - 1])) {
return true;
}
return false;
}
/**
* 防止有连续多个标点符号要找一个非标点符号字符
*
* @date 2014-4-17
*/
private static int dealLineWidthWithPunctuation(int t, char[] text_chars, FontMetrics fontMetrics) {
if (t < 2) {
return 0;
}
int lineWidth = 0;
for (int index = t - 2; index >= 0; index--) {
lineWidth += fontMetrics.charWidth(text_chars[index]);
if (!BaseUtils.isPunctuation(text_chars[index])) {
break;
}
}
return lineWidth;
}
private static boolean isSwitchLine(char[] text_chars, int t) {
return text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n');
}
private static boolean isLN(char[] text_chars, int t) {
return text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == 'n';
}
/**
* Gets the preferred width.
*/
public static UNIT getPreferredWidth(CellElement cell, UNIT height) {
if (cell == null) {
return UNIT.ZERO;
}
Object value = cell.getShowValue();
// 只接受Text,Number,和SeparatorPainter
// got the text
if (value instanceof BaseFormula) {
if (((BaseFormula) value).getResult() != null) {
value = ((BaseFormula) value).getResult();
} else {
value = StringUtils.EMPTY;
}
}
Style style = cell.getStyle();
if (style == null) {
style = Style.DEFAULT_STYLE;
}
CellGUIAttr cg = cell.getCellGUIAttr() == null ? new CellGUIAttr() : cell.getCellGUIAttr();
value = Utils.resolveOtherValue(value, cg.isShowAsImage(), PresentationType.EXPORT);
String text = Style.valueToText(value, style.getFormat());
FontMetrics cellFM = getFontMetrics(style);
//bug 12151 有边框线的单元格 自动调整列宽 会多一行
UNIT padding = new PT(style.getPaddingLeft() + style.getPaddingRight());
if (cg.isShowAsHTML()) {
return Html2ImageUtils.getHtmlWidth(text, height, style);
}
return FU.valueOfPix(cellFM.stringWidth(text) + UNIT_SIZE, Constants.FR_PAINT_RESOLUTION).add(padding);
}
private static FontMetrics getFontMetrics(Style style) {
Font font = style.getFRFont().applyResolutionNP(Constants.FR_PAINT_RESOLUTION);
FontProcessor processor = ExtraClassManager.getInstance().getSingle(FontProcessor.MARK_STRING);
if (processor != null) {
font = processor.readExtraFont(font);
}
return GraphHelper.getFontMetrics(font);
}
/**
* Preferred height. (Got the shrink preferred height of CellElement).
* 单位格的预计算高度
*
* @param cellElement 单元格内容
* @param paintWidth 画的宽度
* @return UNIT 单位
*/
public static UNIT analyzeCellElementPreferredHeight(CellElement cellElement, UNIT paintWidth) {
// 计算高度用显示值
Object value = cellElement.getShowValue();
// 只接受Text,Number,和SeparatorPainter
Style style = cellElement.getStyle();
// got the text
if (value instanceof BaseFormula) {
if (((BaseFormula) value).getResult() != null) {
value = ((BaseFormula) value).getResult();
} else {
value = StringUtils.EMPTY;
}
}
CellGUIAttr cg = cellElement.getCellGUIAttr() == null ? new CellGUIAttr() : cellElement.getCellGUIAttr();
if (!(value instanceof String) && !(value instanceof Integer)) {
value = DataUtils.resolveOtherValue(value, cg.isShowAsImage(), cg.isShowAsDownload(), null, true);
}
String text = Style.valueToText(value, style.getFormat());
if (cg.isShowAsHTML()) {
return Html2ImageUtils.getHtmlHeight(text, paintWidth, style);
}
return PaintUtils.analyzeCellElementPreferredHeight(text, style, paintWidth, cg.isShowAsHTML());
}
/**
* 单位格的预计算高度
* 单位PT
*
* @param text 文本
* @param style 格式
* @param paintWidth 画的宽度
* @param isShowAsHtml 是否以html展示
* @return 返回 单位
*/
private static UNIT analyzeCellElementPreferredHeight(String text, Style style, UNIT paintWidth, boolean isShowAsHtml) {
if (style == null) {
//peter:获取默认的Style.
style = Style.DEFAULT_STYLE;
}
// got the text
if (text == null || text.length() <= 0) {
return PT.valueOf(0);
}
// 变成Line Text List.
if (style.getRotation() != 0) { // more easy to paint.
// attribute map.
return PT.valueOf((float) GraphHelper.stringDimensionWithRotation(text, style.getFRFont(), -style.getRotation(),
CoreConstants.DEFAULT_FRC).getHeight());
}
// 先获得FontMetics.
int lineCount = getLineTextCount(text, style, paintWidth);
AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess();
if (process != null) {
//算了这两个接口分开做
return process.getLinedTextHeight(lineCount, new ObjectHolder(style));
}
// carl:和paint那边一致,添上段前段后和行间距
PT lineSpacing = PT.valueOf(style.getSpacingAfter() + style.getSpacingBefore() + style.getLineSpacing() * lineCount);
FontMetrics fontMetrics = getFontMetrics(style);
int textHeight = fontMetrics.getHeight();
FU allTextHeight = FU.valueOfPix(textHeight * lineCount, Constants.FR_PAINT_RESOLUTION);
return lineSpacing.add(allTextHeight);// 需要给底部添加Leading.
}
/**
* 截取文字只考虑了垂直方向水平方向没意义且难度大.
*
* @param value 画的值
* @param style 字体样式格式.
* @param blockArea 冻结的范围
* @param resolution 分辨率
* @return 返回的字符串
*/
public static String clipBlockValue(Object value, Style style, Rectangle primitiveArea, Rectangle blockArea, int resolution, boolean isShowAsHTML) {
if (value == null) {
return null;
}
if (value instanceof BaseFormula) {
value = ((BaseFormula) value).getResult();
}
if (blockArea.y >= primitiveArea.height || blockArea.y + blockArea.height <= 0) {
return null;
}
//截取位置,相对于clipArea
int startY = blockArea.y > 0 ? blockArea.y : 0;
int endY = blockArea.y + blockArea.height < primitiveArea.height ? blockArea.y + blockArea.height : primitiveArea.height;
if (blockArea.x >= primitiveArea.width || blockArea.x + blockArea.width <= 0) {
return null;
}
if (isShowAsHTML) {
return Html2ImageUtils.clipHtmlContent(value, style, primitiveArea, resolution, startY, endY);
}
List lineList = BaseUtils.getLineTextList((String) value, style, style.getFRFont().applyResolutionNP(resolution), primitiveArea.width, resolution);
if (lineList.isEmpty()) {
return null;
}
double spacingBefore = PT.pt2pix(style.getSpacingBefore(), resolution);
double spacingAfter = PT.pt2pix(style.getSpacingAfter(), resolution);
double lineSpacing = PT.pt2pix(style.getLineSpacing(), resolution);
double lineHeight = lineSpacing + GraphHelper.getFontMetrics(style.getFRFont().applyResolutionNP(resolution)).getHeight();
int textAllHeight = (int) (lineHeight * lineList.size() + spacingBefore + spacingAfter);
//第一行文字距区域高度
int textStartY = (int) spacingBefore;
if (style.getVerticalAlignment() == Constants.BOTTOM) {
textStartY += (primitiveArea.height - textAllHeight);
}
if (endY <= textStartY || startY >= textStartY + lineHeight * lineList.size()) {
return null;
}
int lineStart = getLineStart(lineList, lineHeight, textStartY, startY);//截取区域起始行
int lineEnd = getLineEnd(lineList, lineHeight, endY, textStartY);//截取区域结束行
String text = "";
for (; lineStart <= lineEnd; lineStart++) {
text += lineList.get(lineStart);
}
return text;
}
private static int getLineStart(List lineList, double lineHeight, int textStartY, int startY) {
int lineStart = 0;
for (int i = 0; i < lineList.size(); i++) {
if (textStartY + lineHeight * (i) <= startY && textStartY + lineHeight * (i + 1) > startY) {//压线
if (startY - textStartY - lineHeight * (i) > lineHeight / 2) {
lineStart = i + 1;
} else {
lineStart = i;
}
}
}
return lineStart;
}
private static int getLineEnd(List lineList, double lineHeight, int endY, int textStartY) {
int lineEnd = lineList.size() - 1;
for (int i = 0; i < lineList.size(); i++) {
if (textStartY + lineHeight * (i) < endY && textStartY + lineHeight * (i + 1) >= endY) {//压线
//neil:仿宋,12号字, 行间距8为例, 转为px的行间距大小为10.666, 这边算出的应该有31.98行, 因此要进位
if (endY - textStartY - lineHeight * (i) >= lineHeight / 2) {
lineEnd = i;
} else {
lineEnd = i - 1;
}
}
}
return lineEnd;
}
/**
* paintBarcode
*/
public static void paintBarcode(Graphics2D g2d, int width, int height, String text, Style style, BarcodeAttr barcodeAttr) {
BarcodeImpl barcodeImpl;
try {
barcodeImpl = BarCodeUtils.getBarcodeImpl(barcodeAttr, text);
} catch (BarcodeException exp) {
try {
//设置默认值.
barcodeImpl = BarCodeUtils.getBarcodeImpl(new BarcodeAttr(), null);
} catch (BarcodeException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return;
}
}
//字体
if (style.getFRFont() != null) {
barcodeImpl.setFont(style.getFRFont());
barcodeImpl.setForeground(style.getFRFont().getForeground());
}
//背景
Background background = style.getBackground();
if (background != null && background instanceof ColorBackground) {
barcodeImpl.setBackground(((ColorBackground) background).getColor());
}
//根据宽度和高度来确定起始点
int pointX = (width - barcodeImpl.getWidth()) / 2;
int pointY = (height - barcodeImpl.getHeight()) / 2;
barcodeImpl.draw(g2d, pointX, pointY);
}
/**
* create font attribute map, 创建属性map
*
* @param font 字体
* @return map 返回字体创建的Map
*/
public static Map createFontAttributeMap(Font font) {
Map returnFontAttributeMap = (Map) fontAttributeMapCache.get(font);
if (returnFontAttributeMap == null) {// create
// returnFontAttributeMap.
returnFontAttributeMap = font.getAttributes();
fontAttributeMapCache.put(font, returnFontAttributeMap);
}
if (font instanceof FRFont) {
FRFont frFont = (FRFont) font;
// Strikethrough
if (frFont.isStrikethrough()) {
returnFontAttributeMap.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
}
}
return returnFontAttributeMap;
}
}

214
designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java

@ -0,0 +1,214 @@
package com.fr.design.fit.common;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteBodyLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.file.MutilTempalteTabPane;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.fit.JFormType;
import com.fr.design.fit.NewJForm;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.FormArea;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.JTemplate;
import com.fr.event.Event;
import com.fr.event.Listener;
import com.fr.file.MemFILE;
import com.fr.file.StashedFILE;
import com.fr.form.fit.common.LightTool;
import com.fr.form.fit.NewFormMarkAttr;
import com.fr.form.ui.Widget;
import com.fr.form.ui.widget.CRBoundsWidget;
import com.fr.general.ComparatorUtils;
import java.awt.Rectangle;
import java.util.List;
/**
* @description:模板工具类
* @author: Henry.Wang
* @create: 2020/09/03 14:19
*/
public class TemplateTool {
//和转换有关的所有代码都在这个监听器中
//在判断新老模式时,统一使用FormUIModeConfig.getInstance().newUIMode()进行判断
private static Listener<JTemplate> switchListener = new Listener<JTemplate>() {
@Override
public void on(Event event, JTemplate jTemplate) {
JFormType currentType = JFormType.OLD_TYPE;
if (AdaptiveSwitchUtil.isSwitchJFromIng()) {
currentType = DesignerUIModeConfig.getInstance().newUIMode() ? JFormType.NEW_TYPE : JFormType.OLD_TYPE;
} else {
if (jTemplate instanceof NewJForm) {
NewJForm newJForm = (NewJForm) jTemplate;
if (newJForm.mobileForm()) {
currentType = JFormType.OLD_TYPE;
} else if (LightTool.containNewFormFlag(newJForm.getTarget()) || newJForm.getTarget().getTemplateID() == null) {
currentType = JFormType.NEW_TYPE;
}
}
}
//UI转换
currentType.switchUIMode();
//标志位转换
currentType.updateJFromTemplateType(jTemplate);
//预览方式转换
currentType.updatePreviewType(jTemplate);
}
};
public static Listener<JTemplate> getSwitchListener() {
return switchListener;
}
/**
* @param
* @Description: 获取当前模板
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:17
*/
public static JTemplate getCurrentEditingTemplate() {
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
return jTemplate;
}
/**
* @param
* @Description: 获取当前NewJForm类型的模板
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:17
*/
public static NewJForm getCurrentEditingNewJForm() {
JTemplate jTemplate = getCurrentEditingTemplate();
if (jTemplate instanceof NewJForm)
return (NewJForm) jTemplate;
return null;
}
/**
* @param newJTemplate
* @Description: 每次切换设计模式都会生成新的JForm对象但是TabPane关联的还是老的JForm对象所以要重置关联的对象
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:15
*/
public static void resetTabPaneEditingTemplate(JTemplate newJTemplate) {
if (newJTemplate == null)
return;
List<JTemplate<?, ?>> jTemplateList = HistoryTemplateListCache.getInstance().getHistoryList();
for (int i = 0; i < jTemplateList.size(); i++) {
JTemplate oldJTemplate = jTemplateList.get(i);
if (oldJTemplate != null && ComparatorUtils.equals(oldJTemplate.getEditingFILE(), newJTemplate.getEditingFILE())) {
jTemplateList.set(i, newJTemplate);
MutilTempalteTabPane.getInstance().refreshOpenedTemplate(jTemplateList);
return;
}
}
}
/**
* @param jTemplate
* @Description: 是否是新建的且没有操作的模板
* @return:
* @Author: Henry.Wang
* @date: 2020/9/14 20:41
*/
public static boolean isNewTemplateWithoutModify(JTemplate jTemplate) {
return ((jTemplate.getEditingFILE() instanceof MemFILE) && jTemplate.isSaved()) ? true : false;
}
/**
* @param template
* @Description: 激活模板
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:16
*/
public static void activeAndResizeTemplate(JTemplate template) {
DesignerContext.getDesignerFrame().addAndActivateJTemplate(template);
DesignerContext.getDesignerFrame().setVisible(true);
DesignerContext.getDesignerFrame().resizeFrame();
}
/**
* @param jTemplate
* @Description:保存模板
* @return:
* @Author: Henry.Wang
* @date: 2020/9/6 14:32
*/
public static void saveForm(JTemplate<?, ?> jTemplate) {
//为空不保存
if (jTemplate == null)
return;
//不是NewJForm的模板不保存
if (!(jTemplate instanceof NewJForm))
return;
//切换环境时产生的模板不保存
if (jTemplate.getEditingFILE() instanceof StashedFILE)
return;
//新建的且没有操作的模板不保存
if (TemplateTool.isNewTemplateWithoutModify(jTemplate))
return;
jTemplate.stopEditing();
jTemplate.saveTemplate();
jTemplate.requestFocus();
}
/**
* @param height
* @param width
* @param newJForm
* @Description: 只改变绝对布局body的尺寸
* @return:
* @Author: Henry.Wang
* @date: 2020/9/11 15:14
*/
public static void onlyChangeAbsoluteBodySize(int height, int width, NewJForm newJForm) {
FormDesigner formDesigner = newJForm.getFormDesign();
FormArea formArea = formDesigner.getArea();
XLayoutContainer root = formDesigner.getRootComponent();
XWAbsoluteBodyLayout xwAbsoluteBodyLayout = LayoutTool.getXWAbsoluteBodyLayout(newJForm);
if (root.acceptType(XWFitLayout.class) && xwAbsoluteBodyLayout != null) {
XWFitLayout layout = (XWFitLayout) root;
if (height == layout.toData().getContainerHeight() && width == layout.toData().getContainerWidth())
return;
formArea.setWidthPaneValue(width);
formArea.setHeightPaneValue(height);
layout.setSize(width, height);
xwAbsoluteBodyLayout.setSize(width, height);
Widget widget = layout.toData().getWidget(0);
if (widget instanceof CRBoundsWidget) {
((CRBoundsWidget) widget).setBounds(new Rectangle(0, 0, width, height));
}
layout.toData().setContainerWidth(width);
layout.toData().setContainerHeight(height);
formArea.doReCalculateRoot(width, height, layout);
}
formDesigner.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
}
/**
* @param newJForm
* @Description: 因为新老模板切换有截断的问题所以body的尺寸会在调用onlyChangeAbsoluteBodySize之后发生改变为了使模板文件中的尺寸不发生要在模板保存时调用此函数
* @return:
* @Author: Henry.Wang
* @date: 2020/9/11 15:20
*/
public static void resetAbsoluteBodySize(NewJForm newJForm) {
if (LayoutTool.absoluteLayoutForm(newJForm)) {
NewFormMarkAttr newFormMarkAttr = newJForm.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG);
XLayoutContainer root = newJForm.getFormDesign().getRootComponent();
if (newFormMarkAttr != null && root instanceof XWFitLayout) {
((XWFitLayout) root).toData().setContainerWidth(newFormMarkAttr.getBodyWidth());
((XWFitLayout) root).toData().setContainerHeight(newFormMarkAttr.getBodyHeight());
}
}
}
}

303
designer-form/src/main/java/com/fr/design/fit/menupane/BrowserFitAttrPane.java

@ -0,0 +1,303 @@
package com.fr.design.fit.menupane;
import com.fr.config.Configuration;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.fit.FitStateCompatible;
import com.fr.design.fit.JFormType;
import com.fr.form.fit.FitType;
import com.fr.form.fit.config.FormFitConfig;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.report.fit.ReportFitAttr;
import com.fr.stable.StringUtils;
import com.fr.transaction.Configurations;
import com.fr.transaction.Worker;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* Created by Administrator on 2016/5/5/0005.
*/
public class BrowserFitAttrPane extends BasicBeanPane<ReportFitAttr> {
protected FontRadioGroup fontRadioGroup;
protected FitRadioGroup fitRadionGroup;
protected UICheckBox globalCheck;
protected FitPreviewPane fitPreviewPane;
protected ReportFitAttr localFitAttr;
protected UIRadioButton horizonRadio;
protected UIRadioButton doubleRadio;
protected UIRadioButton notFitRadio;
protected UIRadioButton fontFitRadio;
protected UIRadioButton fontNotFitRadio;
private UIButton editGlobalOps;
private JPanel borderPane;
private JPanel globalOpsPane;
private JPanel fitOpsPane;
private final JFormType jFormType;
public BrowserFitAttrPane(JFormType jFormType, ReportFitAttr fitAttr) {
this.jFormType = jFormType;
if (fitAttr == null) {
initComponents(jFormType.obtainFitAttr());
} else {
initComponents(fitAttr);
}
}
protected void initComponents(ReportFitAttr globalFitAttr) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
globalOpsPane = initGlobalOpsPane(globalFitAttr);
this.add(globalOpsPane, BorderLayout.NORTH);
fitOpsPane = initFitOpsPane();
}
protected void initBorderPane(String title) {
borderPane = FRGUIPaneFactory.createTitledBorderPaneCenter(title);
borderPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0));
borderPane.add(fitOpsPane, BorderLayout.WEST);
fitPreviewPane = new FitPreviewPane();
borderPane.add(fitPreviewPane, BorderLayout.SOUTH);
borderPane.add(getHintUILabel());
this.add(borderPane, BorderLayout.CENTER);
}
/**
* @Description: 获取提示信息
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/9/9 16:09
*/
private UILabel getHintUILabel() {
String hint = globalCheck.isSelected() ? getFillBlank(3) + Toolkit.i18nText("Fine-Designer_Fit_Attr_Pane_Hint") : StringUtils.EMPTY;
UILabel hintUILabel = new UILabel(hint);
hintUILabel.setForeground(new Color(143, 143, 146));
return hintUILabel;
}
/**
* @Description: 获取空字符串
* @param n
* @return:
* @Author: Henry.Wang
* @date: 2020/9/9 16:09
*/
private String getFillBlank(int n) {
String s = "";
for (int i = 0; i < n; i++) {
s = s + " ";
}
return s;
}
private JPanel initFitOpsPane() {
double p = TableLayout.PREFERRED;
double[] rowSize = {p, p};
double[] columnSize = {p, p, p, p, p};
ActionListener actionListener = getPreviewActionListener();
fontRadioGroup = new FontRadioGroup();
fontFitRadio = new UIRadioButton(Toolkit.i18nText("Fine-Designer_Fit") + getFillBlank(4));
fontFitRadio.setSelected(true);
fontNotFitRadio = new UIRadioButton(Toolkit.i18nText("Fine-Designer_Fit-No") + getFillBlank(2));
addRadioToGroup(fontRadioGroup, fontFitRadio, fontNotFitRadio);
fontRadioGroup.addActionListener(actionListener);
fitRadionGroup = new FitRadioGroup();
horizonRadio = new UIRadioButton(FitType.HORIZONTAL_FIT.description());
doubleRadio = new UIRadioButton(FitType.DOUBLE_FIT.description());
notFitRadio = new UIRadioButton(FitType.NOT_FIT.description());
addRadioToGroup(fitRadionGroup, doubleRadio, horizonRadio, notFitRadio);
fitRadionGroup.addActionListener(actionListener);
JPanel fitOpsPane = TableLayoutHelper.createTableLayoutPane(initFitComponents(), rowSize, columnSize);
fitOpsPane.setBorder(BorderFactory.createEmptyBorder(10, 13, 10, 10));
return fitOpsPane;
}
protected Component[][] initFitComponents() {
UILabel fitFontLabel = new UILabel(Toolkit.i18nText("Fine-Designer_Fit-Font"));
fitFontLabel.setHorizontalAlignment(SwingConstants.RIGHT);
UILabel reportFitLabel = new UILabel(Toolkit.i18nText("Fine-Designer_Fit_Report_Scale_Method"));
reportFitLabel.setHorizontalAlignment(SwingConstants.RIGHT);
Component[][] components = new Component[][]{
new Component[]{fitFontLabel, createFontRadioGroupPane()},
new Component[]{reportFitLabel, createFitAttrRadioGroupPane()}
};
return components;
}
private JPanel createFontRadioGroupPane() {
JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
panel.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 0));
panel.add(fontFitRadio);
panel.add(fontNotFitRadio);
return panel;
}
private JPanel createFitAttrRadioGroupPane() {
JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane();
panel.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 0));
panel.add(doubleRadio);
panel.add(horizonRadio);
panel.add(notFitRadio);
return panel;
}
private void addRadioToGroup(ButtonGroup buttonGroup, UIRadioButton... radios) {
for (UIRadioButton radio : radios) {
buttonGroup.add(radio);
}
}
private JPanel initGlobalOpsPane(final ReportFitAttr globalFitAttr) {
final JPanel globalOpsPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
globalCheck = new UICheckBox(Toolkit.i18nText("Fine-Designer_Fit-UseGlobal"));
globalOpsPane.add(globalCheck);
globalCheck.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean isLocalConfig = !globalCheck.isSelected();
//勾选全局时,采用全局保存的自适应属性更新界面
if (!isLocalConfig) {
ReportFitAttr attr = globalFitAttr;
populateAttrPane(attr);
remove(BrowserFitAttrPane.this.borderPane);
initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Global"));
} else {
ReportFitAttr attr = localFitAttr;
populateAttrPane(attr);
remove(BrowserFitAttrPane.this.borderPane);
initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Local"));
}
fontRadioGroup.setEnabled(isLocalConfig);
fitRadionGroup.setEnabled(isLocalConfig);
editGlobalOps.setVisible(!isLocalConfig);
String fitOptions = getCurrentFitOptions();
fitPreviewPane.refreshPreview(fitOptions, fitRadionGroup.isEnabled());
}
});
editGlobalOps = new UIButton(Toolkit.i18nText("Fine-Designer_Fit-EditGlobal"));
editGlobalOps.setVisible(false);
editGlobalOps.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
fontRadioGroup.setEnabled(true);
fitRadionGroup.setEnabled(true);
String fitOptions = getCurrentFitOptions();
fitPreviewPane.refreshPreview(fitOptions, fitRadionGroup.isEnabled());
}
public void mouseEntered(MouseEvent e) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
public void mouseExited(MouseEvent e) {
setCursor(Cursor.getDefaultCursor());
}
});
globalOpsPane.add(editGlobalOps);
return globalOpsPane;
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Designer_Fit-AttrSet");
}
@Override
public void populateBean(ReportFitAttr attr) {
if (attr == null) {
//如果为空, 就用全局的
attr = this.jFormType.obtainFitAttr();
populateGlobalComponents();
} else {
initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Local"));
}
this.localFitAttr = attr;
populateAttrPane(attr);
}
private void populateAttrPane(ReportFitAttr attr) {
fontRadioGroup.selectFontFit((attr).isFitFont());
int fitState = FitStateCompatible.getNewTypeFromOld(attr.fitStateInPC());
fitRadionGroup.selectIndexButton(fitState);
fitPreviewPane.refreshPreview(getCurrentFitOptions(), fitRadionGroup.isEnabled());
}
protected void populateGlobalComponents() {
globalCheck.setSelected(true);
fontRadioGroup.setEnabled(false);
fitRadionGroup.setEnabled(false);
editGlobalOps.setVisible(true);
initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Global"));
}
//有八种组合, 不过有意义的就是6种, 以此为key去缓存里找对应的预览图片
public String getCurrentFitOptions() {
return fitRadionGroup.getSelectRadioIndex() + "" + fontRadioGroup.getSelectRadioIndex();
}
private ActionListener getPreviewActionListener() {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String fitOptions = getCurrentFitOptions();
fitPreviewPane.refreshPreview(fitOptions, fontRadioGroup.isEnabled());
}
};
}
@Override
public ReportFitAttr updateBean() {
ReportFitAttr attr = new ReportFitAttr();
attr.setFitFont(fontRadioGroup.isFontFit());
int fitState = FitStateCompatible.getOldTypeFromNew(fitRadionGroup.getSelectRadioIndex());
attr.setFitStateInPC(fitState);
// 直接用全局的
if (globalCheck.isSelected()) {
updateGlobalConfig(attr);
return null;
}
this.localFitAttr = attr;
return attr;
}
private void updateGlobalConfig(final ReportFitAttr attr) {
Configurations.update(new Worker() {
@Override
public void run() {
jFormType.updateFitAttr(attr);
}
@Override
public Class<? extends Configuration>[] targets() {
return new Class[]{FormFitConfig.class};
}
});
}
}

76
designer-form/src/main/java/com/fr/design/fit/menupane/FitPreviewPane.java

@ -0,0 +1,76 @@
package com.fr.design.fit.menupane;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.IOUtils;
import javax.swing.ImageIcon;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2016/5/5/0005.
*/
public class FitPreviewPane extends BasicPane {
private static final String DEFAULT_FONT_TAG = "00";
private static final String DEFAULT_TAG = "01";
private static final String HORIZON_FONT_TAG = "10";
private static final String HORIZON_TAG = "11";
private static final String DOUBLE_FONT_TAG = "20";
private static final String DOUBLE_TAG = "21";
private static final String NOT_FONT_TAG = "30";
private static final String NOT_TAG = "31";
private UILabel imageLabel;
private Map<String, ImageIcon> cachedPreviewImage = new HashMap<String, ImageIcon>();
private Map<String, ImageIcon> globalCachedPreviewImage = new HashMap<String, ImageIcon>();
public FitPreviewPane() {
//初始化缓存图片, 有些无意义的组合.
initCacheImage();
//初始化组件
initComponents();
this.setPreferredSize(new Dimension(540, 170));
}
//默认和不自适应时,字体自适应不起效,只有6张图
private void initCacheImage() {
globalCachedPreviewImage.put(DEFAULT_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + DOUBLE_FONT_TAG + ".png")));
globalCachedPreviewImage.put(DEFAULT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + DOUBLE_TAG + ".png")));
globalCachedPreviewImage.put(HORIZON_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + HORIZON_FONT_TAG + ".png")));
globalCachedPreviewImage.put(HORIZON_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + HORIZON_TAG + ".png")));
globalCachedPreviewImage.put(DOUBLE_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + NOT_FONT_TAG + ".png")));
globalCachedPreviewImage.put(DOUBLE_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + NOT_FONT_TAG + ".png")));
cachedPreviewImage.put(DEFAULT_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + DOUBLE_FONT_TAG + ".png")));
cachedPreviewImage.put(DEFAULT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + DOUBLE_TAG + ".png")));
cachedPreviewImage.put(HORIZON_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + HORIZON_FONT_TAG + ".png")));
cachedPreviewImage.put(HORIZON_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + HORIZON_TAG + ".png")));
cachedPreviewImage.put(DOUBLE_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + NOT_FONT_TAG + ".png")));
cachedPreviewImage.put(DOUBLE_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + NOT_FONT_TAG + ".png")));
}
private void initComponents() {
this.setLayout(FRGUIPaneFactory.createCenterFlowLayout());
imageLabel = new UILabel();
ImageIcon image = cachedPreviewImage.get(DEFAULT_TAG);
imageLabel.setIcon(image);
this.add(imageLabel, BorderLayout.CENTER);
}
public void refreshPreview(String index, boolean isEditedable) {
ImageIcon newImageIcon = isEditedable ? cachedPreviewImage.get(index) : globalCachedPreviewImage.get(index);
imageLabel.setIcon(newImageIcon);
}
@Override
protected String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit-Preview");
}
}

80
designer-form/src/main/java/com/fr/design/fit/menupane/FitRadioGroup.java

@ -0,0 +1,80 @@
package com.fr.design.fit.menupane;
import com.fr.design.gui.ibutton.UIRadioButton;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
/**
* 自适应四个按钮选项的group
* <p>
* Created by Administrator on 2016/5/5/0005.
*/
public class FitRadioGroup extends ButtonGroup {
private List<UIRadioButton> radioButtons = new ArrayList<UIRadioButton>();
@Override
public void add(AbstractButton button) {
super.add(button);
UIRadioButton radioButton = (UIRadioButton) button;
radioButtons.add(radioButton);
}
/**
* 设置按钮状态
*/
public boolean isEnabled() {
return radioButtons.get(0).isEnabled();
}
/**
* 设置按钮状态
*/
public void setEnabled(boolean enabled) {
for (UIRadioButton radioButton : radioButtons) {
radioButton.setEnabled(enabled);
}
}
/**
* 获取当前选中的按钮index
*
* @return 按钮index
*/
public int getSelectRadioIndex() {
for (int i = 0, len = radioButtons.size(); i < len; i++) {
if (radioButtons.get(i).isSelected()) {
return i;
}
}
return 0;
}
/**
* 选中指定index的按钮
*/
public void selectIndexButton(int index) {
if (index < 0 || index > radioButtons.size() - 1) {
return;
}
UIRadioButton button = radioButtons.get(index);
button.setSelected(true);
}
/**
* 给所有的按钮加上监听
*/
public void addActionListener(ActionListener actionListener) {
for (UIRadioButton radioButton : radioButtons) {
radioButton.addActionListener(actionListener);
}
}
}

17
designer-form/src/main/java/com/fr/design/fit/menupane/FontRadioGroup.java

@ -0,0 +1,17 @@
package com.fr.design.fit.menupane;
/**
* 字体的两个选项组成的group
* <p>
* Created by Administrator on 2016/5/5/0005.
*/
public class FontRadioGroup extends FitRadioGroup {
public void selectFontFit(boolean isFontFit) {
selectIndexButton(isFontFit ? 0 : 1);
}
public boolean isFontFit() {
return getSelectRadioIndex() == 0;
}
}

58
designer-form/src/main/java/com/fr/design/fit/menupane/FormFitAttrPane.java

@ -0,0 +1,58 @@
package com.fr.design.fit.menupane;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.fit.NewJForm;
import com.fr.report.fit.ReportFitAttr;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
/**
* Created by Administrator on 2015/7/6 0006.
*/
public class FormFitAttrPane extends BasicBeanPane<ReportFitAttr> {
private BrowserFitAttrPane attrPane;
private NewJForm newJForm;
public FormFitAttrPane(NewJForm newJForm) {
this.newJForm = newJForm;
initComponents();
}
private void initComponents() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 2, 10));
attrPane = new BrowserFitAttrPane(this.newJForm.getJFormType(),this.newJForm.getTarget().getReportFitAttr());
this.add(attrPane);
}
/**
* 展示界面
*
* @param fitAttr 自适应属性
*/
public void populateBean(ReportFitAttr fitAttr) {
attrPane.populateBean(fitAttr);
}
/**
* 提交数据
*
* @return 界面上的更新数据
*/
public ReportFitAttr updateBean() {
return attrPane.updateBean();
}
/**
* 标题
*
* @return 标题
*/
protected String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_PC_Adaptive_Attr");
}
}

287
designer-form/src/main/java/com/fr/design/fit/toolbar/SwitchAction.java

@ -0,0 +1,287 @@
package com.fr.design.fit.toolbar;
import com.fr.design.actions.UpdateAction;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.fit.NewJForm;
import com.fr.design.fit.common.AdaptiveSwitchUtil;
import com.fr.design.fit.common.TemplateTool;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.BaseJForm;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.menu.MenuKeySet;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.FileFILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.MemFILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.nio.file.Paths;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
/**
* Created by kerry on 2020-06-02
*/
public class SwitchAction extends UpdateAction {
private UIButton switchBtn;
private static final Icon SWITCH_ICON = IOUtils.readIcon("/com/fr/design/form/images/icon_switch.png");
private static final String LOADING_ICON_PATH = "/com/fr/design/form/images/loading.png";
private static final MenuKeySet SWITCH_ATTR = new MenuKeySet() {
@Override
public char getMnemonic() {
return 'C';
}
@Override
public String getMenuName() {
return Toolkit.i18nText("Fine-Designer_Fit_Switch_To_Old_UI");
}
@Override
public KeyStroke getKeyStroke() {
return null;
}
};
public SwitchAction() {
initMenuStyle();
}
private void initMenuStyle() {
this.setMenuKeySet(SWITCH_ATTR);
this.setName(getMenuKeySet().getMenuKeySetName());
this.setMnemonic(getMenuKeySet().getMnemonic());
this.setSmallIcon(SWITCH_ICON);
this.setAccelerator(getMenuKeySet().getKeyStroke());
switchBtn = (UIButton) this.createToolBarComponent();
switchBtn.set4ToolbarButton();
switchBtn.setIcon(SWITCH_ICON);
Font oldFont = switchBtn.getFont();
switchBtn.setFont(new Font(oldFont.getName(),oldFont.getStyle(),12));
switchBtn.setForeground(new Color(0x33, 0x33, 0x34));
freshSwitchButton();
}
@Override
public void actionPerformed(ActionEvent e) {
//如果此时模板还在切换中,则直接返回
if (AdaptiveSwitchUtil.isSwitchJFromIng() || !saveCurrentEditingTemplate())
return;
backToFormTab();
if (confirmSwitchDialog() && backUpOldModeJTemplate()) {
AdaptiveSwitchUtil.setSwitchJFromIng(1);
showLoadingJPanel();
if (DesignerUIModeConfig.getInstance().newUIMode()) {
AdaptiveSwitchUtil.switch2OldUI();
} else {
AdaptiveSwitchUtil.switch2NewUI();
}
}
}
/**
* @Description: 对未存储在磁盘的模板进行界面切换
* @return:
* @Author: Henry.Wang
* @date: 2020/10/22 17:26
*/
public boolean saveCurrentEditingTemplate() {
JTemplate jTemplate = TemplateTool.getCurrentEditingTemplate();
if (!(jTemplate.getEditingFILE() instanceof FileNodeFILE) || !jTemplate.getEditingFILE().exists()) {
int returnVal = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Web_Preview_Message"),
Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
OK_CANCEL_OPTION,
WARNING_MESSAGE);
if (returnVal == JOptionPane.YES_OPTION) {
jTemplate.stopEditing();
if ((jTemplate.getEditingFILE() instanceof MemFILE) || !jTemplate.getEditingFILE().exists()) {
return jTemplate.saveTemplate();
} else if (jTemplate.getEditingFILE() instanceof FileFILE) {
return jTemplate.saveAsTemplate2Env();
}
}
return false;
}
return true;
}
/**
* @Description: 显示加载中界面
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/9/30 15:18
*/
public void showLoadingJPanel() {
JComponent area = TemplateTool.getCurrentEditingNewJForm().getFormDesign().getArea();
JComponent formDesigner = TemplateTool.getCurrentEditingNewJForm().getFormDesign();
area.remove(formDesigner);
JPanel loadingJPanel = new JPanel(new BorderLayout());
loadingJPanel.setBackground(Color.WHITE);
loadingJPanel.setBounds(formDesigner.getBounds());
JLabel jLabel = new JLabel(new ImageIcon(this.getClass().getResource(LOADING_ICON_PATH)), JLabel.CENTER);
loadingJPanel.add(jLabel, BorderLayout.CENTER);
area.setLayout(null);
area.add(loadingJPanel);
DesignerContext.getDesignerFrame().setVisible(true);
}
/**
* @Description: 如果是在报表块编辑状态进行切换时会先回到表单页
* @param
* @return:
* @Author: Henry.Wang
* @date: 2020/9/30 15:20
*/
private void backToFormTab() {
NewJForm newJForm = TemplateTool.getCurrentEditingNewJForm();
if (newJForm != null && newJForm.getEditingReportIndex() != BaseJForm.FORM_TAB) {
newJForm.tabChanged(BaseJForm.FORM_TAB);
}
}
/**
* @param
* @Description: 备份老设计模式下的模板文件
* @return:
* @Author: Henry.Wang
* @date: 2020/9/23 16:24
*/
private boolean backUpOldModeJTemplate() {
JTemplate<?, ?> jTemplate = TemplateTool.getCurrentEditingTemplate();
if (jTemplate != null && !DesignerUIModeConfig.getInstance().newUIMode()) {
FILE editingFILE = jTemplate.getEditingFILE();
if (editingFILE != null && editingFILE.exists()) {
try {
//待备份的文件名称
String fileName = editingFILE.getName().substring(0, editingFILE.getName().length() - jTemplate.suffix().length()) + "_bak";
//生成要备份的文件对象
FILE backUpFile = null;
FileNodeFILE directory = getFileParentDirectory(jTemplate.getEditingFILE());
if (directory != null)
backUpFile = new FileNodeFILE(directory, fileName + jTemplate.suffix(), false);
//要备份的文件存在
if (backUpFile != null && backUpFile.exists()) {
if (!confirmCoverFileDialog()) {
FILEChooserPane fileChooser = FILEChooserPane.getInstance(true, true);
fileChooser.setFileNameTextField(fileName, jTemplate.suffix());
fileChooser.setCurrentDirectory(directory);
int chooseResult = fileChooser.showSaveDialog(DesignerContext.getDesignerFrame(), jTemplate.suffix());
if ((chooseResult == FILEChooserPane.CANCEL_OPTION) ||
(chooseResult == FILEChooserPane.JOPTIONPANE_CANCEL_OPTION)) {
return false;
}
backUpFile = fileChooser.getSelectedFILE();
}
}
jTemplate.getTarget().export(backUpFile.asOutputStream());
TemplateTreePane.getInstance().refresh();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
return false;
}
return true;
}
}
return true;
}
/**
* @param file
* @Description: 获得当前文件的父目录
* @return:
* @Author: Henry.Wang
* @date: 2020/9/23 16:50
*/
public static FileNodeFILE getFileParentDirectory(FILE file) {
FileNodeFILE fileParent = null;
if (file instanceof FileNodeFILE) {
FileNodeFILE fileNodeFILE = (FileNodeFILE) file;
FileNode fileNode = new FileNode(Paths.get(fileNodeFILE.getPath()).getParent().toString(), true);
fileParent = new FileNodeFILE(fileNode, fileNodeFILE.getEnvPath());
}
return fileParent;
}
/**
* @param
* @Description: 确认是否弹出框
* @return: 点击确定返回true
* @Author: Henry.Wang
* @date: 2020/9/18 11:20
*/
private boolean confirmSwitchDialog() {
Object message = DesignerUIModeConfig.getInstance().newUIMode() ? Toolkit.i18nText("Fine-Designer_Fit_Confirm_New_Old_Switch") : Toolkit.i18nText("Fine-Designer_Fit_Confirm_Old_New_Switch");
int returnVal = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
message,
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
YES_NO_OPTION);
return returnVal == JOptionPane.YES_OPTION;
}
/**
* @param
* @Description: 是否覆盖文件
* @return:
* @Author: Henry.Wang
* @date: 2020/9/23 17:00
*/
private boolean confirmCoverFileDialog() {
int returnVal = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Designer_Fit_Cover_File_Switch"),
Toolkit.i18nText("Fine-Design_Basic_Confirm"),
YES_NO_OPTION);
return returnVal == JOptionPane.YES_OPTION;
}
/**
* @param
* @Description:更新按钮的状态
* @return:
* @Author: Henry.Wang
* @date: 2020/8/31 16:39
*/
public UIButton freshSwitchButton() {
if (DesignerUIModeConfig.getInstance().newUIMode()) {
switchBtn.setToolTipText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_Old_UI"));
switchBtn.setText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_Old_Version"));
} else {
switchBtn.setToolTipText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_New_UI"));
switchBtn.setText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_New_Version"));
}
return switchBtn;
}
public UIButton getToolBarButton() {
return freshSwitchButton();
}
}

4
designer-form/src/main/java/com/fr/design/mainframe/CoverReportPane.java

@ -1,10 +1,10 @@
package com.fr.design.mainframe;
import com.fr.design.constants.UIConstants;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.icon.IconPathConstants;
import com.fr.share.ShareConstants;
import com.fr.general.FRScreen;
import com.fr.general.IOUtils;
import com.fr.stable.StringUtils;
@ -63,7 +63,7 @@ public class CoverReportPane extends CoverPane implements HelpDialogHandler{
// controlMode = IOUtils.readIcon(IconPathConstants.TD_EL_SHARE_CLOSE_ICON_PATH);
controlButton.setVisible(false);
helpDialog = new WidgetHelpDialog(DesignerContext.getDesignerFrame(), helpMsg);
double screenValue = FRScreen.getDesignScreenByDimension(Toolkit.getDefaultToolkit().getScreenSize()).getValue();
double screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(Toolkit.getDefaultToolkit().getScreenSize()).getValue();
int offsetX = 0;
if (screenValue < FormArea.DEFAULT_SLIDER) {
offsetX = (int) ((1 - screenValue / FormArea.DEFAULT_SLIDER)

16
designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java

@ -194,7 +194,7 @@ public class EditingMouseListener extends MouseInputAdapter {
e.translatePoint(oldX - e.getX(), oldY - e.getY());
}
private void offsetEventPoint(MouseEvent e){
private void offsetEventPoint(MouseEvent e) {
int x = designer.getRelativeX(e.getX());
int y = designer.getRelativeY(e.getY());
e.translatePoint(x - e.getX(), y - e.getY());
@ -206,8 +206,8 @@ public class EditingMouseListener extends MouseInputAdapter {
* @param e 鼠标事件
*/
public void mouseReleased(MouseEvent e) {
MouseEvent transEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
MouseEvent clickEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
MouseEvent transEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
MouseEvent clickEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
int oldX = e.getX();
int oldY = e.getY();
offsetEventPoint(e);
@ -240,7 +240,7 @@ public class EditingMouseListener extends MouseInputAdapter {
}
}
private boolean isAutoFire(MouseEvent transEvent, MouseEvent clickEvent ) {
private boolean isAutoFire(MouseEvent transEvent, MouseEvent clickEvent) {
offsetEventPoint(transEvent);
XCreator xCreator = designer.getComponentAt(transEvent);
return (pressX != clickEvent.getX() || pressY != clickEvent.getY())
@ -728,15 +728,15 @@ public class EditingMouseListener extends MouseInputAdapter {
/**
* 刷新顶层组件
* */
public void refreshTopXCreator(boolean isEditing){
*/
public void refreshTopXCreator(boolean isEditing) {
designer.refreshTopXCreator(isEditing);
}
/**
* 刷新顶层组件
* */
public void refreshTopXCreator(){
*/
public void refreshTopXCreator() {
refreshTopXCreator(false);
}

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

@ -1,14 +1,13 @@
package com.fr.design.mainframe;
import com.fr.base.ScreenResolution;
import com.fr.common.inputevent.InputEventBaseOnOS;
import com.fr.design.designer.beans.events.DesignerEditListener;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWBorderLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.form.fit.NewFormMarkAttr;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UINumberField;
import com.fr.design.layout.TableLayout;
@ -79,7 +78,6 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
private boolean isValid = true;
// 初始时滑块值为100,托动后的值设为START_VALUE;
private double START_VALUE = DEFAULT_SLIDER;
private int resolution = ScreenResolution.getScreenResolution();
private double screenValue;
@ -253,7 +251,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
private void initCalculateSize() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension scrnsize = toolkit.getScreenSize();
this.screenValue = FRScreen.getDesignScreenByDimension(scrnsize).getValue();
this.screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(scrnsize).getValue();
XLayoutContainer root = FormArea.this.designer.getRootComponent();
// 7.1.1不放缩放滑块,但表单大小仍按屏幕分辨率调整
// slidePane.populateBean(screenValue);
@ -285,10 +283,19 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
// 失去焦点时,可以认为输入结束
int width = (int) ((UINumberField) e.getSource()).getValue();
changeWidthPaneValue(width);
changeFormMarkAttrWidth(width);
}
});
}
private void changeFormMarkAttrWidth(int width) {
NewFormMarkAttr newFormMarkAttr = designer.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG);
if (newFormMarkAttr != null) {
newFormMarkAttr.setBodyWidth(width);
}
}
private void changeWidthPaneValue(int width) {
XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
if (width != layout.toData().getContainerWidth()) {
@ -303,6 +310,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
public void actionPerformed(ActionEvent evt) {
int height = (int) ((UINumberField) evt.getSource()).getValue();
changeHeightPaneValue(height);
changeFormMarkAttrHeight(height);
}
});
heightPane.addFocusListener(
@ -315,6 +323,14 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
});
}
private void changeFormMarkAttrHeight(int height){
NewFormMarkAttr newFormMarkAttr = designer.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG);
if (newFormMarkAttr != null) {
newFormMarkAttr.setBodyHeight(height);
}
}
private void changeHeightPaneValue(int height) {
XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
if (height != layout.toData().getContainerHeight()) {
@ -383,7 +399,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent {
/**
* 修改大小后再根据屏幕分辨率调整下
*/
private void doReCalculateRoot(int width, int height, XWFitLayout layout) {
public void doReCalculateRoot(int width, int height, XWFitLayout layout) {
// double value = slidePane.updateBean();
//重置滑块的值为默认值100
START_VALUE = DEFAULT_SLIDER;

3
designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java

@ -43,6 +43,7 @@ import com.fr.design.designer.properties.FormWidgetAuthorityEditPane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.event.DesignerOpenedListener;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.fit.DesignerUIModeConfig;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.fun.RightSelectionHandlerProvider;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
@ -144,7 +145,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
// 存储被选择组件和剪切板的model
private transient SelectionModel selectionModel;
private int resolution = ScreenResolution.getScreenResolution();
private int resolution = DesignerUIModeConfig.getInstance().getScreenResolution();
// 编辑状态的事件表
private CreatorEventListenerTable edit;
protected List<UpdateAction> designerActions;

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

@ -11,15 +11,11 @@ import com.fr.form.ui.BaseChartEditor;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.form.ui.Widget;
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;
import java.util.Map;
public class FormModelAdapter extends DesignModelAdapter<Form, BaseJForm<Form>> {
@ -46,16 +42,6 @@ public class FormModelAdapter extends DesignModelAdapter<Form, BaseJForm<Form>>
jTemplate.populateParameter();
}
@Override
public void tableDataParametersChanged(String oldName, String tdName, TableData tableData) {
Map<String, ParameterProvider> map = new HashMap<>();
addGlobalParameters(map);
updateTableDataParameters(oldName, tdName, tableData, map, parameterProvider -> !EmbParaFilter.isFRLayerTypePara(parameterProvider));
ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters());
parameters = map.values().toArray(new Parameter[0]);
jTemplate.populateParameter();
}
/**
* 控件配置改变.
*/
@ -149,13 +135,6 @@ public class FormModelAdapter extends DesignModelAdapter<Form, BaseJForm<Form>>
@Override
protected Parameter[] getLatestParameters() {
Map<String, ParameterProvider> map = new HashMap<>();
addGlobalParameters(map);
addTableDataParameters(map, parameterProvider -> !EmbParaFilter.isFRLayerTypePara(parameterProvider));
ParameterApplyHelper.addPara2Map(map, this.getBook().getTemplateParameters());
return map.values().toArray(new Parameter[0]);
return this.getBook().getParameters();
}
}

53
designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java

@ -0,0 +1,53 @@
package com.fr.design.preview;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.impl.AbstractPreviewProvider;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.JTemplate;
import com.fr.general.web.ParameterConstants;
import java.util.HashMap;
import java.util.Map;
/**
* Created by kerry on 2020-04-23
*/
public class DeveloperPreview extends AbstractPreviewProvider {
private static final int PREVIEW_TYPE = 7;
@Override
public String nameForPopupItem() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Developer_Preview");
}
@Override
public String iconPathForPopupItem() {
return "com/fr/design/form/images/developer_preview.png";
}
@Override
public String iconPathForLarge() {
return "com/fr/design/form/images/developer_preview24.png";
}
@Override
public int previewTypeCode() {
return PREVIEW_TYPE;
}
@Override
public Map<String, Object> parametersForPreview() {
Map<String, Object> map = new HashMap<String, Object>();
map.put(ParameterConstants.OP, "developer_preview");
return map;
}
@Override
public boolean accept(JTemplate jTemplate) {
if (jTemplate == null) {
jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
}
return jTemplate instanceof JForm;
}
}

54
designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java

@ -0,0 +1,54 @@
package com.fr.design.preview;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.impl.AbstractPreviewProvider;
import com.fr.design.mainframe.JForm;
import com.fr.design.mainframe.JTemplate;
import com.fr.general.web.ParameterConstants;
import java.util.HashMap;
import java.util.Map;
/**
* Created by kerry on 2020-04-23
*/
public class FormAdaptivePreview extends AbstractPreviewProvider {
private static final int PREVIEW_TYPE = 6;
public static final String PREVIEW_OP = "form_adaptive";
@Override
public String nameForPopupItem() {
return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_New_Form_Preview");
}
@Override
public String iconPathForPopupItem() {
return "com/fr/design/images/buttonicon/runs.png";
}
@Override
public String iconPathForLarge() {
return "com/fr/design/images/buttonicon/run24.png";
}
@Override
public int previewTypeCode() {
return PREVIEW_TYPE;
}
@Override
public Map<String, Object> parametersForPreview() {
Map<String, Object> map = new HashMap<String, Object>();
map.put(ParameterConstants.OP, PREVIEW_OP);
return map;
}
@Override
public boolean accept(JTemplate jTemplate) {
if (jTemplate == null) {
jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
}
return jTemplate instanceof JForm;
}
}

BIN
designer-form/src/main/resources/com/fr/design/form/images/developer_preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

BIN
designer-form/src/main/resources/com/fr/design/form/images/developer_preview24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

BIN
designer-form/src/main/resources/com/fr/design/form/images/icon_form_tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

BIN
designer-form/src/main/resources/com/fr/design/form/images/icon_switch.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

BIN
designer-form/src/main/resources/com/fr/design/form/images/icon_switch_disable.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

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

Loading…
Cancel
Save