Browse Source
Merge in DESIGN/design from ~LOY/design:feature/x to feature/x * commit '99b2c3f97300055966a4392b6ada641b35fb0d0a': REPORT-46916 修复单元测试 REPORT-46916 调整包名,兼容性调整 REPORT-46916 调整包名 REPORT-46916 新引擎内置,调整代码结构,适配代码调用方式 REPORT-46916 新引擎内置,添加模块 REPORT-46916 新引擎内置,添加模块research/11.0
ju|剧浩宇
4 years ago
53 changed files with 3885 additions and 13 deletions
@ -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; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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")); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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()]); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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"); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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()); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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() { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
package com.fr.nx.app.designer; |
||||||
|
|
||||||
|
import com.fr.base.extension.FileExtension; |
||||||
|
import com.fr.design.mainframe.AbstractAppProvider; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* 支持设计器打开cptx文件 |
||||||
|
*/ |
||||||
|
public class CptxApp extends AbstractAppProvider<WorkBook> { |
||||||
|
|
||||||
|
public CptxApp() { |
||||||
|
StartupAssist.initDesignModule(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String[] defaultExtensions() { |
||||||
|
return new String[]{FileExtension.CPTX.getExtension()}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void process() { |
||||||
|
super.process(); |
||||||
|
StartupAssist.reloadTemplate(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 该方法只是为了读到cptx中的cpt |
||||||
|
* |
||||||
|
* @param tplFile file |
||||||
|
* @return template |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public JTemplate<WorkBook, ?> openTemplate(FILE tplFile) { |
||||||
|
WorkBook workBook = DesignerCptxFileUtils.getWorkBook(tplFile); |
||||||
|
if (workBook == null) { |
||||||
|
workBook = new WorkBook(); |
||||||
|
} |
||||||
|
return new JStreamBook(workBook, tplFile); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public WorkBook asIOFile(FILE file) { |
||||||
|
WorkBook workBook = DesignerCptxFileUtils.getWorkBook(file); |
||||||
|
if (workBook == null) { |
||||||
|
workBook = new WorkBook(); |
||||||
|
} |
||||||
|
return workBook; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,117 @@ |
|||||||
|
package com.fr.nx.app.designer; |
||||||
|
|
||||||
|
import com.fr.base.extension.FileExtension; |
||||||
|
import com.fr.design.actions.file.export.CSVExportAction; |
||||||
|
import com.fr.design.actions.file.export.PDFExportAction; |
||||||
|
import com.fr.design.actions.file.export.SVGExportAction; |
||||||
|
import com.fr.design.actions.file.export.TextExportAction; |
||||||
|
import com.fr.design.actions.file.export.WordExportAction; |
||||||
|
import com.fr.design.mainframe.JWorkBook; |
||||||
|
import com.fr.design.menu.MenuDef; |
||||||
|
import com.fr.design.menu.ShortCut; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils; |
||||||
|
import com.fr.nx.cptx.entry.metadata.CptxMetadata; |
||||||
|
import com.fr.nx.app.designer.menu.CalculateAttrAction; |
||||||
|
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.stable.StringUtils; |
||||||
|
import com.fr.stable.project.ProjectConstants; |
||||||
|
import com.fr.third.jodd.util.ArraysUtil; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileOutputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
public class JStreamBook extends JWorkBook { |
||||||
|
|
||||||
|
|
||||||
|
public JStreamBook(WorkBook workBook, FILE file) { |
||||||
|
super(workBook, file); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean saveFile() { |
||||||
|
boolean saved; |
||||||
|
TransformResultInfo resultInfo = TemplateTransformer.compileCPTX(getTarget(), getEditingFILE()); |
||||||
|
saved = resultInfo.isSaved(); |
||||||
|
this.setSaved(saved); |
||||||
|
if (saved) { |
||||||
|
this.fireJTemplateSaved(); |
||||||
|
} |
||||||
|
return saved; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean saveToNewFile(String oldName) { |
||||||
|
String path = this.getEditingFILE().getPath(); |
||||||
|
try { |
||||||
|
if (!path.startsWith(ProjectConstants.REPORTLETS_NAME)) { |
||||||
|
File file = new File(path); |
||||||
|
if (file.getParentFile() != null && !file.getParentFile().exists()) { |
||||||
|
file.getParentFile().mkdirs(); |
||||||
|
} |
||||||
|
file.createNewFile(); |
||||||
|
OutputStream outputStream = new FileOutputStream(file); |
||||||
|
this.getTarget().export(outputStream); |
||||||
|
return true; |
||||||
|
}else { |
||||||
|
TransformResult result; |
||||||
|
if (FileExtension.CPT.matchExtension(path)) { |
||||||
|
result = TemplateTransformer.TO_CPT.transform(this); |
||||||
|
} else { |
||||||
|
result = TemplateTransformer.TO_CPTX.transform(this); |
||||||
|
} |
||||||
|
return ComparatorUtils.equals(TransformResult.SUCCESS, result); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 保存文件的后缀名 |
||||||
|
* |
||||||
|
* @return 后缀的字符串 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String suffix() { |
||||||
|
return ".cptx"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void addShortCut(MenuDef exportMenuDef, MenuDef excelExportMenuDef) { |
||||||
|
exportMenuDef.addShortCut(excelExportMenuDef, new PDFExportAction(this), new WordExportAction(this), new SVGExportAction(this), |
||||||
|
new CSVExportAction(this), new TextExportAction(this)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String getPath() { |
||||||
|
return getEditingFILE().getPath() + getSuffix(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTemplateName() { |
||||||
|
return getEditingFILE().getName() + getSuffix(); |
||||||
|
} |
||||||
|
|
||||||
|
private String getSuffix() { |
||||||
|
CptxMetadata metadata = DesignerCptxFileUtils.getMetadata(this.getEditingFILE()); |
||||||
|
if (metadata != null && metadata.isForceCpt()) { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Compatibility_Mode"); |
||||||
|
} |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ShortCut[] shortcut4TemplateMenu() { |
||||||
|
return ArraysUtil.insert(super.shortcut4TemplateMenu(), new CalculateAttrAction(this), 5); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package com.fr.nx.app.designer; |
||||||
|
|
||||||
|
import com.fr.base.Parameter; |
||||||
|
import com.fr.base.extension.FileExtension; |
||||||
|
import com.fr.common.annotations.Negative; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.design.mainframe.JTemplateFactory; |
||||||
|
import com.fr.design.module.DesignModuleFactory; |
||||||
|
import com.fr.design.parameter.AbstractParameterReader; |
||||||
|
import com.fr.design.ui.util.UIUtil; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.fr.nx.cptx.CptxIOManager; |
||||||
|
import com.fr.nx.cptx.io.handle.CptxTemplateHandle; |
||||||
|
|
||||||
|
/** |
||||||
|
* 保证设计器默认 cptx 启动正常 |
||||||
|
* |
||||||
|
* @author yaohwu |
||||||
|
* created by yaohwu at 2020/6/5 16:28 |
||||||
|
*/ |
||||||
|
public class StartupAssist { |
||||||
|
|
||||||
|
public static void initDesignModule() { |
||||||
|
DesignModuleFactory.registerParameterReader(new AbstractParameterReader() { |
||||||
|
@Override |
||||||
|
public Parameter[] readParameterFromPath(String tplPath) { |
||||||
|
if (accept(tplPath, FileExtension.CPTX.getSuffix())) { |
||||||
|
try { |
||||||
|
CptxTemplateHandle handle = CptxIOManager.open(tplPath); |
||||||
|
WorkBook book = handle.getTemplate().getLegacyWorkBook(); |
||||||
|
return book.getParameters(); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
return new Parameter[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private static void reload() { |
||||||
|
JTemplate<?, ?> old = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
JTemplate<?, ?> template = JTemplateFactory.createJTemplate(old.getEditingFILE()); |
||||||
|
DesignerContext.getDesignerFrame().addAndActivateJTemplate(template); |
||||||
|
HistoryTemplateListCache.getInstance().setCurrentEditingTemplate(template); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 主代码修复后就可以删除了 |
||||||
|
* |
||||||
|
* <a href="https://work.fineres.com/browse/REPORT-33552">主代码任务链接</> |
||||||
|
*/ |
||||||
|
@Negative(until = "2021-09-01") |
||||||
|
public static void reloadTemplate() { |
||||||
|
if (isCptxJTemplate()) { |
||||||
|
UIUtil.invokeLaterIfNeeded(() -> { |
||||||
|
reload(); |
||||||
|
DesignerContext.getDesignerFrame().setVisible(true); |
||||||
|
DesignerContext.getDesignerFrame().resizeFrame(); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean isCptxJTemplate() { |
||||||
|
JTemplate<?, ?> jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
String path; |
||||||
|
return jTemplate != null && |
||||||
|
(path = jTemplate.getPath()) != null |
||||||
|
&& path.endsWith(FileExtension.CPTX.getExtension()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,109 @@ |
|||||||
|
package com.fr.nx.app.designer.cell; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.event.UIObserverListener; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.gui.ilable.MultilineLabel; |
||||||
|
import com.fr.design.mainframe.CellWidgetPropertyPane; |
||||||
|
import com.fr.design.mainframe.ElementCasePane; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.form.ui.Widget; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.report.cell.TemplateCellElement; |
||||||
|
import com.fr.report.web.button.form.TreeNodeToggleButton; |
||||||
|
|
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Color; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author yaohwu |
||||||
|
* created by yaohwu at 2020/4/26 16:33 |
||||||
|
*/ |
||||||
|
public class CellTreeAttrPanel extends BasicBeanPane<TemplateCellElement> { |
||||||
|
private static final Color TIP_COLOR = new Color(0x8f8f92); |
||||||
|
|
||||||
|
private TemplateCellElement cellElement = null; |
||||||
|
|
||||||
|
private final UICheckBox showAsTreeNodeCheckBox; |
||||||
|
|
||||||
|
private final UIObserverListener listener = new UIObserverListener() { |
||||||
|
@Override |
||||||
|
public void doChange() { |
||||||
|
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
if (template != null) { |
||||||
|
if (CellTreeAttrPanel.this.cellElement != null) { |
||||||
|
CellTreeAttrPanel.this.updateBean(); |
||||||
|
} |
||||||
|
template.fireTargetModified(); |
||||||
|
CellWidgetPropertyPane.getInstance().populate((ElementCasePane<?>) template.getCurrentElementCasePane()); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private static final class Holder { |
||||||
|
private static final CellTreeAttrPanel INSTANCE = new CellTreeAttrPanel(); |
||||||
|
} |
||||||
|
|
||||||
|
public static CellTreeAttrPanel getInstance() { |
||||||
|
return Holder.INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
private CellTreeAttrPanel() { |
||||||
|
this.setLayout(new BorderLayout()); |
||||||
|
showAsTreeNodeCheckBox = |
||||||
|
new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Cell_Show_As_Tree_Node")); |
||||||
|
this.add(showAsTreeNodeCheckBox, BorderLayout.NORTH); |
||||||
|
MultilineLabel multilineLabel = |
||||||
|
new MultilineLabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Cell_Show_As_Tree_Node_TIP")); |
||||||
|
multilineLabel.setForeground(TIP_COLOR); |
||||||
|
this.add(multilineLabel, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 展示数据 |
||||||
|
* |
||||||
|
* @param ob 待展示的对象 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void populateBean(TemplateCellElement ob) { |
||||||
|
this.cellElement = ob; |
||||||
|
Widget widget = cellElement.getWidget(); |
||||||
|
showAsTreeNodeCheckBox.registerChangeListener(null); |
||||||
|
showAsTreeNodeCheckBox.setSelected(widget instanceof TreeNodeToggleButton); |
||||||
|
showAsTreeNodeCheckBox.registerChangeListener(listener); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存数据 |
||||||
|
* |
||||||
|
* @return 待保存的对象 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public TemplateCellElement updateBean() { |
||||||
|
if (this.cellElement == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
if (showAsTreeNodeCheckBox.isSelected()) { |
||||||
|
cellElement.setWidget(createTreeToggleButton()); |
||||||
|
} else { |
||||||
|
cellElement.setWidget(null); |
||||||
|
} |
||||||
|
return this.cellElement; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateBean(TemplateCellElement ob) { |
||||||
|
this.cellElement = ob; |
||||||
|
updateBean(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
private TreeNodeToggleButton createTreeToggleButton() { |
||||||
|
return new TreeNodeToggleButton(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package com.fr.nx.app.designer.cell; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.fun.impl.AbstractCellExpandAttrPanelProvider; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.nx.app.designer.JStreamBook; |
||||||
|
import com.fr.report.cell.TemplateCellElement; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author yaohwu |
||||||
|
* created by yaohwu at 2020/4/26 16:32 |
||||||
|
*/ |
||||||
|
public class CellTreeAttrPanelProvider extends AbstractCellExpandAttrPanelProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public BasicBeanPane<TemplateCellElement> createPanel() { |
||||||
|
return CellTreeAttrPanel.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 只有新引擎 cptx 模版才展示 |
||||||
|
* 先注释掉Override,适配老的主jar,保留这个方法是为了在新主jar下支持这个功能 |
||||||
|
*/ |
||||||
|
// @Override
|
||||||
|
public boolean isDisplayable() { |
||||||
|
JTemplate<?, ?> current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||||
|
return current instanceof JStreamBook; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
package com.fr.nx.app.designer.menu; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.design.actions.JTemplateAction; |
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
import com.fr.design.dialog.UIDialog; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.menu.MenuKeySet; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.fr.nx.app.designer.JStreamBook; |
||||||
|
import com.fr.plugin.attr.CalculatorAttrMark; |
||||||
|
|
||||||
|
import javax.swing.KeyStroke; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
|
||||||
|
public class CalculateAttrAction extends JTemplateAction<JStreamBook> { |
||||||
|
|
||||||
|
public CalculateAttrAction(JStreamBook jTemplate) { |
||||||
|
super(jTemplate); |
||||||
|
initMenuStyle(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initMenuStyle() { |
||||||
|
this.setMenuKeySet(CALCULATE_FIT_ATTR); |
||||||
|
this.setName(getMenuKeySet().getMenuKeySetName() + "..."); |
||||||
|
this.setMnemonic(getMenuKeySet().getMnemonic()); |
||||||
|
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/bbs/center.png")); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Action触发事件 |
||||||
|
* |
||||||
|
* @param e 事件 |
||||||
|
*/ |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
final JStreamBook jwb = getEditingComponent(); |
||||||
|
if (jwb == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
WorkBook workBook = jwb.getTarget(); |
||||||
|
CalculatorAttrMark mark = workBook.getAttrMark(CalculatorAttrMark.MARK); |
||||||
|
CalculateAttrPane attrPane = new CalculateAttrPane(); |
||||||
|
showReportFitDialog(mark, jwb, workBook, attrPane); |
||||||
|
} |
||||||
|
|
||||||
|
private void showReportFitDialog(CalculatorAttrMark mark, final JStreamBook jwb, final WorkBook workBook, final BasicBeanPane<CalculatorAttrMark> attrPane) { |
||||||
|
attrPane.populateBean(mark); |
||||||
|
UIDialog dialog = attrPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
workBook.addAttrMark(attrPane.updateBean()); |
||||||
|
jwb.fireTargetModified(); |
||||||
|
} |
||||||
|
}); |
||||||
|
dialog.setVisible(true); |
||||||
|
} |
||||||
|
|
||||||
|
private static final MenuKeySet CALCULATE_FIT_ATTR = new MenuKeySet() { |
||||||
|
@Override |
||||||
|
public char getMnemonic() { |
||||||
|
return 'C'; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getMenuName() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Attr"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public KeyStroke getKeyStroke() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,200 @@ |
|||||||
|
package com.fr.nx.app.designer.menu; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
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.ispinner.UISpinner; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.nx.app.designer.menu.bean.FeatureFlagBean; |
||||||
|
import com.fr.nx.feature.FeatureFlags; |
||||||
|
import com.fr.nx.feature.FeatureManager; |
||||||
|
import com.fr.plugin.attr.CalculatorAttrMark; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.BoxLayout; |
||||||
|
import javax.swing.JDialog; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import javax.swing.SwingUtilities; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Color; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Font; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class CalculateAttrPane extends BasicBeanPane<CalculatorAttrMark> { |
||||||
|
|
||||||
|
private static final Color TIPS_FONT_COLOR = new Color(0x8f8f92); |
||||||
|
|
||||||
|
// private UICheckBox calculateEnd;
|
||||||
|
private UICheckBox queryCache; |
||||||
|
|
||||||
|
private UICheckBox treeAsyncQuery; |
||||||
|
|
||||||
|
private UICheckBox multiSourceMode; |
||||||
|
|
||||||
|
private UISpinner treeExpandLayer; |
||||||
|
|
||||||
|
private JPanel treeConfigPanel; |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前模版从未设置过模版计算属性 |
||||||
|
*/ |
||||||
|
private boolean isEmptyAttr = false; |
||||||
|
|
||||||
|
public CalculateAttrPane() { |
||||||
|
initComponents(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponents() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
||||||
|
|
||||||
|
JPanel featureFlagPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); |
||||||
|
ActionLabel featureLabel = new ActionLabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Experimental_Feature")); |
||||||
|
featureLabel.setFont(new Font(null, Font.PLAIN, 10)); |
||||||
|
featureLabel.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
JDialog wDialog = createJDialog(); |
||||||
|
wDialog.setVisible(true); |
||||||
|
} |
||||||
|
}); |
||||||
|
featureFlagPanel.add(featureLabel); |
||||||
|
|
||||||
|
JPanel calculateAttrPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); |
||||||
|
calculateAttrPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); |
||||||
|
|
||||||
|
// JPanel calculatedEndPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
|
||||||
|
// calculateEnd = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Calculate-End"));
|
||||||
|
// calculatedEndPanel.add(calculateEnd);
|
||||||
|
JPanel queryCachePanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||||
|
queryCache = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Calculate_Query_Cache")); |
||||||
|
queryCachePanel.add(queryCache); |
||||||
|
JPanel multiSourcePanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||||
|
multiSourceMode = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Feature_Multi_Source")); |
||||||
|
multiSourcePanel.add(multiSourceMode); |
||||||
|
|
||||||
|
// calculateAttrPanel.add(calculatedEndPanel);
|
||||||
|
calculateAttrPanel.add(queryCachePanel); |
||||||
|
calculateAttrPanel.add(multiSourcePanel); |
||||||
|
|
||||||
|
|
||||||
|
treeConfigPanel = FRGUIPaneFactory.createTitledBorderPane( |
||||||
|
InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Config") |
||||||
|
); |
||||||
|
treeConfigPanel.setVisible(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE)); |
||||||
|
treeConfigPanel.setLayout(new BoxLayout(treeConfigPanel, BoxLayout.Y_AXIS)); |
||||||
|
|
||||||
|
JPanel treeAsyncQueryPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||||
|
treeAsyncQuery = new UICheckBox(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Async_Query")); |
||||||
|
treeAsyncQueryPanel.add(treeAsyncQuery); |
||||||
|
|
||||||
|
JPanel treeExpandLayerPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||||
|
UILabel treeExpandLayerLabel = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Expand_Layer")); |
||||||
|
treeExpandLayer = new UISpinner(1, Integer.MAX_VALUE, 1, 1); |
||||||
|
// 功能不支持,设置先禁用
|
||||||
|
treeExpandLayer.setEnabled(false); |
||||||
|
|
||||||
|
treeExpandLayerPanel.add(treeExpandLayerLabel); |
||||||
|
treeExpandLayerPanel.add(treeExpandLayer); |
||||||
|
|
||||||
|
JPanel treeExpandLayerLabelPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||||
|
UILabel multilineLabel = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Tree_Expand_Layer_Label")); |
||||||
|
multilineLabel.setForeground(TIPS_FONT_COLOR); |
||||||
|
treeExpandLayerLabelPanel.add(multilineLabel); |
||||||
|
|
||||||
|
|
||||||
|
treeConfigPanel.add(treeAsyncQueryPanel); |
||||||
|
treeConfigPanel.add(treeExpandLayerPanel); |
||||||
|
treeConfigPanel.add(treeExpandLayerLabelPanel); |
||||||
|
|
||||||
|
List<Component[]> components = new ArrayList<>(); |
||||||
|
components.add(new Component[]{featureFlagPanel}); |
||||||
|
components.add(new Component[]{calculateAttrPanel}); |
||||||
|
components.add(new Component[]{treeConfigPanel}); |
||||||
|
|
||||||
|
JPanel content = |
||||||
|
TableLayoutHelper.createGapTableLayoutPane( |
||||||
|
components.toArray(new Component[0][]), |
||||||
|
TableLayoutHelper.FILL_LASTCOLUMN, |
||||||
|
5, |
||||||
|
5 |
||||||
|
); |
||||||
|
|
||||||
|
this.add(content, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(CalculatorAttrMark attrMark) { |
||||||
|
if (attrMark == null) { |
||||||
|
isEmptyAttr = true; |
||||||
|
// 默认折叠树配置
|
||||||
|
treeAsyncQuery.setSelected(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE_ASYNC)); |
||||||
|
return; |
||||||
|
} |
||||||
|
// calculateEnd.setSelected(attrMark.isCalculateEnd());
|
||||||
|
queryCache.setSelected(attrMark.isQueryCache()); |
||||||
|
treeAsyncQuery.setSelected(attrMark.isTreeAsyncQuery()); |
||||||
|
treeExpandLayer.setValue(attrMark.getTreeExpandLayer()); |
||||||
|
multiSourceMode.setSelected(attrMark.isUseMultiSourceMode()); |
||||||
|
isEmptyAttr = false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 提交数据 |
||||||
|
* |
||||||
|
* @return 界面上的更新数据 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public CalculatorAttrMark updateBean() { |
||||||
|
return new CalculatorAttrMark(false, queryCache.isSelected()) |
||||||
|
.treeAsyncQuery(treeAsyncQuery.isSelected()) |
||||||
|
.treeExpandLayer((int) treeExpandLayer.getValue()) |
||||||
|
.useMultiSourceMode(multiSourceMode.isSelected()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 标题 |
||||||
|
* |
||||||
|
* @return 标题 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Attr"); |
||||||
|
} |
||||||
|
|
||||||
|
private void showFeatureConfigPane() { |
||||||
|
treeConfigPanel.setVisible(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE)); |
||||||
|
} |
||||||
|
|
||||||
|
private void resetTreeAsyncConfigPane() { |
||||||
|
if (isEmptyAttr) { |
||||||
|
treeAsyncQuery.setSelected(FeatureManager.getInstance().isFlagEnable(FeatureFlags.TREE_ASYNC)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private JDialog createJDialog() { |
||||||
|
final FeatureFlagsPanel panel = new FeatureFlagsPanel(); |
||||||
|
panel.populateBean(new FeatureFlagBean()); |
||||||
|
return panel.showSmallWindow(SwingUtilities.getWindowAncestor(CalculateAttrPane.this), new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
panel.updateBean().saveModification(); |
||||||
|
super.doOk(); |
||||||
|
CalculateAttrPane.this.resetTreeAsyncConfigPane(); |
||||||
|
CalculateAttrPane.this.showFeatureConfigPane(); |
||||||
|
CalculateAttrPane.this.revalidate(); |
||||||
|
CalculateAttrPane.this.repaint(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
package com.fr.nx.app.designer.menu; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.gui.icheckbox.UICheckBox; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.nx.app.designer.menu.bean.FeatureFlagBean; |
||||||
|
import com.fr.nx.feature.FeatureFlag; |
||||||
|
import com.fr.stable.collections.combination.Pair; |
||||||
|
|
||||||
|
import javax.swing.BorderFactory; |
||||||
|
import javax.swing.JPanel; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by loy on 2020/4/14. |
||||||
|
*/ |
||||||
|
public class FeatureFlagsPanel extends BasicBeanPane<FeatureFlagBean> { |
||||||
|
|
||||||
|
private FeatureFlagBean bean; |
||||||
|
private JPanel mainPanel; |
||||||
|
|
||||||
|
public FeatureFlagsPanel() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
||||||
|
mainPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); |
||||||
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); |
||||||
|
JPanel content = |
||||||
|
TableLayoutHelper.createGapTableLayoutPane( |
||||||
|
new Component[][]{new Component[]{mainPanel}}, |
||||||
|
TableLayoutHelper.FILL_LASTCOLUMN, |
||||||
|
5, |
||||||
|
5 |
||||||
|
); |
||||||
|
|
||||||
|
this.add(content, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(FeatureFlagBean featureFlagBean) { |
||||||
|
this.bean = featureFlagBean; |
||||||
|
mainPanel.removeAll(); |
||||||
|
for (Pair<FeatureFlag, Boolean> entry : featureFlagBean.getAllFlags()) { |
||||||
|
final FeatureFlag flag = entry.getFirst(); |
||||||
|
Boolean selected = entry.getSecond(); |
||||||
|
JPanel itemPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); |
||||||
|
final UICheckBox cb = new UICheckBox(flag.getDisplayName()); |
||||||
|
cb.setSelected(selected); |
||||||
|
cb.addActionListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
bean.modifyFlag(flag, cb.isSelected()); |
||||||
|
} |
||||||
|
}); |
||||||
|
itemPanel.add(cb); |
||||||
|
mainPanel.add(itemPanel); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public FeatureFlagBean updateBean() { |
||||||
|
return bean; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Experimental_Feature"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package com.fr.nx.app.designer.menu.bean; |
||||||
|
|
||||||
|
import com.fr.nx.feature.FeatureFlag; |
||||||
|
import com.fr.nx.feature.FeatureManager; |
||||||
|
import com.fr.stable.collections.combination.Pair; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by loy on 2020/4/14. |
||||||
|
*/ |
||||||
|
public class FeatureFlagBean { |
||||||
|
|
||||||
|
private Map<FeatureFlag, Boolean> modifyMap = new HashMap<>(); |
||||||
|
|
||||||
|
public List<Pair<FeatureFlag, Boolean>> getAllFlags() { |
||||||
|
List<Pair<FeatureFlag, Boolean>> flagList = new ArrayList<>(); |
||||||
|
for (FeatureFlag flag : FeatureManager.getSupportFlags()) { |
||||||
|
flagList.add(new Pair<>(flag, FeatureManager.getInstance().isFlagEnable(flag))); |
||||||
|
} |
||||||
|
return flagList; |
||||||
|
} |
||||||
|
|
||||||
|
public void modifyFlag(FeatureFlag flag, boolean value) { |
||||||
|
modifyMap.put(flag, value); |
||||||
|
} |
||||||
|
|
||||||
|
public void saveModification() { |
||||||
|
for (Map.Entry<FeatureFlag, Boolean> entry : modifyMap.entrySet()) { |
||||||
|
FeatureManager.getInstance().setFlagEnable(entry.getKey(), entry.getValue()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.fr.nx.app.designer; |
||||||
|
|
||||||
|
import com.fr.file.AbstractFILE; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.fr.nx.app.designer.utils.DesignerCptxFileUtils; |
||||||
|
import org.easymock.EasyMock; |
||||||
|
import org.junit.Assert; |
||||||
|
import org.junit.FixMethodOrder; |
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.junit.runners.JUnit4; |
||||||
|
import org.junit.runners.MethodSorters; |
||||||
|
import org.powermock.api.easymock.PowerMock; |
||||||
|
import org.powermock.core.classloader.annotations.PrepareForTest; |
||||||
|
import org.powermock.modules.junit4.PowerMockRunner; |
||||||
|
import org.powermock.modules.junit4.PowerMockRunnerDelegate; |
||||||
|
|
||||||
|
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING) |
||||||
|
@RunWith(PowerMockRunner.class) |
||||||
|
@PowerMockRunnerDelegate(JUnit4.class) |
||||||
|
@PrepareForTest({ |
||||||
|
DesignerCptxFileUtils.class |
||||||
|
}) |
||||||
|
public class CptxAppTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testDefaultExtensions() { |
||||||
|
CptxApp app = new CptxApp(); |
||||||
|
String[] extendsions = app.defaultExtensions(); |
||||||
|
Assert.assertEquals("cptx", extendsions[0]); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testAsIOFile() { |
||||||
|
PowerMock.mockStatic(DesignerCptxFileUtils.class); |
||||||
|
FILE file = new AbstractFILE() { |
||||||
|
}; |
||||||
|
WorkBook workBook = new WorkBook(); |
||||||
|
EasyMock.expect(DesignerCptxFileUtils.getWorkBook(file)) |
||||||
|
.andReturn(workBook).once() |
||||||
|
.andReturn(null).once(); |
||||||
|
|
||||||
|
PowerMock.replay(DesignerCptxFileUtils.class); |
||||||
|
Assert.assertSame(workBook, new CptxApp().asIOFile(file)); |
||||||
|
|
||||||
|
Assert.assertNotNull(new CptxApp().asIOFile(file)); |
||||||
|
|
||||||
|
PowerMock.verify(DesignerCptxFileUtils.class); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,121 @@ |
|||||||
|
package com.fr.nx.app.designer; |
||||||
|
|
||||||
|
import com.fr.file.FILE; |
||||||
|
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 org.easymock.EasyMock; |
||||||
|
import org.easymock.IAnswer; |
||||||
|
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.core.classloader.annotations.SuppressStaticInitializationFor; |
||||||
|
import org.powermock.modules.junit4.PowerMockRunner; |
||||||
|
|
||||||
|
@RunWith(PowerMockRunner.class) |
||||||
|
@PrepareForTest({TemplateTransformer.class, JStreamBook.class}) |
||||||
|
@PowerMockIgnore({"com.fr.license.*"}) |
||||||
|
@SuppressStaticInitializationFor({"com.fr.plugin.designer.JStreamBook"}) |
||||||
|
public class JStreamBookTest { |
||||||
|
|
||||||
|
|
||||||
|
@Test |
||||||
|
public void saveFile() { |
||||||
|
|
||||||
|
PowerMock.mockStatic(TemplateTransformer.class); |
||||||
|
final boolean[] fireSave = {false}; |
||||||
|
|
||||||
|
|
||||||
|
JStreamBook workbook = |
||||||
|
EasyMock.partialMockBuilder(VirtualJStreamBook.class) |
||||||
|
.addMockedMethod("fireJTemplateSaved") |
||||||
|
.addMockedMethod("getTarget") |
||||||
|
.addMockedMethod("getEditingFILE") |
||||||
|
.createMock(); |
||||||
|
// 保存成功
|
||||||
|
EasyMock.expect(TemplateTransformer.compileCPTX(null, null)) |
||||||
|
.andReturn(TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "fake Unsupported").saved(true)) |
||||||
|
.once(); |
||||||
|
PowerMock.replay(TemplateTransformer.class); |
||||||
|
|
||||||
|
workbook.fireJTemplateSaved(); |
||||||
|
EasyMock.expectLastCall().andAnswer(new IAnswer<Void>() { |
||||||
|
@Override |
||||||
|
public Void answer() throws Throwable { |
||||||
|
fireSave[0] = true; |
||||||
|
return null; |
||||||
|
} |
||||||
|
}).once(); |
||||||
|
|
||||||
|
EasyMock.expect(workbook.getTarget()).andAnswer(new IAnswer<WorkBook>() { |
||||||
|
@Override |
||||||
|
public WorkBook answer() throws Throwable { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}).once(); |
||||||
|
|
||||||
|
EasyMock.expect(workbook.getEditingFILE()).andAnswer(new IAnswer<FILE>() { |
||||||
|
@Override |
||||||
|
public FILE answer() throws Throwable { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}).once(); |
||||||
|
|
||||||
|
EasyMock.replay(workbook); |
||||||
|
|
||||||
|
boolean saved = workbook.saveFile(); |
||||||
|
Assert.assertTrue(saved); |
||||||
|
Assert.assertTrue(fireSave[0]); |
||||||
|
|
||||||
|
PowerMock.verify(TemplateTransformer.class); |
||||||
|
EasyMock.verify(workbook); |
||||||
|
|
||||||
|
fireSave[0] = false; |
||||||
|
|
||||||
|
// 保存失败
|
||||||
|
PowerMock.reset(TemplateTransformer.class); |
||||||
|
EasyMock.expect(TemplateTransformer.compileCPTX(null, null)) |
||||||
|
.andReturn(TransformResultInfo.generateResult(TransformResult.FAILED, "fake Unsupported").saved(false)) |
||||||
|
.once(); |
||||||
|
PowerMock.replay(TemplateTransformer.class); |
||||||
|
EasyMock.reset(workbook); |
||||||
|
|
||||||
|
EasyMock.expect(workbook.getTarget()).andAnswer(new IAnswer<WorkBook>() { |
||||||
|
@Override |
||||||
|
public WorkBook answer() throws Throwable { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}).once(); |
||||||
|
|
||||||
|
EasyMock.expect(workbook.getEditingFILE()).andAnswer(new IAnswer<FILE>() { |
||||||
|
@Override |
||||||
|
public FILE answer() throws Throwable { |
||||||
|
return null; |
||||||
|
} |
||||||
|
}).once(); |
||||||
|
EasyMock.replay(workbook); |
||||||
|
|
||||||
|
saved = workbook.saveFile(); |
||||||
|
Assert.assertFalse(saved); |
||||||
|
Assert.assertFalse(fireSave[0]); |
||||||
|
|
||||||
|
PowerMock.verify(TemplateTransformer.class); |
||||||
|
EasyMock.verify(workbook); |
||||||
|
} |
||||||
|
|
||||||
|
private static final class VirtualJStreamBook extends JStreamBook { |
||||||
|
|
||||||
|
public VirtualJStreamBook(WorkBook workBook, FILE file) { |
||||||
|
super(workBook, file); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return this.getClass().getName() + "fake to string"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<WorkBook xmlVersion="20170720" releaseVersion="10.0.0"> |
||||||
|
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1"> |
||||||
|
<ReportPageAttr> |
||||||
|
<HR/> |
||||||
|
<FR/> |
||||||
|
<HC/> |
||||||
|
<FC/> |
||||||
|
</ReportPageAttr> |
||||||
|
<ColumnPrivilegeControl/> |
||||||
|
<RowPrivilegeControl/> |
||||||
|
<RowHeight defaultValue="723900"> |
||||||
|
<![CDATA[723900,4295838,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight> |
||||||
|
<ColumnWidth defaultValue="2743200"> |
||||||
|
<![CDATA[6627865,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth> |
||||||
|
<CellElementList> |
||||||
|
<C c="0" r="0"> |
||||||
|
<PrivilegeControl/> |
||||||
|
<Expand order="1"/> |
||||||
|
</C> |
||||||
|
<C c="1" r="0"> |
||||||
|
<O t="I"> |
||||||
|
<![CDATA[1]]></O> |
||||||
|
<PrivilegeControl/> |
||||||
|
<Expand/> |
||||||
|
</C> |
||||||
|
<C c="0" r="1"> |
||||||
|
<O t="XMLable" class="com.fr.general.ImageWithSuffix"> |
||||||
|
<FineImage fm="png"> |
||||||
|
<IM> |
||||||
|
<![CDATA[!T4)&qh\-E7h#eD$31&+%7s)Y;?-[s;?-[s;@!I,!!(%jK:;i@"K+gZ5u`*!m@D"-'L<GRe" |
||||||
|
s8V+^efB0"$1Z>tC;K&-B[7`5WK?,Xelf@&8+0+s;]Ad+gFe2#R^R0KRcH9&1(_,Q&m?CF2#j |
||||||
|
L2g`#\[sRl3^"LL;I*q<:m`bRtAnUh^m(8[R[\Qdap[PoDZI+D(a6:V.`2I<j@73SOmdDs,A |
||||||
|
+uOS3sXroCYL"=N7$79<fLEF.)_okG>2?>R^Sd'MY!@@k@GfZiTaUt[[X*Qn(Vqi1,QX!S[g |
||||||
|
X8cV#:o/U(RN!]A[-MCK!$>RYIs_SOW[_9PE1L2Q+u4)L'*_+9GA>FbhqkF3><ITQR#Z&\t@r |
||||||
|
[!>rH*rsS)m6q"c>/>qr/Vjd(?R(*:-.oLG%<9eZ1]Al^J"e-:(+>+Q1NPOaSJo+/S+i4n&T% |
||||||
|
\/J4IBcE%5,_GkC[%jH'kh$2]A+l)FI""N?9]AXFHef&/Q\Pm:q*oGRR,WL<dta:sa5g[sEC!i |
||||||
|
2BKX\fS\?I`Sr$qqD4,Rq:A1qgre[HWS.AXA,T'5S3(`gh<4:2'QhJ%3fl9"m:'tu8Ts:@U: |
||||||
|
VVh>M]A._;-d'aOX+8Xcia>YISk1g?.bi%E?!"e!Dq4AIRE5*J06XZ"l9<VXc0CmdGqRCY\[V |
||||||
|
jH,m1GSaXbIcEJA8MVlg3npt"ps&Q#K6#N$Oa+4nH=;+F`U)c]A/o/l[6`,^T3Lkh5?3_]A^#? |
||||||
|
kP/@Wf,h'#E=eI>/,[%5lSYHM*Gsc;De0X(/o,#On+F;om!UF7s$[mR(>_*`AIpT;n1NSp*r |
||||||
|
5Md*5kOL1RpseeaT5!G,kk_1&F%\@jJs#W%4nbD$X(dC(\O+&KX.Vp>]AY-Lo<Zfr&,N4U<l3 |
||||||
|
\c3%i!rXB<7Y--5>L^V=LM7!$S/!&hR'nH_0hm_H,f=2p+p`R&".Le>"lHKmKAHnSIm69U'g |
||||||
|
LYG,>[,VlJ&!5>PutHqRJ4XG^$7ZL6(YG+-e=+b;LUuH3Zrc58GNFlF?j1-+QXQ(%S6.V?:G |
||||||
|
1jf/GeC6q@_Q>S5"##8tiN'(`qU.T7U?<]A'i8Uhe/g^>U%!HX@Al,.N83)TcC)q$'k_OQ-?: |
||||||
|
_D-F="?_k3O8O[DbknE3?fn3U+EJ3:q;#Xc<us;VN0E_,#[5<%bWR/m"YJ/$/ncCA7S?[j0O |
||||||
|
"7eDS"!*;F5*3mL`XuV$==.VthfIr!KbMS$iZjA,/%hUoiVc!Y-RGQBegW]AOdq1#1ZcM-7T7 |
||||||
|
!1]AKjAoOfF;#;YX8dknF7"f0r)k@UaJen54dIPZFo<,FG*kET--FlL!4pNhXJWUmu)gmTe=% |
||||||
|
;EIA(U#04L!G6;`dfD5U#?b(9UAV,ZsGPK90Bb9k\<VBG[>cA+E^R:k_hA7K7g.e*(3U#a[& |
||||||
|
%V(jo6,q3)+CL/"I32M"cKPBGLn2M%"r'=faV2lDBHCm%MHBI]AOIZj%Z*1+*FVK8J!g'*3c# |
||||||
|
"WMR3*Y&1h_H@PEJC*H;"Y@nbp:f4UB61F[-H4phL"^(VI"gQST8h*)bt+Jo(MXVpo+u.k@X |
||||||
|
tpaqkFs9$<?s@QH[Num^)V"=AgaN!FkbtEsHE-B`J,5!(fUS7'8jaJc~ |
||||||
|
]]></IM> |
||||||
|
</FineImage> |
||||||
|
</O> |
||||||
|
<PrivilegeControl/> |
||||||
|
<Expand/> |
||||||
|
</C> |
||||||
|
</CellElementList> |
||||||
|
<ReportAttrSet> |
||||||
|
<ReportSettings headerHeight="0" footerHeight="0"> |
||||||
|
<PaperSetting/> |
||||||
|
<Background name="ColorBackground" color="-1"/> |
||||||
|
</ReportSettings> |
||||||
|
</ReportAttrSet> |
||||||
|
<PrivilegeControl/> |
||||||
|
</Report> |
||||||
|
<ReportParameterAttr> |
||||||
|
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="true"/> |
||||||
|
<PWTitle> |
||||||
|
<![CDATA[参数]]></PWTitle> |
||||||
|
</ReportParameterAttr> |
||||||
|
<StyleList/> |
||||||
|
<DesignerVersion DesignerVersion="KAA"/> |
||||||
|
<PreviewType PreviewType="0"/> |
||||||
|
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark"> |
||||||
|
<TemplateIdAttMark TemplateId="2c82bd1f-e4a5-4d56-bc03-789dfd00971d"/> |
||||||
|
</TemplateIdAttMark> |
||||||
|
</WorkBook> |
@ -0,0 +1,78 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<WorkBook xmlVersion="20170720" releaseVersion="10.0.0"> |
||||||
|
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1"> |
||||||
|
<ReportPageAttr> |
||||||
|
<HR/> |
||||||
|
<FR/> |
||||||
|
<HC/> |
||||||
|
<FC/> |
||||||
|
</ReportPageAttr> |
||||||
|
<ColumnPrivilegeControl/> |
||||||
|
<RowPrivilegeControl/> |
||||||
|
<RowHeight defaultValue="723900"> |
||||||
|
<![CDATA[723900,4295838,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight> |
||||||
|
<ColumnWidth defaultValue="2743200"> |
||||||
|
<![CDATA[6627865,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth> |
||||||
|
<CellElementList> |
||||||
|
<C c="0" r="0"> |
||||||
|
<PrivilegeControl/> |
||||||
|
</C> |
||||||
|
<C c="1" r="0"> |
||||||
|
<O t="I"> |
||||||
|
<![CDATA[1]]></O> |
||||||
|
<PrivilegeControl/> |
||||||
|
<Expand/> |
||||||
|
</C> |
||||||
|
<C c="0" r="1"> |
||||||
|
<O t="XMLable" class="com.fr.general.ImageWithSuffix"> |
||||||
|
<FineImage fm="png"> |
||||||
|
<IM> |
||||||
|
<![CDATA[!T4)&qh\-E7h#eD$31&+%7s)Y;?-[s;?-[s;@!I,!!(%jK:;i@"K+gZ5u`*!m@D"-'L<GRe" |
||||||
|
s8V+^efB0"$1Z>tC;K&-B[7`5WK?,Xelf@&8+0+s;]Ad+gFe2#R^R0KRcH9&1(_,Q&m?CF2#j |
||||||
|
L2g`#\[sRl3^"LL;I*q<:m`bRtAnUh^m(8[R[\Qdap[PoDZI+D(a6:V.`2I<j@73SOmdDs,A |
||||||
|
+uOS3sXroCYL"=N7$79<fLEF.)_okG>2?>R^Sd'MY!@@k@GfZiTaUt[[X*Qn(Vqi1,QX!S[g |
||||||
|
X8cV#:o/U(RN!]A[-MCK!$>RYIs_SOW[_9PE1L2Q+u4)L'*_+9GA>FbhqkF3><ITQR#Z&\t@r |
||||||
|
[!>rH*rsS)m6q"c>/>qr/Vjd(?R(*:-.oLG%<9eZ1]Al^J"e-:(+>+Q1NPOaSJo+/S+i4n&T% |
||||||
|
\/J4IBcE%5,_GkC[%jH'kh$2]A+l)FI""N?9]AXFHef&/Q\Pm:q*oGRR,WL<dta:sa5g[sEC!i |
||||||
|
2BKX\fS\?I`Sr$qqD4,Rq:A1qgre[HWS.AXA,T'5S3(`gh<4:2'QhJ%3fl9"m:'tu8Ts:@U: |
||||||
|
VVh>M]A._;-d'aOX+8Xcia>YISk1g?.bi%E?!"e!Dq4AIRE5*J06XZ"l9<VXc0CmdGqRCY\[V |
||||||
|
jH,m1GSaXbIcEJA8MVlg3npt"ps&Q#K6#N$Oa+4nH=;+F`U)c]A/o/l[6`,^T3Lkh5?3_]A^#? |
||||||
|
kP/@Wf,h'#E=eI>/,[%5lSYHM*Gsc;De0X(/o,#On+F;om!UF7s$[mR(>_*`AIpT;n1NSp*r |
||||||
|
5Md*5kOL1RpseeaT5!G,kk_1&F%\@jJs#W%4nbD$X(dC(\O+&KX.Vp>]AY-Lo<Zfr&,N4U<l3 |
||||||
|
\c3%i!rXB<7Y--5>L^V=LM7!$S/!&hR'nH_0hm_H,f=2p+p`R&".Le>"lHKmKAHnSIm69U'g |
||||||
|
LYG,>[,VlJ&!5>PutHqRJ4XG^$7ZL6(YG+-e=+b;LUuH3Zrc58GNFlF?j1-+QXQ(%S6.V?:G |
||||||
|
1jf/GeC6q@_Q>S5"##8tiN'(`qU.T7U?<]A'i8Uhe/g^>U%!HX@Al,.N83)TcC)q$'k_OQ-?: |
||||||
|
_D-F="?_k3O8O[DbknE3?fn3U+EJ3:q;#Xc<us;VN0E_,#[5<%bWR/m"YJ/$/ncCA7S?[j0O |
||||||
|
"7eDS"!*;F5*3mL`XuV$==.VthfIr!KbMS$iZjA,/%hUoiVc!Y-RGQBegW]AOdq1#1ZcM-7T7 |
||||||
|
!1]AKjAoOfF;#;YX8dknF7"f0r)k@UaJen54dIPZFo<,FG*kET--FlL!4pNhXJWUmu)gmTe=% |
||||||
|
;EIA(U#04L!G6;`dfD5U#?b(9UAV,ZsGPK90Bb9k\<VBG[>cA+E^R:k_hA7K7g.e*(3U#a[& |
||||||
|
%V(jo6,q3)+CL/"I32M"cKPBGLn2M%"r'=faV2lDBHCm%MHBI]AOIZj%Z*1+*FVK8J!g'*3c# |
||||||
|
"WMR3*Y&1h_H@PEJC*H;"Y@nbp:f4UB61F[-H4phL"^(VI"gQST8h*)bt+Jo(MXVpo+u.k@X |
||||||
|
tpaqkFs9$<?s@QH[Num^)V"=AgaN!FkbtEsHE-B`J,5!(fUS7'8jaJc~ |
||||||
|
]]></IM> |
||||||
|
</FineImage> |
||||||
|
</O> |
||||||
|
<PrivilegeControl/> |
||||||
|
<Expand/> |
||||||
|
</C> |
||||||
|
</CellElementList> |
||||||
|
<ReportAttrSet> |
||||||
|
<ReportSettings headerHeight="0" footerHeight="0"> |
||||||
|
<PaperSetting/> |
||||||
|
<Background name="ColorBackground" color="-1"/> |
||||||
|
</ReportSettings> |
||||||
|
</ReportAttrSet> |
||||||
|
<PrivilegeControl/> |
||||||
|
</Report> |
||||||
|
<ReportParameterAttr> |
||||||
|
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="true"/> |
||||||
|
<PWTitle> |
||||||
|
<![CDATA[参数]]></PWTitle> |
||||||
|
</ReportParameterAttr> |
||||||
|
<StyleList/> |
||||||
|
<DesignerVersion DesignerVersion="KAA"/> |
||||||
|
<PreviewType PreviewType="0"/> |
||||||
|
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark"> |
||||||
|
<TemplateIdAttMark TemplateId="2c82bd1f-e4a5-4d56-bc03-789dfd00971d"/> |
||||||
|
</TemplateIdAttMark> |
||||||
|
</WorkBook> |
Loading…
Reference in new issue