You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
17 KiB
413 lines
17 KiB
package com.fr.design.mainframe.share.action; |
|
|
|
import com.fr.base.Parameter; |
|
import com.fr.base.ParameterMapNameSpace; |
|
import com.fr.base.TableData; |
|
import com.fr.chart.chartattr.Chart; |
|
import com.fr.chart.chartattr.ChartCollection; |
|
import com.fr.chart.chartdata.TableDataDefinition; |
|
import com.fr.data.impl.NameTableData; |
|
import com.fr.data.impl.TableDataDictionary; |
|
import com.fr.design.actions.UpdateAction; |
|
import com.fr.design.data.DesignTableDataManager; |
|
import com.fr.design.designer.creator.XChartEditor; |
|
import com.fr.design.designer.creator.XCreator; |
|
import com.fr.design.designer.creator.XWTitleLayout; |
|
import com.fr.design.dialog.BasicPane; |
|
import com.fr.design.dialog.DialogActionAdapter; |
|
import com.fr.design.dialog.FineJOptionPane; |
|
import com.fr.design.file.HistoryTemplateListPane; |
|
import com.fr.design.i18n.Toolkit; |
|
import com.fr.design.mainframe.DesignerContext; |
|
import com.fr.design.mainframe.DesignerFrame; |
|
import com.fr.design.mainframe.FormSelection; |
|
import com.fr.design.mainframe.JForm; |
|
import com.fr.design.mainframe.JTemplate; |
|
import com.fr.design.mainframe.share.constants.ShareEntryKey; |
|
import com.fr.design.mainframe.share.select.ComponentTransformerFactory; |
|
import com.fr.design.parameter.ParameterInputPane; |
|
import com.fr.form.FormElementCaseProvider; |
|
import com.fr.form.main.Form; |
|
import com.fr.form.main.FormIO; |
|
import com.fr.form.main.WidgetGather; |
|
import com.fr.form.ui.BaseChartEditor; |
|
import com.fr.form.ui.ChartEditor; |
|
import com.fr.form.ui.DataControl; |
|
import com.fr.form.ui.DictionaryContainer; |
|
import com.fr.form.ui.ElementCaseEditor; |
|
import com.fr.form.ui.PaddingMargin; |
|
import com.fr.form.ui.Widget; |
|
import com.fr.general.IOUtils; |
|
import com.fr.log.FineLoggerFactory; |
|
import com.fr.report.cell.DefaultTemplateCellElement; |
|
import com.fr.report.cell.cellattr.core.group.DSColumn; |
|
import com.fr.script.Calculator; |
|
import com.fr.stable.ArrayUtils; |
|
import com.fr.stable.Constants; |
|
import com.fr.stable.CoreGraphHelper; |
|
import com.fr.stable.DependenceProvider; |
|
import com.fr.stable.ParameterProvider; |
|
import com.fr.stable.StringUtils; |
|
import com.fr.stable.bridge.StableFactory; |
|
import com.fr.stable.script.CalculatorProvider; |
|
import com.fr.stable.script.NameSpace; |
|
import com.fr.third.guava.base.Preconditions; |
|
import com.fr.third.org.apache.commons.lang3.tuple.ImmutableTriple; |
|
import com.fr.third.org.apache.commons.lang3.tuple.Triple; |
|
|
|
import javax.swing.Action; |
|
import javax.swing.UIManager; |
|
import java.awt.Color; |
|
import java.awt.Component; |
|
import java.awt.Dimension; |
|
import java.awt.Graphics2D; |
|
import java.awt.Image; |
|
import java.awt.Rectangle; |
|
import java.awt.event.ActionEvent; |
|
import java.awt.image.BufferedImage; |
|
import java.io.InputStream; |
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.HashMap; |
|
import java.util.HashSet; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.concurrent.Callable; |
|
import java.util.concurrent.FutureTask; |
|
import java.util.concurrent.TimeUnit; |
|
|
|
import static javax.swing.JOptionPane.ERROR_MESSAGE; |
|
|
|
/** |
|
* @Author: Yuan.Wang |
|
* @Date: 2020/11/3 |
|
* 创建组件事件 |
|
*/ |
|
public class CreateComponentAction extends UpdateAction { |
|
ShareUIAspect aspect; |
|
/** |
|
* 等待时间 500 ms. |
|
*/ |
|
private static final int WAIT_TIME = 500; |
|
|
|
private final HashMap<String, Object> parameterMap = new HashMap<>(); |
|
private String[] widgetPara = new String[]{}; |
|
|
|
|
|
public CreateComponentAction(ShareUIAspect aspect) { |
|
this.putValue(Action.SMALL_ICON, null); |
|
this.setName(Toolkit.i18nText("Fine-Design_Share_Create")); |
|
this.aspect = aspect; |
|
} |
|
|
|
@Override |
|
public void actionPerformed(ActionEvent event) { |
|
DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); |
|
// 停止编辑 |
|
JTemplate<?, ?> jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); |
|
jt.stopEditing(); |
|
Form form = null; |
|
try { |
|
form = (Form) jt.getTarget().clone(); |
|
} catch (CloneNotSupportedException e1) { |
|
FineLoggerFactory.getLogger().error(e1.getMessage(), e1); |
|
} |
|
FormSelection selection = ((JForm) jt).getFormDesign().getSelectionModel().getSelection(); |
|
|
|
// 获取选中的组件 |
|
Triple<Widget, XCreator, Rectangle> sharedTriple = ComponentTransformerFactory.getInstance().transform(selection); |
|
if (sharedTriple == null) { |
|
FineJOptionPane.showMessageDialog(designerFrame, Toolkit.i18nText("Fine-Design_Share_Select_Error_Tip"), |
|
Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), ERROR_MESSAGE, IOUtils.readIcon("/com/fr/base/images/share/Information_Icon_warning_normal_32x32.png")); |
|
return; |
|
} |
|
|
|
Widget widget = sharedTriple.getLeft(); |
|
|
|
try { |
|
|
|
if (form == null) { |
|
throw new NullPointerException("tpl get failed"); |
|
} |
|
//准备参数 |
|
prepareParameter(widget, designerFrame); |
|
|
|
//准备的封面大小 |
|
//组件大小 |
|
Rectangle reportRec = FormIO.getContentRect(form); |
|
Image coverImage = toCoverImage(form, sharedTriple, parameterMap, reportRec); |
|
|
|
Object[] compositeArg = new Object[]{jt, widget, sharedTriple.getRight(), coverImage, parameterMap, (ShareUIAspect)aspect}; |
|
HashMap<String, Class> compoClass = new HashMap<String, Class>(); |
|
compoClass.put(Constants.ARG_0, JTemplate.class); |
|
compoClass.put(Constants.ARG_1, Widget.class); |
|
compoClass.put(Constants.ARG_2, Rectangle.class); |
|
compoClass.put(Constants.ARG_3, Image.class); |
|
compoClass.put(Constants.ARG_4, HashMap.class); |
|
compoClass.put(Constants.ARG_5, ShareUIAspect.class); |
|
|
|
BasicPane ShareGuidePane = StableFactory.getMarkedInstanceObjectFromClass(ShareEntryKey.SHARE_GENERATE, compositeArg, compoClass, BasicPane.class); |
|
// ShareGuidePane moduleGuidePane = new ShareGuidePane(jt, widget, sharedTriple.getRight(), coverImage, parameterMap, aspect); |
|
ShareGuidePane.show(); |
|
} catch (Exception e) { |
|
FineJOptionPane.showMessageDialog(designerFrame, Toolkit.i18nText("Fine-Design_Share_Create_Share_Pane_Failed"), |
|
Toolkit.i18nText("Fine-Design_Basic_Error"), ERROR_MESSAGE, UIManager.getIcon("OptionPane.errorIcon")); |
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
} |
|
} |
|
|
|
/** |
|
* 准备参数 |
|
*/ |
|
private void prepareParameter(Widget widget, DesignerFrame designerFrame) { |
|
|
|
final Calculator ca = Calculator.createCalculator(); |
|
Parameter[] tplParameters = ((Form)HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().getTarget()).getParameters(); |
|
widgetPara = new String[]{}; |
|
calWidgetParameter(widget, ca); |
|
List<Parameter> tplPList = new ArrayList<Parameter>(); |
|
//只弹出使用到参数,其他的不要 |
|
for (String wp : widgetPara) { |
|
for (Parameter tplParameter : tplParameters) { |
|
if (wp.length() > 0 && StringUtils.equals(wp, tplParameter.getName())) { |
|
tplPList.add(tplParameter); |
|
} else if (wp.contains("$") && StringUtils.equals(wp.substring(1, wp.length()), tplParameter.getName())){ |
|
tplPList.add(tplParameter); |
|
} |
|
} |
|
} |
|
Parameter[] parameters = new Parameter[tplPList.size()]; |
|
tplPList.toArray(parameters); |
|
if (ArrayUtils.isNotEmpty(parameters)) {// 检查Parameter. |
|
final ParameterInputPane pPane = new ParameterInputPane(parameters); |
|
pPane.showSmallWindow(designerFrame, new DialogActionAdapter() { |
|
|
|
@Override |
|
public void doOk() { |
|
parameterMap.putAll(pPane.update()); |
|
} |
|
}).setVisible(true); |
|
} |
|
} |
|
|
|
private Triple<Widget, XCreator, Rectangle> prepareImageArgs(Triple<Widget, XCreator, Rectangle> pair, Rectangle reportRec) { |
|
|
|
Widget widget = pair.getLeft(); |
|
XCreator xCreator = pair.getMiddle(); |
|
Rectangle rectangle = pair.getRight(); |
|
|
|
if (widget instanceof ElementCaseEditor) { |
|
rectangle = reportRec; |
|
} |
|
return new ImmutableTriple<>(widget, xCreator, rectangle); |
|
} |
|
|
|
/** |
|
* 准备封面 |
|
* <p> |
|
* 操作可能会很耗时,所以加个时间限制 |
|
*/ |
|
private Image toCoverImage(final Form form, |
|
final Triple<Widget, XCreator, Rectangle> triple, |
|
final Map<String, Object> parameterMap, |
|
Rectangle reportRec) { |
|
|
|
final Triple<Widget, XCreator, Rectangle> imageArgs = prepareImageArgs(triple, reportRec); |
|
FutureTask<Image> task = new FutureTask<>(new Callable<Image>() { |
|
@Override |
|
public Image call() throws Exception { |
|
|
|
Preconditions.checkNotNull(imageArgs); |
|
Widget widget = imageArgs.getLeft(); |
|
XCreator xCreator = imageArgs.getMiddle(); |
|
Rectangle rectangle = imageArgs.getRight(); |
|
if (widget instanceof ElementCaseEditor) { |
|
return moduleToImage(form, (ElementCaseEditor) widget, parameterMap, rectangle); |
|
} else { |
|
return componentToImage(xCreator, rectangle); |
|
} |
|
} |
|
}); |
|
Thread imgThread = new Thread(task, "img-thread"); |
|
try { |
|
imgThread.start(); |
|
//等待一段时间 |
|
return task.get(WAIT_TIME, TimeUnit.MILLISECONDS); |
|
} catch (Throwable throwable) { |
|
|
|
FineLoggerFactory.getLogger().debug("--- img generate failed ---"); |
|
FineLoggerFactory.getLogger().debug(throwable.getMessage(), throwable); |
|
FineLoggerFactory.getLogger().debug("--- prepare use default img ---"); |
|
try (InputStream in = this.getClass().getResourceAsStream("/com/fr/base/images/share/default_cover.png")) { |
|
//读取默认图表 |
|
return IOUtils.readImage(in); |
|
} catch (Throwable e) { |
|
//随便画一个 |
|
Rectangle realRec = triple.getRight(); |
|
BufferedImage allInOne = CoreGraphHelper.createBufferedImage(realRec.width, realRec.height); |
|
Graphics2D g2d = allInOne.createGraphics(); |
|
g2d.setBackground(Color.white); |
|
return allInOne; |
|
} |
|
} |
|
} |
|
|
|
private Image componentToImage(Component comp, Rectangle rect) { |
|
|
|
BufferedImage im = new BufferedImage((int) rect.getWidth(), (int) rect.getHeight(), BufferedImage.TYPE_INT_ARGB); |
|
comp.paint(im.getGraphics()); |
|
if (comp instanceof XWTitleLayout) { |
|
XCreator body = ((XWTitleLayout) comp).getBodyCreator(); |
|
if (body instanceof XChartEditor) { |
|
XChartEditor chartEditor = (XChartEditor) body; |
|
Dimension size = chartEditor.getSize(); |
|
BufferedImage chartImage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); |
|
PaddingMargin margin = chartEditor.toData().getMargin(); |
|
chartEditor.getDesignerEditor().paintEditor(chartImage.getGraphics(), size, margin); |
|
im.getGraphics().drawImage(chartImage, 0, chartEditor.getY(), null); |
|
} |
|
} |
|
return im; |
|
} |
|
|
|
//画报表块的缩略图 |
|
private Image moduleToImage(Form form, ElementCaseEditor editor, Map<String, Object> parameterMap, Rectangle rect) { |
|
|
|
if (editor == null) { |
|
return new BufferedImage((int) rect.getWidth(), (int) rect.getHeight(), BufferedImage.TYPE_INT_ARGB); |
|
} |
|
FormElementCaseProvider provider = editor.getElementCase(); |
|
provider.setName(editor.getWidgetName()); |
|
provider.setTabledataSource(form); |
|
final Calculator ca = Calculator.createCalculator(); |
|
NameSpace ns = ParameterMapNameSpace.create(parameterMap); |
|
ca.pushNameSpace(ns); |
|
BufferedImage image = provider.toImage(ca, (int) rect.getWidth(), (int) rect.getHeight(), parameterMap, true); |
|
return image; |
|
|
|
} |
|
|
|
//计算容器内使用到的参数 |
|
private void calWidgetParameter(Widget widget, final Calculator ca) { |
|
|
|
Form.traversalWidget(widget, new WidgetGather() { |
|
|
|
@Override |
|
public void dealWith(Widget widget) { |
|
DataControl dc = (DataControl) widget; |
|
TableData tableData = null; |
|
try { |
|
tableData = ((TableDataDictionary)(((DictionaryContainer) dc).getDictionary())).getTableData(); |
|
} catch (Exception ignore) { |
|
//ignore |
|
} |
|
widgetPara = ArrayUtils.addAll(widgetPara, getTableDataPara(tableData)); |
|
|
|
} |
|
|
|
@Override |
|
public boolean dealWithAllCards() { |
|
return true; |
|
} |
|
|
|
}, DataControl.class); |
|
|
|
Form.traversalWidget(widget, new WidgetGather() { |
|
|
|
@Override |
|
public void dealWith(Widget widget) { |
|
ElementCaseEditor el = (ElementCaseEditor) widget; |
|
widgetPara = ArrayUtils.addAll(widgetPara, getCellParameters(el.getElementCase(), ca)); |
|
widgetPara = ArrayUtils.addAll(widgetPara, el.getElementCase().dependence(ca)); |
|
} |
|
|
|
public boolean dealWithAllCards() { |
|
return true; |
|
} |
|
|
|
}, ElementCaseEditor.class); |
|
|
|
Form.traversalWidget(widget, new WidgetGather() { |
|
|
|
@Override |
|
public void dealWith(Widget widget) { |
|
//算的好麻烦,本来直接用dependence就好了,但是表单的selectedChart中的tabledata只有一个name,里面的_tableData是null、、所以从环境中重新取一下 |
|
Chart selectedChart = ((ChartCollection) ((ChartEditor) widget).getChartCollection()).getSelectedChart(); |
|
TableData tableData = null; |
|
try { |
|
tableData = ((TableDataDefinition)selectedChart.getFilterDefinition()).getTableData(); |
|
} catch (Exception ignore) { |
|
//ignore |
|
} |
|
widgetPara = ArrayUtils.addAll(widgetPara, getTableDataPara(tableData)); |
|
} |
|
|
|
public boolean dealWithAllCards() { |
|
return true; |
|
} |
|
|
|
}, BaseChartEditor.class); |
|
} |
|
|
|
private ArrayList<String> getTableDataName(FormElementCaseProvider el, CalculatorProvider ca) { |
|
Iterator<DefaultTemplateCellElement> it = el.cellIterator(); |
|
ArrayList<String> allECDepends = new ArrayList<String>(); |
|
while(it.hasNext()){ |
|
DefaultTemplateCellElement ce = it.next(); |
|
Object value = ce.getValue(); |
|
//先处理单元格值(图表, 公式) |
|
if(value instanceof DSColumn){ |
|
String[] valueDep = ((DependenceProvider) value).dependence(ca); |
|
allECDepends.addAll(Arrays.asList(valueDep)); |
|
} |
|
} |
|
return allECDepends; |
|
} |
|
|
|
private String[] getTableDataPara(TableData tableData) { |
|
try { |
|
return getTableParameters(((NameTableData) tableData).getName()); |
|
} catch (Exception ignore) { |
|
return new String[]{}; |
|
} |
|
} |
|
|
|
private String[] getCellParameters(FormElementCaseProvider formElementCase,Calculator ca) { |
|
Iterator<DefaultTemplateCellElement> it = formElementCase.cellIterator(); |
|
ArrayList<String> allECDepends = new ArrayList<String>(); |
|
while(it.hasNext()){ |
|
DefaultTemplateCellElement ce = it.next(); |
|
Object value = ce.getValue(); |
|
//处理单元格值(图表, 公式) |
|
if(value instanceof DependenceProvider){ |
|
String[] valueDep = ((DependenceProvider) value).dependence(ca); |
|
allECDepends.addAll(Arrays.asList(valueDep)); |
|
if (value instanceof DSColumn) { |
|
String[] dsPara = getTableParameters(((DSColumn) value).getDSName()); |
|
allECDepends.addAll(Arrays.asList(dsPara)); |
|
} |
|
} |
|
} |
|
//去掉重复的dependence |
|
HashSet<String> removeRepeat = new HashSet<String>(allECDepends); |
|
return removeRepeat.toArray(new String[removeRepeat.size()]); |
|
} |
|
|
|
//通过tableName获取所用参数 |
|
private String[] getTableParameters(String name) { |
|
final Calculator ca = Calculator.createCalculator(); |
|
ParameterProvider[] parameterProviders = new ParameterProvider[]{}; |
|
TableData tableData = DesignTableDataManager.getEditingTableDataSource().getTableData(name); |
|
//只使用自定义数据集的数据 |
|
if (tableData == null) { |
|
return new String[]{}; |
|
} |
|
parameterProviders = tableData.getParameters(ca); |
|
String[] paras = new String[parameterProviders.length]; |
|
for (int i = 0; i < parameterProviders.length; i++) { |
|
paras[i] = parameterProviders[0].getName(); |
|
} |
|
return paras; |
|
} |
|
}
|
|
|