From dde04792c4447fa4e761a9b427d4a19d02df3a35 Mon Sep 17 00:00:00 2001 From: kerry Date: Thu, 4 Feb 2021 10:59:36 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-47034=20FRM=E6=96=B0=E5=89=8D=E7=AB=AF&?= =?UTF-8?q?=E6=96=B0=E8=87=AA=E9=80=82=E5=BA=94=E5=90=88=E5=85=A5=E4=B8=BB?= =?UTF-8?q?JAR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/design/actions/FormFitAttrAction.java | 83 + .../actions/NewFormMobileAttrAction.java | 115 + .../designer/creator/XWAbsoluteLayout.java | 6 +- .../design/designer/creator/XWFitLayout.java | 4 +- .../fr/design/fit/DesignerUIModeConfig.java | 124 + .../com/fr/design/fit/FitStateCompatible.java | 36 + .../java/com/fr/design/fit/JFormType.java | 133 ++ .../main/java/com/fr/design/fit/NewJForm.java | 285 +++ .../src/main/java/com/fr/design/fit/PX.java | 27 + .../com/fr/design/fit/PXReportLengthUNIT.java | 32 + .../ElementEditorExtendDefinePane.java | 91 + .../FRAbsoluteBodyLayoutExtendDefinePane.java | 161 ++ .../FRAbsoluteLayoutExtendDefinePane.java | 27 + .../attrpane/FRFitLayoutExtendDefinePane.java | 246 ++ .../fit/attrpane/PcFitExpandablePane.java | 107 + .../attrpane/RootDesignExtendDefinePane.java | 303 +++ .../design/fit/common/AdaptiveSwitchUtil.java | 225 ++ .../com/fr/design/fit/common/BaseUtils.java | 1266 ++++++++++ .../design/fit/common/FormDesignerUtil.java | 45 + .../com/fr/design/fit/common/LayoutTool.java | 177 ++ .../fr/design/fit/common/NewFormStyle.java | 2030 +++++++++++++++++ .../com/fr/design/fit/common/PaintUtils.java | 835 +++++++ .../fr/design/fit/common/TemplateTool.java | 214 ++ .../fit/menupane/BrowserFitAttrPane.java | 303 +++ .../design/fit/menupane/FitPreviewPane.java | 76 + .../fr/design/fit/menupane/FitRadioGroup.java | 80 + .../design/fit/menupane/FontRadioGroup.java | 17 + .../design/fit/menupane/FormFitAttrPane.java | 58 + .../fr/design/fit/toolbar/SwitchAction.java | 287 +++ .../fr/design/mainframe/CoverReportPane.java | 4 +- .../com/fr/design/mainframe/FormArea.java | 28 +- .../com/fr/design/mainframe/FormDesigner.java | 3 +- .../fr/design/preview/DeveloperPreview.java | 53 + .../design/preview/FormAdaptivePreview.java | 54 + .../design/form/images/developer_preview.png | Bin 0 -> 542 bytes .../form/images/developer_preview24.png | Bin 0 -> 862 bytes .../fr/design/form/images/icon_form_tab.png | Bin 0 -> 130 bytes .../com/fr/design/form/images/icon_switch.png | Bin 0 -> 304 bytes .../form/images/icon_switch_disable.png | Bin 0 -> 296 bytes .../design/form/images/icon_switch_new_ui.png | Bin 0 -> 413 bytes .../design/form/images/icon_switch_old_ui.png | Bin 0 -> 417 bytes .../com/fr/design/form/images/loading.png | Bin 0 -> 7641 bytes .../columnrow/ColumnRowSizingAction.java | 7 +- .../java/com/fr/design/condition/WHPane.java | 10 +- .../fit/AdaptiveCellElementPainter.java | 27 + .../design/fit/grid/AdaptiveGridListener.java | 123 + .../design/fit/grid/ElementCasePaneUtil.java | 186 ++ .../grid/GridHeaderWithBoundMouseHandler.java | 70 + .../fit/grid/GridLimitColumnMouseHandler.java | 194 ++ .../fit/grid/GridLimitRowMouseHandler.java | 190 ++ .../fit/grid/NewFormDesignerGridUI.java | 190 ++ .../fr/design/mainframe/ElementCasePane.java | 9 +- .../form/FormElementCaseDesigner.java | 4 + .../grid/AbstractGridHeaderMouseHandler.java | 9 +- .../com/fr/grid/DefaultGridUIProcessor.java | 10 +- .../src/main/java/com/fr/grid/GridColumn.java | 27 +- .../com/fr/grid/GridColumnMouseHandler.java | 4 - .../main/java/com/fr/grid/GridColumnUI.java | 7 +- .../src/main/java/com/fr/grid/GridCorner.java | 3 +- .../src/main/java/com/fr/grid/GridHeader.java | 3 +- .../java/com/fr/grid/GridMouseAdapter.java | 3 +- .../src/main/java/com/fr/grid/GridRow.java | 18 +- .../src/main/java/com/fr/grid/GridRowUI.java | 8 +- .../src/main/java/com/fr/grid/GridUtils.java | 5 +- .../fr/start/module/DesignerActivator.java | 15 +- 65 files changed, 8575 insertions(+), 82 deletions(-) create mode 100644 designer-form/src/main/java/com/fr/design/actions/FormFitAttrAction.java create mode 100644 designer-form/src/main/java/com/fr/design/actions/NewFormMobileAttrAction.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/FitStateCompatible.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/JFormType.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/NewJForm.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/PX.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/PXReportLengthUNIT.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteLayoutExtendDefinePane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/attrpane/RootDesignExtendDefinePane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/FormDesignerUtil.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/LayoutTool.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/menupane/BrowserFitAttrPane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/menupane/FitPreviewPane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/menupane/FitRadioGroup.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/menupane/FontRadioGroup.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/menupane/FormFitAttrPane.java create mode 100644 designer-form/src/main/java/com/fr/design/fit/toolbar/SwitchAction.java create mode 100644 designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java create mode 100644 designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java create mode 100755 designer-form/src/main/resources/com/fr/design/form/images/developer_preview.png create mode 100755 designer-form/src/main/resources/com/fr/design/form/images/developer_preview24.png create mode 100755 designer-form/src/main/resources/com/fr/design/form/images/icon_form_tab.png create mode 100644 designer-form/src/main/resources/com/fr/design/form/images/icon_switch.png create mode 100755 designer-form/src/main/resources/com/fr/design/form/images/icon_switch_disable.png create mode 100755 designer-form/src/main/resources/com/fr/design/form/images/icon_switch_new_ui.png create mode 100755 designer-form/src/main/resources/com/fr/design/form/images/icon_switch_old_ui.png create mode 100644 designer-form/src/main/resources/com/fr/design/form/images/loading.png create mode 100644 designer-realize/src/main/java/com/fr/design/fit/AdaptiveCellElementPainter.java create mode 100644 designer-realize/src/main/java/com/fr/design/fit/grid/AdaptiveGridListener.java create mode 100644 designer-realize/src/main/java/com/fr/design/fit/grid/ElementCasePaneUtil.java create mode 100644 designer-realize/src/main/java/com/fr/design/fit/grid/GridHeaderWithBoundMouseHandler.java create mode 100644 designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitColumnMouseHandler.java create mode 100644 designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitRowMouseHandler.java create mode 100644 designer-realize/src/main/java/com/fr/design/fit/grid/NewFormDesignerGridUI.java diff --git a/designer-form/src/main/java/com/fr/design/actions/FormFitAttrAction.java b/designer-form/src/main/java/com/fr/design/actions/FormFitAttrAction.java new file mode 100644 index 000000000..2828abef2 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/actions/FormFitAttrAction.java @@ -0,0 +1,83 @@ +package com.fr.design.actions; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.UIDialog; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.fit.NewJForm; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.MenuKeySet; +import com.fr.report.fit.FitProvider; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +/** + * Created by Administrator on 2015/7/6 0006. + */ +public class FormFitAttrAction extends JTemplateAction { + private static final MenuKeySet REPORT_FIT_ATTR_ELEMENTCASE = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'T'; + } + + @Override + public String getMenuName() { + return DesignerUIModeConfig.getInstance().newUIMode() ? + com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_PC_Adaptive_Attr") : + com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_PC_Element_Case_Fit_Attr"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + + public FormFitAttrAction(JTemplate jTemplate) { + super(jTemplate); + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(REPORT_FIT_ATTR_ELEMENTCASE); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(DesignerUIModeConfig.getInstance().newUIMode() ? + "/com/fr/design/images/reportfit/fit.png": + "/com/fr/design/images/reportfit/fit"); + } + + /** + * Action触发事件 + * + * @param e 事件 + */ + @Override + public void actionPerformed(ActionEvent e) { + final JTemplate jwb = getEditingComponent(); + if (jwb == null || !(jwb instanceof NewJForm)) { + return; + } + final FitProvider wbTpl = (FitProvider) jwb.getTarget(); + ReportFitAttr fitAttr = wbTpl.getReportFitAttr(); + NewJForm newJForm = (NewJForm) jwb; + BasicBeanPane attrPane = newJForm.getJFormType().obtainAttrPane(newJForm); + showFitDialog(fitAttr, jwb, wbTpl, attrPane); + } + + private void showFitDialog(ReportFitAttr fitAttr, final JTemplate jwb, final FitProvider wbTpl, final BasicBeanPane attrPane) { + attrPane.populateBean(fitAttr); + UIDialog dialog = attrPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + wbTpl.setReportFitAttr(attrPane.updateBean()); + jwb.fireTargetModified(); + } + }); + dialog.setVisible(true); + } +} diff --git a/designer-form/src/main/java/com/fr/design/actions/NewFormMobileAttrAction.java b/designer-form/src/main/java/com/fr/design/actions/NewFormMobileAttrAction.java new file mode 100644 index 000000000..17ec76b83 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/actions/NewFormMobileAttrAction.java @@ -0,0 +1,115 @@ +package com.fr.design.actions; + + +import com.fr.base.iofile.attr.MobileOnlyTemplateAttrMark; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteBodyLayout; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.fit.NewJForm; +import com.fr.design.fit.common.AdaptiveSwitchUtil; +import com.fr.design.fit.common.TemplateTool; +import com.fr.design.form.mobile.FormMobileAttrPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.FormArea; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.file.FILE; +import com.fr.form.main.Form; +import com.fr.form.main.mobile.FormMobileAttr; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.stable.StringUtils; + +import java.awt.event.ActionEvent; + +/** + * Created by fanglei on 2016/11/14. + */ +@EnableMetrics +public class NewFormMobileAttrAction extends FormMobileAttrAction { + + public NewFormMobileAttrAction(JForm jf) { + super(jf); + } + + /** + * 执行动作 + * + * @return 是否执行成功 + */ + @Override + public void actionPerformed(ActionEvent e) { + final JForm jf = getEditingComponent(); + if (jf == null) { + return; + } + final Form formTpl = jf.getTarget(); + FormMobileAttr mobileAttr = formTpl.getFormMobileAttr(); + + final FormMobileAttrPane mobileAttrPane = new FormMobileAttrPane(); + mobileAttrPane.populateBean(mobileAttr); + + final boolean oldMobileOnly = mobileAttr.isMobileOnly(); + final boolean oldAdaptive = mobileAttr.isAdaptivePropertyAutoMatch(); + BasicDialog dialog = mobileAttrPane.showWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + FormMobileAttr formMobileAttr = mobileAttrPane.updateBean(); + if (formMobileAttr.isMobileOnly() && jf.getTarget().getAttrMark(MobileOnlyTemplateAttrMark.XML_TAG) == null) { + // 如果是老模板,选择手机专属之后需要另存为 + FILE editingFILE = jf.getEditingFILE(); + if (editingFILE != null && editingFILE.exists()) { + String fileName = editingFILE.getName().substring(0, editingFILE.getName().length() - jf.suffix().length()) + "_mobile"; + if (!jf.saveAsTemplate(true, fileName)) { + return; + } + } + // 放到后面。如果提前 return 了,则仍然处于未设置状态,不要添加 + jf.getTarget().addAttrMark(new MobileOnlyTemplateAttrMark()); + } + // 设置移动端属性并刷新界面 + formTpl.setFormMobileAttr(formMobileAttr); // 会调整 body 的自适应布局,放到最后 + boolean changeSize = (!oldMobileOnly && formMobileAttr.isMobileOnly()) || (oldMobileOnly && !formMobileAttr.isMobileOnly()); + if (changeSize) { + ((FormArea)jf.getFormDesign().getParent()).onMobileAttrModified(); + } + //改变布局为自适应布局,只在移动端属性设置保存后改变一次 + boolean changeLayout = !oldAdaptive && formMobileAttr.isAdaptivePropertyAutoMatch(); + if (changeLayout) { + jf.getFormDesign().getSelectionModel().setSelectedCreator(jf.getFormDesign().getRootComponent()); + doChangeBodyLayout(); + WidgetPropertyPane.getInstance().refreshDockingView(); + } + jf.fireTargetModified(); + FILE editingFILE = jf.getEditingFILE(); + if(editingFILE != null && editingFILE.exists()){ + JForm jForm = getEditingComponent(); + TemplateTool.saveForm(jForm); + if (jForm instanceof NewJForm) { + AdaptiveSwitchUtil.switch2OldUI(); + } + }else { + AdaptiveSwitchUtil.switch2OldUIMode(); + NewJForm mobileJForm = new NewJForm(jf.getTarget(), jf.getEditingFILE()); + //设置临时的id,和新建的模板区分 + mobileJForm.getTarget().setTemplateID(StringUtils.EMPTY); + TemplateTool.resetTabPaneEditingTemplate(mobileJForm); + TemplateTool.activeAndResizeTemplate(mobileJForm); + } + } + }); + dialog.setVisible(true); + } + + private void doChangeBodyLayout(){ + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + XLayoutContainer rootLayout = formDesigner.getRootComponent(); + if (rootLayout.getComponentCount() == 1 && rootLayout.getXCreator(0).acceptType(XWAbsoluteBodyLayout.class)) { + rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(0); + } + ((XWFitLayout)formDesigner.getRootComponent()).switch2FitBodyLayout(rootLayout); + } +} + diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java index da268b0e6..86d9366de 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XWAbsoluteLayout.java @@ -14,6 +14,7 @@ import com.fr.design.designer.beans.location.Direction; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; import com.fr.design.designer.properties.mobile.MobileBooKMarkUsePropertyUI; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.form.layout.FRAbsoluteLayout; import com.fr.design.form.util.FormDesignerUtils; import com.fr.design.form.util.XCreatorConstants; @@ -30,7 +31,6 @@ import com.fr.form.ui.Widget; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; import com.fr.form.ui.container.WLayout; -import com.fr.general.FRScreen; import com.fr.general.IOUtils; import com.fr.share.ShareConstants; @@ -111,7 +111,7 @@ public class XWAbsoluteLayout extends XLayoutContainer { private void initPercent(WAbsoluteLayout widget) { Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension scrnsize = toolkit.getScreenSize(); - double screenValue = FRScreen.getDesignScreenByDimension(scrnsize).getValue(); + double screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(scrnsize).getValue(); if (!AssistUtils.equals(screenValue, FormArea.DEFAULT_SLIDER)) { this.setContainerPercent(screenValue / FormArea.DEFAULT_SLIDER); } @@ -247,7 +247,7 @@ public class XWAbsoluteLayout extends XLayoutContainer { */ @Override public void updateChildBound(int minHeight) { - double prevContainerPercent = FRScreen.getDesignScreenByDimension(toData().getDesigningResolution()).getValue() / FormArea.DEFAULT_SLIDER; + double prevContainerPercent = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(toData().getDesigningResolution()).getValue() / FormArea.DEFAULT_SLIDER; if (toData().getCompState() == 0 && !AssistUtils.equals(containerPercent, prevContainerPercent)) { for (int i = 0; i < this.getComponentCount(); i++) { XCreator creator = getXCreator(i); diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java index 6d55c658f..450dfeae3 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java @@ -6,6 +6,7 @@ import com.fr.design.designer.beans.location.Direction; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; import com.fr.design.designer.properties.mobile.BodyMobilePropertyUI; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.form.layout.FRFitLayout; import com.fr.design.fun.WidgetPropertyUIProvider; import com.fr.design.mainframe.FormArea; @@ -20,7 +21,6 @@ import com.fr.form.ui.container.WFitLayout; import com.fr.form.ui.container.WLayout; import com.fr.general.ComparatorUtils; import com.fr.general.FRLogger; -import com.fr.general.FRScreen; import com.fr.stable.ArrayUtils; import com.fr.stable.AssistUtils; import javax.swing.JOptionPane; @@ -72,7 +72,7 @@ public class XWFitLayout extends XLayoutContainer { private void initPercent(){ Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension scrnsize = toolkit.getScreenSize(); - double screenValue = FRScreen.getDesignScreenByDimension(scrnsize).getValue(); + double screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(scrnsize).getValue(); if (!AssistUtils.equals(FormArea.DEFAULT_SLIDER, screenValue)) { this.setContainerPercent(screenValue / FormArea.DEFAULT_SLIDER); } diff --git a/designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java b/designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java new file mode 100644 index 000000000..5e743d383 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java @@ -0,0 +1,124 @@ +package com.fr.design.fit; + +import com.fr.base.ScreenResolution; +import com.fr.design.fun.ReportLengthUNITProvider; +import com.fr.design.unit.UnitConvertUtil; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRScreen; +import com.fr.stable.Constants; + +import java.awt.Dimension; + +/** + * Created by kerry on 2020-06-05 + */ +public class DesignerUIModeConfig { + private DesignerUIMode mode = DesignerUIMode.NEW_UI_MODE; + + private static class DesignerUIModeConfigHolder { + private static final DesignerUIModeConfig designerUIModeConfig = new DesignerUIModeConfig(); + } + + private DesignerUIModeConfig() { + + } + + public static DesignerUIModeConfig getInstance() { + return DesignerUIModeConfigHolder.designerUIModeConfig; + } + + + /** + * 判断是否是新ui模式 + * + * @return boolean + */ + public boolean newUIMode() { + return ComparatorUtils.equals(DesignerUIMode.NEW_UI_MODE, mode); + } + + /** + * 设置新ui模式 + */ + public void setNewUIMode() { + this.mode = DesignerUIMode.NEW_UI_MODE; + } + + /** + * 设置老ui模式 + */ + public void setOldUIMode() { + this.mode = DesignerUIMode.OLD_UI_MODE; + } + + /** + * 解析不同模式下的尺寸单位 + * + * @param unitType 尺寸类型 + * @return ReportLengthUNITProvider对象 + */ + public ReportLengthUNITProvider parseLengthUNIT(int unitType) { + return mode.parseLengthUNIT(unitType); + } + + /** + * 获取不同模式下的屏幕分辨率 + * + * @return 分辨率 + */ + public int getScreenResolution() { + return mode.getScreenResolution(); + } + + /** + * 根据屏幕尺寸获取设计时的FRScreen + * + * @param screen 屏幕尺寸 + * @return FRScreen + */ + public FRScreen getDesignScreenByDimension(Dimension screen) { + return mode.getDesignScreenByDimension(screen); + } + + private enum DesignerUIMode { + OLD_UI_MODE { + @Override + protected ReportLengthUNITProvider parseLengthUNIT(int unitType) { + return UnitConvertUtil.parseLengthUNIT(unitType); + } + + @Override + protected FRScreen getDesignScreenByDimension(Dimension screen) { + return FRScreen.getDesignScreenByDimension(screen); + } + + @Override + protected int getScreenResolution() { + return ScreenResolution.getScreenResolution(); + } + }, + NEW_UI_MODE { + @Override + protected ReportLengthUNITProvider parseLengthUNIT(int unitType) { + return new PXReportLengthUNIT(); + } + + @Override + protected FRScreen getDesignScreenByDimension(Dimension screen) { + return FRScreen.p1440; + } + + @Override + protected int getScreenResolution() { + return Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION; + } + }; + + protected abstract ReportLengthUNITProvider parseLengthUNIT(int unitType); + + protected abstract FRScreen getDesignScreenByDimension(Dimension screen); + + protected abstract int getScreenResolution(); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/FitStateCompatible.java b/designer-form/src/main/java/com/fr/design/fit/FitStateCompatible.java new file mode 100644 index 000000000..06934e98e --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/FitStateCompatible.java @@ -0,0 +1,36 @@ +package com.fr.design.fit; + +/** + * Created by kerry on 2020-04-27 + */ +public enum FitStateCompatible { + DOUBLE_FIT(2, 0), + HOR_FIT(1, 1), + NO_FIT(3, 2); + + private final int newType; + private final int oldType; + + FitStateCompatible(int oldType, int newType) { + this.oldType = oldType; + this.newType = newType; + } + + public static int getNewTypeFromOld(int oldValue) { + for (FitStateCompatible compatible : values()) { + if (compatible.oldType == oldValue) { + return compatible.newType; + } + } + return DOUBLE_FIT.newType; + } + + public static int getOldTypeFromNew(int newValue) { + for (FitStateCompatible compatible : values()) { + if (compatible.newType == newValue) { + return compatible.oldType; + } + } + return DOUBLE_FIT.oldType; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/JFormType.java b/designer-form/src/main/java/com/fr/design/fit/JFormType.java new file mode 100644 index 000000000..7fe795c6f --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/JFormType.java @@ -0,0 +1,133 @@ +package com.fr.design.fit; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.fit.common.AdaptiveSwitchUtil; +import com.fr.form.fit.NewFormMarkAttr; +import com.fr.form.fit.config.FormFitConfig; +import com.fr.design.fit.menupane.FormFitAttrPane; +import com.fr.design.fun.PreviewProvider; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.preview.FormAdaptivePreview; +import com.fr.design.preview.FormPreview; +import com.fr.design.report.fit.menupane.ReportFitAttrPane; +import com.fr.form.main.Form; +import com.fr.report.fit.ReportFitAttr; + +public enum JFormType { + OLD_TYPE(0, new FormPreview()) { + @Override + public void switchUI() { + AdaptiveSwitchUtil.switch2OldUI(); + } + + @Override + public void switchUIMode() { + AdaptiveSwitchUtil.switch2OldUIMode(); + } + + @Override + public ReportFitAttr obtainFitAttr() { + return FormFitConfig.getInstance().getOldFitAttr(); + } + + @Override + public void updateFitAttr(ReportFitAttr attr) { + FormFitConfig.getInstance().setOldFitAttr(attr); + } + + @Override + public BasicBeanPane obtainAttrPane(NewJForm newJForm) { + return new ReportFitAttrPane(); + } + + }, + NEW_TYPE(1, new FormAdaptivePreview()) { + @Override + public void switchUI() { + AdaptiveSwitchUtil.switch2NewUI(); + } + + @Override + public void switchUIMode() { + AdaptiveSwitchUtil.switch2NewUIMode(); + } + + @Override + public ReportFitAttr obtainFitAttr() { + return FormFitConfig.getInstance().getNewFitAttr(); + } + + @Override + public void updateFitAttr(ReportFitAttr attr) { + FormFitConfig.getInstance().setNewFitAttr(attr); + } + + @Override + public BasicBeanPane obtainAttrPane(NewJForm newJForm) { + return new FormFitAttrPane(newJForm); + } + }; + private int type; + private boolean newType; + private PreviewProvider previewType; + + JFormType(int type, PreviewProvider previewType) { + this.type = type; + this.newType = (type == 1); + this.previewType = previewType; + } + + public int getType() { + return type; + } + + public boolean isNewType() { + return newType; + } + + public PreviewProvider getPreviewType() { + return previewType; + } + + public abstract void switchUI(); + + public abstract void switchUIMode(); + + public abstract ReportFitAttr obtainFitAttr(); + + public abstract void updateFitAttr(ReportFitAttr attr); + + public abstract BasicBeanPane obtainAttrPane(NewJForm newJForm); + + /** + * @Description: 更新模板的标志位 + * @param jTemplate + * @return: + * @Author: Henry.Wang + * @date: 2020/12/17 16:17 + */ + public void updateJFromTemplateType(JTemplate jTemplate) { + if (jTemplate instanceof NewJForm) { + NewJForm newJForm = (NewJForm) jTemplate; + Form form = newJForm.getTarget(); + NewFormMarkAttr newFormMarkAttr = form.getAttrMark(NewFormMarkAttr.XML_TAG); + if (newFormMarkAttr == null) { + newFormMarkAttr = new NewFormMarkAttr(this.getType()); + form.addAttrMark(newFormMarkAttr); + } + newFormMarkAttr.setType(this.getType()); + newJForm.setJFormType(this); + } + } + + /** + * @Description: 更新预览方式 + * @param jTemplate + * @return: + * @Author: Henry.Wang + * @date: 2020/12/17 16:17 + */ + public void updatePreviewType(JTemplate jTemplate) { + jTemplate.setPreviewType(this.getPreviewType()); + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/NewJForm.java b/designer-form/src/main/java/com/fr/design/fit/NewJForm.java new file mode 100644 index 000000000..4df8b4386 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/NewJForm.java @@ -0,0 +1,285 @@ +package com.fr.design.fit; + +import com.fr.base.DynamicUnitList; +import com.fr.design.actions.TemplateParameterAction; +import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.adapters.layout.FRFitLayoutAdapter; +import com.fr.design.designer.beans.events.DesignerEditListener; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.creator.*; +import com.fr.design.fit.common.AdaptiveSwitchUtil; +import com.fr.design.fit.common.LayoutTool; +import com.fr.form.fit.NewFormMarkAttr; +import com.fr.design.fit.common.TemplateTool; +import com.fr.design.actions.FormFitAttrAction; +import com.fr.design.actions.NewFormMobileAttrAction; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.preview.DeveloperPreview; +import com.fr.design.preview.FormAdaptivePreview; +import com.fr.design.fit.toolbar.SwitchAction; +import com.fr.design.fun.PreviewProvider; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.menu.ShortCut; +import com.fr.design.preview.FormPreview; +import com.fr.design.preview.MobilePreview; +import com.fr.design.utils.ComponentUtils; +import com.fr.file.FILE; +import com.fr.form.FormElementCaseProvider; +import com.fr.form.main.Form; +import com.fr.form.main.mobile.FormMobileAttr; +import com.fr.form.ui.ElementCaseEditor; +import com.fr.stable.ArrayUtils; + +import javax.swing.JComponent; +import java.awt.Dimension; +import java.awt.Rectangle; + + +/** + * Created by kerry on 2020-05-31 + */ +public class NewJForm extends JForm { + private static final int FUZZY_EDGE = 10; + private static final int TITLE_HEIGHT = 36; + private JFormType jFormType; + + public NewJForm() { + super(); + init(); + changePaneSize(); + } + + public NewJForm(Form form, FILE file) { + super(form, file); + if (DesignerUIModeConfig.getInstance().newUIMode()) { + init(); + } + changePaneSize(); + } + + /** + * @Description:改变body的大小,主要针对新模式下打开老模板出现截断的情况 + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/9/13 23:23 + */ + private void changePaneSize() { + if (mobileForm()) + return; + NewFormMarkAttr newFormMarkAttr = this.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG); + if (newFormMarkAttr.isNotSetOriginSize()) { + newFormMarkAttr.setBodyHeight(LayoutTool.getBodyHeight(this)); + newFormMarkAttr.setBodyWidth(LayoutTool.getBodyWidth(this)); + return; + } + //这种是针对body为绝对布局时,可能出现截断的情况 + if (LayoutTool.absoluteLayoutForm(this)) { + int bodyHeight = newFormMarkAttr.getBodyHeight(); + int bodyWidth = newFormMarkAttr.getBodyWidth(); + Rectangle rectangle = LayoutTool.getAbsoluteBodySize(this); + if (!isNewJFrom() && (rectangle.width != bodyWidth || rectangle.height != bodyHeight)) { + TemplateTool.onlyChangeAbsoluteBodySize(bodyHeight, bodyWidth, this); + } else if(isNewJFrom()){ + if (rectangle.width > bodyWidth && rectangle.height > bodyHeight) { + TemplateTool.onlyChangeAbsoluteBodySize(rectangle.height, rectangle.width, this); + } else if (rectangle.width > bodyWidth) { + TemplateTool.onlyChangeAbsoluteBodySize(bodyHeight, rectangle.width, this); + } else if (rectangle.height > bodyHeight) { + TemplateTool.onlyChangeAbsoluteBodySize(rectangle.height, bodyWidth, this); + } + } + } else if (AdaptiveSwitchUtil.isSwitchJFromIng()) { + //这种是针对body中有绝对画布块,导致截断的情况 + double scale = LayoutTool.getContainerPercent(); + if (isNewJFrom()) { + LayoutTool.scaleAbsoluteBlockComponentsBounds(this.getFormDesign().getRootComponent(), 1 / scale); + } else { + LayoutTool.scaleAbsoluteBlockComponentsBounds(this.getFormDesign().getRootComponent(), scale); + } + } + } + + public JFormType getJFormType() { + return this.jFormType; + } + + public void setJFormType(JFormType jFormType) { + this.jFormType = jFormType; + } + + + /** + * 模板菜单 + * + * @return 返回菜单 + */ + @Override + public ShortCut[] shortcut4TemplateMenu() { + if (this.index == FORM_TAB) { + return ArrayUtils.addAll(new ShortCut[]{new TemplateParameterAction(this), new NewFormMobileAttrAction(this), new FormFitAttrAction(this)}, new ShortCut[0]); + } else { + return ArrayUtils.addAll(new ShortCut[]{new TemplateParameterAction(this), new NewFormMobileAttrAction(this), new FormFitAttrAction(this)}, this.getElementCaseDesign().shortcut4TemplateMenu()); + } + } + + + private void init() { + this.getFormDesign().addDesignerEditListener(new DesignerEditListener() { + private Rectangle oldRec; + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getAffectedCreator() == null) { + return; + } + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) { + XComponent affectedCreator = evt.getAffectedCreator(); + if (isElementCase((JComponent) affectedCreator)) { + processAbsorbingEffect((XWTitleLayout) affectedCreator); + } + } + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + XComponent affectedCreator = evt.getAffectedCreator(); + oldRec = new Rectangle(affectedCreator.getBounds()); + } + } + + private boolean isElementCase(JComponent component) { + return component.getComponents().length > 0 && component.getComponent(0) instanceof XElementCase; + } + + private void processAbsorbingEffect(XWTitleLayout xwTitleLayout) { + NewJForm.this.getFormDesign().repaint(); + Dimension bound = new Dimension(xwTitleLayout.getSize()); + ElementCaseEditor elementCaseEditor = (ElementCaseEditor) xwTitleLayout.toData().getBodyBoundsWidget().getWidget(); + FormElementCaseProvider elementCase = elementCaseEditor.getElementCase(); + if (oldRec.width != bound.width) { + processColumnAbsorbingEffect(xwTitleLayout, elementCase.getColumnWidthList_DEC(), bound); + oldRec.width = bound.width; + } + if (oldRec.height != bound.height) { + processRowAbsorbingEffect(xwTitleLayout, elementCase.getRowHeightList_DEC(), bound); + oldRec.height = bound.height; + } + NewJForm.this.getFormDesign().refreshDesignerUI(); + } + + private boolean hasTitle(XWTitleLayout xwTitleLayout) { + return xwTitleLayout.getComponentCount() > 1; + } + + private void processColumnAbsorbingEffect(XWTitleLayout xwTitleLayout, DynamicUnitList columnUnitList, Dimension bound) { + int temp = 0; + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution();; + int difference = 0; + int i = 0; + while (true) { + if (i < columnUnitList.size()) { + temp += columnUnitList.get(i++).toPixI(resolution); + } else { + //在处理吸附效果时,columnUnitList数组长度可能比实际显示的列数少,所以用默认值来补充 + temp += columnUnitList.getDefaultUnit().toPixI(resolution); + } + if (bound.width - temp < 0) { + break; + } + if (bound.width - temp < FUZZY_EDGE) { + difference = bound.width - temp; + bound.width = temp; + break; + } + } + fixLayout(xwTitleLayout, bound, difference, 0); + } + + private void processRowAbsorbingEffect(XWTitleLayout xwTitleLayout, DynamicUnitList rowUnitList, Dimension bound) { + int temp = hasTitle(xwTitleLayout) ? TITLE_HEIGHT : 0; + int resolution =DesignerUIModeConfig.getInstance().getScreenResolution(); + int difference = 0; + int i = 0; + while (true) { + if (i < rowUnitList.size()) { + temp += rowUnitList.get(i++).toPixI(resolution); + } else { + //在处理吸附效果时,rowUnitList数组长度可能比实际显示的行数少,所以用默认值来补充 + temp += rowUnitList.getDefaultUnit().toPixI(resolution); + } + if (bound.height - temp < 0) { + break; + } + if (bound.height - temp < FUZZY_EDGE) { + difference = bound.height - temp; + bound.height = temp; + break; + } + } + fixLayout(xwTitleLayout, bound, difference, 1); + } + + + private void fixLayout(XWTitleLayout xwTitleLayout, Dimension bound, int difference, int row) { + Rectangle backupBounds = getBound(xwTitleLayout); + xwTitleLayout.setSize(bound); + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + LayoutAdapter adapter = AdapterBus.searchLayoutAdapter(formDesigner, xwTitleLayout); + if (adapter instanceof FRFitLayoutAdapter) { + FRFitLayoutAdapter layoutAdapter = (FRFitLayoutAdapter) adapter; + layoutAdapter.setEdit(true); + layoutAdapter.calculateBounds(backupBounds, xwTitleLayout.getBounds(), xwTitleLayout, row, difference); + } + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xwTitleLayout); + if (parent != null && parent.toData() != null) { + parent.toData().setBounds(xwTitleLayout.toData(), xwTitleLayout.getBounds()); + } + + } + + }); + } + + + public Rectangle getBound(XWTitleLayout creator) { + Rectangle bounds = new Rectangle(creator.getBounds()); + if (creator.getParent() == null) { + return bounds; + } + Rectangle rec = ComponentUtils.getRelativeBounds(creator.getParent()); + bounds.x += rec.x; + bounds.y += rec.y; + return bounds; + + } + + @Override + public PreviewProvider[] supportPreview() { + if (isNewJFrom()) { + return new PreviewProvider[]{new FormAdaptivePreview(), new DeveloperPreview(), new MobilePreview()}; + } + return new PreviewProvider[]{new FormPreview(), new MobilePreview()}; + } + + public boolean mobileForm() { + FormMobileAttr mobileAttr = this.getTarget().getFormMobileAttr(); + if (mobileAttr.isMobileOnly() && mobileAttr.isAdaptivePropertyAutoMatch()) { + return true; + } + return false; + } + + private SwitchAction switchAction; + + public UIButton[] createExtraButtons() { + UIButton[] extraButtons = super.createExtraButtons(); + switchAction = new SwitchAction(); + return ArrayUtils.addAll(extraButtons, new UIButton[]{switchAction.getToolBarButton()}); + } + + + public boolean isNewJFrom() { + return jFormType == null || jFormType.isNewType(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/PX.java b/designer-form/src/main/java/com/fr/design/fit/PX.java new file mode 100644 index 000000000..720268ea6 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/PX.java @@ -0,0 +1,27 @@ +package com.fr.design.fit; + +import com.fr.stable.Constants; +import com.fr.stable.unit.LEN_UNIT; + +public class PX extends LEN_UNIT { + private static final long FU_SCALE = 36576L; + + public PX(float var1) { + super(var1); + } + + + public boolean equals(Object var1) { + return var1 instanceof PX && super.equals(var1); + } + + protected long getMoreFUScale() { + int dpi = DesignerUIModeConfig.getInstance().getScreenResolution(); + return FU_SCALE / dpi; + } + + public static double toPixWithResolution(double value, int resolution) { + return value * resolution / Constants.FR_PAINT_RESOLUTION; + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/PXReportLengthUNIT.java b/designer-form/src/main/java/com/fr/design/fit/PXReportLengthUNIT.java new file mode 100644 index 000000000..8d8f1de16 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/PXReportLengthUNIT.java @@ -0,0 +1,32 @@ +package com.fr.design.fit; + +import com.fr.design.fun.impl.AbstractReportLengthUNITProvider; +import com.fr.stable.unit.UNIT; + +/** + * Created by kerry on 2020-04-09 + */ +public class PXReportLengthUNIT extends AbstractReportLengthUNITProvider { + public static final short UNIT_TYPE = 4; + + @Override + public String unitText() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Px"); + } + + @Override + public int unitType() { + return UNIT_TYPE; + } + + @Override + public float unit2Value4Scale(UNIT value) { + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); + return value.toPixF(resolution); + } + + @Override + public UNIT float2UNIT(float value) { + return new PX(value); + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java b/designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java new file mode 100644 index 000000000..3d25590f4 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java @@ -0,0 +1,91 @@ +package com.fr.design.fit.attrpane; + +import com.fr.design.designer.IntervalConstants; +import com.fr.design.designer.creator.CRPropertyDescriptor; +import com.fr.design.designer.creator.PropertyGroupPane; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XElementCase; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.widget.accessibles.AccessibleElementCaseToolBarEditor; +import com.fr.design.widget.ui.designer.component.PaddingBoundPane; +import com.fr.design.widget.ui.designer.layout.WTitleLayoutDefinePane; +import com.fr.form.ui.ElementCaseEditor; +import com.fr.form.web.FormToolBarManager; +import com.fr.general.ComparatorUtils; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-04-09 + */ +public class ElementEditorExtendDefinePane extends WTitleLayoutDefinePane { + private PaddingBoundPane paddingBoundPane; + private AccessibleElementCaseToolBarEditor elementCaseToolBarEditor; + private PropertyGroupPane extraPropertyGroupPane; + private PcFitExpandablePane pcFitExpandablePane; + + private static final String FIT_STATE_PC = "fitStateInPC"; + + public ElementEditorExtendDefinePane(XCreator xCreator) { + super(xCreator); + } + + protected JPanel createCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + paddingBoundPane = new PaddingBoundPane(); + elementCaseToolBarEditor = new AccessibleElementCaseToolBarEditor(); + Component[][] components = new Component[][]{ + new Component[]{paddingBoundPane, null}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_EC_Toolbar")), elementCaseToolBarEditor}, + }; + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); + CRPropertyDescriptor[] extraTableEditor = removeOldFitEditor(((XElementCase) creator).getExtraTableEditor()); + extraPropertyGroupPane = new PropertyGroupPane(extraTableEditor, creator); + centerPane.add(panel, BorderLayout.NORTH); + if (extraTableEditor.length > 0) { + centerPane.add(extraPropertyGroupPane, BorderLayout.CENTER); + } + pcFitExpandablePane = new PcFitExpandablePane(this); + centerPane.add(pcFitExpandablePane, BorderLayout.SOUTH); + return centerPane; + } + + private CRPropertyDescriptor[] removeOldFitEditor(CRPropertyDescriptor[] extraTableEditor) { + List list = new ArrayList(); + for (CRPropertyDescriptor crPropertyDescriptor : extraTableEditor) { + if (!ComparatorUtils.equals(FIT_STATE_PC, crPropertyDescriptor.getName())) { + list.add(crPropertyDescriptor); + } + } + return list.toArray(new CRPropertyDescriptor[list.size()]); + } + + protected ElementCaseEditor updateSubBean() { + ElementCaseEditor elementCaseEditor = (ElementCaseEditor) creator.toData(); + if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate"))) { + paddingBoundPane.update(elementCaseEditor); + } + elementCaseEditor.setToolBars((FormToolBarManager[]) elementCaseToolBarEditor.getValue()); + ReportFitAttr fitAttr = pcFitExpandablePane.update(); + elementCaseEditor.setReportFitAttr(fitAttr); + return elementCaseEditor; + } + + + protected void populateSubBean(ElementCaseEditor ob) { + paddingBoundPane.populate(ob); + elementCaseToolBarEditor.setValue(ob.getToolBars()); + extraPropertyGroupPane.populate(ob); + pcFitExpandablePane.populate(ob.getReportFitAttr()); + + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java new file mode 100644 index 000000000..69781e7a6 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java @@ -0,0 +1,161 @@ +package com.fr.design.fit.attrpane; + +import com.fr.base.io.IOFile; +import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.design.data.DataCreatorUI; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.properties.items.FRLayoutTypeItems; +import com.fr.design.designer.properties.items.Item; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.mainframe.widget.accessibles.AccessibleBodyWatermarkEditor; +import com.fr.design.mainframe.widget.accessibles.AccessibleWLayoutBorderStyleEditor; +import com.fr.design.utils.gui.UIComponentUtils; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.design.widget.ui.designer.layout.FRAbsoluteLayoutDefinePane; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.container.WAbsoluteBodyLayout; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.form.ui.container.WBodyLayoutType; +import com.fr.report.core.ReportUtils; + +import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + +/** + * Created by kerry on 2020-04-22 + */ +public class FRAbsoluteBodyLayoutExtendDefinePane extends FRAbsoluteLayoutDefinePane { + private static final int MAX_LABEL_WIDTH = 80; + + private AccessibleWLayoutBorderStyleEditor borderStyleEditor; + private AccessibleBodyWatermarkEditor watermarkEditor; + + private UIComboBox layoutCombox; + private WBodyLayoutType layoutType = WBodyLayoutType.ABSOLUTE; + + public FRAbsoluteBodyLayoutExtendDefinePane(XCreator xCreator) { + super(xCreator); + } + + + public void initComponent() { + initCenterPane(); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + borderStyleEditor = new AccessibleWLayoutBorderStyleEditor(); + watermarkEditor = new AccessibleBodyWatermarkEditor(); + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style")), borderStyleEditor}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), watermarkEditor} + }, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W3, IntervalConstants.INTERVAL_L1); + JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + jPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + borderPane.add(jPanel, BorderLayout.CENTER); + UIExpandablePane advancedPane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, borderPane); + centerPane.add(advancedPane, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.NORTH); + } + + private void initCenterPane(){ + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initUIComboBox(); + JPanel thirdPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel jPanel = createThirdPane(); + jPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + thirdPane.add(jPanel, BorderLayout.CENTER); + UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout"), 280, 20, thirdPane); + this.add(layoutExpandablePane, BorderLayout.CENTER); + + } + + public JPanel createThirdPane() { + initLayoutComboBox(); + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p}; + double[] colSize = {p, f}; + + UILabel layoutTypeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")); + JPanel northPane = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + new Component[]{layoutTypeLabel, UIComponentUtils.wrapWithBorderLayoutPane(layoutCombox)}}, + rowSize, colSize, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + jPanel.add(northPane, BorderLayout.NORTH); + return jPanel; + + } + + public void initLayoutComboBox() { + Item[] items = FRLayoutTypeItems.ITEMS; + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (Item item : items) { + model.addElement(item); + } + layoutCombox = new UIComboBox(model); + layoutCombox.setSelectedIndex(1); + } + + @Override + public String title4PopupWindow() { + return "absoluteBodyLayout"; + } + + public void populateSubPane(WAbsoluteLayout ob) { + layoutCombox.setSelectedIndex(1); + borderStyleEditor.setValue(ob.getBorderStyle()); + watermarkEditor.setValue(ReportUtils.getWatermarkAttrFromTemplate(getCurrentIOFile())); + } + + public WAbsoluteBodyLayout updateSubPane() { + WAbsoluteBodyLayout layout = (WAbsoluteBodyLayout) creator.toData(); + Item item = (Item) layoutCombox.getSelectedItem(); + Object value = item.getValue(); + int state = 0; + if (value instanceof Integer) { + state = (Integer) value; + } + + if (layoutType == WBodyLayoutType.ABSOLUTE) { + ((XWFitLayout) creator.getBackupParent()).toData().resetStyle(); + if (state == WBodyLayoutType.FIT.getTypeValue()) { + XWFitLayout xwFitLayout = ((XWFitLayout)creator.getBackupParent()); + xwFitLayout.switch2FitBodyLayout(creator); + copyLayoutAttr(layout, xwFitLayout.toData()); + } + } + layout.setBorderStyle((LayoutBorderStyle) borderStyleEditor.getValue()); + updateWatermark(); + return layout; + } + + private void updateWatermark() { + WatermarkAttr watermark = (WatermarkAttr) watermarkEditor.getValue(); + if (watermark != null) { + IOFile ioFile = getCurrentIOFile(); + ioFile.addAttrMark(watermark); + } + } + + private IOFile getCurrentIOFile() { + return WidgetPropertyPane.getInstance().getEditingFormDesigner().getTarget(); + } + + @Override + public DataCreatorUI dataUI() { + return null; + } + + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteLayoutExtendDefinePane.java b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteLayoutExtendDefinePane.java new file mode 100644 index 000000000..60ffae3eb --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteLayoutExtendDefinePane.java @@ -0,0 +1,27 @@ +package com.fr.design.fit.attrpane; + +import com.fr.design.designer.creator.XCreator; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.widget.ui.designer.layout.AbstractFRLayoutDefinePane; +import com.fr.form.ui.container.WAbsoluteLayout; + +/** + * Created by kerry on 2020-04-22 + */ +public class FRAbsoluteLayoutExtendDefinePane extends AbstractFRLayoutDefinePane { + + public FRAbsoluteLayoutExtendDefinePane(XCreator xCreator) { + super(xCreator); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + } + + @Override + public void populateBean(WAbsoluteLayout ob) { + } + + @Override + public WAbsoluteLayout updateBean() { + WAbsoluteLayout wAbsoluteLayout = (WAbsoluteLayout) creator.toData(); + return wAbsoluteLayout; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java new file mode 100644 index 000000000..3dd0f1c48 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java @@ -0,0 +1,246 @@ +package com.fr.design.fit.attrpane; + +import com.fr.base.io.IOFile; +import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.design.data.DataCreatorUI; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteBodyLayout; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.XWScaleLayout; +import com.fr.design.designer.properties.items.FRLayoutTypeItems; +import com.fr.design.designer.properties.items.Item; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.FormSelectionUtils; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.mainframe.widget.accessibles.AccessibleBodyWatermarkEditor; +import com.fr.design.mainframe.widget.accessibles.AccessibleWLayoutBorderStyleEditor; +import com.fr.design.utils.gui.UIComponentUtils; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.design.widget.ui.designer.component.PaddingBoundPane; +import com.fr.design.widget.ui.designer.layout.AbstractFRLayoutDefinePane; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.WAbsoluteBodyLayout; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.form.ui.container.WBodyLayoutType; +import com.fr.form.ui.container.WFitLayout; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.report.core.ReportUtils; + +import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; + +/** + * Created by kerry on 2020-04-22 + */ +public class FRFitLayoutExtendDefinePane extends AbstractFRLayoutDefinePane { + private static final int ADAPT_LABEL_MAX_WIDTH = 80; + private XWFitLayout xWFitLayout; + private WFitLayout wFitLayout; + private UIComboBox layoutComboBox; + private UISpinner componentIntervel; + private PaddingBoundPane paddingBound; + private AccessibleWLayoutBorderStyleEditor stylePane; + private AccessibleBodyWatermarkEditor watermarkEditor; + + public FRFitLayoutExtendDefinePane(XCreator xCreator) { + super(xCreator); + this.xWFitLayout = (XWFitLayout) xCreator; + wFitLayout = xWFitLayout.toData(); + initComponent(); + } + + + public void initComponent() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel advancePane = createAdvancePane(); + UIExpandablePane advanceExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, advancePane); + this.add(advanceExpandablePane, BorderLayout.NORTH); + UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout"), 280, 20, createLayoutPane()); + this.add(layoutExpandablePane, BorderLayout.CENTER); + } + + public JPanel createAdvancePane() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + stylePane = new AccessibleWLayoutBorderStyleEditor(); + watermarkEditor = new AccessibleBodyWatermarkEditor(); + paddingBound = new PaddingBoundPane(); + JPanel jp2 = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style")), stylePane}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), watermarkEditor} + }, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W3, IntervalConstants.INTERVAL_L1); + jp2.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + jPanel.add(paddingBound, BorderLayout.CENTER); + jPanel.add(jp2, BorderLayout.NORTH); + return jPanel; + } + + public JPanel createLayoutPane() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + layoutComboBox = initUIComboBox(FRLayoutTypeItems.ITEMS); + componentIntervel = new UISpinner(0, Integer.MAX_VALUE, 1, 0); + JPanel componentIntervelPane = UIComponentUtils.wrapWithBorderLayoutPane(componentIntervel); + + UILabel intervalLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Component_Interval")); + + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, f}; + int[][] rowCount = {{1, 1}, {1, 1}}; + + + Component[][] components = new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")), layoutComboBox}, + new Component[]{intervalLabel, componentIntervelPane} + }; + JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + centerPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + jPanel.add(centerPane, BorderLayout.CENTER); + return jPanel; + } + + + public UIComboBox initUIComboBox(Item[] items) { + DefaultComboBoxModel model = new DefaultComboBoxModel(); + for (Item item : items) { + model.addElement(item); + } + return new UIComboBox(model); + } + + + @Override + public String title4PopupWindow() { + return "fitLayout"; + } + + @Override + public void populateBean(WFitLayout ob) { + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + XLayoutContainer rootLayout = selectedBodyLayout(formDesigner); + if (rootLayout != formDesigner.getRootComponent() + && formDesigner.getSelectionModel().getSelection().getSelectedCreator() == formDesigner.getRootComponent()) { + formDesigner.getSelectionModel().setSelectedCreators( + FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{selectedBodyLayout(formDesigner).toData()})); + + } + paddingBound.populate(ob); + layoutComboBox.setSelectedIndex(ob.getBodyLayoutType().getTypeValue()); + componentIntervel.setValue(ob.getCompInterval()); + stylePane.setValue(ob.getBorderStyle()); + watermarkEditor.setValue(ReportUtils.getWatermarkAttrFromTemplate(getCurrentIOFile())); + } + + private XLayoutContainer selectedBodyLayout(FormDesigner formDesigner) { + XLayoutContainer rootLayout = formDesigner.getRootComponent(); + if (rootLayout.getComponentCount() == 1 && rootLayout.getXCreator(0).acceptType(XWAbsoluteBodyLayout.class)) { + rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(0); + } + return rootLayout; + } + + + @Override + public WFitLayout updateBean() { + WFitLayout layout = (WFitLayout) creator.toData(); + if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate"))) { + paddingBound.update(layout); + } + LayoutBorderStyle borderStyle = (LayoutBorderStyle) stylePane.getValue(); + if (borderStyle != null) { + layout.setBorderStyle(borderStyle); + } + updateWatermark(); + Item item = (Item) layoutComboBox.getSelectedItem(); + Object value = item.getValue(); + int state = 0; + if (value instanceof Integer) { + state = (Integer) value; + } + //todo 验证下 + layout.setLayoutType(WBodyLayoutType.parse(state)); + try { + if (state == WBodyLayoutType.ABSOLUTE.getTypeValue()) { + WAbsoluteBodyLayout wAbsoluteBodyLayout = new WAbsoluteBodyLayout("body"); + wAbsoluteBodyLayout.setCompState(WAbsoluteLayout.STATE_FIXED); + Component[] components = xWFitLayout.getComponents(); + xWFitLayout.removeAll(); + layout.resetStyle(); + XWAbsoluteBodyLayout xwAbsoluteBodyLayout = xWFitLayout.getBackupParent() == null ? new XWAbsoluteBodyLayout(wAbsoluteBodyLayout, new Dimension(0, 0)) : (XWAbsoluteBodyLayout) xWFitLayout.getBackupParent(); + xWFitLayout.getLayoutAdapter().addBean(xwAbsoluteBodyLayout, 0, 0); + for (Component component : components) { + XCreator xCreator = (XCreator) component; + //部分控件被ScaleLayout包裹着,绝对布局里面要放出来 + if (xCreator.acceptType(XWScaleLayout.class)) { + if (xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator()) { + component = xCreator.getComponent(0); + component.setBounds(xCreator.getBounds()); + } + } + xwAbsoluteBodyLayout.add(component); + } + copyLayoutAttr(wFitLayout, wAbsoluteBodyLayout); + xWFitLayout.setBackupParent(xwAbsoluteBodyLayout); + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + formDesigner.getSelectionModel().setSelectedCreators( + FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{wAbsoluteBodyLayout})); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + + } + + int intervelValue = (int) componentIntervel.getValue(); + if (xWFitLayout.canAddInterval(intervelValue)) { +// 设置完间隔后,要同步处理界面组件,容器刷新后显示出对应效果 + setLayoutGap(intervelValue); + } + + return layout; + } + + private void updateWatermark() { + WatermarkAttr watermark = (WatermarkAttr) watermarkEditor.getValue(); + if (watermark != null) { + IOFile ioFile = getCurrentIOFile(); + ioFile.addAttrMark(watermark); + } + } + + private IOFile getCurrentIOFile() { + return WidgetPropertyPane.getInstance().getEditingFormDesigner().getTarget(); + } + + private void setLayoutGap(int value) { + int interval = wFitLayout.getCompInterval(); + if (value != interval) { + xWFitLayout.moveContainerMargin(); + xWFitLayout.moveCompInterval(xWFitLayout.getAcualInterval()); + wFitLayout.setCompInterval(value); + xWFitLayout.addCompInterval(xWFitLayout.getAcualInterval()); + } + } + + @Override + public DataCreatorUI dataUI() { + return null; + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java b/designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java new file mode 100644 index 000000000..0bd1e2bd2 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java @@ -0,0 +1,107 @@ +package com.fr.design.fit.attrpane; + +import com.fr.design.designer.IntervalConstants; +import com.fr.design.fit.FitStateCompatible; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.widget.DataModify; +import com.fr.report.fit.FitAttrState; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + + +/** + * Created by kerry on 2020-04-22 + */ +public class PcFitExpandablePane extends JPanel { + UIComboBox comboBox = new UIComboBox( + new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Double_Fit"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Hor_Fit"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit")}); + UILabel tipLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit_Tip")); + + public PcFitExpandablePane(DataModify attrPane) { + init(attrPane); + } + + public void init(final DataModify attrPane) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel pcFitPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + final JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + borderPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + tipLabel.setForeground(Color.gray); + comboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + tipLabel.setText(ScaleTipType.getScaleTip(comboBox.getSelectedIndex()).getTip()); + } + }); + Component[][] components = new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Content_Display_Type")), comboBox}, + new Component[]{tipLabel, null}, + }; + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_W0); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); + + borderPane.add(panel, BorderLayout.CENTER); + borderPane.add(tipLabel, BorderLayout.SOUTH); + pcFitPane.add(borderPane, BorderLayout.CENTER); + this.add(pcFitPane, BorderLayout.CENTER); + } + + public ReportFitAttr update() { + ReportFitAttr fitAttr = getReportFitAttr(); + fitAttr.setFitStateInPC(FitStateCompatible.getOldTypeFromNew(comboBox.getSelectedIndex())); + return fitAttr; + } + + public void populate(ReportFitAttr fitAttr) { + if (fitAttr == null) { + fitAttr = getReportFitAttr(); + } + int selectIndex = FitStateCompatible.getNewTypeFromOld(fitAttr.fitStateInPC()); + comboBox.setSelectedIndex(selectIndex); + tipLabel.setText(ScaleTipType.getScaleTip(selectIndex).getTip()); + } + + private ReportFitAttr getReportFitAttr() { + ReportFitAttr fitAttr = new ReportFitAttr(); + fitAttr.setFitStateInPC(FitAttrState.NOT_FIT.getState()); + return fitAttr; + } + + private enum ScaleTipType { + EC_DOUBLE_FIT(0, com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Double_Fit_Tip")), + EC_HOR_FIT(1, com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_Hor_Fit_Tip")), + EC_NO_FIT(2, com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit_Tip")); + private int index; + private String tip; + + ScaleTipType(int index, String tip) { + this.index = index; + this.tip = tip; + } + + public String getTip() { + return tip; + } + + public static ScaleTipType getScaleTip(int selectIndex) { + for (ScaleTipType tipType : values()) { + if (selectIndex == tipType.index) { + return tipType; + } + } + return EC_NO_FIT; + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/attrpane/RootDesignExtendDefinePane.java b/designer-form/src/main/java/com/fr/design/fit/attrpane/RootDesignExtendDefinePane.java new file mode 100644 index 000000000..8a8aa404a --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/RootDesignExtendDefinePane.java @@ -0,0 +1,303 @@ +package com.fr.design.fit.attrpane; + +import com.fr.base.BaseUtils; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.data.DataCreatorUI; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.designer.creator.CRPropertyDescriptor; +import com.fr.design.designer.creator.PropertyGroupPane; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XWParameterLayout; +import com.fr.design.designer.properties.PropertyTab; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.fit.common.TemplateTool; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.fun.ParameterExpandablePaneUIProvider; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.FormSelection; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.widget.accessibles.AccessibleBackgroundEditor; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.design.utils.gui.UIComponentUtils; +import com.fr.design.widget.ui.designer.AbstractDataModify; +import com.fr.design.widget.ui.designer.component.UIBoundSpinner; +import com.fr.form.ui.container.WParameterLayout; +import com.fr.general.Background; +import com.fr.report.stable.FormConstants; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Rectangle; +import java.util.Set; + +public class RootDesignExtendDefinePane extends AbstractDataModify { + private XWParameterLayout root; + private UISpinner designerWidth; + private UISpinner paraHeight; + private UICheckBox displayReport; + private UICheckBox useParamsTemplate; + private AccessibleBackgroundEditor background; + private UIButtonGroup hAlignmentPane; + private UITextField labelNameTextField; + //是否是新设计模式下决策报表 + private boolean newForm; + private PropertyGroupPane extraPropertyGroupPane; + + public RootDesignExtendDefinePane(XCreator xCreator) { + super(xCreator); + newForm = TemplateTool.getCurrentEditingNewJForm() != null && DesignerUIModeConfig.getInstance().newUIMode(); + this.root = (XWParameterLayout) xCreator; + initComponent(); + } + + + public void initComponent() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + if (newForm) { + paraHeight = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, 0); + } else { + designerWidth = new UIBoundSpinner(1, Integer.MAX_VALUE, 1); + } + JPanel advancePane = createAdvancePane(); + UIExpandablePane advanceExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, advancePane); + this.add(advanceExpandablePane, BorderLayout.NORTH); + JPanel layoutPane = createBoundsPane(); + UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Size"), 280, 20, layoutPane); + this.add(layoutExpandablePane, BorderLayout.CENTER); + this.addExtraUIExpandablePaneFromPlugin(); + } + + private void addExtraUIExpandablePaneFromPlugin() { + Set pluginCreators = ExtraDesignClassManager.getInstance().getArray(ParameterExpandablePaneUIProvider.XML_TAG); + JPanel panel = FRGUIPaneFactory.createYBoxEmptyBorderPane(); + for (ParameterExpandablePaneUIProvider provider : pluginCreators) { + UIExpandablePane uiExpandablePane = provider.createUIExpandablePane(); + PropertyTab propertyTab = provider.addToWhichPropertyTab(); + if (uiExpandablePane != null && propertyTab == PropertyTab.ATTR) { + panel.add(uiExpandablePane); + } + } + this.add(panel, BorderLayout.SOUTH); + } + + public JPanel createBoundsPane() { + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p}; + double[] columnSize = {p, f}; + int[][] rowCount = {{1, 1}}; + Component[] component = newForm ? new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Design_Height")), paraHeight} : + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Desin_Width")), designerWidth}; + Component[][] components = new Component[][]{component}; + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + jPanel.add(panel); + return jPanel; + } + + public JPanel createAdvancePane() { + if (newForm) { + return getNewFormAdvancePane(); + } else { + return getTemplateAdvancePane(); + } + } + + /** + * @Description: 获取的非新决策报表AdvancePane + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/11/05 15:36 + */ + private JPanel getTemplateAdvancePane() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + labelNameTextField = new UITextField(); + displayReport = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Display_Nothing_Before_Query")); + UIComponentUtils.setLineWrap(displayReport); + useParamsTemplate = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Use_Params_Template")); + background = new AccessibleBackgroundEditor(); + Icon[] hAlignmentIconArray = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), + BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), + BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png"),}; + Integer[] hAlignment = new Integer[]{FormConstants.LEFTPOSITION, FormConstants.CENTERPOSITION, FormConstants.RIGHTPOSITION}; + hAlignmentPane = new UIButtonGroup(hAlignmentIconArray, hAlignment); + hAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Left") + , com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_StyleAlignment_Right")}); + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p, p}; + double[] columnSize = {p, f}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; + Component[][] components = new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_Background")), background}, + new Component[]{displayReport, null}, + new Component[]{useParamsTemplate, null}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Display_Position")), hAlignmentPane} + }; + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1); + panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); + CRPropertyDescriptor[] extraTableEditor = new CRPropertyDescriptor[0]; + extraTableEditor = root.getExtraTableEditor(); + extraPropertyGroupPane = new PropertyGroupPane(extraTableEditor, root); + + jPanel.add(panel, BorderLayout.NORTH); + jPanel.add(extraPropertyGroupPane, BorderLayout.CENTER); + return jPanel; + } + + /** + * @Description: 获取新决策报表的AdvancePane + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/11/05 15:36 + */ + private JPanel getNewFormAdvancePane() { + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + labelNameTextField = new UITextField(); + displayReport = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Display_Nothing_Before_Query")); + UIComponentUtils.setLineWrap(displayReport); + useParamsTemplate = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Use_Params_Template")); + background = new AccessibleBackgroundEditor(); + + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, f}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}}; + Component[][] components = new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Label_Name")), labelNameTextField}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_Background")), background}, + new Component[]{displayReport, null}, + new Component[]{useParamsTemplate, null} + }; + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1); + panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); + + jPanel.add(panel, BorderLayout.NORTH); + + return jPanel; + } + + @Override + public String title4PopupWindow() { + return "parameter"; + } + + @Override + public void populateBean(WParameterLayout ob) { + labelNameTextField.setText(ob.getLabelName()); + background.setValue(ob.getBackground()); + displayReport.setSelected(ob.isDelayDisplayContent()); + useParamsTemplate.setSelected(ob.isUseParamsTemplate()); + if (newForm) { + FormDesigner designer = TemplateTool.getCurrentEditingNewJForm().getFormDesign(); + paraHeight.setValue(designer.getParaHeight()); + } else { + designerWidth.setValue(ob.getDesignWidth()); + hAlignmentPane.setSelectedItem(ob.getPosition()); + + if (extraPropertyGroupPane != null) { + extraPropertyGroupPane.populate(ob); + } + } + } + + + @Override + public WParameterLayout updateBean() { + if (newForm) { + return updateNewFormBean(); + } else { + return updateTemplateBean(); + } + } + + /** + * @Description: 更新非新决策报表的bean + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/11/05 15:36 + */ + private WParameterLayout updateTemplateBean() { + WParameterLayout wParameterLayout = (WParameterLayout) creator.toData(); + wParameterLayout.setLabelName(labelNameTextField.getText()); + if (isCompsOutOfDesignerWidth((int) designerWidth.getValue())) { + designerWidth.setValue(wParameterLayout.getDesignWidth()); + } else { + wParameterLayout.setDesignWidth((int) designerWidth.getValue()); + } + wParameterLayout.setDelayDisplayContent(displayReport.isSelected()); + wParameterLayout.setUseParamsTemplate(useParamsTemplate.isSelected()); + JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected()); + wParameterLayout.setBackground((Background) background.getValue()); + wParameterLayout.setPosition((Integer) hAlignmentPane.getSelectedItem()); + return wParameterLayout; + } + + /** + * @Description: 更新新决策报表的bean + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/11/05 15:36 + */ + private WParameterLayout updateNewFormBean() { + WParameterLayout wParameterLayout = (WParameterLayout) creator.toData(); + wParameterLayout.setLabelName(labelNameTextField.getText()); + + wParameterLayout.setDelayDisplayContent(displayReport.isSelected()); + wParameterLayout.setUseParamsTemplate(useParamsTemplate.isSelected()); + JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected()); + wParameterLayout.setBackground((Background) background.getValue()); + //设置参数模板面板的高度 + int height = (int) paraHeight.getTextField().getValue(); + FormDesigner designer = TemplateTool.getCurrentEditingNewJForm().getFormDesign(); + FormSelection selection = designer.getSelectionModel().getSelection(); + XCreator creator = designer.getParaComponent(); + Rectangle rectangle = creator.getBounds(); + Rectangle newRectangle = new Rectangle(rectangle.x, rectangle.y, rectangle.width, height); + creator.setBounds(newRectangle); + if (paraHeight.getValue() != newRectangle.height) + paraHeight.setValue(newRectangle.height); + designer.setParaHeight(newRectangle.height); + designer.getArea().doLayout(); + LayoutUtils.layoutContainer(creator); + selection.fixCreator(designer); + designer.repaint(); + return wParameterLayout; + } + + private boolean isCompsOutOfDesignerWidth(int designerWidth) { + for (int i = 0; i < root.getComponentCount(); i++) { + Component comp = root.getComponent(i); + if (comp.getX() + comp.getWidth() > designerWidth) { + return true; + } + } + return false; + } + + @Override + public DataCreatorUI dataUI() { + return null; + } +} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java b/designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java new file mode 100644 index 000000000..5d9c9463c --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java @@ -0,0 +1,225 @@ +package com.fr.design.fit.common; + +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.fit.NewJForm; +import com.fr.design.fit.attrpane.ElementEditorExtendDefinePane; +import com.fr.design.fit.attrpane.FRAbsoluteBodyLayoutExtendDefinePane; +import com.fr.design.fit.attrpane.FRAbsoluteLayoutExtendDefinePane; +import com.fr.design.fit.attrpane.FRFitLayoutExtendDefinePane; +import com.fr.design.fit.attrpane.RootDesignExtendDefinePane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.JTemplateFactory; +import com.fr.design.parameter.RootDesignDefinePane; +import com.fr.design.preview.FormAdaptivePreview; +import com.fr.design.preview.FormPreview; +import com.fr.design.widget.Appearance; +import com.fr.design.widget.FormWidgetDefinePaneFactoryBase; +import com.fr.design.widget.ui.designer.layout.ElementEditorDefinePane; +import com.fr.design.widget.ui.designer.layout.FRAbsoluteBodyLayoutDefinePane; +import com.fr.design.widget.ui.designer.layout.FRAbsoluteLayoutDefinePane; +import com.fr.design.widget.ui.designer.layout.FRFitLayoutDefinePane; +import com.fr.file.FILE; +import com.fr.file.MemFILE; +import com.fr.form.ui.ElementCaseEditor; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.WAbsoluteBodyLayout; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.form.ui.container.WFitLayout; +import com.fr.form.ui.container.WParameterLayout; +import com.fr.form.ui.widget.CRBoundsWidget; +import com.fr.log.FineLoggerFactory; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.SwingUtilities; + +/** + * Created by kerry on 2020-06-02 + */ +public class AdaptiveSwitchUtil { + + private static int switchJFromIng = 0; + + private AdaptiveSwitchUtil() { + + } + + public static void switch2NewUI() { + switch2NewUIMode(); + reload(); + } + + public static void switch2NewUIMode() { + DesignerUIModeConfig.getInstance().setNewUIMode(); + FormWidgetDefinePaneFactoryBase.registerDefinePane(ElementCaseEditor.class, + new Appearance(ElementEditorExtendDefinePane.class, "elementCaseEditor")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WFitLayout.class, + new Appearance(FRFitLayoutExtendDefinePane.class, "wFitLayout")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteBodyLayout.class, + new Appearance(FRAbsoluteBodyLayoutExtendDefinePane.class, "wAbsoluteBodyLayout")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteLayout.class, + new Appearance(FRAbsoluteLayoutExtendDefinePane.class, "wAbsoluteLayout")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WParameterLayout.class, + new Appearance(RootDesignExtendDefinePane.class, "wParameterLayout")); + } + + public static void switch2OldUI() { + switch2OldUIMode(); + reload(); + } + + public static void switch2OldUIMode() { + DesignerUIModeConfig.getInstance().setOldUIMode(); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteLayout.class, + new Appearance(FRAbsoluteLayoutDefinePane.class, "wAbsoluteLayout")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(ElementCaseEditor.class, + new Appearance(ElementEditorDefinePane.class, "elementCaseEditor")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WAbsoluteBodyLayout.class, + new Appearance(FRAbsoluteBodyLayoutDefinePane.class, "wAbsoluteBodyLayout")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WFitLayout.class, + new Appearance(FRFitLayoutDefinePane.class, "wFitLayout")); + FormWidgetDefinePaneFactoryBase.registerDefinePane(WParameterLayout.class, + new Appearance(RootDesignDefinePane.class, "wParameterLayout")); + } + + public static void reload() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + synchronized (AdaptiveSwitchUtil.class) { + try { + if (DesignerContext.getDesignerFrame() == null) { + return; + } + JTemplate old = TemplateTool.getCurrentEditingTemplate(); + if (old == null || !(old instanceof JForm)) { + return; + } + JTemplate template = createNewJTemplate(old); + if (template != null) { + DesignTableDataManager.closeTemplate(old); + TemplateTool.resetTabPaneEditingTemplate(template); + TemplateTool.activeAndResizeTemplate(template); + setPreviewType(); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } finally { + switchJFromIng = 0; + } + } + } + }); + } + + /** + * @Description: 设置预览方式 + * @return: 新创建的模板 + * @Author: Henry.Wang + * @date: 2020/10/13 14:08 + */ + private static void setPreviewType() { + JTemplate jTemplate = TemplateTool.getCurrentEditingTemplate(); + if (jTemplate != null) { + if (DesignerUIModeConfig.getInstance().newUIMode()) { + jTemplate.setPreviewType(new FormAdaptivePreview()); + } else { + jTemplate.setPreviewType(new FormPreview()); + } + } + } + + /** + * @Description: 创建模板 + * @param old 以前的模板 + * @return: 新创建的模板 + * @Author: Henry.Wang + * @date: 2020/9/6 14:08 + */ + public static JTemplate createNewJTemplate(JTemplate old) { + JTemplate template; + template = createNewJTemplateInternal(old); + if (template instanceof NewJForm) { + NewJForm jForm = ((NewJForm) template); + //如果是从旧的设计模板转化为新的设计模式,并且不是全局配置的模板。则更新新模板的Pc端自适应属性 + if (DesignerUIModeConfig.getInstance().newUIMode() && jForm.getTarget().getReportFitAttr() != null && isSwitchJFromIng()) { + jForm.getTarget().setReportFitAttr(shiftReportFitAttr(old, jForm.getTarget().getReportFitAttr().isFitFont())); + } + TemplateTool.saveForm(jForm); + } + return template; + } + + /** + * @Description: 创建模板核心方法 + * @param old 以前的方法 + * @return: 新创建的模板 + * @Author: Henry.Wang + * @date: 2020/9/6 14:09 + */ + private static JTemplate createNewJTemplateInternal(JTemplate old) { + FILE file = old.getEditingFILE(); + if ((file instanceof MemFILE) || !old.isSaved()) { + if (old instanceof NewJForm) { + TemplateTool.resetAbsoluteBodySize((NewJForm) old); + } + TemplateTool.saveForm(old); + } + return JTemplateFactory.createJTemplate(old.getEditingFILE()); + } + + /** + * @Description: 老模板切换到新模板的属性配置转换( + * 1、绝对布局-适应区域--》双向自适应 + * 2、自适应布局-双向自适应--》双向自适应 + * 3、自适应布局-横向自适应--》横向自适应 + * 4、绝对布局-固定大小--》不自适应 + * ) + * @param old + * @param fitFont 字体是否自适应 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:01 + */ + private static ReportFitAttr shiftReportFitAttr(JTemplate old, boolean fitFont) { + if (old instanceof JForm && DesignerUIModeConfig.getInstance().newUIMode()) { + JForm jForm = (JForm) old; + try { + int layoutType = LayoutTool.getFormLayoutType(jForm); + int compState = -1; + //自适应布局 + if (layoutType == 0) { + compState = ((WFitLayout) jForm.getFormDesign().getRootComponent().toData()).getCompState(); + if (compState == WFitLayout.STATE_FULL) { + return new ReportFitAttr(2, fitFont); + } else if (compState == WFitLayout.STATE_ORIGIN) { + return new ReportFitAttr(1, fitFont); + } + } else if (layoutType == 1) {//绝对布局 + Widget widget = ((CRBoundsWidget) jForm.getFormDesign().getRootComponent().toData().getWidget(0)).getWidget(); + if (widget instanceof WAbsoluteLayout) { + compState = ((WAbsoluteLayout) widget).getCompState(); + } + if (compState == WAbsoluteLayout.STATE_FIT) { + return new ReportFitAttr(2, fitFont); + } else if (compState == WAbsoluteLayout.STATE_FIXED) { + return new ReportFitAttr(3, fitFont); + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + return null; + } + + public static void setSwitchJFromIng(int switchJFromIng) { + AdaptiveSwitchUtil.switchJFromIng = switchJFromIng; + } + + public static boolean isSwitchJFromIng() { + return switchJFromIng == 1; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java b/designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java new file mode 100644 index 000000000..829d320e8 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/BaseUtils.java @@ -0,0 +1,1266 @@ +package com.fr.design.fit.common; + +import com.fr.base.AutoChangeLineAndDrawManager; +import com.fr.base.FRContext; +import com.fr.base.GraphHelper; +import com.fr.base.Style; +import com.fr.base.SynchronizedLiveDataModelUtils; +import com.fr.base.TableData; +import com.fr.base.regist.LicenseConfigManager; +import com.fr.config.ServerPreferenceConfig; +import com.fr.data.api.TableDataAssist; +import com.fr.design.fit.PX; +import com.fr.general.ComparatorUtils; +import com.fr.general.FArray; +import com.fr.general.FRFont; +import com.fr.general.GeneralContext; +import com.fr.general.GeneralUtils; +import com.fr.general.IOUtils; +import com.fr.general.data.DataModel; +import com.fr.general.data.TableDataException; +import com.fr.general.xml.GeneralXMLTools; +import com.fr.json.JSONArray; +import com.fr.json.JSONException; +import com.fr.json.JSONObject; +import com.fr.json.JSONUtils; +import com.fr.json.revise.EmbedJson; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.injectable.PluginModule; +import com.fr.report.fun.VerticalTextProcessor; +import com.fr.report.fun.impl.DefaultVerticalTextProcessor; +import com.fr.script.Calculator; +import com.fr.stable.ColumnRow; +import com.fr.stable.Constants; +import com.fr.stable.GraphDrawHelper; +import com.fr.stable.ListSet; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.bridge.ObjectHolder; +import com.fr.stable.fun.AutoChangeLineAndDrawProcess; +import com.fr.stable.fun.FontProcessor; +import com.fr.stable.plugin.ExtraClassManagerProvider; +import com.fr.stable.project.ProjectConstants; +import com.fr.stable.script.CalculatorProvider; +import com.fr.stable.unit.FU; +import com.fr.stable.unit.UNIT; +import com.fr.workspace.WorkContext; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Dimension2D; +import java.awt.image.BufferedImage; +import java.awt.image.CropImageFilter; +import java.awt.image.FilteredImageSource; +import java.io.IOException; +import java.io.InputStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + + +/** + * 基本的工具类 + */ +public class BaseUtils { + + private BaseUtils() { + } + + /** + * 从缓存中读取图片(如果缓存中存在的话则直接从缓存中读取,如果不存在则从磁盘读取并将读取的结果缓存起来) + * + * @param resource 图片的路径 + * @return 图片 + * @see IOUtils#readImageWithCache(String) + * @deprecated + */ + public static BufferedImage readImageWithCache(String resource) { + return IOUtils.readImageWithCache(resource); + } + + /** + * 从缓存中读取图片,如果缓存中不存在则返回null + * + * @param resource 图片路径 + * @return 图片,缓存中没有则返回null + * @see IOUtils#readCacheImage(String) + * @deprecated + */ + public static BufferedImage readCacheImage(String resource) { + return IOUtils.readCacheImage(resource); + } + + /** + * 直接从磁盘中读取图片,这种方法效率稍低但每次图片更改了也能即时反应出来 + * + * @param resource 图片的路径 + * @return 图片 + * @see IOUtils#readImage(String) + * @deprecated + */ + public static BufferedImage readImage(String resource) { + //daniel bug 5400 图片读取 默认关闭缓存 + return IOUtils.readImage(resource); + } + + /** + * 读取图标,该方法启用了缓存 + * + * @param resource 图标文件的存放路径 + * @return 图标 + * @see IOUtils#readIcon(String) + * @deprecated + */ + public static Icon readIcon(String resource) { + return IOUtils.readIcon(resource); + } + + /** + * 从输入流中读取图片 + * + * @param input 输入流 + * @return 图片 + * @throws IOException + * @see IOUtils#readImage(InputStream) + * @deprecated + */ + public static BufferedImage readImage(InputStream input) throws IOException { + return IOUtils.readImage(input); + } + + /** + * 将行列对象转换成其字符串的表示形式 + * 转换后的字符串将像A2,B4,C45这样的 + *

+ * 将A1单元格转化成字符串"A1": + *

+ * BaseUtils.convertColumnRowToCellString(ColumnRow.valueOf(0,0)); + * + * @param columnRow 要转换的行列对象 + * @return 表示行列位置的字符串 + */ + public static String convertColumnRowToCellString(ColumnRow columnRow) { + if (columnRow == null) { + return ""; + } + + return columnRow.toString(); + } + + /** + * 将表示行列位置的字符串转换成行列对象 + * 如果转换失败,将会返回{@link ColumnRow} + * + * @param columnRowString 表示行列位置的字符串对象 + * @return 行列对象 + * @see ColumnRow#valueOf(String) + * @deprecated + */ + public static ColumnRow convertCellStringToColumnRow(String columnRowString) { + return ColumnRow.valueOf(columnRowString); + } + + /** + * 读取jar的版本号 + * + * @return 版本号 + * @see GeneralUtils#readBuildNO() + * @deprecated + */ + public static String readBuildNO() { + return GeneralUtils.readBuildNO(); + } + + /** + * 把指定位置的资源以默认的GBK编码的形式读取成字符串 + * + * @param path 资源存放的路径 + * @return 表示资源内容的字符串 + * @see IOUtils#readResourceAsString(String) + * @deprecated + */ + public static String readResourceAsString(String path) { + return IOUtils.readResourceAsString(path); + } + + /** + * 将指定位置的资源以指定的编码形式读取成字符串 + * + * @param path 资源存放的路径 + * @param encode 读取资源所用的编码 + * @return 表示资源内容的字符串 + * @see IOUtils#readResourceAsString(String, String) + * @deprecated + */ + public static String readResourceAsString(String path, String encode) { + return IOUtils.readResourceAsString(path, encode); + } + + @Deprecated + public static String[] getDependence(Object value, CalculatorProvider c) { + + try { + return (String[]) StableUtils.invokeMethod("com.fr.form.FormUtils", "getDependence", new Class[]{Object.class, CalculatorProvider.class}, new Object[]{value, c}); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + /** + * 读取资源 + * + * @param path 资源存放的路径,可以是一个URL + * @return 返回资源的输入流 + * @see IOUtils#readResource(String) + * @deprecated + */ + public static InputStream readResource(String path) { + return IOUtils.readResource(path); + } + + /** + * 截取图片的指定区域作为一个图标 + * + * @param image 原始的图片 + * @param startx 截取的横向起始位置 + * @param starty 截取的纵向起始位置 + * @param width 截取的图标的宽度 + * @param height 截取的图标的高度 + * @return 图标 + */ + public static ImageIcon createIcon(Image image, int startx, int starty, int width, int height) { + JFrame jc = new JFrame(); + Image cropImage = jc.createImage(new FilteredImageSource(image.getSource(), new CropImageFilter(startx, starty, width, height))); + return new ImageIcon(cropImage); + } + + /** + * 将一个长整形数组以指定的分隔符转化成一个字符串 + * + * @param array 数组 + * @param decimal 分隔符 + * @return 表示数组的字符串 + */ + public static String toLongArrayString(long[] array, char decimal) { + StringBuffer sb = new StringBuffer(); + if (array != null) { + for (int i = 0; i < array.length; i++) { + if (i != 0) { + sb.append(decimal); + } + sb.append(array[i]); + } + } + return sb.toString(); + } + + /** + * 将一个有规则的字符串按指定的分隔符分割并转化成一个长整型数组 + * + * @param str 有规则的字符串 + * @param decimal 分隔符 + * @return 长整型数组 + */ + public static long[] toLongArrayFromStr(String str, char decimal) { + List list = new ArrayList(); + if (str == null) { + return new long[0]; + } + String[] strarray = StableUtils.splitString(str, String.valueOf(decimal)); + for (int i = 0; i < strarray.length; i++) { + String text = strarray[i].trim(); + list.add(Long.valueOf(text)); + } + + long[] res = new long[list.size()]; + for (int i = 0; i < res.length; i++) { + res[i] = ((Long) list.get(i)).longValue(); + } + + return res; + } + + + /** + * 获取样式中字体的类型 + * + * @param g2d 图形上下文 + * @param style 样式 + * @param resolution 屏幕分辨率 + * @return 字体 + */ + public static Font getStyleFont(Graphics2D g2d, Style style, int resolution) { + FRFont font = style.getFRFont(); + Font rfont = initFontWithLocaleAndG2d(g2d, font, resolution); + if (!ComparatorUtils.equals(rfont, g2d.getFont())) { + g2d.setFont(rfont); + } + Color foreground = font.getForeground(); + if (!ComparatorUtils.equals(foreground, g2d.getPaint())) { + g2d.setPaint(foreground); + } + + return rfont; + } + + + private static Font initFontWithLocaleAndG2d(Graphics2D g2d, FRFont font, int resolution) { + Locale locale = GeneralContext.getLocale(); + Font rfont; + if (ComparatorUtils.equals(Locale.ENGLISH, locale)) { + rfont = FRFont.getInstance("Dialog", font.getStyle(), font.getSize()); + } + + rfont = font.applyResolutionNP(resolution); + //itext的bug 用SimSun导出无法实现粗体斜体, 其作者解释是使用basefont是不支持这些style的, 要转成itext的亚洲字体 + //这边不用instance of的原因就是不想把itext包引到applet包里面去. + if (g2d.toString().indexOf("PdfGraphics2D") != -1 && ComparatorUtils.equals(FRFont.DEFAULT_FONTNAME, font.getName())) { + //不要把这边的'宋体'改成'Simsun', 就这么设定的 + rfont = FRFont.getInstance(InterProviderFactory.getProvider().getLocText("Fine-Core_Base_Song_TypeFace"), rfont.getStyle(), rfont.getSize(), + font.getForeground(), font.getUnderline(), font.isStrikethrough(), font.isShadow(), + font.isSuperscript(), font.isSubscript()); + } + + return rfont; + } + + /** + * 获取样式中关于水平方向上的对齐类型 + * + * @param style 样式 + * @return 水平方向上的对齐类型 + */ + public static int getAlignment4Horizontal(Style style) { + return getAlignment4Horizontal(style, null); + } + + /** + * 获取DataMoodel中第columnIndex列的数据. + * + * @param model 取数的数据来源 + * @param columnIndex 取数的数据列序号 + * @return 返回数据数组Object[] + */ + public static Object[] getDistinctValues(DataModel model, int columnIndex) throws TableDataException { + ListSet list = new ListSet(); + if (columnIndex != DataModel.COLUMN_NAME_NOT_FOUND) { + for (int i = 0, len = model.getRowCount(); i < len; i++) { + list.add(model.getValueAt(i, columnIndex)); + } + } + + return list.toArray(); + } + + /** + * 获取水平方向上的对齐样式 + * + * @param style 样式 + * @param value 单元格的值,默认情况下,当不设置对齐类型时,如果单元格的值是数字则靠右对齐,字符串则靠左对齐 + * @return 水平方向上的对齐样式 + */ + public static int getAlignment4Horizontal(Style style, Object value) { + int horizontalAlignment = style.getHorizontalAlignment(); + //若是默认值:判断 bug5188 数字居右 + if (value != null && horizontalAlignment == Constants.NULL) { + if (value instanceof String) { + if (style.getFormat() instanceof NumberFormat || StableUtils.isNumber((String) value)) { + horizontalAlignment = Constants.RIGHT; + } else { + //字符串:靠左 + horizontalAlignment = Constants.LEFT; + } + } else if (value instanceof Number) { + horizontalAlignment = Constants.RIGHT; + } + } + return horizontalAlignment; + } + + /** + * 基本的画文本的方法,只考虑样式中的字体和对齐方式 + * + * @param g2d 图形上下文 + * @param width 画文本的区域的宽度 + * @param height 画文本的区域的高度 + * @param text 要画的文本 + * @param style 样式 + * @param resolution 屏幕分辨率 + */ + public static void drawStringStyleInRotation(Graphics2D g2d, int width, int height, String text, Style style, int resolution) { + if (StringUtils.isBlank(text)) { + return; + } + + Paint oldPaint = g2d.getPaint(); + Font oldFont = g2d.getFont(); + + if (style == null) { + style = Style.DEFAULT_STYLE; + } + + Font font = getStyleFont(g2d, style, resolution); + font = readExtraFont(g2d, font); + int horizontalAlignment = BaseUtils.getAlignment4Horizontal(style, text); + + if (style.getRotation() != 0 && style.getVerticalText() == Style.HORIZONTALTEXT) { + drawHorizontalText(g2d, text, font, style, width, height, horizontalAlignment); + } else { + drawRotationText(g2d, text, style, font, width, height, horizontalAlignment, resolution); + } + + g2d.setFont(oldFont); + g2d.setPaint(oldPaint); + } + + private static Font readExtraFont(Graphics2D g2d, Font font) { + ExtraClassManagerProvider pluginProvider = PluginModule.getAgent(PluginModule.ExtraCore); + if (pluginProvider != null) { + FontProcessor processor = pluginProvider.getSingle(FontProcessor.MARK_STRING); + if (processor != null) { + font = processor.readExtraFont(font); + g2d.setFont(font); + } + } + return font; + } + + private static void drawHorizontalText(Graphics2D g2d, String text, Font rfont, Style style, double width, double height, int horizontalAlignment) { + AffineTransform trans = new AffineTransform(); + trans.rotate(-Math.toRadians(style.getRotation())); + + double textX = width / 2.0; + double textY = height / 2.0; + + Dimension2D textDimension = GraphHelper.stringDimensionWithRotation(text, rfont, -style.getRotation(), g2d.getFontRenderContext()); + + if (textDimension.getWidth() < width) { + if (horizontalAlignment == Constants.LEFT) { + textX = textDimension.getWidth() / 2.0; + } else if (horizontalAlignment == Constants.RIGHT) { + textX = width - textDimension.getWidth() / 2.0 - style.getPaddingLeft() * + Math.cos(Math.toRadians(style.getRotation())); + } else { + } + } + + // adjust y, height. + if (textDimension.getHeight() < height) { + if (style.getVerticalAlignment() == Constants.TOP) { + textY = textDimension.getHeight() / 2.0; + } else if (style.getVerticalAlignment() == Constants.BOTTOM) { + textY = height - textDimension.getHeight() / 2.0 - style.getPaddingLeft() * Math.sin(Math.toRadians(style.getRotation())); + } else { + } + } + + GraphHelper.drawRotatedString(g2d, text, textX, textY, -style.getRotation()); + } + + private static void drawRotationText(Graphics2D g2d, String text, Style style, Font rfont, int width, int height, int horizontalAlignment, int resolution) { + AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess(); + if (process != null) { + process.drawRotationText(g2d, text, new ObjectHolder(style), rfont, width, height, horizontalAlignment, resolution); + return; + } + + FontMetrics cellFM = GraphHelper.getFontMetrics(rfont); + List lineTextList = BaseUtils.getLineTextList(text, style, rfont, height, width, resolution); + + if (width <= 0 || lineTextList.isEmpty()) { + return; + } + + int textAscent = cellFM.getAscent(); + int textHeight = cellFM.getHeight(); + + int textY = calculateTextY(style, height, textHeight, textAscent, lineTextList, resolution); + + int maxWidth = 0; + for (int i = 0; i < lineTextList.size(); i++) { + String paint_str = (String) lineTextList.get(i); + int textWidth = cellFM.stringWidth(paint_str); + if (textWidth > maxWidth) { + maxWidth = textWidth; + } + } + for (int i = 0; i < lineTextList.size(); i++) { + String paint_str = (String) lineTextList.get(i); + //把自定义角度为0的横排和竖排区分开来 + if (style.getRotation() == 0 && style.getVerticalText() == style.HORIZONTALTEXT) { + maxWidth = cellFM.stringWidth(paint_str); + } + boolean textLonger = false;//KevinWang: 标志一下:是否串长大于列宽 + if (maxWidth > width - style.getPaddingLeft() - style.getPaddingRight()) { + textLonger = true;//added by KevinWang <处理分散对齐时使用> + } //待会串长大于列宽时需要特别处理:只从中抽取合适长度的串值显示 + + int textX = (int) calculateTextX(style, width, maxWidth, horizontalAlignment, resolution); + int textWidth = width - style.getPaddingRight(); + if (isAutomaticLine(style, horizontalAlignment, textLonger)) {//自动换行时 + GraphHelper.drawString2(g2d, paint_str, textX, textY, textWidth); + } else if (isDistributeAlign(style, horizontalAlignment, textLonger)) { + drawTextWihenDistributeAlign(g2d, paint_str, cellFM, textWidth, textX, textY); + } else { //这里不能删除 + GraphHelper.drawString(g2d, paint_str, textX, textY); + } + textY += textHeight;// TODO 只增加了Y. + textY += PX.toPixWithResolution(style.getLineSpacing(), resolution); + } + } + + public static int calculateTextY(Style style, int height, int textHeight, int textAscent, List lineTextList, int resolution) { + return calculateTextY(style, height, textHeight, textAscent, lineTextList, resolution, 1); + } + + /** + * 计算Y的高度 + * + * @param style 样式 + * @param height 总高度 + * @param textHeight 文本高度 + * @param textAscent 字体的基线到大多数字母数字字符顶部的距离 + * @param lineTextList 文本列 + * @param resolution 分辨率 + * @return Y高度 + */ + public static int calculateTextY(Style style, int height, int textHeight, int textAscent, List lineTextList, int resolution, int scale) { + // 计算Y的高度. + int textY = 0; + int textAllHeight = textHeight * lineTextList.size(); + double spacingBefore = PX.toPixWithResolution(style.getSpacingBefore() * scale, resolution); + double spacingAfter = PX.toPixWithResolution(style.getSpacingAfter() * scale, resolution); + double lineSpacing = PX.toPixWithResolution(style.getLineSpacing() * scale, resolution); + textAllHeight += spacingBefore + spacingAfter + lineSpacing * lineTextList.size(); + if (style.getVerticalAlignment() == Constants.TOP) { + } else if (style.getVerticalAlignment() == Constants.CENTER) { + if (height > textAllHeight) {// 如果所有文本的高度小于当前可以绘区域的高度,就从0开始画字符. + textY = (height - textAllHeight) / 2; + } + } else if (style.getVerticalAlignment() == Constants.BOTTOM) { + if (height > textAllHeight) { + textY = height - textAllHeight; + } + } + textY += textAscent;// 在绘画的时候,必须添加Ascent的高度. + textY += spacingBefore + lineSpacing;//james:加上"段前间距"+“行间距” + return textY; + } + + + public static int calculateTextX(Style style, Font rfont, String paint_str, int width, int textWidth, int horizontalAlignment) { + return calculateTextX(style, rfont, paint_str, width, textWidth, horizontalAlignment, 1); + } + + /** + * 计算X宽度 + * + * @param style 样式 + * @param rfont 字体 + * @param paint_str 字符串 + * @param width 宽度 + * @param textWidth 文本宽度 + * @param horizontalAlignment 垂向对齐 + * @return X宽度 + */ + public static int calculateTextX(Style style, Font rfont, String paint_str, int width, int textWidth, int horizontalAlignment, int scale) { + int textX = style.getPaddingLeft() * scale; + if (horizontalAlignment == Constants.CENTER) { + textX += (width - textWidth - textX) / 2; + } else if (horizontalAlignment == Constants.RIGHT) { + textX = width - style.getPaddingRight() * scale - textWidth; +//// // TODO alex:just for flash print && for font.Tahoma +// if (Boolean.TRUE == FRCoreContext.TMAP.get() +// && ComparatorUtils.equals(rfont.getFontName(), "Tahoma")) { +// textX -= paint_str.length() / 3; +// } + } + return textX; + } + + /** + * 计算X宽度 + * + * @param style 样式 + * @param width 宽度 + * @param textWidth 文本宽度 + * @param horizontalAlignment 垂向对齐 + * @param resolution 分辨率 + * @return X宽度 + */ + public static double calculateTextX(Style style, int width, int textWidth, int horizontalAlignment, int resolution) { + return calculateTextX(style, width, textWidth, horizontalAlignment, resolution, 1); + } + + /** + * 计算文本X位置 + * + * @param style 样式 + * @param width 宽度 + * @param textWidth 文本宽度 + * @param horizontalAlignment 水平对齐 + * @return X宽度 + */ + public static double calculateTextX(Style style, int width, int textWidth, int horizontalAlignment, int resolution, int scale) { + double textX = padding2PixExcludeRight(style.getPaddingLeft(), resolution); + if (horizontalAlignment == Constants.CENTER) { + textX += (width - textWidth - textX) / 2f; + } else if (horizontalAlignment == Constants.RIGHT) { + textX = width - style.getPaddingRight() * scale - textWidth; + } + return textX; + } + + /** + * 将缩减、段间距转为对应dpi下的pix Ps:除了右缩进 + * + * @param padding + * @param resolution + * @return + */ + public static double padding2PixExcludeRight(int padding, int resolution) { + return PX.toPixWithResolution(padding, resolution); + } + + /** + * 将右缩进转为对应dpi下的pix + * + * @param paddingRight + * @param resolution + * @return + */ + public static double paddingRight2Pix(int paddingRight, int resolution) { + if (paddingRight == Style.DEFAULT_PADDING) { + return 0; + } + return paddingRight; + } + + public static boolean isAutomaticLine(Style style, int horizontalAlignment, boolean textLonger) { + return horizontalAlignment == Constants.DISTRIBUTED + && style.getTextStyle() == Style.TEXTSTYLE_WRAPTEXT + || horizontalAlignment == Constants.DISTRIBUTED + && style.getTextStyle() == Style.TEXTSTYLE_SINGLELINE + && !textLonger; + } + + public static boolean isDistributeAlign(Style style, int horizontalAlignment, boolean textLonger) { + return horizontalAlignment == Constants.DISTRIBUTED + && style.getTextStyle() == Style.TEXTSTYLE_SINGLELINE + && textLonger; + } + + public static void drawTextWihenDistributeAlign(Graphics2D g2d, String paint_str, FontMetrics cellFM, int width, int textX, int textY) { + drawTextWihenDistributeAlign(g2d, paint_str, cellFM, width, textX, textY, 1f); + } + + /** + * 画字符串:分散对齐 + * @param scale 缩放比例,主目前要用于删除线、下划线及阴影的绘制 + */ + public static void drawTextWihenDistributeAlign(Graphics2D g2d, String paint_str, FontMetrics cellFM, int width, int textX, int textY, float scale) { + String lineText = getSingleLineText(paint_str, cellFM, width); + if (StringUtils.isNotEmpty(lineText)) { + GraphDrawHelper.drawString4DistributeAlign(g2d, lineText, textX, textY, width, scale); + } + } + + /** + * 获取用于单行显示的text + * + * @param lineText 分行显示时第i行的内容,但是也可能单行 + * @param cellFM 字体 + * @param width 宽度 + * @return 拆分后的字符串 + */ + private static String getSingleLineText(String lineText, FontMetrics cellFM, int width) { + // 单行显示时的分散对齐实现e + // 串长大于列宽时需要特别处理:只从中抽取合适长度的串值显示 + StringBuffer strBuff = new StringBuffer(); + for (int charIndex = 0; charIndex < lineText.length(); charIndex++) { + strBuff.append(lineText.charAt(charIndex)); + int buffWidth = cellFM.stringWidth(new String(strBuff)); + if (buffWidth > width) { //长度足够了,开始显示 + return strBuff.substring(0, 0 == charIndex ? 0 : charIndex - 1);//只画一行 + } + } + //上面的width没有减去padding-left,可能啥也没画 + return strBuff.toString(); + } + + /** + * 将输入字符串转换为实际字符,\代表转义字符。 + * + * @param text 字符串 + * @return the real value 实际字符 + */ + public static String textToString(String text) { + //跟这里的drawText算法是一致的,这样"所见即所得", + //如果把drawText的参数text先用此方法转换也行的,但是会遍历俩次,所以先留着 + if (text == null) { + return ""; + } + + int len = text.length(); + StringBuffer sb = new StringBuffer(len); + + for (int i = 0; i < len; i++) { + char c = text.charAt(i); + if (c == '\\' && i + 1 < len) { + char next = text.charAt(i + 1); + if (next == 'n') { + i++; + c = '\n'; + } else if (next == '\\') { + i++; + } + + } + sb.append(c); + } + return sb.toString(); + } + + /** + * daniel: 自动换行算法, 这个算法要求跟DHTML中Table的自动换行表现结果一样 + * 所以统一72dpi进行处理 + * + * @param text + * @param style + * @param paintWidth + * @return + */ + public static List getLineTextList(String text, Style style, Font font, double paintWidth, int resolution) { + List lineTextList = new ArrayList(); + if (text == null || text.length() <= 0) { + return lineTextList; + } + + style = style == null ? Style.DEFAULT_STYLE : style; + + if (style.getRotation() != 0) { + lineTextList.add(text); + return lineTextList; + } + + if (style.getTextStyle() != Style.TEXTSTYLE_WRAPTEXT) { + return lineTextListNotChangeLine(lineTextList, text); + } + // 自动换行 + else { + UNIT width = FU.valueOfPix((int) paintWidth, resolution); + return lineTextListAutoChangeLine(lineTextList, text, font, style, width, resolution); + } + } + + private static List lineTextListNotChangeLine(List lineTextList, String text) { + char tmpChar; + StringBuffer tmpTextBuf = new StringBuffer(); + for (int t = 0; t < text.length(); t++) { + tmpChar = text.charAt(t); + if (tmpChar == '\\') {// 判断是否是 "\n" + if (t + 1 < text.length() && text.charAt(t + 1) == 'n') { + // 是"\n"字符串,但不是换行符. + t++; + lineTextList.add(tmpTextBuf.toString()); + tmpTextBuf.delete(0, tmpTextBuf.length()); + } else { + tmpTextBuf.append(tmpChar); + } + } else { + tmpTextBuf.append(tmpChar); + } + } + + // 最后一个 + if (tmpTextBuf.length() > 0) { + lineTextList.add(tmpTextBuf.toString()); + tmpTextBuf.delete(0, tmpTextBuf.length()); + } + + return lineTextList; + } + + /** + * 这里需要用resolution 72的dpi进行分行,因为96dpi会导致font有小数导致获取的宽度不正确 + * + * @param lineTextList + * @param text + * @param style + * @return + */ + private static List lineTextListAutoChangeLine(List lineTextList, String text, Font font, Style style, UNIT unitWidth, int resolution) { + + AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess(); + if (process != null) { + return process.autoChangeLine(text, new ObjectHolder(style), unitWidth); + } + if (font == null) { + font = style.getFRFont(); + } + FontMetrics fontMetrics = GraphHelper.getFontMetrics(font); + double paintWidth = unitWidth.toPixD(resolution); + double width = paintWidth - style.getPaddingLeft() - style.getPaddingRight() - style.getBorderLeftWidth(); + StringBuffer lineTextBuf = new StringBuffer(); + int lineTextWidth = 0; + + StringBuffer wordBuf = new StringBuffer(); + int wordWidth = 0; + int[] tmpWidth = new int[2]; + tmpWidth[0] = wordWidth; + tmpWidth[1] = lineTextWidth; + + lineTextListDealWithText(text, lineTextList, width, tmpWidth, wordBuf, lineTextBuf, fontMetrics); + + // 最后处理 + if (tmpWidth[1] + tmpWidth[0] > width && lineTextBuf.length() > 0) { + lineTextList.add(lineTextBuf.toString()); + lineTextList.add(wordBuf.toString()); + } else { + lineTextBuf.append(wordBuf); + lineTextList.add(lineTextBuf.toString()); + } + return lineTextList; + } + private static void lineTextListDealWithText(String text, List lineTextList, double width, int[] tmpWidth, + StringBuffer wordBuf, StringBuffer lineTextBuf, FontMetrics fontMetrics) { + for (int t = 0; t < text.length(); t++) { + if (t != 0 && isNumOrLetter(text.charAt(t)) && isNumOrLetter(text.charAt(t - 1))) { + dealWithTextNumOrLetter(text, t, lineTextList, width, tmpWidth, wordBuf, lineTextBuf, fontMetrics); + } else if (text.charAt(t) == '\n' || (text.charAt(t) == '\r' && t + 1 < text.length() - 1 && text.charAt(t + 1) != '\n')) { + dealWithTextChangeLineSymbol(text, t, lineTextList, width, tmpWidth, wordBuf, lineTextBuf, fontMetrics); + } else if (text.charAt(t) == '\\' && t + 1 < text.length() && text.charAt(t + 1) == 'n') {// 判断是否是 "\n" + // 是"\n"字符串,但不是换行符,依然需要换行. + dealWidthTextManualChangeLine(text, t, lineTextList, width, tmpWidth, wordBuf, lineTextBuf, fontMetrics); + // 需要跳过后面的n + t++; + } else { + int increaseStep = 0; + if (text.charAt(t) == '\\' && t + 1 < text.length() && text.charAt(t + 1) == '\\') {// 判断是否是转义字符'\' + // _denny: 增加了转义字符'\\'用来表示\,使"\n"可以输入 + t++; + increaseStep++; + } + if (tmpWidth[1] + tmpWidth[0] > width && lineTextBuf.length() > 0) { + if (isPunctuationAtLineHead(t, text)) { + for (int index = lineTextBuf.length(); index > 0; index--) { + char prec = lineTextBuf.charAt(index - 1); + lineTextBuf.deleteCharAt(index - 1); + if (!isPunctuation(prec)) { + break; + } + } + } + lineTextList.add(lineTextBuf.toString()); + lineTextBuf.delete(0, lineTextBuf.length()); + tmpWidth[1] = isPunctuationAtLineHead(t, text) ? dealWithPunctuationAtLinehead(t, fontMetrics, text, lineTextBuf, wordBuf.length(), increaseStep) : 0; + } + lineTextBuf.append(wordBuf); + tmpWidth[1] += tmpWidth[0]; + + wordBuf.delete(0, wordBuf.length()); + tmpWidth[0] = 0; + wordBuf.append(text.charAt(t)); + tmpWidth[0] = fontMetrics.charWidth(text.charAt(t)); + } + } + } + + + + /** + * 标点符号是否在换行后的行首 + */ + private static boolean isPunctuationAtLineHead(int t, String text) { + return t > 1 && BaseUtils.isPunctuation(text.charAt(t - 1)); + } + + private static int dealWithPunctuationAtLinehead(int t, FontMetrics fontMetrics, String text, StringBuffer lineTextBuf, int wordBufLength, int increaseStep) { + //lineTextBuf 最后一个字符下标 与 text当前字符下标 t 的距离 + 1 + int indexDistance = 1 + wordBufLength + increaseStep; + if (t < indexDistance) { + return 0; + } + int lineWidth = 0; + for (int index = t - indexDistance; index >= 0; index--) { + lineWidth += fontMetrics.charWidth(text.charAt(index)); + lineTextBuf.insert(0, text.charAt(index)); + if (!isPunctuation(text.charAt(index))) { + break; + } + } + return lineWidth; + } + + private static void dealWithTextNumOrLetter(String text, int t, List lineTextList, double width, int[] tmpWidth, + StringBuffer wordBuf, StringBuffer lineTextBuf, FontMetrics fontMetrics) { + if (tmpWidth[0] + fontMetrics.charWidth(text.charAt(t)) > width) { + if (tmpWidth[1] > 0) { + lineTextList.add(lineTextBuf.toString()); + lineTextBuf.delete(0, lineTextBuf.length()); + tmpWidth[1] = 0; + } + + lineTextList.add(wordBuf.toString()); + wordBuf.delete(0, wordBuf.length()); + tmpWidth[0] = 0; + } + + wordBuf.append(text.charAt(t)); + tmpWidth[0] += fontMetrics.charWidth(text.charAt(t)); + } + + private static void dealWithTextChangeLineSymbol(String text, int t, List lineTextList, double width, int[] tmpWidth, + StringBuffer wordBuf, StringBuffer lineTextBuf, FontMetrics fontMetrics) { + wordBuf.append('\n'); + if (tmpWidth[1] + tmpWidth[0] > width && lineTextBuf.length() > 0) { + lineTextList.add(lineTextBuf.toString()); + lineTextList.add(wordBuf.toString()); + } else { + lineTextBuf.append(wordBuf); + lineTextList.add(lineTextBuf.toString()); + } + lineTextBuf.delete(0, lineTextBuf.length()); + tmpWidth[1] = 0; + wordBuf.delete(0, wordBuf.length()); + tmpWidth[0] = 0; + } + + private static void dealWidthTextManualChangeLine(String text, int t, List lineTextList, double width, int[] tmpWidth, + StringBuffer wordBuf, StringBuffer lineTextBuf, FontMetrics fontMetrics) { + t++;// 忽略'n'字符. + wordBuf.append('\n'); + if (tmpWidth[1] + tmpWidth[0] > width && lineTextBuf.length() > 0) { + lineTextList.add(lineTextBuf.toString()); + lineTextList.add(wordBuf.toString()); + } else { + lineTextBuf.append(wordBuf); + lineTextList.add(lineTextBuf.toString()); + } + lineTextBuf.delete(0, lineTextBuf.length()); + tmpWidth[1] = 0; + wordBuf.delete(0, wordBuf.length()); + tmpWidth[0] = 0; + } + + + /** + * @param cuChar + * @return + * @see StableUtils + * @deprecated + */ + public static boolean isNum(char cuChar) { + return StableUtils.isNum(cuChar); + } + + + /** + * 判断字符是否为数字或字母 + * + * @param curChar 被检查的字符 + * @return 是否为数字或字母 + */ + public static boolean isNumOrLetter(char curChar) { + return GeneralUtils.isLetter(curChar) || StableUtils.isNum(curChar); + } + + public static boolean isPunctuation(char c) { + int type = Character.getType(c); + return type == Character.OTHER_PUNCTUATION + || type == Character.DASH_PUNCTUATION + || type == Character.START_PUNCTUATION + || type == Character.END_PUNCTUATION + || type == Character.CONNECTOR_PUNCTUATION; + } + + + public static List getLineTextList(String text, Style style, Font font, double paintHeight, double paintWidth) { + return getLineTextList(text, style, font, paintHeight, paintWidth, Constants.DEFAULT_PRINT_AND_EXPORT_RESOLUTION); + } + + /** + * james daniel 放一起 + * 同时含有height和width参数表示会根据style自动判断字体为竖排还是横排 + * TODO + */ + public static List getLineTextList(String text, Style style, Font font, double paintHeight, double paintWidth, int resolution) { + //正常文字 + if (style == null + || style.getVerticalText() != Style.VERTICALTEXT) {//james:正常的文字时 + return BaseUtils.getLineTextList(text, style, font, paintWidth, resolution); + } + ExtraClassManagerProvider pluginProvider = PluginModule.getAgent(PluginModule.ExtraCore); + if (pluginProvider != null) { + VerticalTextProcessor processor = pluginProvider.getSingle(VerticalTextProcessor.XML_TAG, DefaultVerticalTextProcessor.class); + String[] res = processor.process(text, style, font, paintHeight, paintWidth, resolution); + return Arrays.asList(res); + } + String[] res = new DefaultVerticalTextProcessor().process(text, style, font, paintHeight, paintWidth, resolution); + return Arrays.asList(res); + } + + /** + * 返回边框宽 + * + * @param borderType 边框类型 + * @return 宽度 + */ + public static int getBorderWidth(int borderType) { + switch (borderType) { + case Constants.LINE_NONE: + return 0; + case Constants.LINE_SLIM: + return 1; + case Constants.LINE_THIN: + return 1; + case Constants.LINE_DASH: + return 1; + case Constants.LINE_HAIR: + return 1; + case Constants.LINE_HAIR2: + return 1; + case Constants.LINE_THICK: + return 3; + case Constants.LINE_DOT: + return 1; + default: + return 2; + } + } + + /** + * 将边框转为对应的字符串描述 + * + * @param borderStyle 边框线型 + * @return web端对应的边框 + */ + public static String border2Style(int borderStyle) { + switch (borderStyle) { + case Constants.LINE_NONE: + return "none"; + case Constants.LINE_SLIM: + return "solid"; + case Constants.LINE_THIN: + return "solid"; + case Constants.LINE_MEDIUM: + return "solid"; + case Constants.LINE_THICK: + return "solid"; + case Constants.LINE_DOUBLE: + return "double"; + case Constants.LINE_DOT: + return "double"; + case Constants.LINE_DASH_DOT: + return "double"; + case Constants.LINE_DASH_DOT_DOT: + return "dotted"; + default: + return "dashed"; + } + } + + /** + * 克隆对象 + * + * @param object 对象 + * @return 克隆出的对象 + * @throws CloneNotSupportedException 不被支持的克隆异常 + * @see StableUtils#cloneObject(Object) + * @deprecated + */ + public static Object cloneObject(Object object) throws CloneNotSupportedException { + return StableUtils.cloneObject(object); + } + + + /** + * 把java.util.Map转成一段JSONObject的String与上面方法对应 + * + * @param map map对象 + * @return json对象 + * @throws JSONException json异常 + */ + public static JSONObject map2JSON(Map map) throws JSONException { + JSONObject jo = new JSONObject(); + Iterator iter = map.keySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + Object value = entry.getValue(); + if (value instanceof FArray) { + JSONArray ja = new JSONArray(); + FArray array = (FArray) value; + for (int i = 0; i < array.length(); i++) { + ja.put(array.elementAt(i)); + } + value = ja; + } + jo.put((String) entry.getKey(), value); + } + return jo; + } + + /** + * 将一个对象转化成json样式的字符串 + * + * @param o 待转化的对象 + * @return json样式的字符串 + * @throws JSONException json异常 + * @see EmbedJson#encode(Object) (Object) + * @deprecated + */ + public static String jsonEncode(Object o) throws JSONException { + return EmbedJson.encode(o); + } + + + /** + * 将一个字符串转化成JSON格式的对象 + * + * @param str 要转化的字符串 + * @return JSON格式的对象 + * @throws JSONException json异常 + * @see JSONUtils#jsonDecode(String) + * @deprecated + */ + public static Object jsonDecode(String str) throws JSONException { + return JSONUtils.jsonDecode(str); + } + + /** + * 检查图片1和2是否相同. + * + * @param img1 图片1 + * @param img2 图片2 + * @return 图片1和2是否相同 + */ + public static boolean imageEquals(Image img1, Image img2) { + if (img1 == img2) { + return true; + } + + if (img1 == null || img2 == null) {//null < not null + return img1 == null && img2 == null; + } + + //开始比较图片. + byte[] buf1 = GeneralXMLTools.imageEncode(img1); + byte[] buf2 = GeneralXMLTools.imageEncode(img2); + if (buf1.length != buf2.length) { + return false; + } + + for (int i = 0; i < buf1.length; i++) { + if (buf1[i] != buf2[i]) { + return false; + } + } + + return true; + } + + /** + * 根据数据集名获取数据模型 + * + * @param cal 算子 + * @param tdName 列表名 + * @return 数据模型 + */ + public static DataModel getDataModelFromTableDataName(Calculator cal, String tdName) { + String tableDataName = tdName; + //先看当前的报表中的私有数据源 + DataModel resultSet = SynchronizedLiveDataModelUtils.getSELiveDataModel4Share(cal, tableDataName); + if (resultSet == null) { + TableData td = TableDataAssist.getTableData(cal, tableDataName); + resultSet = td == null ? null : td.createDataModel(cal); + } + return resultSet; + } + + + /** + * kunsnat: List转化为二维表 + * + * @param list 列表 + * @return 二维数组 + */ + public static Object[][] list2Array2D(List list) { + int rowNum = list.size(); + int colNum = 0; + for (int i = 0; i < rowNum; i++) { + List row = (List) list.get(i); + if (row.size() > colNum) { + colNum = row.size(); + } + } + Object[][] result = new Object[rowNum][colNum]; + + for (int i = 0; i < rowNum; i++) { + List row = (List) list.get(i); + for (int j = 0; j < colNum; j++) { + if (j < row.size()) { + result[i][j] = row.get(j); + } else { + result[i][j] = null; + } + } + } + + return result; + } + + /** + * 判断当前Env下是否有lic文件 + * + * @return 判断当前Env下是否有lic文件 + */ + public static boolean checkLicExist() { + + if (ServerPreferenceConfig.getInstance().isLicUseLock()) { + return true;//加密狗 + } else if (!LicenseConfigManager.getInstance().isUseFile()) { + //不使用文件,说明用户配置了注册信息,一定是注册了 + return true; + } + + try { + String licName = FRContext.getCommonOperator().getLicenseName(); + byte[] bytes = WorkContext.getWorkResource().readFully(StableUtils.pathJoin(ProjectConstants.RESOURCES_NAME, licName)); + return bytes != null && bytes.length != 0; + } catch (Exception ignored) { + } + + return false; + } + + /** + * 判断是否内容为图表相关. + * + * @param cellOption 单元格属性 + * @return 返回是否为图表单元格相关. + */ + public static boolean isChartCell(JSONObject cellOption) { + if (cellOption != null) { + JSONObject value = cellOption.optJSONObject("value"); + if (value != null) { + return ComparatorUtils.equals("simplechart", value.optString("type")); + } + } + + return false; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/common/FormDesignerUtil.java b/designer-form/src/main/java/com/fr/design/fit/common/FormDesignerUtil.java new file mode 100644 index 000000000..6e0739a01 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/FormDesignerUtil.java @@ -0,0 +1,45 @@ +package com.fr.design.fit.common; + +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XElementCase; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.form.FormElementCaseProvider; +import com.fr.form.ui.ElementCaseEditor; + +import java.util.Iterator; +import java.util.List; + +/** + * Created by kerry on 2020-06-12 + */ +public class FormDesignerUtil { + private FormDesignerUtil(){ + + } + public static XElementCase getXelementCase(XLayoutContainer rootContainer, FormElementCaseProvider elementCaseProvider) { + for (int i = 0; i < rootContainer.getComponentCount(); i++) { + XCreator creator = rootContainer.getXCreator(i); + if (creator instanceof XElementCase && elementCaseProvider == ((ElementCaseEditor) creator.toData()).getElementCase()) { + return (XElementCase) creator; + } + if (creator instanceof XLayoutContainer) { + XElementCase temp = getXelementCase((XLayoutContainer) creator, elementCaseProvider); + if (temp != null) { + return temp; + } + } + } + return null; + } + + + public static void removeDeletedEC(List currentECList, List waitToProcessECList) { + Iterator iterator = waitToProcessECList.iterator(); + while (iterator.hasNext()) { + Object editor = iterator.next(); + if (!currentECList.contains(editor)) { + iterator.remove(); + } + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/common/LayoutTool.java b/designer-form/src/main/java/com/fr/design/fit/common/LayoutTool.java new file mode 100644 index 000000000..6bebbbbe8 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/LayoutTool.java @@ -0,0 +1,177 @@ +package com.fr.design.fit.common; + +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteBodyLayout; +import com.fr.design.designer.creator.XWAbsoluteLayout; +import com.fr.design.designer.creator.cardlayout.XWCardLayout; +import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; +import com.fr.design.fit.NewJForm; +import com.fr.design.mainframe.FormArea; +import com.fr.design.mainframe.JForm; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.form.ui.container.WAbsoluteBodyLayout; +import com.fr.form.ui.container.WFitLayout; +import com.fr.form.ui.container.WLayout; +import com.fr.form.ui.widget.CRBoundsWidget; +import com.fr.general.FRScreen; +import com.fr.log.FineLoggerFactory; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.Toolkit; + +/** + * @description:布局工具类 + * @author: Henry.Wang + * @create: 2020/09/03 14:18 + */ +public class LayoutTool { + /** + * @Description: 获取布局类型 + * @param jForm + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:31 + */ + public static int getFormLayoutType(JForm jForm) { + JForm tempJForm = jForm; + if (tempJForm == null) + tempJForm = TemplateTool.getCurrentEditingNewJForm(); + if (tempJForm == null || tempJForm.getFormDesign().getRootComponent() == null) + return -1; + return ((WFitLayout) tempJForm.getFormDesign().getRootComponent().toData()).getBodyLayoutType().getTypeValue(); + + } + + /** + * @Description: 是否为绝对布局 + * @param jForm + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:31 + */ + public static boolean absoluteLayoutForm(NewJForm jForm) { + if (getFormLayoutType(jForm) == 1) + return true; + return false; + } + + /** + * @Description: 如果为绝对布局则获取XWAbsoluteBodyLayout,否则返回null + * @param jForm + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:26 + */ + public static XWAbsoluteBodyLayout getXWAbsoluteBodyLayout(NewJForm jForm) { + NewJForm tempJForm = jForm; + if (tempJForm == null) + tempJForm = TemplateTool.getCurrentEditingNewJForm(); + if (tempJForm != null) { + if (absoluteLayoutForm(tempJForm)) { + XLayoutContainer xLayoutContainer = tempJForm.getFormDesign().getRootComponent(); + if (xLayoutContainer != null && xLayoutContainer.getComponentCount() > 0) { + Component component = xLayoutContainer.getComponent(0); + if (component instanceof XWAbsoluteBodyLayout) { + return (XWAbsoluteBodyLayout) component; + } + } + } + } + return null; + } + + /** + * @Description: 通过子组件的位置获取绝对布局body的尺寸。为什么不直接调用getRootComponent().toData().getContentHeight()呢?因为在截断的情况下就不不一致了 + * @param newJForm + * @return: + * @Author: Henry.Wang + * @date: 2020/9/11 15:24 + */ + public static Rectangle getAbsoluteBodySize(NewJForm newJForm) { + int width = 0; + int height = 0; + XWAbsoluteBodyLayout xwAbsoluteBodyLayout = LayoutTool.getXWAbsoluteBodyLayout(newJForm); + if (xwAbsoluteBodyLayout != null) { + WAbsoluteBodyLayout wAbsoluteBodyLayout = xwAbsoluteBodyLayout.toData(); + if (wAbsoluteBodyLayout.getWidgetCount() > 0) { + for (int i = 0; i < wAbsoluteBodyLayout.getWidgetCount(); i++) { + Rectangle rectangle = ((CRBoundsWidget) wAbsoluteBodyLayout.getWidget(i)).getBounds(); + if (rectangle.x + rectangle.width > width) + width = rectangle.x + rectangle.width; + if (rectangle.y + rectangle.height > height) + height = rectangle.y + rectangle.height; + } + } + } + return new Rectangle(0, 0, width, height); + } + + + public static int getBodyHeight(NewJForm newJForm) { + return newJForm.getFormDesign().getRootComponent().toData().getContentHeight(); + } + + public static int getBodyWidth(NewJForm newJForm) { + return newJForm.getFormDesign().getRootComponent().toData().getContentWidth(); + } + + /** + * @Description: 对绝对画布块里的组件进行缩放 + * @param xCreator + * @param scale 缩放比例 + * @return: + * @Author: Henry.Wang + * @date: 2020/10/26 20:39 + */ + public static void scaleAbsoluteBlockComponentsBounds(XCreator xCreator, Double scale) { + try { + Component[] components = xCreator.getComponents(); + for (Component component : components) { + if (component instanceof XWCardMainBorderLayout) { + XWCardLayout xwCardLayout = ((XWCardMainBorderLayout)component).getCardPart(); + for (Component tabComponent : xwCardLayout.getComponents()) { + scaleAbsoluteBlockComponentsBounds((XCreator) tabComponent, scale); + scaleAbsoluteBlockComponentsBoundsInternal((XCreator) tabComponent, scale); + } + } else if (component instanceof XWAbsoluteLayout) { + scaleAbsoluteBlockComponentsBounds((XCreator) component, scale); + scaleAbsoluteBlockComponentsBoundsInternal((XCreator) component, scale); + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } + + } + + public static void scaleAbsoluteBlockComponentsBoundsInternal(XCreator parentXCreator, Double scale) { + if (parentXCreator instanceof XWAbsoluteLayout) { + XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) parentXCreator; + Component[] absoluteComponents = xwAbsoluteLayout.getComponents(); + for (Component absoluteComponent : absoluteComponents) { + XCreator xCreator = (XCreator) absoluteComponent; + Rectangle bounds = new Rectangle(absoluteComponent.getBounds()); + Rectangle newBounds = new Rectangle((int) (bounds.x * scale), (int) (bounds.y * scale), (int) (bounds.width * scale), (int) (bounds.height * scale)); + WLayout wAbsoluteLayout = xwAbsoluteLayout.toData(); + wAbsoluteLayout.setBounds(xCreator.toData(), newBounds); + xCreator.setBounds(newBounds); + LayoutUtils.layoutContainer(xCreator); + } + } + } + + /** + * @Description: 获取老预览时的缩放比例 + * @return: + * @Author: Henry.Wang + * @date: 2020/10/26 20:39 + */ + public static double getContainerPercent(){ + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + double screenValue = FRScreen.getFRScreenByDimension(screen).getValue(); + return screenValue / FormArea.DEFAULT_SLIDER; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java b/designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java new file mode 100644 index 000000000..a937ba2d4 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/NewFormStyle.java @@ -0,0 +1,2030 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.fit.common; + +import com.fr.base.BaseFormula; +import com.fr.base.CoreDecimalFormat; +import com.fr.base.FRContext; +import com.fr.base.FormatRepository; +import com.fr.base.GraphHelper; +import com.fr.base.ImageProvider; +import com.fr.base.Painter; +import com.fr.base.Style; +import com.fr.base.Utils; +import com.fr.base.background.ImageBackground; +import com.fr.common.annotations.Open; +import com.fr.data.DataBaseUtils; +import com.fr.general.Background; +import com.fr.general.ComparatorUtils; +import com.fr.general.DateUtils; +import com.fr.general.DefaultValues; +import com.fr.general.FRFont; +import com.fr.general.GeneralUtils; +import com.fr.json.JSONException; +import com.fr.json.JSONObject; +import com.fr.stable.AssistUtils; +import com.fr.stable.Constants; +import com.fr.stable.CoreGraphHelper; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.unit.PT; +import com.fr.stable.web.Repository; +import com.fr.stable.web.ServletContext; +import com.fr.stable.web.ServletContextAdapter; +import org.jetbrains.annotations.Nullable; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Rectangle2D; +import java.io.InvalidObjectException; +import java.io.Serializable; +import java.sql.Clob; +import java.text.DateFormat; +import java.text.Format; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 用于表示样式的类,包括边框、颜色、字体、缩进、间距等 + * 注意:这是一个开放类,所有的修改都要注意保持兼容 + */ +@Open +public class NewFormStyle extends Style implements Serializable, Cloneable { + + // temp rectangle + private static Rectangle2D tempRectangle2D = new Rectangle2D.Double(0, 0, 0, 0); + + public static final int TEXTSTYLE_WRAPTEXT = 0; // 换行. + public static final int TEXTSTYLE_SINGLELINE = 1; // 单行,超出部分不显示. + public static final int TEXTSTYLE_SINGLELINEADJUSTFONT = 2; // 单行,调整字体来显示所有的字. + public static final int TEXTSTYLE_MULTILINEADJUSTFONT = 3; //多行,固定单元格高和宽,调整字体来显示所有的字 + + public static final int VERTICALTEXT = 1;// 竖排,与Excel中的设置值相同 + public static final int HORIZONTALTEXT = 0;// 横排 + + public static final int LEFT_TO_RIGHT = 1;// JAMES:垂直文字时,文字为从左向右顺序排列 + public static final int RIGHT_TO_LEFT = 0;// JAMES:垂直文字时,文字为从右向左顺序排列 + + //EXCEL 宋体11号字, 一个缩进单位对应96dpi下27px + public static final int PADDING_ARG = 27; + public static final int DEFAULT_PADDING = 2; + /** + * 细线透明度值 + */ + public static final double FACTORY_ALPHA = 0.4; + public static final NewFormStyle NULL_STYLE = null; + + /** + * Default Style + */ + public static final NewFormStyle DEFAULT_STYLE = new NewFormStyle(); + + /** + * Border Style + */ + public static final NewFormStyle BORDER_STYLE = new NewFormStyle(); + + private static final long serialVersionUID = -1675056857456167839L; + private static final int MAX_FONT_SIZE = 100; + private static final int N_SIZE = 9; + private static final int MIN_SIZE = 8; + private static final int MAX_SIZE = 26; + + private static final int LINE_HEIGHT_FIX = 4; + private static final int LINE_HEIGHT_FIX2 = 3; + + private static class ContentLineGroup { + Style style; + List newLineTextList; + int newTextHeight; + + public ContentLineGroup(Style style, List lineList, int textHeight) { + this.style = style; + this.newLineTextList = lineList; + this.newTextHeight = textHeight; + } + + public int totalHeight() { + return newTextHeight * newLineTextList.size(); + } + } + + private static Map clsFontFamily = null; + + // 全局Style的map + private static Map initializeStyle = new ConcurrentHashMap();// + + static { + ServletContext.addServletContextListener(new ServletContextAdapter() { + @Override + public void onServletStop() { + initializeStyle.clear(); + } + }); + } + + // format + private Format format = null; + + // element font. + private FRFont frFont = null; + + private Background background = null; + + // border. + private byte border_top = Constants.LINE_NONE; + private byte border_left = Constants.LINE_NONE; + private byte border_bottom = Constants.LINE_NONE; + private byte border_right = Constants.LINE_NONE; + private Color border_top_color = Color.BLACK; + private Color border_left_color = Color.BLACK; + private Color border_bottom_color = Color.BLACK; + private Color border_right_color = Color.BLACK; + + // alignment. + private int horizontal_alignment = Constants.NULL; + private int vertical_alignment = Constants.CENTER; + + // TextStyle + private int textStyle = NewFormStyle.TEXTSTYLE_WRAPTEXT; + + // james: verticalText + private int verticalText = NewFormStyle.HORIZONTALTEXT;// 默认为0,水平方向 + + // james: the direction of text when the text is vertical + private int textDirection = NewFormStyle.RIGHT_TO_LEFT;// 默认为从右向左的顺序 + + private int rotation = 0; + + private byte imageLayout = Constants.IMAGE_CENTER;//现在默认改为center了 + + //padding有两个计量单位, 一种是以前的pt, 一种是现在的, 为了兼容excel的 + //设计器中设置1个单位, 兼容为以前的27pt + // 左缩进 + private int paddingLeft = DEFAULT_PADDING; + // 右缩进 + private int paddingRight = DEFAULT_PADDING; + + // 段前间距 + private byte spacingBefore = 0; + // 段后间距 + private byte spacingAfter = 0; + // 行间距h + private byte lineSpacing = 0; + + private String contentClsCss = StringUtils.EMPTY; + private Map contentStyleCssMap = new HashMap(); + + private String borderClsCss = StringUtils.EMPTY; + private Map borderStyleCssMap = new HashMap(); + + /** + * Constructor. + */ + protected NewFormStyle() { + //peter:这里主动从Context, 获得默认的FRFont的值. + DefaultValues defaultValues = FRContext.getDefaultValues(); + this.frFont = defaultValues.getFRFont(); + + // HTML输出 CSS初始化 + this.contentClsCss = this.contentStyle2class(this.contentStyleCssMap); + this.borderClsCss = this.border2Class(this.borderStyleCssMap); + } + + private NewFormStyle(Background background, Format format, FRFont frFont, + int border_top, Color border_top_color, int border_bottom, Color border_bottom_color, + int border_left, Color border_left_color, int border_right, Color border_right_color, + int horizontal_alignment, int vertical_alignment, int textStyle, + int verticalText, int textDirection, int rotation, int imageLayout, + int paddingLeft, int paddingRight, int spacingBefore, int spacingAfter, int lineSpacing) { + this.background = background; + this.format = format; + this.frFont = frFont; + + this.border_top = (byte) border_top; + this.border_top_color = border_top_color; + this.border_bottom = (byte) border_bottom; + this.border_bottom_color = border_bottom_color; + this.border_left = (byte) border_left; + this.border_left_color = border_left_color; + this.border_right = (byte) border_right; + this.border_right_color = border_right_color; + + this.horizontal_alignment = (byte) horizontal_alignment; + this.vertical_alignment = (byte) vertical_alignment; + this.textStyle = (byte) textStyle; + + this.verticalText = (byte) verticalText; + this.textDirection = (byte) textDirection; + this.rotation = (short) rotation; + this.imageLayout = (byte) imageLayout; + + this.paddingLeft = paddingLeft; + this.paddingRight = paddingRight; + + this.spacingBefore = (byte) spacingBefore; + this.spacingAfter = (byte) spacingAfter; + this.lineSpacing = (byte) lineSpacing; + + // HTML输出 CSS初始化 + this.contentClsCss = this.contentStyle2class(this.contentStyleCssMap); + this.borderClsCss = this.border2Class(this.borderStyleCssMap); + } + + private static Map getclsFontFamily() { + if (clsFontFamily == null) { + clsFontFamily = new HashMap() { + { + put("Arial Black", "fnab"); + put("Basic Sans SF", "fnbs"); + put("Book Antiqua", "fnba"); + put("Calibri", "fnci"); + put("Comic Sans MS", "fncs"); + put("Courier New", "fncn"); + put("Elementary SF", "fnes"); + put("Garamond", "fngd"); + put("Georgia", "fnga"); + put("Letter Gothic", "fnlg"); + put("Lucida Console", "fnlc"); + put("Marigold", "fnmd"); + put("MS Sans Serif", "fnms"); + put("MS Gothic", "fnmg"); + put("MS PGothic", "fnmpg"); + put("MS Mincho", "fnmm"); + put("MS P Mincho", "fnmpm"); + put("MingLiU", "fnml"); + put("SimHei", "fnsh"); + put("System", "fnsm"); + put("Tahoma", "fnta"); + put("Times New Roman", "fntn"); + put("Trebuchet MS", "fntms"); + put("Verdana", "fnva"); + + put("SimSun", "fnss"); + put("Arial", "fnar"); + put("Microsoft YaHei", "fnyh"); + put("KaiTi", "fnkt"); + } + }; + } + + return clsFontFamily; + } + + /** + * 设置样式 + * + * @param format 格式g + * @return 样式y + */ + public NewFormStyle deriveFormat(Format format) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 获取实例 + */ + public static NewFormStyle getInstance(Format format) { + return DEFAULT_STYLE.deriveFormat(format); + } + + /** + * 设置字体 + * + * @param frFont 字体 + * @return 样式 + */ + public NewFormStyle deriveFRFont(FRFont frFont) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * getInstance + */ + public static NewFormStyle getInstance() { + NewFormStyle style = new NewFormStyle(); + + Object valueStyle = initializeStyle.get(style); + if (valueStyle != null) { + return (NewFormStyle) valueStyle; + } else { + initializeStyle.put(style, style); + return style; + } + } + + /** + * getInstance + */ + private static NewFormStyle getInstance(Background background, Format format, FRFont frFont, + int border_top, Color border_top_color, int border_bottom, Color border_bottom_color, + int border_left, Color border_left_color, int border_right, Color border_right_color, + int horizontal_alignment, int vertical_alignment, int textStyle, + int verticalText, int textDirection, int rotation, int imageLayout, + int paddingLeft, int paddingRight, int spacingBefore, int spacingAfter, int lineSpacing) { + NewFormStyle style = new NewFormStyle(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + + Object valueStyle = initializeStyle.get(style); + if (valueStyle != null) { + return (NewFormStyle) valueStyle; + } else { + initializeStyle.put(style, style); + return style; + } + } + + /** + * getInstance + */ + public static NewFormStyle getInstance(FRFont frFont) { + if (frFont == null) { + return NewFormStyle.getInstance(); + } + return DEFAULT_STYLE.deriveFRFont(frFont); + } + + /** + * 设置背景 + * + * @param background 背景 b + * @return 样式 y + */ + public NewFormStyle deriveBackground(Background background) { + if (background instanceof ImageBackground) { + return new NewFormStyle(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * getInstance + */ + public static NewFormStyle getInstance(Background background) { + return DEFAULT_STYLE.deriveBackground(background); + } + + /** + * 去掉边框和单元格背景 + * + * @return 样式y + */ + public NewFormStyle deriveBorderBackgroundNone() { + return getInstance(null, format, frFont, + Constants.LINE_NONE, border_top_color, Constants.LINE_NONE, border_bottom_color, + Constants.LINE_NONE, border_left_color, Constants.LINE_NONE, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置边框 + * + * @param border_top 上边框像素 + * @param border_top_color 上边框颜色s + * @param border_bottom 下 x + * @param border_bottom_color 下 x + * @param border_left 左 z + * @param border_left_color 左z + * @param border_right 右y + * @param border_right_color 右y + * @return 样式y + */ + public NewFormStyle deriveBorder(int border_top, Color border_top_color, + int border_bottom, Color border_bottom_color, + int border_left, Color border_left_color, + int border_right, Color border_right_color) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置上边框 + * + * @param border_top 上边框尺寸s + * @param border_top_color 上边框颜色 s + * @return 样式 y + */ + public NewFormStyle deriveBorderTop(int border_top, Color border_top_color) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置下边框 + * + * @param border_bottom 下边框尺寸 x + * @param border_bottom_color 下颜色x + * @return 样式y + */ + public NewFormStyle deriveBorderBottom(int border_bottom, Color border_bottom_color) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置左边框 + * + * @param border_left 尺寸 z + * @param border_left_color 颜色y + * @return 样式y + */ + public NewFormStyle deriveBorderLeft(int border_left, Color border_left_color) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置右边框 + * + * @param border_right 尺寸 c + * @param border_right_color 颜色 y + * @return 样式 y + */ + public NewFormStyle deriveBorderRight(int border_right, Color border_right_color) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置水平方向 + * + * @param horizontal_alignment 水平方向s + * @return 样式 y + */ + public NewFormStyle deriveHorizontalAlignment(int horizontal_alignment) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置垂直方向 + * + * @param vertical_alignment 垂直方向c + * @return 样式 + * @see Constants#TOP + * @see Constants#CENTER + * @see Constants#BOTTOM + */ + public NewFormStyle deriveVerticalAlignment(int vertical_alignment) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置单元格展示样式(自动换行, 单行显示, 多行显示等) + * + * @param textStyle 文字样式 + * @return 样式 + * @see NewFormStyle#TEXTSTYLE_WRAPTEXT + * @see NewFormStyle#TEXTSTYLE_SINGLELINE + * @see NewFormStyle#TEXTSTYLE_SINGLELINEADJUSTFONT + * @see NewFormStyle#TEXTSTYLE_MULTILINEADJUSTFONT + */ + public NewFormStyle deriveTextStyle(int textStyle) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置单元格方向 + * + * @param textDirection 文本方向w + * @return 样式t + */ + public NewFormStyle deriveTextDirection(int textDirection) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置单元格垂直方向 + * + * @param verticalText 垂直方向c + * @return 样式 + */ + public NewFormStyle deriveVerticalText(int verticalText) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置旋转方向 + * + * @param rotation 旋转方向 the new rotation of cell (between -90 and 90 degrees). + * @return 样式 + */ + public NewFormStyle deriveRotation(int rotation) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置图片布局 + * + * @param imageLayout the new image layout 图片布局t + * @return 样式 + * @see Constants#IMAGE_TILED + * @see Constants#IMAGE_CENTER + * @see Constants#IMAGE_EXTEND + */ + public NewFormStyle deriveImageLayout(int imageLayout) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置缩进 + * + * @param paddingLeft 左缩进 + * @param paddingRight 右缩进 + * @return 样式 + */ + public NewFormStyle derivePadding(int paddingLeft, int paddingRight) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置左缩进 + * + * @param paddingLeft 左缩进 + * @return 样式 + */ + public NewFormStyle derivePaddingLeft(int paddingLeft) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置右缩进 + * + * @param paddingRight 右缩进 + * @return 样式 + */ + public NewFormStyle derivePaddingRight(int paddingRight) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置段前间距 + * + * @param spacingBefore 段前间距d + * @return 样式 y + */ + public NewFormStyle deriveSpacingBefore(int spacingBefore) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置段后间距 + * + * @param spacingAfter 段后间距d + * @return 样式y + */ + public NewFormStyle deriveSpacingAfter(int spacingAfter) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 设置行间距 + * + * @param lineSpacing 行间距h + * @return 样式y + */ + public NewFormStyle deriveLineSpacing(int lineSpacing) { + return getInstance(background, format, frFont, + border_top, border_top_color, border_bottom, border_bottom_color, + border_left, border_left_color, border_right, border_right_color, + horizontal_alignment, vertical_alignment, textStyle, + verticalText, textDirection, rotation, imageLayout, + paddingLeft, paddingRight, spacingBefore, spacingAfter, lineSpacing); + } + + /** + * 对象转为json格式 + * + * @param repo 浏览器上下文 + * @param size 单元格大小 + * @return json格式数据 + */ + public JSONObject toJSONObject(Repository repo, Dimension size) throws JSONException { + JSONObject jo = new JSONObject(); + if (background != null) { + jo.put("background", background.toJSONObject(repo, size)); + } + // 不是默认值才输出,节省流量 + if (frFont != null && !ComparatorUtils.equals(frFont, FRContext.getDefaultValues().getFRFont())) { + jo.put("font", frFont.toJSONObject(repo)); + } + + if (!checkLeftRightTopBottom4b0()) { + jo.put("border", border2JSONObject()); + jo.put("borderCss", borderClsCss); + } + + createAlignAndTextStyleConfig(jo); + if (rotation != 0) { + jo.put("ro", rotation); + } + if (imageLayout != Constants.IMAGE_CENTER) { + jo.put("il", imageLayout); + } + createSpacingAndPaddingConfig(jo); + + return jo; + } + + private void createAlignAndTextStyleConfig(JSONObject jo) throws JSONException { + if (horizontal_alignment != Constants.NULL) { + jo.put("ha", horizontal_alignment); + } + if (vertical_alignment != Constants.CENTER) { + jo.put("va", vertical_alignment); + } + if (textStyle != TEXTSTYLE_WRAPTEXT) { + jo.put("ts", textStyle); + } + if (verticalText != NewFormStyle.HORIZONTALTEXT) { + jo.put("vt", verticalText); + } + if (textDirection != RIGHT_TO_LEFT) { + jo.put("td", textDirection); + } + jo.put("contentCss", contentClsCss); + } + + private void createSpacingAndPaddingConfig(JSONObject jo) throws JSONException { + if (paddingLeft != DEFAULT_PADDING) { + jo.put("pl", paddingLeft); + } + if (paddingRight != DEFAULT_PADDING) { + jo.put("pr", paddingRight); + } + if (spacingBefore != 0) { + jo.put("sb", spacingBefore); + } + if (spacingAfter != 0) { + jo.put("sa", spacingAfter); + } + if (lineSpacing != 0) { + jo.put("ls", lineSpacing); + } + } + + /** + * 获取字体 + */ + public FRFont getFRFont() { + if (this.frFont == null) { + this.frFont = FRContext.getDefaultValues().getFRFont(); + } + return this.frFont; + } + + /** + * Gets cell format. + */ + public Format getFormat() { + return this.format; + } + + /** + * Gets background. + */ + public Background getBackground() { + return this.background; + } + + /** + * Gets the type of border to use for the top border of the cell. + * + * @see Constants#LINE_NONE + * @see Constants#LINE_THIN + * @see Constants#LINE_MEDIUM + * @see Constants#LINE_DASH + * @see Constants#LINE_HAIR + * @see Constants#LINE_HAIR2 + * @see Constants#LINE_THICK + * @see Constants#LINE_DOUBLE + * @see Constants#LINE_DOT + * @see Constants#LINE_MEDIUM_DASH + * @see Constants#LINE_DASH_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT + * @see Constants#LINE_DASH_DOT_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT_DOT + * @see Constants#LINE_SLANTED_DASH_DOT + */ + public int getBorderTop() { + return this.border_top; + } + + /** + * 获取上边框线的宽度 + */ + public int getBorderTopWidth() { + return GraphHelper.getLineStyleSize(this.getBorderTop()); + } + + /** + * Gets the type of border to use for the left border of the cell. + * + * @see Constants#LINE_NONE + * @see Constants#LINE_THIN + * @see Constants#LINE_MEDIUM + * @see Constants#LINE_DASH + * @see Constants#LINE_HAIR + * @see Constants#LINE_HAIR2 + * @see Constants#LINE_THICK + * @see Constants#LINE_DOUBLE + * @see Constants#LINE_DOT + * @see Constants#LINE_MEDIUM_DASH + * @see Constants#LINE_DASH_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT + * @see Constants#LINE_DASH_DOT_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT_DOT + * @see Constants#LINE_SLANTED_DASH_DOT + */ + public int getBorderLeft() { + return this.border_left; + } + + public int getBorderLeftWidth() { + return GraphHelper.getLineStyleSize(this.getBorderLeft()); + } + + public int getBorderRightWidth() { + return GraphHelper.getLineStyleSize(this.getBorderRight()); + } + + public int getBorderBottomWidth() { + return GraphHelper.getLineStyleSize(this.getBorderBottom()); + } + + /** + * Gets the type of border to use for the bottom border of the cell. + * + * @see Constants#LINE_NONE + * @see Constants#LINE_THIN + * @see Constants#LINE_MEDIUM + * @see Constants#LINE_DASH + * @see Constants#LINE_HAIR + * @see Constants#LINE_HAIR2 + * @see Constants#LINE_THICK + * @see Constants#LINE_DOUBLE + * @see Constants#LINE_DOT + * @see Constants#LINE_MEDIUM_DASH + * @see Constants#LINE_DASH_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT + * @see Constants#LINE_DASH_DOT_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT_DOT + * @see Constants#LINE_SLANTED_DASH_DOT + */ + public int getBorderBottom() { + return this.border_bottom; + } + + /** + * Gets the type of border to use for the right border of the cell. + * + * @see Constants#LINE_NONE + * @see Constants#LINE_THIN + * @see Constants#LINE_MEDIUM + * @see Constants#LINE_DASH + * @see Constants#LINE_HAIR + * @see Constants#LINE_HAIR2 + * @see Constants#LINE_THICK + * @see Constants#LINE_DOUBLE + * @see Constants#LINE_DOT + * @see Constants#LINE_MEDIUM_DASH + * @see Constants#LINE_DASH_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT + * @see Constants#LINE_DASH_DOT_DOT + * @see Constants#LINE_MEDIUM_DASH_DOT_DOT + * @see Constants#LINE_SLANTED_DASH_DOT + */ + public int getBorderRight() { + return this.border_right; + } + + /** + * Gets the color of border to use for the top border of the cell. + */ + public Color getBorderTopColor() { + return this.border_top_color; + } + + /** + * Gets the color of border to use for the left border of the cell. + */ + public Color getBorderLeftColor() { + return this.border_left_color; + } + + /** + * Gets the color of border to use for the bottom border of the cell. + */ + public Color getBorderBottomColor() { + return this.border_bottom_color; + } + + /** + * Gets the color of border to use for the right border of the cell. + */ + public Color getBorderRightColor() { + return this.border_right_color; + } + + /** + * Gets the type of horizontal alignment for the cell + * + * @see BaseUtils#getAlignment4Horizontal(NewFormStyle style, Object value) + * @see BaseUtils#getAlignment4Horizontal(NewFormStyle style) + * @see Constants#LEFT + * @see Constants#CENTER + * @see Constants#RIGHT + * @deprecated suggest not directly use; + */ + public int getHorizontalAlignment() { + return this.horizontal_alignment; + } + + /** + * Gets the type of vertical alignment for the cell + * + * @see Constants#TOP + * @see Constants#CENTER + * @see Constants#BOTTOM + */ + public int getVerticalAlignment() { + return this.vertical_alignment; + } + + /** + * Gets the text style. + * + * @see NewFormStyle#TEXTSTYLE_WRAPTEXT + * @see NewFormStyle#TEXTSTYLE_SINGLELINE + * @see NewFormStyle#TEXTSTYLE_SINGLELINEADJUSTFONT + * @see NewFormStyle#TEXTSTYLE_MULTILINEADJUSTFONT + */ + public int getTextStyle() { + return textStyle; + } + + /** + * Gets the value of verticalText + */ + public int getVerticalText() { + return this.verticalText; + } + + /** + * Gets the value of textDirection + */ + public int getTextDirection() { + return this.textDirection; + } + + /** + * Gets the degree of rotation for the text in the cell + * (between -90 and 90 degrees). + */ + public int getRotation() { + return this.rotation; + } + + /** + * Gets the image layout + * + * @return the image layout + * @see Constants#IMAGE_TILED + * @see Constants#IMAGE_CENTER + * @see Constants#IMAGE_EXTEND + */ + public int getImageLayout() { + return imageLayout; + } + + /** + * get indentation value + */ + public int getPaddingLeft() { + return this.paddingLeft; + } + + /** + * get indentation value + */ + public int getPaddingRight() { + return this.paddingRight; + } + + /** + * @return the spacingBefore + */ + public byte getSpacingBefore() { + return spacingBefore; + } + + /** + * @return the spacingAfter + */ + public byte getSpacingAfter() { + return spacingAfter; + } + + /** + * @return the lineSpacing + */ + public byte getLineSpacing() { + return lineSpacing; + } + + + /** + * 如果单元格内容不为数字或者字符串的时候使用静态数据 + * + * @return + */ + public String getContentClsCss() { + return contentClsCss; + } + + /** + * 若value为数字或字符串需要判断一下是否可以转换为数字显示 + * + * @param value + * @return + */ + public String getContentClsCss(Object value) { + return this.contentStyle2class(this.contentStyleCssMap, value); + } + + /** + * getContentStyleCssMap + */ + public Map getContentStyleCssMap() { + return contentStyleCssMap; + } + + /** + * getBorderClsCss + */ + public String getBorderClsCss() { + return borderClsCss; + } + + /** + * getBorderStyleCssMap + */ + public Map getBorderStyleCssMap() { + return borderStyleCssMap; + } + + /** + * contentStyle2class + */ + private String contentStyle2class(Map contentCssMap) { + return contentStyle2class(contentCssMap, null); + } + + protected String contentStyle2class(Map contentCssMap, Object value) { + StringBuilder sb = new StringBuilder(); + sb.append("fh"); + int horizontal_alignment = BaseUtils.getAlignment4Horizontal(this, value); + switch (horizontal_alignment) { + case Constants.CENTER: + sb.append(" tac"); + break; + case Constants.RIGHT: + sb.append(" tar"); + break; + } + switch (this.vertical_alignment) { + case Constants.BOTTOM: + sb.append(" vab"); + break; + case Constants.TOP: + sb.append(" vat"); + break; + } + + if (this.textStyle != NewFormStyle.TEXTSTYLE_WRAPTEXT + && this.textStyle != NewFormStyle.TEXTSTYLE_MULTILINEADJUSTFONT) { + sb.append(" nw"); + } else { + sb.append(" bw"); // alex:只可以用于ie,英文的长单词会被换行分开 + } + + FRFont font = this.getFRFont(); + if (font != null) { + sb.append(font2Class(font, contentCssMap, lineSpacing)); + } + + int lit = this.paddingLeft; + int rit = this.paddingRight; + int tit = this.spacingBefore; + int bit = this.spacingAfter; + //这边的<= 包括下面<>修改的话, 都要做好兼容的 + if (lit <= DEFAULT_PADDING) { + sb.append(" pl" + lit); + } else { + contentCssMap.put("padding-left", lit + "pt"); + } + + if (rit < DEFAULT_PADDING) { + sb.append(" pr" + rit); + } else if (rit > DEFAULT_PADDING) { + contentCssMap.put("padding-right", rit + "pt"); + } + + if (0 < tit && tit <= DEFAULT_PADDING) { + sb.append(" pt" + tit); + } else if (tit > DEFAULT_PADDING) { + contentCssMap.put("padding-top", tit + "pt"); + } + + if (0 < bit && bit <= DEFAULT_PADDING) { + sb.append(" pb" + bit); + } else if (bit > DEFAULT_PADDING) { + contentCssMap.put("padding-bottom", bit + "pt"); + } + + return sb.toString().trim(); + } + + public JSONObject border2JSONObject() throws JSONException { + JSONObject borderJSON = new JSONObject(); + if (checkLeftRightTopBottom4b1()) { + borderJSON.put("b1", true); + } else { + border2JSONObject(borderJSON, border_top, border_top_color, "t"); + border2JSONObject(borderJSON, border_left, border_left_color, "l"); + border2JSONObject(borderJSON, border_bottom, border_bottom_color, "b"); + border2JSONObject(borderJSON, border_right, border_right_color, "r"); + } + return borderJSON; + } + + private void border2JSONObject(JSONObject jo, byte borderStyle, Color borderColor, String position) throws JSONException { + if (borderStyle == Constants.LINE_THIN + && ComparatorUtils.equals(borderColor, Color.black)) { + jo.put(position, new JSONObject().put("w", 1)); + } else { + int bw = BaseUtils.getBorderWidth(borderStyle); + if (bw > 0) { + JSONObject extra = new JSONObject(); + extra.put("w", bw); + if (!ComparatorUtils.equals(borderColor, Color.black)) { + extra.put("c", StableUtils.javaColorToCSSColor(borderColor)); + } + // 留着保持兼容老的app + extra.put("s", borderLine2String(borderStyle)); + // MOBILE-21527 报表设计器设置不同的border后台返回具体的border类型 + extra.put("type", borderStyle); + jo.put(position, extra); + } + } + } + + private String borderLine2String(int borderStyle) { + switch (borderStyle) { + case Constants.LINE_THIN: + case Constants.LINE_SLIM: + return "t"; + case Constants.LINE_MEDIUM: + return "m"; + case Constants.LINE_THICK: + return "tk"; + case Constants.LINE_DOUBLE: + return "de"; + case Constants.LINE_DOT: + return "dt"; + case Constants.LINE_DASH_DOT: + return "dadt"; + case Constants.LINE_DASH_DOT_DOT: + return "ddd"; + default: + return "dash"; + } + } + + /* + * 返回classBuf与styleBuf + */ + private String border2Class(Map borderCssMap) { + StringBuilder sb = new StringBuilder(); + // 简化class + if (checkLeftRightTopBottom4b0()) { + sb.append(" b0"); + return sb.toString().trim(); + } else if (checkLeftRightTopBottom4b1()) { + sb.append(" b1"); + return sb.toString().trim(); + } + + // right + visible_border_css(this.border_right, this.border_right_color, sb, borderCssMap, "r"); + // bottom + visible_border_css(this.border_bottom, this.border_bottom_color, sb, borderCssMap, "b"); + // left + visible_border_css(this.border_left, this.border_left_color, sb, borderCssMap, "l"); + // top + visible_border_css(this.border_top, this.border_top_color, sb, borderCssMap, "t"); + + return sb.toString().trim(); + } + + private boolean checkLeftRightTopBottom4b0() { + return this.border_left == Constants.LINE_NONE && this.border_right == Constants.LINE_NONE + && this.border_top == Constants.LINE_NONE && this.border_bottom == Constants.LINE_NONE; + } + + private boolean checkLeftRightTopBottom4b1() { + return this.border_left == Constants.LINE_THIN && this.border_right == Constants.LINE_THIN + && this.border_top == Constants.LINE_THIN && this.border_bottom == Constants.LINE_THIN + && ComparatorUtils.equals(this.border_left_color, Color.black) + && ComparatorUtils.equals(this.border_right_color, Color.black) + && ComparatorUtils.equals(this.border_top_color, Color.black) + && ComparatorUtils.equals(this.border_bottom_color, Color.black); + } + + private static void visible_border_css( + byte border_style, Color border_color, StringBuilder classBuf, Map borderCssMap, String border_position + ) {// right + if (border_style == Constants.LINE_THIN + && ComparatorUtils.equals(border_color, Color.black)) { + classBuf.append(" b" + border_position + "1"); + } + + int bw = BaseUtils.getBorderWidth(border_style); + if (bw > 0) { + // width + classBuf.append(" b" + border_position + "w" + bw); + + // style + classBuf.append(" " + __border2Class(border_style, border_position)); + + // color + // 细线需要另外处理为 rgba,rgba的边框在chrome上会出现渲染问题 + // 转为 rgb 显示 + if (border_style == Constants.LINE_SLIM) { + borderCssMap.put(_position2Colorcss(border_position), + StableUtils.javaColorToCSSColor(brighter(border_color))); + } else if (ComparatorUtils.equals(border_color, Color.black)) { + classBuf.append(" b" + border_position + "cb"); + } else { + borderCssMap.put(_position2Colorcss(border_position), StableUtils.javaColorToCSSColor(border_color)); + } + } else { + classBuf.append(" b" + border_position + "0"); + } + } + + private static Color brighter(Color ori) { + return new Color(Math.min((int) ((1 - FACTORY_ALPHA) * 255 + FACTORY_ALPHA * ori.getRed()), 255), + Math.min((int) ((1 - FACTORY_ALPHA) * 255 + FACTORY_ALPHA * ori.getGreen()), 255), + Math.min((int) ((1 - FACTORY_ALPHA) * 255 + FACTORY_ALPHA * ori.getBlue()), 255), + 255); + } + + private static String _position2Colorcss(String border_position) { + if (ComparatorUtils.equals(border_position, "r")) { + return "border-right-color"; + } else if (ComparatorUtils.equals(border_position, "b")) { + return "border-bottom-color"; + } else if (ComparatorUtils.equals(border_position, "l")) { + return "border-left-color"; + } else if (ComparatorUtils.equals(border_position, "t")) { + return "border-top-color"; + } else { + return "border-color"; + } + } + + private static String __border2Class(int borderStyle, String d) { + switch (borderStyle) { + case Constants.LINE_SLIM: + return "b" + d + "ss"; + case Constants.LINE_THIN: + return "b" + d + "ss"; + case Constants.LINE_MEDIUM: + return "b" + d + "ss"; + case Constants.LINE_THICK: + return "b" + d + "ss"; + case Constants.LINE_DOUBLE: + return "b" + d + "sd"; + case Constants.LINE_DOT: + return "b" + d + "sdo"; + case Constants.LINE_DASH_DOT: + return "b" + d + "sdo"; + case Constants.LINE_DASH_DOT_DOT: + return "b" + d + "sdo"; + default: + return "b" + d + "sda"; + } + } + + private static String font2Class(Font font, Map cssMap, byte lineSpacing) { + StringBuilder sb = new StringBuilder(); + if (font.isBold()) { + sb.append(" fwb"); + } + if (font.isItalic()) { + sb.append(" fsi"); + } + String fontName = font.getName(); + String cls = (String) getclsFontFamily().get(fontName); + if (cls == null) { + // REPORT-25741 部分字体需要加引号才能识别 + cssMap.put("font-family", "'" + fontName + "'"); + } else if (!ComparatorUtils.equals(cls, "fnss")) { // alex:font-family:SimSun写在fh里面了 + sb.append(" " + cls); + } + float size = font.getSize2D(); + if (AssistUtils.equals(size, N_SIZE)) { // alex:font-size:9pt写在fh里面 + } else if (size >= MIN_SIZE && size <= MAX_SIZE) { + size = Utils.round5(size); + sb.append(" f" + String.valueOf(size).replace('.', '-')); + } else { + cssMap.put("font-size", font.getSize2D() + "pt"); + } + + if (lineSpacing != 0) { + // carl:直接在这里添上line-height + //cellFM.getHeight() 不能简单的 *(4/3)进行转换,数值不对 + FontMetrics cellFM = GraphHelper.getFontMetrics(FRFont.getInstance(font).applyResolutionNP(Constants.FR_PAINT_RESOLUTION)); + cssMap.put("line-height", (int) (cellFM.getHeight() + lineSpacing * LINE_HEIGHT_FIX / LINE_HEIGHT_FIX2) + "px"); + } + + font2ClassOnFRFont(font, cssMap, sb); + + return sb.toString(); + } + + private static void font2ClassOnFRFont(Font font, Map cssMap, StringBuilder sb) { + if (font instanceof FRFont) { + if (((FRFont) font).isStrikethrough()) { + if (((FRFont) font).getUnderline() != Constants.LINE_NONE) { + sb.append(" tdstu"); + } else { + sb.append(" tdst"); + } + } else { + if (((FRFont) font).getUnderline() != Constants.LINE_NONE) { + sb.append(" tdu"); + } + } + if (((FRFont) font).isSubscript()) { + sb.append(" suber"); + } else if (((FRFont) font).isSuperscript()) { + sb.append(" super"); + } + if (((FRFont) font).isShadow()) { + sb.append(" shadow"); + } + Color color = ((FRFont) font).getForeground(); + if (!ComparatorUtils.equals(color, Color.black) && color != null) { + cssMap.put("color", StableUtils.javaColorToCSSColor(color)); + } + } + } + + + private transient int hashCode = -1; + + /** + * 哈希码 + * + * @return 哈希值h + */ + public int hashCode() { + + if (hashCode == -1) { + //因为format和非ColorBackground的Background并不是唯一的(也就是说即使equals但hashCode也会不一样),所以不放在hashCode的计算里面 + int code = this.border_top ^ this.border_bottom ^ this.border_left ^ this.border_right ^ + this.border_top_color.hashCode() ^ this.border_bottom_color.hashCode() ^ + this.border_left_color.hashCode() ^ this.border_right_color.hashCode() ^ + this.horizontal_alignment ^ this.imageLayout ^ this.verticalText ^ + this.paddingLeft ^ this.paddingRight ^ this.rotation ^ this.textDirection ^ this.textStyle ^ this.vertical_alignment; + + if (frFont != null) { + code ^= frFont.hashCode(); + } + if (background != null) { + code = background.fixHashCode(code); + } + hashCode = code; + } + return hashCode; + } + + /** + * Equals. + */ + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (!(object instanceof NewFormStyle)) { + return false; + } + + NewFormStyle newStyle = (NewFormStyle) object; + + //由于java中所有的Format都实现了equals()方法,这里可以直接来比较. + return ComparatorUtils.equals(newStyle.getFormat(), this.getFormat()) && + ComparatorUtils.equals(newStyle.getFRFont(), this.getFRFont()) && + ComparatorUtils.equals(newStyle.getBackground(), this.getBackground()) && + + newStyle.getBorderTop() == this.getBorderTop() && + newStyle.getBorderLeft() == this.getBorderLeft() && + newStyle.getBorderBottom() == this.getBorderBottom() && + newStyle.getBorderRight() == this.getBorderRight() && + + ComparatorUtils.equals(newStyle.getBorderTopColor(), this.getBorderTopColor()) && + ComparatorUtils.equals(newStyle.getBorderLeftColor(), this.getBorderLeftColor()) && + ComparatorUtils.equals(newStyle.getBorderBottomColor(), this.getBorderBottomColor()) && + ComparatorUtils.equals(newStyle.getBorderRightColor(), this.getBorderRightColor()) && + + BaseUtils.getAlignment4Horizontal(newStyle) == BaseUtils.getAlignment4Horizontal(this) && + newStyle.getVerticalAlignment() == this.getVerticalAlignment() && + newStyle.getTextStyle() == this.getTextStyle() && + + //james verticalText + newStyle.getVerticalText() == this.getVerticalText() && + newStyle.getTextDirection() == this.getTextDirection() && + newStyle.getRotation() == this.getRotation() && + newStyle.getImageLayout() == this.getImageLayout() && + + // alex padding + newStyle.getPaddingLeft() == this.getPaddingLeft() && + newStyle.getPaddingRight() == this.getPaddingRight() && + + //间距 + newStyle.getSpacingBefore() == this.getSpacingBefore() && + newStyle.getSpacingAfter() == this.getSpacingAfter() && + newStyle.getLineSpacing() == this.getLineSpacing(); + } + + /** + * Clone. + */ + public Object clone() throws CloneNotSupportedException { + return this; + } + + protected Object readResolve() throws InvalidObjectException { + if (this.getClass() != NewFormStyle.class) { + throw new InvalidObjectException("subclass didn't correctly implement readResolve"); + } + + Object res = initializeStyle.get(this); + //alex:从ObjectInputStream生成的Object可能不存在于全局的map中,可能为null + if (res == null) { + res = this; + initializeStyle.put(this, res); + } + + return res; + } + + /** + * 画单元格的Value + *

+ * 通过width, height方式画 + */ + public static void paintContent(Graphics2D g2d, Object value, NewFormStyle style, int width, int height, int resolution) { + // kunsnat: 添加判断width和height. 是否有必要继续paint, @bug0006854, 增加了混乱的字符. + if (value == null || width == 0 || height == 0) { + return; + } + + if (style == null) { + //peter:获取默认的Style. + style = NewFormStyle.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_CENTER); + } + + if (value instanceof BaseFormula) { + value = ((BaseFormula) value).getResult(); + } + + if (value instanceof Painter) { + // TODO 弹出界面然后 esc bug.. + ((Painter) value).paint(g2d, width, height, resolution, style); + } else if (value instanceof ImageProvider) { + paintImageContent(g2d, ((ImageProvider) value).getImage(), style, width, height, resolution); + } else if (value instanceof Image) { + paintImageContent(g2d, (Image) value, style, width, height, resolution); + } else { + //默认Paint String + String text = valueToText(value, style.getFormat()); + paintCellStyleString(g2d, width, height, text, style, resolution); + } + } + + public static void paintImageContent(Graphics2D g2d, Image value, NewFormStyle style, int width, int height, int resolution) { + int imageLayout = CoreGraphHelper.changeImageLayout4Draw(value, style.getImageLayout(), width, height); + + //这边做scale的目的是为了在导出图片以及以图片方式打印时,根据不同的resolution调整对应的dpi + int defaultResolution = Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION; + double scale = resolution * 1d / defaultResolution; + width = (int) (width / scale); + height = (int) (height / scale); + g2d.scale(scale, scale); + + GraphHelper.paintImage(g2d, width, height, value, imageLayout, + style.getHorizontalAlignment(), style.getVerticalAlignment(), -1, -1); + //最后把画板改回来 + g2d.scale(defaultResolution * 1d / resolution, defaultResolution * 1d / resolution); + } + + /** + * 画单元格的Value + *

+ * 通过PaintRectangle + ClipRectangle画 + */ + public static void paintContent(Graphics2D g2d, Object value, int resolution, NewFormStyle style, Rectangle paintRectangle, Rectangle clipRectangle) { + Shape oldClip = g2d.getClip(); + g2d.translate(paintRectangle.getX(), paintRectangle.getY()); + g2d.clip(clipRectangle); // kunsnat: 这些clip 都没有考虑边框啊!!! 所有图表的边框压缩到里面去了. + + paintContent(g2d, value, style, paintRectangle.width, paintRectangle.height, resolution); + + g2d.translate(-paintRectangle.getX(), -paintRectangle.getY()); + g2d.setClip(oldClip); + } + + /** + * 画背景 + *

+ * 通过width, height方式画 + */ + public static void paintBackground(Graphics2D g2d, NewFormStyle style, double width, double height) { + if (style == null) {// 还是需要检查一下的,假如DefaultCellStyle拥有Border就需要Paint了. + return; + } + + // paint background. + Background background = style.getBackground(); + if (background == null) { + return; + } + + background.layoutDidChange((int) width, (int) height); + synchronized (tempRectangle2D) { + tempRectangle2D.setRect(0, 0, width, height); + background.paint(g2d, tempRectangle2D); + } + } + + /** + * 画单元格的背景 + *

+ * 通过PaintRectangle + ClipRectangle画 + */ + public static void paintBackground(Graphics2D g2d, NewFormStyle style, Rectangle paintRectangle, Rectangle clipRectangle) { + if (style == null) { + //peter:获取默认的Style. + style = NewFormStyle.DEFAULT_STYLE; + } + Shape oldClip = g2d.getClip(); + g2d.translate(paintRectangle.getX(), paintRectangle.getY()); + g2d.clip(clipRectangle); + Background background = style.getBackground(); + + if (background != null) { + // alex:根据paintRectangle和clipRectangle共同决定Background的PaintRectangle + background.paint(g2d, new Rectangle( + clipRectangle.x, clipRectangle.y, + clipRectangle.width, clipRectangle.height)); + } + g2d.translate(-paintRectangle.getX(), -paintRectangle.getY()); + g2d.setClip(oldClip); + } + + /** + * 画边框 + *

+ * 通过width, height方式画 + */ + public static void paintBorder(Graphics2D g2d, NewFormStyle style, double width, double height) { + if (style == null) {// 还是需要检查一下的,假如DefaultCellStyle拥有Border就需要Paint了. + return; + } + + //peter:当是粗线的时候,需要计算尺寸 + double left = 0; + double right = 0; + if (style.getBorderLeft() != Constants.LINE_NONE) { + int borderLeftSize = GraphHelper.getLineStyleSize(style.getBorderLeft()); + left = borderLeftSize / 2; + } + if (style.getBorderRight() != Constants.LINE_NONE) { + int borderRightSize = GraphHelper.getLineStyleSize(style.getBorderRight()); + right = borderRightSize / 2; + } + + double top = 0; + double bottom = 0; + if (style.getBorderTop() != Constants.LINE_NONE) { + int bSize = GraphHelper.getLineStyleSize(style.getBorderTop()); + top = bSize / 2; + } + if (style.getBorderBottom() != Constants.LINE_NONE) { + int bSize = GraphHelper.getLineStyleSize(style.getBorderBottom()); + bottom = bSize / 2; + } + + // paint border + if (style.getBorderTop() != Constants.LINE_NONE) { + g2d.setPaint(style.getBorderTopColor()); + GraphHelper.drawLine(g2d, 0 - left, 0, width + right, 0, style.getBorderTop()); + } + if (style.getBorderLeft() != Constants.LINE_NONE) { + g2d.setPaint(style.getBorderLeftColor()); + GraphHelper.drawLine(g2d, 0, 0 - top, 0, height + bottom, style.getBorderLeft()); + } + if (style.getBorderBottom() != Constants.LINE_NONE) { + g2d.setPaint(style.getBorderBottomColor()); + GraphHelper.drawLine(g2d, 0 - left, height, width + right, height, style.getBorderBottom()); + } + if (style.getBorderRight() != Constants.LINE_NONE) { + g2d.setPaint(style.getBorderRightColor()); + GraphHelper.drawLine(g2d, width, 0 - top, width, height + bottom, style.getBorderRight()); + } + } + + /** + * 画单元格的边框 + *

+ * 通过PaintRectangle + ClipRectangle画边框 + */ + public static void paintBorder(Graphics2D g2d, NewFormStyle style, Rectangle paintRectangle, Rectangle clipRectangle) { + //单元格行高列宽=0时, 不需要绘制边框 + if (paintRectangle.width == 0 || paintRectangle.height == 0) { + return; + } + g2d.translate(paintRectangle.getX(), paintRectangle.getY()); + + Rectangle realPaintRect = new Rectangle(0, 0, + paintRectangle.width, paintRectangle.height); + //peter:需要判断的因为clipRectangle极可能不是null. + if (clipRectangle != null) { + realPaintRect = realPaintRect.intersection(clipRectangle); + } + g2d.translate(realPaintRect.getX(), realPaintRect.getY()); + + if (style == null) {// 还是需要检查一下的,假如DefaultCellStyle拥有Border就需要Paint了. + //peter:获取默认的Style. + style = NewFormStyle.DEFAULT_STYLE; + } + + paintBorder(g2d, style, realPaintRect.getWidth(), realPaintRect.getHeight()); + + // 返回Translate + g2d.translate(-realPaintRect.getX(), -realPaintRect.getY()); + g2d.translate(-paintRectangle.getX(), -paintRectangle.getY()); + } + + /** + * 转化成文本 + * + * @param value 带转化的对象 + * @param format 格式g + * @return 字符串z + */ + public static String valueToText(Object value, Format format) { + //需要画的值,主要是把公式里面的值拿出来 + Object valueToPaint = value; + String text = null; + + String checkInfinity = StableUtils.checkInfinity(value); + if (StringUtils.isNotEmpty(checkInfinity)) { + return checkInfinity; + } + + if (value != null) { + if (value instanceof BaseFormula) { + BaseFormula formula = (BaseFormula) value; + if (StableUtils.isNull(formula.getResult())) { + return StringUtils.EMPTY;// BUG4788,应该显示空字符串 + } else { + valueToPaint = formula.getResult(); + } + } else if (value instanceof Clob) { + valueToPaint = DataBaseUtils.clob2String((Clob) value); + } + + if (format != null) { + format = FormatRepository.getInstance().getLocalFormat(format); + if (format instanceof DateFormat) {// Date. + text = valueInDateFormat((DateFormat) format, valueToPaint); + } else if (format instanceof NumberFormat) {// Number. + text = valueInNumberFormat(format, valueToPaint); + } else { + try { + text = format.format(valueToPaint); + } catch (Exception exp) { + text = Utils.objectToString(valueToPaint); + } + } + } else + text = Utils.objectToString(valueToPaint); + } else { + text = StringUtils.EMPTY; + } + + return text; + } + + protected static String valueInNumberFormat(Format format, Object valueToPaint) { + Number number = GeneralUtils.objectToNumberReturnNull(valueToPaint); + if (number != null) { + try { + if (format instanceof CoreDecimalFormat) { + //数字类型的要roundup一下, 默认会逢5奇进偶不进, 62.325->62.33 + return ((CoreDecimalFormat) format).formatRoundingModeUp(number); + } + //62.325->62.32 + return format.format(number); + } catch (Exception ignore) { + } + } + return Utils.objectToString(valueToPaint); + } + + private static String valueInDateFormat(DateFormat format, Object valueToPaint) { + + String result; + Date date2Format = tryGet(format, valueToPaint); + if (date2Format == null) { + date2Format = DateUtils.object2Date(valueToPaint, true); + } + if (date2Format != null) { + result = format.format(date2Format); + } + /* + * alex:如果date2Format为null,就是说valueToPaint不能转换成日期型,那么就直接画valueToPaint的字符串 + * 为什么必须要画valueToPaint的字符串呢?见bug0004566 + * 因为在Grid里面直接写=today(),并设置format为日期,如果不画,就一片空白,什么都看不到了 + */ + else { + result = Utils.objectToString(valueToPaint); + } + + return result; + } + + @Nullable + private static Date tryGet(DateFormat format, Object valueToPaint) { + + Date date2Format = null; + // 先用format来生成日期啊 + if (valueToPaint instanceof Date) { + date2Format = (Date) valueToPaint; + } else { + try { + date2Format = format.parse(GeneralUtils.objectToString(valueToPaint)); + } catch (Exception e) { + // nothing + } + } + return date2Format; + } + + /** + * Paint string according to Style. + */ + public static void paintCellStyleString2(Graphics2D g2d, int width, int height, String text, Style style, int resolution) { + if (StringUtils.isBlank(text)) { + return; + } + Paint oldPaint = g2d.getPaint(); + if (style == null) { + style = NewFormStyle.DEFAULT_STYLE; + } + Font rfont = BaseUtils.getStyleFont(g2d, style, resolution); + if (style.getRotation() != 0 && style.getVerticalText() == NewFormStyle.HORIZONTALTEXT) { + BaseUtils.drawStringStyleInRotation(g2d, width, height, text, style, resolution); + } else { + if (style.getTextStyle() == NewFormStyle.TEXTSTYLE_SINGLELINEADJUSTFONT + || style.getTextStyle() == NewFormStyle.TEXTSTYLE_MULTILINEADJUSTFONT) { + List lineTextList = BaseUtils.getLineTextList(text, style, rfont, height, width, resolution); + if (width <= 0 || lineTextList.isEmpty()) { + return; + } + int textAscent = g2d.getFontMetrics().getAscent(); + int textHeight = g2d.getFontMetrics().getHeight(); + + int textY = 0; + int textAllHeight = textHeight * lineTextList.size(); + double spacingBefore = PT.pt2pix(style.getSpacingBefore(), resolution); + double spacingAfter = PT.pt2pix(style.getSpacingAfter(), resolution); + double lineSpacing = PT.pt2pix(style.getLineSpacing(), resolution); + //james:加上间距,WORD中的行间距是从第一行文本的上面一行就算的,所以行间距形成的空隙与文本行数相同 + textAllHeight += spacingBefore + spacingAfter + lineSpacing * lineTextList.size(); + if (style.getVerticalAlignment() == Constants.CENTER) { + if (height > textAllHeight) {// 如果所有文本的高度小于当前可以绘区域的高度,就从0开始画字符. + textY = (height - textAllHeight) / 2; + } + } else if (style.getVerticalAlignment() == Constants.BOTTOM) { + textY = height - textAllHeight; + } + textY += textAscent;// 在绘画的时候,必须添加Ascent的高度. + textY += spacingBefore + lineSpacing;//james:加上"段前间距"+“行间距” + if (style.getTextStyle() == NewFormStyle.TEXTSTYLE_SINGLELINEADJUSTFONT) {// 通过自动调整字体显示所有的信息调整Font来显示所有的字符 + ContentLineGroup contentLineGroup = singleLineAdjustFont(style, lineTextList, width, height, g2d, resolution, true); + _drawContentLineGroup(contentLineGroup, g2d, textY, height, width, BaseUtils.getAlignment4Horizontal(style, text)); + } else if (style.getTextStyle() == NewFormStyle.TEXTSTYLE_MULTILINEADJUSTFONT) { + ContentLineGroup contentLineGroup = mulitiLineAdjustFont(style, lineTextList, width, height, g2d, resolution, true); + _drawContentLineGroup(contentLineGroup, g2d, textY, height, width, BaseUtils.getAlignment4Horizontal(style, text)); + } + } else { + BaseUtils.drawStringStyleInRotation(g2d, width, height, text, style, resolution); + } + } + g2d.setPaint(oldPaint); + } + + + + private static void _drawContentLineGroup( + ContentLineGroup contentLineGroup, Graphics2D g2d, + int textY, int height, int width, int horizontalAlignment + ) { + Style style = contentLineGroup.style; + + Font oldFRFont = g2d.getFont(); + g2d.setFont(style.getFRFont()); + if (style.getVerticalAlignment() == Constants.TOP) { + textY = 0; + } else if (style.getVerticalAlignment() == Constants.CENTER) { + if (height > contentLineGroup.totalHeight()) {// 如果所有文本的高度小于当前可以绘区域的高度,就从0开始画字符. + textY = (height - contentLineGroup.totalHeight()) / 2; + } else { + textY = 0; + } + } else if (style.getVerticalAlignment() == Constants.BOTTOM) { + textY = height - contentLineGroup.totalHeight(); + } + textY += g2d.getFontMetrics().getAscent();// 在绘画的时候,必须添加Ascent的高度. + + for (int i = 0; i < contentLineGroup.newLineTextList.size(); i++) { + double textX = style.getPaddingLeft(); + int textWidth = GraphHelper.getFontMetrics(style.getFRFont()).stringWidth((String) contentLineGroup.newLineTextList.get(i)); + if (horizontalAlignment == Constants.CENTER) { + textX = (width - textWidth - style.getPaddingRight()) / 2.0; + } else if (horizontalAlignment == Constants.RIGHT) { + textX = width - style.getPaddingRight() - textWidth; + } else if (horizontalAlignment == Constants.DISTRIBUTED) {// added by KevinWang + } + + if (horizontalAlignment == Constants.DISTRIBUTED) { + String lineText = (String) contentLineGroup.newLineTextList.get(i);// 分行显示时第i行的内容,但是也可能单行 + double charSpace = (width - style.getPaddingLeft() - style.getPaddingRight() + - g2d.getFontMetrics().charWidth(lineText.charAt(lineText.length() - 1))) + / (lineText.length() - 1); + for (int charIndex = 0; charIndex < lineText.length(); charIndex++) { + char tmpChar = lineText.charAt(charIndex);//取出一个字符待显示 + String tmpString = new String((new StringBuffer()).append(tmpChar));// 将其包装成string形式 + double charX = style.getPaddingLeft() + charIndex * charSpace; + GraphHelper.drawString(g2d, tmpString, charX, textY);//显示 + } + } else { + GraphHelper.drawString(g2d, (String) contentLineGroup.newLineTextList.get(i), textX, textY); + } + textY += contentLineGroup.newTextHeight; + } + g2d.setFont(oldFRFont); + } + + /* + * 通过自动调整字体显示所有的信息调整Font来显示所有的字符 + */ + private static ContentLineGroup singleLineAdjustFont(Style style, List lineTextList, int width, int height, Graphics2D g2d, int resolution, boolean fontScale) { + FRFont newFRFont = (FRFont) style.getFRFont().applyResolutionNP(resolution); + + int maxTextWidth = 0; + FontMetrics oriFontMetrics = GraphHelper.getFontMetrics(newFRFont); + int maxTextHeight = oriFontMetrics.getHeight() * lineTextList.size(); + String examle_text = ""; + for (int i = 0; i < lineTextList.size(); i++) { + if (oriFontMetrics.stringWidth((String) lineTextList.get(i)) > maxTextWidth) { + examle_text = (String) lineTextList.get(i); + maxTextWidth = oriFontMetrics.stringWidth((String) lineTextList.get(i)); + } + } + + if (maxTextWidth > 0 || maxTextHeight > 0) { // 只有当大于0时才改变字体大小 + // 调整宽度和高度 + if (maxTextWidth > (width - style.getPaddingLeft() - style.getPaddingRight()) || maxTextHeight > height) { + while (newFRFont.getSize() > 1) { + newFRFont = newFRFont.applySize((float) newFRFont.getSize() - 1); + maxTextWidth = GraphHelper.getFontMetrics(newFRFont).stringWidth(examle_text); + maxTextHeight = GraphHelper.getFontMetrics(newFRFont).getHeight() * lineTextList.size(); + + // 由于Font的变化单位是1, 所以必须这么找最适合的 Font + if (maxTextWidth <= (width - style.getPaddingLeft() - style.getPaddingRight()) && maxTextHeight <= height) { + break; + } + } + } + } + + FRFont returnFont = style.getFRFont().applySize(fontScale ? newFRFont.getSize2D() : FRFont.convResolution(newFRFont.getSize2D(), resolution)); + return new ContentLineGroup(style.deriveFRFont(returnFont), lineTextList, GraphHelper.getFontMetrics(newFRFont, g2d).getHeight()); + } + + /* + * 多行显示(调整字体大小),即固定单元格高和框,改变字体大小使适应。 + */ + private static ContentLineGroup mulitiLineAdjustFont(Style style, List lineTextList, int width, int height, Graphics2D g2d, int resolution, boolean fontScale) { + FRFont newFRFont = (FRFont) style.getFRFont().applyResolutionNP(resolution); + List newLineTextList; + NewFormStyle tmpStyle = NewFormStyle.DEFAULT_STYLE; + tmpStyle = tmpStyle.deriveTextStyle(NewFormStyle.TEXTSTYLE_WRAPTEXT); + int newTextHeight = GraphHelper.getFontMetrics(newFRFont, g2d).getHeight(); + + newLineTextList = resovleLineTextListByStyle(newFRFont, lineTextList, tmpStyle, width, resolution); + + if (newLineTextList.size() * newTextHeight > height) { + while (newFRFont.getSize() > 1) { + newFRFont = newFRFont.applySize((float) newFRFont.getSize() - 1); + newLineTextList = resovleLineTextListByStyle(newFRFont, lineTextList, tmpStyle, width, resolution); + + newTextHeight = GraphHelper.getFontMetrics(newFRFont, g2d).getHeight(); + if (newLineTextList.size() * newTextHeight <= height) { + break; + } + } + } else if (newLineTextList.size() * newTextHeight < height) { + while (newFRFont.getSize() < MAX_FONT_SIZE) { // _denny: 设定字体最大为100 + newFRFont = newFRFont.applySize((float) newFRFont.getSize() + 1); + + newLineTextList = resovleLineTextListByStyle(newFRFont, lineTextList, tmpStyle, width, resolution); + + newTextHeight = GraphHelper.getFontMetrics(newFRFont, g2d).getHeight(); + if (newLineTextList.size() * newTextHeight > height) { + newFRFont = newFRFont.applySize(newFRFont.getSize() - 1); + + newLineTextList = resovleLineTextListByStyle(newFRFont, lineTextList, tmpStyle, width, resolution); + + newTextHeight = GraphHelper.getFontMetrics(newFRFont, g2d).getHeight(); + break; + } + } + } + + FRFont returnFont = tmpStyle.getFRFont().applySize(fontScale ? newFRFont.getSize2D() : FRFont.convResolution(newFRFont.getSize2D(), resolution)); + tmpStyle.deriveFRFont(returnFont); + + return new ContentLineGroup(tmpStyle, newLineTextList, newTextHeight); + } + + private static List resovleLineTextListByStyle(Font font, List lineTextList, NewFormStyle tmpStyle, int width, int resolution) { + List newLineTextList = new ArrayList(); + + List tmpLineTextList; + for (int i = 0; i < lineTextList.size(); i++) { + tmpLineTextList = BaseUtils.getLineTextList((String) lineTextList.get(i), tmpStyle, font, width, resolution); + for (int j = 0; j < tmpLineTextList.size(); j++) { + newLineTextList.add((String) tmpLineTextList.get(j)); + } + } + + return newLineTextList; + } + + /** + * 修改格子样式 + * + * @param width 宽 k + * @param height 高g + * @param text 文本w + * @param style 样式y + * @param resolution 转化率z + * @return 样式 y + */ + public static Style modCellStyleString(int width, int height, String text, Style style, int resolution) { + List lineTextList = BaseUtils.getLineTextList(text, style, null, height, width, resolution); + if (style.getTextStyle() == NewFormStyle.TEXTSTYLE_SINGLELINEADJUSTFONT) { + style = singleLineAdjustFont(style, lineTextList, width, height, null, resolution, false).style; + } else if (style.getTextStyle() == NewFormStyle.TEXTSTYLE_MULTILINEADJUSTFONT) { + style = mulitiLineAdjustFont(style, lineTextList, width, height, null, resolution, false).style; + } + + return style; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java b/designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java new file mode 100644 index 000000000..8f913a7aa --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/PaintUtils.java @@ -0,0 +1,835 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.fit.common; + +import com.fr.base.AutoChangeLineAndDrawManager; +import com.fr.base.BaseFormula; +import com.fr.base.BaseUtils; +import com.fr.base.GraphHelper; +import com.fr.base.ImageProvider; +import com.fr.base.Painter; +import com.fr.base.Style; +import com.fr.base.Utils; +import com.fr.base.background.ColorBackground; +import com.fr.base.chart.BaseChartCollection; +import com.fr.base.chart.result.WebChartIDInfo; +import com.fr.code.BarcodeImpl; +import com.fr.code.bar.BarcodeException; +import com.fr.code.bar.core.BarCodeUtils; +import com.fr.code.bar.core.BarcodeAttr; +import com.fr.data.DataUtils; +import com.fr.data.PresentationType; +import com.fr.data.condition.ListCondition; +import com.fr.file.ResultChangeWhenExport; +import com.fr.form.ui.Widget; +import com.fr.general.Background; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRFont; +import com.fr.general.ImageWithSuffix; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.ExtraClassManager; +import com.fr.report.cell.CellElement; +import com.fr.report.cell.FloatElement; +import com.fr.report.cell.TemplateCellElement; +import com.fr.report.cell.cellattr.CellExpandAttr; +import com.fr.report.cell.cellattr.CellGUIAttr; +import com.fr.report.cell.cellattr.core.CellUtils; +import com.fr.report.cell.cellattr.core.ResultSubReport; +import com.fr.report.cell.cellattr.core.group.DSColumn; +import com.fr.report.core.Html2ImageUtils; +import com.fr.report.core.ReportUtils; +import com.fr.script.Calculator; +import com.fr.stable.Constants; +import com.fr.stable.CoreConstants; +import com.fr.stable.StringUtils; +import com.fr.stable.bridge.ObjectHolder; +import com.fr.stable.fun.AutoChangeLineAndDrawProcess; +import com.fr.stable.fun.FontProcessor; +import com.fr.stable.html.Tag; +import com.fr.stable.unit.FU; +import com.fr.stable.unit.PT; +import com.fr.stable.unit.UNIT; +import com.fr.stable.web.Repository; + +import javax.swing.ImageIcon; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.font.TextAttribute; +import java.awt.geom.GeneralPath; +import java.awt.image.BufferedImage; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +/** + * The util for paint. + */ +public class PaintUtils { + // Add by Denny + public static final int CELL_MARK_SIZE = 6; + public static final Color CELL_HIGHT_LIGHT_MARK_COLOR = new Color(255, 0, 55); + public static final Color CELL_PRESENT_MARK_COLOR = new Color(0, 255, 200); + public static final Color CELL_PAGINATION_MARK_COLOR = new Color(55, 255, 0); + public static final Color CELL_RESULT_MARK_COLOR = new Color(200, 0, 255); + public static final Color CELL_CONDITION_FILTER_MARK_COLOR = new Color(255, 200, 0); + public static final Color CELL_PARAMETER_FILTER_MARK_CONLR = new Color(0, 55, 255); + + public static final Color CELL_DIRECTION_MARK_COLOR = Color.gray; + private static final int UNIT_SIZE = 4; + + //原值是15,矩形线条会缺失,加1px绘制没问题。这地方有水印,但是貌似不是水印影响,未找到线条被挡住的原因 + private static final int WIDGET_WIDTH = 16; + private static final int WIDGET_HEIGHT = 16; + + // Suppresses default constructor, ensuring non-instantiability. + private PaintUtils() { + } + + // font attributes map cache + private static Hashtable fontAttributeMapCache = new Hashtable(); + + /* + * 用于在Grid里面画CellElement的Content + Background + * + * 不画Border,是因为在Grid里面先画所有单元格的Content + Background,再画所有单元格的Border(peter认为这可以提高速度) + */ + public static void paintGridCellContent(Graphics2D g2d, TemplateCellElement cell, int width, int height, int resolution) { + int cell_mark_size = CELL_MARK_SIZE; + // denny_Grid + // 左上角: 条件高亮, 形态 + int leftUpCount = 0; + int rightUpCount = 0; + int leftDownCount = 0; + GraphHelper.applyRenderingHints(g2d); + if (paintHighlightGroupMarkWhenExsit(g2d, cell, leftUpCount)) { + leftUpCount++; + } + if (paintPresentMarkWhenExsit(g2d, cell, leftUpCount)) { + leftUpCount++; + } + if (paintPaginationMarkWhenExsit(g2d, cell, width, rightUpCount)) { + rightUpCount++; + } + paintWidgetMarkWhenExsit(g2d, cell, width, height); + paintExpandMarkWhenExsit(g2d, cell); + Object value = cell.getValue(); + if (value == null) {// 先判断是否是空. + return; + } + if (paintResultMarkWhenExsit(g2d, value, width, rightUpCount)) { + rightUpCount++; + } + + if (paintDSColumnParametermarkWhenExsit(g2d, value, height, leftDownCount)) { + leftDownCount++; + } + + if (paintDSColumnConditionmarkWhenExsit(g2d, value, height, leftDownCount)) { + leftDownCount++; + } + // 画value,但因为是在Grid里面画,所以画Formula.content + if (value instanceof BaseFormula) { + value = ((BaseFormula) value).getContent(); + } + if (value instanceof ImageWithSuffix) { + value = ((ImageWithSuffix) value).getFineImage(); + } + if (value instanceof BaseChartCollection) { + value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height); + } + // Carl:当是子报表时,在格子里画一个子报表的图 + /* + * alex:TODO 此处在Grid里面画ChartCollection和SubReport都只画一个图表,这种做法,很不雅 + */ + if (value instanceof ResultSubReport) { + value = BaseUtils.readImage("/com/fr/base/images/report/painter/subReport.png"); + GraphHelper.paintImage(g2d, width, height, (Image) value, Constants.IMAGE_CENTER, + BaseUtils.getAlignment4Horizontal(cell.getStyle(), value), cell.getStyle().getVerticalAlignment(), + width > 16 ? 16 : width, height > 16 ? 16 : height); + } else { + renderContent(g2d, value, cell.getStyle(), width, height, resolution); + } + } + + + private static void renderContent(Graphics2D g2d, Object value, Style style, int width, int height, int resolution) { + if (value != null && width != 0 && height != 0) { + if (style == null) { + style = Style.DEFAULT_STYLE.deriveImageLayout(1); + } + + if (value instanceof BaseFormula) { + value = ((BaseFormula) value).getResult(); + } + + if (value instanceof Painter) { + ((Painter)value).paint(g2d, width, height, resolution, style); + } else if (value instanceof ImageProvider) { + Style.paintImageContent(g2d, ((ImageProvider) value).getImage(), style, width, height, resolution); + } else if (value instanceof Image) { + Style.paintImageContent(g2d, (Image) value, style, width, height, resolution); + } else { + String var6 = Style.valueToText(value, style.getFormat()); + NewFormStyle.paintCellStyleString2(g2d, width, height, var6, style, resolution); + } + + } + } + + + private static boolean paintHighlightGroupMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) { + if (cell.getHighlightGroup() != null && cell.getHighlightGroup().size() > 0) { + Paint oldPaint = g2d.getPaint(); + + g2d.setPaint(CELL_HIGHT_LIGHT_MARK_COLOR); + GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); + polyline.moveTo(0, 0); + polyline.lineTo(0, CELL_MARK_SIZE); + polyline.lineTo(CELL_MARK_SIZE, 0); + GraphHelper.fill(g2d, polyline); + + g2d.setPaint(oldPaint); + return true; + } + return false; + } + + private static boolean paintPresentMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int left_up_count) { + if (cell.getPresent() != null) { + Paint oldPaint = g2d.getPaint(); + + g2d.setPaint(CELL_PRESENT_MARK_COLOR); + GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); + polyline.moveTo(0 + left_up_count * CELL_MARK_SIZE, 0); + polyline.lineTo(0 + left_up_count * CELL_MARK_SIZE, 6); + polyline.lineTo(CELL_MARK_SIZE + left_up_count * CELL_MARK_SIZE, 0); + GraphHelper.fill(g2d, polyline); + + g2d.setPaint(oldPaint); + return true; + } + return false; + } + + private static boolean paintPaginationMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int ringt_up_count) { + // 右上角: 标记是否有分页 + if (isRightTopMarker(cell)) { + Paint oldPaint = g2d.getPaint(); + + g2d.setPaint(CELL_PAGINATION_MARK_COLOR); + GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); + polyline.moveTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, 0); + polyline.lineTo(width - 1 - ringt_up_count * CELL_MARK_SIZE, CELL_MARK_SIZE); + polyline.lineTo(width - 1 - (ringt_up_count + 1) * CELL_MARK_SIZE, 0); + GraphHelper.fill(g2d, polyline); + + g2d.setPaint(oldPaint); + return true; + } + return false; + } + + private static boolean isRightTopMarker(TemplateCellElement cell) { + return cell.getCellPageAttr() != null && (cell.getCellPageAttr().isPageAfterColumn() + || cell.getCellPageAttr().isPageBeforeColumn() + || cell.getCellPageAttr().isPageAfterRow() + || cell.getCellPageAttr().isPageBeforeRow()); + } + + private static boolean paintResultMarkWhenExsit(Graphics2D g2d, Object value, int width, int ringt_up_count) { + //右上角标记是否自定义显示 + if (value instanceof DSColumn && ((DSColumn) value).getResult() != null) { + if (!ComparatorUtils.equals(((DSColumn) value).getResult(), "$$$")) { + Paint oldPaint = g2d.getPaint(); + + g2d.setPaint(CELL_RESULT_MARK_COLOR); + GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); + polyline.moveTo(width - ringt_up_count * CELL_MARK_SIZE - 1, 0); + polyline.lineTo(width - ringt_up_count * CELL_MARK_SIZE - 1, CELL_MARK_SIZE); + polyline.lineTo(width - (ringt_up_count + 1) * CELL_MARK_SIZE - 1, 0); + GraphHelper.fill(g2d, polyline); + + g2d.setPaint(oldPaint); + return true; + } + } + + return false; + } + + private static void paintWidgetMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell, int width, int height) { + // 右下角:是否填报, 设置为4时,三角太小了,不知何故,设置为6 + if (cell.getWidget() != null) { + Widget widget = cell.getWidget(); + Image img = ((ImageIcon) ReportUtils.createWidgetIcon(widget.getClass())).getImage(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.67f)); + g2d.drawImage(img, width - 15, height - 15, WIDGET_WIDTH, WIDGET_HEIGHT, null); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + } + } + + private static void paintExpandMarkWhenExsit(Graphics2D g2d, TemplateCellElement cell) { + CellExpandAttr cellExpandAttr = cell.getCellExpandAttr(); + if (cellExpandAttr != null) { + if (cellExpandAttr.getDirection() == Constants.TOP_TO_BOTTOM) { + Paint oldPaint = g2d.getPaint(); + g2d.setPaint(CELL_DIRECTION_MARK_COLOR); + GraphHelper.drawLine(g2d, 2, 0, 2, 5); + GraphHelper.drawLine(g2d, 2, 5, 0, 2); + GraphHelper.drawLine(g2d, 2, 5, 4, 2); + g2d.setPaint(oldPaint); + } else if (cellExpandAttr.getDirection() == Constants.LEFT_TO_RIGHT) { + Paint oldPaint = g2d.getPaint(); + g2d.setPaint(CELL_DIRECTION_MARK_COLOR); + GraphHelper.drawLine(g2d, 0, 2, 5, 2); + GraphHelper.drawLine(g2d, 5, 2, 2, 0); + GraphHelper.drawLine(g2d, 5, 2, 2, 4); + g2d.setPaint(oldPaint); + } + } + } + + private static boolean paintDSColumnConditionmarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) { + // 左下角:数据列(DSColumn)相关:比如条件过滤 + if (value instanceof DSColumn && ((DSColumn) value).getCondition() != null) { + if (((DSColumn) value).getCondition() instanceof ListCondition && + ((ListCondition) ((DSColumn) value).getCondition()).getJoinConditionCount() == 0) { + // do nothing + } else { + Paint oldPaint = g2d.getPaint(); + + g2d.setPaint(CELL_CONDITION_FILTER_MARK_COLOR); + GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); + polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1); + polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1); + polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE); + GraphHelper.fill(g2d, polyline); + + g2d.setPaint(oldPaint); + return true; + } + } + return false; + } + + private static boolean paintDSColumnParametermarkWhenExsit(Graphics2D g2d, Object value, int height, int left_dowm_count) { + // 左下角:动态注入参数 + if (value instanceof DSColumn && ((DSColumn) value).getParameters() != null) { + if (((DSColumn) value).getParameters().length > 0) { + Paint oldPaint = g2d.getPaint(); + + g2d.setPaint(CELL_PARAMETER_FILTER_MARK_CONLR); + GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3); + polyline.moveTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 1); + polyline.lineTo((left_dowm_count + 1) * CELL_MARK_SIZE + 1, height - 1); + polyline.lineTo(0 + left_dowm_count * CELL_MARK_SIZE, height - 2 - CELL_MARK_SIZE); + GraphHelper.fill(g2d, polyline); + + g2d.setPaint(oldPaint); + return true; + } + } + return false; + } + + /* + * 画悬浮元素 + * + * 仅根据宽度 + 高度画 + */ + //b:此方法在grid和tohtml的时候都被调用,所以对formula会有冲突,暂时这么改,应该考虑分开的,也可以根据result来判断,但是那么写好像不妥 + public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, int width, int height, int resolution) { + Style.paintBackground(g2d, flotEl.getStyle(), width, height); + + Object value = flotEl.getValue(); + if (value instanceof BaseFormula) { + value = ((BaseFormula) value).getContent(); + } + if (value instanceof BaseChartCollection) { + value = ((BaseChartCollection) value).createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), WebChartIDInfo.createEmptyDesignerInfo(), width, height); + } + //图片需要切割一下 + if (value instanceof Image) { + value = CellUtils.value2ImageWithBackground(value, resolution, flotEl.getStyle(), width, height); + } + Style.paintContent(g2d, value, flotEl.getStyle(), width, height, resolution); + + Style.paintBorder(g2d, flotEl.getStyle(), width, height); + } + + /* + * 画悬浮元素flotEl + * + * 也就是画三个东西:背景 + 内容 + 边框 + */ + public static void paintFloatElement(Graphics2D g2d, FloatElement flotEl, Rectangle paintRectangle, Rectangle clipRectangle, int resolution) { + // 画悬浮元素的背景 + Style.paintBackground(g2d, flotEl.getStyle(), paintRectangle, clipRectangle); + + Object value = flotEl.getValue(); + if (value instanceof ResultChangeWhenExport) { + value = ((ResultChangeWhenExport) value).changeThis(); + } + // 画悬浮元素的内容 + Style.paintContent(g2d, value, resolution, flotEl.getStyle(), paintRectangle, clipRectangle); + // 画悬浮元素的边框 + Style.paintBorder(g2d, flotEl.getStyle(), paintRectangle, clipRectangle); + } + + public static void paintHTMLContent(Graphics2D g2d, String value, int resolution, Style style, Rectangle paintRectangle, Rectangle clipRectangle) { + Style.paintContent(g2d, createHTMLContentBufferedImage(value, paintRectangle, 0, 0, style), resolution, style, paintRectangle, clipRectangle); + } + + public static void paintTag(Painter painter, Repository repo, int width, int height, Style style, Tag tag) { + painter.paintTag(repo, width, height, style, tag); + } + + /** + * 如果用户希望以HTML方式展示String,这个时候先value变成图片 + * + * @param value 值 + * @param paintRectangle 绘制范围 + * @param x x坐标 + * @param y y坐标 + * @param style 当前格子样式 + * @return BufferedImage 返回图片. + */ + public static BufferedImage createHTMLContentBufferedImage(String value, Rectangle paintRectangle, int x, int y, Style style) { + return Html2ImageUtils.createHTMLContentBufferedImage(value, paintRectangle, x, y, style); + } + + /** + * see BaseUtils.getLineTextList, 等于BaseUtils.getLineTextList().size() + * Denny: 为了提高速度和性能,才单独拿出来的 + * TODO: 重构 + * + * @param text 文本 + * @param style 样式 + * @param paintWidth 单元格宽度 + * @return paintWidth 单位为PT + */ + public static int getLineTextCount(String text, Style style, UNIT paintWidth) { + if (style.getRotation() != 0) { + return 1; + } + + + if (style.getTextStyle() != Style.TEXTSTYLE_WRAPTEXT) { + return dealNotWrapTextCount(text.toCharArray()); + } else {// 自动换行 + return dealWrapTextCount(text, style, paintWidth); + } + } + + private static int dealNotWrapTextCount(char[] text_chars) { + boolean remain_chars = false; + int count = 0; + for (int t = 0; t < text_chars.length; t++) { + if (text_chars[t] == '\\') {// 判断是否是 "\n" + if (t + 1 < text_chars.length && text_chars[t + 1] == 'n') { + // 是"\n"字符串,但不是换行符. + t++; + count++; + if (remain_chars) { + remain_chars = false; + } + } else { + if (!remain_chars) { + remain_chars = true; + } + } + } else if (text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n')) { + count++; + if (remain_chars) { + remain_chars = false; + } + } else { + if (!remain_chars) { + remain_chars = true; + } + } + } + + // 最后一个 + if (remain_chars) { + count++; + } + + return count; + } + + // 自动换行 + //neil:style里面, 默认值padding right = 2时, 默认不生效, 这边算行高时也不要计算入内 + //临时处理, 去掉左边框线, 因为浏览器计算时需要考虑左边框线宽度, 但这边还是存在问题的 + //同样需要考虑的是导出和web端展示, padding计算方式也不一致. + private static int dealWrapTextCount(String text, Style style, UNIT unitWidth) { + AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess(); + if (process != null) { + return process.getAutoChangeLineCount(text, new ObjectHolder(style), unitWidth); + } + int count = 0; + char[] text_chars = text.toCharArray(); + FontMetrics fontMetrics = getFontMetrics(style); + double paintWidth = unitWidth.toPixD(Constants.FR_PAINT_RESOLUTION); + double width = paintWidth - style.getPaddingLeft() - (style.getPaddingRight() == Style.DEFAULT_PADDING ? 0 : style.getPaddingRight()) - style.getBorderLeftWidth(); + boolean remain_lineText = false; + int lineTextWidth = 0; + int wordWidth = 0; + for (int t = 0, len = text_chars.length; t < len; t++) { + if (t != 0 && BaseUtils.isNumOrLetter(text_chars[t]) && BaseUtils.isNumOrLetter(text_chars[t - 1])) { + if (wordWidth + fontMetrics.charWidth(text_chars[t]) > width) { + if (lineTextWidth > 0) { + count++; + remain_lineText = false; + lineTextWidth = 0; + } + count++; + wordWidth = 0; + } + wordWidth += fontMetrics.charWidth(text_chars[t]); + } else if (isSwitchLine(text_chars, t) || isLN(text_chars, t)) {// 判断是否是 "\n" + if (isLN(text_chars, t)) { + t++;// 忽略'n'字符.// 是"\n"字符串,但不是换行符,依然需要换行. + } + if (lineTextWidth + wordWidth > width && remain_lineText) { + count += 2; + } else { + count++; + } + remain_lineText = false; + lineTextWidth = 0; + wordWidth = 0; + } else { + if (text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == '\\') {// 判断是否是转义字符'\' + t++;// _denny: 增加了转义字符'\\'用来表示\,使"\n"可以输入 + } + if (lineTextWidth + wordWidth > width && remain_lineText) { + count++; + lineTextWidth = isPunctuationAtLineHead(t, text_chars) ? dealLineWidthWithPunctuation(t, text_chars, fontMetrics) : 0; + } + remain_lineText = true; + lineTextWidth += wordWidth; + wordWidth = fontMetrics.charWidth(text_chars[t]); + } + } + if (lineTextWidth + wordWidth > width && remain_lineText) { + count += 2; + } else { + count++; + } + return count; + } + + /** + * 标点符号是否在换行后的行首 + */ + private static boolean isPunctuationAtLineHead(int t, char[] text_chars) { + if (t > 1 && BaseUtils.isPunctuation(text_chars[t - 1])) { + return true; + } + return false; + } + + /** + * 防止有连续多个标点符号,要找一个非标点符号字符 + * + * @date 2014-4-17 + */ + private static int dealLineWidthWithPunctuation(int t, char[] text_chars, FontMetrics fontMetrics) { + if (t < 2) { + return 0; + } + int lineWidth = 0; + for (int index = t - 2; index >= 0; index--) { + lineWidth += fontMetrics.charWidth(text_chars[index]); + if (!BaseUtils.isPunctuation(text_chars[index])) { + break; + } + } + return lineWidth; + } + + private static boolean isSwitchLine(char[] text_chars, int t) { + return text_chars[t] == '\n' || (text_chars[t] == '\r' && t + 1 < text_chars.length - 1 && text_chars[t + 1] != '\n'); + } + + private static boolean isLN(char[] text_chars, int t) { + return text_chars[t] == '\\' && t + 1 < text_chars.length && text_chars[t + 1] == 'n'; + } + + /** + * Gets the preferred width. + */ + public static UNIT getPreferredWidth(CellElement cell, UNIT height) { + if (cell == null) { + return UNIT.ZERO; + } + + Object value = cell.getShowValue(); + // 只接受Text,Number,和SeparatorPainter + // got the text + if (value instanceof BaseFormula) { + if (((BaseFormula) value).getResult() != null) { + value = ((BaseFormula) value).getResult(); + } else { + value = StringUtils.EMPTY; + } + } + Style style = cell.getStyle(); + if (style == null) { + style = Style.DEFAULT_STYLE; + } + CellGUIAttr cg = cell.getCellGUIAttr() == null ? new CellGUIAttr() : cell.getCellGUIAttr(); + value = Utils.resolveOtherValue(value, cg.isShowAsImage(), PresentationType.EXPORT); + String text = Style.valueToText(value, style.getFormat()); + + FontMetrics cellFM = getFontMetrics(style); + //bug 12151 有边框线的单元格 自动调整列宽 会多一行 + UNIT padding = new PT(style.getPaddingLeft() + style.getPaddingRight()); + + if (cg.isShowAsHTML()) { + return Html2ImageUtils.getHtmlWidth(text, height, style); + } + + return FU.valueOfPix(cellFM.stringWidth(text) + UNIT_SIZE, Constants.FR_PAINT_RESOLUTION).add(padding); + } + + private static FontMetrics getFontMetrics(Style style) { + Font font = style.getFRFont().applyResolutionNP(Constants.FR_PAINT_RESOLUTION); + FontProcessor processor = ExtraClassManager.getInstance().getSingle(FontProcessor.MARK_STRING); + if (processor != null) { + font = processor.readExtraFont(font); + } + return GraphHelper.getFontMetrics(font); + } + + /** + * Preferred height. (Got the shrink preferred height of CellElement). + * 单位格的预计算高度 + * + * @param cellElement 单元格内容 + * @param paintWidth 画的宽度 + * @return UNIT 单位 + */ + public static UNIT analyzeCellElementPreferredHeight(CellElement cellElement, UNIT paintWidth) { + // 计算高度用显示值 + Object value = cellElement.getShowValue(); + // 只接受Text,Number,和SeparatorPainter + Style style = cellElement.getStyle(); + // got the text + if (value instanceof BaseFormula) { + if (((BaseFormula) value).getResult() != null) { + value = ((BaseFormula) value).getResult(); + } else { + value = StringUtils.EMPTY; + } + } + CellGUIAttr cg = cellElement.getCellGUIAttr() == null ? new CellGUIAttr() : cellElement.getCellGUIAttr(); + if (!(value instanceof String) && !(value instanceof Integer)) { + value = DataUtils.resolveOtherValue(value, cg.isShowAsImage(), cg.isShowAsDownload(), null, true); + } + String text = Style.valueToText(value, style.getFormat()); + + if (cg.isShowAsHTML()) { + return Html2ImageUtils.getHtmlHeight(text, paintWidth, style); + } + + return PaintUtils.analyzeCellElementPreferredHeight(text, style, paintWidth, cg.isShowAsHTML()); + } + + /** + * 单位格的预计算高度 + * 单位PT + * + * @param text 文本 + * @param style 格式 + * @param paintWidth 画的宽度 + * @param isShowAsHtml 是否以html展示 + * @return 返回 单位 + */ + private static UNIT analyzeCellElementPreferredHeight(String text, Style style, UNIT paintWidth, boolean isShowAsHtml) { + if (style == null) { + //peter:获取默认的Style. + style = Style.DEFAULT_STYLE; + } + + // got the text + if (text == null || text.length() <= 0) { + return PT.valueOf(0); + } + + // 变成Line Text List. + if (style.getRotation() != 0) { // more easy to paint. + // attribute map. + return PT.valueOf((float) GraphHelper.stringDimensionWithRotation(text, style.getFRFont(), -style.getRotation(), + CoreConstants.DEFAULT_FRC).getHeight()); + } + // 先获得FontMetics. + int lineCount = getLineTextCount(text, style, paintWidth); + AutoChangeLineAndDrawProcess process = AutoChangeLineAndDrawManager.getProcess(); + if (process != null) { + //算了这两个接口分开做 + return process.getLinedTextHeight(lineCount, new ObjectHolder(style)); + } + + // carl:和paint那边一致,添上段前段后和行间距 + PT lineSpacing = PT.valueOf(style.getSpacingAfter() + style.getSpacingBefore() + style.getLineSpacing() * lineCount); + FontMetrics fontMetrics = getFontMetrics(style); + int textHeight = fontMetrics.getHeight(); + FU allTextHeight = FU.valueOfPix(textHeight * lineCount, Constants.FR_PAINT_RESOLUTION); + return lineSpacing.add(allTextHeight);// 需要给底部添加Leading. + } + + /** + * 截取文字,只考虑了垂直方向,水平方向没意义且难度大. + * + * @param value 画的值 + * @param style 字体样式格式. + * @param blockArea 冻结的范围 + * @param resolution 分辨率 + * @return 返回的字符串 + */ + public static String clipBlockValue(Object value, Style style, Rectangle primitiveArea, Rectangle blockArea, int resolution, boolean isShowAsHTML) { + if (value == null) { + return null; + } + if (value instanceof BaseFormula) { + value = ((BaseFormula) value).getResult(); + } + if (blockArea.y >= primitiveArea.height || blockArea.y + blockArea.height <= 0) { + return null; + } + //截取位置,相对于clipArea + int startY = blockArea.y > 0 ? blockArea.y : 0; + int endY = blockArea.y + blockArea.height < primitiveArea.height ? blockArea.y + blockArea.height : primitiveArea.height; + if (blockArea.x >= primitiveArea.width || blockArea.x + blockArea.width <= 0) { + return null; + } + if (isShowAsHTML) { + return Html2ImageUtils.clipHtmlContent(value, style, primitiveArea, resolution, startY, endY); + } + List lineList = BaseUtils.getLineTextList((String) value, style, style.getFRFont().applyResolutionNP(resolution), primitiveArea.width, resolution); + if (lineList.isEmpty()) { + return null; + } + double spacingBefore = PT.pt2pix(style.getSpacingBefore(), resolution); + double spacingAfter = PT.pt2pix(style.getSpacingAfter(), resolution); + double lineSpacing = PT.pt2pix(style.getLineSpacing(), resolution); + double lineHeight = lineSpacing + GraphHelper.getFontMetrics(style.getFRFont().applyResolutionNP(resolution)).getHeight(); + int textAllHeight = (int) (lineHeight * lineList.size() + spacingBefore + spacingAfter); + //第一行文字距区域高度 + int textStartY = (int) spacingBefore; + + if (style.getVerticalAlignment() == Constants.BOTTOM) { + textStartY += (primitiveArea.height - textAllHeight); + } + if (endY <= textStartY || startY >= textStartY + lineHeight * lineList.size()) { + return null; + } + int lineStart = getLineStart(lineList, lineHeight, textStartY, startY);//截取区域起始行 + int lineEnd = getLineEnd(lineList, lineHeight, endY, textStartY);//截取区域结束行 + String text = ""; + for (; lineStart <= lineEnd; lineStart++) { + text += lineList.get(lineStart); + } + return text; + } + + private static int getLineStart(List lineList, double lineHeight, int textStartY, int startY) { + int lineStart = 0; + for (int i = 0; i < lineList.size(); i++) { + if (textStartY + lineHeight * (i) <= startY && textStartY + lineHeight * (i + 1) > startY) {//压线 + if (startY - textStartY - lineHeight * (i) > lineHeight / 2) { + lineStart = i + 1; + } else { + lineStart = i; + } + } + } + return lineStart; + } + + private static int getLineEnd(List lineList, double lineHeight, int endY, int textStartY) { + int lineEnd = lineList.size() - 1; + for (int i = 0; i < lineList.size(); i++) { + if (textStartY + lineHeight * (i) < endY && textStartY + lineHeight * (i + 1) >= endY) {//压线 + //neil:仿宋,12号字, 行间距8为例, 转为px的行间距大小为10.666, 这边算出的应该有31.98行, 因此要进位 + if (endY - textStartY - lineHeight * (i) >= lineHeight / 2) { + lineEnd = i; + } else { + lineEnd = i - 1; + } + } + } + return lineEnd; + } + + /** + * paintBarcode + */ + public static void paintBarcode(Graphics2D g2d, int width, int height, String text, Style style, BarcodeAttr barcodeAttr) { + BarcodeImpl barcodeImpl; + try { + barcodeImpl = BarCodeUtils.getBarcodeImpl(barcodeAttr, text); + } catch (BarcodeException exp) { + try { + //设置默认值. + barcodeImpl = BarCodeUtils.getBarcodeImpl(new BarcodeAttr(), null); + } catch (BarcodeException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return; + } + } + + //字体 + if (style.getFRFont() != null) { + barcodeImpl.setFont(style.getFRFont()); + barcodeImpl.setForeground(style.getFRFont().getForeground()); + } + //背景 + Background background = style.getBackground(); + if (background != null && background instanceof ColorBackground) { + barcodeImpl.setBackground(((ColorBackground) background).getColor()); + } + + //根据宽度和高度来确定起始点 + int pointX = (width - barcodeImpl.getWidth()) / 2; + int pointY = (height - barcodeImpl.getHeight()) / 2; + + barcodeImpl.draw(g2d, pointX, pointY); + } + + /** + * create font attribute map, 创建属性map + * + * @param font 字体 + * @return map 返回字体创建的Map + */ + public static Map createFontAttributeMap(Font font) { + Map returnFontAttributeMap = (Map) fontAttributeMapCache.get(font); + if (returnFontAttributeMap == null) {// create + // returnFontAttributeMap. + returnFontAttributeMap = font.getAttributes(); + fontAttributeMapCache.put(font, returnFontAttributeMap); + } + + if (font instanceof FRFont) { + FRFont frFont = (FRFont) font; + + // Strikethrough + if (frFont.isStrikethrough()) { + returnFontAttributeMap.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON); + } + } + + return returnFontAttributeMap; + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java b/designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java new file mode 100644 index 000000000..c760d01da --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java @@ -0,0 +1,214 @@ +package com.fr.design.fit.common; + +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteBodyLayout; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.fit.JFormType; +import com.fr.design.fit.NewJForm; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.FormArea; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.JTemplate; +import com.fr.event.Event; +import com.fr.event.Listener; +import com.fr.file.MemFILE; +import com.fr.file.StashedFILE; +import com.fr.form.fit.common.LightTool; +import com.fr.form.fit.NewFormMarkAttr; +import com.fr.form.ui.Widget; +import com.fr.form.ui.widget.CRBoundsWidget; +import com.fr.general.ComparatorUtils; + +import java.awt.Rectangle; +import java.util.List; + +/** + * @description:模板工具类 + * @author: Henry.Wang + * @create: 2020/09/03 14:19 + */ +public class TemplateTool { + //和转换有关的所有代码都在这个监听器中 + //在判断新老模式时,统一使用FormUIModeConfig.getInstance().newUIMode()进行判断 + private static Listener switchListener = new Listener() { + @Override + public void on(Event event, JTemplate jTemplate) { + JFormType currentType = JFormType.OLD_TYPE; + if (AdaptiveSwitchUtil.isSwitchJFromIng()) { + currentType = DesignerUIModeConfig.getInstance().newUIMode() ? JFormType.NEW_TYPE : JFormType.OLD_TYPE; + } else { + if (jTemplate instanceof NewJForm) { + NewJForm newJForm = (NewJForm) jTemplate; + if (newJForm.mobileForm()) { + currentType = JFormType.OLD_TYPE; + } else if (LightTool.containNewFormFlag(newJForm.getTarget()) || newJForm.getTarget().getTemplateID() == null) { + currentType = JFormType.NEW_TYPE; + } + } + } + //UI转换 + currentType.switchUIMode(); + //标志位转换 + currentType.updateJFromTemplateType(jTemplate); + //预览方式转换 + currentType.updatePreviewType(jTemplate); + } + }; + + public static Listener getSwitchListener() { + return switchListener; + } + + /** + * @param + * @Description: 获取当前模板 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:17 + */ + public static JTemplate getCurrentEditingTemplate() { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return jTemplate; + } + + /** + * @param + * @Description: 获取当前NewJForm类型的模板 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:17 + */ + public static NewJForm getCurrentEditingNewJForm() { + JTemplate jTemplate = getCurrentEditingTemplate(); + if (jTemplate instanceof NewJForm) + return (NewJForm) jTemplate; + return null; + } + + /** + * @param newJTemplate + * @Description: 每次切换设计模式,都会生成新的JForm对象。但是TabPane关联的还是老的JForm对象,所以要重置关联的对象 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:15 + */ + public static void resetTabPaneEditingTemplate(JTemplate newJTemplate) { + if (newJTemplate == null) + return; + List> jTemplateList = HistoryTemplateListCache.getInstance().getHistoryList(); + for (int i = 0; i < jTemplateList.size(); i++) { + JTemplate oldJTemplate = jTemplateList.get(i); + if (oldJTemplate != null && ComparatorUtils.equals(oldJTemplate.getEditingFILE(), newJTemplate.getEditingFILE())) { + jTemplateList.set(i, newJTemplate); + MutilTempalteTabPane.getInstance().refreshOpenedTemplate(jTemplateList); + return; + } + } + } + + + /** + * @param jTemplate + * @Description: 是否是新建的且没有操作的模板 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/14 20:41 + */ + public static boolean isNewTemplateWithoutModify(JTemplate jTemplate) { + return ((jTemplate.getEditingFILE() instanceof MemFILE) && jTemplate.isSaved()) ? true : false; + } + + /** + * @param template + * @Description: 激活模板 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:16 + */ + public static void activeAndResizeTemplate(JTemplate template) { + DesignerContext.getDesignerFrame().addAndActivateJTemplate(template); + DesignerContext.getDesignerFrame().setVisible(true); + DesignerContext.getDesignerFrame().resizeFrame(); + } + + /** + * @param jTemplate + * @Description:保存模板 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/6 14:32 + */ + public static void saveForm(JTemplate jTemplate) { + //为空不保存 + if (jTemplate == null) + return; + //不是NewJForm的模板不保存 + if (!(jTemplate instanceof NewJForm)) + return; + //切换环境时产生的模板不保存 + if (jTemplate.getEditingFILE() instanceof StashedFILE) + return; + //新建的且没有操作的模板不保存 + if (TemplateTool.isNewTemplateWithoutModify(jTemplate)) + return; + jTemplate.stopEditing(); + jTemplate.saveTemplate(); + jTemplate.requestFocus(); + } + + /** + * @param height + * @param width + * @param newJForm + * @Description: 只改变绝对布局body的尺寸 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/11 15:14 + */ + public static void onlyChangeAbsoluteBodySize(int height, int width, NewJForm newJForm) { + FormDesigner formDesigner = newJForm.getFormDesign(); + FormArea formArea = formDesigner.getArea(); + XLayoutContainer root = formDesigner.getRootComponent(); + XWAbsoluteBodyLayout xwAbsoluteBodyLayout = LayoutTool.getXWAbsoluteBodyLayout(newJForm); + if (root.acceptType(XWFitLayout.class) && xwAbsoluteBodyLayout != null) { + XWFitLayout layout = (XWFitLayout) root; + if (height == layout.toData().getContainerHeight() && width == layout.toData().getContainerWidth()) + return; + formArea.setWidthPaneValue(width); + formArea.setHeightPaneValue(height); + layout.setSize(width, height); + xwAbsoluteBodyLayout.setSize(width, height); + Widget widget = layout.toData().getWidget(0); + if (widget instanceof CRBoundsWidget) { + ((CRBoundsWidget) widget).setBounds(new Rectangle(0, 0, width, height)); + } + layout.toData().setContainerWidth(width); + layout.toData().setContainerHeight(height); + formArea.doReCalculateRoot(width, height, layout); + } + formDesigner.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED); + } + + /** + * @param newJForm + * @Description: 因为新老模板切换有截断的问题,所以body的尺寸会在调用onlyChangeAbsoluteBodySize之后发生改变。为了使模板文件中的尺寸不发生,要在模板保存时调用此函数 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/11 15:20 + */ + public static void resetAbsoluteBodySize(NewJForm newJForm) { + if (LayoutTool.absoluteLayoutForm(newJForm)) { + NewFormMarkAttr newFormMarkAttr = newJForm.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG); + XLayoutContainer root = newJForm.getFormDesign().getRootComponent(); + if (newFormMarkAttr != null && root instanceof XWFitLayout) { + ((XWFitLayout) root).toData().setContainerWidth(newFormMarkAttr.getBodyWidth()); + ((XWFitLayout) root).toData().setContainerHeight(newFormMarkAttr.getBodyHeight()); + } + } + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/menupane/BrowserFitAttrPane.java b/designer-form/src/main/java/com/fr/design/fit/menupane/BrowserFitAttrPane.java new file mode 100644 index 000000000..fdc2f8332 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/menupane/BrowserFitAttrPane.java @@ -0,0 +1,303 @@ +package com.fr.design.fit.menupane; + +import com.fr.config.Configuration; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.fit.FitStateCompatible; +import com.fr.design.fit.JFormType; +import com.fr.form.fit.FitType; +import com.fr.form.fit.config.FormFitConfig; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.report.fit.ReportFitAttr; +import com.fr.stable.StringUtils; +import com.fr.transaction.Configurations; +import com.fr.transaction.Worker; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * Created by Administrator on 2016/5/5/0005. + */ +public class BrowserFitAttrPane extends BasicBeanPane { + + protected FontRadioGroup fontRadioGroup; + protected FitRadioGroup fitRadionGroup; + protected UICheckBox globalCheck; + protected FitPreviewPane fitPreviewPane; + protected ReportFitAttr localFitAttr; + protected UIRadioButton horizonRadio; + protected UIRadioButton doubleRadio; + protected UIRadioButton notFitRadio; + protected UIRadioButton fontFitRadio; + protected UIRadioButton fontNotFitRadio; + private UIButton editGlobalOps; + private JPanel borderPane; + private JPanel globalOpsPane; + private JPanel fitOpsPane; + private final JFormType jFormType; + + public BrowserFitAttrPane(JFormType jFormType, ReportFitAttr fitAttr) { + this.jFormType = jFormType; + if (fitAttr == null) { + initComponents(jFormType.obtainFitAttr()); + } else { + initComponents(fitAttr); + } + } + + protected void initComponents(ReportFitAttr globalFitAttr) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + globalOpsPane = initGlobalOpsPane(globalFitAttr); + this.add(globalOpsPane, BorderLayout.NORTH); + fitOpsPane = initFitOpsPane(); + } + + protected void initBorderPane(String title) { + borderPane = FRGUIPaneFactory.createTitledBorderPaneCenter(title); + borderPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0)); + borderPane.add(fitOpsPane, BorderLayout.WEST); + fitPreviewPane = new FitPreviewPane(); + borderPane.add(fitPreviewPane, BorderLayout.SOUTH); + borderPane.add(getHintUILabel()); + this.add(borderPane, BorderLayout.CENTER); + } + + /** + * @Description: 获取提示信息 + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/9/9 16:09 + */ + private UILabel getHintUILabel() { + String hint = globalCheck.isSelected() ? getFillBlank(3) + Toolkit.i18nText("Fine-Designer_Fit_Attr_Pane_Hint") : StringUtils.EMPTY; + UILabel hintUILabel = new UILabel(hint); + hintUILabel.setForeground(new Color(143, 143, 146)); + return hintUILabel; + } + + /** + * @Description: 获取空字符串 + * @param n + * @return: + * @Author: Henry.Wang + * @date: 2020/9/9 16:09 + */ + private String getFillBlank(int n) { + String s = ""; + for (int i = 0; i < n; i++) { + s = s + " "; + } + return s; + } + + private JPanel initFitOpsPane() { + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p, p, p, p}; + + ActionListener actionListener = getPreviewActionListener(); + + fontRadioGroup = new FontRadioGroup(); + fontFitRadio = new UIRadioButton(Toolkit.i18nText("Fine-Designer_Fit") + getFillBlank(4)); + fontFitRadio.setSelected(true); + fontNotFitRadio = new UIRadioButton(Toolkit.i18nText("Fine-Designer_Fit-No") + getFillBlank(2)); + addRadioToGroup(fontRadioGroup, fontFitRadio, fontNotFitRadio); + fontRadioGroup.addActionListener(actionListener); + + fitRadionGroup = new FitRadioGroup(); + horizonRadio = new UIRadioButton(FitType.HORIZONTAL_FIT.description()); + doubleRadio = new UIRadioButton(FitType.DOUBLE_FIT.description()); + notFitRadio = new UIRadioButton(FitType.NOT_FIT.description()); + addRadioToGroup(fitRadionGroup, doubleRadio, horizonRadio, notFitRadio); + fitRadionGroup.addActionListener(actionListener); + + + JPanel fitOpsPane = TableLayoutHelper.createTableLayoutPane(initFitComponents(), rowSize, columnSize); + fitOpsPane.setBorder(BorderFactory.createEmptyBorder(10, 13, 10, 10)); + return fitOpsPane; + } + + protected Component[][] initFitComponents() { + UILabel fitFontLabel = new UILabel(Toolkit.i18nText("Fine-Designer_Fit-Font")); + fitFontLabel.setHorizontalAlignment(SwingConstants.RIGHT); + UILabel reportFitLabel = new UILabel(Toolkit.i18nText("Fine-Designer_Fit_Report_Scale_Method")); + reportFitLabel.setHorizontalAlignment(SwingConstants.RIGHT); + Component[][] components = new Component[][]{ + new Component[]{fitFontLabel, createFontRadioGroupPane()}, + new Component[]{reportFitLabel, createFitAttrRadioGroupPane()} + }; + return components; + } + + private JPanel createFontRadioGroupPane() { + JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 0)); + panel.add(fontFitRadio); + panel.add(fontNotFitRadio); + return panel; + } + + private JPanel createFitAttrRadioGroupPane() { + JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 0)); + panel.add(doubleRadio); + panel.add(horizonRadio); + panel.add(notFitRadio); + return panel; + } + + private void addRadioToGroup(ButtonGroup buttonGroup, UIRadioButton... radios) { + for (UIRadioButton radio : radios) { + buttonGroup.add(radio); + } + } + + private JPanel initGlobalOpsPane(final ReportFitAttr globalFitAttr) { + final JPanel globalOpsPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + globalCheck = new UICheckBox(Toolkit.i18nText("Fine-Designer_Fit-UseGlobal")); + globalOpsPane.add(globalCheck); + globalCheck.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + boolean isLocalConfig = !globalCheck.isSelected(); + //勾选全局时,采用全局保存的自适应属性更新界面 + if (!isLocalConfig) { + ReportFitAttr attr = globalFitAttr; + populateAttrPane(attr); + remove(BrowserFitAttrPane.this.borderPane); + initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Global")); + } else { + ReportFitAttr attr = localFitAttr; + populateAttrPane(attr); + remove(BrowserFitAttrPane.this.borderPane); + initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Local")); + } + fontRadioGroup.setEnabled(isLocalConfig); + fitRadionGroup.setEnabled(isLocalConfig); + editGlobalOps.setVisible(!isLocalConfig); + String fitOptions = getCurrentFitOptions(); + fitPreviewPane.refreshPreview(fitOptions, fitRadionGroup.isEnabled()); + } + }); + + editGlobalOps = new UIButton(Toolkit.i18nText("Fine-Designer_Fit-EditGlobal")); + editGlobalOps.setVisible(false); + editGlobalOps.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + fontRadioGroup.setEnabled(true); + fitRadionGroup.setEnabled(true); + String fitOptions = getCurrentFitOptions(); + + fitPreviewPane.refreshPreview(fitOptions, fitRadionGroup.isEnabled()); + } + + public void mouseEntered(MouseEvent e) { + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + + public void mouseExited(MouseEvent e) { + setCursor(Cursor.getDefaultCursor()); + } + }); + globalOpsPane.add(editGlobalOps); + return globalOpsPane; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Designer_Fit-AttrSet"); + } + + @Override + public void populateBean(ReportFitAttr attr) { + if (attr == null) { + //如果为空, 就用全局的 + attr = this.jFormType.obtainFitAttr(); + populateGlobalComponents(); + } else { + initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Local")); + } + this.localFitAttr = attr; + populateAttrPane(attr); + } + + private void populateAttrPane(ReportFitAttr attr) { + fontRadioGroup.selectFontFit((attr).isFitFont()); + int fitState = FitStateCompatible.getNewTypeFromOld(attr.fitStateInPC()); + fitRadionGroup.selectIndexButton(fitState); + fitPreviewPane.refreshPreview(getCurrentFitOptions(), fitRadionGroup.isEnabled()); + } + + protected void populateGlobalComponents() { + globalCheck.setSelected(true); + fontRadioGroup.setEnabled(false); + fitRadionGroup.setEnabled(false); + editGlobalOps.setVisible(true); + initBorderPane(Toolkit.i18nText("Fine-Designer_Fit-Global")); + } + + //有八种组合, 不过有意义的就是6种, 以此为key去缓存里找对应的预览图片 + public String getCurrentFitOptions() { + return fitRadionGroup.getSelectRadioIndex() + "" + fontRadioGroup.getSelectRadioIndex(); + } + + private ActionListener getPreviewActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String fitOptions = getCurrentFitOptions(); + fitPreviewPane.refreshPreview(fitOptions, fontRadioGroup.isEnabled()); + } + }; + } + + @Override + public ReportFitAttr updateBean() { + ReportFitAttr attr = new ReportFitAttr(); + attr.setFitFont(fontRadioGroup.isFontFit()); + int fitState = FitStateCompatible.getOldTypeFromNew(fitRadionGroup.getSelectRadioIndex()); + attr.setFitStateInPC(fitState); + + // 直接用全局的 + if (globalCheck.isSelected()) { + updateGlobalConfig(attr); + return null; + } + this.localFitAttr = attr; + return attr; + } + + private void updateGlobalConfig(final ReportFitAttr attr) { + + Configurations.update(new Worker() { + @Override + public void run() { + jFormType.updateFitAttr(attr); + } + + @Override + public Class[] targets() { + return new Class[]{FormFitConfig.class}; + } + }); + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/menupane/FitPreviewPane.java b/designer-form/src/main/java/com/fr/design/fit/menupane/FitPreviewPane.java new file mode 100644 index 000000000..ed387f39d --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/menupane/FitPreviewPane.java @@ -0,0 +1,76 @@ +package com.fr.design.fit.menupane; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.IOUtils; + +import javax.swing.ImageIcon; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Administrator on 2016/5/5/0005. + */ +public class FitPreviewPane extends BasicPane { + private static final String DEFAULT_FONT_TAG = "00"; + private static final String DEFAULT_TAG = "01"; + private static final String HORIZON_FONT_TAG = "10"; + private static final String HORIZON_TAG = "11"; + private static final String DOUBLE_FONT_TAG = "20"; + private static final String DOUBLE_TAG = "21"; + private static final String NOT_FONT_TAG = "30"; + private static final String NOT_TAG = "31"; + + private UILabel imageLabel; + private Map cachedPreviewImage = new HashMap(); + private Map globalCachedPreviewImage = new HashMap(); + + public FitPreviewPane() { + //初始化缓存图片, 有些无意义的组合. + initCacheImage(); + //初始化组件 + initComponents(); + this.setPreferredSize(new Dimension(540, 170)); + } + + //默认和不自适应时,字体自适应不起效,只有6张图 + private void initCacheImage() { + globalCachedPreviewImage.put(DEFAULT_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + DOUBLE_FONT_TAG + ".png"))); + globalCachedPreviewImage.put(DEFAULT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + DOUBLE_TAG + ".png"))); + globalCachedPreviewImage.put(HORIZON_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + HORIZON_FONT_TAG + ".png"))); + globalCachedPreviewImage.put(HORIZON_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + HORIZON_TAG + ".png"))); + globalCachedPreviewImage.put(DOUBLE_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + NOT_FONT_TAG + ".png"))); + globalCachedPreviewImage.put(DOUBLE_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/gray/" + NOT_FONT_TAG + ".png"))); + + cachedPreviewImage.put(DEFAULT_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + DOUBLE_FONT_TAG + ".png"))); + cachedPreviewImage.put(DEFAULT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + DOUBLE_TAG + ".png"))); + cachedPreviewImage.put(HORIZON_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + HORIZON_FONT_TAG + ".png"))); + cachedPreviewImage.put(HORIZON_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + HORIZON_TAG + ".png"))); + cachedPreviewImage.put(DOUBLE_FONT_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + NOT_FONT_TAG + ".png"))); + cachedPreviewImage.put(DOUBLE_TAG, new ImageIcon(IOUtils.readImage("/com/fr/design/images/reportfit/preview/" + NOT_FONT_TAG + ".png"))); + + } + + private void initComponents() { + this.setLayout(FRGUIPaneFactory.createCenterFlowLayout()); + imageLabel = new UILabel(); + ImageIcon image = cachedPreviewImage.get(DEFAULT_TAG); + imageLabel.setIcon(image); + this.add(imageLabel, BorderLayout.CENTER); + } + + public void refreshPreview(String index, boolean isEditedable) { + ImageIcon newImageIcon = isEditedable ? cachedPreviewImage.get(index) : globalCachedPreviewImage.get(index); + imageLabel.setIcon(newImageIcon); + } + + @Override + protected String title4PopupWindow() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit-Preview"); + } + + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/menupane/FitRadioGroup.java b/designer-form/src/main/java/com/fr/design/fit/menupane/FitRadioGroup.java new file mode 100644 index 000000000..46fb32768 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/menupane/FitRadioGroup.java @@ -0,0 +1,80 @@ +package com.fr.design.fit.menupane; + +import com.fr.design.gui.ibutton.UIRadioButton; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +/** + * 自适应四个按钮选项的group + *

+ * Created by Administrator on 2016/5/5/0005. + */ +public class FitRadioGroup extends ButtonGroup { + + private List radioButtons = new ArrayList(); + + @Override + public void add(AbstractButton button) { + super.add(button); + + UIRadioButton radioButton = (UIRadioButton) button; + radioButtons.add(radioButton); + } + + /** + * 设置按钮状态 + */ + public boolean isEnabled() { + return radioButtons.get(0).isEnabled(); + } + + /** + * 设置按钮状态 + */ + public void setEnabled(boolean enabled) { + for (UIRadioButton radioButton : radioButtons) { + radioButton.setEnabled(enabled); + } + } + + /** + * 获取当前选中的按钮index + * + * @return 按钮index + */ + public int getSelectRadioIndex() { + for (int i = 0, len = radioButtons.size(); i < len; i++) { + if (radioButtons.get(i).isSelected()) { + return i; + } + } + + return 0; + } + + /** + * 选中指定index的按钮 + */ + public void selectIndexButton(int index) { + if (index < 0 || index > radioButtons.size() - 1) { + return; + } + + UIRadioButton button = radioButtons.get(index); + button.setSelected(true); + } + + /** + * 给所有的按钮加上监听 + */ + public void addActionListener(ActionListener actionListener) { + for (UIRadioButton radioButton : radioButtons) { + radioButton.addActionListener(actionListener); + } + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/menupane/FontRadioGroup.java b/designer-form/src/main/java/com/fr/design/fit/menupane/FontRadioGroup.java new file mode 100644 index 000000000..8d26f4074 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/menupane/FontRadioGroup.java @@ -0,0 +1,17 @@ +package com.fr.design.fit.menupane; + +/** + * 字体的两个选项组成的group + *

+ * Created by Administrator on 2016/5/5/0005. + */ +public class FontRadioGroup extends FitRadioGroup { + + public void selectFontFit(boolean isFontFit) { + selectIndexButton(isFontFit ? 0 : 1); + } + + public boolean isFontFit() { + return getSelectRadioIndex() == 0; + } +} diff --git a/designer-form/src/main/java/com/fr/design/fit/menupane/FormFitAttrPane.java b/designer-form/src/main/java/com/fr/design/fit/menupane/FormFitAttrPane.java new file mode 100644 index 000000000..be1411264 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/menupane/FormFitAttrPane.java @@ -0,0 +1,58 @@ +package com.fr.design.fit.menupane; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.fit.NewJForm; +import com.fr.report.fit.ReportFitAttr; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; + +/** + * Created by Administrator on 2015/7/6 0006. + */ +public class FormFitAttrPane extends BasicBeanPane { + + private BrowserFitAttrPane attrPane; + private NewJForm newJForm; + + public FormFitAttrPane(NewJForm newJForm) { + this.newJForm = newJForm; + initComponents(); + } + + private void initComponents() { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 2, 10)); + attrPane = new BrowserFitAttrPane(this.newJForm.getJFormType(),this.newJForm.getTarget().getReportFitAttr()); + this.add(attrPane); + + } + + /** + * 展示界面 + * + * @param fitAttr 自适应属性 + */ + public void populateBean(ReportFitAttr fitAttr) { + attrPane.populateBean(fitAttr); + } + + /** + * 提交数据 + * + * @return 界面上的更新数据 + */ + public ReportFitAttr updateBean() { + return attrPane.updateBean(); + } + + /** + * 标题 + * + * @return 标题 + */ + protected String title4PopupWindow() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_PC_Adaptive_Attr"); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/fit/toolbar/SwitchAction.java b/designer-form/src/main/java/com/fr/design/fit/toolbar/SwitchAction.java new file mode 100644 index 000000000..e14d39a68 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/toolbar/SwitchAction.java @@ -0,0 +1,287 @@ +package com.fr.design.fit.toolbar; + +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.TemplateTreePane; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.fit.NewJForm; +import com.fr.design.fit.common.AdaptiveSwitchUtil; +import com.fr.design.fit.common.TemplateTool; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.BaseJForm; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; +import com.fr.file.FileFILE; +import com.fr.file.FileNodeFILE; +import com.fr.file.MemFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.nio.file.Paths; + +import static javax.swing.JOptionPane.OK_CANCEL_OPTION; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.YES_NO_OPTION; + +/** + * Created by kerry on 2020-06-02 + */ +public class SwitchAction extends UpdateAction { + + private UIButton switchBtn; + private static final Icon SWITCH_ICON = IOUtils.readIcon("/com/fr/design/form/images/icon_switch.png"); + private static final String LOADING_ICON_PATH = "/com/fr/design/form/images/loading.png"; + private static final MenuKeySet SWITCH_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return Toolkit.i18nText("Fine-Designer_Fit_Switch_To_Old_UI"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + + public SwitchAction() { + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(SWITCH_ATTR); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(SWITCH_ICON); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + switchBtn = (UIButton) this.createToolBarComponent(); + switchBtn.set4ToolbarButton(); + switchBtn.setIcon(SWITCH_ICON); + Font oldFont = switchBtn.getFont(); + switchBtn.setFont(new Font(oldFont.getName(),oldFont.getStyle(),12)); + switchBtn.setForeground(new Color(0x33, 0x33, 0x34)); + freshSwitchButton(); + } + + @Override + public void actionPerformed(ActionEvent e) { + //如果此时模板还在切换中,则直接返回 + if (AdaptiveSwitchUtil.isSwitchJFromIng() || !saveCurrentEditingTemplate()) + return; + backToFormTab(); + if (confirmSwitchDialog() && backUpOldModeJTemplate()) { + AdaptiveSwitchUtil.setSwitchJFromIng(1); + showLoadingJPanel(); + if (DesignerUIModeConfig.getInstance().newUIMode()) { + AdaptiveSwitchUtil.switch2OldUI(); + } else { + AdaptiveSwitchUtil.switch2NewUI(); + } + } + } + + /** + * @Description: 对未存储在磁盘的模板进行界面切换 + * @return: + * @Author: Henry.Wang + * @date: 2020/10/22 17:26 + */ + public boolean saveCurrentEditingTemplate() { + JTemplate jTemplate = TemplateTool.getCurrentEditingTemplate(); + if (!(jTemplate.getEditingFILE() instanceof FileNodeFILE) || !jTemplate.getEditingFILE().exists()) { + int returnVal = FineJOptionPane.showConfirmDialog( + DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design_Basic_Web_Preview_Message"), + Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + OK_CANCEL_OPTION, + WARNING_MESSAGE); + if (returnVal == JOptionPane.YES_OPTION) { + jTemplate.stopEditing(); + if ((jTemplate.getEditingFILE() instanceof MemFILE) || !jTemplate.getEditingFILE().exists()) { + return jTemplate.saveTemplate(); + } else if (jTemplate.getEditingFILE() instanceof FileFILE) { + return jTemplate.saveAsTemplate2Env(); + } + } + return false; + } + return true; + } + + /** + * @Description: 显示加载中界面 + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/9/30 15:18 + */ + public void showLoadingJPanel() { + JComponent area = TemplateTool.getCurrentEditingNewJForm().getFormDesign().getArea(); + JComponent formDesigner = TemplateTool.getCurrentEditingNewJForm().getFormDesign(); + area.remove(formDesigner); + + JPanel loadingJPanel = new JPanel(new BorderLayout()); + loadingJPanel.setBackground(Color.WHITE); + loadingJPanel.setBounds(formDesigner.getBounds()); + JLabel jLabel = new JLabel(new ImageIcon(this.getClass().getResource(LOADING_ICON_PATH)), JLabel.CENTER); + loadingJPanel.add(jLabel, BorderLayout.CENTER); + + area.setLayout(null); + area.add(loadingJPanel); + DesignerContext.getDesignerFrame().setVisible(true); + } + + + /** + * @Description: 如果是在报表块编辑状态进行切换时,会先回到表单页 + * @param + * @return: + * @Author: Henry.Wang + * @date: 2020/9/30 15:20 + */ + private void backToFormTab() { + NewJForm newJForm = TemplateTool.getCurrentEditingNewJForm(); + if (newJForm != null && newJForm.getEditingReportIndex() != BaseJForm.FORM_TAB) { + newJForm.tabChanged(BaseJForm.FORM_TAB); + } + } + + /** + * @param + * @Description: 备份老设计模式下的模板文件 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/23 16:24 + */ + private boolean backUpOldModeJTemplate() { + JTemplate jTemplate = TemplateTool.getCurrentEditingTemplate(); + if (jTemplate != null && !DesignerUIModeConfig.getInstance().newUIMode()) { + FILE editingFILE = jTemplate.getEditingFILE(); + if (editingFILE != null && editingFILE.exists()) { + try { + //待备份的文件名称 + String fileName = editingFILE.getName().substring(0, editingFILE.getName().length() - jTemplate.suffix().length()) + "_bak"; + //生成要备份的文件对象 + FILE backUpFile = null; + FileNodeFILE directory = getFileParentDirectory(jTemplate.getEditingFILE()); + if (directory != null) + backUpFile = new FileNodeFILE(directory, fileName + jTemplate.suffix(), false); + //要备份的文件存在 + if (backUpFile != null && backUpFile.exists()) { + if (!confirmCoverFileDialog()) { + FILEChooserPane fileChooser = FILEChooserPane.getInstance(true, true); + fileChooser.setFileNameTextField(fileName, jTemplate.suffix()); + fileChooser.setCurrentDirectory(directory); + int chooseResult = fileChooser.showSaveDialog(DesignerContext.getDesignerFrame(), jTemplate.suffix()); + if ((chooseResult == FILEChooserPane.CANCEL_OPTION) || + (chooseResult == FILEChooserPane.JOPTIONPANE_CANCEL_OPTION)) { + return false; + } + backUpFile = fileChooser.getSelectedFILE(); + } + } + jTemplate.getTarget().export(backUpFile.asOutputStream()); + TemplateTreePane.getInstance().refresh(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + return false; + } + return true; + } + } + return true; + } + + /** + * @param file + * @Description: 获得当前文件的父目录 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/23 16:50 + */ + public static FileNodeFILE getFileParentDirectory(FILE file) { + FileNodeFILE fileParent = null; + if (file instanceof FileNodeFILE) { + FileNodeFILE fileNodeFILE = (FileNodeFILE) file; + FileNode fileNode = new FileNode(Paths.get(fileNodeFILE.getPath()).getParent().toString(), true); + fileParent = new FileNodeFILE(fileNode, fileNodeFILE.getEnvPath()); + } + return fileParent; + } + + /** + * @param + * @Description: 确认是否弹出框 + * @return: 点击确定返回true + * @Author: Henry.Wang + * @date: 2020/9/18 11:20 + */ + private boolean confirmSwitchDialog() { + Object message = DesignerUIModeConfig.getInstance().newUIMode() ? Toolkit.i18nText("Fine-Designer_Fit_Confirm_New_Old_Switch") : Toolkit.i18nText("Fine-Designer_Fit_Confirm_Old_New_Switch"); + int returnVal = FineJOptionPane.showConfirmDialog( + DesignerContext.getDesignerFrame(), + message, + Toolkit.i18nText("Fine-Design_Basic_Confirm"), + YES_NO_OPTION); + return returnVal == JOptionPane.YES_OPTION; + } + + /** + * @param + * @Description: 是否覆盖文件 + * @return: + * @Author: Henry.Wang + * @date: 2020/9/23 17:00 + */ + private boolean confirmCoverFileDialog() { + int returnVal = FineJOptionPane.showConfirmDialog( + DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Designer_Fit_Cover_File_Switch"), + Toolkit.i18nText("Fine-Design_Basic_Confirm"), + YES_NO_OPTION); + return returnVal == JOptionPane.YES_OPTION; + } + + /** + * @param + * @Description:更新按钮的状态 + * @return: + * @Author: Henry.Wang + * @date: 2020/8/31 16:39 + */ + public UIButton freshSwitchButton() { + if (DesignerUIModeConfig.getInstance().newUIMode()) { + switchBtn.setToolTipText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_Old_UI")); + switchBtn.setText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_Old_Version")); + } else { + switchBtn.setToolTipText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_New_UI")); + switchBtn.setText(Toolkit.i18nText("Fine-Designer_Fit_Switch_To_New_Version")); + } + return switchBtn; + } + + public UIButton getToolBarButton() { + return freshSwitchButton(); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/CoverReportPane.java b/designer-form/src/main/java/com/fr/design/mainframe/CoverReportPane.java index d976691c6..e475133a9 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/CoverReportPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/CoverReportPane.java @@ -1,10 +1,10 @@ package com.fr.design.mainframe; import com.fr.design.constants.UIConstants; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.icon.IconPathConstants; import com.fr.share.ShareConstants; -import com.fr.general.FRScreen; import com.fr.general.IOUtils; import com.fr.stable.StringUtils; @@ -63,7 +63,7 @@ public class CoverReportPane extends CoverPane implements HelpDialogHandler{ // controlMode = IOUtils.readIcon(IconPathConstants.TD_EL_SHARE_CLOSE_ICON_PATH); controlButton.setVisible(false); helpDialog = new WidgetHelpDialog(DesignerContext.getDesignerFrame(), helpMsg); - double screenValue = FRScreen.getDesignScreenByDimension(Toolkit.getDefaultToolkit().getScreenSize()).getValue(); + double screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(Toolkit.getDefaultToolkit().getScreenSize()).getValue(); int offsetX = 0; if (screenValue < FormArea.DEFAULT_SLIDER) { offsetX = (int) ((1 - screenValue / FormArea.DEFAULT_SLIDER) diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormArea.java b/designer-form/src/main/java/com/fr/design/mainframe/FormArea.java index f127f8ea0..bc4e941fc 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormArea.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormArea.java @@ -1,14 +1,13 @@ package com.fr.design.mainframe; -import com.fr.base.ScreenResolution; import com.fr.common.inputevent.InputEventBaseOnOS; -import com.fr.design.designer.beans.events.DesignerEditListener; import com.fr.design.designer.beans.events.DesignerEvent; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWBorderLayout; import com.fr.design.designer.creator.XWFitLayout; -import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.form.fit.NewFormMarkAttr; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UINumberField; import com.fr.design.layout.TableLayout; @@ -79,7 +78,6 @@ public class FormArea extends JComponent implements ScrollRulerComponent { private boolean isValid = true; // 初始时滑块值为100,托动后的值设为START_VALUE; private double START_VALUE = DEFAULT_SLIDER; - private int resolution = ScreenResolution.getScreenResolution(); private double screenValue; @@ -253,7 +251,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent { private void initCalculateSize() { Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension scrnsize = toolkit.getScreenSize(); - this.screenValue = FRScreen.getDesignScreenByDimension(scrnsize).getValue(); + this.screenValue = DesignerUIModeConfig.getInstance().getDesignScreenByDimension(scrnsize).getValue(); XLayoutContainer root = FormArea.this.designer.getRootComponent(); // 7.1.1不放缩放滑块,但表单大小仍按屏幕分辨率调整 // slidePane.populateBean(screenValue); @@ -285,10 +283,19 @@ public class FormArea extends JComponent implements ScrollRulerComponent { // 失去焦点时,可以认为输入结束 int width = (int) ((UINumberField) e.getSource()).getValue(); changeWidthPaneValue(width); + changeFormMarkAttrWidth(width); } }); } + private void changeFormMarkAttrWidth(int width) { + NewFormMarkAttr newFormMarkAttr = designer.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG); + if (newFormMarkAttr != null) { + newFormMarkAttr.setBodyWidth(width); + } + } + + private void changeWidthPaneValue(int width) { XWFitLayout layout = (XWFitLayout) designer.getRootComponent(); if (width != layout.toData().getContainerWidth()) { @@ -303,6 +310,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent { public void actionPerformed(ActionEvent evt) { int height = (int) ((UINumberField) evt.getSource()).getValue(); changeHeightPaneValue(height); + changeFormMarkAttrHeight(height); } }); heightPane.addFocusListener( @@ -315,6 +323,14 @@ public class FormArea extends JComponent implements ScrollRulerComponent { }); } + private void changeFormMarkAttrHeight(int height){ + NewFormMarkAttr newFormMarkAttr = designer.getTarget().getAttrMark(NewFormMarkAttr.XML_TAG); + if (newFormMarkAttr != null) { + newFormMarkAttr.setBodyHeight(height); + } + } + + private void changeHeightPaneValue(int height) { XWFitLayout layout = (XWFitLayout) designer.getRootComponent(); if (height != layout.toData().getContainerHeight()) { @@ -383,7 +399,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent { /** * 修改大小后,再根据屏幕分辨率调整下 */ - private void doReCalculateRoot(int width, int height, XWFitLayout layout) { + public void doReCalculateRoot(int width, int height, XWFitLayout layout) { // double value = slidePane.updateBean(); //重置滑块的值为默认值100 START_VALUE = DEFAULT_SLIDER; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java index 1d4fad8e3..f167a2c72 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java @@ -43,6 +43,7 @@ import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.event.DesignerOpenedListener; import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.form.util.XCreatorConstants; import com.fr.design.fun.RightSelectionHandlerProvider; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; @@ -144,7 +145,7 @@ public class FormDesigner extends TargetComponent

implements TreeSelection // 存储被选择组件和剪切板的model private transient SelectionModel selectionModel; - private int resolution = ScreenResolution.getScreenResolution(); + private int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); // 编辑状态的事件表 private CreatorEventListenerTable edit; protected List designerActions; diff --git a/designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java b/designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java new file mode 100644 index 000000000..7db99129c --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java @@ -0,0 +1,53 @@ +package com.fr.design.preview; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.fun.impl.AbstractPreviewProvider; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.JTemplate; +import com.fr.general.web.ParameterConstants; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by kerry on 2020-04-23 + */ +public class DeveloperPreview extends AbstractPreviewProvider { + private static final int PREVIEW_TYPE = 7; + + @Override + public String nameForPopupItem() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_Developer_Preview"); + } + + @Override + public String iconPathForPopupItem() { + return "com/fr/design/form/images/developer_preview.png"; + } + + @Override + public String iconPathForLarge() { + return "com/fr/design/form/images/developer_preview24.png"; + } + + @Override + public int previewTypeCode() { + return PREVIEW_TYPE; + } + + + @Override + public Map parametersForPreview() { + Map map = new HashMap(); + map.put(ParameterConstants.OP, "developer_preview"); + return map; + } + + @Override + public boolean accept(JTemplate jTemplate) { + if (jTemplate == null) { + jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + } + return jTemplate instanceof JForm; + } +} diff --git a/designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java b/designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java new file mode 100644 index 000000000..01bd0e126 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java @@ -0,0 +1,54 @@ +package com.fr.design.preview; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.fun.impl.AbstractPreviewProvider; +import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.JTemplate; +import com.fr.general.web.ParameterConstants; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by kerry on 2020-04-23 + */ +public class FormAdaptivePreview extends AbstractPreviewProvider { + private static final int PREVIEW_TYPE = 6; + public static final String PREVIEW_OP = "form_adaptive"; + + @Override + public String nameForPopupItem() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Fit_New_Form_Preview"); + } + + @Override + public String iconPathForPopupItem() { + return "com/fr/design/images/buttonicon/runs.png"; + } + + @Override + public String iconPathForLarge() { + return "com/fr/design/images/buttonicon/run24.png"; + } + + @Override + public int previewTypeCode() { + return PREVIEW_TYPE; + } + + + @Override + public Map parametersForPreview() { + Map map = new HashMap(); + map.put(ParameterConstants.OP, PREVIEW_OP); + return map; + } + + @Override + public boolean accept(JTemplate jTemplate) { + if (jTemplate == null) { + jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + } + return jTemplate instanceof JForm; + } +} diff --git a/designer-form/src/main/resources/com/fr/design/form/images/developer_preview.png b/designer-form/src/main/resources/com/fr/design/form/images/developer_preview.png new file mode 100755 index 0000000000000000000000000000000000000000..7d7e064d1cdf48fa3304c490e92817f0c9737633 GIT binary patch literal 542 zcmV+(0^$9MP)g-Xe$z{md1k(f(D@;MD(Z<1<{HpJp`$sf(Jo7C>X&U zM5V~GLLrD64Y7ox5=0t%NYX;%W0e$(sBM$om8`B3NRtZwmtmNhZyx`Q!0)&H=4>3( z^xFDdQqv~Fsi5niZ5RFkLNjKq;F3L;OC!t9Td82{p_2a306WRkzyd4w{{vi&0{uRb zqiT_Fvv6sr#K0S!Q{5u{Pju4xU!7L0z}+Npeuu=>M3HA%lNAkcWw*?}I|aH|3iNeJ z1RoVieKIQp?(Ua~W^_U?3@gjAEutl_4eOQ+bc*z}Iyi8zP`iSmagz(1#t03*;=@+~ z_XZDVde>C1pp>OFgL6KSvo|92wmVtf;YAQkvdI|Ah{0HcZ|)h`U*wq1v$sA$&#paX zs}YT;+@I>ga5h$M!S=5EILv8(GfP`ml>xN(6I@g?%rtwe1LVmOj&C+-TfeakFrFUe za&(G9lczcWL#IOvb0lyWNs=sxVHgaAuk*alPjTV$8UVoY<1?=OAY0wb5G9dh@-^E! z*YV(CjCXB)JU-bnzg2cjPl9P!gIk=r%?bZnVlUs4j7Ju!s`};cEzIYfO_L=#1y8;9 gJuwt-R}>}t6Ak^{5p4;(QUCw|07*qoM6N<$f=1i*UH||9 literal 0 HcmV?d00001 diff --git a/designer-form/src/main/resources/com/fr/design/form/images/developer_preview24.png b/designer-form/src/main/resources/com/fr/design/form/images/developer_preview24.png new file mode 100755 index 0000000000000000000000000000000000000000..fc3d3d34788de6d53a98a5461a896f335b1394e5 GIT binary patch literal 862 zcmV-k1EKthP)2W958P*4ISgx3N1AiM@J*P+IXQckV^10YZa+)X4gK?9c?DCg!J^hGHoSa#}rQ8Ec1 zF>qZ+VaVp{fyWLw#P21MSRG8Dy`Mo&{S3esg$VbR5|}J3)U|dzI!q#3PT(obl3z3c%US)SwWysPeJ#camhHYyje7WyAUXr0nb$u*eD>a z(vGoN1_%}cckxV*A&?$JLideEVH54#y`V`ry(*WTl`08V1hB|`(u84iH-h}cu#C~z z5gmez)Od7S2w{%lYzW6iWT$~k4HRz2S@Bu_3LCa3AS^t>>44a3!iV=-=-5OIh(cWQ zV$nIU;NOmAu(78CIp@zn;^Q-K7(>%|TJ{Vrfhs^Ob@mGeAni6FFJ+a>&gW7Ln)^{u z)q-E)`-KOH=&8fC?2~-Y0X!_N#+TqU;Q_WX&Ge9T6U2O>Z5pX7M}l zxU2@B0*?s~Anj^Ie%dC;L&FwyVZ<_oTV;A!S1N@E07D_hT!{;r86d>sc@QkiLQ`9c zcLR~IDdM~U0Du_n!?rOUj;1CfXt~@e;@G+2Z9NVhNPt$Sg~q%d){vc({em4sry4yD z|86}Z{YMb&M_|~-pu-{qP52@u^e2qQW+W+*3zlXK&6NCYb>!363je`2n=L9e oQ7}eEf4d3w4yhG+yQrzi*+G+mLDp8Y31 zA%W}ga(3T``$IX7D)e&LbsgHA?!VS;8{U7b2QXQtKv`=fj4so$Eg#oBC@(~faX dY-YY&#qh($G@r}j^ADh*44$rjF6*2UngDvpEFb^? literal 0 HcmV?d00001 diff --git a/designer-form/src/main/resources/com/fr/design/form/images/icon_switch.png b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch.png new file mode 100644 index 0000000000000000000000000000000000000000..3730b3b79d0c44ede776f8bb1e3575302ea741b9 GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6oZW8(2`y1f!v9fk}`jvc=IysLe>zwH?YHHqekS(BTuc0ROs z);J^JmXyOL%~xV|`2T-i>uvd|JUl!izyCe{ZpY@QR+hG4sM4=_Q@{W zS=IV_m-TTcG&Y@OTXghclkv;3_JN40_212e(-kR1bUgl)78&qol`;+05m>t A`v3p{ literal 0 HcmV?d00001 diff --git a/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_disable.png b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_disable.png new file mode 100755 index 0000000000000000000000000000000000000000..daee74b513d87662cdf4eeb8bf59268b862eb51c GIT binary patch literal 296 zcmV+@0oVSCP);zykPa?0|z+aG)mYum__73XlRkaIgb2 zI>_5>CP5b>m-+0x&kW@CUmV9rLFtb1+u`J7zUF%##nCF`)iae0a^w6)` z_t)p1WGk~Y#ySxN;xbLsRogxeM9+Ii;9`Bqnez&Ho_8F~%SHqtYL19iJ>B}RzlzThydtl9N?-l upj9-;uK(iz``gT;^C={PAt+5D5bO(KVpuOb$Wvbc00004%P)F8+hA7VG3tTiQxR z#6b~PMXMZkzV*KIan3zl!apAc)o1e7(TfwxRko?^Y6Aldvnv2AQ9ifZi&U>(3T0Lh25mLMrdt~jh(MFP@3M8jWNf+$BBv$rq6_W<03*p_&Z z&q@bm{{|aGK$A%rL@> z*g_-{;Y&pP)pc+UATG(6J=q9fdWi?~RVkIaTj88@GV+}r0r{zvm5-B2JyENbYhDmd z(s5-)$YN00000NkvXX Hu0mjfc literal 0 HcmV?d00001 diff --git a/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_old_ui.png b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_old_ui.png new file mode 100755 index 0000000000000000000000000000000000000000..08217d41132434f3e03617896800278903046bad GIT binary patch literal 417 zcmV;S0bc%zP)LAb5AH}F0x5F+jGC)J>Pc@;h#mL>NPE)mCFwm0B%P+GC2EfSu{=a)oY4gh{=MpMQ|ob(~M0agea9}FM#uIvR<`u!V%YL zJpr)DFpLzl7^~OCO|^Pg_Y!ydnLLNyMC%=(Pl`n1bHO0BW%j-{uC#MkS^tg~Bvojq z!SWKob9Y_o)pW66(;vtrDr literal 0 HcmV?d00001 diff --git a/designer-form/src/main/resources/com/fr/design/form/images/loading.png b/designer-form/src/main/resources/com/fr/design/form/images/loading.png new file mode 100644 index 0000000000000000000000000000000000000000..d479fb376be6526651ffa41579bd4551f5d44916 GIT binary patch literal 7641 zcmd6MRZtvC6eS@L+}(o)C%C%@hu}^iz~D}B8(f2j4DRkO!3jFRFgSw*A3V5Zd4IdV zTeVVkTRytFySnc^efr!OO?5>qbaHeA1OzN)B{}Wa_WHG~p}u>q%klSfUK=D^X*FpC zgoY%HCre}m1gd0ZIqA>7Z%#lM0fY-Zqchpr>r)sqN{GMdxQPBdRN5`9Zr4B~nI)=- zj2)bw4eHj=kp@QfdRB;6SE}05&ml*nH}f|hlEcScy3+Uo&AJXXHO)puJz?nZNU^bS z>!!Nwj=m<#9YmES#+<+xb%~s8;j=68tGuf$-hcE+SZK)z{~y>dCA6^=gjgnKxc=`Bo3^WzL}ALM1|bu+2}O4?@~-?5dLp{HimmutsJZuYz>3ZI4`x_ zRi5lJ&(f(35m0kBw49*ad{=mi=VXy8(hWWm8ADT!v|nrQvs$o;5((K8Up08#F1Mu{ zM5`~Ec18YpPe@QdOvy6bSuRzzWK68@&&P7cU23n#K>bQrTCb^SulI|*?*sm1iR3x7 zNlgf}{q{(3TJ6jD@swRJ2PVGhbI@K}TNAQZqkUhXNg~5RVnH@z-1Df@YLkmq04-dhTex{5I<|E_uj&`!t zF~3tC9GX%_;;^eDJYuN)*R7j-jK!iCuw|`p=hs4cHh?^JfQK64bfMM7nCs6bgv%#C zSju>cqR7?q6qD^^6Xs>uSL@Me`EKL+p^qp%o`bd(si9=ZIBABs@1+Q4dsJ&Ug~8@i z%rGaG7!jv|U$bVh*}6QB1wsTd*F)~vMrHptA7Y#0Aou2U8e9o7p?igSRUK|ulM#3& z77+YN2e^!?Lrm18$~C;Y?@4KZBK=1E9B!)eWL@hqo7(HUnQf6nxxL|;M*dyw7iG7y zRtU%4*nDUHY8MZ!^$5q|@m6Oz%D2+k%|g*3Zpm02+xWk15#_N#GE^kfZ!)-?uwrYd zb>OEBL%X(cSjTcbf)uv*s%; zX_IK$lvR~CF_FnUZ<8&EjJARsf;gZ5zSQ_tQ_K*2_@!vIU44*>20g>l zFea%2&VwV{t*eyR4gYTqa?Q4j1n}Egt+s~qKUgyh7G+i^&X{2eP!*vFsZSCf32Dw* zwzP;dzmsuGb1R|0;49VQ9l_NZ(ZbLoPucO1CdYpt+D#`_FkN+IZK;F+dnQ0cOO^`4 z%h%l34{YRPc<=6B==d_&+O&8quD<|-6t3)38@w;z{}G9#B!xHDk>R%iSY2qDcx<(a z6|GMlTyc8N-2~ox%dX?T0$vDRvWE;6x_@2-v@d~UV$Igs*^>qX6x4_IE?{jt?Uok} zPX9UrYyD@s_99f#0Sx}zRbY8Jbikj)pm~7gu2By3T^AUh zNlmMz>8e(muJp`zl{pV{GJ`YDw#{kadxU=SjZX}?jIWbEkEQcOPi9Uz0Yv4AtfuFV zg4r{9{w*3SIK(UB3t@)-BsjABW<>tMQEQ(gL5qU=HTnrdO(=Dm_Fh3Cl2)pK`W-e% z={?EoWqC9}vuyE6BN2dpq(Yu_p(YHk2R3ZM#lPCcbye+Js4H99HVB$aHIRfuT!7M%63U>3^w_2 z0Ln;>Jc{RjU^Gls>xo|ak6f<_rG65U<(wr8M44ViEyM{_p@U~)3Wz@3xz!(hwA9!9 zi_FuE{p7{viRgo2oOE1PncY&QaK~9~yqn$lE#`5@dSI^-Hbnic!$@RLv9!FwY&F&N)(TLPSmW;m*A@THf95Nsgq8q~AsTFUT84f>E7LJ+aVDt8S_P;1OTxt=9JR_fWOg^Q(>L73I|1Ij8RD`UZI{B+7uQ z_%jFZdv~AE8=6)Lah?kF%aQ4L>y3Xe719&H(QFLDM5b{;zQ7i{z%DM_)=YjusIwR$ z_53BL)Z)`j4#kJSrjFTXYquCNqM*9GwoVUt!N8v%;y{r_06WfQRp+{7r)RhC$zX`@ zQ^HHMMU_+ZxXJJJ#B@dlYswRhm2Ebh=Gf5u7WW(~8_#d3LwNbI_32V^q4V+I>n)^;8>qR@h2LCsCCknzHa z7piCIU}n-p6-B_V^2EvxhheM+Jsf;rF;un|J??2NnSNj$Kf{Ek$=2`d7YvWYs$`>Zb@j=>W(6WHBNMJj`K6I*UEsD*aphS!e`FGH^ws*vwI z0Q{{oI-m`W6i9o!!~Vws-769RBkhe6-ZrVIb>z(U4HL&Oy|@*5XAI{-{flWL8=8MN zt7E!O(;T%C@YU@^H|uw)6piLA;nCZWa~=<*Gz(aqJj+!ulzi5vlxapn_gKb(Ba*ms z?XR8U<`k%Zd#~iQi3NOd94kYWhvCF4XJOL71em~@#k)Fb@k1_+Um3ch5e?&H8P;b3 zhpTQs&ornTb<=@4^HA3!^i4K$>$8Ga`mYQCV~s~_3t9EVeZqbAx3-rRYZdGmK#_Dl zvPC=s&6;yA^JR)}XHTl(qI2tsB+C~q*lxF(tUyZxj%&4zZx>I5om9Y1@L32ub00Zx zU0{LYlew`{b$jC{p)Y#z-WIF5I9)P@qF=*%bjsS#$*UWimsqH4%uhN*Fk+K+4f8c^ zb-f79zC!S4a%j#7pO=((Pz*%KsU+F(ySQsNT0bzaJPd4$SMwcX1zc|U?a4(Mc zCXEW%d|Jqj9H93(z}G3qnTq5rQkC-RprAg&oj+fI)?AIq_r@fuHIDZ66%OQPL5=Qn zOe~|*&1*T)qE2+pyJsG2mg<24>IIyCR%R@gbuj|hxmJg`7qDktoxiR9j2GX0oAkC$ zH@}G0^8$>;KR~-HPEzC4!|yDI{8hO?y?S6LC@052^FbszL|el5m;kg5si;-L2+a5Y z+xaz~wp33@Ubliaad-}VS$NmxzzD&C-L@QU*e}fs6@`Flz0(C3Ap@kk3kG2}#>fv-ff1S3nEU257S7*%0O-$T( zguf_W_v*wF)CO3zxxBB=n`^WlcwC;e=DQTAbXBAu%ue)hPQ5i^uIa+Q&q}zCtvHkY z+8I)m)jP-3xmS5K##XJR%7lM?wD13xVgvs8Qd*LFN`2ByDv3tO5c=Q+O64-$KZ%m4 zZ_bho+-&3OYfE1}CH%8KB2yM6H74os35chvVMRAbfogaY?^%+mcIaBjo&%syy0Thb zDPD0G|Eha?K->z5ua&?i6YQ+8wuKWO!K*X7Cy07OIo*V9R(fHuGDC%&fAyxWso8`_ z-2{1XcHG|3NR#>E@K@GMm6rVutvE$$rBl|Pogj6b4)NfH*vG%S?f6Ha`qgUhcCeoe zJq(Mh|57@&;*HJo#MZMU0p@p-jV1c=IKbqz4Erd2Nkxr%Ufc|aIymjLS@NDzgo8}) zC4Yk`D~sOe~t#9U#wi5cqiH8vYqobx1#Gq80jQDq=Q&w3fZ&o$+%3dv29&M2JkF%bHqCkWH3Et%|Qn;J}ZjGd&-~^ zg&Cs;xz=o%AeGplY!XKVYNq;uM_LG5Y4(HUwio$U>r^lnLm4?*ilYw_GHO)()P*tA$SKyAFAO>2 z!^HCI1)VfG$bC4Xo1%CbVo@TmVTN$m|LdNYB;c4Ls~34AIL95ri-jnP=CmTWCTG9; zQJhIdjEdzAO9O4*daRwdbbFg@x8$#D<4D5EB=wRq*M-6x1Lif7YHHI`Uc65^zRr9rbc6R7*Zl|8Ukc<&s(?-g1f3~|# zIGk2b2~SM^YsUh=*!D8;#N8EpwEuXFz2mD@D+TXn)-x1R-G(|C9z!^A9s~Nq{{&&b z+jJCK3;O{^jAo0*m3EY&;p4ulaZr#-ZH0a2h5eW~yTl0otu-KM`YD*aDpEP+|D;4n z87mc-x)1Ht&27TorFIAoO7&S;W17LSI>8q=e+hGX4^R5?JoEZrF6sR(de)8NKQg*P za};nIYkGWq3eyQ<_F1tdc|+gTnEKoi8seLeJcRR13)b$Kks8J3OOi@K<%?i0szv@x zez-l7!Fc-N=AK++&9(1jY43{DO({EhPISsrXiC#{S`!KF=Vs`IuANMU-|m@N$@HJ2 zhxA;%Kk9(aCBTn81H1Rx9Jdb=2~lxX9kYRt^;)0qfw8f%oAp5lS^P-M5M{k#p)&5P zEsCl~+JR5k8beYRvIRai~vEGmXjaw*m7ii4}IUGf)(30#p2bU5uI+ojc!>) zsQRm!&ez%{kKvI=y^kw&@F?<^ey%fCnTTUD67T8(v+|WYs8q-qoriq%Ml!OE7=$)O zw|RU-bVRj?8x`R42-Y_}E?o*mQ6sU^iH%Ove!5MQp=X|kIUR0U{h4&OuYRVzyqSOC zubIywS#;Fj;_QX#xUWpEJR{weaF|s!n=e%^=m(|U+lqc>L&FRB^NDpe3E_8Puxxso z{I~I=YOzLFnLHEUJ9cNsJGm_oJG51)&#SD|A;{6bz_9e5lrJ_A?YzJ>D45{8c2psE ziLB}p74*CFRu6R;hOR{+eosW(Y-7gOgK*i$AXJ*w^Y_Av_n_70W7cRm%Tc%UZmm2x z*k52x_VEE*H-oV^(E(4OKt?sXC_kzi{X#9SoEF2_=RN6KgPKC$^SFwOZ)_0`o(+ml zN7d?MCdj2cU+c?Ea_5etwI0m)j2OS92=W_b14iTlCWHIEKXoa zRYPMZwg|A7cWHN}+af>%VoJ3y@NJgAwa~Sk(G=6bdUfVC>8~D`v!O z=u3wSbHGo6zZV)&wbK=vxPE+{8@4A{w-r>ZbP5D>p?4bsKv%H_J4f5V`P$(~KFHg> zoj^0+F}GJuhQ3^C73^oTr2SADg~>G1+b|W?(8Tk+)U6)vbKWIm%Bu695KM$=Qm6dw z)=XnG?V%K^j4Luh2vt5%*Z75bD?Coaux3wMt1l?<8GG2p5Xu)1gz26x3B03#$Mh=w zGcg?E)hwD_B76XgZdXCa&9=o=}bY5G3R zUYszXUde}B7PGO}w7E(!K(h2C)fQW>$Ej*MS6GV8K{Vrhf>5#G*+8mP#FtI1EKFnl zHmk+pFZA{Mf*cirdO$;LwGFNv{^ff%pFGOe$&gmFI9I+#UWRr@#w>}@vbn9_6z@{5sZ+F zEi0k+@;2^}f>_@r1#3LYw8}o}jP*;@w0v^=1@1u^u3f49vaO|+>hSr7J4+_C=G<3p zwOeIzSL1WFRyegHOKaM5?x1S`VGG7PSr5v{Zh626I7@^OUAzKV{k@!qx+&_vop{Z5 z7w^%gV~#*@kN(65O9h~vY{|;jfr~w5>&-<>*mE*FU4Sf+soqo<@?68~jE7$se3 z!ee^3b4@q&KUR6aGdd%&+L?=O>AW0|0X5WBf@N}Sb3b31!R3~_7dDzcbX9hK8N3wx zFT|RPsJHiI&}f);oky5NN#w+(aBVF)#uY99zRafA4KF>3>_!F_Ps>fj2Np-PTR1(c z@>0I&-*F5oSt5==uj(bIhkZZv+U5&Fj?WyrP@FS&NDjSsEIoX*VxCjWh}%VPrXW>z zk^B@CfGD$3>0e1Wz!MeL#LDO2Xjd0Q_Lo5@b!WLFgK!QpT+UGgGY9ADK+h%A!z`Xx zuV&D+vfm{lozHaw*03Vwg!+uAu?jKOs%uef%h#n-Az}NQ|IW=QIbDUc@Zi!pQZRm^ zmGddMzGl(Lu$c*&P_B<-Cl3|xHt_#X?P>MT+&3G#pkx~Lzc6y(H`Dv_)|-1b8>oAh z*9P^cj3B+T`C1W6(Qh&qt^&%*(2XxIv)E_D>3$;Pw$fHNmgIv{qe>)BExRa)z@&0r zehn>)u?uymUC-~3Su6R~dot$cG!D}JFeJU@8l?13^~HMxY*EHpON7iD-N8Mfbu_qvczDZ*51!e;sra{N6&V$q+PZ@}*3K!sYuyuP3*{io5}4n4#STHgWN_ zWvLqS{Rg>AWmL-{`Ussx4m`tIWWxu4;JmNqXMN-@@h-tZ|BgM+8f{ZI)rgbpC|S0T zc;0#F--szCm{X^Tiw$&^h zwd#V-x^j=sITflT= 0 && e.getY() < height) { + Point convertPoint = new Point(width, 0); + SwingUtilities.convertPointToScreen(convertPoint, grid); + showToolTip(grid, e, actualWidth + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Px"), convertPoint); + return; + } else { + hideToolTip(); + } + if (Math.abs(e.getY() - height) < 5 && e.getX() >= 0 && e.getX() < width) { + Point convertPoint = new Point(0, height); + SwingUtilities.convertPointToScreen(convertPoint, grid); + showToolTip(grid, e, actualHeight + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Px"), convertPoint); + return; + } else { + hideToolTip(); + } + } + + private void showToolTip(Grid grid, MouseEvent evt, String text, Point tipLocation) { + if (tipWindow == null) { + tipWindow = new JWindow(); + + + tip = grid.createToolTip(); + tip.setBorder(BorderFactory.createEmptyBorder()); + tipWindow.getContentPane().add(tip, BorderLayout.CENTER); + } + tip.setTipText(text); + tip.setForeground(Color.decode("#88ACC6")); + tipWindow.setLocation(tipLocation.x, tipLocation.y); + tipWindow.pack(); + tipWindow.setVisible(true); + } + + private void hideToolTip() { + if (tipWindow != null) { + tipWindow.setVisible(false); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + hideToolTip(); + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + hideToolTip(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/fit/grid/ElementCasePaneUtil.java b/designer-realize/src/main/java/com/fr/design/fit/grid/ElementCasePaneUtil.java new file mode 100644 index 000000000..1078250c6 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/fit/grid/ElementCasePaneUtil.java @@ -0,0 +1,186 @@ +package com.fr.design.fit.grid; + +import com.fr.base.vcs.DesignerMode; +import com.fr.design.actions.cell.CleanAuthorityAction; +import com.fr.design.actions.columnrow.CancelColumnAction; +import com.fr.design.actions.columnrow.CancelRowAction; +import com.fr.design.actions.columnrow.ColumnHideAction; +import com.fr.design.actions.columnrow.ColumnWidthAction; +import com.fr.design.actions.columnrow.DeleteColumnAction; +import com.fr.design.actions.columnrow.DeleteRowAction; +import com.fr.design.actions.columnrow.FootColumnAction; +import com.fr.design.actions.columnrow.FootRowAction; +import com.fr.design.actions.columnrow.HeadColumnAction; +import com.fr.design.actions.columnrow.HeadRowAction; +import com.fr.design.actions.columnrow.InsertColumnAction; +import com.fr.design.actions.columnrow.InsertRowAction; +import com.fr.design.actions.columnrow.ResetColumnHideAction; +import com.fr.design.actions.columnrow.ResetRowHideAction; +import com.fr.design.actions.columnrow.RowHeightAction; +import com.fr.design.actions.columnrow.RowHideAction; +import com.fr.design.gui.imenu.UIPopupMenu; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.grid.GridUtils; +import com.fr.grid.selection.CellSelection; +import com.fr.page.ReportPageAttrProvider; +import com.fr.report.elementcase.ElementCase; +import com.fr.stable.ColumnRow; + +import javax.swing.JPopupMenu; +import java.awt.event.MouseEvent; + +/** + * Created by kerry on 2020-04-28 + */ +public class ElementCasePaneUtil { + public static UIPopupMenu createColumnPopupMenu(ElementCasePane reportPane, MouseEvent evt, int selectedColumn) { + UIPopupMenu popupMenu = new UIPopupMenu(); + + if (DesignerMode.isAuthorityEditing()) { + popupMenu.add(new CleanAuthorityAction(reportPane).createMenuItem()); + return popupMenu; + } + + InsertColumnAction insertColumnAction = new InsertColumnAction(reportPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_Insert_Column")); + + DeleteColumnAction deleteColumnAction = new DeleteColumnAction(reportPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_Delete_Column")); + + ColumnWidthAction columnWidthAction = new ColumnWidthAction(reportPane, selectedColumn); + + ColumnHideAction columnHideAction = new ColumnHideAction(reportPane, selectedColumn); + + ResetColumnHideAction resetRowHideAction = new ResetColumnHideAction(reportPane, selectedColumn); + popupMenu.add(insertColumnAction.createMenuItem()); + popupMenu.add(deleteColumnAction.createMenuItem()); + popupMenu.addSeparator(); + popupMenu.add(columnWidthAction.createMenuItem()); + + CellSelection cs = (CellSelection) reportPane.getSelection(); + addColumnMenu(reportPane, popupMenu, evt, cs.getColumn(), cs.getColumn() + cs.getColumnSpan() - 1); + popupMenu.add(columnHideAction.createMenuItem()); + popupMenu.add(resetRowHideAction.createMenuItem()); + + return popupMenu; + } + + private static void addColumnMenu(ElementCasePane reportPane, UIPopupMenu popupMenu, MouseEvent evt, int selectedColumnsFrom, int selectedColumnsTo) { + HeadColumnAction headcolumnAction = new HeadColumnAction(reportPane); + FootColumnAction footcolumnAction = new FootColumnAction(reportPane); + + ColumnRow selectedCellPoint = GridUtils.getAdjustEventColumnRow_withresolution(reportPane, evt.getX(), evt.getY(), reportPane.getResolution()); + ElementCase elementCase = reportPane.getEditingElementCase(); + boolean cancel = false; + ReportPageAttrProvider reportPageAttr = elementCase.getReportPageAttr(); + + if (reportPageAttr != null) { + popupMenu.addSeparator(); + popupMenu.add(headcolumnAction.createMenuItem()); + popupMenu.add(footcolumnAction.createMenuItem()); + int from = reportPageAttr.getRepeatHeaderColumnFrom(); + int to = reportPageAttr.getRepeatHeaderColumnTo(); + int from2 = reportPageAttr.getRepeatFooterColumnFrom(); + int to2 = reportPageAttr.getRepeatFooterColumnTo(); + int column = selectedCellPoint.getColumn(); + + if (column >= selectedColumnsFrom && column <= selectedColumnsTo) { + cancel = isCancel(elementCase, selectedColumnsFrom, selectedColumnsTo, from, to, from2, to2); + } else { + + if (elementCase.getReportPageAttr() != null) { + + if (column == from || column == to || column == from2 || column == to2) { + cancel = true; + } + } + } + if (cancel) { + CancelColumnAction cancelAction = new CancelColumnAction(reportPane); + popupMenu.add(cancelAction.createMenuItem()); + } + } + } + + private static boolean isCancel(ElementCase report, int selectedColumnsFrom, int selectedColumnsTo, int from, int to, int from2, int to2) { + + boolean cancel = false; + + if (report.getReportPageAttr() != null) { + + if (from == selectedColumnsFrom && to == selectedColumnsTo) { + cancel = true; + } + + if (from2 == selectedColumnsFrom && to2 == selectedColumnsTo) { + cancel = true; + } + } + return cancel; + } + + public static UIPopupMenu createRowPopupMenu(ElementCasePane reportPane, MouseEvent evt, int selectedRows) { + UIPopupMenu popupMenu = new UIPopupMenu(); + if (DesignerMode.isAuthorityEditing()) { + popupMenu.add(new CleanAuthorityAction(reportPane).createMenuItem()); + return popupMenu; + } + + InsertRowAction insertRowAction = new InsertRowAction(reportPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_Insert_Row")); + + DeleteRowAction deleteRowAction = new DeleteRowAction(reportPane, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Delete_Row")); + + RowHeightAction rowHeightAction = new RowHeightAction(reportPane, selectedRows); + + RowHideAction rowHideAction = new RowHideAction(reportPane, selectedRows); + + ResetRowHideAction resetRowHideAction = new ResetRowHideAction(reportPane, selectedRows); + popupMenu.add(insertRowAction.createMenuItem()); + popupMenu.add(deleteRowAction.createMenuItem()); + popupMenu.addSeparator(); + popupMenu.add(rowHeightAction.createMenuItem()); + CellSelection cs = (CellSelection) reportPane.getSelection(); + addRowMenu(reportPane, popupMenu, evt, cs.getRow(), cs.getRow() + cs.getRowSpan() - 1); + popupMenu.add(rowHideAction.createMenuItem()); + popupMenu.add(resetRowHideAction.createMenuItem()); + return popupMenu; + } + + private static void addRowMenu(ElementCasePane reportPane, JPopupMenu popupMenu, MouseEvent evt, int selectedRowsFrom, int selectedRowsTo) { + HeadRowAction headrowAction = new HeadRowAction(reportPane); + FootRowAction footrowAction = new FootRowAction(reportPane); + + ElementCase elementCase = reportPane.getEditingElementCase(); + boolean cancel = false; + ColumnRow selectedCellPoint = GridUtils.getAdjustEventColumnRow_withresolution(reportPane, evt.getX(), evt.getY(), reportPane.getResolution()); + ReportPageAttrProvider reportPageAttr = elementCase.getReportPageAttr(); + ElementCase report = reportPane.getEditingElementCase(); + if (reportPageAttr != null) { + popupMenu.addSeparator(); + popupMenu.add(headrowAction.createMenuItem()); + popupMenu.add(footrowAction.createMenuItem()); + int from = report.getReportPageAttr().getRepeatHeaderRowFrom(); + int to = report.getReportPageAttr().getRepeatHeaderRowTo(); + int from2 = report.getReportPageAttr().getRepeatFooterRowFrom(); + int to2 = report.getReportPageAttr().getRepeatFooterRowTo(); + + if (selectedCellPoint.getRow() >= selectedRowsFrom && selectedCellPoint.getRow() <= selectedRowsTo) { + + cancel = isCancel(report, selectedRowsFrom, selectedRowsTo, from, to, from2, to2); + + } else { + + int row = selectedCellPoint.getRow(); + if (report.getReportPageAttr() != null) { + if (row == from || row == to || row == from2 || row == to2) { + cancel = true; + } + } + } + + if (cancel) { + CancelRowAction cancelAction = new CancelRowAction(reportPane); + popupMenu.add(cancelAction.createMenuItem()); + } + } + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/fit/grid/GridHeaderWithBoundMouseHandler.java b/designer-realize/src/main/java/com/fr/design/fit/grid/GridHeaderWithBoundMouseHandler.java new file mode 100644 index 000000000..bd3c73846 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/fit/grid/GridHeaderWithBoundMouseHandler.java @@ -0,0 +1,70 @@ +package com.fr.design.fit.grid; + +import com.fr.base.DynamicUnitList; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.grid.GridHeader; +import com.fr.grid.AbstractGridHeaderMouseHandler; +import com.fr.report.elementcase.ElementCase; +import com.fr.report.elementcase.TemplateElementCase; + +import java.awt.event.MouseEvent; + +public abstract class GridHeaderWithBoundMouseHandler extends AbstractGridHeaderMouseHandler{ + protected static final int FUZZY_EDGE = 10; + private int limit; + + public GridHeaderWithBoundMouseHandler(GridHeader gHeader, int limit) { + super(gHeader); + this.limit = limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } + + public int getLimit() { + return limit; + } + + public int getDragIndex(MouseEvent evt) { + ElementCase report = this.getEditingElementCase(); + DynamicUnitList sizeList = getSizeList(report); + + int scrollValue = getScrollValue(this.getElementCasePane()); + int scrollExtent = getScrollExtent(this.getElementCasePane()); + int endValue = scrollValue + scrollExtent + 1; + + int beginValue = getBeginValue(this.getElementCasePane()); + + double tmpSize1 = 0; + double tmpSize2; + double tmpIncreaseSize = 0; + + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); + + for (int index = beginValue; index < endValue; index++) { + if (index == 0) { + index = scrollValue; + } + + tmpSize1 += tmpIncreaseSize; + tmpIncreaseSize = sizeList.get(index).toPixD(resolution); + tmpSize2 = tmpSize1 + Math.max(1, tmpIncreaseSize); + if (isOnSeparatorLineIncludeZero(evt, tmpSize2, tmpIncreaseSize) || isOnNormalSeparatorLine(evt, tmpSize2)) { + return index; + } + } + return -1; + } + + + public ElementCasePane getElementCasePane() { + return this.gHeader.getElementCasePane(); + } + + public TemplateElementCase getEditingElementCase() { + return this.getElementCasePane().getEditingElementCase(); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitColumnMouseHandler.java b/designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitColumnMouseHandler.java new file mode 100644 index 000000000..28185bc38 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitColumnMouseHandler.java @@ -0,0 +1,194 @@ +package com.fr.design.fit.grid; + +import com.fr.base.DynamicUnitList; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.gui.imenu.UIPopupMenu; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.grid.GridColumn; +import com.fr.grid.GridHeader; +import com.fr.grid.GridUtils; +import com.fr.grid.selection.CellSelection; +import com.fr.grid.selection.Selection; +import com.fr.report.ReportHelper; +import com.fr.report.elementcase.ElementCase; +import com.fr.stable.ColumnRow; +import com.fr.stable.unit.FU; +import com.fr.stable.unit.UNIT; + +import javax.swing.SwingUtilities; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.event.MouseEvent; + +/** + * peter:处理对GridColumn的Mouse事件. + */ +public class GridLimitColumnMouseHandler extends GridHeaderWithBoundMouseHandler { + + + public GridLimitColumnMouseHandler(GridColumn gridColumn, int limit) { + super(gridColumn, limit); + this.resolution = gridColumn.getResolution(); + } + + @Override + protected void resetSelectionByRightButton(ColumnRow selectedCellPoint, Selection cs, ElementCasePane ePane) { + int[] selectedColumns = cs.getSelectedColumns(); + if (selectedColumns.length == 0 + || selectedCellPoint.getColumn() < selectedColumns[0] + || selectedCellPoint.getColumn() > selectedColumns[selectedColumns.length - 1]) { + resetGridSelectionBySelect(selectedCellPoint.getColumn(), ePane); + } + } + + + protected int doChooseFrom() { + return CellSelection.CHOOSE_COLUMN; + } + + @Override + protected Rectangle resetSelectedBoundsByShift(Rectangle editRectangle, ColumnRow selectedCellPoint, ElementCasePane reportPane) { + int tempOldSelectedCellX = editRectangle.x;// editRectangle.x; + + // adjust them to got the correct selected bounds. + if (selectedCellPoint.getColumn() >= editRectangle.x) { + selectedCellPoint = ColumnRow.valueOf(selectedCellPoint.getColumn() + 1, selectedCellPoint.getRow()); + } else { + tempOldSelectedCellX++; + } + + int lastRow = GridUtils.getAdjustLastColumnRowOfReportPane(reportPane).getRow(); + return new Rectangle(Math.min(tempOldSelectedCellX, selectedCellPoint.getColumn()), 0, Math.max(editRectangle.width, Math.abs(tempOldSelectedCellX + - selectedCellPoint.getColumn())), lastRow); + } + + @Override + protected int[] getGridSelectionIndices(CellSelection cs) { + return cs.getSelectedColumns(); + } + + @Override + protected int getScrollValue(ElementCasePane casePane) { + return casePane.getGrid().getHorizontalValue(); + } + + @Override + protected int getScrollExtent(ElementCasePane casePane) { + return casePane.getGrid().getHorizontalExtent(); + } + + @Override + protected int getBeginValue(ElementCasePane casePane) { + return casePane.getGrid().getHorizontalBeginValue(); + } + + @Override + protected int getColumnOrRowByGridHeader(ColumnRow selectedCellPoint) { + return selectedCellPoint.getColumn(); + } + + + /** + * Checks whether is on zero separator line. + */ + @Override + protected boolean isOnSeparatorLineIncludeZero(MouseEvent evt, double tmpWidth2, double tmpIncreaseWidth) { + return tmpIncreaseWidth <= 1 && (evt.getX() >= tmpWidth2 + 2 && (evt.getX() <= tmpWidth2 + SEPARATOR_GAP)); + } + + @Override + protected boolean between(MouseEvent evt, double from, double to) { + return evt.getX() > from && evt.getX() <= to; + } + + /** + * Checks whether is on normal separator line. + */ + @Override + protected boolean isOnNormalSeparatorLine(MouseEvent evt, double tmpWidth2) { + return (evt.getX() >= tmpWidth2 - 2) && (evt.getX() <= tmpWidth2 + 2); + } + + @Override + protected int evtOffset(MouseEvent evt, int offset) { + return evt.getX() - offset; + } + + @Override + protected DynamicUnitList getSizeList(ElementCase elementCase) { + return ReportHelper.getColumnWidthList(elementCase); + } + + @Override + protected String methodName() { + return "setColumnWidth"; + } + + @Override + protected String getSelectedHeaderTooltip(int selectedColumnCount) { + return selectedColumnCount + "C"; + } + + @Override + protected Point getTipLocationByMouseEvent(MouseEvent evt, GridHeader gHeader, Dimension tipPreferredSize) { + Point convertPoint = new Point(evt.getX(), 0); + SwingUtilities.convertPointToScreen(convertPoint, gHeader); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + convertPoint.x = Math.max(0, Math.min(convertPoint.x - tipPreferredSize.width / 2, screenSize.width - tipPreferredSize.width)); + convertPoint.y = convertPoint.y - tipPreferredSize.height - 2; + + return convertPoint; + } + + @Override + protected void resetGridSelectionBySelect(int column, ElementCasePane ePane) { + int lastRow = GridUtils.getAdjustLastColumnRowOfReportPane(ePane).getRow(); + CellSelection cellSelection = new CellSelection(column, 0, 1, lastRow); + cellSelection.setSelectedType(CellSelection.CHOOSE_COLUMN); + ePane.setSelection(cellSelection); + } + + @Override + protected String nameOfMoveCursorGIF() { + return "cursor_hmove"; + } + + @Override + protected String nameOfSelectCursorGIF() { + return "cursor_hselect"; + } + + @Override + protected String nameOfSplitCursorGIF() { + return "cursor_hsplit"; + } + + @Override + protected UIPopupMenu createPopupMenu(ElementCasePane reportPane, + MouseEvent evt, int columnIndex) { + return ElementCasePaneUtil.createColumnPopupMenu(reportPane, evt, columnIndex); + } + + @Override + protected void resetGridSelectionByDrag(CellSelection gridSelection, ElementCasePane reportPane, + int startMultiSelectIndex, int endMultiSelectIndex) { + int lastRow = GridUtils.getAdjustLastColumnRowOfReportPane(reportPane).getRow(); + gridSelection.setLastRectangleBounds(Math.min(endMultiSelectIndex, startMultiSelectIndex), 0, Math.abs(startMultiSelectIndex - endMultiSelectIndex) + 1, lastRow); + } + + @Override + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); + int dragIndex = getDragIndex(e); + if (Math.abs(e.getX() - getLimit()) < FUZZY_EDGE && dragIndex >= 0) { + UNIT oldValue = this.getEditingElementCase().getColumnWidth(dragIndex); + this.getEditingElementCase().setColumnWidth(dragIndex, FU.valueOfPix(oldValue.toPixI(resolution) + getLimit() - e.getX(), resolution)); + } + this.getElementCasePane().repaint(); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitRowMouseHandler.java b/designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitRowMouseHandler.java new file mode 100644 index 000000000..ac4a70eab --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/fit/grid/GridLimitRowMouseHandler.java @@ -0,0 +1,190 @@ +package com.fr.design.fit.grid; + +import com.fr.base.DynamicUnitList; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.gui.imenu.UIPopupMenu; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.grid.GridHeader; +import com.fr.grid.GridRow; +import com.fr.grid.GridUtils; +import com.fr.grid.selection.CellSelection; +import com.fr.grid.selection.Selection; +import com.fr.report.ReportHelper; +import com.fr.report.elementcase.ElementCase; +import com.fr.stable.ColumnRow; +import com.fr.stable.unit.FU; +import com.fr.stable.unit.UNIT; + +import javax.swing.SwingUtilities; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +/** + * peter:处理对GridRow的Mouse事件. + */ +public class GridLimitRowMouseHandler extends GridHeaderWithBoundMouseHandler { + + public GridLimitRowMouseHandler(GridRow gridRow, int limit) { + super(gridRow, limit); + } + + @Override + protected void resetSelectionByRightButton(ColumnRow selectedCellPoint, Selection cs, ElementCasePane ePane) { + int[] selectedRows = cs.getSelectedRows(); + if (selectedRows.length == 0 + || selectedCellPoint.getRow() < selectedRows[0] + || selectedCellPoint.getRow() > selectedRows[selectedRows.length - 1]) { + resetGridSelectionBySelect(selectedCellPoint.getRow(), ePane); + } + } + + + protected int doChooseFrom() { + return CellSelection.CHOOSE_ROW; + } + + @Override + protected int getScrollValue(ElementCasePane casePane) { + return casePane.getGrid().getVerticalValue(); + } + + @Override + protected int getScrollExtent(ElementCasePane casePane) { + return casePane.getGrid().getVerticalExtent(); + } + + @Override + protected int getBeginValue(ElementCasePane casePane) { + return casePane.getGrid().getVerticalBeginValue(); + } + + @Override + protected Rectangle resetSelectedBoundsByShift(Rectangle editRectangle, ColumnRow selectedCellPoint, ElementCasePane reportPane) { + int tempOldSelectedCellY = editRectangle.y;// editRectangle.x; + + // ajust them to got the correct selected bounds. + if (selectedCellPoint.getRow() >= editRectangle.y) { + selectedCellPoint = ColumnRow.valueOf(selectedCellPoint.getColumn(), selectedCellPoint.getRow() + 1); + } else { + tempOldSelectedCellY++; + } + + int lastColumn = GridUtils.getAdjustLastColumnRowOfReportPane(reportPane).getColumn(); + return new Rectangle(0, Math.min(tempOldSelectedCellY, selectedCellPoint.getRow()), + lastColumn, Math.max(editRectangle.height, Math.abs(tempOldSelectedCellY - selectedCellPoint.getRow()))); + } + + @Override + protected int[] getGridSelectionIndices(CellSelection cs) { + return cs.getSelectedRows(); + } + + @Override + protected int getColumnOrRowByGridHeader(ColumnRow selectedCellPoint) { + return selectedCellPoint.getRow(); + } + + + @Override + protected void resetGridSelectionBySelect(int row, ElementCasePane ePane) { + int lastColumn = GridUtils.getAdjustLastColumnRowOfReportPane(ePane).getColumn(); + CellSelection cellSelection = new CellSelection(0, row, lastColumn, 1); + cellSelection.setSelectedType(CellSelection.CHOOSE_ROW); + ePane.setSelection(cellSelection); + } + + /** + * Checks whether is on zero separator line. + */ + @Override + protected boolean isOnSeparatorLineIncludeZero(MouseEvent evt, double tmpHeight2, double tmpIncreaseHeight) { + return tmpIncreaseHeight <= 1 && (evt.getY() >= tmpHeight2 + 2 && evt.getY() <= tmpHeight2 + SEPARATOR_GAP); + } + + @Override + protected boolean between(MouseEvent evt, double from, double to) { + return evt.getY() > from && evt.getY() <= to; + } + + @Override + protected DynamicUnitList getSizeList(ElementCase elementCase) { + return ReportHelper.getRowHeightList(elementCase); + } + + @Override + protected String methodName() { + return "setRowHeight"; + } + + /** + * Checks whether is on normal separator line. + */ + @Override + protected boolean isOnNormalSeparatorLine(MouseEvent evt, double tmpHeight2) { + return (evt.getY() >= tmpHeight2 - 2) && (evt.getY() <= tmpHeight2 + 2); + } + + @Override + protected int evtOffset(MouseEvent evt, int offset) { + return evt.getY() - offset; + } + + @Override + protected String getSelectedHeaderTooltip(int rowSelectedCount) { + return rowSelectedCount + "R"; + } + + @Override + protected Point getTipLocationByMouseEvent(MouseEvent evt, GridHeader gHeader, Dimension tipPreferredSize) { + Point convertPoint = new Point(0, evt.getY()); + SwingUtilities.convertPointToScreen(convertPoint, gHeader); + + convertPoint.x = convertPoint.x + gHeader.getSize().width + 2; + convertPoint.y = convertPoint.y - tipPreferredSize.height / 2; + + return convertPoint; + } + + @Override + protected String nameOfMoveCursorGIF() { + return "cursor_vmove"; + } + + @Override + protected String nameOfSelectCursorGIF() { + return "cursor_vselect"; + } + + @Override + protected String nameOfSplitCursorGIF() { + return "cursor_vsplit"; + } + + @Override + protected UIPopupMenu createPopupMenu(ElementCasePane reportPane, + MouseEvent evt, int rowIndex) { + return ElementCasePaneUtil.createRowPopupMenu(reportPane, evt, rowIndex); + } + + @Override + protected void resetGridSelectionByDrag(CellSelection gridSelection, ElementCasePane reportPane, + int startMultiSelectIndex, int endMultiSelectIndex) { + int lastColumn = GridUtils.getAdjustLastColumnRowOfReportPane(reportPane).getColumn(); + gridSelection.setLastRectangleBounds(0, Math.min(endMultiSelectIndex, startMultiSelectIndex), lastColumn, Math.abs(startMultiSelectIndex - endMultiSelectIndex) + 1); + + } + + @Override + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); + int dragIndex = getDragIndex(e); + if (Math.abs(e.getY() - getLimit()) < FUZZY_EDGE && dragIndex >= 0) { + UNIT oldValue = this.getEditingElementCase().getRowHeight(dragIndex); + this.getEditingElementCase().setRowHeight(dragIndex, FU.valueOfPix(oldValue.toPixI(resolution) + getLimit() - e.getY(), resolution)); + } + this.getElementCasePane().repaint(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/fit/grid/NewFormDesignerGridUI.java b/designer-realize/src/main/java/com/fr/design/fit/grid/NewFormDesignerGridUI.java new file mode 100644 index 000000000..c3cc4f53d --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/fit/grid/NewFormDesignerGridUI.java @@ -0,0 +1,190 @@ +package com.fr.design.fit.grid; + +import com.fr.design.designer.creator.XElementCase; +import com.fr.design.fit.AdaptiveCellElementPainter; +import com.fr.design.fit.common.FormDesignerUtil; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.FormDesigner; +import com.fr.grid.CellElementPainter; +import com.fr.grid.Grid; +import com.fr.grid.GridColumn; +import com.fr.grid.GridRow; +import com.fr.grid.GridUI; +import com.fr.report.elementcase.TemplateElementCase; +import com.fr.report.worksheet.FormElementCase; +import com.fr.stable.Constants; +import com.fr.stable.GraphDrawHelper; + +import javax.swing.JComponent; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelListener; + + +/** + * Created by kerry on 2020-04-14 + */ +public class NewFormDesignerGridUI extends GridUI { + private GridLimitColumnMouseHandler gridColumnMouseHandler; + private GridLimitRowMouseHandler gridRowMouseHandler; + private AdaptiveGridListener adaptiveGridListener; + private FormDesigner designer; + + public NewFormDesignerGridUI(FormDesigner designer, int resolution) { + super(resolution); + this.designer = designer; + this.setCellElementPainter(new AdaptiveCellElementPainter()); + } + + public void setCellElementPainter(CellElementPainter elementPainter) { + this.painter = elementPainter; + } + + public void paint(Graphics g, JComponent c) { + Graphics2D g2d = (Graphics2D) g; + Grid grid = (Grid) c; + // 取得ElementCasePane.ElementCase + ElementCasePane elementCasePane = grid.getElementCasePane(); + final TemplateElementCase elementCase = elementCasePane.getEditingElementCase(); + + super.paint(g, c); + + if (!(elementCase instanceof FormElementCase)) { + return; + } + final Rectangle rectangle = getBoundsLineRect(elementCase, grid); + int width = rectangle.width - columnWidthList.getRangeValue(0, horizontalValue).toPixI(resolution); + int height = rectangle.height - rowHeightList.getRangeValue(0, verticalValue).toPixI(resolution); + drawBoundsLine(g2d, width, height); + addListener(grid, elementCasePane, width, height, rectangle.width, rectangle.height); + } + + /** + * 获取需要画线的矩形大小 + */ + private Rectangle getBoundsLineRect(TemplateElementCase elementCase, Grid grid) { + final Rectangle rectangle = new Rectangle(); + XElementCase xElementCase = FormDesignerUtil.getXelementCase(designer.getRootComponent(), (FormElementCase) elementCase); + if (xElementCase != null) { + rectangle.setBounds(xElementCase.getBounds()); + + //减去内边距的宽和高 + Insets insets = xElementCase.getInsets(); + rectangle.width -= insets.left + insets.right; + rectangle.height -= insets.top + insets.bottom; + + } + return rectangle; + } + + + private void addListener(Grid grid, ElementCasePane elementCasePane, int width, int height, int actualWidth, int actualHeight) { + addGridColumnListener(elementCasePane.getGridColumn(), width); + addGridRowListener(elementCasePane.getGridRow(), height); + addMouseListener(grid, width, height, actualWidth, actualHeight); + } + + + private void drawBoundsLine(Graphics2D g2d, int width, int height) { + g2d.setPaint(Color.black); + g2d.setStroke(GraphDrawHelper.getStroke(Constants.LINE_DASH_DOT)); + g2d.drawLine(0, height, width, height); + g2d.drawLine(width, 0, width, height); + } + + private void removeGridColumnListener(GridColumn column) { + MouseMotionListener[] mouseMotionListeners = column.getMouseMotionListeners(); + for (MouseMotionListener mouseMotionListener : mouseMotionListeners) { + if (mouseMotionListener instanceof com.fr.grid.GridColumnMouseHandler || mouseMotionListener instanceof GridLimitColumnMouseHandler) { + column.removeMouseMotionListener(mouseMotionListener); + } + } + MouseListener[] mouseListeners = column.getMouseListeners(); + for (MouseListener motionListener : mouseListeners) { + if (motionListener instanceof com.fr.grid.GridColumnMouseHandler || motionListener instanceof GridLimitColumnMouseHandler) { + column.removeMouseListener(motionListener); + } + } + } + + private void removeGridRowListener(GridRow row) { + MouseMotionListener[] mouseMotionListeners = row.getMouseMotionListeners(); + for (MouseMotionListener mouseMotionListener : mouseMotionListeners) { + if (mouseMotionListener instanceof com.fr.grid.GridRowMouseHandler || mouseMotionListener instanceof GridLimitRowMouseHandler) { + row.removeMouseMotionListener(mouseMotionListener); + } + } + MouseListener[] mouseListeners = row.getMouseListeners(); + for (MouseListener motionListener : mouseListeners) { + if (motionListener instanceof com.fr.grid.GridRowMouseHandler || motionListener instanceof GridLimitRowMouseHandler) { + row.removeMouseListener(motionListener); + } + } + } + + private void removeGridListener(Grid grid) { + MouseMotionListener[] mouseMotionListeners = grid.getMouseMotionListeners(); + for (MouseMotionListener mouseMotionListener : mouseMotionListeners) { + if (mouseMotionListener instanceof AdaptiveGridListener) { + grid.removeMouseMotionListener(mouseMotionListener); + break; + } + } + MouseListener[] mouseListeners = grid.getMouseListeners(); + for (MouseListener motionListener : mouseListeners) { + if (motionListener instanceof AdaptiveGridListener) { + grid.removeMouseListener(motionListener); + break; + } + } + MouseWheelListener[] mouseWheelListeners = grid.getMouseWheelListeners(); + for (MouseWheelListener mouseWheelListener : mouseWheelListeners) { + if (mouseWheelListener instanceof AdaptiveGridListener) { + grid.removeMouseWheelListener(mouseWheelListener); + break; + } + } + } + + private void addGridColumnListener(GridColumn column, int width) { + if (gridColumnMouseHandler != null) { + gridColumnMouseHandler.setLimit(width); + return; + } + removeGridColumnListener(column); + gridColumnMouseHandler = new GridLimitColumnMouseHandler(column, width); + column.addMouseListener(gridColumnMouseHandler); + column.addMouseMotionListener(gridColumnMouseHandler); + } + + + private void addGridRowListener(GridRow row, int height) { + if (gridRowMouseHandler != null) { + gridRowMouseHandler.setLimit(height); + return; + } + removeGridRowListener(row); + gridRowMouseHandler = new GridLimitRowMouseHandler(row, height); + row.addMouseMotionListener(gridRowMouseHandler); + row.addMouseListener(gridRowMouseHandler); + } + + + private void addMouseListener(Grid grid, int width, int height, int actualWidth, int actualHeight) { + if (adaptiveGridListener != null) { + adaptiveGridListener.resetBoundInfo(width, height, actualWidth, actualHeight); + return; + } + removeGridListener(grid); + adaptiveGridListener = new AdaptiveGridListener(grid, width, height, actualWidth, actualHeight); + grid.addMouseMotionListener(adaptiveGridListener); + grid.addMouseListener(adaptiveGridListener); + grid.addMouseWheelListener(adaptiveGridListener); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java index 30f7b1546..befe413f9 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java @@ -67,6 +67,7 @@ import com.fr.design.constants.UIConstants; import com.fr.design.designer.EditingState; import com.fr.design.designer.TargetComponent; import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.fun.ElementUIProvider; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.imenu.UIPopupMenu; @@ -225,7 +226,7 @@ public abstract class ElementCasePane extends Tar //todo 直接修改分辨率 if (this.resolution == 0) { - this.resolution = ScreenResolution.getScreenResolution(); + this.resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); } this.initGridComponent(); @@ -351,10 +352,10 @@ public abstract class ElementCasePane extends Tar this.grid = new Grid(this.resolution); } if (this.gridColumn == null) { - this.gridColumn = new GridColumn(); + this.gridColumn = new GridColumn(this.resolution); } if (this.gridRow == null) { - this.gridRow = new GridRow(); + this.gridRow = new GridRow(this.resolution); } if (this.gridCorner == null) { this.gridCorner = new GridCorner(); @@ -1375,7 +1376,7 @@ public abstract class ElementCasePane extends Tar protected Selection selection; protected int verticalValue = 0; protected int horizontalValue = 0; - protected int resolution = ScreenResolution.getScreenResolution(); + protected int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); protected ElementCaseEditingState(Selection selection, int verticalValue, int horizontalValue, int resolution) { try { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java index 45c2fea61..dea5145ce 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/form/FormElementCaseDesigner.java @@ -13,6 +13,7 @@ import com.fr.design.designer.EditingState; import com.fr.design.designer.TargetComponent; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.gui.frpane.HyperlinkGroupPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.AuthorityEditPane; @@ -137,6 +138,9 @@ public class FormElementCaseDesigner g.setColor(Color.WHITE); g.fillRect(0, 0, size.width, size.height); g.setColor(oldColor); + if (DesignerUIModeConfig.getInstance().newUIMode()) { + g.translate(-elementCasePane.getGridCorner().getWidth(), -elementCasePane.getGridCorner().getHeight()); + } this.elementCasePane.paintComponents(g); diff --git a/designer-realize/src/main/java/com/fr/grid/AbstractGridHeaderMouseHandler.java b/designer-realize/src/main/java/com/fr/grid/AbstractGridHeaderMouseHandler.java index 349503bd7..b04e4ad1e 100644 --- a/designer-realize/src/main/java/com/fr/grid/AbstractGridHeaderMouseHandler.java +++ b/designer-realize/src/main/java/com/fr/grid/AbstractGridHeaderMouseHandler.java @@ -2,13 +2,12 @@ package com.fr.grid; import com.fr.base.BaseUtils; import com.fr.base.DynamicUnitList; -import com.fr.base.ScreenResolution; import com.fr.base.vcs.DesignerMode; import com.fr.design.DesignerEnvManager; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.fun.ReportLengthUNITProvider; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.mainframe.ElementCasePane; -import com.fr.design.unit.UnitConvertUtil; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.FloatSelection; @@ -39,7 +38,7 @@ import java.lang.reflect.Method; public abstract class AbstractGridHeaderMouseHandler extends MouseInputAdapter { protected static final int SEPARATOR_GAP = 5; - private GridHeader gHeader; + protected GridHeader gHeader; private int dragType = GridUtils.DRAG_NONE; //james 是否为选定多行的drag private boolean isMultiSelectDragPermited = false; @@ -51,7 +50,7 @@ public abstract class AbstractGridHeaderMouseHandler extends MouseInputAdapter { private int dragIndex = 0; private JToolTip tip = null; private JWindow tipWindow = null; - protected int resolution = ScreenResolution.getScreenResolution(); + protected int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); public AbstractGridHeaderMouseHandler(GridHeader gHeader) { this.gHeader = gHeader; @@ -307,7 +306,7 @@ public abstract class AbstractGridHeaderMouseHandler extends MouseInputAdapter { // int resolution = ScreenResolution.getScreenResolution(); FU ulen = FU.valueOfPix((int) doubleValue, resolution); FU tulen = FU.valueOfPix((int) totalDoubleValue, resolution); - ReportLengthUNITProvider lengthUNIT = UnitConvertUtil.parseLengthUNIT(unitType); + ReportLengthUNITProvider lengthUNIT = DesignerUIModeConfig.getInstance().parseLengthUNIT(unitType); String unit = lengthUNIT.unitText(); double len = lengthUNIT.unit2Value4Scale(ulen); double tlen = lengthUNIT.unit2Value4Scale(tulen); diff --git a/designer-realize/src/main/java/com/fr/grid/DefaultGridUIProcessor.java b/designer-realize/src/main/java/com/fr/grid/DefaultGridUIProcessor.java index 65b6aa456..0b4c900e3 100644 --- a/designer-realize/src/main/java/com/fr/grid/DefaultGridUIProcessor.java +++ b/designer-realize/src/main/java/com/fr/grid/DefaultGridUIProcessor.java @@ -1,16 +1,24 @@ package com.fr.grid; +import com.fr.design.fit.DesignerUIModeConfig; +import com.fr.design.fit.grid.NewFormDesignerGridUI; import com.fr.design.fun.impl.AbstractGridUIProcessor; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.WidgetPropertyPane; import javax.swing.plaf.ComponentUI; /** * Created by Administrator on 2016/6/28/0028. */ -public class DefaultGridUIProcessor extends AbstractGridUIProcessor{ +public class DefaultGridUIProcessor extends AbstractGridUIProcessor { @Override public ComponentUI appearanceForGrid(int resolution) { + if (DesignerUIModeConfig.getInstance().newUIMode()) { + FormDesigner designer = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + return new NewFormDesignerGridUI(designer, resolution); + } return new GridUI(resolution); } diff --git a/designer-realize/src/main/java/com/fr/grid/GridColumn.java b/designer-realize/src/main/java/com/fr/grid/GridColumn.java index 8ba6484bc..eed4136d4 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridColumn.java +++ b/designer-realize/src/main/java/com/fr/grid/GridColumn.java @@ -6,14 +6,10 @@ package com.fr.grid; import java.awt.Dimension; import com.fr.base.GraphHelper; -import com.fr.base.ScreenResolution; -import com.fr.design.ExtraDesignClassManager; -import com.fr.design.fun.GridUIProcessor; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.mainframe.ElementCasePane; import com.fr.stable.StableUtils; -import javax.swing.plaf.ComponentUI; - /** * GridColumn used to paint and edit grid column. * @@ -22,20 +18,23 @@ import javax.swing.plaf.ComponentUI; */ public class GridColumn extends GridHeader { - public int resolution = ScreenResolution.getScreenResolution(); private GridColumnMouseHandler gridColumnMouseHandler; + public GridColumn(int resolution) { + super(resolution); + } + @Override protected void initByConstructor() { - resolution = ScreenResolution.getScreenResolution(); - this.setResolution(resolution); gridColumnMouseHandler = new GridColumnMouseHandler(this); this.addMouseListener(gridColumnMouseHandler); this.addMouseMotionListener(gridColumnMouseHandler); this.updateUI(); } + + @Override public String getDisplay(int index) { return StableUtils.convertIntToABC(index + 1); @@ -48,26 +47,16 @@ public class GridColumn extends GridHeader { gridColumnMouseHandler = new GridColumnMouseHandler(this); this.addMouseListener(gridColumnMouseHandler); this.addMouseMotionListener(gridColumnMouseHandler); -// gridColumnMouseHandler.setResolution(resolution); this.setUI(new GridColumnUI(resolution)); } - public void setResolution(int resolution) { - this.resolution = resolution; - } - - @Override - public int getResolution() { - return this.resolution; - } - /** * Gets the preferred size. */ @Override public Dimension getPreferredSize() { ElementCasePane reportPane = this.getElementCasePane(); - float time = (float)reportPane.getResolution()/ ScreenResolution.getScreenResolution(); + float time = (float)reportPane.getResolution()/ DesignerUIModeConfig.getInstance().getScreenResolution(); if (!reportPane.isColumnHeaderVisible()) { return new Dimension(0, 0); } diff --git a/designer-realize/src/main/java/com/fr/grid/GridColumnMouseHandler.java b/designer-realize/src/main/java/com/fr/grid/GridColumnMouseHandler.java index 09ad45d32..bc5b54c90 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridColumnMouseHandler.java +++ b/designer-realize/src/main/java/com/fr/grid/GridColumnMouseHandler.java @@ -7,9 +7,7 @@ import java.awt.Toolkit; import java.awt.event.MouseEvent; import javax.swing.SwingUtilities; - import com.fr.base.DynamicUnitList; -import com.fr.base.ScreenResolution; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.mainframe.ElementCasePane; import com.fr.grid.selection.CellSelection; @@ -23,8 +21,6 @@ import com.fr.stable.ColumnRow; */ public class GridColumnMouseHandler extends AbstractGridHeaderMouseHandler { - private int resolution; - public GridColumnMouseHandler(GridColumn gridColumn) { super(gridColumn); this.resolution = gridColumn.resolution; diff --git a/designer-realize/src/main/java/com/fr/grid/GridColumnUI.java b/designer-realize/src/main/java/com/fr/grid/GridColumnUI.java index d3e90308b..088c8f220 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridColumnUI.java +++ b/designer-realize/src/main/java/com/fr/grid/GridColumnUI.java @@ -16,6 +16,7 @@ import com.fr.base.ScreenResolution; import com.fr.base.vcs.DesignerMode; import com.fr.cache.list.IntList; import com.fr.design.constants.UIConstants; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.mainframe.ElementCasePane; import com.fr.design.roleAuthority.ReportAndFSManagePane; import com.fr.grid.selection.Selection; @@ -33,7 +34,7 @@ public class GridColumnUI extends ComponentUI { public GridColumnUI(int resolution){ if (resolution == 0){ - resolution = ScreenResolution.getScreenResolution(); + resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); } this.resolution = resolution; } @@ -49,7 +50,7 @@ public class GridColumnUI extends ComponentUI { Grid gird = reportPane.getGrid(); // size Dimension size = gridColumn.getSize(); - float time = (float)resolution/ScreenResolution.getScreenResolution(); + float time = (float)resolution/DesignerUIModeConfig.getInstance().getScreenResolution(); g2d.setFont(gridColumn.getFont().deriveFont(gridColumn.getFont().getSize2D() * time)); ElementCase elementCase = reportPane.getEditingElementCase(); @@ -161,7 +162,7 @@ public class GridColumnUI extends ComponentUI { columnContent += "(FR)"; } } - float time = (float)resolution/ScreenResolution.getScreenResolution(); + float time = (float)resolution/DesignerUIModeConfig.getInstance().getScreenResolution(); double stringWidth = gridColumn.getFont().getStringBounds(columnContent, fontRenderContext).getWidth() * time; if (stringWidth > tmpIncreaseWidth) { diff --git a/designer-realize/src/main/java/com/fr/grid/GridCorner.java b/designer-realize/src/main/java/com/fr/grid/GridCorner.java index f2dd43d5e..4d1d393b7 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridCorner.java +++ b/designer-realize/src/main/java/com/fr/grid/GridCorner.java @@ -6,6 +6,7 @@ package com.fr.grid; import com.fr.base.GraphHelper; import com.fr.base.ScreenResolution; import com.fr.design.constants.UIConstants; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.mainframe.ElementCasePane; import javax.swing.event.MouseInputListener; @@ -35,7 +36,7 @@ public class GridCorner extends BaseGridComponent { Graphics2D g2d = (Graphics2D) g; ElementCasePane reportPane = this.getElementCasePane(); - float time = (float) reportPane.getResolution() / ScreenResolution.getScreenResolution(); + float time = (float) reportPane.getResolution() / DesignerUIModeConfig.getInstance().getScreenResolution(); //size Dimension size = this.getSize(); Rectangle2D rect2D = new Rectangle2D.Double(0, 0, size.getWidth(), size.getHeight()); diff --git a/designer-realize/src/main/java/com/fr/grid/GridHeader.java b/designer-realize/src/main/java/com/fr/grid/GridHeader.java index 9a4a1b949..ec974b197 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridHeader.java +++ b/designer-realize/src/main/java/com/fr/grid/GridHeader.java @@ -15,7 +15,8 @@ public abstract class GridHeader extends BaseGridComponent { protected int resolution; - public GridHeader() { + public GridHeader(int resolution) { + this.resolution = resolution; //清除所有的Key Action. this.getInputMap().clear(); this.getActionMap().clear(); diff --git a/designer-realize/src/main/java/com/fr/grid/GridMouseAdapter.java b/designer-realize/src/main/java/com/fr/grid/GridMouseAdapter.java index b0f91a902..060bc2ace 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridMouseAdapter.java +++ b/designer-realize/src/main/java/com/fr/grid/GridMouseAdapter.java @@ -6,6 +6,7 @@ import com.fr.base.ScreenResolution; import com.fr.base.vcs.DesignerMode; import com.fr.common.inputevent.InputEventBaseOnOS; import com.fr.design.constants.UIConstants; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.EastRegionContainerPane; import com.fr.design.mainframe.ElementCasePane; @@ -73,7 +74,7 @@ public class GridMouseAdapter implements MouseListener, MouseWheelListener, Mous private int ECBlockGap = 40; - private int resolution = ScreenResolution.getScreenResolution(); + private int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); protected GridMouseAdapter(Grid grid) { this.grid = grid; diff --git a/designer-realize/src/main/java/com/fr/grid/GridRow.java b/designer-realize/src/main/java/com/fr/grid/GridRow.java index 7dbb4af3a..a85c3c398 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridRow.java +++ b/designer-realize/src/main/java/com/fr/grid/GridRow.java @@ -8,6 +8,7 @@ import java.awt.Dimension; import com.fr.base.GraphHelper; import com.fr.base.ScreenResolution; import com.fr.design.ExtraDesignClassManager; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.fun.GridUIProcessor; import com.fr.design.mainframe.ElementCasePane; @@ -22,13 +23,14 @@ import javax.swing.plaf.ComponentUI; public class GridRow extends GridHeader { private static final int MAX = 4; - private int resolution = ScreenResolution.getScreenResolution(); private GridRowMouseHandler gridRowMouseHandler; + public GridRow(int resolution) { + super(resolution); + } + @Override protected void initByConstructor() { - resolution = ScreenResolution.getScreenResolution(); - this.setResolution(resolution); gridRowMouseHandler = new GridRowMouseHandler(this); this.addMouseListener(gridRowMouseHandler); this.addMouseMotionListener(gridRowMouseHandler); @@ -50,14 +52,6 @@ public class GridRow extends GridHeader { this.setUI(new GridRowUI(resolution)); } - public void setResolution(int resolution) { - this.resolution = resolution; - } - - public int getResolution() { - return this.resolution; - } - /** * Gets the preferred size. @@ -65,7 +59,7 @@ public class GridRow extends GridHeader { @Override public Dimension getPreferredSize() { ElementCasePane reportPane = this.getElementCasePane(); - float time = (float)reportPane.getResolution()/ ScreenResolution.getScreenResolution(); + float time = (float)reportPane.getResolution()/ DesignerUIModeConfig.getInstance().getScreenResolution(); if (!(reportPane.isRowHeaderVisible())) { return new Dimension(0, 0); } diff --git a/designer-realize/src/main/java/com/fr/grid/GridRowUI.java b/designer-realize/src/main/java/com/fr/grid/GridRowUI.java index a0245a3d8..6c2fed6d0 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridRowUI.java +++ b/designer-realize/src/main/java/com/fr/grid/GridRowUI.java @@ -7,6 +7,8 @@ import java.awt.geom.Rectangle2D; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; + +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.stable.AssistUtils; import com.fr.base.BaseUtils; import com.fr.base.DynamicUnitList; @@ -32,7 +34,7 @@ public class GridRowUI extends ComponentUI { GridRowUI(int resolution){ if (resolution == 0){ - resolution = ScreenResolution.getScreenResolution(); + resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); } this.resolution = resolution; } @@ -47,7 +49,7 @@ public class GridRowUI extends ComponentUI { ElementCasePane reportPane = gridRow.getElementCasePane(); // size Dimension size = gridRow.getSize(); - float time = (float)resolution/ScreenResolution.getScreenResolution(); + float time = (float)resolution/DesignerUIModeConfig.getInstance().getScreenResolution(); g2d.setFont(gridRow.getFont().deriveFont(gridRow.getFont().getSize2D() * time)); ElementCase elementCase = reportPane.getEditingElementCase(); @@ -156,7 +158,7 @@ public class GridRowUI extends ComponentUI { , ElementCase elementCase, Dimension size, double tmpHeight1) { // FontMetrics FontRenderContext fontRenderContext = g2d.getFontRenderContext(); - float time = (float)resolution/ScreenResolution.getScreenResolution(); + float time = (float)resolution/DesignerUIModeConfig.getInstance().getScreenResolution(); float fmAscent = GraphHelper.getFontMetrics(gridRow.getFont()).getAscent() * time; double stringWidth = gridRow.getFont().getStringBounds(paintText, fontRenderContext).getWidth() * time; double stringHeight = gridRow.getFont().getStringBounds(paintText, fontRenderContext).getHeight() * time; diff --git a/designer-realize/src/main/java/com/fr/grid/GridUtils.java b/designer-realize/src/main/java/com/fr/grid/GridUtils.java index 80e6f3ff5..31ceacd7a 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridUtils.java +++ b/designer-realize/src/main/java/com/fr/grid/GridUtils.java @@ -5,6 +5,7 @@ import com.fr.base.ScreenResolution; import com.fr.design.cell.clipboard.CellElementsClip; import com.fr.design.cell.clipboard.ElementsTransferable; import com.fr.design.cell.clipboard.FloatElementsClip; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.mainframe.ElementCasePane; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.ComparatorUtils; @@ -124,7 +125,7 @@ public class GridUtils { */ public static double[] caculateFloatElementLocations(FloatElement floatElement, DynamicUnitList columnWidthList, DynamicUnitList rowHeightList, int verticalValue, int horizentalValue) { - int resolution = ScreenResolution.getScreenResolution(); + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); double floatX = columnWidthList.getRangeValue(horizentalValue, 0).toPixD(resolution) + floatElement.getLeftDistance().toPixD(resolution); double floatY = rowHeightList.getRangeValue(verticalValue, 0).toPixD(resolution) + floatElement.getTopDistance().toPixD(resolution); @@ -177,7 +178,7 @@ public class GridUtils { private static int cc_selected_column_or_row(double mouseEvtPosition, int beginValue, int value, DynamicUnitList sizeList) { double tmpIntIndex = 0; int selectedCellIndex = 0; - int resolution = ScreenResolution.getScreenResolution(); + int resolution = DesignerUIModeConfig.getInstance().getScreenResolution(); if (mouseEvtPosition < 0) { selectedCellIndex = value; for (; true; selectedCellIndex--) { diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java index 3f1aa2663..025539d79 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java @@ -27,6 +27,8 @@ import com.fr.design.actions.insert.flot.ImageFloatAction; import com.fr.design.actions.insert.flot.TextBoxFloatAction; import com.fr.design.bridge.DesignToolbarProvider; import com.fr.design.constants.DesignerLaunchStatus; +import com.fr.design.fit.NewJForm; +import com.fr.design.fit.common.TemplateTool; import com.fr.design.form.parameter.FormParaDesigner; import com.fr.design.fun.ElementUIProvider; import com.fr.design.gui.controlpane.NameObjectCreator; @@ -42,7 +44,7 @@ import com.fr.design.mainframe.BaseJForm; import com.fr.design.mainframe.ElementCaseThumbnail; import com.fr.design.mainframe.FormHierarchyTreePane; import com.fr.design.mainframe.InformationCollector; -import com.fr.design.mainframe.JForm; +import com.fr.design.mainframe.JTemplateEvent; import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.mainframe.WidgetToolBarPane; import com.fr.design.mainframe.alphafine.AlphaFineHelper; @@ -62,6 +64,7 @@ import com.fr.design.parameter.WorkBookParameterReader; import com.fr.design.update.actions.RecoverForDesigner; import com.fr.design.update.push.DesignerPushUpdateManager; import com.fr.design.widget.ui.btn.FormSubmitButtonDetailPane; +import com.fr.event.EventDispatcher; import com.fr.form.stable.ElementCaseThumbnailProcessor; import com.fr.general.GeneralContext; import com.fr.general.xml.GeneralXMLTools; @@ -395,9 +398,15 @@ public class DesignerActivator extends Activator { DesignModuleFactory.registerButtonDetailPaneClass(FormSubmitButtonDetailPane.class); DesignModuleFactory.registerParameterReader(new FormParameterReader()); - StableFactory.registerMarkedClass(BaseJForm.XML_TAG, JForm.class); - + StableFactory.registerMarkedClass(BaseJForm.XML_TAG, NewJForm.class); StableFactory.registerMarkedObject(ElementCaseThumbnailProcessor.MARK_STRING, new ElementCaseThumbnail()); + + registerJTemplateEvent(); + } + + private static void registerJTemplateEvent(){ + EventDispatcher.listen(JTemplateEvent.BEFORE_TEMPLATE_INIT, TemplateTool.getSwitchListener()); + EventDispatcher.listen(JTemplateEvent.BEFORE_TEMPLATE_ACTIVE, TemplateTool.getSwitchListener()); } private static void storePassport() {